blob: 7d4e131303de43b7ed5ab06078bfcf9963465c02 [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
Forest Bond92b96792009-06-13 07:38:31 -040031 * ControlvWriteByte - Write one byte to MEM/BB/MAC/EEPROM
32 * ControlvReadByte - Read one byte from MEM/BB/MAC/EEPROM
33 * 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 "control.h"
Forest Bond92b96792009-06-13 07:38:31 -040045#include "desc.h"
Forest Bond92b96792009-06-13 07:38:31 -040046#include "device.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 Priestley441c21c2014-05-26 13:59:02 +010086int vnt_control_in(struct vnt_private *priv, u8 request, u16 value,
Malcolm Priestley9af49fd2014-05-17 09:50:22 +010087 u16 index, u16 length, u8 *buffer)
Forest Bond92b96792009-06-13 07:38:31 -040088{
Malcolm Priestley9af49fd2014-05-17 09:50:22 +010089 int status;
Forest Bond92b96792009-06-13 07:38:31 -040090
Malcolm Priestley9af49fd2014-05-17 09:50:22 +010091 if (priv->Flags & fMP_DISCONNECTED)
Malcolm Priestleye1feda12013-10-14 19:44:13 +010092 return STATUS_FAILURE;
93
Malcolm Priestley9af49fd2014-05-17 09:50:22 +010094 mutex_lock(&priv->usb_lock);
Malcolm Priestleyc91b1862014-05-15 22:49:19 +010095
Malcolm Priestley9af49fd2014-05-17 09:50:22 +010096 status = usb_control_msg(priv->usb,
97 usb_rcvctrlpipe(priv->usb, 0), request, 0xc0, value,
98 index, buffer, length, USB_CTL_WAIT);
Forest Bond92b96792009-06-13 07:38:31 -040099
Malcolm Priestley9af49fd2014-05-17 09:50:22 +0100100 mutex_unlock(&priv->usb_lock);
Malcolm Priestleyc91b1862014-05-15 22:49:19 +0100101
Malcolm Priestley9af49fd2014-05-17 09:50:22 +0100102 if (status < (int)length)
Malcolm Priestley0fb2af32014-05-15 22:49:23 +0100103 return STATUS_FAILURE;
Forest Bond92b96792009-06-13 07:38:31 -0400104
Malcolm Priestley0fb2af32014-05-15 22:49:23 +0100105 return STATUS_SUCCESS;
Forest Bond92b96792009-06-13 07:38:31 -0400106}
107
Forest Bond92b96792009-06-13 07:38:31 -0400108/*
109 * Description:
110 * Allocates an usb interrupt in irp and calls USBD.
111 *
112 * Parameters:
113 * In:
114 * pDevice - Pointer to the adapter
115 * Out:
116 * none
117 *
118 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
119 *
120 */
Malcolm Priestleyfe5d00e2012-12-10 22:14:36 +0000121
Malcolm Priestley5f38b782014-02-19 18:37:32 +0000122int PIPEnsInterruptRead(struct vnt_private *priv)
Forest Bond92b96792009-06-13 07:38:31 -0400123{
Malcolm Priestley5f38b782014-02-19 18:37:32 +0000124 int status = STATUS_FAILURE;
Forest Bond92b96792009-06-13 07:38:31 -0400125
Malcolm Priestleyf764e002014-02-19 18:39:09 +0000126 if (priv->int_buf.in_use == true)
Malcolm Priestley5f38b782014-02-19 18:37:32 +0000127 return STATUS_FAILURE;
Forest Bond92b96792009-06-13 07:38:31 -0400128
Malcolm Priestleyf764e002014-02-19 18:39:09 +0000129 priv->int_buf.in_use = true;
Forest Bond92b96792009-06-13 07:38:31 -0400130
Malcolm Priestley5f38b782014-02-19 18:37:32 +0000131 usb_fill_int_urb(priv->pInterruptURB,
132 priv->usb,
Malcolm Priestleyb9d93d12014-03-16 12:34:11 +0000133 usb_rcvintpipe(priv->usb, 1),
Malcolm Priestleyf764e002014-02-19 18:39:09 +0000134 priv->int_buf.data_buf,
Forest Bond92b96792009-06-13 07:38:31 -0400135 MAX_INTERRUPT_SIZE,
136 s_nsInterruptUsbIoCompleteRead,
Malcolm Priestley5f38b782014-02-19 18:37:32 +0000137 priv,
138 priv->int_interval);
Forest Bond92b96792009-06-13 07:38:31 -0400139
Malcolm Priestley5f38b782014-02-19 18:37:32 +0000140 status = usb_submit_urb(priv->pInterruptURB, GFP_ATOMIC);
141 if (status) {
Malcolm Priestley8a660262014-05-17 09:50:20 +0100142 dev_dbg(&priv->usb->dev, "Submit int URB failed %d\n", status);
Malcolm Priestleyf764e002014-02-19 18:39:09 +0000143 priv->int_buf.in_use = false;
Malcolm Priestley59858f52014-02-19 18:36:37 +0000144 }
Forest Bond92b96792009-06-13 07:38:31 -0400145
Malcolm Priestley5f38b782014-02-19 18:37:32 +0000146 return status;
Forest Bond92b96792009-06-13 07:38:31 -0400147}
148
Forest Bond92b96792009-06-13 07:38:31 -0400149/*
150 * Description:
151 * Complete function of usb interrupt in irp.
152 *
153 * Parameters:
154 * In:
155 * pDevice - Pointer to the adapter
156 *
157 * Out:
158 * none
159 *
160 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
161 *
162 */
Forest Bond92b96792009-06-13 07:38:31 -0400163
Malcolm Priestleyfe5d00e2012-12-10 22:14:36 +0000164static void s_nsInterruptUsbIoCompleteRead(struct urb *urb)
Forest Bond92b96792009-06-13 07:38:31 -0400165{
Malcolm Priestley599e4b52014-02-25 20:51:51 +0000166 struct vnt_private *priv = urb->context;
Malcolm Priestleyd9ad7a92014-02-17 21:27:30 +0000167 int status;
Forest Bond92b96792009-06-13 07:38:31 -0400168
Malcolm Priestleyc98fbf92014-02-17 21:16:20 +0000169 switch (urb->status) {
170 case 0:
171 case -ETIMEDOUT:
172 break;
173 case -ECONNRESET:
174 case -ENOENT:
175 case -ESHUTDOWN:
Malcolm Priestleyf764e002014-02-19 18:39:09 +0000176 priv->int_buf.in_use = false;
Malcolm Priestleyc98fbf92014-02-17 21:16:20 +0000177 return;
178 default:
179 break;
180 }
181
Malcolm Priestleyd9ad7a92014-02-17 21:27:30 +0000182 status = urb->status;
Forest Bond92b96792009-06-13 07:38:31 -0400183
Malcolm Priestleyd9ad7a92014-02-17 21:27:30 +0000184 if (status != STATUS_SUCCESS) {
Malcolm Priestleyf764e002014-02-19 18:39:09 +0000185 priv->int_buf.in_use = false;
Forest Bond92b96792009-06-13 07:38:31 -0400186
Malcolm Priestley8a660262014-05-17 09:50:20 +0100187 dev_dbg(&priv->usb->dev, "%s status = %d\n", __func__, status);
Malcolm Priestley247b4b62014-02-17 21:12:51 +0000188 } else {
Malcolm Priestleyd9ad7a92014-02-17 21:27:30 +0000189 INTnsProcessData(priv);
Malcolm Priestley247b4b62014-02-17 21:12:51 +0000190 }
Malcolm Priestley749627f2014-02-17 21:24:33 +0000191
Malcolm Priestleyd9ad7a92014-02-17 21:27:30 +0000192 status = usb_submit_urb(priv->pInterruptURB, GFP_ATOMIC);
193 if (status) {
Malcolm Priestley8a660262014-05-17 09:50:20 +0100194 dev_dbg(&priv->usb->dev, "Submit int URB failed %d\n", status);
Malcolm Priestleyd9ad7a92014-02-17 21:27:30 +0000195 } else {
Malcolm Priestleyf764e002014-02-19 18:39:09 +0000196 priv->int_buf.in_use = true;
Malcolm Priestleyd9ad7a92014-02-17 21:27:30 +0000197 }
198
199 return;
Forest Bond92b96792009-06-13 07:38:31 -0400200}
201
202/*
203 * Description:
204 * Allocates an usb BulkIn irp and calls USBD.
205 *
206 * Parameters:
207 * In:
208 * pDevice - Pointer to the adapter
209 * Out:
210 * none
211 *
212 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
213 *
214 */
Malcolm Priestleyfe5d00e2012-12-10 22:14:36 +0000215
Malcolm Priestley0b787d72014-02-25 20:51:50 +0000216int PIPEnsBulkInUsbRead(struct vnt_private *priv, struct vnt_rcb *rcb)
Forest Bond92b96792009-06-13 07:38:31 -0400217{
Malcolm Priestley0b787d72014-02-25 20:51:50 +0000218 int status = 0;
219 struct urb *urb;
Forest Bond92b96792009-06-13 07:38:31 -0400220
Malcolm Priestley0b787d72014-02-25 20:51:50 +0000221 if (priv->Flags & fMP_DISCONNECTED)
222 return STATUS_FAILURE;
Forest Bond92b96792009-06-13 07:38:31 -0400223
Malcolm Priestley0b787d72014-02-25 20:51:50 +0000224 urb = rcb->pUrb;
225 if (rcb->skb == NULL) {
Malcolm Priestley8a660262014-05-17 09:50:20 +0100226 dev_dbg(&priv->usb->dev, "rcb->skb is null\n");
Malcolm Priestley0b787d72014-02-25 20:51:50 +0000227 return status;
228 }
Forest Bond92b96792009-06-13 07:38:31 -0400229
Malcolm Priestley0b787d72014-02-25 20:51:50 +0000230 usb_fill_bulk_urb(urb,
231 priv->usb,
232 usb_rcvbulkpipe(priv->usb, 2),
233 (void *) (rcb->skb->data),
Forest Bond92b96792009-06-13 07:38:31 -0400234 MAX_TOTAL_SIZE_WITH_ALL_HEADERS,
235 s_nsBulkInUsbIoCompleteRead,
Malcolm Priestley0b787d72014-02-25 20:51:50 +0000236 rcb);
Forest Bond92b96792009-06-13 07:38:31 -0400237
Malcolm Priestley0b787d72014-02-25 20:51:50 +0000238 status = usb_submit_urb(urb, GFP_ATOMIC);
239 if (status != 0) {
Malcolm Priestley8a660262014-05-17 09:50:20 +0100240 dev_dbg(&priv->usb->dev, "Submit Rx URB failed %d\n", status);
Forest Bond92b96792009-06-13 07:38:31 -0400241 return STATUS_FAILURE ;
242 }
Forest Bond92b96792009-06-13 07:38:31 -0400243
Malcolm Priestley0b787d72014-02-25 20:51:50 +0000244 rcb->Ref = 1;
245 rcb->bBoolInUse = true;
246
247 return status;
Forest Bond92b96792009-06-13 07:38:31 -0400248}
249
Forest Bond92b96792009-06-13 07:38:31 -0400250/*
251 * Description:
252 * Complete function of usb BulkIn irp.
253 *
254 * Parameters:
255 * In:
256 * pDevice - Pointer to the adapter
257 *
258 * Out:
259 * none
260 *
261 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
262 *
263 */
Forest Bond92b96792009-06-13 07:38:31 -0400264
Malcolm Priestleyfe5d00e2012-12-10 22:14:36 +0000265static void s_nsBulkInUsbIoCompleteRead(struct urb *urb)
Forest Bond92b96792009-06-13 07:38:31 -0400266{
Malcolm Priestley599e4b52014-02-25 20:51:51 +0000267 struct vnt_rcb *rcb = urb->context;
Malcolm Priestleyd4fa2ab2014-02-25 20:51:49 +0000268 struct vnt_private *priv = rcb->pDevice;
Malcolm Priestley29b02372014-05-15 22:49:20 +0100269 unsigned long flags;
Malcolm Priestleyd4fa2ab2014-02-25 20:51:49 +0000270 int re_alloc_skb = false;
Forest Bond92b96792009-06-13 07:38:31 -0400271
Malcolm Priestley67638982014-02-25 20:51:48 +0000272 switch (urb->status) {
273 case 0:
Malcolm Priestley67638982014-02-25 20:51:48 +0000274 break;
275 case -ECONNRESET:
276 case -ENOENT:
277 case -ESHUTDOWN:
278 return;
279 case -ETIMEDOUT:
280 default:
Malcolm Priestley8a660262014-05-17 09:50:20 +0100281 dev_dbg(&priv->usb->dev, "BULK In failed %d\n", urb->status);
Malcolm Priestley67638982014-02-25 20:51:48 +0000282 break;
283 }
Forest Bond92b96792009-06-13 07:38:31 -0400284
Malcolm Priestleyd4fa2ab2014-02-25 20:51:49 +0000285 if (urb->actual_length) {
Malcolm Priestley29b02372014-05-15 22:49:20 +0100286 spin_lock_irqsave(&priv->lock, flags);
Forest Bond92b96792009-06-13 07:38:31 -0400287
Malcolm Priestleyd4fa2ab2014-02-25 20:51:49 +0000288 if (RXbBulkInProcessData(priv, rcb, urb->actual_length) == true)
289 re_alloc_skb = true;
290
Malcolm Priestley29b02372014-05-15 22:49:20 +0100291 spin_unlock_irqrestore(&priv->lock, flags);
Malcolm Priestleyd4fa2ab2014-02-25 20:51:49 +0000292 }
293
294 rcb->Ref--;
295 if (rcb->Ref == 0) {
Malcolm Priestley8a660262014-05-17 09:50:20 +0100296 dev_dbg(&priv->usb->dev,
297 "RxvFreeNormal %d\n", priv->NumRecvFreeList);
298
Malcolm Priestley29b02372014-05-15 22:49:20 +0100299 spin_lock_irqsave(&priv->lock, flags);
Malcolm Priestleyd4fa2ab2014-02-25 20:51:49 +0000300
301 RXvFreeRCB(rcb, re_alloc_skb);
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 return;
Forest Bond92b96792009-06-13 07:38:31 -0400307}
308
309/*
310 * Description:
311 * Allocates an usb BulkOut irp and calls USBD.
312 *
313 * Parameters:
314 * In:
315 * pDevice - Pointer to the adapter
316 * Out:
317 * none
318 *
319 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
320 *
321 */
Malcolm Priestleyfe5d00e2012-12-10 22:14:36 +0000322
Malcolm Priestley3f382902014-02-25 20:51:45 +0000323int PIPEnsSendBulkOut(struct vnt_private *priv,
324 struct vnt_usb_send_context *context)
Forest Bond92b96792009-06-13 07:38:31 -0400325{
Malcolm Priestleyfe5d00e2012-12-10 22:14:36 +0000326 int status;
Malcolm Priestley3f382902014-02-25 20:51:45 +0000327 struct urb *urb;
Forest Bond92b96792009-06-13 07:38:31 -0400328
Malcolm Priestley3f382902014-02-25 20:51:45 +0000329 priv->bPWBitOn = false;
Forest Bond92b96792009-06-13 07:38:31 -0400330
Malcolm Priestley3f382902014-02-25 20:51:45 +0000331 if (!(MP_IS_READY(priv) && priv->Flags & fMP_POST_WRITES)) {
Malcolm Priestley30a05b32014-05-15 22:49:11 +0100332 context->in_use = false;
Malcolm Priestley13338302014-02-25 20:51:43 +0000333 return STATUS_RESOURCES;
334 }
Forest Bond92b96792009-06-13 07:38:31 -0400335
Malcolm Priestley30a05b32014-05-15 22:49:11 +0100336 urb = context->urb;
Forest Bond92b96792009-06-13 07:38:31 -0400337
Malcolm Priestley3f382902014-02-25 20:51:45 +0000338 usb_fill_bulk_urb(urb,
339 priv->usb,
340 usb_sndbulkpipe(priv->usb, 3),
Malcolm Priestley30a05b32014-05-15 22:49:11 +0100341 context->data,
342 context->buf_len,
Malcolm Priestley3f382902014-02-25 20:51:45 +0000343 s_nsBulkOutIoCompleteWrite,
344 context);
345
346 status = usb_submit_urb(urb, GFP_ATOMIC);
347 if (status != 0) {
Malcolm Priestley8a660262014-05-17 09:50:20 +0100348 dev_dbg(&priv->usb->dev, "Submit Tx URB failed %d\n", status);
349
Malcolm Priestley30a05b32014-05-15 22:49:11 +0100350 context->in_use = false;
Malcolm Priestley3f382902014-02-25 20:51:45 +0000351 return STATUS_FAILURE;
352 }
353
354 return STATUS_PENDING;
Forest Bond92b96792009-06-13 07:38:31 -0400355}
356
357/*
358 * Description: s_nsBulkOutIoCompleteWrite
359 * 1a) Indicate to the protocol the status of the write.
360 * 1b) Return ownership of the packet to the protocol.
361 *
362 * 2) If any more packets are queue for sending, send another packet
363 * to USBD.
364 * If the attempt to send the packet to the driver fails,
365 * return ownership of the packet to the protocol and
366 * try another packet (until one succeeds).
367 *
368 * Parameters:
369 * In:
370 * pdoUsbDevObj - pointer to the USB device object which
371 * completed the irp
372 * pIrp - the irp which was completed by the
373 * device object
374 * pContext - the context given to IoSetCompletionRoutine
375 * before calling IoCallDriver on the irp
376 * The pContext is a pointer to the USB device object.
377 * Out:
378 * none
379 *
380 * Return Value: STATUS_MORE_PROCESSING_REQUIRED - allows the completion routine
381 * (IofCompleteRequest) to stop working on the irp.
382 *
383 */
Malcolm Priestleyfe5d00e2012-12-10 22:14:36 +0000384
385static void s_nsBulkOutIoCompleteWrite(struct urb *urb)
Forest Bond92b96792009-06-13 07:38:31 -0400386{
Malcolm Priestley599e4b52014-02-25 20:51:51 +0000387 struct vnt_usb_send_context *context = urb->context;
Malcolm Priestley30a05b32014-05-15 22:49:11 +0100388 struct vnt_private *priv = context->priv;
Malcolm Priestley1450ba62014-02-19 21:56:33 +0000389 u8 context_type = context->type;
Forest Bond92b96792009-06-13 07:38:31 -0400390
Malcolm Priestleye8152bf2014-02-19 21:53:35 +0000391 switch (urb->status) {
392 case 0:
Malcolm Priestley8a660262014-05-17 09:50:20 +0100393 dev_dbg(&priv->usb->dev, "Write %d bytes\n", context->buf_len);
Malcolm Priestleye8152bf2014-02-19 21:53:35 +0000394 break;
395 case -ECONNRESET:
396 case -ENOENT:
397 case -ESHUTDOWN:
Malcolm Priestley30a05b32014-05-15 22:49:11 +0100398 context->in_use = false;
Malcolm Priestleye8152bf2014-02-19 21:53:35 +0000399 return;
Malcolm Priestleyd1b2a112014-02-27 23:06:15 +0000400 case -ETIMEDOUT:
Malcolm Priestleye8152bf2014-02-19 21:53:35 +0000401 default:
Malcolm Priestley8a660262014-05-17 09:50:20 +0100402 dev_dbg(&priv->usb->dev, "BULK Out failed %d\n", urb->status);
Malcolm Priestleye8152bf2014-02-19 21:53:35 +0000403 break;
404 }
405
Malcolm Priestley21aa2122014-02-19 21:54:45 +0000406 if (!netif_device_present(priv->dev))
407 return;
Forest Bond92b96792009-06-13 07:38:31 -0400408
Malcolm Priestley21aa2122014-02-19 21:54:45 +0000409 if (CONTEXT_DATA_PACKET == context_type) {
Malcolm Priestley30a05b32014-05-15 22:49:11 +0100410 if (context->skb != NULL) {
411 dev_kfree_skb_irq(context->skb);
412 context->skb = NULL;
Malcolm Priestley8a660262014-05-17 09:50:20 +0100413 dev_dbg(&priv->usb->dev,
414 "tx %d bytes\n", context->buf_len);
Malcolm Priestley21aa2122014-02-19 21:54:45 +0000415 }
Forest Bond92b96792009-06-13 07:38:31 -0400416
Malcolm Priestley21aa2122014-02-19 21:54:45 +0000417 priv->dev->trans_start = jiffies;
Malcolm Priestley21aa2122014-02-19 21:54:45 +0000418 }
Forest Bond92b96792009-06-13 07:38:31 -0400419
Malcolm Priestley21aa2122014-02-19 21:54:45 +0000420 if (priv->bLinkPass == true) {
421 if (netif_queue_stopped(priv->dev))
422 netif_wake_queue(priv->dev);
423 }
424
Malcolm Priestley30a05b32014-05-15 22:49:11 +0100425 context->in_use = false;
Malcolm Priestley21aa2122014-02-19 21:54:45 +0000426
427 return;
Forest Bond92b96792009-06-13 07:38:31 -0400428}