blob: fd8776c1a1073cd089f99814dd907c67f1fbb7e1 [file] [log] [blame]
Forest Bond92b96792009-06-13 07:38:31 -04001/*
2 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
3 * All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 *
20 * File: usbpipe.c
21 *
22 * Purpose: Handle USB control endpoint
23 *
24 * Author: Warren Hsu
25 *
26 * Date: Mar. 29, 2005
27 *
28 * Functions:
Malcolm Priestley1390b022014-05-26 13:59:01 +010029 * vnt_control_out - Write variable length bytes to MEM/BB/MAC/EEPROM
Malcolm Priestley441c21c2014-05-26 13:59:02 +010030 * vnt_control_in - Read variable length bytes from MEM/BB/MAC/EEPROM
Malcolm Priestley285d58c2014-05-26 13:59:03 +010031 * vnt_control_out_u8 - Write one byte to MEM/BB/MAC/EEPROM
Malcolm Priestley53742902014-05-26 13:59:06 +010032 * vnt_control_in_u8 - Read one byte from MEM/BB/MAC/EEPROM
Forest Bond92b96792009-06-13 07:38:31 -040033 * ControlvMaskByte - Read one byte from MEM/BB/MAC/EEPROM and clear/set some bits in the same address
34 *
35 * Revision History:
36 * 04-05-2004 Jerry Chen: Initial release
37 * 11-24-2004 Warren Hsu: Add ControlvWriteByte,ControlvReadByte,ControlvMaskByte
38 *
39 */
40
Forest Bond92b96792009-06-13 07:38:31 -040041#include "int.h"
Forest Bond92b96792009-06-13 07:38:31 -040042#include "rxtx.h"
Forest Bond92b96792009-06-13 07:38:31 -040043#include "dpc.h"
Forest Bond92b96792009-06-13 07:38:31 -040044#include "desc.h"
Forest Bond92b96792009-06-13 07:38:31 -040045#include "device.h"
Malcolm Priestley62c85262014-05-26 13:59:07 +010046#include "usbpipe.h"
Forest Bond92b96792009-06-13 07:38:31 -040047
Forest Bond92b96792009-06-13 07:38:31 -040048//endpoint def
49//endpoint 0: control
50//endpoint 1: interrupt
51//endpoint 2: read bulk
52//endpoint 3: write bulk
53
Forest Bond92b96792009-06-13 07:38:31 -040054#define USB_CTL_WAIT 500 //ms
55
56#ifndef URB_ASYNC_UNLINK
57#define URB_ASYNC_UNLINK 0
58#endif
59
Malcolm Priestleyfe5d00e2012-12-10 22:14:36 +000060static void s_nsInterruptUsbIoCompleteRead(struct urb *urb);
61static void s_nsBulkInUsbIoCompleteRead(struct urb *urb);
62static void s_nsBulkOutIoCompleteWrite(struct urb *urb);
Forest Bond92b96792009-06-13 07:38:31 -040063
Malcolm Priestley1390b022014-05-26 13:59:01 +010064int vnt_control_out(struct vnt_private *priv, u8 request, u16 value,
Malcolm Priestley0f06a732014-05-17 09:50:21 +010065 u16 index, u16 length, u8 *buffer)
Forest Bond92b96792009-06-13 07:38:31 -040066{
Malcolm Priestley0f06a732014-05-17 09:50:21 +010067 int status = 0;
Forest Bond92b96792009-06-13 07:38:31 -040068
Malcolm Priestley0f06a732014-05-17 09:50:21 +010069 if (priv->Flags & fMP_DISCONNECTED)
Malcolm Priestleye1feda12013-10-14 19:44:13 +010070 return STATUS_FAILURE;
71
Malcolm Priestley0f06a732014-05-17 09:50:21 +010072 mutex_lock(&priv->usb_lock);
Malcolm Priestleyc91b1862014-05-15 22:49:19 +010073
Malcolm Priestley0f06a732014-05-17 09:50:21 +010074 status = usb_control_msg(priv->usb,
75 usb_sndctrlpipe(priv->usb, 0), request, 0x40, value,
76 index, buffer, length, USB_CTL_WAIT);
Forest Bond92b96792009-06-13 07:38:31 -040077
Malcolm Priestley0f06a732014-05-17 09:50:21 +010078 mutex_unlock(&priv->usb_lock);
Malcolm Priestleyc91b1862014-05-15 22:49:19 +010079
Malcolm Priestley0f06a732014-05-17 09:50:21 +010080 if (status < (int)length)
Malcolm Priestley7021b682014-05-15 22:49:22 +010081 return STATUS_FAILURE;
82
83 return STATUS_SUCCESS;
Forest Bond92b96792009-06-13 07:38:31 -040084}
85
Malcolm Priestley285d58c2014-05-26 13:59:03 +010086void vnt_control_out_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 data)
87{
88 vnt_control_out(priv, MESSAGE_TYPE_WRITE,
89 reg_off, reg, sizeof(u8), &data);
90}
91
Malcolm Priestley441c21c2014-05-26 13:59:02 +010092int vnt_control_in(struct vnt_private *priv, u8 request, u16 value,
Malcolm Priestley9af49fd2014-05-17 09:50:22 +010093 u16 index, u16 length, u8 *buffer)
Forest Bond92b96792009-06-13 07:38:31 -040094{
Malcolm Priestley9af49fd2014-05-17 09:50:22 +010095 int status;
Forest Bond92b96792009-06-13 07:38:31 -040096
Malcolm Priestley9af49fd2014-05-17 09:50:22 +010097 if (priv->Flags & fMP_DISCONNECTED)
Malcolm Priestleye1feda12013-10-14 19:44:13 +010098 return STATUS_FAILURE;
99
Malcolm Priestley9af49fd2014-05-17 09:50:22 +0100100 mutex_lock(&priv->usb_lock);
Malcolm Priestleyc91b1862014-05-15 22:49:19 +0100101
Malcolm Priestley9af49fd2014-05-17 09:50:22 +0100102 status = usb_control_msg(priv->usb,
103 usb_rcvctrlpipe(priv->usb, 0), request, 0xc0, value,
104 index, buffer, length, USB_CTL_WAIT);
Forest Bond92b96792009-06-13 07:38:31 -0400105
Malcolm Priestley9af49fd2014-05-17 09:50:22 +0100106 mutex_unlock(&priv->usb_lock);
Malcolm Priestleyc91b1862014-05-15 22:49:19 +0100107
Malcolm Priestley9af49fd2014-05-17 09:50:22 +0100108 if (status < (int)length)
Malcolm Priestley0fb2af32014-05-15 22:49:23 +0100109 return STATUS_FAILURE;
Forest Bond92b96792009-06-13 07:38:31 -0400110
Malcolm Priestley0fb2af32014-05-15 22:49:23 +0100111 return STATUS_SUCCESS;
Forest Bond92b96792009-06-13 07:38:31 -0400112}
113
Malcolm Priestley53742902014-05-26 13:59:06 +0100114void vnt_control_in_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 *data)
115{
116 vnt_control_in(priv, MESSAGE_TYPE_READ,
117 reg_off, reg, sizeof(u8), data);
118}
119
Forest Bond92b96792009-06-13 07:38:31 -0400120/*
121 * Description:
122 * Allocates an usb interrupt in irp and calls USBD.
123 *
124 * Parameters:
125 * In:
126 * pDevice - Pointer to the adapter
127 * Out:
128 * none
129 *
130 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
131 *
132 */
Malcolm Priestleyfe5d00e2012-12-10 22:14:36 +0000133
Malcolm Priestley5f38b782014-02-19 18:37:32 +0000134int PIPEnsInterruptRead(struct vnt_private *priv)
Forest Bond92b96792009-06-13 07:38:31 -0400135{
Malcolm Priestley5f38b782014-02-19 18:37:32 +0000136 int status = STATUS_FAILURE;
Forest Bond92b96792009-06-13 07:38:31 -0400137
Malcolm Priestleyf764e002014-02-19 18:39:09 +0000138 if (priv->int_buf.in_use == true)
Malcolm Priestley5f38b782014-02-19 18:37:32 +0000139 return STATUS_FAILURE;
Forest Bond92b96792009-06-13 07:38:31 -0400140
Malcolm Priestleyf764e002014-02-19 18:39:09 +0000141 priv->int_buf.in_use = true;
Forest Bond92b96792009-06-13 07:38:31 -0400142
Malcolm Priestley5f38b782014-02-19 18:37:32 +0000143 usb_fill_int_urb(priv->pInterruptURB,
144 priv->usb,
Malcolm Priestleyb9d93d12014-03-16 12:34:11 +0000145 usb_rcvintpipe(priv->usb, 1),
Malcolm Priestleyf764e002014-02-19 18:39:09 +0000146 priv->int_buf.data_buf,
Forest Bond92b96792009-06-13 07:38:31 -0400147 MAX_INTERRUPT_SIZE,
148 s_nsInterruptUsbIoCompleteRead,
Malcolm Priestley5f38b782014-02-19 18:37:32 +0000149 priv,
150 priv->int_interval);
Forest Bond92b96792009-06-13 07:38:31 -0400151
Malcolm Priestley5f38b782014-02-19 18:37:32 +0000152 status = usb_submit_urb(priv->pInterruptURB, GFP_ATOMIC);
153 if (status) {
Malcolm Priestley8a660262014-05-17 09:50:20 +0100154 dev_dbg(&priv->usb->dev, "Submit int URB failed %d\n", status);
Malcolm Priestleyf764e002014-02-19 18:39:09 +0000155 priv->int_buf.in_use = false;
Malcolm Priestley59858f52014-02-19 18:36:37 +0000156 }
Forest Bond92b96792009-06-13 07:38:31 -0400157
Malcolm Priestley5f38b782014-02-19 18:37:32 +0000158 return status;
Forest Bond92b96792009-06-13 07:38:31 -0400159}
160
Forest Bond92b96792009-06-13 07:38:31 -0400161/*
162 * Description:
163 * Complete function of usb interrupt in irp.
164 *
165 * Parameters:
166 * In:
167 * pDevice - Pointer to the adapter
168 *
169 * Out:
170 * none
171 *
172 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
173 *
174 */
Forest Bond92b96792009-06-13 07:38:31 -0400175
Malcolm Priestleyfe5d00e2012-12-10 22:14:36 +0000176static void s_nsInterruptUsbIoCompleteRead(struct urb *urb)
Forest Bond92b96792009-06-13 07:38:31 -0400177{
Malcolm Priestley599e4b52014-02-25 20:51:51 +0000178 struct vnt_private *priv = urb->context;
Malcolm Priestleyd9ad7a92014-02-17 21:27:30 +0000179 int status;
Forest Bond92b96792009-06-13 07:38:31 -0400180
Malcolm Priestleyc98fbf92014-02-17 21:16:20 +0000181 switch (urb->status) {
182 case 0:
183 case -ETIMEDOUT:
184 break;
185 case -ECONNRESET:
186 case -ENOENT:
187 case -ESHUTDOWN:
Malcolm Priestleyf764e002014-02-19 18:39:09 +0000188 priv->int_buf.in_use = false;
Malcolm Priestleyc98fbf92014-02-17 21:16:20 +0000189 return;
190 default:
191 break;
192 }
193
Malcolm Priestleyd9ad7a92014-02-17 21:27:30 +0000194 status = urb->status;
Forest Bond92b96792009-06-13 07:38:31 -0400195
Malcolm Priestleyd9ad7a92014-02-17 21:27:30 +0000196 if (status != STATUS_SUCCESS) {
Malcolm Priestleyf764e002014-02-19 18:39:09 +0000197 priv->int_buf.in_use = false;
Forest Bond92b96792009-06-13 07:38:31 -0400198
Malcolm Priestley8a660262014-05-17 09:50:20 +0100199 dev_dbg(&priv->usb->dev, "%s status = %d\n", __func__, status);
Malcolm Priestley247b4b62014-02-17 21:12:51 +0000200 } else {
Malcolm Priestleyd9ad7a92014-02-17 21:27:30 +0000201 INTnsProcessData(priv);
Malcolm Priestley247b4b62014-02-17 21:12:51 +0000202 }
Malcolm Priestley749627f2014-02-17 21:24:33 +0000203
Malcolm Priestleyd9ad7a92014-02-17 21:27:30 +0000204 status = usb_submit_urb(priv->pInterruptURB, GFP_ATOMIC);
205 if (status) {
Malcolm Priestley8a660262014-05-17 09:50:20 +0100206 dev_dbg(&priv->usb->dev, "Submit int URB failed %d\n", status);
Malcolm Priestleyd9ad7a92014-02-17 21:27:30 +0000207 } else {
Malcolm Priestleyf764e002014-02-19 18:39:09 +0000208 priv->int_buf.in_use = true;
Malcolm Priestleyd9ad7a92014-02-17 21:27:30 +0000209 }
210
211 return;
Forest Bond92b96792009-06-13 07:38:31 -0400212}
213
214/*
215 * Description:
216 * Allocates an usb BulkIn irp and calls USBD.
217 *
218 * Parameters:
219 * In:
220 * pDevice - Pointer to the adapter
221 * Out:
222 * none
223 *
224 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
225 *
226 */
Malcolm Priestleyfe5d00e2012-12-10 22:14:36 +0000227
Malcolm Priestley0b787d72014-02-25 20:51:50 +0000228int PIPEnsBulkInUsbRead(struct vnt_private *priv, struct vnt_rcb *rcb)
Forest Bond92b96792009-06-13 07:38:31 -0400229{
Malcolm Priestley0b787d72014-02-25 20:51:50 +0000230 int status = 0;
231 struct urb *urb;
Forest Bond92b96792009-06-13 07:38:31 -0400232
Malcolm Priestley0b787d72014-02-25 20:51:50 +0000233 if (priv->Flags & fMP_DISCONNECTED)
234 return STATUS_FAILURE;
Forest Bond92b96792009-06-13 07:38:31 -0400235
Malcolm Priestley0b787d72014-02-25 20:51:50 +0000236 urb = rcb->pUrb;
237 if (rcb->skb == NULL) {
Malcolm Priestley8a660262014-05-17 09:50:20 +0100238 dev_dbg(&priv->usb->dev, "rcb->skb is null\n");
Malcolm Priestley0b787d72014-02-25 20:51:50 +0000239 return status;
240 }
Forest Bond92b96792009-06-13 07:38:31 -0400241
Malcolm Priestley0b787d72014-02-25 20:51:50 +0000242 usb_fill_bulk_urb(urb,
243 priv->usb,
244 usb_rcvbulkpipe(priv->usb, 2),
Malcolm Priestley63b99072014-06-25 21:14:22 +0100245 skb_put(rcb->skb, skb_tailroom(rcb->skb)),
Forest Bond92b96792009-06-13 07:38:31 -0400246 MAX_TOTAL_SIZE_WITH_ALL_HEADERS,
247 s_nsBulkInUsbIoCompleteRead,
Malcolm Priestley0b787d72014-02-25 20:51:50 +0000248 rcb);
Forest Bond92b96792009-06-13 07:38:31 -0400249
Malcolm Priestley0b787d72014-02-25 20:51:50 +0000250 status = usb_submit_urb(urb, GFP_ATOMIC);
251 if (status != 0) {
Malcolm Priestley8a660262014-05-17 09:50:20 +0100252 dev_dbg(&priv->usb->dev, "Submit Rx URB failed %d\n", status);
Forest Bond92b96792009-06-13 07:38:31 -0400253 return STATUS_FAILURE ;
254 }
Forest Bond92b96792009-06-13 07:38:31 -0400255
Malcolm Priestley0b787d72014-02-25 20:51:50 +0000256 rcb->Ref = 1;
257 rcb->bBoolInUse = true;
258
259 return status;
Forest Bond92b96792009-06-13 07:38:31 -0400260}
261
Forest Bond92b96792009-06-13 07:38:31 -0400262/*
263 * Description:
264 * Complete function of usb BulkIn irp.
265 *
266 * Parameters:
267 * In:
268 * pDevice - Pointer to the adapter
269 *
270 * Out:
271 * none
272 *
273 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
274 *
275 */
Forest Bond92b96792009-06-13 07:38:31 -0400276
Malcolm Priestleyfe5d00e2012-12-10 22:14:36 +0000277static void s_nsBulkInUsbIoCompleteRead(struct urb *urb)
Forest Bond92b96792009-06-13 07:38:31 -0400278{
Malcolm Priestley599e4b52014-02-25 20:51:51 +0000279 struct vnt_rcb *rcb = urb->context;
Malcolm Priestleyd4fa2ab2014-02-25 20:51:49 +0000280 struct vnt_private *priv = rcb->pDevice;
Malcolm Priestley29b02372014-05-15 22:49:20 +0100281 unsigned long flags;
Malcolm Priestleyd4fa2ab2014-02-25 20:51:49 +0000282 int re_alloc_skb = false;
Forest Bond92b96792009-06-13 07:38:31 -0400283
Malcolm Priestley67638982014-02-25 20:51:48 +0000284 switch (urb->status) {
285 case 0:
Malcolm Priestley67638982014-02-25 20:51:48 +0000286 break;
287 case -ECONNRESET:
288 case -ENOENT:
289 case -ESHUTDOWN:
290 return;
291 case -ETIMEDOUT:
292 default:
Malcolm Priestley8a660262014-05-17 09:50:20 +0100293 dev_dbg(&priv->usb->dev, "BULK In failed %d\n", urb->status);
Malcolm Priestley67638982014-02-25 20:51:48 +0000294 break;
295 }
Forest Bond92b96792009-06-13 07:38:31 -0400296
Malcolm Priestleyd4fa2ab2014-02-25 20:51:49 +0000297 if (urb->actual_length) {
Malcolm Priestley29b02372014-05-15 22:49:20 +0100298 spin_lock_irqsave(&priv->lock, flags);
Forest Bond92b96792009-06-13 07:38:31 -0400299
Malcolm Priestley63b99072014-06-25 21:14:22 +0100300 if (vnt_rx_data(priv, rcb, urb->actual_length))
Malcolm Priestleyd4fa2ab2014-02-25 20:51:49 +0000301 re_alloc_skb = true;
302
Malcolm Priestley29b02372014-05-15 22:49:20 +0100303 spin_unlock_irqrestore(&priv->lock, flags);
Malcolm Priestleyd4fa2ab2014-02-25 20:51:49 +0000304 }
305
306 rcb->Ref--;
307 if (rcb->Ref == 0) {
Malcolm Priestley8a660262014-05-17 09:50:20 +0100308 dev_dbg(&priv->usb->dev,
309 "RxvFreeNormal %d\n", priv->NumRecvFreeList);
310
Malcolm Priestley29b02372014-05-15 22:49:20 +0100311 spin_lock_irqsave(&priv->lock, flags);
Malcolm Priestleyd4fa2ab2014-02-25 20:51:49 +0000312
313 RXvFreeRCB(rcb, re_alloc_skb);
314
Malcolm Priestley29b02372014-05-15 22:49:20 +0100315 spin_unlock_irqrestore(&priv->lock, flags);
Malcolm Priestleyd4fa2ab2014-02-25 20:51:49 +0000316 }
317
318 return;
Forest Bond92b96792009-06-13 07:38:31 -0400319}
320
321/*
322 * Description:
323 * Allocates an usb BulkOut irp and calls USBD.
324 *
325 * Parameters:
326 * In:
327 * pDevice - Pointer to the adapter
328 * Out:
329 * none
330 *
331 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
332 *
333 */
Malcolm Priestleyfe5d00e2012-12-10 22:14:36 +0000334
Malcolm Priestley3f382902014-02-25 20:51:45 +0000335int PIPEnsSendBulkOut(struct vnt_private *priv,
336 struct vnt_usb_send_context *context)
Forest Bond92b96792009-06-13 07:38:31 -0400337{
Malcolm Priestleyfe5d00e2012-12-10 22:14:36 +0000338 int status;
Malcolm Priestley3f382902014-02-25 20:51:45 +0000339 struct urb *urb;
Forest Bond92b96792009-06-13 07:38:31 -0400340
Malcolm Priestley3f382902014-02-25 20:51:45 +0000341 priv->bPWBitOn = false;
Forest Bond92b96792009-06-13 07:38:31 -0400342
Malcolm Priestley3f382902014-02-25 20:51:45 +0000343 if (!(MP_IS_READY(priv) && priv->Flags & fMP_POST_WRITES)) {
Malcolm Priestley30a05b32014-05-15 22:49:11 +0100344 context->in_use = false;
Malcolm Priestley13338302014-02-25 20:51:43 +0000345 return STATUS_RESOURCES;
346 }
Forest Bond92b96792009-06-13 07:38:31 -0400347
Malcolm Priestley30a05b32014-05-15 22:49:11 +0100348 urb = context->urb;
Forest Bond92b96792009-06-13 07:38:31 -0400349
Malcolm Priestley3f382902014-02-25 20:51:45 +0000350 usb_fill_bulk_urb(urb,
351 priv->usb,
352 usb_sndbulkpipe(priv->usb, 3),
Malcolm Priestley30a05b32014-05-15 22:49:11 +0100353 context->data,
354 context->buf_len,
Malcolm Priestley3f382902014-02-25 20:51:45 +0000355 s_nsBulkOutIoCompleteWrite,
356 context);
357
358 status = usb_submit_urb(urb, GFP_ATOMIC);
359 if (status != 0) {
Malcolm Priestley8a660262014-05-17 09:50:20 +0100360 dev_dbg(&priv->usb->dev, "Submit Tx URB failed %d\n", status);
361
Malcolm Priestley30a05b32014-05-15 22:49:11 +0100362 context->in_use = false;
Malcolm Priestley3f382902014-02-25 20:51:45 +0000363 return STATUS_FAILURE;
364 }
365
366 return STATUS_PENDING;
Forest Bond92b96792009-06-13 07:38:31 -0400367}
368
369/*
370 * Description: s_nsBulkOutIoCompleteWrite
371 * 1a) Indicate to the protocol the status of the write.
372 * 1b) Return ownership of the packet to the protocol.
373 *
374 * 2) If any more packets are queue for sending, send another packet
375 * to USBD.
376 * If the attempt to send the packet to the driver fails,
377 * return ownership of the packet to the protocol and
378 * try another packet (until one succeeds).
379 *
380 * Parameters:
381 * In:
382 * pdoUsbDevObj - pointer to the USB device object which
383 * completed the irp
384 * pIrp - the irp which was completed by the
385 * device object
386 * pContext - the context given to IoSetCompletionRoutine
387 * before calling IoCallDriver on the irp
388 * The pContext is a pointer to the USB device object.
389 * Out:
390 * none
391 *
392 * Return Value: STATUS_MORE_PROCESSING_REQUIRED - allows the completion routine
393 * (IofCompleteRequest) to stop working on the irp.
394 *
395 */
Malcolm Priestleyfe5d00e2012-12-10 22:14:36 +0000396
397static void s_nsBulkOutIoCompleteWrite(struct urb *urb)
Forest Bond92b96792009-06-13 07:38:31 -0400398{
Malcolm Priestley599e4b52014-02-25 20:51:51 +0000399 struct vnt_usb_send_context *context = urb->context;
Malcolm Priestley30a05b32014-05-15 22:49:11 +0100400 struct vnt_private *priv = context->priv;
Malcolm Priestleyd38b13a2014-06-25 21:14:23 +0100401 struct ieee80211_tx_info *info;
Forest Bond92b96792009-06-13 07:38:31 -0400402
Malcolm Priestleye8152bf2014-02-19 21:53:35 +0000403 switch (urb->status) {
404 case 0:
Malcolm Priestley8a660262014-05-17 09:50:20 +0100405 dev_dbg(&priv->usb->dev, "Write %d bytes\n", context->buf_len);
Malcolm Priestleye8152bf2014-02-19 21:53:35 +0000406 break;
407 case -ECONNRESET:
408 case -ENOENT:
409 case -ESHUTDOWN:
Malcolm Priestley30a05b32014-05-15 22:49:11 +0100410 context->in_use = false;
Malcolm Priestleye8152bf2014-02-19 21:53:35 +0000411 return;
Malcolm Priestleyd1b2a112014-02-27 23:06:15 +0000412 case -ETIMEDOUT:
Malcolm Priestleye8152bf2014-02-19 21:53:35 +0000413 default:
Malcolm Priestley8a660262014-05-17 09:50:20 +0100414 dev_dbg(&priv->usb->dev, "BULK Out failed %d\n", urb->status);
Malcolm Priestleye8152bf2014-02-19 21:53:35 +0000415 break;
416 }
417
Malcolm Priestleyd38b13a2014-06-25 21:14:23 +0100418 if (context->skb) {
419 info = IEEE80211_SKB_CB(context->skb);
420 ieee80211_tx_info_clear_status(info);
421 info->status.rates[0].idx = priv->wCurrentRate;
422 info->status.rates[0].count = 0;
423 if (!urb->status)
424 info->flags |= IEEE80211_TX_STAT_ACK;
425 ieee80211_tx_status_irqsafe(priv->hw, context->skb);
Malcolm Priestley21aa2122014-02-19 21:54:45 +0000426 }
Forest Bond92b96792009-06-13 07:38:31 -0400427
Malcolm Priestleyd38b13a2014-06-25 21:14:23 +0100428 if (context->type == CONTEXT_DATA_PACKET)
429 ieee80211_wake_queues(priv->hw);
Malcolm Priestley21aa2122014-02-19 21:54:45 +0000430
Malcolm Priestley30a05b32014-05-15 22:49:11 +0100431 context->in_use = false;
Malcolm Priestley21aa2122014-02-19 21:54:45 +0000432
433 return;
Forest Bond92b96792009-06-13 07:38:31 -0400434}