Commit | Line | Data |
---|---|---|
92b96797 FB |
1 | /* |
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 | ||
92b96797 | 41 | #include "int.h" |
92b96797 | 42 | #include "rxtx.h" |
92b96797 | 43 | #include "dpc.h" |
92b96797 | 44 | #include "control.h" |
92b96797 | 45 | #include "desc.h" |
92b96797 | 46 | #include "device.h" |
92b96797 | 47 | |
92b96797 FB |
48 | //endpoint def |
49 | //endpoint 0: control | |
50 | //endpoint 1: interrupt | |
51 | //endpoint 2: read bulk | |
52 | //endpoint 3: write bulk | |
53 | ||
92b96797 FB |
54 | //static int msglevel =MSG_LEVEL_DEBUG; |
55 | static int msglevel =MSG_LEVEL_INFO; | |
56 | ||
92b96797 FB |
57 | #define USB_CTL_WAIT 500 //ms |
58 | ||
59 | #ifndef URB_ASYNC_UNLINK | |
60 | #define URB_ASYNC_UNLINK 0 | |
61 | #endif | |
62 | ||
fe5d00eb MP |
63 | static void s_nsInterruptUsbIoCompleteRead(struct urb *urb); |
64 | static void s_nsBulkInUsbIoCompleteRead(struct urb *urb); | |
65 | static void s_nsBulkOutIoCompleteWrite(struct urb *urb); | |
66 | static void s_nsControlInUsbIoCompleteRead(struct urb *urb); | |
67 | static void s_nsControlInUsbIoCompleteWrite(struct urb *urb); | |
92b96797 | 68 | |
fe5d00eb MP |
69 | int PIPEnsControlOutAsyn(struct vnt_private *pDevice, u8 byRequest, |
70 | u16 wValue, u16 wIndex, u16 wLength, u8 *pbyBuffer) | |
92b96797 | 71 | { |
6487c49e | 72 | int ntStatus; |
92b96797 | 73 | |
731047f9 | 74 | if (pDevice->Flags & fMP_DISCONNECTED) |
92b96797 FB |
75 | return STATUS_FAILURE; |
76 | ||
731047f9 | 77 | if (pDevice->Flags & fMP_CONTROL_WRITES) |
92b96797 | 78 | return STATUS_FAILURE; |
92b96797 FB |
79 | |
80 | if (in_interrupt()) { | |
81 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"in_interrupt return ..byRequest %x\n", byRequest); | |
82 | return STATUS_FAILURE; | |
83 | } | |
84 | ||
85 | ntStatus = usb_control_msg( | |
86 | pDevice->usb, | |
87 | usb_sndctrlpipe(pDevice->usb , 0), | |
88 | byRequest, | |
89 | 0x40, // RequestType | |
90 | wValue, | |
91 | wIndex, | |
8611a29a | 92 | (void *) pbyBuffer, |
92b96797 FB |
93 | wLength, |
94 | HZ | |
95 | ); | |
96 | if (ntStatus >= 0) { | |
97 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"usb_sndctrlpipe ntStatus= %d\n", ntStatus); | |
98 | ntStatus = 0; | |
99 | } else { | |
100 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"usb_sndctrlpipe fail, ntStatus= %d\n", ntStatus); | |
101 | } | |
102 | ||
103 | return ntStatus; | |
104 | } | |
105 | ||
fe5d00eb MP |
106 | int PIPEnsControlOut(struct vnt_private *pDevice, u8 byRequest, u16 wValue, |
107 | u16 wIndex, u16 wLength, u8 *pbyBuffer) | |
9009dd16 IM |
108 | __releases(&pDevice->lock) |
109 | __acquires(&pDevice->lock) | |
92b96797 | 110 | { |
6487c49e | 111 | int ntStatus = 0; |
fe5d00eb | 112 | int ii; |
92b96797 | 113 | |
731047f9 | 114 | if (pDevice->Flags & fMP_DISCONNECTED) |
92b96797 FB |
115 | return STATUS_FAILURE; |
116 | ||
731047f9 | 117 | if (pDevice->Flags & fMP_CONTROL_WRITES) |
92b96797 | 118 | return STATUS_FAILURE; |
92b96797 | 119 | |
ae5943de MP |
120 | if (pDevice->Flags & fMP_CONTROL_READS) |
121 | return STATUS_FAILURE; | |
122 | ||
e1feda13 MP |
123 | if (pDevice->pControlURB->hcpriv) |
124 | return STATUS_FAILURE; | |
125 | ||
ae5943de MP |
126 | MP_SET_FLAG(pDevice, fMP_CONTROL_WRITES); |
127 | ||
92b96797 FB |
128 | pDevice->sUsbCtlRequest.bRequestType = 0x40; |
129 | pDevice->sUsbCtlRequest.bRequest = byRequest; | |
130 | pDevice->sUsbCtlRequest.wValue = cpu_to_le16p(&wValue); | |
131 | pDevice->sUsbCtlRequest.wIndex = cpu_to_le16p(&wIndex); | |
132 | pDevice->sUsbCtlRequest.wLength = cpu_to_le16p(&wLength); | |
133 | pDevice->pControlURB->transfer_flags |= URB_ASYNC_UNLINK; | |
134 | pDevice->pControlURB->actual_length = 0; | |
135 | // Notice, pbyBuffer limited point to variable buffer, can't be constant. | |
136 | usb_fill_control_urb(pDevice->pControlURB, pDevice->usb, | |
137 | usb_sndctrlpipe(pDevice->usb , 0), (char *) &pDevice->sUsbCtlRequest, | |
138 | pbyBuffer, wLength, s_nsControlInUsbIoCompleteWrite, pDevice); | |
139 | ||
bfbfeecc JP |
140 | ntStatus = usb_submit_urb(pDevice->pControlURB, GFP_ATOMIC); |
141 | if (ntStatus != 0) { | |
ae5943de MP |
142 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO |
143 | "control send request submission failed: %d\n", | |
144 | ntStatus); | |
145 | MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES); | |
92b96797 FB |
146 | return STATUS_FAILURE; |
147 | } | |
ae5943de | 148 | |
92b96797 FB |
149 | spin_unlock_irq(&pDevice->lock); |
150 | for (ii = 0; ii <= USB_CTL_WAIT; ii ++) { | |
731047f9 AM |
151 | |
152 | if (pDevice->Flags & fMP_CONTROL_WRITES) | |
153 | mdelay(1); | |
92b96797 | 154 | else |
731047f9 AM |
155 | break; |
156 | ||
92b96797 | 157 | if (ii >= USB_CTL_WAIT) { |
731047f9 AM |
158 | DBG_PRT(MSG_LEVEL_DEBUG, |
159 | KERN_INFO "control send request submission timeout\n"); | |
92b96797 FB |
160 | spin_lock_irq(&pDevice->lock); |
161 | MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES); | |
162 | return STATUS_FAILURE; | |
163 | } | |
164 | } | |
165 | spin_lock_irq(&pDevice->lock); | |
166 | ||
167 | return STATUS_SUCCESS; | |
168 | } | |
169 | ||
fe5d00eb MP |
170 | int PIPEnsControlIn(struct vnt_private *pDevice, u8 byRequest, u16 wValue, |
171 | u16 wIndex, u16 wLength, u8 *pbyBuffer) | |
9009dd16 IM |
172 | __releases(&pDevice->lock) |
173 | __acquires(&pDevice->lock) | |
92b96797 | 174 | { |
6487c49e | 175 | int ntStatus = 0; |
fe5d00eb | 176 | int ii; |
92b96797 | 177 | |
731047f9 | 178 | if (pDevice->Flags & fMP_DISCONNECTED) |
92b96797 FB |
179 | return STATUS_FAILURE; |
180 | ||
731047f9 AM |
181 | if (pDevice->Flags & fMP_CONTROL_READS) |
182 | return STATUS_FAILURE; | |
183 | ||
ae5943de MP |
184 | if (pDevice->Flags & fMP_CONTROL_WRITES) |
185 | return STATUS_FAILURE; | |
e1feda13 MP |
186 | |
187 | if (pDevice->pControlURB->hcpriv) | |
188 | return STATUS_FAILURE; | |
ae5943de MP |
189 | |
190 | MP_SET_FLAG(pDevice, fMP_CONTROL_READS); | |
191 | ||
92b96797 FB |
192 | pDevice->sUsbCtlRequest.bRequestType = 0xC0; |
193 | pDevice->sUsbCtlRequest.bRequest = byRequest; | |
194 | pDevice->sUsbCtlRequest.wValue = cpu_to_le16p(&wValue); | |
195 | pDevice->sUsbCtlRequest.wIndex = cpu_to_le16p(&wIndex); | |
196 | pDevice->sUsbCtlRequest.wLength = cpu_to_le16p(&wLength); | |
197 | pDevice->pControlURB->transfer_flags |= URB_ASYNC_UNLINK; | |
198 | pDevice->pControlURB->actual_length = 0; | |
199 | usb_fill_control_urb(pDevice->pControlURB, pDevice->usb, | |
200 | usb_rcvctrlpipe(pDevice->usb , 0), (char *) &pDevice->sUsbCtlRequest, | |
201 | pbyBuffer, wLength, s_nsControlInUsbIoCompleteRead, pDevice); | |
202 | ||
bfbfeecc JP |
203 | ntStatus = usb_submit_urb(pDevice->pControlURB, GFP_ATOMIC); |
204 | if (ntStatus != 0) { | |
ae5943de MP |
205 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO |
206 | "control request submission failed: %d\n", ntStatus); | |
207 | MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS); | |
208 | return STATUS_FAILURE; | |
209 | } | |
92b96797 FB |
210 | |
211 | spin_unlock_irq(&pDevice->lock); | |
212 | for (ii = 0; ii <= USB_CTL_WAIT; ii ++) { | |
731047f9 AM |
213 | |
214 | if (pDevice->Flags & fMP_CONTROL_READS) | |
215 | mdelay(1); | |
216 | else | |
217 | break; | |
218 | ||
219 | if (ii >= USB_CTL_WAIT) { | |
220 | DBG_PRT(MSG_LEVEL_DEBUG, | |
221 | KERN_INFO "control rcv request submission timeout\n"); | |
92b96797 FB |
222 | spin_lock_irq(&pDevice->lock); |
223 | MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS); | |
224 | return STATUS_FAILURE; | |
225 | } | |
226 | } | |
227 | spin_lock_irq(&pDevice->lock); | |
228 | ||
229 | return ntStatus; | |
230 | } | |
231 | ||
fe5d00eb | 232 | static void s_nsControlInUsbIoCompleteWrite(struct urb *urb) |
92b96797 | 233 | { |
fe5d00eb | 234 | struct vnt_private *pDevice = (struct vnt_private *)urb->context; |
92b96797 FB |
235 | |
236 | pDevice = urb->context; | |
237 | switch (urb->status) { | |
238 | case 0: | |
239 | break; | |
240 | case -EINPROGRESS: | |
241 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl write urb status EINPROGRESS%d\n", urb->status); | |
242 | break; | |
243 | case -ENOENT: | |
244 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl write urb status ENOENT %d\n", urb->status); | |
245 | break; | |
246 | default: | |
247 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl write urb status %d\n", urb->status); | |
248 | } | |
249 | ||
250 | MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES); | |
251 | } | |
252 | ||
92b96797 FB |
253 | /* |
254 | * Description: | |
255 | * Complete function of usb Control callback | |
256 | * | |
257 | * Parameters: | |
258 | * In: | |
259 | * pDevice - Pointer to the adapter | |
260 | * | |
261 | * Out: | |
262 | * none | |
263 | * | |
264 | * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver | |
265 | * | |
266 | */ | |
fe5d00eb MP |
267 | |
268 | static void s_nsControlInUsbIoCompleteRead(struct urb *urb) | |
92b96797 | 269 | { |
fe5d00eb | 270 | struct vnt_private *pDevice = (struct vnt_private *)urb->context; |
92b96797 | 271 | |
92b96797 FB |
272 | switch (urb->status) { |
273 | case 0: | |
274 | break; | |
275 | case -EINPROGRESS: | |
276 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl read urb status EINPROGRESS%d\n", urb->status); | |
277 | break; | |
278 | case -ENOENT: | |
279 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl read urb status = ENOENT %d\n", urb->status); | |
280 | break; | |
281 | default: | |
282 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl read urb status %d\n", urb->status); | |
283 | } | |
284 | ||
285 | MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS); | |
286 | } | |
287 | ||
92b96797 FB |
288 | /* |
289 | * Description: | |
290 | * Allocates an usb interrupt in irp and calls USBD. | |
291 | * | |
292 | * Parameters: | |
293 | * In: | |
294 | * pDevice - Pointer to the adapter | |
295 | * Out: | |
296 | * none | |
297 | * | |
298 | * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver | |
299 | * | |
300 | */ | |
fe5d00eb | 301 | |
5f38b783 | 302 | int PIPEnsInterruptRead(struct vnt_private *priv) |
92b96797 | 303 | { |
5f38b783 | 304 | int status = STATUS_FAILURE; |
92b96797 | 305 | |
5f38b783 MP |
306 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO |
307 | "---->s_nsStartInterruptUsbRead()\n"); | |
92b96797 | 308 | |
f764e00d | 309 | if (priv->int_buf.in_use == true) |
5f38b783 MP |
310 | return STATUS_FAILURE; |
311 | ||
f764e00d | 312 | priv->int_buf.in_use = true; |
5f38b783 MP |
313 | |
314 | usb_fill_int_urb(priv->pInterruptURB, | |
315 | priv->usb, | |
b9d93d1c | 316 | usb_rcvintpipe(priv->usb, 1), |
f764e00d | 317 | priv->int_buf.data_buf, |
92b96797 FB |
318 | MAX_INTERRUPT_SIZE, |
319 | s_nsInterruptUsbIoCompleteRead, | |
5f38b783 MP |
320 | priv, |
321 | priv->int_interval); | |
92b96797 | 322 | |
5f38b783 MP |
323 | status = usb_submit_urb(priv->pInterruptURB, GFP_ATOMIC); |
324 | if (status) { | |
59858f5e | 325 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO |
5f38b783 | 326 | "Submit int URB failed %d\n", status); |
f764e00d | 327 | priv->int_buf.in_use = false; |
59858f5e | 328 | } |
92b96797 | 329 | |
5f38b783 MP |
330 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO |
331 | "<----s_nsStartInterruptUsbRead Return(%x)\n", status); | |
332 | ||
333 | return status; | |
92b96797 FB |
334 | } |
335 | ||
92b96797 FB |
336 | /* |
337 | * Description: | |
338 | * Complete function of usb interrupt in irp. | |
339 | * | |
340 | * Parameters: | |
341 | * In: | |
342 | * pDevice - Pointer to the adapter | |
343 | * | |
344 | * Out: | |
345 | * none | |
346 | * | |
347 | * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver | |
348 | * | |
349 | */ | |
92b96797 | 350 | |
fe5d00eb | 351 | static void s_nsInterruptUsbIoCompleteRead(struct urb *urb) |
92b96797 | 352 | { |
599e4b5c | 353 | struct vnt_private *priv = urb->context; |
d9ad7a98 | 354 | int status; |
92b96797 | 355 | |
d9ad7a98 MP |
356 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO |
357 | "---->s_nsInterruptUsbIoCompleteRead\n"); | |
92b96797 | 358 | |
c98fbf90 MP |
359 | switch (urb->status) { |
360 | case 0: | |
361 | case -ETIMEDOUT: | |
362 | break; | |
363 | case -ECONNRESET: | |
364 | case -ENOENT: | |
365 | case -ESHUTDOWN: | |
f764e00d | 366 | priv->int_buf.in_use = false; |
c98fbf90 MP |
367 | return; |
368 | default: | |
369 | break; | |
370 | } | |
371 | ||
d9ad7a98 | 372 | status = urb->status; |
92b96797 | 373 | |
d9ad7a98 MP |
374 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO |
375 | "s_nsInterruptUsbIoCompleteRead Status %d\n", status); | |
92b96797 | 376 | |
d9ad7a98 | 377 | if (status != STATUS_SUCCESS) { |
f764e00d | 378 | priv->int_buf.in_use = false; |
92b96797 | 379 | |
d9ad7a98 MP |
380 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO |
381 | "IntUSBIoCompleteControl STATUS = %d\n", status); | |
382 | } else { | |
d9ad7a98 MP |
383 | INTnsProcessData(priv); |
384 | } | |
92b96797 | 385 | |
d9ad7a98 MP |
386 | status = usb_submit_urb(priv->pInterruptURB, GFP_ATOMIC); |
387 | if (status) { | |
247b4b68 | 388 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO |
d9ad7a98 | 389 | "Submit int URB failed %d\n", status); |
247b4b68 | 390 | } else { |
f764e00d | 391 | priv->int_buf.in_use = true; |
247b4b68 | 392 | } |
749627f2 | 393 | |
d9ad7a98 | 394 | return; |
92b96797 FB |
395 | } |
396 | ||
397 | /* | |
398 | * Description: | |
399 | * Allocates an usb BulkIn irp and calls USBD. | |
400 | * | |
401 | * Parameters: | |
402 | * In: | |
403 | * pDevice - Pointer to the adapter | |
404 | * Out: | |
405 | * none | |
406 | * | |
407 | * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver | |
408 | * | |
409 | */ | |
fe5d00eb | 410 | |
0b787d71 | 411 | int PIPEnsBulkInUsbRead(struct vnt_private *priv, struct vnt_rcb *rcb) |
92b96797 | 412 | { |
0b787d71 MP |
413 | int status = 0; |
414 | struct urb *urb; | |
92b96797 | 415 | |
0b787d71 | 416 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsStartBulkInUsbRead\n"); |
92b96797 | 417 | |
0b787d71 MP |
418 | if (priv->Flags & fMP_DISCONNECTED) |
419 | return STATUS_FAILURE; | |
92b96797 | 420 | |
0b787d71 MP |
421 | urb = rcb->pUrb; |
422 | if (rcb->skb == NULL) { | |
423 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"rcb->skb is null\n"); | |
424 | return status; | |
425 | } | |
92b96797 | 426 | |
0b787d71 MP |
427 | usb_fill_bulk_urb(urb, |
428 | priv->usb, | |
429 | usb_rcvbulkpipe(priv->usb, 2), | |
430 | (void *) (rcb->skb->data), | |
92b96797 FB |
431 | MAX_TOTAL_SIZE_WITH_ALL_HEADERS, |
432 | s_nsBulkInUsbIoCompleteRead, | |
0b787d71 | 433 | rcb); |
92b96797 | 434 | |
0b787d71 MP |
435 | status = usb_submit_urb(urb, GFP_ATOMIC); |
436 | if (status != 0) { | |
437 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO | |
438 | "Submit Rx URB failed %d\n", status); | |
92b96797 FB |
439 | return STATUS_FAILURE ; |
440 | } | |
92b96797 | 441 | |
0b787d71 MP |
442 | rcb->Ref = 1; |
443 | rcb->bBoolInUse = true; | |
444 | ||
445 | return status; | |
92b96797 FB |
446 | } |
447 | ||
92b96797 FB |
448 | /* |
449 | * Description: | |
450 | * Complete function of usb BulkIn irp. | |
451 | * | |
452 | * Parameters: | |
453 | * In: | |
454 | * pDevice - Pointer to the adapter | |
455 | * | |
456 | * Out: | |
457 | * none | |
458 | * | |
459 | * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver | |
460 | * | |
461 | */ | |
92b96797 | 462 | |
fe5d00eb | 463 | static void s_nsBulkInUsbIoCompleteRead(struct urb *urb) |
92b96797 | 464 | { |
599e4b5c | 465 | struct vnt_rcb *rcb = urb->context; |
d4fa2ab0 MP |
466 | struct vnt_private *priv = rcb->pDevice; |
467 | int re_alloc_skb = false; | |
92b96797 | 468 | |
d4fa2ab0 | 469 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkInUsbIoCompleteRead\n"); |
e3a8fa17 | 470 | |
67638980 MP |
471 | switch (urb->status) { |
472 | case 0: | |
67638980 MP |
473 | break; |
474 | case -ECONNRESET: | |
475 | case -ENOENT: | |
476 | case -ESHUTDOWN: | |
477 | return; | |
478 | case -ETIMEDOUT: | |
479 | default: | |
67638980 MP |
480 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO |
481 | "BULK In failed %d\n", urb->status); | |
482 | break; | |
483 | } | |
92b96797 | 484 | |
d4fa2ab0 MP |
485 | if (urb->actual_length) { |
486 | spin_lock(&priv->lock); | |
487 | ||
488 | if (RXbBulkInProcessData(priv, rcb, urb->actual_length) == true) | |
489 | re_alloc_skb = true; | |
490 | ||
491 | spin_unlock(&priv->lock); | |
492 | } | |
92b96797 | 493 | |
d4fa2ab0 MP |
494 | rcb->Ref--; |
495 | if (rcb->Ref == 0) { | |
496 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"RxvFreeNormal %d\n", | |
497 | priv->NumRecvFreeList); | |
498 | spin_lock(&priv->lock); | |
499 | ||
500 | RXvFreeRCB(rcb, re_alloc_skb); | |
501 | ||
502 | spin_unlock(&priv->lock); | |
503 | } | |
504 | ||
505 | return; | |
92b96797 FB |
506 | } |
507 | ||
508 | /* | |
509 | * Description: | |
510 | * Allocates an usb BulkOut irp and calls USBD. | |
511 | * | |
512 | * Parameters: | |
513 | * In: | |
514 | * pDevice - Pointer to the adapter | |
515 | * Out: | |
516 | * none | |
517 | * | |
518 | * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver | |
519 | * | |
520 | */ | |
fe5d00eb | 521 | |
3f38290e MP |
522 | int PIPEnsSendBulkOut(struct vnt_private *priv, |
523 | struct vnt_usb_send_context *context) | |
92b96797 | 524 | { |
fe5d00eb | 525 | int status; |
3f38290e | 526 | struct urb *urb; |
92b96797 | 527 | |
3f38290e | 528 | priv->bPWBitOn = false; |
92b96797 | 529 | |
3f38290e | 530 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_nsSendBulkOut\n"); |
92b96797 | 531 | |
3f38290e MP |
532 | if (!(MP_IS_READY(priv) && priv->Flags & fMP_POST_WRITES)) { |
533 | context->bBoolInUse = false; | |
13338303 MP |
534 | return STATUS_RESOURCES; |
535 | } | |
92b96797 | 536 | |
3f38290e | 537 | urb = context->pUrb; |
3f38290e MP |
538 | |
539 | usb_fill_bulk_urb(urb, | |
540 | priv->usb, | |
541 | usb_sndbulkpipe(priv->usb, 3), | |
542 | context->Data, | |
543 | context->uBufLen, | |
da5c99fd | 544 | s_nsBulkOutIoCompleteWrite, |
3f38290e MP |
545 | context); |
546 | ||
547 | status = usb_submit_urb(urb, GFP_ATOMIC); | |
548 | if (status != 0) { | |
549 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO | |
550 | "Submit Tx URB failed %d\n", status); | |
551 | context->bBoolInUse = false; | |
552 | return STATUS_FAILURE; | |
553 | } | |
554 | ||
555 | return STATUS_PENDING; | |
92b96797 FB |
556 | } |
557 | ||
558 | /* | |
559 | * Description: s_nsBulkOutIoCompleteWrite | |
560 | * 1a) Indicate to the protocol the status of the write. | |
561 | * 1b) Return ownership of the packet to the protocol. | |
562 | * | |
563 | * 2) If any more packets are queue for sending, send another packet | |
564 | * to USBD. | |
565 | * If the attempt to send the packet to the driver fails, | |
566 | * return ownership of the packet to the protocol and | |
567 | * try another packet (until one succeeds). | |
568 | * | |
569 | * Parameters: | |
570 | * In: | |
571 | * pdoUsbDevObj - pointer to the USB device object which | |
572 | * completed the irp | |
573 | * pIrp - the irp which was completed by the | |
574 | * device object | |
575 | * pContext - the context given to IoSetCompletionRoutine | |
576 | * before calling IoCallDriver on the irp | |
577 | * The pContext is a pointer to the USB device object. | |
578 | * Out: | |
579 | * none | |
580 | * | |
581 | * Return Value: STATUS_MORE_PROCESSING_REQUIRED - allows the completion routine | |
582 | * (IofCompleteRequest) to stop working on the irp. | |
583 | * | |
584 | */ | |
fe5d00eb MP |
585 | |
586 | static void s_nsBulkOutIoCompleteWrite(struct urb *urb) | |
92b96797 | 587 | { |
599e4b5c | 588 | struct vnt_usb_send_context *context = urb->context; |
21aa212c | 589 | struct vnt_private *priv = context->pDevice; |
1450ba62 | 590 | u8 context_type = context->type; |
92b96797 | 591 | |
21aa212c | 592 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkOutIoCompleteWrite\n"); |
92b96797 | 593 | |
e8152bfb MP |
594 | switch (urb->status) { |
595 | case 0: | |
d1b2a11d MP |
596 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO |
597 | "Write %d bytes\n", context->uBufLen); | |
e8152bfb MP |
598 | break; |
599 | case -ECONNRESET: | |
600 | case -ENOENT: | |
601 | case -ESHUTDOWN: | |
21aa212c | 602 | context->bBoolInUse = false; |
e8152bfb | 603 | return; |
d1b2a11d | 604 | case -ETIMEDOUT: |
e8152bfb | 605 | default: |
d1b2a11d MP |
606 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO |
607 | "BULK Out failed %d\n", urb->status); | |
e8152bfb MP |
608 | break; |
609 | } | |
610 | ||
21aa212c MP |
611 | if (!netif_device_present(priv->dev)) |
612 | return; | |
92b96797 | 613 | |
21aa212c MP |
614 | if (CONTEXT_DATA_PACKET == context_type) { |
615 | if (context->pPacket != NULL) { | |
616 | dev_kfree_skb_irq(context->pPacket); | |
617 | context->pPacket = NULL; | |
618 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO | |
d597aaef | 619 | "tx %d bytes\n", context->uBufLen); |
21aa212c | 620 | } |
92b96797 | 621 | |
21aa212c | 622 | priv->dev->trans_start = jiffies; |
21aa212c | 623 | } |
92b96797 | 624 | |
21aa212c MP |
625 | if (priv->bLinkPass == true) { |
626 | if (netif_queue_stopped(priv->dev)) | |
627 | netif_wake_queue(priv->dev); | |
628 | } | |
629 | ||
630 | context->bBoolInUse = false; | |
631 | ||
632 | return; | |
92b96797 | 633 | } |