reprint Please indicate source: Http://blog.csdn.net/Righthek Thank you!
The previous article has mentioned that the most important two functions of the USB interface in the WiFi module are Usb_read_port () and Usb_write_port (). So how do they relate to WiFi? We can analyze from the following three aspects:
1, the first need to clear the WiFi module is a USB device, the main control (CPU) side is a USB host;
2, USB host if need to the WiFi module to read and write data, it must go through the USB interface;
3, since the data read and write operation, it is necessary to use the corresponding reading and writing functions, then Usb_read_port () and Usb_write_port () is their reading and writing functions.
We begin by reading the data, and before we analyze it, we must understand the USB device-driven read data process. The USB read data operation flow is as follows:
(1) Create and assign a URB as a carrier for transmitting USB data via the USB_ALLOC_URB () function;
(2) Create and allocate DMA buffers to quickly transfer data in DMA mode;
(3) Initialize URB, according to the amount of data transmitted by WiFi, we need to initialize to batch URB, corresponding operation function is usb_fill_bulk_urb ();
(4) Submit the URB to the USB core;
(5) After the successful submission, the completion function of URB will be called by the USB core.
Now we step through the process of detailed analysis, so-called creation and allocation, is essentially the allocation of memory. As a Linux driver development programmer, you must understand Linux memory management knowledge and reasonable use of memory.
So how do we reasonably create and allocate URB and DMA buffers? Obviously, we should allocate it when we use it and release it when we are not.
So here's the question. When is it used, and when does it not? The problem is simple, that is, the master is allocated to read the data, after reading the release, and only when the WiFi module has data readable, the main control side can successfully read the data. So when does the WiFi module have data to read? --Here's the point! The WiFi module receives the wireless network data via the RF side and caches it in the ram of the WiFi chip, where the WiFi module has data to read.
Through the above analysis, we found a USB interface and WiFi module on the relationship between the clue, is the WiFi module receiving data, will trigger the USB interface read data;
Now, let's go to the receive function of the WiFi module and see if that's true?
in the WiFi receive function initialization, we can see that usb_alloc_urb () creates an interrupt Urb. The pseudo code is as follows:
int Xxxwifi_init_recv (_adapter *padapter) {struct Recv_priv *precvpriv = &padapter->recvpriv;int I, res = _SUCCESS ; struct Recv_buf *precvbuf;tasklet_init (&precvpriv->recv_tasklet, (Void (*) (unsigned long)) rtl8188eu_recv_ Tasklet, (unsigned long) padapter);p recvpriv->int_in_urb = usb_alloc_urb (0, Gfp_kernel); Create an interrupt Urbprecvpriv->int_in_buf = Rtw_zmalloc (Interrupt_msg_format_len);//init Recv_buf_rtw_init_queue (& Precvpriv->free_recv_buf_queue); _rtw_init_queue (&precvpriv->recv_buf_pending_queue);p Recvpriv Pallocated_recv_buf = Rtw_zmalloc (nr_recvbuff *sizeof (struct recv_buf) + 4);p recvbuf = (struct recv_buf*) precvpriv-> Precv_buf;for (i=0; i < Nr_recvbuff; i++) {_rtw_init_listhead (&precvbuf->list); _rtw_spinlock_init (& Precvbuf->recvbuf_lock);p RECVBUF->ALLOC_SZ = Max_recvbuf_sz;res = Rtw_os_recvbuf_resource_alloc (Padapter, PRECVBUF);p recvbuf->ref_cnt = 0;precvbuf->adapter =padapter;precvbuf++;} Precvpriv->free_recv_buf_queue_CNT = Nr_recvbuff;skb_queue_head_init (&precvpriv->rx_skb_queue); #ifdef config_prealloc_recv_skb{int i; Size_ptr tmpaddr=0; Size_ptr alignment=0;struct sk_buff *pskb=null;skb_queue_head_init (&precvpriv->free_recv_skb_queue); for (i= 0; i<nr_prealloc_recv_skb; i++) {pskb = Rtw_skb_alloc (MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ), if (PSKB) {Pskb->dev = Padapter->pnetdev;tmpaddr = ( SIZE_PTR) Pskb->data;alignment = tmpaddr & (recvbuff_align_sz-1); Skb_reserve (PSKB, (RECVBUFF_ALIGN_SZ- Alignment)); Skb_queue_tail (&precvpriv->free_recv_skb_queue, PSKB);} Pskb=null;}} #endifreturn Res;}
In the Rtw_os_recvbuf_resource_alloc function, create a batch URB and a DMA buffer. The pseudo code is as follows:
int Rtw_os_ Recvbuf_resource_alloc (_adapter *padapter, struct recv_buf *precvbuf) {int res=_success;struct Dvobj_priv*pdvobjpriv = Adapter_to_dvobj (padapter); struct USB_DEVICE*PUSBD = pdvobjpriv->pusbdev;precvbuf->irp_pending = _FALSE; Precvbuf->purb = usb_alloc_urb (0, Gfp_kernel); Create a batch URBPRECVBUF->PSKB = Null;precvbuf->reuse = _false;precvbuf->pallocated_buf = Precvbuf->pbuf = NULL ;p Recvbuf->pdata = Precvbuf->phead = Precvbuf->ptail = Precvbuf->pend = Null;precvbuf->transfer_len = 0; Precvbuf->len = 0; #ifdef config_use_usb_buffer_alloc_rxprecvbuf->pallocated_buf = Rtw_usb_buffer_alloc (PUSBD, (size_t) PRECVBUF->ALLOC_SZ, &precvbuf->dma_transfer_addr); Create a DMA buffer precvbuf->pbuf = precvbuf->pallocated_buf;if (precvbuf->pallocated_buf = = NULL) return _fail;# endif//config_use_usb_buffer_alloc_rxreturn Res;}
In the Usb_read_port () function, the batch URB is initialized by Usb_fill_bulk_urb () and submitted to the USB core, which is the 3rd, 4 steps of the USB read data operation process. In the Usb_fill_bulk_urb () function, initialize the URB completion function Usb_read_port_complete (), and the function Usb_read_port_complete () is called only when the URB commit is complete. The pseudo code is as follows:
Static u32 usb_read_port (struct intf_hdl *pintfhdl, u32 addr, u32 cnt, U8 *rmem) {struct recv_buf*precvbuf = (struct recv_b UF *) Rmem;_adapter*adapter = pintfhdl->padapter;struct Dvobj_priv*pdvobj = adapter_to_dvobj (adapter); struct Pwrctrl_priv *pwrctl = Dvobj_to_pwrctl (pdvobj); struct Recv_priv*precvpriv = &adapter->recvpriv;struct usb_ DEVICE*PUSBD = Pdvobj->pusbdev;rtl8188eu_init_recvbuf (Adapter, precvbuf);p recvpriv->rx_pending_cnt++;p urb = Precvbuf->purb;//translate DMA FIFO addr to Pipehandlepipe = FFADDR2PIPEHDL (pdvobj, addr); Usb_fill_bulk_urb (Purb, PUSBD, Pipe, Precvbuf->pbuf, MAX_RECVBUF_SZ, usb_read_port_complete, precvbuf);//context is Precvbuferr = Usb_submit_urb (Purb, gfp_atomic); return ret;}
With the code above, we know that the URB and DMA buffers are allocated when the WiFi module is ready to initialize the received data. In the Usb_read_port () function, the URB and commit urb are initialized.
Why does it have to do this? What is the purpose?
Next, we'll announce it in the next article.
reprint Please indicate source: Http://blog.csdn.net/Righthek Thank you!
"Smart Home article" WiFi Driver Understanding (3) Role of the--usb interface in the WiFi module