1. peripheral
1.1 发数据 tx
(1)应用层通过系统调用,进入到内核层;
(2)内核的数据链路层将数据送入驱动层;
(3)USB 网卡驱动将数据发送到 UDC控制器;(将req 写入in 端点)
(4)UDC 控制器写寄存器将数据通过 phy 发送出去。
// \drivers\usb\gadget\function\u_ether.c // .ndo_start_xmit = eth_start_xmit,
== eth_start_xmit(struct sk_buff *skb, struct net_device *net)
== usb_ep_queue(in, req, GFP_ATOMIC); // 将req 写入in 端点
== ret = ep->ops->queue(ep, req, gfp_flags);
== dwc3_gadget_ep_queue();
== __dwc3_gadget_ep_queue();
== __dwc3_gadget_kick_transfer();
== dwc3_prepare_trbs();
== dwc3_send_gadget_ep_cmd(); trace_dwc3_gadget_ep_cmd(dep, cmd, params, cmd_status);
== dwc3_writel(dep->regs, DWC3_DEPCMDPAR0, params->param0);
1.2 收数据 rx
(1)应用层通过系统调用,进入到内核层;
(2)内核的数据链路层将数据送入驱动层;
(3)USB 网卡驱动将数据发送到 UDC控制器;(将req 写入out 端点,表示要读buf)
(4)UDC 控制器接收 host 中断;
(5)req 的完成函数;
(6)完成函数将数据返回给数据链路层。
// \drivers\usb\gadget\function\u_ether.c //.ndo_open = eth_open,
== eth_open(struct net_device *net);
== eth_start(struct eth_dev *dev, gfp_t gfp_flags);
== rx_fill(struct eth_dev *dev, gfp_t gfp_flags);
== rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags);
== req->complete = rx_complete;
== req->complete = rx_complete;
== usb_ep_queue(out, req, gfp_flags); //将req 写入out 端点,表示要读buf
== dwc3_gadget_start(); //注册中断
== request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt, IRQF_SHARED, "dwc3", dwc->ev_buf);
== dwc3_thread_interrupt(); //中断产生(host发消息过来),调用回调函数
== dwc3_process_event_buf(); //处理中断事件buf(dwc3_event_buffer )
== dwc3_process_event_entry(); trace_dwc3_event(event->raw, dwc);
== dwc3_endpoint_interrupt(); //对端点处理的中断
== dwc3_gadget_endpoint_transfer_complete(); //传输完成
== dwc3_gadget_endpoint_trbs_complete();
== dwc3_gadget_ep_cleanup_completed_requests()
== dwc3_gadget_giveback(); //数据返回
== dwc3_gadget_del_and_unmap_request(); trace_dwc3_gadget_giveback(req);
== usb_gadget_giveback_request() trace_usb_gadget_giveback_request(ep, req, 0);// give the request back to the gadget layer
== req->complete(ep, req);
== rx_complete(struct usb_ep *ep, struct usb_request *req); // u_ether 的回调函数
== rx_complete();
== skb_dequeue(); //获取skb
== netif_rx(struct sk_buff *skb); // post buffer to the network code
2. host
2.1 发数据 tx
(1)应用层通过系统调用,进入到内核层;
(2)内核的数据链路层将数据送入驱动层;
(3)USB 网卡驱动将数据发送到 XHCI 控制器;
(4)XHCI 控制器写寄存器将数据通过 phy 发送出去。
// \drivers\net\usb\usbnet.c .ndo_start_xmit = usbnet_start_xmit,
== usbnet_start_xmit();
== usb_alloc_urb();
== usb_fill_bulk_urb();
== usb_submit_urb();
== usb_submit_urb(cmdinfo->cmd_urb, GFP_ATOMIC);
== usb_hcd_submit_urb(struct urb *urb, gfp_t mem_flags)
hcd->driver->urb_enqueue(hcd, urb, mem_flags);
== xhci_urb_enqueue(); trace_xhci_urb_enqueue(urb);
== xhci_queue_bulk_tx(); //批量传输
== prepare_transfer();
== usb_hcd_link_urb_to_ep() //add an URB to its endpoint queue
== list_add_tail(&urb->urb_list, &urb->ep->urb_list);
== queue_trb() trace_xhci_queue_trb(ring, trb); //queueing a TRB on a ring
== inc_enq() trace_xhci_inc_enq(ring);
== giveback_first_trb() //Pass all the TRBs to the hardware at once and make sure this write isn't reordered.
== xhci_ring_ep_doorbell() trace_xhci_ring_ep_doorbell(slot_id, DB_VALUE(ep_index, stream_id));
== writel(DB_VALUE(ep_index, stream_id), db_addr);
2.2 收数据 rx
(1)应用层通过系统调用,进入到内核层;
(2)内核的数据链路层将数据送入驱动层;
(3)USB 网卡驱动将数据发送到 XHCI 控制器;
(4)XHCI 控制器接收中断;
(5)urb 的完成函数;
(6)完成函数将数据返回给数据链路层。
// \drivers\net\usb\usbnet.c //.ndo_open = usbnet_open,
== usbnet_open(struct net_device *net);
== tasklet_schedule (&dev->bh);
== usbnet_bh();
== rx_alloc_submit();
== rx_submit(struct usbnet *dev, struct urb *urb, gfp_t flags);
== usb_fill_bulk_urb (urb, dev->udev, dev->in, skb->data, size, rx_complete, skb);
== usb_submit_urb();
== xhci_irq(struct usb_hcd *hcd)
== xhci_handle_event(struct xhci_hcd *xhci) trace_xhci_handle_event(xhci->event_ring, &event->generic);
== handle_tx_event() trace_xhci_handle_transfer(ep_ring, (struct xhci_generic_trb *) ep_trb)
== process_bulk_intr_td() //Process bulk and interrupt tds, update urb status and actual_length.
== finish_td()
== xhci_td_cleanup()
== xhci_giveback_urb_in_irq() trace_xhci_urb_giveback(urb);
== usb_hcd_unlink_urb_from_ep(hcd, urb);
== usb_hcd_giveback_urb(hcd, urb, status);
== urb->complete(urb);
== rx_complete();
== rx_complete();
== defer_bh();
== tasklet_schedule (&dev->bh);
== usbnet_bh(); // tasklet (work deferred from completions, in_irq) or timer
== rx_process(); // skb_state = rx_done
== usbnet_skb_return();
== netif_rx (skb);