USB Core 八

//将提交过来的urb 指派给合适的主机控制器驱动程序
 int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
 {
 int status;
 struct usb_hcd *hcd = bus_to_hcd(urb->dev->bus);

/*
 static inline struct usb_bus *hcd_to_bus (struct usb_hcd *hcd)
 {
 	return &hcd->self;
 }

 static inline struct usb_hcd *bus_to_hcd (struct usb_bus *bus)
 {
 	return container_of(bus, struct usb_hcd, self);
 }
*/

 struct usb_host_endpoint *ep;
 unsigned long flags;

 if (!hcd)
 return -ENODEV;
/*usbmon_urb_submit 就是与前面Greg 孕育出来的usb Monitor 有关的,如果你编译内核的时候没有配置上CONFIG_USB_MON,它就啥也不是,一个空函数,一具空壳。*/
 usbmon_urb_submit(&hcd->self, urb);

 /*
 * Atomically queue the urb, first to our records, then to the HCD.
 * Access to urb->status is controlled by urb->lock ... changes on
 * i/o completion (normal or fault) or unlinking.
 */

 // FIXME: verify that quiescing hc works right (RH cleans up)

 spin_lock_irqsave (&hcd_data_lock, flags);
 ep = (usb_pipein(urb->pipe) ? urb->dev->ep_in : urb->dev->ep_out)
 [usb_pipeendpoint(urb->pipe)];

 if (unlikely (!ep))
 	status = -ENOENT;
 else if (unlikely (urb->reject))//目的端点为空的可能性太小了,所以加上了unlikely
	 status = -EPERM;

 else switch (hcd->state) {
 case HC_STATE_RUNNING:
 case HC_STATE_RESUMING:
 	doit:
	 list_add_tail (&urb->urb_list, &ep->urb_list);
	 status = 0;
 	break;
 case HC_STATE_SUSPENDED:
 /* HC upstream links (register access, wakeup signaling) can work
 * even when the downstream links (and DMA etc) are quiesced;let
 * usbcore talk to the root hub.
 */
 	if (hcd->self.controller->power.power_state.event ==PM_EVENT_ON&& urb->dev->parent == NULL)
 	goto doit;
 /* FALL THROUGH */
 default:
	 status = -ESHUTDOWN;
	 break;
 }
 spin_unlock_irqrestore (&hcd_data_lock, flags);
 if (status) {

 INIT_LIST_HEAD (&urb->urb_list);
 usbmon_urb_submit_error(&hcd->self, urb, status);
 return status;
 }

 /* increment urb's reference count as part of giving it to the HCD
 * (which now controls it). HCD guarantees that it either returns
 * an error or calls giveback(), but not both.
 */
 urb = usb_get_urb (urb);//可以放心的增加urb 的引用计数了
 atomic_inc (&urb->use_count);//将urb 的use_count 也增加1,表示urb 已经被HCD 接受了,正在被处理着。

 if (urb->dev == hcd->self.root_hub) {
 /* NOTE: requirement on hub callers (usbfs and the hub
 * driver, for now) that URBs' urb->transfer_buffer be
 * valid and usb_buffer_{sync,unmap}() not be needed, since
 * they could clobber root hub response data.
 */
 status = rh_urb_enqueue (hcd, urb);
 goto done;
 }

 /* lower level hcd code should use *_dma exclusively,
 * unless it uses pio or talks to another transport.
 */
/*
如果这个主机控制器支持DMA,可你却没有告诉它URB_NO_SETUP_DMA_MAP或URB_NO_TRANSFER_DMA_MAP 这两个标志,它就会认为你在urb 里没有提供DMA的缓冲区,就会调用dma_map_single将setup_packet 或transfer_buffer映射为DMA缓冲区。
*/
 if (hcd->self.uses_dma) {

 if (usb_pipecontrol (urb->pipe)&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
 	urb->setup_dma = dma_map_single (hcd->self.controller,urb->setup_packet,sizeof (struct usb_ctrlrequest),DMA_TO_DEVICE);

 if (urb->transfer_buffer_length != 0&& !(urb->transfer_flags &URB_NO_TRANSFER_DMA_MAP))
 	urb->transfer_dma = dma_map_single (hcd->self.controller,urb->transfer_buffer,urb->transfer_buffer_length,usb_pipein (urb->pipe)? DMA_FROM_DEVICE: DMA_TO_DEVICE);
 }

 status = hcd->driver->urb_enqueue (hcd, ep, urb, mem_flags); //终于可以将urb 扔给具体的主机控制器驱动程序了

 done:
	 if (unlikely (status)) {
		 urb_unlink (urb);
 		atomic_dec (&urb->use_count);
		 if (urb->reject)
		 wake_up (&usb_kill_urb_queue);
		 usbmon_urb_submit_error(&hcd->self, urb, status);
		 usb_put_urb (urb);
		 }
    return status;
 }


 

你可能感兴趣的:(USB Core 八)