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);
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
)
172 struct _adapter
*padapter
= (struct _adapter
*)pintfhdl
->adapter
;
173 struct intf_priv
*pintfpriv
= pintfhdl
->pintfpriv
;
174 struct io_queue
*pio_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 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
;
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 netdev_err(padapter
->pnetdev
, "ERROR: URB IS IN PROGRESS!\n");
252 u32
r8712_usb_read_port(struct intf_hdl
*pintfhdl
, u32 addr
, u32 cnt
, u8
*rmem
)
259 struct urb
*purb
= NULL
;
260 struct recv_buf
*precvbuf
= (struct recv_buf
*)rmem
;
261 struct intf_priv
*pintfpriv
= pintfhdl
->pintfpriv
;
262 struct dvobj_priv
*pdvobj
= (struct dvobj_priv
*)pintfpriv
->intf_dev
;
263 struct _adapter
*adapter
= pdvobj
->padapter
;
264 struct recv_priv
*precvpriv
= &adapter
->recvpriv
;
265 struct usb_device
*pusbd
= pdvobj
->pusbdev
;
267 if (adapter
->bDriverStopped
|| adapter
->bSurpriseRemoved
||
268 adapter
->pwrctrlpriv
.pnp_bstop_trx
)
270 if (precvbuf
->reuse
|| !precvbuf
->pskb
) {
271 precvbuf
->pskb
= skb_dequeue(&precvpriv
->free_recv_skb_queue
);
272 if (precvbuf
->pskb
!= NULL
)
273 precvbuf
->reuse
= true;
275 if (precvbuf
!= NULL
) {
276 r8712_init_recvbuf(adapter
, precvbuf
);
277 /* re-assign for linux based on skb */
278 if (!precvbuf
->reuse
|| !precvbuf
->pskb
) {
279 precvbuf
->pskb
= netdev_alloc_skb(adapter
->pnetdev
,
280 MAX_RECVBUF_SZ
+ RECVBUFF_ALIGN_SZ
);
283 tmpaddr
= (addr_t
)precvbuf
->pskb
->data
;
284 alignment
= tmpaddr
& (RECVBUFF_ALIGN_SZ
- 1);
285 skb_reserve(precvbuf
->pskb
,
286 (RECVBUFF_ALIGN_SZ
- alignment
));
287 precvbuf
->phead
= precvbuf
->pskb
->head
;
288 precvbuf
->pdata
= precvbuf
->pskb
->data
;
289 precvbuf
->ptail
= skb_tail_pointer(precvbuf
->pskb
);
290 precvbuf
->pend
= skb_end_pointer(precvbuf
->pskb
);
291 precvbuf
->pbuf
= precvbuf
->pskb
->data
;
292 } else { /* reuse skb */
293 precvbuf
->phead
= precvbuf
->pskb
->head
;
294 precvbuf
->pdata
= precvbuf
->pskb
->data
;
295 precvbuf
->ptail
= skb_tail_pointer(precvbuf
->pskb
);
296 precvbuf
->pend
= skb_end_pointer(precvbuf
->pskb
);
297 precvbuf
->pbuf
= precvbuf
->pskb
->data
;
298 precvbuf
->reuse
= false;
300 purb
= precvbuf
->purb
;
301 /* translate DMA FIFO addr to pipehandle */
302 pipe
= ffaddr2pipehdl(pdvobj
, addr
);
303 usb_fill_bulk_urb(purb
, pusbd
, pipe
,
304 precvbuf
->pbuf
, MAX_RECVBUF_SZ
,
305 r8712_usb_read_port_complete
,
307 err
= usb_submit_urb(purb
, GFP_ATOMIC
);
308 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
;
335 if (padapter
->bDriverStopped
||
336 padapter
->bSurpriseRemoved
) {
337 netdev_err(padapter
->pnetdev
, "xmit_bh => bDriverStopped or bSurpriseRemoved\n");
340 ret
= r8712_xmitframe_complete(padapter
, pxmitpriv
, NULL
);
343 tasklet_hi_schedule(&pxmitpriv
->xmit_tasklet
);
346 static void usb_write_port_complete(struct urb
*purb
)
349 struct xmit_frame
*pxmitframe
= (struct xmit_frame
*)purb
->context
;
350 struct xmit_buf
*pxmitbuf
= pxmitframe
->pxmitbuf
;
351 struct _adapter
*padapter
= pxmitframe
->padapter
;
352 struct xmit_priv
*pxmitpriv
= &padapter
->xmitpriv
;
353 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
355 switch (pattrib
->priority
) {
358 pxmitpriv
->bkq_cnt
--;
362 pxmitpriv
->viq_cnt
--;
366 pxmitpriv
->voq_cnt
--;
371 pxmitpriv
->beq_cnt
--;
374 pxmitpriv
->txirp_cnt
--;
375 for (i
= 0; i
< 8; i
++) {
376 if (purb
== pxmitframe
->pxmit_urb
[i
]) {
377 pxmitframe
->bpending
[i
] = false;
381 if (padapter
->bSurpriseRemoved
)
383 switch (purb
->status
) {
387 netdev_warn(padapter
->pnetdev
,
388 "r8712u: pipe error: (%d)\n", purb
->status
);
391 /* not to consider tx fragment */
392 r8712_free_xmitframe_ex(pxmitpriv
, pxmitframe
);
393 r8712_free_xmitbuf(pxmitpriv
, pxmitbuf
);
394 tasklet_hi_schedule(&pxmitpriv
->xmit_tasklet
);
397 u32
r8712_usb_write_port(struct intf_hdl
*pintfhdl
, u32 addr
, u32 cnt
, u8
*wmem
)
403 struct urb
*purb
= NULL
;
404 struct _adapter
*padapter
= (struct _adapter
*)pintfhdl
->adapter
;
405 struct dvobj_priv
*pdvobj
= &padapter
->dvobjpriv
;
406 struct xmit_priv
*pxmitpriv
= &padapter
->xmitpriv
;
407 struct xmit_frame
*pxmitframe
= (struct xmit_frame
*)wmem
;
408 struct usb_device
*pusbd
= pdvobj
->pusbdev
;
409 struct pkt_attrib
*pattrib
= &pxmitframe
->attrib
;
411 if ((padapter
->bDriverStopped
) || (padapter
->bSurpriseRemoved
) ||
412 (padapter
->pwrctrlpriv
.pnp_bstop_trx
))
414 for (i
= 0; i
< 8; i
++) {
415 if (!pxmitframe
->bpending
[i
]) {
416 spin_lock_irqsave(&pxmitpriv
->lock
, irqL
);
417 pxmitpriv
->txirp_cnt
++;
418 pxmitframe
->bpending
[i
] = true;
419 switch (pattrib
->priority
) {
422 pxmitpriv
->bkq_cnt
++;
426 pxmitpriv
->viq_cnt
++;
430 pxmitpriv
->voq_cnt
++;
435 pxmitpriv
->beq_cnt
++;
438 spin_unlock_irqrestore(&pxmitpriv
->lock
, irqL
);
439 pxmitframe
->sz
[i
] = (u16
)cnt
;
440 purb
= pxmitframe
->pxmit_urb
[i
];
445 if (pdvobj
->ishighspeed
) {
446 if (cnt
> 0 && cnt
% 512 == 0)
449 if (cnt
> 0 && cnt
% 64 == 0)
452 /* translate DMA FIFO addr to pipehandle */
453 pipe
= ffaddr2pipehdl(pdvobj
, addr
);
454 if (pxmitpriv
->free_xmitbuf_cnt
% NR_XMITBUFF
== 0)
455 purb
->transfer_flags
&= (~URB_NO_INTERRUPT
);
457 purb
->transfer_flags
|= URB_NO_INTERRUPT
;
460 usb_fill_bulk_urb(purb
, pusbd
, pipe
,
461 pxmitframe
->mem_addr
,
462 cnt
, usb_write_port_complete
,
463 pxmitframe
); /* context is xmit_frame */
464 status
= usb_submit_urb(purb
, GFP_ATOMIC
);
472 void r8712_usb_write_port_cancel(struct _adapter
*padapter
)
475 struct xmit_buf
*pxmitbuf
= (struct xmit_buf
*)
476 padapter
->xmitpriv
.pxmitbuf
;
478 for (i
= 0; i
< NR_XMITBUFF
; i
++) {
479 for (j
= 0; j
< 8; j
++) {
480 if (pxmitbuf
->pxmit_urb
[j
])
481 usb_kill_urb(pxmitbuf
->pxmit_urb
[j
]);
487 int r8712_usbctrl_vendorreq(struct intf_priv
*pintfpriv
, u8 request
, u16 value
,
488 u16 index
, void *pdata
, u16 len
, u8 requesttype
)
493 struct dvobj_priv
*pdvobjpriv
= (struct dvobj_priv
*)
495 struct usb_device
*udev
= pdvobjpriv
->pusbdev
;
496 /* For mstar platform, mstar suggests the address for USB IO
497 * should be 16 bytes alignment. Trying to fix it here.
499 u8
*palloc_buf
, *pIo_buf
;
501 palloc_buf
= kmalloc((u32
)len
+ 16, GFP_ATOMIC
);
502 if (palloc_buf
== NULL
)
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
);