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 uint
r8712_usb_init_intf_priv(struct intf_priv
*pintfpriv
)
50 pintfpriv
->piorw_urb
= usb_alloc_urb(0, GFP_ATOMIC
);
51 if (!pintfpriv
->piorw_urb
)
53 sema_init(&(pintfpriv
->io_retevt
), 0);
57 void r8712_usb_unload_intf_priv(struct intf_priv
*pintfpriv
)
59 if (pintfpriv
->piorw_urb
) {
60 usb_kill_urb(pintfpriv
->piorw_urb
);
61 usb_free_urb(pintfpriv
->piorw_urb
);
65 static unsigned int ffaddr2pipehdl(struct dvobj_priv
*pdvobj
, u32 addr
)
67 unsigned int pipe
= 0;
68 struct usb_device
*pusbd
= pdvobj
->pusbdev
;
70 if (pdvobj
->nr_endpoint
== 11) {
73 pipe
= usb_sndbulkpipe(pusbd
, 0x07);
76 pipe
= usb_sndbulkpipe(pusbd
, 0x06);
79 pipe
= usb_sndbulkpipe(pusbd
, 0x05);
82 pipe
= usb_sndbulkpipe(pusbd
, 0x04);
84 case RTL8712_DMA_BCNQ
:
85 pipe
= usb_sndbulkpipe(pusbd
, 0x0a);
87 case RTL8712_DMA_BMCQ
: /* HI Queue */
88 pipe
= usb_sndbulkpipe(pusbd
, 0x0b);
90 case RTL8712_DMA_MGTQ
:
91 pipe
= usb_sndbulkpipe(pusbd
, 0x0c);
93 case RTL8712_DMA_RX0FF
:
94 pipe
= usb_rcvbulkpipe(pusbd
, 0x03); /* in */
96 case RTL8712_DMA_C2HCMD
:
97 pipe
= usb_rcvbulkpipe(pusbd
, 0x09); /* in */
99 case RTL8712_DMA_H2CCMD
:
100 pipe
= usb_sndbulkpipe(pusbd
, 0x0d);
103 } else if (pdvobj
->nr_endpoint
== 6) {
105 case RTL8712_DMA_BKQ
:
106 pipe
= usb_sndbulkpipe(pusbd
, 0x07);
108 case RTL8712_DMA_BEQ
:
109 pipe
= usb_sndbulkpipe(pusbd
, 0x06);
111 case RTL8712_DMA_VIQ
:
112 pipe
= usb_sndbulkpipe(pusbd
, 0x05);
114 case RTL8712_DMA_VOQ
:
115 pipe
= usb_sndbulkpipe(pusbd
, 0x04);
117 case RTL8712_DMA_RX0FF
:
118 case RTL8712_DMA_C2HCMD
:
119 pipe
= usb_rcvbulkpipe(pusbd
, 0x03); /* in */
121 case RTL8712_DMA_H2CCMD
:
122 case RTL8712_DMA_BCNQ
:
123 case RTL8712_DMA_BMCQ
:
124 case RTL8712_DMA_MGTQ
:
125 pipe
= usb_sndbulkpipe(pusbd
, 0x0d);
128 } else if (pdvobj
->nr_endpoint
== 4) {
130 case RTL8712_DMA_BEQ
:
131 pipe
= usb_sndbulkpipe(pusbd
, 0x06);
133 case RTL8712_DMA_VOQ
:
134 pipe
= usb_sndbulkpipe(pusbd
, 0x04);
136 case RTL8712_DMA_RX0FF
:
137 case RTL8712_DMA_C2HCMD
:
138 pipe
= usb_rcvbulkpipe(pusbd
, 0x03); /* in */
140 case RTL8712_DMA_H2CCMD
:
141 case RTL8712_DMA_BCNQ
:
142 case RTL8712_DMA_BMCQ
:
143 case RTL8712_DMA_MGTQ
:
144 pipe
= usb_sndbulkpipe(pusbd
, 0x0d);
152 static void usb_write_mem_complete(struct urb
*purb
)
154 struct io_queue
*pio_q
= (struct io_queue
*)purb
->context
;
155 struct intf_hdl
*pintf
= &(pio_q
->intf
);
156 struct intf_priv
*pintfpriv
= pintf
->pintfpriv
;
157 struct _adapter
*padapter
= (struct _adapter
*)pintf
->adapter
;
159 if (purb
->status
!= 0) {
160 if (purb
->status
== (-ESHUTDOWN
))
161 padapter
->bDriverStopped
= true;
163 padapter
->bSurpriseRemoved
= true;
165 up(&pintfpriv
->io_retevt
);
168 void r8712_usb_write_mem(struct intf_hdl
*pintfhdl
, u32 addr
, u32 cnt
, u8
*wmem
)
172 struct _adapter
*padapter
= (struct _adapter
*)pintfhdl
->adapter
;
173 struct intf_priv
*pintfpriv
= pintfhdl
->pintfpriv
;
174 struct io_queue
*pio_queue
= (struct io_queue
*)padapter
->pio_queue
;
175 struct dvobj_priv
*pdvobj
= (struct dvobj_priv
*)pintfpriv
->intf_dev
;
176 struct usb_device
*pusbd
= pdvobj
->pusbdev
;
177 struct urb
*piorw_urb
= pintfpriv
->piorw_urb
;
179 if ((padapter
->bDriverStopped
) || (padapter
->bSurpriseRemoved
) ||
180 (padapter
->pwrctrlpriv
.pnp_bstop_trx
))
182 /* translate DMA FIFO addr to pipehandle */
183 pipe
= ffaddr2pipehdl(pdvobj
, addr
);
186 usb_fill_bulk_urb(piorw_urb
, pusbd
, pipe
,
187 wmem
, cnt
, usb_write_mem_complete
,
189 status
= usb_submit_urb(piorw_urb
, GFP_ATOMIC
);
190 _down_sema(&pintfpriv
->io_retevt
);
193 static void r8712_usb_read_port_complete(struct urb
*purb
)
196 struct recv_buf
*precvbuf
= (struct recv_buf
*)purb
->context
;
197 struct _adapter
*padapter
= (struct _adapter
*)precvbuf
->adapter
;
198 struct recv_priv
*precvpriv
= &padapter
->recvpriv
;
200 if (padapter
->bSurpriseRemoved
|| padapter
->bDriverStopped
)
202 if (purb
->status
== 0) { /* SUCCESS */
203 if ((purb
->actual_length
> (MAX_RECVBUF_SZ
)) ||
204 (purb
->actual_length
< RXDESC_SIZE
)) {
205 precvbuf
->reuse
= true;
206 r8712_read_port(padapter
, precvpriv
->ff_hwaddr
, 0,
207 (unsigned char *)precvbuf
);
209 precvbuf
->transfer_len
= purb
->actual_length
;
210 pbuf
= (uint
*)precvbuf
->pbuf
;
211 isevt
= le32_to_cpu(*(pbuf
+ 1)) & 0x1ff;
212 if ((isevt
& 0x1ff) == 0x1ff) {
213 r8712_rxcmd_event_hdl(padapter
, pbuf
);
214 precvbuf
->reuse
= true;
215 r8712_read_port(padapter
, precvpriv
->ff_hwaddr
,
216 0, (unsigned char *)precvbuf
);
218 _pkt
*pskb
= precvbuf
->pskb
;
219 skb_put(pskb
, purb
->actual_length
);
220 skb_queue_tail(&precvpriv
->rx_skb_queue
, pskb
);
221 tasklet_hi_schedule(&precvpriv
->recv_tasklet
);
222 precvbuf
->pskb
= NULL
;
223 precvbuf
->reuse
= false;
224 r8712_read_port(padapter
, precvpriv
->ff_hwaddr
,
225 0, (unsigned char *)precvbuf
);
229 switch (purb
->status
) {
235 padapter
->bDriverStopped
= true;
238 precvbuf
->reuse
= true;
239 r8712_read_port(padapter
, precvpriv
->ff_hwaddr
, 0,
240 (unsigned char *)precvbuf
);
243 netdev_err(padapter
->pnetdev
, "ERROR: URB IS IN PROGRESS!\n");
251 u32
r8712_usb_read_port(struct intf_hdl
*pintfhdl
, u32 addr
, u32 cnt
, u8
*rmem
)
258 struct urb
*purb
= NULL
;
259 struct recv_buf
*precvbuf
= (struct recv_buf
*)rmem
;
260 struct intf_priv
*pintfpriv
= pintfhdl
->pintfpriv
;
261 struct dvobj_priv
*pdvobj
= (struct dvobj_priv
*)pintfpriv
->intf_dev
;
262 struct _adapter
*adapter
= (struct _adapter
*)pdvobj
->padapter
;
263 struct recv_priv
*precvpriv
= &adapter
->recvpriv
;
264 struct usb_device
*pusbd
= pdvobj
->pusbdev
;
266 if (adapter
->bDriverStopped
|| adapter
->bSurpriseRemoved
||
267 adapter
->pwrctrlpriv
.pnp_bstop_trx
)
269 if ((precvbuf
->reuse
== false) || (precvbuf
->pskb
== NULL
)) {
270 precvbuf
->pskb
= skb_dequeue(&precvpriv
->free_recv_skb_queue
);
271 if (NULL
!= precvbuf
->pskb
)
272 precvbuf
->reuse
= true;
274 if (precvbuf
!= NULL
) {
275 r8712_init_recvbuf(adapter
, precvbuf
);
276 /* re-assign for linux based on skb */
277 if ((precvbuf
->reuse
== false) || (precvbuf
->pskb
== NULL
)) {
278 precvbuf
->pskb
= netdev_alloc_skb(adapter
->pnetdev
,
279 MAX_RECVBUF_SZ
+ RECVBUFF_ALIGN_SZ
);
280 if (precvbuf
->pskb
== NULL
)
282 tmpaddr
= (addr_t
)precvbuf
->pskb
->data
;
283 alignment
= tmpaddr
& (RECVBUFF_ALIGN_SZ
-1);
284 skb_reserve(precvbuf
->pskb
,
285 (RECVBUFF_ALIGN_SZ
- alignment
));
286 precvbuf
->phead
= precvbuf
->pskb
->head
;
287 precvbuf
->pdata
= precvbuf
->pskb
->data
;
288 precvbuf
->ptail
= skb_tail_pointer(precvbuf
->pskb
);
289 precvbuf
->pend
= skb_end_pointer(precvbuf
->pskb
);
290 precvbuf
->pbuf
= precvbuf
->pskb
->data
;
291 } else { /* reuse skb */
292 precvbuf
->phead
= precvbuf
->pskb
->head
;
293 precvbuf
->pdata
= precvbuf
->pskb
->data
;
294 precvbuf
->ptail
= skb_tail_pointer(precvbuf
->pskb
);
295 precvbuf
->pend
= skb_end_pointer(precvbuf
->pskb
);
296 precvbuf
->pbuf
= precvbuf
->pskb
->data
;
297 precvbuf
->reuse
= false;
299 purb
= precvbuf
->purb
;
300 /* translate DMA FIFO addr to pipehandle */
301 pipe
= ffaddr2pipehdl(pdvobj
, addr
);
302 usb_fill_bulk_urb(purb
, pusbd
, pipe
,
303 precvbuf
->pbuf
, MAX_RECVBUF_SZ
,
304 r8712_usb_read_port_complete
,
306 err
= usb_submit_urb(purb
, GFP_ATOMIC
);
307 if ((err
) && (err
!= (-EPERM
)))
314 void r8712_usb_read_port_cancel(struct _adapter
*padapter
)
317 struct recv_buf
*precvbuf
;
319 precvbuf
= (struct recv_buf
*)padapter
->recvpriv
.precv_buf
;
320 for (i
= 0; i
< NR_RECVBUFF
; i
++) {
322 usb_kill_urb(precvbuf
->purb
);
327 void r8712_xmit_bh(void *priv
)
330 struct _adapter
*padapter
= (struct _adapter
*)priv
;
331 struct xmit_priv
*pxmitpriv
= &padapter
->xmitpriv
;
333 if ((padapter
->bDriverStopped
== true) ||
334 (padapter
->bSurpriseRemoved
== true)) {
335 netdev_err(padapter
->pnetdev
, "xmit_bh => bDriverStopped or bSurpriseRemoved\n");
338 ret
= r8712_xmitframe_complete(padapter
, pxmitpriv
, NULL
);
341 tasklet_hi_schedule(&pxmitpriv
->xmit_tasklet
);
344 static void usb_write_port_complete(struct urb
*purb
)
347 struct xmit_frame
*pxmitframe
= (struct xmit_frame
*)purb
->context
;
348 struct xmit_buf
*pxmitbuf
= pxmitframe
->pxmitbuf
;
349 struct _adapter
*padapter
= pxmitframe
->padapter
;
350 struct xmit_priv
*pxmitpriv
= &padapter
->xmitpriv
;
351 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
353 switch (pattrib
->priority
) {
356 pxmitpriv
->bkq_cnt
--;
360 pxmitpriv
->viq_cnt
--;
364 pxmitpriv
->voq_cnt
--;
369 pxmitpriv
->beq_cnt
--;
372 pxmitpriv
->txirp_cnt
--;
373 for (i
= 0; i
< 8; i
++) {
374 if (purb
== pxmitframe
->pxmit_urb
[i
]) {
375 pxmitframe
->bpending
[i
] = false;
379 if (padapter
->bSurpriseRemoved
)
381 switch (purb
->status
) {
385 netdev_warn(padapter
->pnetdev
, "r8712u: pipe error: (%d)\n", purb
->status
);
388 /* not to consider tx fragment */
389 r8712_free_xmitframe_ex(pxmitpriv
, pxmitframe
);
390 r8712_free_xmitbuf(pxmitpriv
, pxmitbuf
);
391 tasklet_hi_schedule(&pxmitpriv
->xmit_tasklet
);
394 u32
r8712_usb_write_port(struct intf_hdl
*pintfhdl
, u32 addr
, u32 cnt
, u8
*wmem
)
400 struct urb
*purb
= NULL
;
401 struct _adapter
*padapter
= (struct _adapter
*)pintfhdl
->adapter
;
402 struct dvobj_priv
*pdvobj
= (struct dvobj_priv
*)&padapter
->dvobjpriv
;
403 struct xmit_priv
*pxmitpriv
= &padapter
->xmitpriv
;
404 struct xmit_frame
*pxmitframe
= (struct xmit_frame
*)wmem
;
405 struct usb_device
*pusbd
= pdvobj
->pusbdev
;
406 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
408 if ((padapter
->bDriverStopped
) || (padapter
->bSurpriseRemoved
) ||
409 (padapter
->pwrctrlpriv
.pnp_bstop_trx
))
411 for (i
= 0; i
< 8; i
++) {
412 if (pxmitframe
->bpending
[i
] == false) {
413 spin_lock_irqsave(&pxmitpriv
->lock
, irqL
);
414 pxmitpriv
->txirp_cnt
++;
415 pxmitframe
->bpending
[i
] = true;
416 switch (pattrib
->priority
) {
419 pxmitpriv
->bkq_cnt
++;
423 pxmitpriv
->viq_cnt
++;
427 pxmitpriv
->voq_cnt
++;
432 pxmitpriv
->beq_cnt
++;
435 spin_unlock_irqrestore(&pxmitpriv
->lock
, irqL
);
436 pxmitframe
->sz
[i
] = (u16
)cnt
;
437 purb
= pxmitframe
->pxmit_urb
[i
];
442 if (pdvobj
->ishighspeed
) {
443 if (cnt
> 0 && cnt
% 512 == 0)
446 if (cnt
> 0 && cnt
% 64 == 0)
449 /* translate DMA FIFO addr to pipehandle */
450 pipe
= ffaddr2pipehdl(pdvobj
, addr
);
451 if (pxmitpriv
->free_xmitbuf_cnt
%NR_XMITBUFF
== 0)
452 purb
->transfer_flags
&= (~URB_NO_INTERRUPT
);
454 purb
->transfer_flags
|= URB_NO_INTERRUPT
;
457 usb_fill_bulk_urb(purb
, pusbd
, pipe
,
458 pxmitframe
->mem_addr
,
459 cnt
, usb_write_port_complete
,
460 pxmitframe
); /* context is xmit_frame */
461 status
= usb_submit_urb(purb
, GFP_ATOMIC
);
469 void r8712_usb_write_port_cancel(struct _adapter
*padapter
)
472 struct xmit_buf
*pxmitbuf
= (struct xmit_buf
*)
473 padapter
->xmitpriv
.pxmitbuf
;
475 for (i
= 0; i
< NR_XMITBUFF
; i
++) {
476 for (j
= 0; j
< 8; j
++) {
477 if (pxmitbuf
->pxmit_urb
[j
])
478 usb_kill_urb(pxmitbuf
->pxmit_urb
[j
]);
484 int r8712_usbctrl_vendorreq(struct intf_priv
*pintfpriv
, u8 request
, u16 value
,
485 u16 index
, void *pdata
, u16 len
, u8 requesttype
)
490 struct dvobj_priv
*pdvobjpriv
= (struct dvobj_priv
*)
492 struct usb_device
*udev
= pdvobjpriv
->pusbdev
;
493 /* For mstar platform, mstar suggests the address for USB IO
494 * should be 16 bytes alignment. Trying to fix it here.
496 u8
*palloc_buf
, *pIo_buf
;
498 palloc_buf
= kmalloc((u32
)len
+ 16, GFP_ATOMIC
);
499 if (palloc_buf
== NULL
) {
500 dev_err(&udev
->dev
, "%s: Can't alloc memory for vendor request\n",
504 pIo_buf
= palloc_buf
+ 16 - ((addr_t
)(palloc_buf
) & 0x0f);
505 if (requesttype
== 0x01) {
506 pipe
= usb_rcvctrlpipe(udev
, 0); /* read_in */
507 reqtype
= RTL871X_VENQT_READ
;
509 pipe
= usb_sndctrlpipe(udev
, 0); /* write_out */
510 reqtype
= RTL871X_VENQT_WRITE
;
511 memcpy(pIo_buf
, pdata
, len
);
513 status
= usb_control_msg(udev
, pipe
, request
, reqtype
, value
, index
,
514 pIo_buf
, len
, HZ
/ 2);
515 if (status
> 0) { /* Success this control transfer. */
516 if (requesttype
== 0x01) {
517 /* For Control read transfer, we have to copy the read
518 * data from pIo_buf to pdata.
520 memcpy(pdata
, pIo_buf
, status
);