staging: vt6656: remove code placeholders
[firefly-linux-kernel-4.4.55.git] / drivers / staging / vt6656 / usbpipe.c
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
41 #include "int.h"
42 #include "rxtx.h"
43 #include "dpc.h"
44 #include "control.h"
45 #include "desc.h"
46 #include "device.h"
47
48 //endpoint def
49 //endpoint 0: control
50 //endpoint 1: interrupt
51 //endpoint 2: read bulk
52 //endpoint 3: write bulk
53
54 //static int          msglevel                =MSG_LEVEL_DEBUG;
55 static int          msglevel                =MSG_LEVEL_INFO;
56
57
58 #define USB_CTL_WAIT   500 //ms
59
60 #ifndef URB_ASYNC_UNLINK
61 #define URB_ASYNC_UNLINK    0
62 #endif
63
64
65
66 static void s_nsInterruptUsbIoCompleteRead(struct urb *urb);
67 static void s_nsBulkInUsbIoCompleteRead(struct urb *urb);
68 static void s_nsBulkOutIoCompleteWrite(struct urb *urb);
69 static void s_nsControlInUsbIoCompleteRead(struct urb *urb);
70 static void s_nsControlInUsbIoCompleteWrite(struct urb *urb);
71
72
73
74 int PIPEnsControlOutAsyn(struct vnt_private *pDevice, u8 byRequest,
75         u16 wValue, u16 wIndex, u16 wLength, u8 *pbyBuffer)
76 {
77         int ntStatus;
78
79     if (pDevice->Flags & fMP_DISCONNECTED)
80         return STATUS_FAILURE;
81
82     if (pDevice->Flags & fMP_CONTROL_WRITES)
83         return STATUS_FAILURE;
84
85     if (in_interrupt()) {
86         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"in_interrupt return ..byRequest %x\n", byRequest);
87         return STATUS_FAILURE;
88     }
89
90     ntStatus = usb_control_msg(
91                             pDevice->usb,
92                             usb_sndctrlpipe(pDevice->usb , 0),
93                             byRequest,
94                             0x40, // RequestType
95                             wValue,
96                             wIndex,
97                             (void *) pbyBuffer,
98                             wLength,
99                             HZ
100                           );
101     if (ntStatus >= 0) {
102         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"usb_sndctrlpipe ntStatus= %d\n", ntStatus);
103         ntStatus = 0;
104     } else {
105         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"usb_sndctrlpipe fail, ntStatus= %d\n", ntStatus);
106     }
107
108     return ntStatus;
109 }
110
111 int PIPEnsControlOut(struct vnt_private *pDevice, u8 byRequest, u16 wValue,
112                 u16 wIndex, u16 wLength, u8 *pbyBuffer)
113 {
114         int ntStatus = 0;
115         int ii;
116
117     if (pDevice->Flags & fMP_DISCONNECTED)
118         return STATUS_FAILURE;
119
120     if (pDevice->Flags & fMP_CONTROL_WRITES)
121         return STATUS_FAILURE;
122
123         if (pDevice->Flags & fMP_CONTROL_READS)
124                 return STATUS_FAILURE;
125
126         MP_SET_FLAG(pDevice, fMP_CONTROL_WRITES);
127
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
140         ntStatus = usb_submit_urb(pDevice->pControlURB, GFP_ATOMIC);
141         if (ntStatus != 0) {
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);
146                 return STATUS_FAILURE;
147         }
148
149         spin_unlock_irq(&pDevice->lock);
150     for (ii = 0; ii <= USB_CTL_WAIT; ii ++) {
151
152         if (pDevice->Flags & fMP_CONTROL_WRITES)
153                 mdelay(1);
154         else
155                 break;
156
157         if (ii >= USB_CTL_WAIT) {
158                 DBG_PRT(MSG_LEVEL_DEBUG,
159                         KERN_INFO "control send request submission timeout\n");
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
170 int PIPEnsControlIn(struct vnt_private *pDevice, u8 byRequest, u16 wValue,
171         u16 wIndex, u16 wLength,  u8 *pbyBuffer)
172 {
173         int ntStatus = 0;
174         int ii;
175
176     if (pDevice->Flags & fMP_DISCONNECTED)
177         return STATUS_FAILURE;
178
179     if (pDevice->Flags & fMP_CONTROL_READS)
180         return STATUS_FAILURE;
181
182         if (pDevice->Flags & fMP_CONTROL_WRITES)
183                 return STATUS_FAILURE;
184
185         MP_SET_FLAG(pDevice, fMP_CONTROL_READS);
186
187         pDevice->sUsbCtlRequest.bRequestType = 0xC0;
188         pDevice->sUsbCtlRequest.bRequest = byRequest;
189         pDevice->sUsbCtlRequest.wValue = cpu_to_le16p(&wValue);
190         pDevice->sUsbCtlRequest.wIndex = cpu_to_le16p(&wIndex);
191         pDevice->sUsbCtlRequest.wLength = cpu_to_le16p(&wLength);
192         pDevice->pControlURB->transfer_flags |= URB_ASYNC_UNLINK;
193     pDevice->pControlURB->actual_length = 0;
194         usb_fill_control_urb(pDevice->pControlURB, pDevice->usb,
195                          usb_rcvctrlpipe(pDevice->usb , 0), (char *) &pDevice->sUsbCtlRequest,
196                          pbyBuffer, wLength, s_nsControlInUsbIoCompleteRead, pDevice);
197
198         ntStatus = usb_submit_urb(pDevice->pControlURB, GFP_ATOMIC);
199         if (ntStatus != 0) {
200                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
201                         "control request submission failed: %d\n", ntStatus);
202                 MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS);
203                 return STATUS_FAILURE;
204         }
205
206         spin_unlock_irq(&pDevice->lock);
207     for (ii = 0; ii <= USB_CTL_WAIT; ii ++) {
208
209         if (pDevice->Flags & fMP_CONTROL_READS)
210                 mdelay(1);
211         else
212                 break;
213
214         if (ii >= USB_CTL_WAIT) {
215                 DBG_PRT(MSG_LEVEL_DEBUG,
216                         KERN_INFO "control rcv request submission timeout\n");
217             spin_lock_irq(&pDevice->lock);
218             MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS);
219             return STATUS_FAILURE;
220         }
221     }
222         spin_lock_irq(&pDevice->lock);
223
224     return ntStatus;
225 }
226
227 static void s_nsControlInUsbIoCompleteWrite(struct urb *urb)
228 {
229         struct vnt_private *pDevice = (struct vnt_private *)urb->context;
230
231         pDevice = urb->context;
232         switch (urb->status) {
233         case 0:
234                 break;
235         case -EINPROGRESS:
236                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl write urb status EINPROGRESS%d\n", urb->status);
237                 break;
238         case -ENOENT:
239                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl write urb status ENOENT %d\n", urb->status);
240                 break;
241         default:
242                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl write urb status %d\n", urb->status);
243         }
244
245     MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES);
246 }
247
248
249
250 /*
251  * Description:
252  *      Complete function of usb Control callback
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  */
264
265 static void s_nsControlInUsbIoCompleteRead(struct urb *urb)
266 {
267         struct vnt_private *pDevice = (struct vnt_private *)urb->context;
268
269         switch (urb->status) {
270         case 0:
271                 break;
272         case -EINPROGRESS:
273                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl read urb status EINPROGRESS%d\n", urb->status);
274                 break;
275         case -ENOENT:
276                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl read urb status = ENOENT %d\n", urb->status);
277                 break;
278         default:
279                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl read urb status %d\n", urb->status);
280         }
281
282     MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS);
283 }
284
285
286
287
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  */
301
302 int PIPEnsInterruptRead(struct vnt_private *pDevice)
303 {
304         int ntStatus = STATUS_FAILURE;
305
306     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsStartInterruptUsbRead()\n");
307
308     if(pDevice->intBuf.bInUse == true){
309         return (STATUS_FAILURE);
310     }
311     pDevice->intBuf.bInUse = true;
312 //    pDevice->bEventAvailable = false;
313     pDevice->ulIntInPosted++;
314
315     //
316     // Now that we have created the urb, we will send a
317     // request to the USB device object.
318     //
319     pDevice->pInterruptURB->interval = pDevice->int_interval;
320
321 usb_fill_bulk_urb(pDevice->pInterruptURB,
322                 pDevice->usb,
323                 usb_rcvbulkpipe(pDevice->usb, 1),
324                 (void *) pDevice->intBuf.pDataBuf,
325                 MAX_INTERRUPT_SIZE,
326                 s_nsInterruptUsbIoCompleteRead,
327                 pDevice);
328
329         ntStatus = usb_submit_urb(pDevice->pInterruptURB, GFP_ATOMIC);
330         if (ntStatus != 0) {
331             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit int URB failed %d\n", ntStatus);
332     }
333
334     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"<----s_nsStartInterruptUsbRead Return(%x)\n",ntStatus);
335     return ntStatus;
336 }
337
338
339 /*
340  * Description:
341  *      Complete function of usb interrupt in irp.
342  *
343  * Parameters:
344  *  In:
345  *      pDevice     - Pointer to the adapter
346  *
347  *  Out:
348  *      none
349  *
350  * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
351  *
352  */
353
354 static void s_nsInterruptUsbIoCompleteRead(struct urb *urb)
355 {
356         struct vnt_private *pDevice = (struct vnt_private *)urb->context;
357         int ntStatus;
358
359     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsInterruptUsbIoCompleteRead\n");
360     //
361     // The context given to IoSetCompletionRoutine is the receive buffer object
362     //
363
364     //
365     // We have a number of cases:
366     //      1) The USB read timed out and we received no data.
367     //      2) The USB read timed out and we received some data.
368     //      3) The USB read was successful and fully filled our irp buffer.
369     //      4) The irp was cancelled.
370     //      5) Some other failure from the USB device object.
371     //
372     ntStatus = urb->status;
373
374     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_nsInterruptUsbIoCompleteRead Status %d\n", ntStatus);
375
376     // if we were not successful, we need to free the int buffer for future use right here
377     // otherwise interrupt data handler will free int buffer after it handle it.
378     if (( ntStatus != STATUS_SUCCESS )) {
379         pDevice->ulBulkInError++;
380         pDevice->intBuf.bInUse = false;
381
382 //        if (ntStatus == USBD_STATUS_CRC) {
383 //            pDevice->ulIntInContCRCError++;
384 //        }
385
386 //        if (ntStatus == STATUS_NOT_CONNECTED )
387 //        {
388             pDevice->fKillEventPollingThread = true;
389 //        }
390         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"IntUSBIoCompleteControl STATUS = %d\n", ntStatus );
391     } else {
392             pDevice->ulIntInBytesRead += (unsigned long) urb->actual_length;
393             pDevice->ulIntInContCRCError = 0;
394             pDevice->bEventAvailable = true;
395             INTnsProcessData(pDevice);
396     }
397
398     STAvUpdateUSBCounter(&pDevice->scStatistic.USB_InterruptStat, ntStatus);
399
400
401     if (pDevice->fKillEventPollingThread != true) {
402        usb_fill_bulk_urb(pDevice->pInterruptURB,
403                       pDevice->usb,
404                       usb_rcvbulkpipe(pDevice->usb, 1),
405                      (void *) pDevice->intBuf.pDataBuf,
406                      MAX_INTERRUPT_SIZE,
407                      s_nsInterruptUsbIoCompleteRead,
408                      pDevice);
409
410         ntStatus = usb_submit_urb(pDevice->pInterruptURB, GFP_ATOMIC);
411         if (ntStatus != 0) {
412             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit int URB failed %d\n", ntStatus);
413            }
414     }
415     //
416     // We return STATUS_MORE_PROCESSING_REQUIRED so that the completion
417     // routine (IofCompleteRequest) will stop working on the irp.
418     //
419     return ;
420 }
421
422 /*
423  * Description:
424  *      Allocates an usb BulkIn  irp and calls USBD.
425  *
426  * Parameters:
427  *  In:
428  *      pDevice     - Pointer to the adapter
429  *  Out:
430  *      none
431  *
432  * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
433  *
434  */
435
436 int PIPEnsBulkInUsbRead(struct vnt_private *pDevice, PRCB pRCB)
437 {
438         int ntStatus = 0;
439         struct urb *pUrb;
440
441
442     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsStartBulkInUsbRead\n");
443
444     if (pDevice->Flags & fMP_DISCONNECTED)
445         return STATUS_FAILURE;
446
447     pDevice->ulBulkInPosted++;
448
449
450         pUrb = pRCB->pUrb;
451     //
452     // Now that we have created the urb, we will send a
453     // request to the USB device object.
454     //
455     if (pRCB->skb == NULL) {
456         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pRCB->skb is null \n");
457         return ntStatus;
458     }
459
460         usb_fill_bulk_urb(pUrb,
461                 pDevice->usb,
462                 usb_rcvbulkpipe(pDevice->usb, 2),
463                 (void *) (pRCB->skb->data),
464                 MAX_TOTAL_SIZE_WITH_ALL_HEADERS,
465                 s_nsBulkInUsbIoCompleteRead,
466                 pRCB);
467
468         ntStatus = usb_submit_urb(pUrb, GFP_ATOMIC);
469         if (ntStatus != 0) {
470                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit Rx URB failed %d\n", ntStatus);
471                 return STATUS_FAILURE ;
472         }
473     pRCB->Ref = 1;
474     pRCB->bBoolInUse= true;
475
476     return ntStatus;
477 }
478
479
480
481
482 /*
483  * Description:
484  *      Complete function of usb BulkIn irp.
485  *
486  * Parameters:
487  *  In:
488  *      pDevice     - Pointer to the adapter
489  *
490  *  Out:
491  *      none
492  *
493  * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
494  *
495  */
496
497 static void s_nsBulkInUsbIoCompleteRead(struct urb *urb)
498 {
499         PRCB pRCB = (PRCB)urb->context;
500         struct vnt_private *pDevice = pRCB->pDevice;
501         unsigned long   bytesRead;
502         int bIndicateReceive = false;
503         int bReAllocSkb = false;
504         int status;
505
506     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkInUsbIoCompleteRead\n");
507     status = urb->status;
508     bytesRead = urb->actual_length;
509
510     if (status) {
511         pDevice->ulBulkInError++;
512         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BULK In failed %d\n", status);
513
514            pDevice->scStatistic.RxFcsErrCnt ++;
515 //todo...xxxxxx
516 //        if (status == USBD_STATUS_CRC) {
517 //            pDevice->ulBulkInContCRCError++;
518 //        }
519 //        if (status == STATUS_DEVICE_NOT_CONNECTED )
520 //        {
521 //            MP_SET_FLAG(pDevice, fMP_DISCONNECTED);
522 //        }
523     } else {
524         if (bytesRead)
525                 bIndicateReceive = true;
526         pDevice->ulBulkInContCRCError = 0;
527         pDevice->ulBulkInBytesRead += bytesRead;
528
529            pDevice->scStatistic.RxOkCnt ++;
530     }
531
532
533     STAvUpdateUSBCounter(&pDevice->scStatistic.USB_BulkInStat, status);
534
535     if (bIndicateReceive) {
536         spin_lock(&pDevice->lock);
537         if (RXbBulkInProcessData(pDevice, pRCB, bytesRead) == true)
538             bReAllocSkb = true;
539         spin_unlock(&pDevice->lock);
540     }
541     pRCB->Ref--;
542     if (pRCB->Ref == 0)
543     {
544         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"RxvFreeNormal %d \n",pDevice->NumRecvFreeList);
545         spin_lock(&pDevice->lock);
546         RXvFreeRCB(pRCB, bReAllocSkb);
547         spin_unlock(&pDevice->lock);
548     }
549
550
551     return;
552 }
553
554 /*
555  * Description:
556  *      Allocates an usb BulkOut  irp and calls USBD.
557  *
558  * Parameters:
559  *  In:
560  *      pDevice     - Pointer to the adapter
561  *  Out:
562  *      none
563  *
564  * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
565  *
566  */
567
568 int PIPEnsSendBulkOut(struct vnt_private *pDevice, PUSB_SEND_CONTEXT pContext)
569 {
570         int status;
571         struct urb          *pUrb;
572
573
574
575     pDevice->bPWBitOn = false;
576
577 /*
578     if (pDevice->pPendingBulkOutContext != NULL) {
579         pDevice->NumContextsQueued++;
580         EnqueueContext(pDevice->FirstTxContextQueue, pDevice->LastTxContextQueue, pContext);
581         status = STATUS_PENDING;
582         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Send pending!\n");
583         return status;
584     }
585 */
586
587     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_nsSendBulkOut\n");
588
589     if (MP_IS_READY(pDevice) && (pDevice->Flags & fMP_POST_WRITES)) {
590
591         pUrb = pContext->pUrb;
592         pDevice->ulBulkOutPosted++;
593 //        pDevice->pPendingBulkOutContext = pContext;
594         usb_fill_bulk_urb(
595                     pUrb,
596                         pDevice->usb,
597                     usb_sndbulkpipe(pDevice->usb, 3),
598                     (void *) &(pContext->Data[0]),
599                         pContext->uBufLen,
600                         s_nsBulkOutIoCompleteWrite,
601                         pContext);
602
603         status = usb_submit_urb(pUrb, GFP_ATOMIC);
604         if (status != 0)
605         {
606                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit Tx URB failed %d\n", status);
607                 pContext->bBoolInUse = false;
608                 return STATUS_FAILURE;
609         }
610         return STATUS_PENDING;
611     }
612     else {
613         pContext->bBoolInUse = false;
614         return STATUS_RESOURCES;
615     }
616 }
617
618 /*
619  * Description: s_nsBulkOutIoCompleteWrite
620  *     1a) Indicate to the protocol the status of the write.
621  *     1b) Return ownership of the packet to the protocol.
622  *
623  *     2)  If any more packets are queue for sending, send another packet
624  *         to USBD.
625  *         If the attempt to send the packet to the driver fails,
626  *         return ownership of the packet to the protocol and
627  *         try another packet (until one succeeds).
628  *
629  * Parameters:
630  *  In:
631  *      pdoUsbDevObj  - pointer to the USB device object which
632  *                      completed the irp
633  *      pIrp          - the irp which was completed by the
634  *                      device object
635  *      pContext      - the context given to IoSetCompletionRoutine
636  *                      before calling IoCallDriver on the irp
637  *                      The pContext is a pointer to the USB device object.
638  *  Out:
639  *      none
640  *
641  * Return Value: STATUS_MORE_PROCESSING_REQUIRED - allows the completion routine
642  *               (IofCompleteRequest) to stop working on the irp.
643  *
644  */
645
646 static void s_nsBulkOutIoCompleteWrite(struct urb *urb)
647 {
648         struct vnt_private *pDevice;
649         int status;
650         CONTEXT_TYPE ContextType;
651         unsigned long ulBufLen;
652         PUSB_SEND_CONTEXT pContext;
653
654
655     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkOutIoCompleteWrite\n");
656     //
657     // The context given to IoSetCompletionRoutine is an USB_CONTEXT struct
658     //
659     pContext = (PUSB_SEND_CONTEXT) urb->context;
660     ASSERT( NULL != pContext );
661
662     pDevice = pContext->pDevice;
663     ContextType = pContext->Type;
664     ulBufLen = pContext->uBufLen;
665
666     if (!netif_device_present(pDevice->dev))
667             return;
668
669    //
670     // Perform various IRP, URB, and buffer 'sanity checks'
671     //
672
673     status = urb->status;
674     //we should have failed, succeeded, or cancelled, but NOT be pending
675     STAvUpdateUSBCounter(&pDevice->scStatistic.USB_BulkOutStat, status);
676
677     if(status == STATUS_SUCCESS) {
678         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Write %d bytes\n",(int)ulBufLen);
679         pDevice->ulBulkOutBytesWrite += ulBufLen;
680         pDevice->ulBulkOutContCRCError = 0;
681         pDevice->nTxDataTimeCout = 0;
682
683     } else {
684         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BULK Out failed %d\n", status);
685         pDevice->ulBulkOutError++;
686     }
687
688 //    pDevice->ulCheckForHangCount = 0;
689 //    pDevice->pPendingBulkOutContext = NULL;
690
691     if ( CONTEXT_DATA_PACKET == ContextType ) {
692         // Indicate to the protocol the status of the sent packet and return
693         // ownership of the packet.
694             if (pContext->pPacket != NULL) {
695                 dev_kfree_skb_irq(pContext->pPacket);
696                 pContext->pPacket = NULL;
697             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"tx  %d bytes\n",(int)ulBufLen);
698             }
699
700         pDevice->dev->trans_start = jiffies;
701
702
703         if (status == STATUS_SUCCESS) {
704             pDevice->packetsSent++;
705         }
706         else {
707             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Send USB error! [%08xh]\n", status);
708             pDevice->packetsSentDropped++;
709         }
710
711     }
712     if (pDevice->bLinkPass == true) {
713         if (netif_queue_stopped(pDevice->dev))
714             netif_wake_queue(pDevice->dev);
715     }
716     pContext->bBoolInUse = false;
717
718     return;
719 }