OSDN Git Service

Make certain that if, for, while, do, and switch have a space before an open paren
[android-x86/external-modules-rtl8723au.git] / hal / usb_ops_linux.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17  *
18  *
19  ******************************************************************************/
20 #define _HCI_OPS_OS_C_
21
22 #include <drv_conf.h>
23 #include <osdep_service.h>
24 #include <drv_types.h>
25 #include <osdep_intf.h>
26 #include <usb_ops.h>
27 #include <circ_buf.h>
28 #include <recv_osdep.h>
29 #include <rtl8723a_hal.h>
30 #include <rtl8723a_recv.h>
31
32 static int usbctrl_vendorreq(struct intf_hdl *pintfhdl, u8 request, u16 value, u16 index, void *pdata, u16 len, u8 requesttype)
33 {
34         _adapter                *padapter = pintfhdl->padapter ;
35         struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
36         struct usb_device *udev=pdvobjpriv->pusbdev;
37
38         unsigned int pipe;
39         int status = 0;
40         u32 tmp_buflen=0;
41         u8 reqtype;
42         u8 *pIo_buf;
43         int vendorreq_times = 0;
44
45         #ifdef CONFIG_USB_VENDOR_REQ_BUFFER_DYNAMIC_ALLOCATE
46         u8 *tmp_buf;
47         #else // use stack memory
48         u8 tmp_buf[MAX_USB_IO_CTL_SIZE];
49         #endif
50
51 #ifdef CONFIG_CONCURRENT_MODE
52         if (padapter->adapter_type > PRIMARY_ADAPTER)
53         {
54                 padapter = padapter->pbuddy_adapter;
55                 pdvobjpriv = adapter_to_dvobj(padapter);
56                 udev = pdvobjpriv->pusbdev;
57         }
58 #endif
59
60
61         //DBG_871X("%s %s:%d\n",__FUNCTION__, current->comm, current->pid);
62
63         if ((padapter->bSurpriseRemoved) ||(padapter->pwrctrlpriv.pnp_bstop_trx)){
64                 RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usbctrl_vendorreq:(padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n"));
65                 status = -EPERM;
66                 goto exit;
67         }
68
69         if (len>MAX_VENDOR_REQ_CMD_SIZE){
70                 DBG_8192C( "[%s] Buffer len error ,vendor request failed\n", __FUNCTION__ );
71                 status = -EINVAL;
72                 goto exit;
73         }
74
75         #ifdef CONFIG_USB_VENDOR_REQ_MUTEX
76         _enter_critical_mutex(&pdvobjpriv->usb_vendor_req_mutex, NULL);
77         #endif
78
79
80         // Acquire IO memory for vendorreq
81 #ifdef CONFIG_USB_VENDOR_REQ_BUFFER_PREALLOC
82         pIo_buf = pdvobjpriv->usb_vendor_req_buf;
83 #else
84         #ifdef CONFIG_USB_VENDOR_REQ_BUFFER_DYNAMIC_ALLOCATE
85         tmp_buf = rtw_malloc( (u32) len + ALIGNMENT_UNIT);
86         tmp_buflen =  (u32)len + ALIGNMENT_UNIT;
87         #else // use stack memory
88         tmp_buflen = MAX_USB_IO_CTL_SIZE;
89         #endif
90
91         // Added by Albert 2010/02/09
92         // For mstar platform, mstar suggests the address for USB IO should be 16 bytes alignment.
93         // Trying to fix it here.
94         pIo_buf = (tmp_buf==NULL)?NULL:tmp_buf + ALIGNMENT_UNIT -((SIZE_PTR)(tmp_buf) & 0x0f );
95 #endif
96
97         if ( pIo_buf== NULL) {
98                 DBG_8192C( "[%s] pIo_buf == NULL\n", __FUNCTION__ );
99                 status = -ENOMEM;
100                 goto release_mutex;
101         }
102
103         while (++vendorreq_times<= MAX_USBCTRL_VENDORREQ_TIMES)
104         {
105                 memset(pIo_buf, 0, len);
106
107                 if (requesttype == 0x01) {
108                         pipe = usb_rcvctrlpipe(udev, 0);//read_in
109                         reqtype =  REALTEK_USB_VENQT_READ;
110                 } else {
111                         pipe = usb_sndctrlpipe(udev, 0);//write_out
112                         reqtype =  REALTEK_USB_VENQT_WRITE;
113                         memcpy( pIo_buf, pdata, len);
114                 }
115
116                 status = rtw_usb_control_msg(udev, pipe, request, reqtype, value, index, pIo_buf, len, RTW_USB_CONTROL_MSG_TIMEOUT);
117
118                 if ( status == len)   // Success this control transfer.
119                 {
120                         rtw_reset_continual_urb_error(pdvobjpriv);
121                         if ( requesttype == 0x01 )
122                         {   // For Control read transfer, we have to copy the read data from pIo_buf to pdata.
123                                 memcpy( pdata, pIo_buf,  len );
124                         }
125                 }
126                 else { // error cases
127                         DBG_8192C("reg 0x%x, usb %s %u fail, status:%d value=0x%x, vendorreq_times:%d\n"
128                                 , value,(requesttype == 0x01)?"read":"write" , len, status, *(u32*)pdata, vendorreq_times);
129
130                         if (status < 0) {
131                                 if (status == (-ESHUTDOWN)      || status == -ENODEV    )
132                                 {
133                                         padapter->bSurpriseRemoved = true;
134                                 } else {
135                                         #ifdef DBG_CONFIG_ERROR_DETECT
136                                         {
137                                                 HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);
138                                                 pHalData->srestpriv.Wifi_Error_Status = USB_VEN_REQ_CMD_FAIL;
139                                         }
140                                         #endif
141                                 }
142                         }
143                         else // status != len && status >= 0
144                         {
145                                 if (status > 0) {
146                                         if ( requesttype == 0x01 )
147                                         {   // For Control read transfer, we have to copy the read data from pIo_buf to pdata.
148                                                 memcpy( pdata, pIo_buf,  len );
149                                         }
150                                 }
151                         }
152
153                         if (rtw_inc_and_chk_continual_urb_error(pdvobjpriv) == true ){
154                                 padapter->bSurpriseRemoved = true;
155                                 break;
156                         }
157
158                 }
159
160                 // firmware download is checksumed, don't retry
161                 if ( (value >= FW_8723A_START_ADDRESS && value <= FW_8723A_END_ADDRESS) || status == len )
162                         break;
163
164         }
165
166         // release IO memory used by vendorreq
167         #ifdef CONFIG_USB_VENDOR_REQ_BUFFER_DYNAMIC_ALLOCATE
168         rtw_mfree(tmp_buf, tmp_buflen);
169         #endif
170
171 release_mutex:
172         #ifdef CONFIG_USB_VENDOR_REQ_MUTEX
173         _exit_critical_mutex(&pdvobjpriv->usb_vendor_req_mutex, NULL);
174         #endif
175 exit:
176         return status;
177
178 }
179
180 static u8 usb_read8(struct intf_hdl *pintfhdl, u32 addr)
181 {
182         u8 request;
183         u8 requesttype;
184         u16 wvalue;
185         u16 index;
186         u16 len;
187         u8 data=0;
188
189         _func_enter_;
190
191         request = 0x05;
192         requesttype = 0x01;//read_in
193         index = 0;//n/a
194
195         wvalue = (u16)(addr&0x0000ffff);
196         len = 1;
197
198         usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
199
200         _func_exit_;
201
202         return data;
203
204 }
205
206 static u16 usb_read16(struct intf_hdl *pintfhdl, u32 addr)
207 {
208         u8 request;
209         u8 requesttype;
210         u16 wvalue;
211         u16 index;
212         u16 len;
213         u16 data=0;
214
215         _func_enter_;
216
217         request = 0x05;
218         requesttype = 0x01;//read_in
219         index = 0;//n/a
220
221         wvalue = (u16)(addr&0x0000ffff);
222         len = 2;
223
224         usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
225
226         _func_exit_;
227
228         return data;
229
230 }
231
232 static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
233 {
234         u8 request;
235         u8 requesttype;
236         u16 wvalue;
237         u16 index;
238         u16 len;
239         u32 data=0;
240
241         _func_enter_;
242
243         request = 0x05;
244         requesttype = 0x01;//read_in
245         index = 0;//n/a
246
247         wvalue = (u16)(addr&0x0000ffff);
248         len = 4;
249
250         usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
251
252         _func_exit_;
253
254         return data;
255
256 }
257
258 static int usb_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val)
259 {
260         u8 request;
261         u8 requesttype;
262         u16 wvalue;
263         u16 index;
264         u16 len;
265         u8 data;
266         int ret;
267
268         _func_enter_;
269
270         request = 0x05;
271         requesttype = 0x00;//write_out
272         index = 0;//n/a
273
274         wvalue = (u16)(addr&0x0000ffff);
275         len = 1;
276
277         data = val;
278
279          ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
280
281         _func_exit_;
282
283         return ret;
284
285 }
286
287 static int usb_write16(struct intf_hdl *pintfhdl, u32 addr, u16 val)
288 {
289         u8 request;
290         u8 requesttype;
291         u16 wvalue;
292         u16 index;
293         u16 len;
294         u16 data;
295         int ret;
296
297         _func_enter_;
298
299         request = 0x05;
300         requesttype = 0x00;//write_out
301         index = 0;//n/a
302
303         wvalue = (u16)(addr&0x0000ffff);
304         len = 2;
305
306         data = val;
307
308         ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
309
310         _func_exit_;
311
312         return ret;
313
314 }
315
316 static int usb_write32(struct intf_hdl *pintfhdl, u32 addr, u32 val)
317 {
318         u8 request;
319         u8 requesttype;
320         u16 wvalue;
321         u16 index;
322         u16 len;
323         u32 data;
324         int ret;
325
326         _func_enter_;
327
328         request = 0x05;
329         requesttype = 0x00;//write_out
330         index = 0;//n/a
331
332         wvalue = (u16)(addr&0x0000ffff);
333         len = 4;
334         data = val;
335
336
337         ret =usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
338
339         _func_exit_;
340
341         return ret;
342
343 }
344
345 static int usb_writeN(struct intf_hdl *pintfhdl, u32 addr, u32 length, u8 *pdata)
346 {
347         u8 request;
348         u8 requesttype;
349         u16 wvalue;
350         u16 index;
351         u16 len;
352         u8 buf[VENDOR_CMD_MAX_DATA_LEN]={0};
353         int ret;
354
355         _func_enter_;
356
357         request = 0x05;
358         requesttype = 0x00;//write_out
359         index = 0;//n/a
360
361         wvalue = (u16)(addr&0x0000ffff);
362         len = length;
363          memcpy(buf, pdata, len );
364
365         ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index, buf, len, requesttype);
366
367         _func_exit_;
368
369         return ret;
370
371 }
372
373 #ifdef CONFIG_USB_INTERRUPT_IN_PIPE
374 //
375 // Description:
376 //      Recognize the interrupt content by reading the interrupt register or content and masking interrupt mask (IMR)
377 //      if it is our NIC's interrupt. After recognizing, we may clear the all interrupts (ISR).
378 // Arguments:
379 //      [in] Adapter -
380 //              The adapter context.
381 //      [in] pContent -
382 //              Under PCI interface, this field is ignord.
383 //              Under USB interface, the content is the interrupt content pointer.
384 //              Under SDIO interface, this is the interrupt type which is Local interrupt or system interrupt.
385 //      [in] ContentLen -
386 //              The length in byte of pContent.
387 // Return:
388 //      If any interrupt matches the mask (IMR), return true, and return false otherwise.
389 //
390 bool
391 InterruptRecognized8723AU(
392         IN      PADAPTER                        Adapter,
393         IN      void *                          pContent,
394         IN      u32                             ContentLen
395 )
396 {
397         HAL_DATA_TYPE   *pHalData=GET_HAL_DATA(Adapter);
398         u8 *                    buffer = (u8 *)pContent;
399
400         memcpy(&(pHalData->IntArray[0]), &(buffer[USB_INTR_CONTENT_HISR_OFFSET]), 4);
401         pHalData->IntArray[0] &= pHalData->IntrMask[0];
402
403         //For HISR extension. Added by tynli. 2009.10.07.
404         memcpy(&(pHalData->IntArray[1]), &(buffer[USB_INTR_CONTENT_HISRE_OFFSET]), 4);
405         pHalData->IntArray[1] &= pHalData->IntrMask[1];
406         {
407                 struct reportpwrstate_parm report;
408                 memcpy(&report.state, &(buffer[USB_INTR_CPWM_OFFSET]), 1);
409 #ifdef CONFIG_LPS_LCLK
410                 if ( ((pHalData->IntArray[0])&UHIMR_CPWM)){
411                         _set_workitem(&Adapter->pwrctrlpriv.cpwm_event);
412                         pHalData->IntArray[0]&= ~UHIMR_CPWM;
413                 }
414 #endif
415         }
416         return (((pHalData->IntArray[0])&pHalData->IntrMask[0])!=0 ||
417                 ((pHalData->IntArray[1])&pHalData->IntrMask[1])!=0);
418
419 }
420
421
422 static void usb_read_interrupt_complete(struct urb *purb, struct pt_regs *regs)
423 {
424         int     err;
425         PADAPTER padapter = (PADAPTER)purb->context;
426
427
428         if (padapter->bSurpriseRemoved || padapter->bDriverStopped||padapter->bReadPortCancel)
429         {
430                 DBG_8192C("%s() RX Warning! bDriverStopped(%d) OR bSurpriseRemoved(%d) bReadPortCancel(%d)\n",
431                 __FUNCTION__,padapter->bDriverStopped, padapter->bSurpriseRemoved,padapter->bReadPortCancel);
432                 return;
433         }
434
435         if (purb->status == 0)//SUCCESS
436         {
437                 struct c2h_evt_hdr *c2h_evt = (struct c2h_evt_hdr *)purb->transfer_buffer;
438
439                 if (purb->actual_length > USB_INTR_CONTENT_LENGTH) {
440                         DBG_8192C("usb_read_interrupt_complete: purb->actual_length > USB_INTR_CONTENT_LENGTH\n");
441                 }
442
443                 InterruptRecognized8723AU(padapter, purb->transfer_buffer, purb->actual_length);
444
445                 if (c2h_evt_exist(c2h_evt)) {
446                         if ((c2h_evt = (struct c2h_evt_hdr *)rtw_malloc(16)) != NULL) {
447                                 memcpy(c2h_evt, purb->transfer_buffer, 16);
448                                 rtw_c2h_wk_cmd(padapter, (u8 *)c2h_evt);
449                         }
450                 }
451
452                 err = usb_submit_urb(purb, GFP_ATOMIC);
453                 if ((err) && (err != (-EPERM)))
454                 {
455                         DBG_8192C("cannot submit interrupt in-token(err = 0x%08x),urb_status = %d\n",err, purb->status);
456                 }
457         }
458         else
459         {
460                 DBG_8192C("###=> usb_read_interrupt_complete => urb status(%d)\n", purb->status);
461
462                 switch (purb->status)
463                 {
464                         case -EINVAL:
465                         case -EPIPE:
466                         case -ENODEV:
467                         case -ESHUTDOWN:
468                                 //padapter->bSurpriseRemoved = true;
469                                 RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_read_port_complete:bSurpriseRemoved=true\n"));
470                         case -ENOENT:
471                                 padapter->bDriverStopped = true;
472                                 RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_read_port_complete:bDriverStopped=true\n"));
473                                 break;
474                         case -EPROTO:
475                                 break;
476                         case -EINPROGRESS:
477                                 DBG_8192C("ERROR: URB IS IN PROGRESS!/n");
478                                 break;
479                         default:
480                                 break;
481                 }
482         }
483 }
484
485 static u32 usb_read_interrupt(struct intf_hdl *pintfhdl, u32 addr)
486 {
487         int     err;
488         unsigned int pipe;
489         u32     ret = _SUCCESS;
490         _adapter                        *adapter = pintfhdl->padapter;
491         struct dvobj_priv       *pdvobj = adapter_to_dvobj(adapter);
492         struct recv_priv        *precvpriv = &adapter->recvpriv;
493         struct usb_device       *pusbd = pdvobj->pusbdev;
494
495 _func_enter_;
496
497         //translate DMA FIFO addr to pipehandle
498         pipe = ffaddr2pipehdl(pdvobj, addr);
499
500         usb_fill_int_urb(precvpriv->int_in_urb, pusbd, pipe,
501                                         precvpriv->int_in_buf,
502                                         USB_INTR_CONTENT_LENGTH,
503                                         usb_read_interrupt_complete,
504                                         adapter,
505                                         1);
506
507         err = usb_submit_urb(precvpriv->int_in_urb, GFP_ATOMIC);
508         if ((err) && (err != (-EPERM)))
509         {
510                 DBG_8192C("cannot submit interrupt in-token(err = 0x%08x),urb_status = %d\n",err, precvpriv->int_in_urb->status);
511                 ret = _FAIL;
512         }
513
514 _func_exit_;
515
516         return ret;
517 }
518 #endif
519
520 static s32 pre_recv_entry(union recv_frame *precvframe, struct recv_stat *prxstat, struct phy_stat *pphy_info)
521 {
522         s32 ret=_SUCCESS;
523 #ifdef CONFIG_CONCURRENT_MODE
524         u8 *primary_myid, *secondary_myid, *paddr1;
525         union recv_frame        *precvframe_if2 = NULL;
526         _adapter *primary_padapter = precvframe->u.hdr.adapter;
527         _adapter *secondary_padapter = primary_padapter->pbuddy_adapter;
528         struct recv_priv *precvpriv = &primary_padapter->recvpriv;
529         _queue *pfree_recv_queue = &precvpriv->free_recv_queue;
530         u8      *pbuf = precvframe->u.hdr.rx_head;
531
532         if (!secondary_padapter)
533                 return ret;
534
535         paddr1 = GetAddr1Ptr(precvframe->u.hdr.rx_data);
536
537         if (IS_MCAST(paddr1) == false)//unicast packets
538         {
539                 //primary_myid = myid(&primary_padapter->eeprompriv);
540                 secondary_myid = myid(&secondary_padapter->eeprompriv);
541
542                 if (_rtw_memcmp(paddr1, secondary_myid, ETH_ALEN))
543                 {
544                         //change to secondary interface
545                         precvframe->u.hdr.adapter = secondary_padapter;
546                 }
547
548                 //ret = recv_entry(precvframe);
549
550         }
551         else // Handle BC/MC Packets
552         {
553
554                 u8 clone = true;
555
556                 if (true == clone) {
557                         //clone/copy to if2
558                         u8 shift_sz = 0;
559                         u32 alloc_sz, skb_len;
560                         _pkt     *pkt_copy = NULL;
561                         struct rx_pkt_attrib *pattrib = NULL;
562
563                         precvframe_if2 = rtw_alloc_recvframe(pfree_recv_queue);
564                         if (precvframe_if2) {
565                                 precvframe_if2->u.hdr.adapter = secondary_padapter;
566
567                                 _rtw_init_listhead(&precvframe_if2->u.hdr.list);
568                                 precvframe_if2->u.hdr.precvbuf = NULL;  //can't access the precvbuf for new arch.
569                                 precvframe_if2->u.hdr.len=0;
570
571                                 memcpy(&precvframe_if2->u.hdr.attrib, &precvframe->u.hdr.attrib, sizeof(struct rx_pkt_attrib));
572
573                                 pattrib = &precvframe_if2->u.hdr.attrib;
574
575                                 //      Modified by Albert 20101213
576                                 //      For 8 bytes IP header alignment.
577                                 if (pattrib->qos)       //      Qos data, wireless lan header length is 26
578                                         shift_sz = 6;
579                                 else
580                                         shift_sz = 0;
581
582                                 skb_len = pattrib->pkt_len;
583
584                                 // for first fragment packet, driver need allocate 1536+drvinfo_sz+RXDESC_SIZE to defrag packet.
585                                 // modify alloc_sz for recvive crc error packet by thomas 2011-06-02
586                                 if ((pattrib->mfrag == 1)&&(pattrib->frag_num == 0)){
587                                         //alloc_sz = 1664;      //1664 is 128 alignment.
588                                         if (skb_len <= 1650)
589                                                 alloc_sz = 1664;
590                                         else
591                                                 alloc_sz = skb_len + 14;
592                                 }
593                                 else {
594                                         alloc_sz = skb_len;
595                                         //      6 is for IP header 8 bytes alignment in QoS packet case.
596                                         //      8 is for skb->data 4 bytes alignment.
597                                         alloc_sz += 14;
598                                 }
599
600 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) // http://www.mail-archive.com/netdev@vger.kernel.org/msg17214.html
601                                 pkt_copy = dev_alloc_skb(alloc_sz);
602 #else
603                                 pkt_copy = netdev_alloc_skb(secondary_padapter->pnetdev, alloc_sz);
604 #endif
605                                 if (pkt_copy)
606                                 {
607                                         pkt_copy->dev = secondary_padapter->pnetdev;
608                                         precvframe_if2->u.hdr.pkt = pkt_copy;
609                                         skb_reserve( pkt_copy, 8 - ((SIZE_PTR)( pkt_copy->data ) & 7 ));//force pkt_copy->data at 8-byte alignment address
610                                         skb_reserve( pkt_copy, shift_sz );//force ip_hdr at 8-byte alignment address according to shift_sz.
611                                         memcpy(pkt_copy->data, pbuf, skb_len);
612                                         precvframe_if2->u.hdr.rx_head = precvframe_if2->u.hdr.rx_data = precvframe_if2->u.hdr.rx_tail = pkt_copy->data;
613                                         precvframe_if2->u.hdr.rx_end = pkt_copy->data + alloc_sz;
614
615                                         recvframe_put(precvframe_if2, skb_len);
616                                         //recvframe_pull(precvframe_if2, drvinfo_sz + RXDESC_SIZE);
617                                         if (pphy_info)
618                                         update_recvframe_phyinfo(precvframe_if2, pphy_info);
619                                         //rtl8192c_translate_rx_signal_stuff(precvframe_if2, pphy_info);
620
621                                         ret = rtw_recv_entry(precvframe_if2);
622
623                                 } else {
624                                         rtw_free_recvframe(precvframe_if2, pfree_recv_queue);
625                                         DBG_8192C("%s()-%d: alloc_skb() failed!\n", __FUNCTION__, __LINE__);
626                                 }
627
628                         }
629
630                 }
631
632         }
633
634         ret = rtw_recv_entry(precvframe);
635
636 #endif
637
638         return ret;
639
640 }
641
642 static int recvbuf2recvframe(_adapter *padapter, struct sk_buff *pskb)
643 {
644         u8      *pbuf;
645         u8      shift_sz = 0;
646         u16     pkt_cnt;
647         u32     pkt_offset, skb_len, alloc_sz;
648         s32     transfer_len;
649         struct recv_stat        *prxstat;
650         struct phy_stat *pphy_info = NULL;
651         struct sk_buff          *pkt_copy = NULL;
652         union recv_frame        *precvframe = NULL;
653         struct rx_pkt_attrib    *pattrib = NULL;
654         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);
655         struct recv_priv        *precvpriv = &padapter->recvpriv;
656         _queue                  *pfree_recv_queue = &precvpriv->free_recv_queue;
657
658
659         transfer_len = (s32)pskb->len;
660         pbuf = pskb->data;
661
662         prxstat = (struct recv_stat *)pbuf;
663         pkt_cnt = (le32_to_cpu(prxstat->rxdw2)>>16) & 0xff;
664
665         do{
666                 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
667                          ("recvbuf2recvframe: rxdesc=offsset 0:0x%08x, 4:0x%08x, 8:0x%08x, C:0x%08x\n",
668                           prxstat->rxdw0, prxstat->rxdw1, prxstat->rxdw2, prxstat->rxdw4));
669
670                 prxstat = (struct recv_stat *)pbuf;
671
672                 precvframe = rtw_alloc_recvframe(pfree_recv_queue);
673                 if (precvframe==NULL) {
674                         RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("recvbuf2recvframe: precvframe==NULL\n"));
675                         DBG_8192C("%s()-%d: rtw_alloc_recvframe() failed! RX Drop!\n", __FUNCTION__, __LINE__);
676                         goto _exit_recvbuf2recvframe;
677                 }
678
679                 _rtw_init_listhead(&precvframe->u.hdr.list);
680                 precvframe->u.hdr.precvbuf = NULL;      //can't access the precvbuf for new arch.
681                 precvframe->u.hdr.len=0;
682
683                 update_recvframe_attrib(precvframe, prxstat);
684
685                 pattrib = &precvframe->u.hdr.attrib;
686
687                 if (pattrib->crc_err){
688                         DBG_8192C("%s()-%d: RX Warning! rx CRC ERROR !!\n", __FUNCTION__, __LINE__);
689                         rtw_free_recvframe(precvframe, pfree_recv_queue);
690                         goto _exit_recvbuf2recvframe;
691                 }
692
693                 pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz + pattrib->shift_sz + pattrib->pkt_len;
694
695                 if ((pattrib->pkt_len<=0) || (pkt_offset>transfer_len))
696                 {
697                         RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("recvbuf2recvframe: pkt_len<=0\n"));
698                         DBG_8192C("%s()-%d: RX Warning!\n", __FUNCTION__, __LINE__);
699                         rtw_free_recvframe(precvframe, pfree_recv_queue);
700                         goto _exit_recvbuf2recvframe;
701                 }
702
703                 //      Modified by Albert 20101213
704                 //      For 8 bytes IP header alignment.
705                 if (pattrib->qos)       //      Qos data, wireless lan header length is 26
706                 {
707                         shift_sz = 6;
708                 }
709                 else
710                 {
711                         shift_sz = 0;
712                 }
713
714                 skb_len = pattrib->pkt_len;
715
716                 // for first fragment packet, driver need allocate 1536+drvinfo_sz+RXDESC_SIZE to defrag packet.
717                 // modify alloc_sz for recvive crc error packet by thomas 2011-06-02
718                 if ((pattrib->mfrag == 1)&&(pattrib->frag_num == 0)){
719                         //alloc_sz = 1664;      //1664 is 128 alignment.
720                         if (skb_len <= 1650)
721                                 alloc_sz = 1664;
722                         else
723                                 alloc_sz = skb_len + 14;
724                 }
725                 else {
726                         alloc_sz = skb_len;
727                         //      6 is for IP header 8 bytes alignment in QoS packet case.
728                         //      8 is for skb->data 4 bytes alignment.
729                         alloc_sz += 14;
730                 }
731
732 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) // http://www.mail-archive.com/netdev@vger.kernel.org/msg17214.html
733                 pkt_copy = dev_alloc_skb(alloc_sz);
734 #else
735                 pkt_copy = netdev_alloc_skb(padapter->pnetdev, alloc_sz);
736 #endif
737                 if (pkt_copy) {
738                         pkt_copy->dev = padapter->pnetdev;
739                         precvframe->u.hdr.pkt = pkt_copy;
740                         skb_reserve( pkt_copy, 8 - ((SIZE_PTR)( pkt_copy->data ) & 7 ));//force pkt_copy->data at 8-byte alignment address
741                         skb_reserve( pkt_copy, shift_sz );//force ip_hdr at 8-byte alignment address according to shift_sz.
742                         memcpy(pkt_copy->data, (pbuf + pattrib->shift_sz + pattrib->drvinfo_sz + RXDESC_SIZE), skb_len);
743                         precvframe->u.hdr.rx_head = precvframe->u.hdr.rx_data = precvframe->u.hdr.rx_tail = pkt_copy->data;
744                         precvframe->u.hdr.rx_end = pkt_copy->data + alloc_sz;
745                 } else {
746                         if ((pattrib->mfrag == 1)&&(pattrib->frag_num == 0)) {
747                                 DBG_8192C("recvbuf2recvframe: alloc_skb fail , drop frag frame\n");
748                                 rtw_free_recvframe(precvframe, pfree_recv_queue);
749                                 goto _exit_recvbuf2recvframe;
750                         }
751
752                         precvframe->u.hdr.pkt = skb_clone(pskb, GFP_ATOMIC);
753                         if (precvframe->u.hdr.pkt) {
754                                 precvframe->u.hdr.rx_head = precvframe->u.hdr.rx_data = precvframe->u.hdr.rx_tail
755                                         = pbuf+ pattrib->drvinfo_sz + RXDESC_SIZE;
756                                 precvframe->u.hdr.rx_end =  pbuf +pattrib->drvinfo_sz + RXDESC_SIZE+ alloc_sz;
757                         } else {
758                                 DBG_8192C("recvbuf2recvframe: skb_clone fail\n");
759                                 rtw_free_recvframe(precvframe, pfree_recv_queue);
760                                 goto _exit_recvbuf2recvframe;
761                         }
762
763                 }
764
765                 recvframe_put(precvframe, skb_len);
766
767                 if (pattrib->physt) {
768                         pphy_info = (struct phy_stat*)(pbuf + RXDESC_OFFSET);
769                         update_recvframe_phyinfo(precvframe, pphy_info);
770                 }
771
772 #ifdef CONFIG_USB_RX_AGGREGATION
773                 switch (pHalData->UsbRxAggMode) {
774                 case USB_RX_AGG_DMA:
775                 case USB_RX_AGG_MIX:
776                         pkt_offset = (u16)_RND128(pkt_offset);
777                         break;
778                 case USB_RX_AGG_USB:
779                         pkt_offset = (u16)_RND4(pkt_offset);
780                         break;
781                 case USB_RX_AGG_DISABLE:
782                 default:
783                         break;
784                 }
785 #endif
786
787 #ifdef CONFIG_CONCURRENT_MODE
788                 if (pre_recv_entry(precvframe, prxstat, pphy_info) != _SUCCESS)
789                 {
790                         RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("recvbuf2recvframe: recv_entry(precvframe) != _SUCCESS\n"));
791                 }
792 #else
793                 if (rtw_recv_entry(precvframe) != _SUCCESS)
794                 {
795                         RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("recvbuf2recvframe: rtw_recv_entry(precvframe) != _SUCCESS\n"));
796                 }
797 #endif
798
799                 pkt_cnt--;
800                 transfer_len -= pkt_offset;
801                 pbuf += pkt_offset;
802                 precvframe = NULL;
803                 pkt_copy = NULL;
804
805                 if (transfer_len>0 && pkt_cnt==0)
806                         pkt_cnt = (le32_to_cpu(prxstat->rxdw2)>>16) & 0xff;
807
808         }while ((transfer_len>0) && (pkt_cnt>0));
809
810 _exit_recvbuf2recvframe:
811
812         return _SUCCESS;
813 }
814
815 void rtl8192cu_recv_tasklet(void *priv)
816 {
817         struct sk_buff          *pskb;
818         _adapter                *padapter = (_adapter*)priv;
819         struct recv_priv        *precvpriv = &padapter->recvpriv;
820
821         while (NULL != (pskb = skb_dequeue(&precvpriv->rx_skb_queue)))
822         {
823                 if ((padapter->bDriverStopped == true)||(padapter->bSurpriseRemoved== true))
824                 {
825                         DBG_8192C("recv_tasklet => bDriverStopped or bSurpriseRemoved\n");
826                         dev_kfree_skb_any(pskb);
827                         break;
828                 }
829
830                 recvbuf2recvframe(padapter, pskb);
831
832 #ifdef CONFIG_PREALLOC_RECV_SKB
833
834                 skb_reset_tail_pointer(pskb);
835
836                 pskb->len = 0;
837
838                 skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
839
840 #else
841                 dev_kfree_skb_any(pskb);
842 #endif
843
844         }
845
846 }
847
848
849 static void usb_read_port_complete(struct urb *purb, struct pt_regs *regs)
850 {
851         unsigned long irqL;
852         uint isevt, *pbuf;
853         struct recv_buf *precvbuf = (struct recv_buf *)purb->context;
854         _adapter                        *padapter =(_adapter *)precvbuf->adapter;
855         struct recv_priv        *precvpriv = &padapter->recvpriv;
856
857         RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_read_port_complete!!!\n"));
858
859         //_enter_critical(&precvpriv->lock, &irqL);
860         //precvbuf->irp_pending=false;
861         //precvpriv->rx_pending_cnt --;
862         //_exit_critical(&precvpriv->lock, &irqL);
863
864         precvpriv->rx_pending_cnt --;
865
866         //if (precvpriv->rx_pending_cnt== 0)
867         //{
868         //      RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_read_port_complete: rx_pending_cnt== 0, set allrxreturnevt!\n"));
869         //      _rtw_up_sema(&precvpriv->allrxreturnevt);
870         //}
871
872         if (padapter->bSurpriseRemoved || padapter->bDriverStopped||padapter->bReadPortCancel)
873         {
874                 RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_read_port_complete:bDriverStopped(%d) OR bSurpriseRemoved(%d)\n", padapter->bDriverStopped, padapter->bSurpriseRemoved));
875
876         #ifdef CONFIG_PREALLOC_RECV_SKB
877                 precvbuf->reuse = true;
878         #else
879                 if (precvbuf->pskb){
880                         DBG_8192C("==> free skb(%p)\n",precvbuf->pskb);
881                         dev_kfree_skb_any(precvbuf->pskb);
882                 }
883         #endif
884                 DBG_8192C("%s()-%d: RX Warning! bDriverStopped(%d) OR bSurpriseRemoved(%d) bReadPortCancel(%d)\n",
885                 __FUNCTION__, __LINE__,padapter->bDriverStopped, padapter->bSurpriseRemoved,padapter->bReadPortCancel);
886                 goto exit;
887         }
888
889         if (purb->status==0)//SUCCESS
890         {
891                 if ((purb->actual_length > MAX_RECVBUF_SZ) || (purb->actual_length < RXDESC_SIZE))
892                 {
893                         RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_read_port_complete: (purb->actual_length > MAX_RECVBUF_SZ) || (purb->actual_length < RXDESC_SIZE)\n"));
894                         precvbuf->reuse = true;
895                         rtw_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);
896                         DBG_8192C("%s()-%d: RX Warning!\n", __FUNCTION__, __LINE__);
897                 }
898                 else
899                 {
900                         rtw_reset_continual_urb_error(adapter_to_dvobj(padapter));
901
902                         precvbuf->transfer_len = purb->actual_length;
903                         skb_put(precvbuf->pskb, purb->actual_length);
904                         skb_queue_tail(&precvpriv->rx_skb_queue, precvbuf->pskb);
905
906                         if (skb_queue_len(&precvpriv->rx_skb_queue)<=1)
907                                 tasklet_schedule(&precvpriv->recv_tasklet);
908
909                         precvbuf->pskb = NULL;
910                         precvbuf->reuse = false;
911                         rtw_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);
912                 }
913         }
914         else
915         {
916                 RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_read_port_complete : purb->status(%d) != 0\n", purb->status));
917
918                 DBG_8192C("###=> usb_read_port_complete => urb status(%d)\n", purb->status);
919
920                 if (rtw_inc_and_chk_continual_urb_error(adapter_to_dvobj(padapter)) == true ){
921                         padapter->bSurpriseRemoved = true;
922                 }
923
924                 switch (purb->status) {
925                         case -EINVAL:
926                         case -EPIPE:
927                         case -ENODEV:
928                         case -ESHUTDOWN:
929                                 //padapter->bSurpriseRemoved=true;
930                                 RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_read_port_complete:bSurpriseRemoved=true\n"));
931                         case -ENOENT:
932                                 padapter->bDriverStopped=true;
933                                 RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_read_port_complete:bDriverStopped=true\n"));
934                                 break;
935                         case -EPROTO:
936                         case -EOVERFLOW:
937                                 #ifdef DBG_CONFIG_ERROR_DETECT
938                                 {
939                                         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);
940                                         pHalData->srestpriv.Wifi_Error_Status = USB_READ_PORT_FAIL;
941                                 }
942                                 #endif
943                                 precvbuf->reuse = true;
944                                 rtw_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);
945                                 break;
946                         case -EINPROGRESS:
947                                 DBG_8192C("ERROR: URB IS IN PROGRESS!/n");
948                                 break;
949                         default:
950                                 break;
951                 }
952
953         }
954
955 exit:
956
957 _func_exit_;
958
959 }
960
961 static u32 usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
962 {
963         unsigned long irqL;
964         int err;
965         unsigned int pipe;
966         SIZE_PTR tmpaddr=0;
967         SIZE_PTR alignment=0;
968         u32 ret = _SUCCESS;
969         struct urb * purb = NULL;
970         struct recv_buf *precvbuf = (struct recv_buf *)rmem;
971         _adapter                *adapter = pintfhdl->padapter;
972         struct dvobj_priv       *pdvobj = adapter_to_dvobj(adapter);
973         struct recv_priv        *precvpriv = &adapter->recvpriv;
974         struct usb_device       *pusbd = pdvobj->pusbdev;
975
976
977 _func_enter_;
978
979         if (adapter->bDriverStopped || adapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)
980         {
981                 RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_read_port:( padapter->bDriverStopped ||padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n"));
982                 return _FAIL;
983         }
984
985 #ifdef CONFIG_PREALLOC_RECV_SKB
986         if ((precvbuf->reuse == false) || (precvbuf->pskb == NULL))
987         {
988                 if (NULL != (precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue)))
989                 {
990                         precvbuf->reuse = true;
991                 }
992         }
993 #endif
994
995
996         if (precvbuf !=NULL)
997         {
998                 rtl8192cu_init_recvbuf(adapter, precvbuf);
999
1000                 //re-assign for linux based on skb
1001                 if ((precvbuf->reuse == false) || (precvbuf->pskb == NULL))
1002                 {
1003                         //precvbuf->pskb = alloc_skb(MAX_RECVBUF_SZ, GFP_ATOMIC);//don't use this after v2.6.25
1004 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) // http://www.mail-archive.com/netdev@vger.kernel.org/msg17214.html
1005                         precvbuf->pskb = dev_alloc_skb(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
1006 #else
1007                         precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev, MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
1008 #endif
1009                         if (precvbuf->pskb == NULL)
1010                         {
1011                                 RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("init_recvbuf(): alloc_skb fail!\n"));
1012                                 return _FAIL;
1013                         }
1014
1015                         tmpaddr = (SIZE_PTR)precvbuf->pskb->data;
1016                         alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
1017                         skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
1018
1019                         precvbuf->phead = precvbuf->pskb->head;
1020                         precvbuf->pdata = precvbuf->pskb->data;
1021                         precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
1022                         precvbuf->pend = skb_end_pointer(precvbuf->pskb);
1023                         precvbuf->pbuf = precvbuf->pskb->data;
1024                 }
1025                 else//reuse skb
1026                 {
1027                         precvbuf->phead = precvbuf->pskb->head;
1028                         precvbuf->pdata = precvbuf->pskb->data;
1029                         precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
1030                         precvbuf->pend = skb_end_pointer(precvbuf->pskb);
1031                 precvbuf->pbuf = precvbuf->pskb->data;
1032
1033                         precvbuf->reuse = false;
1034                 }
1035
1036                 //_enter_critical(&precvpriv->lock, &irqL);
1037                 //precvpriv->rx_pending_cnt++;
1038                 //precvbuf->irp_pending = true;
1039                 //_exit_critical(&precvpriv->lock, &irqL);
1040
1041                 precvpriv->rx_pending_cnt++;
1042
1043                 purb = precvbuf->purb;
1044
1045                 //translate DMA FIFO addr to pipehandle
1046                 pipe = ffaddr2pipehdl(pdvobj, addr);
1047
1048                 usb_fill_bulk_urb(purb, pusbd, pipe,
1049                                                 precvbuf->pbuf,
1050                                                 MAX_RECVBUF_SZ,
1051                                                 usb_read_port_complete,
1052                                                 precvbuf);//context is precvbuf
1053
1054                 err = usb_submit_urb(purb, GFP_ATOMIC);
1055                 if ((err) && (err != (-EPERM)))
1056                 {
1057                         RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("cannot submit rx in-token(err=0x%.8x), URB_STATUS =0x%.8x", err, purb->status));
1058                         DBG_8192C("cannot submit rx in-token(err = 0x%08x),urb_status = %d\n",err,purb->status);
1059                         ret = _FAIL;
1060                 }
1061         }
1062         else
1063         {
1064                 RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_read_port:precvbuf ==NULL\n"));
1065                 ret = _FAIL;
1066         }
1067
1068 _func_exit_;
1069
1070         return ret;
1071 }
1072
1073 void rtl8192cu_xmit_tasklet(void *priv)
1074 {
1075         int ret = false;
1076         _adapter *padapter = (_adapter*)priv;
1077         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1078
1079         if (check_fwstate(&padapter->mlmepriv, _FW_UNDER_SURVEY) == true)
1080                 return;
1081
1082         while (1)
1083         {
1084                 if ((padapter->bDriverStopped == true)||(padapter->bSurpriseRemoved== true) || (padapter->bWritePortCancel == true))
1085                 {
1086                         DBG_8192C("xmit_tasklet => bDriverStopped or bSurpriseRemoved or bWritePortCancel\n");
1087                         break;
1088                 }
1089
1090                 ret = rtl8192cu_xmitframe_complete(padapter, pxmitpriv, NULL);
1091
1092                 if (ret==false)
1093                         break;
1094
1095         }
1096
1097 }
1098
1099 void rtl8723au_set_intf_ops(struct _io_ops      *pops)
1100 {
1101         _func_enter_;
1102
1103         memset((u8 *)pops, 0, sizeof(struct _io_ops));
1104
1105         pops->_read8 = &usb_read8;
1106         pops->_read16 = &usb_read16;
1107         pops->_read32 = &usb_read32;
1108         pops->_read_mem = &usb_read_mem;
1109         pops->_read_port = &usb_read_port;
1110
1111         pops->_write8 = &usb_write8;
1112         pops->_write16 = &usb_write16;
1113         pops->_write32 = &usb_write32;
1114         pops->_writeN = &usb_writeN;
1115
1116 #ifdef CONFIG_USB_SUPPORT_ASYNC_VDN_REQ
1117         pops->_write8_async= &usb_async_write8;
1118         pops->_write16_async = &usb_async_write16;
1119         pops->_write32_async = &usb_async_write32;
1120 #endif
1121         pops->_write_mem = &usb_write_mem;
1122         pops->_write_port = &usb_write_port;
1123
1124         pops->_read_port_cancel = &usb_read_port_cancel;
1125         pops->_write_port_cancel = &usb_write_port_cancel;
1126
1127 #ifdef CONFIG_USB_INTERRUPT_IN_PIPE
1128         pops->_read_interrupt = &usb_read_interrupt;
1129 #endif
1130
1131         _func_exit_;
1132
1133 }
1134 void rtl8723au_set_hw_type(_adapter *padapter)
1135 {
1136         padapter->chip_type = RTL8723A;
1137         padapter->HardwareType = HARDWARE_TYPE_RTL8723AU;
1138         DBG_871X("CHIP TYPE: RTL8723A\n");
1139 }