USB 网卡驱动数据流

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);
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值