blob: 9946bfd57fe405611b28aa597e1ef1837167f724 [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:
29 * CONTROLnsRequestOut - Write variable length bytes to MEM/BB/MAC/EEPROM
30 * CONTROLnsRequestIn - Read variable length bytes from MEM/BB/MAC/EEPROM
31 * 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//static int msglevel =MSG_LEVEL_DEBUG;
55static int msglevel =MSG_LEVEL_INFO;
56
Forest Bond92b96792009-06-13 07:38:31 -040057#define USB_CTL_WAIT 500 //ms
58
59#ifndef URB_ASYNC_UNLINK
60#define URB_ASYNC_UNLINK 0
61#endif
62
Malcolm Priestleyfe5d00e2012-12-10 22:14:36 +000063static void s_nsInterruptUsbIoCompleteRead(struct urb *urb);
64static void s_nsBulkInUsbIoCompleteRead(struct urb *urb);
65static void s_nsBulkOutIoCompleteWrite(struct urb *urb);
Forest Bond92b96792009-06-13 07:38:31 -040066
Malcolm Priestleyfe5d00e2012-12-10 22:14:36 +000067int PIPEnsControlOutAsyn(struct vnt_private *pDevice, u8 byRequest,
68 u16 wValue, u16 wIndex, u16 wLength, u8 *pbyBuffer)
Forest Bond92b96792009-06-13 07:38:31 -040069{
Andres More6487c492010-08-02 20:51:57 -030070 int ntStatus;
Forest Bond92b96792009-06-13 07:38:31 -040071
Andres More731047f2010-08-05 22:17:20 -030072 if (pDevice->Flags & fMP_DISCONNECTED)
Forest Bond92b96792009-06-13 07:38:31 -040073 return STATUS_FAILURE;
74
Forest Bond92b96792009-06-13 07:38:31 -040075 if (in_interrupt()) {
76 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"in_interrupt return ..byRequest %x\n", byRequest);
77 return STATUS_FAILURE;
78 }
79
Malcolm Priestleyc91b1862014-05-15 22:49:19 +010080 mutex_lock(&pDevice->usb_lock);
81
Forest Bond92b96792009-06-13 07:38:31 -040082 ntStatus = usb_control_msg(
83 pDevice->usb,
84 usb_sndctrlpipe(pDevice->usb , 0),
85 byRequest,
86 0x40, // RequestType
87 wValue,
88 wIndex,
Andres More8611a292010-05-01 14:25:00 -030089 (void *) pbyBuffer,
Forest Bond92b96792009-06-13 07:38:31 -040090 wLength,
91 HZ
92 );
93 if (ntStatus >= 0) {
94 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"usb_sndctrlpipe ntStatus= %d\n", ntStatus);
95 ntStatus = 0;
96 } else {
97 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"usb_sndctrlpipe fail, ntStatus= %d\n", ntStatus);
98 }
99
Malcolm Priestleyc91b1862014-05-15 22:49:19 +0100100 mutex_unlock(&pDevice->usb_lock);
101
Forest Bond92b96792009-06-13 07:38:31 -0400102 return ntStatus;
103}
104
Malcolm Priestleyfe5d00e2012-12-10 22:14:36 +0000105int PIPEnsControlOut(struct vnt_private *pDevice, u8 byRequest, u16 wValue,
106 u16 wIndex, u16 wLength, u8 *pbyBuffer)
Forest Bond92b96792009-06-13 07:38:31 -0400107{
Andres More6487c492010-08-02 20:51:57 -0300108 int ntStatus = 0;
Forest Bond92b96792009-06-13 07:38:31 -0400109
Malcolm Priestley7021b682014-05-15 22:49:22 +0100110 if (pDevice->Flags & fMP_DISCONNECTED)
Malcolm Priestleye1feda12013-10-14 19:44:13 +0100111 return STATUS_FAILURE;
112
Malcolm Priestleyc91b1862014-05-15 22:49:19 +0100113 mutex_lock(&pDevice->usb_lock);
114
Malcolm Priestley7021b682014-05-15 22:49:22 +0100115 ntStatus = usb_control_msg(pDevice->usb,
116 usb_sndctrlpipe(pDevice->usb, 0), byRequest, 0x40, wValue,
117 wIndex, pbyBuffer, wLength, USB_CTL_WAIT);
Forest Bond92b96792009-06-13 07:38:31 -0400118
Malcolm Priestleyc91b1862014-05-15 22:49:19 +0100119 mutex_unlock(&pDevice->usb_lock);
120
Malcolm Priestley7021b682014-05-15 22:49:22 +0100121 if (ntStatus < (int)wLength)
122 return STATUS_FAILURE;
123
124 return STATUS_SUCCESS;
Forest Bond92b96792009-06-13 07:38:31 -0400125}
126
Malcolm Priestleyfe5d00e2012-12-10 22:14:36 +0000127int PIPEnsControlIn(struct vnt_private *pDevice, u8 byRequest, u16 wValue,
Malcolm Priestley0fb2af32014-05-15 22:49:23 +0100128 u16 wIndex, u16 wLength, u8 *pbyBuffer)
Forest Bond92b96792009-06-13 07:38:31 -0400129{
Malcolm Priestley0fb2af32014-05-15 22:49:23 +0100130 int ntStatus;
Forest Bond92b96792009-06-13 07:38:31 -0400131
Malcolm Priestley0fb2af32014-05-15 22:49:23 +0100132 if (pDevice->Flags & fMP_DISCONNECTED)
Malcolm Priestleye1feda12013-10-14 19:44:13 +0100133 return STATUS_FAILURE;
134
Malcolm Priestleyc91b1862014-05-15 22:49:19 +0100135 mutex_lock(&pDevice->usb_lock);
136
Malcolm Priestley0fb2af32014-05-15 22:49:23 +0100137 ntStatus = usb_control_msg(pDevice->usb,
138 usb_rcvctrlpipe(pDevice->usb, 0), byRequest, 0xc0, wValue,
139 wIndex, pbyBuffer, wLength, USB_CTL_WAIT);
Forest Bond92b96792009-06-13 07:38:31 -0400140
Malcolm Priestleyc91b1862014-05-15 22:49:19 +0100141 mutex_unlock(&pDevice->usb_lock);
142
Malcolm Priestley0fb2af32014-05-15 22:49:23 +0100143 if (ntStatus < (int)wLength)
144 return STATUS_FAILURE;
Forest Bond92b96792009-06-13 07:38:31 -0400145
Malcolm Priestley0fb2af32014-05-15 22:49:23 +0100146 return STATUS_SUCCESS;
Forest Bond92b96792009-06-13 07:38:31 -0400147}
148
Forest Bond92b96792009-06-13 07:38:31 -0400149/*
150 * Description:
151 * Allocates an usb interrupt in irp and calls USBD.
152 *
153 * Parameters:
154 * In:
155 * pDevice - Pointer to the adapter
156 * Out:
157 * none
158 *
159 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
160 *
161 */
Malcolm Priestleyfe5d00e2012-12-10 22:14:36 +0000162
Malcolm Priestley5f38b782014-02-19 18:37:32 +0000163int PIPEnsInterruptRead(struct vnt_private *priv)
Forest Bond92b96792009-06-13 07:38:31 -0400164{
Malcolm Priestley5f38b782014-02-19 18:37:32 +0000165 int status = STATUS_FAILURE;
Forest Bond92b96792009-06-13 07:38:31 -0400166
Malcolm Priestley5f38b782014-02-19 18:37:32 +0000167 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
168 "---->s_nsStartInterruptUsbRead()\n");
Forest Bond92b96792009-06-13 07:38:31 -0400169
Malcolm Priestleyf764e002014-02-19 18:39:09 +0000170 if (priv->int_buf.in_use == true)
Malcolm Priestley5f38b782014-02-19 18:37:32 +0000171 return STATUS_FAILURE;
Forest Bond92b96792009-06-13 07:38:31 -0400172
Malcolm Priestleyf764e002014-02-19 18:39:09 +0000173 priv->int_buf.in_use = true;
Forest Bond92b96792009-06-13 07:38:31 -0400174
Malcolm Priestley5f38b782014-02-19 18:37:32 +0000175 usb_fill_int_urb(priv->pInterruptURB,
176 priv->usb,
Malcolm Priestleyb9d93d12014-03-16 12:34:11 +0000177 usb_rcvintpipe(priv->usb, 1),
Malcolm Priestleyf764e002014-02-19 18:39:09 +0000178 priv->int_buf.data_buf,
Forest Bond92b96792009-06-13 07:38:31 -0400179 MAX_INTERRUPT_SIZE,
180 s_nsInterruptUsbIoCompleteRead,
Malcolm Priestley5f38b782014-02-19 18:37:32 +0000181 priv,
182 priv->int_interval);
Forest Bond92b96792009-06-13 07:38:31 -0400183
Malcolm Priestley5f38b782014-02-19 18:37:32 +0000184 status = usb_submit_urb(priv->pInterruptURB, GFP_ATOMIC);
185 if (status) {
Malcolm Priestley59858f52014-02-19 18:36:37 +0000186 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
Malcolm Priestley5f38b782014-02-19 18:37:32 +0000187 "Submit int URB failed %d\n", status);
Malcolm Priestleyf764e002014-02-19 18:39:09 +0000188 priv->int_buf.in_use = false;
Malcolm Priestley59858f52014-02-19 18:36:37 +0000189 }
Forest Bond92b96792009-06-13 07:38:31 -0400190
Malcolm Priestley5f38b782014-02-19 18:37:32 +0000191 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
192 "<----s_nsStartInterruptUsbRead Return(%x)\n", status);
193
194 return status;
Forest Bond92b96792009-06-13 07:38:31 -0400195}
196
Forest Bond92b96792009-06-13 07:38:31 -0400197/*
198 * Description:
199 * Complete function of usb interrupt in irp.
200 *
201 * Parameters:
202 * In:
203 * pDevice - Pointer to the adapter
204 *
205 * Out:
206 * none
207 *
208 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
209 *
210 */
Forest Bond92b96792009-06-13 07:38:31 -0400211
Malcolm Priestleyfe5d00e2012-12-10 22:14:36 +0000212static void s_nsInterruptUsbIoCompleteRead(struct urb *urb)
Forest Bond92b96792009-06-13 07:38:31 -0400213{
Malcolm Priestley599e4b52014-02-25 20:51:51 +0000214 struct vnt_private *priv = urb->context;
Malcolm Priestleyd9ad7a92014-02-17 21:27:30 +0000215 int status;
Forest Bond92b96792009-06-13 07:38:31 -0400216
Malcolm Priestleyd9ad7a92014-02-17 21:27:30 +0000217 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
218 "---->s_nsInterruptUsbIoCompleteRead\n");
Forest Bond92b96792009-06-13 07:38:31 -0400219
Malcolm Priestleyc98fbf92014-02-17 21:16:20 +0000220 switch (urb->status) {
221 case 0:
222 case -ETIMEDOUT:
223 break;
224 case -ECONNRESET:
225 case -ENOENT:
226 case -ESHUTDOWN:
Malcolm Priestleyf764e002014-02-19 18:39:09 +0000227 priv->int_buf.in_use = false;
Malcolm Priestleyc98fbf92014-02-17 21:16:20 +0000228 return;
229 default:
230 break;
231 }
232
Malcolm Priestleyd9ad7a92014-02-17 21:27:30 +0000233 status = urb->status;
Forest Bond92b96792009-06-13 07:38:31 -0400234
Malcolm Priestleyd9ad7a92014-02-17 21:27:30 +0000235 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
236 "s_nsInterruptUsbIoCompleteRead Status %d\n", status);
Forest Bond92b96792009-06-13 07:38:31 -0400237
Malcolm Priestleyd9ad7a92014-02-17 21:27:30 +0000238 if (status != STATUS_SUCCESS) {
Malcolm Priestleyf764e002014-02-19 18:39:09 +0000239 priv->int_buf.in_use = false;
Forest Bond92b96792009-06-13 07:38:31 -0400240
Malcolm Priestley247b4b62014-02-17 21:12:51 +0000241 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
Malcolm Priestleyd9ad7a92014-02-17 21:27:30 +0000242 "IntUSBIoCompleteControl STATUS = %d\n", status);
Malcolm Priestley247b4b62014-02-17 21:12:51 +0000243 } else {
Malcolm Priestleyd9ad7a92014-02-17 21:27:30 +0000244 INTnsProcessData(priv);
Malcolm Priestley247b4b62014-02-17 21:12:51 +0000245 }
Malcolm Priestley749627f2014-02-17 21:24:33 +0000246
Malcolm Priestleyd9ad7a92014-02-17 21:27:30 +0000247 status = usb_submit_urb(priv->pInterruptURB, GFP_ATOMIC);
248 if (status) {
249 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
250 "Submit int URB failed %d\n", status);
251 } else {
Malcolm Priestleyf764e002014-02-19 18:39:09 +0000252 priv->int_buf.in_use = true;
Malcolm Priestleyd9ad7a92014-02-17 21:27:30 +0000253 }
254
255 return;
Forest Bond92b96792009-06-13 07:38:31 -0400256}
257
258/*
259 * Description:
260 * Allocates an usb BulkIn irp and calls USBD.
261 *
262 * Parameters:
263 * In:
264 * pDevice - Pointer to the adapter
265 * Out:
266 * none
267 *
268 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
269 *
270 */
Malcolm Priestleyfe5d00e2012-12-10 22:14:36 +0000271
Malcolm Priestley0b787d72014-02-25 20:51:50 +0000272int PIPEnsBulkInUsbRead(struct vnt_private *priv, struct vnt_rcb *rcb)
Forest Bond92b96792009-06-13 07:38:31 -0400273{
Malcolm Priestley0b787d72014-02-25 20:51:50 +0000274 int status = 0;
275 struct urb *urb;
Forest Bond92b96792009-06-13 07:38:31 -0400276
Malcolm Priestley0b787d72014-02-25 20:51:50 +0000277 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsStartBulkInUsbRead\n");
Forest Bond92b96792009-06-13 07:38:31 -0400278
Malcolm Priestley0b787d72014-02-25 20:51:50 +0000279 if (priv->Flags & fMP_DISCONNECTED)
280 return STATUS_FAILURE;
Forest Bond92b96792009-06-13 07:38:31 -0400281
Malcolm Priestley0b787d72014-02-25 20:51:50 +0000282 urb = rcb->pUrb;
283 if (rcb->skb == NULL) {
284 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"rcb->skb is null\n");
285 return status;
286 }
Forest Bond92b96792009-06-13 07:38:31 -0400287
Malcolm Priestley0b787d72014-02-25 20:51:50 +0000288 usb_fill_bulk_urb(urb,
289 priv->usb,
290 usb_rcvbulkpipe(priv->usb, 2),
291 (void *) (rcb->skb->data),
Forest Bond92b96792009-06-13 07:38:31 -0400292 MAX_TOTAL_SIZE_WITH_ALL_HEADERS,
293 s_nsBulkInUsbIoCompleteRead,
Malcolm Priestley0b787d72014-02-25 20:51:50 +0000294 rcb);
Forest Bond92b96792009-06-13 07:38:31 -0400295
Malcolm Priestley0b787d72014-02-25 20:51:50 +0000296 status = usb_submit_urb(urb, GFP_ATOMIC);
297 if (status != 0) {
298 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
299 "Submit Rx URB failed %d\n", status);
Forest Bond92b96792009-06-13 07:38:31 -0400300 return STATUS_FAILURE ;
301 }
Forest Bond92b96792009-06-13 07:38:31 -0400302
Malcolm Priestley0b787d72014-02-25 20:51:50 +0000303 rcb->Ref = 1;
304 rcb->bBoolInUse = true;
305
306 return status;
Forest Bond92b96792009-06-13 07:38:31 -0400307}
308
Forest Bond92b96792009-06-13 07:38:31 -0400309/*
310 * Description:
311 * Complete function of usb BulkIn irp.
312 *
313 * Parameters:
314 * In:
315 * pDevice - Pointer to the adapter
316 *
317 * Out:
318 * none
319 *
320 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
321 *
322 */
Forest Bond92b96792009-06-13 07:38:31 -0400323
Malcolm Priestleyfe5d00e2012-12-10 22:14:36 +0000324static void s_nsBulkInUsbIoCompleteRead(struct urb *urb)
Forest Bond92b96792009-06-13 07:38:31 -0400325{
Malcolm Priestley599e4b52014-02-25 20:51:51 +0000326 struct vnt_rcb *rcb = urb->context;
Malcolm Priestleyd4fa2ab2014-02-25 20:51:49 +0000327 struct vnt_private *priv = rcb->pDevice;
Malcolm Priestley29b02372014-05-15 22:49:20 +0100328 unsigned long flags;
Malcolm Priestleyd4fa2ab2014-02-25 20:51:49 +0000329 int re_alloc_skb = false;
Forest Bond92b96792009-06-13 07:38:31 -0400330
Malcolm Priestleyd4fa2ab2014-02-25 20:51:49 +0000331 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkInUsbIoCompleteRead\n");
Malcolm Priestleye3a8fa12014-02-25 20:51:46 +0000332
Malcolm Priestley67638982014-02-25 20:51:48 +0000333 switch (urb->status) {
334 case 0:
Malcolm Priestley67638982014-02-25 20:51:48 +0000335 break;
336 case -ECONNRESET:
337 case -ENOENT:
338 case -ESHUTDOWN:
339 return;
340 case -ETIMEDOUT:
341 default:
Malcolm Priestley67638982014-02-25 20:51:48 +0000342 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
343 "BULK In failed %d\n", urb->status);
344 break;
345 }
Forest Bond92b96792009-06-13 07:38:31 -0400346
Malcolm Priestleyd4fa2ab2014-02-25 20:51:49 +0000347 if (urb->actual_length) {
Malcolm Priestley29b02372014-05-15 22:49:20 +0100348 spin_lock_irqsave(&priv->lock, flags);
Forest Bond92b96792009-06-13 07:38:31 -0400349
Malcolm Priestleyd4fa2ab2014-02-25 20:51:49 +0000350 if (RXbBulkInProcessData(priv, rcb, urb->actual_length) == true)
351 re_alloc_skb = true;
352
Malcolm Priestley29b02372014-05-15 22:49:20 +0100353 spin_unlock_irqrestore(&priv->lock, flags);
Malcolm Priestleyd4fa2ab2014-02-25 20:51:49 +0000354 }
355
356 rcb->Ref--;
357 if (rcb->Ref == 0) {
358 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"RxvFreeNormal %d\n",
359 priv->NumRecvFreeList);
Malcolm Priestley29b02372014-05-15 22:49:20 +0100360 spin_lock_irqsave(&priv->lock, flags);
Malcolm Priestleyd4fa2ab2014-02-25 20:51:49 +0000361
362 RXvFreeRCB(rcb, re_alloc_skb);
363
Malcolm Priestley29b02372014-05-15 22:49:20 +0100364 spin_unlock_irqrestore(&priv->lock, flags);
Malcolm Priestleyd4fa2ab2014-02-25 20:51:49 +0000365 }
366
367 return;
Forest Bond92b96792009-06-13 07:38:31 -0400368}
369
370/*
371 * Description:
372 * Allocates an usb BulkOut irp and calls USBD.
373 *
374 * Parameters:
375 * In:
376 * pDevice - Pointer to the adapter
377 * Out:
378 * none
379 *
380 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
381 *
382 */
Malcolm Priestleyfe5d00e2012-12-10 22:14:36 +0000383
Malcolm Priestley3f382902014-02-25 20:51:45 +0000384int PIPEnsSendBulkOut(struct vnt_private *priv,
385 struct vnt_usb_send_context *context)
Forest Bond92b96792009-06-13 07:38:31 -0400386{
Malcolm Priestleyfe5d00e2012-12-10 22:14:36 +0000387 int status;
Malcolm Priestley3f382902014-02-25 20:51:45 +0000388 struct urb *urb;
Forest Bond92b96792009-06-13 07:38:31 -0400389
Malcolm Priestley3f382902014-02-25 20:51:45 +0000390 priv->bPWBitOn = false;
Forest Bond92b96792009-06-13 07:38:31 -0400391
Malcolm Priestley3f382902014-02-25 20:51:45 +0000392 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_nsSendBulkOut\n");
Forest Bond92b96792009-06-13 07:38:31 -0400393
Malcolm Priestley3f382902014-02-25 20:51:45 +0000394 if (!(MP_IS_READY(priv) && priv->Flags & fMP_POST_WRITES)) {
Malcolm Priestley30a05b32014-05-15 22:49:11 +0100395 context->in_use = false;
Malcolm Priestley13338302014-02-25 20:51:43 +0000396 return STATUS_RESOURCES;
397 }
Forest Bond92b96792009-06-13 07:38:31 -0400398
Malcolm Priestley30a05b32014-05-15 22:49:11 +0100399 urb = context->urb;
Forest Bond92b96792009-06-13 07:38:31 -0400400
Malcolm Priestley3f382902014-02-25 20:51:45 +0000401 usb_fill_bulk_urb(urb,
402 priv->usb,
403 usb_sndbulkpipe(priv->usb, 3),
Malcolm Priestley30a05b32014-05-15 22:49:11 +0100404 context->data,
405 context->buf_len,
Malcolm Priestley3f382902014-02-25 20:51:45 +0000406 s_nsBulkOutIoCompleteWrite,
407 context);
408
409 status = usb_submit_urb(urb, GFP_ATOMIC);
410 if (status != 0) {
411 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
412 "Submit Tx URB failed %d\n", status);
Malcolm Priestley30a05b32014-05-15 22:49:11 +0100413 context->in_use = false;
Malcolm Priestley3f382902014-02-25 20:51:45 +0000414 return STATUS_FAILURE;
415 }
416
417 return STATUS_PENDING;
Forest Bond92b96792009-06-13 07:38:31 -0400418}
419
420/*
421 * Description: s_nsBulkOutIoCompleteWrite
422 * 1a) Indicate to the protocol the status of the write.
423 * 1b) Return ownership of the packet to the protocol.
424 *
425 * 2) If any more packets are queue for sending, send another packet
426 * to USBD.
427 * If the attempt to send the packet to the driver fails,
428 * return ownership of the packet to the protocol and
429 * try another packet (until one succeeds).
430 *
431 * Parameters:
432 * In:
433 * pdoUsbDevObj - pointer to the USB device object which
434 * completed the irp
435 * pIrp - the irp which was completed by the
436 * device object
437 * pContext - the context given to IoSetCompletionRoutine
438 * before calling IoCallDriver on the irp
439 * The pContext is a pointer to the USB device object.
440 * Out:
441 * none
442 *
443 * Return Value: STATUS_MORE_PROCESSING_REQUIRED - allows the completion routine
444 * (IofCompleteRequest) to stop working on the irp.
445 *
446 */
Malcolm Priestleyfe5d00e2012-12-10 22:14:36 +0000447
448static void s_nsBulkOutIoCompleteWrite(struct urb *urb)
Forest Bond92b96792009-06-13 07:38:31 -0400449{
Malcolm Priestley599e4b52014-02-25 20:51:51 +0000450 struct vnt_usb_send_context *context = urb->context;
Malcolm Priestley30a05b32014-05-15 22:49:11 +0100451 struct vnt_private *priv = context->priv;
Malcolm Priestley1450ba62014-02-19 21:56:33 +0000452 u8 context_type = context->type;
Forest Bond92b96792009-06-13 07:38:31 -0400453
Malcolm Priestley21aa2122014-02-19 21:54:45 +0000454 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkOutIoCompleteWrite\n");
Forest Bond92b96792009-06-13 07:38:31 -0400455
Malcolm Priestleye8152bf2014-02-19 21:53:35 +0000456 switch (urb->status) {
457 case 0:
Malcolm Priestleyd1b2a112014-02-27 23:06:15 +0000458 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
Malcolm Priestley30a05b32014-05-15 22:49:11 +0100459 "Write %d bytes\n", context->buf_len);
Malcolm Priestleye8152bf2014-02-19 21:53:35 +0000460 break;
461 case -ECONNRESET:
462 case -ENOENT:
463 case -ESHUTDOWN:
Malcolm Priestley30a05b32014-05-15 22:49:11 +0100464 context->in_use = false;
Malcolm Priestleye8152bf2014-02-19 21:53:35 +0000465 return;
Malcolm Priestleyd1b2a112014-02-27 23:06:15 +0000466 case -ETIMEDOUT:
Malcolm Priestleye8152bf2014-02-19 21:53:35 +0000467 default:
Malcolm Priestleyd1b2a112014-02-27 23:06:15 +0000468 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
469 "BULK Out failed %d\n", urb->status);
Malcolm Priestleye8152bf2014-02-19 21:53:35 +0000470 break;
471 }
472
Malcolm Priestley21aa2122014-02-19 21:54:45 +0000473 if (!netif_device_present(priv->dev))
474 return;
Forest Bond92b96792009-06-13 07:38:31 -0400475
Malcolm Priestley21aa2122014-02-19 21:54:45 +0000476 if (CONTEXT_DATA_PACKET == context_type) {
Malcolm Priestley30a05b32014-05-15 22:49:11 +0100477 if (context->skb != NULL) {
478 dev_kfree_skb_irq(context->skb);
479 context->skb = NULL;
Malcolm Priestley21aa2122014-02-19 21:54:45 +0000480 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
Malcolm Priestley30a05b32014-05-15 22:49:11 +0100481 "tx %d bytes\n", context->buf_len);
Malcolm Priestley21aa2122014-02-19 21:54:45 +0000482 }
Forest Bond92b96792009-06-13 07:38:31 -0400483
Malcolm Priestley21aa2122014-02-19 21:54:45 +0000484 priv->dev->trans_start = jiffies;
Malcolm Priestley21aa2122014-02-19 21:54:45 +0000485 }
Forest Bond92b96792009-06-13 07:38:31 -0400486
Malcolm Priestley21aa2122014-02-19 21:54:45 +0000487 if (priv->bLinkPass == true) {
488 if (netif_queue_stopped(priv->dev))
489 netif_wake_queue(priv->dev);
490 }
491
Malcolm Priestley30a05b32014-05-15 22:49:11 +0100492 context->in_use = false;
Malcolm Priestley21aa2122014-02-19 21:54:45 +0000493
494 return;
Forest Bond92b96792009-06-13 07:38:31 -0400495}