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
)
171 struct _adapter
*padapter
= (struct _adapter
*)pintfhdl
->adapter
;
172 struct intf_priv
*pintfpriv
= pintfhdl
->pintfpriv
;
173 struct io_queue
*pio_queue
= (struct io_queue
*)padapter
->pio_queue
;
174 struct dvobj_priv
*pdvobj
= (struct dvobj_priv
*)pintfpriv
->intf_dev
;
175 struct usb_device
*pusbd
= pdvobj
->pusbdev
;
176 struct urb
*piorw_urb
= pintfpriv
->piorw_urb
;
178 if ((padapter
->bDriverStopped
) || (padapter
->bSurpriseRemoved
) ||
179 (padapter
->pwrctrlpriv
.pnp_bstop_trx
))
181 /* translate DMA FIFO addr to pipehandle */
182 pipe
= ffaddr2pipehdl(pdvobj
, addr
);
185 usb_fill_bulk_urb(piorw_urb
, pusbd
, pipe
,
186 wmem
, cnt
, usb_write_mem_complete
,
188 usb_submit_urb(piorw_urb
, GFP_ATOMIC
);
189 _down_sema(&pintfpriv
->io_retevt
);
192 static void r8712_usb_read_port_complete(struct urb
*purb
)
195 struct recv_buf
*precvbuf
= (struct recv_buf
*)purb
->context
;
196 struct _adapter
*padapter
= (struct _adapter
*)precvbuf
->adapter
;
197 struct recv_priv
*precvpriv
= &padapter
->recvpriv
;
199 if (padapter
->bSurpriseRemoved
|| padapter
->bDriverStopped
)
201 if (purb
->status
== 0) { /* SUCCESS */
202 if ((purb
->actual_length
> (MAX_RECVBUF_SZ
)) ||
203 (purb
->actual_length
< RXDESC_SIZE
)) {
204 precvbuf
->reuse
= true;
205 r8712_read_port(padapter
, precvpriv
->ff_hwaddr
, 0,
206 (unsigned char *)precvbuf
);
208 precvbuf
->transfer_len
= purb
->actual_length
;
209 pbuf
= (uint
*)precvbuf
->pbuf
;
210 isevt
= le32_to_cpu(*(pbuf
+ 1)) & 0x1ff;
211 if ((isevt
& 0x1ff) == 0x1ff) {
212 r8712_rxcmd_event_hdl(padapter
, pbuf
);
213 precvbuf
->reuse
= true;
214 r8712_read_port(padapter
, precvpriv
->ff_hwaddr
,
215 0, (unsigned char *)precvbuf
);
217 _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
) {
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
|| !precvbuf
->pskb
) {
278 precvbuf
->pskb
= netdev_alloc_skb(adapter
->pnetdev
,
279 MAX_RECVBUF_SZ
+ RECVBUFF_ALIGN_SZ
);
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
,
386 "r8712u: pipe error: (%d)\n", purb
->status
);
389 /* not to consider tx fragment */
390 r8712_free_xmitframe_ex(pxmitpriv
, pxmitframe
);
391 r8712_free_xmitbuf(pxmitpriv
, pxmitbuf
);
392 tasklet_hi_schedule(&pxmitpriv
->xmit_tasklet
);
395 u32
r8712_usb_write_port(struct intf_hdl
*pintfhdl
, u32 addr
, u32 cnt
, u8
*wmem
)
401 struct urb
*purb
= NULL
;
402 struct _adapter
*padapter
= (struct _adapter
*)pintfhdl
->adapter
;
403 struct dvobj_priv
*pdvobj
= (struct dvobj_priv
*)&padapter
->dvobjpriv
;
404 struct xmit_priv
*pxmitpriv
= &padapter
->xmitpriv
;
405 struct xmit_frame
*pxmitframe
= (struct xmit_frame
*)wmem
;
406 struct usb_device
*pusbd
= pdvobj
->pusbdev
;
407 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
409 if ((padapter
->bDriverStopped
) || (padapter
->bSurpriseRemoved
) ||
410 (padapter
->pwrctrlpriv
.pnp_bstop_trx
))
412 for (i
= 0; i
< 8; i
++) {
413 if (pxmitframe
->bpending
[i
] == false) {
414 spin_lock_irqsave(&pxmitpriv
->lock
, irqL
);
415 pxmitpriv
->txirp_cnt
++;
416 pxmitframe
->bpending
[i
] = true;
417 switch (pattrib
->priority
) {
420 pxmitpriv
->bkq_cnt
++;
424 pxmitpriv
->viq_cnt
++;
428 pxmitpriv
->voq_cnt
++;
433 pxmitpriv
->beq_cnt
++;
436 spin_unlock_irqrestore(&pxmitpriv
->lock
, irqL
);
437 pxmitframe
->sz
[i
] = (u16
)cnt
;
438 purb
= pxmitframe
->pxmit_urb
[i
];
443 if (pdvobj
->ishighspeed
) {
444 if (cnt
> 0 && cnt
% 512 == 0)
447 if (cnt
> 0 && cnt
% 64 == 0)
450 /* translate DMA FIFO addr to pipehandle */
451 pipe
= ffaddr2pipehdl(pdvobj
, addr
);
452 if (pxmitpriv
->free_xmitbuf_cnt
%NR_XMITBUFF
== 0)
453 purb
->transfer_flags
&= (~URB_NO_INTERRUPT
);
455 purb
->transfer_flags
|= URB_NO_INTERRUPT
;
458 usb_fill_bulk_urb(purb
, pusbd
, pipe
,
459 pxmitframe
->mem_addr
,
460 cnt
, usb_write_port_complete
,
461 pxmitframe
); /* context is xmit_frame */
462 status
= usb_submit_urb(purb
, GFP_ATOMIC
);
470 void r8712_usb_write_port_cancel(struct _adapter
*padapter
)
473 struct xmit_buf
*pxmitbuf
= (struct xmit_buf
*)
474 padapter
->xmitpriv
.pxmitbuf
;
476 for (i
= 0; i
< NR_XMITBUFF
; i
++) {
477 for (j
= 0; j
< 8; j
++) {
478 if (pxmitbuf
->pxmit_urb
[j
])
479 usb_kill_urb(pxmitbuf
->pxmit_urb
[j
]);
485 int r8712_usbctrl_vendorreq(struct intf_priv
*pintfpriv
, u8 request
, u16 value
,
486 u16 index
, void *pdata
, u16 len
, u8 requesttype
)
491 struct dvobj_priv
*pdvobjpriv
= (struct dvobj_priv
*)
493 struct usb_device
*udev
= pdvobjpriv
->pusbdev
;
494 /* For mstar platform, mstar suggests the address for USB IO
495 * should be 16 bytes alignment. Trying to fix it here.
497 u8
*palloc_buf
, *pIo_buf
;
499 palloc_buf
= kmalloc((u32
)len
+ 16, GFP_ATOMIC
);
500 if (palloc_buf
== NULL
)
502 pIo_buf
= palloc_buf
+ 16 - ((addr_t
)(palloc_buf
) & 0x0f);
503 if (requesttype
== 0x01) {
504 pipe
= usb_rcvctrlpipe(udev
, 0); /* read_in */
505 reqtype
= RTL871X_VENQT_READ
;
507 pipe
= usb_sndctrlpipe(udev
, 0); /* write_out */
508 reqtype
= RTL871X_VENQT_WRITE
;
509 memcpy(pIo_buf
, pdata
, len
);
511 status
= usb_control_msg(udev
, pipe
, request
, reqtype
, value
, index
,
512 pIo_buf
, len
, HZ
/ 2);
513 if (status
> 0) { /* Success this control transfer. */
514 if (requesttype
== 0x01) {
515 /* For Control read transfer, we have to copy the read
516 * data from pIo_buf to pdata.
518 memcpy(pdata
, pIo_buf
, status
);