Merge branch 'fix/hda' into for-linus
[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 /*---------------------  Static Definitions -------------------------*/
49 //endpoint def
50 //endpoint 0: control
51 //endpoint 1: interrupt
52 //endpoint 2: read bulk
53 //endpoint 3: write bulk
54
55 //RequestType:
56 //#define REQUEST_OUT       (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE) // 0x40
57 //#define REQUEST_IN        (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE )  //0xc0
58 //static int          msglevel                =MSG_LEVEL_DEBUG;
59 static int          msglevel                =MSG_LEVEL_INFO;
60
61
62 #define USB_CTL_WAIT   500 //ms
63
64 #ifndef URB_ASYNC_UNLINK
65 #define URB_ASYNC_UNLINK    0
66 #endif
67
68 /*---------------------  Static Classes  ----------------------------*/
69
70 /*---------------------  Static Variables  --------------------------*/
71
72 /*---------------------  Static Functions  --------------------------*/
73 static
74 VOID
75 s_nsInterruptUsbIoCompleteRead(
76     IN struct urb *urb
77     );
78
79
80 static
81 VOID
82 s_nsBulkInUsbIoCompleteRead(
83     IN struct urb *urb
84     );
85
86
87 static
88 VOID
89 s_nsBulkOutIoCompleteWrite(
90     IN struct urb *urb
91     );
92
93
94 static
95 VOID
96 s_nsControlInUsbIoCompleteRead(
97     IN struct urb *urb
98     );
99
100 static
101 VOID
102 s_nsControlInUsbIoCompleteWrite(
103     IN struct urb *urb
104     );
105
106 /*---------------------  Export Variables  --------------------------*/
107
108 /*---------------------  Export Functions  --------------------------*/
109
110
111
112 NTSTATUS
113 PIPEnsControlOutAsyn(
114     IN PSDevice     pDevice,
115     IN BYTE         byRequest,
116     IN WORD         wValue,
117     IN WORD         wIndex,
118     IN WORD         wLength,
119     IN PBYTE        pbyBuffer
120     )
121 {
122     NTSTATUS                ntStatus;
123
124
125     if (MP_TEST_FLAG(pDevice, fMP_DISCONNECTED))
126         return STATUS_FAILURE;
127
128
129     if (MP_TEST_FLAG(pDevice, fMP_CONTROL_WRITES)) {
130         return STATUS_FAILURE;
131     }
132
133     if (in_interrupt()) {
134         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"in_interrupt return ..byRequest %x\n", byRequest);
135         return STATUS_FAILURE;
136     }
137
138     ntStatus = usb_control_msg(
139                             pDevice->usb,
140                             usb_sndctrlpipe(pDevice->usb , 0),
141                             byRequest,
142                             0x40, // RequestType
143                             wValue,
144                             wIndex,
145                             (PVOID) pbyBuffer,
146                             wLength,
147                             HZ
148                           );
149     if (ntStatus >= 0) {
150         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"usb_sndctrlpipe ntStatus= %d\n", ntStatus);
151         ntStatus = 0;
152     } else {
153         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"usb_sndctrlpipe fail, ntStatus= %d\n", ntStatus);
154     }
155
156     return ntStatus;
157 }
158
159
160
161
162
163 NTSTATUS
164 PIPEnsControlOut(
165     IN PSDevice     pDevice,
166     IN BYTE         byRequest,
167     IN WORD         wValue,
168     IN WORD         wIndex,
169     IN WORD         wLength,
170     IN PBYTE        pbyBuffer
171     )
172 {
173     NTSTATUS            ntStatus = 0;
174     int ii;
175
176
177     if (MP_TEST_FLAG(pDevice, fMP_DISCONNECTED))
178         return STATUS_FAILURE;
179
180     if (MP_TEST_FLAG(pDevice, fMP_CONTROL_WRITES)) {
181         return STATUS_FAILURE;
182     }
183
184         pDevice->sUsbCtlRequest.bRequestType = 0x40;
185         pDevice->sUsbCtlRequest.bRequest = byRequest;
186         pDevice->sUsbCtlRequest.wValue = cpu_to_le16p(&wValue);
187         pDevice->sUsbCtlRequest.wIndex = cpu_to_le16p(&wIndex);
188         pDevice->sUsbCtlRequest.wLength = cpu_to_le16p(&wLength);
189         pDevice->pControlURB->transfer_flags |= URB_ASYNC_UNLINK;
190     pDevice->pControlURB->actual_length = 0;
191     // Notice, pbyBuffer limited point to variable buffer, can't be constant.
192         usb_fill_control_urb(pDevice->pControlURB, pDevice->usb,
193                          usb_sndctrlpipe(pDevice->usb , 0), (char *) &pDevice->sUsbCtlRequest,
194                          pbyBuffer, wLength, s_nsControlInUsbIoCompleteWrite, pDevice);
195
196         if ((ntStatus = usb_submit_urb(pDevice->pControlURB, GFP_ATOMIC)) != 0) {
197                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"control send request submission failed: %d\n", ntStatus);
198                 return STATUS_FAILURE;
199         }
200         else {
201             MP_SET_FLAG(pDevice, fMP_CONTROL_WRITES);
202         }
203         spin_unlock_irq(&pDevice->lock);
204     for (ii = 0; ii <= USB_CTL_WAIT; ii ++) {
205         if (MP_TEST_FLAG(pDevice, fMP_CONTROL_WRITES))
206             mdelay(1);
207         else
208             break;
209         if (ii >= USB_CTL_WAIT) {
210             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"control send request submission timeout \n");
211             spin_lock_irq(&pDevice->lock);
212             MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES);
213             return STATUS_FAILURE;
214         }
215     }
216         spin_lock_irq(&pDevice->lock);
217
218     return STATUS_SUCCESS;
219 }
220
221
222
223
224 NTSTATUS
225 PIPEnsControlIn(
226     IN PSDevice     pDevice,
227     IN BYTE         byRequest,
228     IN WORD         wValue,
229     IN WORD         wIndex,
230     IN WORD         wLength,
231     IN OUT  PBYTE   pbyBuffer
232     )
233 {
234     NTSTATUS            ntStatus = 0;
235     int ii;
236
237     if (MP_TEST_FLAG(pDevice, fMP_DISCONNECTED))
238         return STATUS_FAILURE;
239
240     if (MP_TEST_FLAG(pDevice, fMP_CONTROL_READS)) {
241         return STATUS_FAILURE;
242     }
243         pDevice->sUsbCtlRequest.bRequestType = 0xC0;
244         pDevice->sUsbCtlRequest.bRequest = byRequest;
245         pDevice->sUsbCtlRequest.wValue = cpu_to_le16p(&wValue);
246         pDevice->sUsbCtlRequest.wIndex = cpu_to_le16p(&wIndex);
247         pDevice->sUsbCtlRequest.wLength = cpu_to_le16p(&wLength);
248         pDevice->pControlURB->transfer_flags |= URB_ASYNC_UNLINK;
249     pDevice->pControlURB->actual_length = 0;
250         usb_fill_control_urb(pDevice->pControlURB, pDevice->usb,
251                          usb_rcvctrlpipe(pDevice->usb , 0), (char *) &pDevice->sUsbCtlRequest,
252                          pbyBuffer, wLength, s_nsControlInUsbIoCompleteRead, pDevice);
253
254         if ((ntStatus = usb_submit_urb(pDevice->pControlURB, GFP_ATOMIC)) != 0) {
255                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"control request submission failed: %d\n", ntStatus);
256         }else {
257                 MP_SET_FLAG(pDevice, fMP_CONTROL_READS);
258     }
259
260         spin_unlock_irq(&pDevice->lock);
261     for (ii = 0; ii <= USB_CTL_WAIT; ii ++) {
262         if (MP_TEST_FLAG(pDevice, fMP_CONTROL_READS))
263             mdelay(1);
264         else {
265             break;
266         }
267         if (ii >= USB_CTL_WAIT) {
268             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"control rcv request submission timeout \n");
269             spin_lock_irq(&pDevice->lock);
270             MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS);
271             return STATUS_FAILURE;
272         }
273     }
274         spin_lock_irq(&pDevice->lock);
275
276     return ntStatus;
277 }
278
279 static
280 VOID
281 s_nsControlInUsbIoCompleteWrite(
282     IN struct urb *urb
283     )
284 {
285     PSDevice        pDevice;
286
287         pDevice = urb->context;
288         switch (urb->status) {
289         case 0:
290                 break;
291         case -EINPROGRESS:
292                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl write urb status EINPROGRESS%d\n", urb->status);
293                 break;
294         case -ENOENT:
295                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl write urb status ENOENT %d\n", urb->status);
296                 break;
297         default:
298                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl write urb status %d\n", urb->status);
299         }
300
301     MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES);
302 }
303
304
305
306 /*
307  * Description:
308  *      Complete function of usb Control callback
309  *
310  * Parameters:
311  *  In:
312  *      pDevice     - Pointer to the adapter
313  *
314  *  Out:
315  *      none
316  *
317  * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
318  *
319  */
320 static
321 VOID
322 s_nsControlInUsbIoCompleteRead(
323     IN struct urb *urb
324     )
325 {
326     PSDevice        pDevice;
327
328         pDevice = urb->context;
329         switch (urb->status) {
330         case 0:
331                 break;
332         case -EINPROGRESS:
333                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl read urb status EINPROGRESS%d\n", urb->status);
334                 break;
335         case -ENOENT:
336                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl read urb status = ENOENT %d\n", urb->status);
337                 break;
338         default:
339                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl read urb status %d\n", urb->status);
340         }
341
342     MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS);
343 }
344
345
346
347
348 /*
349  * Description:
350  *      Allocates an usb interrupt in irp and calls USBD.
351  *
352  * Parameters:
353  *  In:
354  *      pDevice     - Pointer to the adapter
355  *  Out:
356  *      none
357  *
358  * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
359  *
360  */
361 NTSTATUS
362 PIPEnsInterruptRead(
363     IN PSDevice pDevice
364     )
365 {
366     NTSTATUS            ntStatus = STATUS_FAILURE;
367
368
369     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsStartInterruptUsbRead()\n");
370
371     if(pDevice->intBuf.bInUse == TRUE){
372         return (STATUS_FAILURE);
373     }
374     pDevice->intBuf.bInUse = TRUE;
375 //    pDevice->bEventAvailable = FALSE;
376     pDevice->ulIntInPosted++;
377
378     //
379     // Now that we have created the urb, we will send a
380     // request to the USB device object.
381     //
382 #if 0            //reserve int URB submit
383         usb_fill_int_urb(pDevice->pInterruptURB,
384                          pDevice->usb,
385                          usb_rcvintpipe(pDevice->usb, 1),
386                          (PVOID) pDevice->intBuf.pDataBuf,
387                          MAX_INTERRUPT_SIZE,
388                          s_nsInterruptUsbIoCompleteRead,
389                          pDevice,
390                          pDevice->int_interval
391                          );
392 #else            //replace int URB submit by bulk transfer
393 #ifndef Safe_Close
394         usb_fill_int_urb(pDevice->pInterruptURB,
395                          pDevice->usb,
396                          usb_rcvintpipe(pDevice->usb, 1),
397                          (PVOID) pDevice->intBuf.pDataBuf,
398                          MAX_INTERRUPT_SIZE,
399                          s_nsInterruptUsbIoCompleteRead,
400                          pDevice,
401                          pDevice->int_interval
402                          );
403 #else
404
405     pDevice->pInterruptURB->interval = pDevice->int_interval;
406
407 usb_fill_bulk_urb(pDevice->pInterruptURB,
408                 pDevice->usb,
409                 usb_rcvbulkpipe(pDevice->usb, 1),
410                 (PVOID) pDevice->intBuf.pDataBuf,
411                 MAX_INTERRUPT_SIZE,
412                 s_nsInterruptUsbIoCompleteRead,
413                 pDevice);
414 #endif
415 #endif
416
417         if ((ntStatus = usb_submit_urb(pDevice->pInterruptURB, GFP_ATOMIC)) != 0) {
418             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit int URB failed %d\n", ntStatus);
419     }
420
421     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"<----s_nsStartInterruptUsbRead Return(%x)\n",ntStatus);
422     return ntStatus;
423 }
424
425
426 /*
427  * Description:
428  *      Complete function of usb interrupt in irp.
429  *
430  * Parameters:
431  *  In:
432  *      pDevice     - Pointer to the adapter
433  *
434  *  Out:
435  *      none
436  *
437  * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
438  *
439  */
440 static
441 VOID
442 s_nsInterruptUsbIoCompleteRead(
443     IN struct urb *urb
444     )
445
446 {
447     PSDevice        pDevice;
448     NTSTATUS        ntStatus;
449
450
451     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsInterruptUsbIoCompleteRead\n");
452     //
453     // The context given to IoSetCompletionRoutine is the receive buffer object
454     //
455     pDevice = (PSDevice)urb->context;
456
457     //
458     // We have a number of cases:
459     //      1) The USB read timed out and we received no data.
460     //      2) The USB read timed out and we received some data.
461     //      3) The USB read was successful and fully filled our irp buffer.
462     //      4) The irp was cancelled.
463     //      5) Some other failure from the USB device object.
464     //
465     ntStatus = urb->status;
466
467     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_nsInterruptUsbIoCompleteRead Status %d\n", ntStatus);
468
469     // if we were not successful, we need to free the int buffer for future use right here
470     // otherwise interrupt data handler will free int buffer after it handle it.
471     if (( ntStatus != STATUS_SUCCESS )) {
472         pDevice->ulBulkInError++;
473         pDevice->intBuf.bInUse = FALSE;
474
475 //        if (ntStatus == USBD_STATUS_CRC) {
476 //            pDevice->ulIntInContCRCError++;
477 //        }
478
479 //        if (ntStatus == STATUS_NOT_CONNECTED )
480 //        {
481             pDevice->fKillEventPollingThread = TRUE;
482 //        }
483         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"IntUSBIoCompleteControl STATUS = %d\n", ntStatus );
484     }
485     else {
486         pDevice->ulIntInBytesRead += (ULONG)urb->actual_length;
487         pDevice->ulIntInContCRCError = 0;
488         pDevice->bEventAvailable = TRUE;
489         INTnsProcessData(pDevice);
490     }
491
492     STAvUpdateUSBCounter(&pDevice->scStatistic.USB_InterruptStat, ntStatus);
493
494
495     if (pDevice->fKillEventPollingThread != TRUE) {
496    #if 0               //reserve int URB submit
497         if ((ntStatus = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
498             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Re-Submit int URB failed %d\n", ntStatus);
499     }
500    #else                                                                                     //replace int URB submit by bulk transfer
501     #ifdef Safe_Close
502        usb_fill_bulk_urb(pDevice->pInterruptURB,
503                       pDevice->usb,
504                       usb_rcvbulkpipe(pDevice->usb, 1),
505                      (PVOID) pDevice->intBuf.pDataBuf,
506                      MAX_INTERRUPT_SIZE,
507                      s_nsInterruptUsbIoCompleteRead,
508                      pDevice);
509
510         if ((ntStatus = usb_submit_urb(pDevice->pInterruptURB, GFP_ATOMIC)) != 0) {
511             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit int URB failed %d\n", ntStatus);
512            }
513
514     #else
515         tasklet_schedule(&pDevice->EventWorkItem);
516     #endif
517 #endif
518     }
519     //
520     // We return STATUS_MORE_PROCESSING_REQUIRED so that the completion
521     // routine (IofCompleteRequest) will stop working on the irp.
522     //
523     return ;
524 }
525
526 /*
527  * Description:
528  *      Allocates an usb BulkIn  irp and calls USBD.
529  *
530  * Parameters:
531  *  In:
532  *      pDevice     - Pointer to the adapter
533  *  Out:
534  *      none
535  *
536  * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
537  *
538  */
539 NTSTATUS
540 PIPEnsBulkInUsbRead(
541     IN PSDevice pDevice,
542     IN PRCB     pRCB
543     )
544 {
545     NTSTATUS            ntStatus= 0;
546     struct urb          *pUrb;
547
548
549     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsStartBulkInUsbRead\n");
550
551     if (MP_TEST_FLAG(pDevice, fMP_DISCONNECTED))
552         return STATUS_FAILURE;
553
554     pDevice->ulBulkInPosted++;
555
556
557         pUrb = pRCB->pUrb;
558     //
559     // Now that we have created the urb, we will send a
560     // request to the USB device object.
561     //
562     if (pRCB->skb == NULL) {
563         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pRCB->skb is null \n");
564         return ntStatus;
565     }
566
567         usb_fill_bulk_urb(pUrb,
568                 pDevice->usb,
569                 usb_rcvbulkpipe(pDevice->usb, 2),
570                 (PVOID) (pRCB->skb->data),
571                 MAX_TOTAL_SIZE_WITH_ALL_HEADERS,
572                 s_nsBulkInUsbIoCompleteRead,
573                 pRCB);
574
575         if((ntStatus = usb_submit_urb(pUrb, GFP_ATOMIC)) != 0){
576                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit Rx URB failed %d\n", ntStatus);
577                 return STATUS_FAILURE ;
578         }
579     pRCB->Ref = 1;
580     pRCB->bBoolInUse= TRUE;
581
582     return ntStatus;
583 }
584
585
586
587
588 /*
589  * Description:
590  *      Complete function of usb BulkIn irp.
591  *
592  * Parameters:
593  *  In:
594  *      pDevice     - Pointer to the adapter
595  *
596  *  Out:
597  *      none
598  *
599  * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
600  *
601  */
602 static
603 VOID
604 s_nsBulkInUsbIoCompleteRead(
605     IN struct urb *urb
606     )
607
608 {
609     PRCB    pRCB = (PRCB)urb->context;
610     PSDevice pDevice = (PSDevice)pRCB->pDevice;
611     ULONG   bytesRead;
612     BOOL    bIndicateReceive = FALSE;
613     BOOL    bReAllocSkb = FALSE;
614     NTSTATUS    status;
615
616
617
618     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkInUsbIoCompleteRead\n");
619     status = urb->status;
620     bytesRead = urb->actual_length;
621
622     if (status) {
623         pDevice->ulBulkInError++;
624         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BULK In failed %d\n", status);
625
626         #ifdef Calcu_LinkQual
627            pDevice->scStatistic.RxFcsErrCnt ++;
628         #endif
629 //todo...xxxxxx
630 //        if (status == USBD_STATUS_CRC) {
631 //            pDevice->ulBulkInContCRCError++;
632 //        }
633 //        if (status == STATUS_DEVICE_NOT_CONNECTED )
634 //        {
635 //            MP_SET_FLAG(pDevice, fMP_DISCONNECTED);
636 //        }
637     } else {
638         bIndicateReceive = TRUE;
639         pDevice->ulBulkInContCRCError = 0;
640         pDevice->ulBulkInBytesRead += bytesRead;
641
642         #ifdef Calcu_LinkQual
643            pDevice->scStatistic.RxOkCnt ++;
644         #endif
645     }
646
647
648     STAvUpdateUSBCounter(&pDevice->scStatistic.USB_BulkInStat, status);
649
650     if (bIndicateReceive) {
651         spin_lock(&pDevice->lock);
652         if (RXbBulkInProcessData(pDevice, pRCB, bytesRead) == TRUE)
653             bReAllocSkb = TRUE;
654         spin_unlock(&pDevice->lock);
655     }
656     pRCB->Ref--;
657     if (pRCB->Ref == 0)
658     {
659         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"RxvFreeNormal %d \n",pDevice->NumRecvFreeList);
660         spin_lock(&pDevice->lock);
661         RXvFreeRCB(pRCB, bReAllocSkb);
662         spin_unlock(&pDevice->lock);
663     }
664
665
666     return;
667 }
668
669 /*
670  * Description:
671  *      Allocates an usb BulkOut  irp and calls USBD.
672  *
673  * Parameters:
674  *  In:
675  *      pDevice     - Pointer to the adapter
676  *  Out:
677  *      none
678  *
679  * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
680  *
681  */
682 NDIS_STATUS
683 PIPEnsSendBulkOut(
684     IN  PSDevice pDevice,
685     IN  PUSB_SEND_CONTEXT pContext
686     )
687 {
688     NTSTATUS            status;
689     struct urb          *pUrb;
690
691
692
693     pDevice->bPWBitOn = FALSE;
694
695 /*
696     if (pDevice->pPendingBulkOutContext != NULL) {
697         pDevice->NumContextsQueued++;
698         EnqueueContext(pDevice->FirstTxContextQueue, pDevice->LastTxContextQueue, pContext);
699         status = STATUS_PENDING;
700         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Send pending!\n");
701         return status;
702     }
703 */
704
705     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_nsSendBulkOut\n");
706
707     if(MP_IS_READY(pDevice) && MP_TEST_FLAG(pDevice, fMP_POST_WRITES)) {
708
709         pUrb = pContext->pUrb;
710         pDevice->ulBulkOutPosted++;
711 //        pDevice->pPendingBulkOutContext = pContext;
712         usb_fill_bulk_urb(
713                     pUrb,
714                         pDevice->usb,
715                         usb_sndbulkpipe(pDevice->usb, 3),
716                         (PVOID) &(pContext->Data[0]),
717                         pContext->uBufLen,
718                         s_nsBulkOutIoCompleteWrite,
719                         pContext);
720
721         if((status = usb_submit_urb(pUrb, GFP_ATOMIC))!=0)
722         {
723                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit Tx URB failed %d\n", status);
724                 return STATUS_FAILURE;
725         }
726         return STATUS_PENDING;
727     }
728     else {
729         pContext->bBoolInUse = FALSE;
730         return STATUS_RESOURCES;
731     }
732 }
733
734 /*
735  * Description: s_nsBulkOutIoCompleteWrite
736  *     1a) Indicate to the protocol the status of the write.
737  *     1b) Return ownership of the packet to the protocol.
738  *
739  *     2)  If any more packets are queue for sending, send another packet
740  *         to USBD.
741  *         If the attempt to send the packet to the driver fails,
742  *         return ownership of the packet to the protocol and
743  *         try another packet (until one succeeds).
744  *
745  * Parameters:
746  *  In:
747  *      pdoUsbDevObj  - pointer to the USB device object which
748  *                      completed the irp
749  *      pIrp          - the irp which was completed by the
750  *                      device object
751  *      pContext      - the context given to IoSetCompletionRoutine
752  *                      before calling IoCallDriver on the irp
753  *                      The pContext is a pointer to the USB device object.
754  *  Out:
755  *      none
756  *
757  * Return Value: STATUS_MORE_PROCESSING_REQUIRED - allows the completion routine
758  *               (IofCompleteRequest) to stop working on the irp.
759  *
760  */
761 static
762 VOID
763 s_nsBulkOutIoCompleteWrite(
764     IN struct urb *urb
765     )
766 {
767     PSDevice            pDevice;
768     NTSTATUS            status;
769     CONTEXT_TYPE        ContextType;
770     ULONG               ulBufLen;
771     PUSB_SEND_CONTEXT   pContext;
772
773
774     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkOutIoCompleteWrite\n");
775     //
776     // The context given to IoSetCompletionRoutine is an USB_CONTEXT struct
777     //
778     pContext = (PUSB_SEND_CONTEXT) urb->context;
779     ASSERT( NULL != pContext );
780
781     pDevice = pContext->pDevice;
782     ContextType = pContext->Type;
783     ulBufLen = pContext->uBufLen;
784
785     if (!netif_device_present(pDevice->dev))
786             return;
787
788    //
789     // Perform various IRP, URB, and buffer 'sanity checks'
790     //
791
792     status = urb->status;
793     //we should have failed, succeeded, or cancelled, but NOT be pending
794     STAvUpdateUSBCounter(&pDevice->scStatistic.USB_BulkOutStat, status);
795
796     if(status == STATUS_SUCCESS) {
797         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Write %d bytes\n",(int)ulBufLen);
798         pDevice->ulBulkOutBytesWrite += ulBufLen;
799         pDevice->ulBulkOutContCRCError = 0;
800         //2007-0115-06<Add>by MikeLiu
801            #ifdef TxInSleep
802              pDevice->nTxDataTimeCout = 0;
803            #endif
804
805     } else {
806         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BULK Out failed %d\n", status);
807         pDevice->ulBulkOutError++;
808     }
809
810 //    pDevice->ulCheckForHangCount = 0;
811 //    pDevice->pPendingBulkOutContext = NULL;
812
813     if ( CONTEXT_DATA_PACKET == ContextType ) {
814         // Indicate to the protocol the status of the sent packet and return
815         // ownership of the packet.
816             if (pContext->pPacket != NULL) {
817                 dev_kfree_skb_irq(pContext->pPacket);
818                 pContext->pPacket = NULL;
819             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"tx  %d bytes\n",(int)ulBufLen);
820             }
821
822         pDevice->dev->trans_start = jiffies;
823
824
825         if (status == STATUS_SUCCESS) {
826             pDevice->packetsSent++;
827         }
828         else {
829             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Send USB error! [%08xh]\n", status);
830             pDevice->packetsSentDropped++;
831         }
832
833     }
834     if (pDevice->bLinkPass == TRUE) {
835         if (netif_queue_stopped(pDevice->dev))
836             netif_wake_queue(pDevice->dev);
837     }
838     pContext->bBoolInUse = FALSE;
839
840     return;
841 }