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 "osdep_service.h"
32 #include "drv_types.h"
33 #include "osdep_intf.h"
36 #define RTL871X_VENQT_READ 0xc0
37 #define RTL871X_VENQT_WRITE 0x40
39 struct zero_bulkout_context
{
46 #define usb_write_cmd r8712_usb_write_mem
47 #define usb_write_cmd_complete usb_write_mem_complete
49 uint
r8712_usb_init_intf_priv(struct intf_priv
*pintfpriv
)
51 pintfpriv
->piorw_urb
= _usb_alloc_urb(0, GFP_ATOMIC
);
52 if (!pintfpriv
->piorw_urb
)
54 sema_init(&(pintfpriv
->io_retevt
), 0);
58 void r8712_usb_unload_intf_priv(struct intf_priv
*pintfpriv
)
60 if (pintfpriv
->piorw_urb
) {
61 usb_kill_urb(pintfpriv
->piorw_urb
);
62 usb_free_urb(pintfpriv
->piorw_urb
);
66 static unsigned int ffaddr2pipehdl(struct dvobj_priv
*pdvobj
, u32 addr
)
68 unsigned int pipe
= 0;
69 struct usb_device
*pusbd
= pdvobj
->pusbdev
;
71 if (pdvobj
->nr_endpoint
== 11) {
74 pipe
= usb_sndbulkpipe(pusbd
, 0x07);
77 pipe
= usb_sndbulkpipe(pusbd
, 0x06);
80 pipe
= usb_sndbulkpipe(pusbd
, 0x05);
83 pipe
= usb_sndbulkpipe(pusbd
, 0x04);
85 case RTL8712_DMA_BCNQ
:
86 pipe
= usb_sndbulkpipe(pusbd
, 0x0a);
88 case RTL8712_DMA_BMCQ
: /* HI Queue */
89 pipe
= usb_sndbulkpipe(pusbd
, 0x0b);
91 case RTL8712_DMA_MGTQ
:
92 pipe
= usb_sndbulkpipe(pusbd
, 0x0c);
94 case RTL8712_DMA_RX0FF
:
95 pipe
= usb_rcvbulkpipe(pusbd
, 0x03); /* in */
97 case RTL8712_DMA_C2HCMD
:
98 pipe
= usb_rcvbulkpipe(pusbd
, 0x09); /* in */
100 case RTL8712_DMA_H2CCMD
:
101 pipe
= usb_sndbulkpipe(pusbd
, 0x0d);
104 } else if (pdvobj
->nr_endpoint
== 6) {
106 case RTL8712_DMA_BKQ
:
107 pipe
= usb_sndbulkpipe(pusbd
, 0x07);
109 case RTL8712_DMA_BEQ
:
110 pipe
= usb_sndbulkpipe(pusbd
, 0x06);
112 case RTL8712_DMA_VIQ
:
113 pipe
= usb_sndbulkpipe(pusbd
, 0x05);
115 case RTL8712_DMA_VOQ
:
116 pipe
= usb_sndbulkpipe(pusbd
, 0x04);
118 case RTL8712_DMA_RX0FF
:
119 case RTL8712_DMA_C2HCMD
:
120 pipe
= usb_rcvbulkpipe(pusbd
, 0x03); /* in */
122 case RTL8712_DMA_H2CCMD
:
123 case RTL8712_DMA_BCNQ
:
124 case RTL8712_DMA_BMCQ
:
125 case RTL8712_DMA_MGTQ
:
126 pipe
= usb_sndbulkpipe(pusbd
, 0x0d);
129 } else if (pdvobj
->nr_endpoint
== 4) {
131 case RTL8712_DMA_BEQ
:
132 pipe
= usb_sndbulkpipe(pusbd
, 0x06);
134 case RTL8712_DMA_VOQ
:
135 pipe
= usb_sndbulkpipe(pusbd
, 0x04);
137 case RTL8712_DMA_RX0FF
:
138 case RTL8712_DMA_C2HCMD
:
139 pipe
= usb_rcvbulkpipe(pusbd
, 0x03); /* in */
141 case RTL8712_DMA_H2CCMD
:
142 case RTL8712_DMA_BCNQ
:
143 case RTL8712_DMA_BMCQ
:
144 case RTL8712_DMA_MGTQ
:
145 pipe
= usb_sndbulkpipe(pusbd
, 0x0d);
153 static void usb_write_mem_complete(struct urb
*purb
)
155 struct io_queue
*pio_q
= (struct io_queue
*)purb
->context
;
156 struct intf_hdl
*pintf
= &(pio_q
->intf
);
157 struct intf_priv
*pintfpriv
= pintf
->pintfpriv
;
158 struct _adapter
*padapter
= (struct _adapter
*)pintf
->adapter
;
160 if (purb
->status
!= 0) {
161 if (purb
->status
== (-ESHUTDOWN
))
162 padapter
->bDriverStopped
= true;
164 padapter
->bSurpriseRemoved
= true;
166 up(&pintfpriv
->io_retevt
);
169 void r8712_usb_write_mem(struct intf_hdl
*pintfhdl
, u32 addr
, u32 cnt
, u8
*wmem
)
173 struct _adapter
*padapter
= (struct _adapter
*)pintfhdl
->adapter
;
174 struct intf_priv
*pintfpriv
= pintfhdl
->pintfpriv
;
175 struct io_queue
*pio_queue
= (struct io_queue
*)padapter
->pio_queue
;
176 struct dvobj_priv
*pdvobj
= (struct dvobj_priv
*)pintfpriv
->intf_dev
;
177 struct usb_device
*pusbd
= pdvobj
->pusbdev
;
178 struct urb
*piorw_urb
= pintfpriv
->piorw_urb
;
180 if ((padapter
->bDriverStopped
) || (padapter
->bSurpriseRemoved
) ||
181 (padapter
->pwrctrlpriv
.pnp_bstop_trx
))
183 /* translate DMA FIFO addr to pipehandle */
184 pipe
= ffaddr2pipehdl(pdvobj
, addr
);
187 usb_fill_bulk_urb(piorw_urb
, pusbd
, pipe
,
188 wmem
, cnt
, usb_write_mem_complete
,
190 status
= _usb_submit_urb(piorw_urb
, GFP_ATOMIC
);
191 _down_sema(&pintfpriv
->io_retevt
);
194 static void r8712_usb_read_port_complete(struct urb
*purb
)
197 struct recv_buf
*precvbuf
= (struct recv_buf
*)purb
->context
;
198 struct _adapter
*padapter
= (struct _adapter
*)precvbuf
->adapter
;
199 struct recv_priv
*precvpriv
= &padapter
->recvpriv
;
201 if (padapter
->bSurpriseRemoved
|| padapter
->bDriverStopped
)
203 if (purb
->status
== 0) { /* SUCCESS */
204 if ((purb
->actual_length
> (MAX_RECVBUF_SZ
)) ||
205 (purb
->actual_length
< RXDESC_SIZE
)) {
206 precvbuf
->reuse
= true;
207 r8712_read_port(padapter
, precvpriv
->ff_hwaddr
, 0,
208 (unsigned char *)precvbuf
);
210 precvbuf
->transfer_len
= purb
->actual_length
;
211 pbuf
= (uint
*)precvbuf
->pbuf
;
212 isevt
= le32_to_cpu(*(pbuf
+ 1)) & 0x1ff;
213 if ((isevt
& 0x1ff) == 0x1ff) {
214 r8712_rxcmd_event_hdl(padapter
, pbuf
);
215 precvbuf
->reuse
= true;
216 r8712_read_port(padapter
, precvpriv
->ff_hwaddr
,
217 0, (unsigned char *)precvbuf
);
219 _pkt
*pskb
= precvbuf
->pskb
;
220 skb_put(pskb
, purb
->actual_length
);
221 skb_queue_tail(&precvpriv
->rx_skb_queue
, pskb
);
222 tasklet_hi_schedule(&precvpriv
->recv_tasklet
);
223 precvbuf
->pskb
= NULL
;
224 precvbuf
->reuse
= false;
225 r8712_read_port(padapter
, precvpriv
->ff_hwaddr
,
226 0, (unsigned char *)precvbuf
);
230 switch (purb
->status
) {
236 padapter
->bDriverStopped
= true;
239 precvbuf
->reuse
= true;
240 r8712_read_port(padapter
, precvpriv
->ff_hwaddr
, 0,
241 (unsigned char *)precvbuf
);
244 printk(KERN_ERR
"r8712u: ERROR: URB IS IN"
253 u32
r8712_usb_read_port(struct intf_hdl
*pintfhdl
, u32 addr
, u32 cnt
, u8
*rmem
)
260 struct urb
*purb
= NULL
;
261 struct recv_buf
*precvbuf
= (struct recv_buf
*)rmem
;
262 struct intf_priv
*pintfpriv
= pintfhdl
->pintfpriv
;
263 struct dvobj_priv
*pdvobj
= (struct dvobj_priv
*)pintfpriv
->intf_dev
;
264 struct _adapter
*adapter
= (struct _adapter
*)pdvobj
->padapter
;
265 struct recv_priv
*precvpriv
= &adapter
->recvpriv
;
266 struct usb_device
*pusbd
= pdvobj
->pusbdev
;
268 if (adapter
->bDriverStopped
|| adapter
->bSurpriseRemoved
||
269 adapter
->pwrctrlpriv
.pnp_bstop_trx
)
271 if ((precvbuf
->reuse
== false) || (precvbuf
->pskb
== NULL
)) {
272 precvbuf
->pskb
= skb_dequeue(&precvpriv
->free_recv_skb_queue
);
273 if (NULL
!= precvbuf
->pskb
)
274 precvbuf
->reuse
= true;
276 if (precvbuf
!= NULL
) {
277 r8712_init_recvbuf(adapter
, precvbuf
);
278 /* re-assign for linux based on skb */
279 if ((precvbuf
->reuse
== false) || (precvbuf
->pskb
== NULL
)) {
280 precvbuf
->pskb
= netdev_alloc_skb(adapter
->pnetdev
,
281 MAX_RECVBUF_SZ
+ RECVBUFF_ALIGN_SZ
);
282 if (precvbuf
->pskb
== NULL
)
284 tmpaddr
= (addr_t
)precvbuf
->pskb
->data
;
285 alignment
= tmpaddr
& (RECVBUFF_ALIGN_SZ
-1);
286 skb_reserve(precvbuf
->pskb
,
287 (RECVBUFF_ALIGN_SZ
- alignment
));
288 precvbuf
->phead
= precvbuf
->pskb
->head
;
289 precvbuf
->pdata
= precvbuf
->pskb
->data
;
290 precvbuf
->ptail
= skb_tail_pointer(precvbuf
->pskb
);
291 precvbuf
->pend
= skb_end_pointer(precvbuf
->pskb
);
292 precvbuf
->pbuf
= precvbuf
->pskb
->data
;
293 } else { /* reuse skb */
294 precvbuf
->phead
= precvbuf
->pskb
->head
;
295 precvbuf
->pdata
= precvbuf
->pskb
->data
;
296 precvbuf
->ptail
= skb_tail_pointer(precvbuf
->pskb
);
297 precvbuf
->pend
= skb_end_pointer(precvbuf
->pskb
);
298 precvbuf
->pbuf
= precvbuf
->pskb
->data
;
299 precvbuf
->reuse
= false;
301 purb
= precvbuf
->purb
;
302 /* translate DMA FIFO addr to pipehandle */
303 pipe
= ffaddr2pipehdl(pdvobj
, addr
);
304 usb_fill_bulk_urb(purb
, pusbd
, pipe
,
305 precvbuf
->pbuf
, MAX_RECVBUF_SZ
,
306 r8712_usb_read_port_complete
,
308 err
= _usb_submit_urb(purb
, GFP_ATOMIC
);
309 if ((err
) && (err
!= (-EPERM
)))
316 void r8712_usb_read_port_cancel(struct _adapter
*padapter
)
319 struct recv_buf
*precvbuf
;
321 precvbuf
= (struct recv_buf
*)padapter
->recvpriv
.precv_buf
;
322 for (i
= 0; i
< NR_RECVBUFF
; i
++) {
324 usb_kill_urb(precvbuf
->purb
);
329 void r8712_xmit_bh(void *priv
)
332 struct _adapter
*padapter
= (struct _adapter
*)priv
;
333 struct xmit_priv
*pxmitpriv
= &padapter
->xmitpriv
;
336 if ((padapter
->bDriverStopped
== true) ||
337 (padapter
->bSurpriseRemoved
== true)) {
338 printk(KERN_ERR
"r8712u: xmit_bh => bDriverStopped"
339 " or bSurpriseRemoved\n");
342 ret
= r8712_xmitframe_complete(padapter
, pxmitpriv
, NULL
);
348 static void usb_write_port_complete(struct urb
*purb
)
351 struct xmit_frame
*pxmitframe
= (struct xmit_frame
*)purb
->context
;
352 struct xmit_buf
*pxmitbuf
= pxmitframe
->pxmitbuf
;
353 struct _adapter
*padapter
= pxmitframe
->padapter
;
354 struct xmit_priv
*pxmitpriv
= &padapter
->xmitpriv
;
355 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
357 switch (pattrib
->priority
) {
360 pxmitpriv
->bkq_cnt
--;
364 pxmitpriv
->viq_cnt
--;
368 pxmitpriv
->voq_cnt
--;
373 pxmitpriv
->beq_cnt
--;
376 pxmitpriv
->txirp_cnt
--;
377 for (i
= 0; i
< 8; i
++) {
378 if (purb
== pxmitframe
->pxmit_urb
[i
]) {
379 pxmitframe
->bpending
[i
] = false;
383 if (padapter
->bSurpriseRemoved
)
385 switch (purb
->status
) {
389 printk(KERN_WARNING
"r8712u: pipe error: (%d)\n", purb
->status
);
392 /* not to consider tx fragment */
393 r8712_free_xmitframe_ex(pxmitpriv
, pxmitframe
);
394 r8712_free_xmitbuf(pxmitpriv
, pxmitbuf
);
395 tasklet_hi_schedule(&pxmitpriv
->xmit_tasklet
);
398 u32
r8712_usb_write_port(struct intf_hdl
*pintfhdl
, u32 addr
, u32 cnt
, u8
*wmem
)
404 struct urb
*purb
= NULL
;
405 struct _adapter
*padapter
= (struct _adapter
*)pintfhdl
->adapter
;
406 struct dvobj_priv
*pdvobj
= (struct dvobj_priv
*)&padapter
->dvobjpriv
;
407 struct xmit_priv
*pxmitpriv
= &padapter
->xmitpriv
;
408 struct xmit_frame
*pxmitframe
= (struct xmit_frame
*)wmem
;
409 struct usb_device
*pusbd
= pdvobj
->pusbdev
;
410 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
412 if ((padapter
->bDriverStopped
) || (padapter
->bSurpriseRemoved
) ||
413 (padapter
->pwrctrlpriv
.pnp_bstop_trx
))
415 for (i
= 0; i
< 8; i
++) {
416 if (pxmitframe
->bpending
[i
] == false) {
417 spin_lock_irqsave(&pxmitpriv
->lock
, irqL
);
418 pxmitpriv
->txirp_cnt
++;
419 pxmitframe
->bpending
[i
] = true;
420 switch (pattrib
->priority
) {
423 pxmitpriv
->bkq_cnt
++;
427 pxmitpriv
->viq_cnt
++;
431 pxmitpriv
->voq_cnt
++;
436 pxmitpriv
->beq_cnt
++;
439 spin_unlock_irqrestore(&pxmitpriv
->lock
, irqL
);
440 pxmitframe
->sz
[i
] = (u16
)cnt
;
441 purb
= pxmitframe
->pxmit_urb
[i
];
446 if (pdvobj
->ishighspeed
) {
447 if (cnt
> 0 && cnt
% 512 == 0)
450 if (cnt
> 0 && cnt
% 64 == 0)
453 /* translate DMA FIFO addr to pipehandle */
454 pipe
= ffaddr2pipehdl(pdvobj
, addr
);
455 if (pxmitpriv
->free_xmitbuf_cnt
%NR_XMITBUFF
== 0)
456 purb
->transfer_flags
&= (~URB_NO_INTERRUPT
);
458 purb
->transfer_flags
|= URB_NO_INTERRUPT
;
461 usb_fill_bulk_urb(purb
, pusbd
, pipe
,
462 pxmitframe
->mem_addr
,
463 cnt
, usb_write_port_complete
,
464 pxmitframe
); /* context is xmit_frame */
465 status
= _usb_submit_urb(purb
, GFP_ATOMIC
);
473 void r8712_usb_write_port_cancel(struct _adapter
*padapter
)
476 struct xmit_buf
*pxmitbuf
= (struct xmit_buf
*)
477 padapter
->xmitpriv
.pxmitbuf
;
479 for (i
= 0; i
< NR_XMITBUFF
; i
++) {
480 for (j
= 0; j
< 8; j
++) {
481 if (pxmitbuf
->pxmit_urb
[j
])
482 usb_kill_urb(pxmitbuf
->pxmit_urb
[j
]);
488 int r8712_usbctrl_vendorreq(struct intf_priv
*pintfpriv
, u8 request
, u16 value
,
489 u16 index
, void *pdata
, u16 len
, u8 requesttype
)
494 struct dvobj_priv
*pdvobjpriv
= (struct dvobj_priv
*)
496 struct usb_device
*udev
= pdvobjpriv
->pusbdev
;
497 /* For mstar platform, mstar suggests the address for USB IO
498 * should be 16 bytes alignment. Trying to fix it here.
500 u8
*palloc_buf
, *pIo_buf
;
502 palloc_buf
= _malloc((u32
) len
+ 16);
503 if (palloc_buf
== NULL
) {
504 printk(KERN_ERR
"r8712u: [%s] Can't alloc memory for vendor"
505 " request\n", __func__
);
508 pIo_buf
= palloc_buf
+ 16 - ((addr_t
)(palloc_buf
) & 0x0f);
509 if (requesttype
== 0x01) {
510 pipe
= usb_rcvctrlpipe(udev
, 0); /* read_in */
511 reqtype
= RTL871X_VENQT_READ
;
513 pipe
= usb_sndctrlpipe(udev
, 0); /* write_out */
514 reqtype
= RTL871X_VENQT_WRITE
;
515 memcpy(pIo_buf
, pdata
, len
);
517 status
= usb_control_msg(udev
, pipe
, request
, reqtype
, value
, index
,
518 pIo_buf
, len
, HZ
/ 2);
519 if (status
> 0) { /* Success this control transfer. */
520 if (requesttype
== 0x01) {
521 /* For Control read transfer, we have to copy the read
522 * data from pIo_buf to pdata.
524 memcpy(pdata
, pIo_buf
, status
);