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