1 /******************************************************************************
4 * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
5 * Linux device driver for RTL8192SU
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
20 * Modifications for inclusion into the Linux staging tree are
21 * Copyright(c) 2010 Larry Finger. All rights reserved.
23 * Contact information:
24 * WLAN FAE <wlanfae@realtek.com>
25 * Larry Finger <Larry.Finger@lwfinger.net>
27 ******************************************************************************/
29 #define _HCI_OPS_OS_C_
31 #include <linux/usb.h>
33 #include "osdep_service.h"
34 #include "drv_types.h"
35 #include "osdep_intf.h"
38 #define RTL871X_VENQT_READ 0xc0
39 #define RTL871X_VENQT_WRITE 0x40
41 struct zero_bulkout_context
{
48 #define usb_write_cmd r8712_usb_write_mem
49 #define usb_write_cmd_complete usb_write_mem_complete
51 uint
r8712_usb_init_intf_priv(struct intf_priv
*pintfpriv
)
53 pintfpriv
->piorw_urb
= usb_alloc_urb(0, GFP_ATOMIC
);
54 if (!pintfpriv
->piorw_urb
)
56 sema_init(&(pintfpriv
->io_retevt
), 0);
60 void r8712_usb_unload_intf_priv(struct intf_priv
*pintfpriv
)
62 if (pintfpriv
->piorw_urb
) {
63 usb_kill_urb(pintfpriv
->piorw_urb
);
64 usb_free_urb(pintfpriv
->piorw_urb
);
68 static unsigned int ffaddr2pipehdl(struct dvobj_priv
*pdvobj
, u32 addr
)
70 unsigned int pipe
= 0;
71 struct usb_device
*pusbd
= pdvobj
->pusbdev
;
73 if (pdvobj
->nr_endpoint
== 11) {
76 pipe
= usb_sndbulkpipe(pusbd
, 0x07);
79 pipe
= usb_sndbulkpipe(pusbd
, 0x06);
82 pipe
= usb_sndbulkpipe(pusbd
, 0x05);
85 pipe
= usb_sndbulkpipe(pusbd
, 0x04);
87 case RTL8712_DMA_BCNQ
:
88 pipe
= usb_sndbulkpipe(pusbd
, 0x0a);
90 case RTL8712_DMA_BMCQ
: /* HI Queue */
91 pipe
= usb_sndbulkpipe(pusbd
, 0x0b);
93 case RTL8712_DMA_MGTQ
:
94 pipe
= usb_sndbulkpipe(pusbd
, 0x0c);
96 case RTL8712_DMA_RX0FF
:
97 pipe
= usb_rcvbulkpipe(pusbd
, 0x03); /* in */
99 case RTL8712_DMA_C2HCMD
:
100 pipe
= usb_rcvbulkpipe(pusbd
, 0x09); /* in */
102 case RTL8712_DMA_H2CCMD
:
103 pipe
= usb_sndbulkpipe(pusbd
, 0x0d);
106 } else if (pdvobj
->nr_endpoint
== 6) {
108 case RTL8712_DMA_BKQ
:
109 pipe
= usb_sndbulkpipe(pusbd
, 0x07);
111 case RTL8712_DMA_BEQ
:
112 pipe
= usb_sndbulkpipe(pusbd
, 0x06);
114 case RTL8712_DMA_VIQ
:
115 pipe
= usb_sndbulkpipe(pusbd
, 0x05);
117 case RTL8712_DMA_VOQ
:
118 pipe
= usb_sndbulkpipe(pusbd
, 0x04);
120 case RTL8712_DMA_RX0FF
:
121 case RTL8712_DMA_C2HCMD
:
122 pipe
= usb_rcvbulkpipe(pusbd
, 0x03); /* in */
124 case RTL8712_DMA_H2CCMD
:
125 case RTL8712_DMA_BCNQ
:
126 case RTL8712_DMA_BMCQ
:
127 case RTL8712_DMA_MGTQ
:
128 pipe
= usb_sndbulkpipe(pusbd
, 0x0d);
131 } else if (pdvobj
->nr_endpoint
== 4) {
133 case RTL8712_DMA_BEQ
:
134 pipe
= usb_sndbulkpipe(pusbd
, 0x06);
136 case RTL8712_DMA_VOQ
:
137 pipe
= usb_sndbulkpipe(pusbd
, 0x04);
139 case RTL8712_DMA_RX0FF
:
140 case RTL8712_DMA_C2HCMD
:
141 pipe
= usb_rcvbulkpipe(pusbd
, 0x03); /* in */
143 case RTL8712_DMA_H2CCMD
:
144 case RTL8712_DMA_BCNQ
:
145 case RTL8712_DMA_BMCQ
:
146 case RTL8712_DMA_MGTQ
:
147 pipe
= usb_sndbulkpipe(pusbd
, 0x0d);
155 static void usb_write_mem_complete(struct urb
*purb
)
157 struct io_queue
*pio_q
= (struct io_queue
*)purb
->context
;
158 struct intf_hdl
*pintf
= &(pio_q
->intf
);
159 struct intf_priv
*pintfpriv
= pintf
->pintfpriv
;
160 struct _adapter
*padapter
= (struct _adapter
*)pintf
->adapter
;
162 if (purb
->status
!= 0) {
163 if (purb
->status
== (-ESHUTDOWN
))
164 padapter
->bDriverStopped
= true;
166 padapter
->bSurpriseRemoved
= true;
168 up(&pintfpriv
->io_retevt
);
171 void r8712_usb_write_mem(struct intf_hdl
*pintfhdl
, u32 addr
, u32 cnt
, u8
*wmem
)
175 struct _adapter
*padapter
= (struct _adapter
*)pintfhdl
->adapter
;
176 struct intf_priv
*pintfpriv
= pintfhdl
->pintfpriv
;
177 struct io_queue
*pio_queue
= (struct io_queue
*)padapter
->pio_queue
;
178 struct dvobj_priv
*pdvobj
= (struct dvobj_priv
*)pintfpriv
->intf_dev
;
179 struct usb_device
*pusbd
= pdvobj
->pusbdev
;
180 struct urb
*piorw_urb
= pintfpriv
->piorw_urb
;
182 if ((padapter
->bDriverStopped
) || (padapter
->bSurpriseRemoved
) ||
183 (padapter
->pwrctrlpriv
.pnp_bstop_trx
))
185 /* translate DMA FIFO addr to pipehandle */
186 pipe
= ffaddr2pipehdl(pdvobj
, addr
);
189 usb_fill_bulk_urb(piorw_urb
, pusbd
, pipe
,
190 wmem
, cnt
, usb_write_mem_complete
,
192 status
= usb_submit_urb(piorw_urb
, GFP_ATOMIC
);
193 _down_sema(&pintfpriv
->io_retevt
);
196 static void r8712_usb_read_port_complete(struct urb
*purb
)
199 struct recv_buf
*precvbuf
= (struct recv_buf
*)purb
->context
;
200 struct _adapter
*padapter
= (struct _adapter
*)precvbuf
->adapter
;
201 struct recv_priv
*precvpriv
= &padapter
->recvpriv
;
203 if (padapter
->bSurpriseRemoved
|| padapter
->bDriverStopped
)
205 if (purb
->status
== 0) { /* SUCCESS */
206 if ((purb
->actual_length
> (MAX_RECVBUF_SZ
)) ||
207 (purb
->actual_length
< RXDESC_SIZE
)) {
208 precvbuf
->reuse
= true;
209 r8712_read_port(padapter
, precvpriv
->ff_hwaddr
, 0,
210 (unsigned char *)precvbuf
);
212 precvbuf
->transfer_len
= purb
->actual_length
;
213 pbuf
= (uint
*)precvbuf
->pbuf
;
214 isevt
= le32_to_cpu(*(pbuf
+ 1)) & 0x1ff;
215 if ((isevt
& 0x1ff) == 0x1ff) {
216 r8712_rxcmd_event_hdl(padapter
, pbuf
);
217 precvbuf
->reuse
= true;
218 r8712_read_port(padapter
, precvpriv
->ff_hwaddr
,
219 0, (unsigned char *)precvbuf
);
221 _pkt
*pskb
= precvbuf
->pskb
;
222 skb_put(pskb
, purb
->actual_length
);
223 skb_queue_tail(&precvpriv
->rx_skb_queue
, pskb
);
224 tasklet_hi_schedule(&precvpriv
->recv_tasklet
);
225 precvbuf
->pskb
= NULL
;
226 precvbuf
->reuse
= false;
227 r8712_read_port(padapter
, precvpriv
->ff_hwaddr
,
228 0, (unsigned char *)precvbuf
);
232 switch (purb
->status
) {
238 padapter
->bDriverStopped
= true;
241 precvbuf
->reuse
= true;
242 r8712_read_port(padapter
, precvpriv
->ff_hwaddr
, 0,
243 (unsigned char *)precvbuf
);
246 printk(KERN_ERR
"r8712u: ERROR: URB IS IN"
255 u32
r8712_usb_read_port(struct intf_hdl
*pintfhdl
, u32 addr
, u32 cnt
, u8
*rmem
)
262 struct urb
*purb
= NULL
;
263 struct recv_buf
*precvbuf
= (struct recv_buf
*)rmem
;
264 struct intf_priv
*pintfpriv
= pintfhdl
->pintfpriv
;
265 struct dvobj_priv
*pdvobj
= (struct dvobj_priv
*)pintfpriv
->intf_dev
;
266 struct _adapter
*adapter
= (struct _adapter
*)pdvobj
->padapter
;
267 struct recv_priv
*precvpriv
= &adapter
->recvpriv
;
268 struct usb_device
*pusbd
= pdvobj
->pusbdev
;
270 if (adapter
->bDriverStopped
|| adapter
->bSurpriseRemoved
||
271 adapter
->pwrctrlpriv
.pnp_bstop_trx
)
273 if ((precvbuf
->reuse
== false) || (precvbuf
->pskb
== NULL
)) {
274 precvbuf
->pskb
= skb_dequeue(&precvpriv
->free_recv_skb_queue
);
275 if (NULL
!= precvbuf
->pskb
)
276 precvbuf
->reuse
= true;
278 if (precvbuf
!= NULL
) {
279 r8712_init_recvbuf(adapter
, precvbuf
);
280 /* re-assign for linux based on skb */
281 if ((precvbuf
->reuse
== false) || (precvbuf
->pskb
== NULL
)) {
282 precvbuf
->pskb
= netdev_alloc_skb(adapter
->pnetdev
,
283 MAX_RECVBUF_SZ
+ RECVBUFF_ALIGN_SZ
);
284 if (precvbuf
->pskb
== NULL
)
286 tmpaddr
= (addr_t
)precvbuf
->pskb
->data
;
287 alignment
= tmpaddr
& (RECVBUFF_ALIGN_SZ
-1);
288 skb_reserve(precvbuf
->pskb
,
289 (RECVBUFF_ALIGN_SZ
- alignment
));
290 precvbuf
->phead
= precvbuf
->pskb
->head
;
291 precvbuf
->pdata
= precvbuf
->pskb
->data
;
292 precvbuf
->ptail
= skb_tail_pointer(precvbuf
->pskb
);
293 precvbuf
->pend
= skb_end_pointer(precvbuf
->pskb
);
294 precvbuf
->pbuf
= precvbuf
->pskb
->data
;
295 } else { /* reuse skb */
296 precvbuf
->phead
= precvbuf
->pskb
->head
;
297 precvbuf
->pdata
= precvbuf
->pskb
->data
;
298 precvbuf
->ptail
= skb_tail_pointer(precvbuf
->pskb
);
299 precvbuf
->pend
= skb_end_pointer(precvbuf
->pskb
);
300 precvbuf
->pbuf
= precvbuf
->pskb
->data
;
301 precvbuf
->reuse
= false;
303 purb
= precvbuf
->purb
;
304 /* translate DMA FIFO addr to pipehandle */
305 pipe
= ffaddr2pipehdl(pdvobj
, addr
);
306 usb_fill_bulk_urb(purb
, pusbd
, pipe
,
307 precvbuf
->pbuf
, MAX_RECVBUF_SZ
,
308 r8712_usb_read_port_complete
,
310 err
= usb_submit_urb(purb
, GFP_ATOMIC
);
311 if ((err
) && (err
!= (-EPERM
)))
318 void r8712_usb_read_port_cancel(struct _adapter
*padapter
)
321 struct recv_buf
*precvbuf
;
323 precvbuf
= (struct recv_buf
*)padapter
->recvpriv
.precv_buf
;
324 for (i
= 0; i
< NR_RECVBUFF
; i
++) {
326 usb_kill_urb(precvbuf
->purb
);
331 void r8712_xmit_bh(void *priv
)
334 struct _adapter
*padapter
= (struct _adapter
*)priv
;
335 struct xmit_priv
*pxmitpriv
= &padapter
->xmitpriv
;
337 if ((padapter
->bDriverStopped
== true) ||
338 (padapter
->bSurpriseRemoved
== true)) {
339 printk(KERN_ERR
"r8712u: xmit_bh => bDriverStopped"
340 " or bSurpriseRemoved\n");
343 ret
= r8712_xmitframe_complete(padapter
, pxmitpriv
, NULL
);
346 tasklet_hi_schedule(&pxmitpriv
->xmit_tasklet
);
349 static void usb_write_port_complete(struct urb
*purb
)
352 struct xmit_frame
*pxmitframe
= (struct xmit_frame
*)purb
->context
;
353 struct xmit_buf
*pxmitbuf
= pxmitframe
->pxmitbuf
;
354 struct _adapter
*padapter
= pxmitframe
->padapter
;
355 struct xmit_priv
*pxmitpriv
= &padapter
->xmitpriv
;
356 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
358 switch (pattrib
->priority
) {
361 pxmitpriv
->bkq_cnt
--;
365 pxmitpriv
->viq_cnt
--;
369 pxmitpriv
->voq_cnt
--;
374 pxmitpriv
->beq_cnt
--;
377 pxmitpriv
->txirp_cnt
--;
378 for (i
= 0; i
< 8; i
++) {
379 if (purb
== pxmitframe
->pxmit_urb
[i
]) {
380 pxmitframe
->bpending
[i
] = false;
384 if (padapter
->bSurpriseRemoved
)
386 switch (purb
->status
) {
390 printk(KERN_WARNING
"r8712u: pipe error: (%d)\n", purb
->status
);
393 /* not to consider tx fragment */
394 r8712_free_xmitframe_ex(pxmitpriv
, pxmitframe
);
395 r8712_free_xmitbuf(pxmitpriv
, pxmitbuf
);
396 tasklet_hi_schedule(&pxmitpriv
->xmit_tasklet
);
399 u32
r8712_usb_write_port(struct intf_hdl
*pintfhdl
, u32 addr
, u32 cnt
, u8
*wmem
)
405 struct urb
*purb
= NULL
;
406 struct _adapter
*padapter
= (struct _adapter
*)pintfhdl
->adapter
;
407 struct dvobj_priv
*pdvobj
= (struct dvobj_priv
*)&padapter
->dvobjpriv
;
408 struct xmit_priv
*pxmitpriv
= &padapter
->xmitpriv
;
409 struct xmit_frame
*pxmitframe
= (struct xmit_frame
*)wmem
;
410 struct usb_device
*pusbd
= pdvobj
->pusbdev
;
411 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
413 if ((padapter
->bDriverStopped
) || (padapter
->bSurpriseRemoved
) ||
414 (padapter
->pwrctrlpriv
.pnp_bstop_trx
))
416 for (i
= 0; i
< 8; i
++) {
417 if (pxmitframe
->bpending
[i
] == false) {
418 spin_lock_irqsave(&pxmitpriv
->lock
, irqL
);
419 pxmitpriv
->txirp_cnt
++;
420 pxmitframe
->bpending
[i
] = true;
421 switch (pattrib
->priority
) {
424 pxmitpriv
->bkq_cnt
++;
428 pxmitpriv
->viq_cnt
++;
432 pxmitpriv
->voq_cnt
++;
437 pxmitpriv
->beq_cnt
++;
440 spin_unlock_irqrestore(&pxmitpriv
->lock
, irqL
);
441 pxmitframe
->sz
[i
] = (u16
)cnt
;
442 purb
= pxmitframe
->pxmit_urb
[i
];
447 if (pdvobj
->ishighspeed
) {
448 if (cnt
> 0 && cnt
% 512 == 0)
451 if (cnt
> 0 && cnt
% 64 == 0)
454 /* translate DMA FIFO addr to pipehandle */
455 pipe
= ffaddr2pipehdl(pdvobj
, addr
);
456 if (pxmitpriv
->free_xmitbuf_cnt
%NR_XMITBUFF
== 0)
457 purb
->transfer_flags
&= (~URB_NO_INTERRUPT
);
459 purb
->transfer_flags
|= URB_NO_INTERRUPT
;
462 usb_fill_bulk_urb(purb
, pusbd
, pipe
,
463 pxmitframe
->mem_addr
,
464 cnt
, usb_write_port_complete
,
465 pxmitframe
); /* context is xmit_frame */
466 status
= usb_submit_urb(purb
, GFP_ATOMIC
);
474 void r8712_usb_write_port_cancel(struct _adapter
*padapter
)
477 struct xmit_buf
*pxmitbuf
= (struct xmit_buf
*)
478 padapter
->xmitpriv
.pxmitbuf
;
480 for (i
= 0; i
< NR_XMITBUFF
; i
++) {
481 for (j
= 0; j
< 8; j
++) {
482 if (pxmitbuf
->pxmit_urb
[j
])
483 usb_kill_urb(pxmitbuf
->pxmit_urb
[j
]);
489 int r8712_usbctrl_vendorreq(struct intf_priv
*pintfpriv
, u8 request
, u16 value
,
490 u16 index
, void *pdata
, u16 len
, u8 requesttype
)
495 struct dvobj_priv
*pdvobjpriv
= (struct dvobj_priv
*)
497 struct usb_device
*udev
= pdvobjpriv
->pusbdev
;
498 /* For mstar platform, mstar suggests the address for USB IO
499 * should be 16 bytes alignment. Trying to fix it here.
501 u8
*palloc_buf
, *pIo_buf
;
503 palloc_buf
= _malloc((u32
) len
+ 16);
504 if (palloc_buf
== NULL
) {
505 printk(KERN_ERR
"r8712u: [%s] Can't alloc memory for vendor"
506 " request\n", __func__
);
509 pIo_buf
= palloc_buf
+ 16 - ((addr_t
)(palloc_buf
) & 0x0f);
510 if (requesttype
== 0x01) {
511 pipe
= usb_rcvctrlpipe(udev
, 0); /* read_in */
512 reqtype
= RTL871X_VENQT_READ
;
514 pipe
= usb_sndctrlpipe(udev
, 0); /* write_out */
515 reqtype
= RTL871X_VENQT_WRITE
;
516 memcpy(pIo_buf
, pdata
, len
);
518 status
= usb_control_msg(udev
, pipe
, request
, reqtype
, value
, index
,
519 pIo_buf
, len
, HZ
/ 2);
520 if (status
> 0) { /* Success this control transfer. */
521 if (requesttype
== 0x01) {
522 /* For Control read transfer, we have to copy the read
523 * data from pIo_buf to pdata.
525 memcpy(pdata
, pIo_buf
, status
);