]> Git Repo - linux.git/blob - drivers/staging/vt6656/usbpipe.c
clocksource: Exynos_mct: Use irq_force_affinity() in cpu bringup
[linux.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 #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                 __releases(&pDevice->lock)
109                 __acquires(&pDevice->lock)
110 {
111         int ntStatus = 0;
112         int ii;
113
114     if (pDevice->Flags & fMP_DISCONNECTED)
115         return STATUS_FAILURE;
116
117     if (pDevice->Flags & fMP_CONTROL_WRITES)
118         return STATUS_FAILURE;
119
120         if (pDevice->Flags & fMP_CONTROL_READS)
121                 return STATUS_FAILURE;
122
123         if (pDevice->pControlURB->hcpriv)
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         __releases(&pDevice->lock)
173         __acquires(&pDevice->lock)
174 {
175         int ntStatus = 0;
176         int ii;
177
178     if (pDevice->Flags & fMP_DISCONNECTED)
179         return STATUS_FAILURE;
180
181     if (pDevice->Flags & fMP_CONTROL_READS)
182         return STATUS_FAILURE;
183
184         if (pDevice->Flags & fMP_CONTROL_WRITES)
185                 return STATUS_FAILURE;
186
187         if (pDevice->pControlURB->hcpriv)
188                 return STATUS_FAILURE;
189
190         MP_SET_FLAG(pDevice, fMP_CONTROL_READS);
191
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
203         ntStatus = usb_submit_urb(pDevice->pControlURB, GFP_ATOMIC);
204         if (ntStatus != 0) {
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         }
210
211         spin_unlock_irq(&pDevice->lock);
212     for (ii = 0; ii <= USB_CTL_WAIT; ii ++) {
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");
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
232 static void s_nsControlInUsbIoCompleteWrite(struct urb *urb)
233 {
234         struct vnt_private *pDevice = (struct vnt_private *)urb->context;
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
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  */
267
268 static void s_nsControlInUsbIoCompleteRead(struct urb *urb)
269 {
270         struct vnt_private *pDevice = (struct vnt_private *)urb->context;
271
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
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 *priv)
303 {
304         int status = STATUS_FAILURE;
305
306         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
307                         "---->s_nsStartInterruptUsbRead()\n");
308
309         if (priv->int_buf.in_use == true)
310                 return STATUS_FAILURE;
311
312         priv->int_buf.in_use = true;
313
314         usb_fill_int_urb(priv->pInterruptURB,
315                 priv->usb,
316                 usb_rcvintpipe(priv->usb, 1),
317                 priv->int_buf.data_buf,
318                 MAX_INTERRUPT_SIZE,
319                 s_nsInterruptUsbIoCompleteRead,
320                 priv,
321                 priv->int_interval);
322
323         status = usb_submit_urb(priv->pInterruptURB, GFP_ATOMIC);
324         if (status) {
325                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
326                         "Submit int URB failed %d\n", status);
327                 priv->int_buf.in_use = false;
328         }
329
330         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
331                 "<----s_nsStartInterruptUsbRead Return(%x)\n", status);
332
333         return status;
334 }
335
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  */
350
351 static void s_nsInterruptUsbIoCompleteRead(struct urb *urb)
352 {
353         struct vnt_private *priv = urb->context;
354         int status;
355
356         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
357                         "---->s_nsInterruptUsbIoCompleteRead\n");
358
359         switch (urb->status) {
360         case 0:
361         case -ETIMEDOUT:
362                 break;
363         case -ECONNRESET:
364         case -ENOENT:
365         case -ESHUTDOWN:
366                 priv->int_buf.in_use = false;
367                 return;
368         default:
369                 break;
370         }
371
372         status = urb->status;
373
374         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
375                 "s_nsInterruptUsbIoCompleteRead Status %d\n", status);
376
377         if (status != STATUS_SUCCESS) {
378                 priv->int_buf.in_use = false;
379
380                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
381                         "IntUSBIoCompleteControl STATUS = %d\n", status);
382         } else {
383                 INTnsProcessData(priv);
384         }
385
386         status = usb_submit_urb(priv->pInterruptURB, GFP_ATOMIC);
387         if (status) {
388                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
389                         "Submit int URB failed %d\n", status);
390         } else {
391                 priv->int_buf.in_use = true;
392         }
393
394         return;
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  */
410
411 int PIPEnsBulkInUsbRead(struct vnt_private *priv, struct vnt_rcb *rcb)
412 {
413         int status = 0;
414         struct urb *urb;
415
416         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsStartBulkInUsbRead\n");
417
418         if (priv->Flags & fMP_DISCONNECTED)
419                 return STATUS_FAILURE;
420
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         }
426
427         usb_fill_bulk_urb(urb,
428                 priv->usb,
429                 usb_rcvbulkpipe(priv->usb, 2),
430                 (void *) (rcb->skb->data),
431                 MAX_TOTAL_SIZE_WITH_ALL_HEADERS,
432                 s_nsBulkInUsbIoCompleteRead,
433                 rcb);
434
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);
439                 return STATUS_FAILURE ;
440         }
441
442         rcb->Ref = 1;
443         rcb->bBoolInUse = true;
444
445         return status;
446 }
447
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  */
462
463 static void s_nsBulkInUsbIoCompleteRead(struct urb *urb)
464 {
465         struct vnt_rcb *rcb = urb->context;
466         struct vnt_private *priv = rcb->pDevice;
467         int re_alloc_skb = false;
468
469         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkInUsbIoCompleteRead\n");
470
471         switch (urb->status) {
472         case 0:
473                 break;
474         case -ECONNRESET:
475         case -ENOENT:
476         case -ESHUTDOWN:
477                 return;
478         case -ETIMEDOUT:
479         default:
480                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
481                                 "BULK In failed %d\n", urb->status);
482                 break;
483         }
484
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         }
493
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;
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  */
521
522 int PIPEnsSendBulkOut(struct vnt_private *priv,
523                                 struct vnt_usb_send_context *context)
524 {
525         int status;
526         struct urb *urb;
527
528         priv->bPWBitOn = false;
529
530         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_nsSendBulkOut\n");
531
532         if (!(MP_IS_READY(priv) && priv->Flags & fMP_POST_WRITES)) {
533                 context->bBoolInUse = false;
534                 return STATUS_RESOURCES;
535         }
536
537         urb = context->pUrb;
538
539         usb_fill_bulk_urb(urb,
540                         priv->usb,
541                         usb_sndbulkpipe(priv->usb, 3),
542                         context->Data,
543                         context->uBufLen,
544                         s_nsBulkOutIoCompleteWrite,
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;
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  */
585
586 static void s_nsBulkOutIoCompleteWrite(struct urb *urb)
587 {
588         struct vnt_usb_send_context *context = urb->context;
589         struct vnt_private *priv = context->pDevice;
590         u8 context_type = context->type;
591
592         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkOutIoCompleteWrite\n");
593
594         switch (urb->status) {
595         case 0:
596                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
597                         "Write %d bytes\n", context->uBufLen);
598                 break;
599         case -ECONNRESET:
600         case -ENOENT:
601         case -ESHUTDOWN:
602                 context->bBoolInUse = false;
603                 return;
604         case -ETIMEDOUT:
605         default:
606                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
607                                 "BULK Out failed %d\n", urb->status);
608                 break;
609         }
610
611         if (!netif_device_present(priv->dev))
612                 return;
613
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
619                                 "tx  %d bytes\n", context->uBufLen);
620                 }
621
622                 priv->dev->trans_start = jiffies;
623         }
624
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;
633 }
This page took 0.064985 seconds and 4 git commands to generate.