Merge branch 'perf/core' into perf/urgent, to pick up the latest fixes
[deliverable/linux.git] / drivers / staging / vt6656 / usbpipe.c
CommitLineData
92b96797
FB
1/*
2 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
3 * All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 *
20 * File: usbpipe.c
21 *
22 * Purpose: Handle USB control endpoint
23 *
24 * Author: Warren Hsu
25 *
26 * Date: Mar. 29, 2005
27 *
28 * Functions:
1390b02a 29 * vnt_control_out - Write variable length bytes to MEM/BB/MAC/EEPROM
441c21c3 30 * vnt_control_in - Read variable length bytes from MEM/BB/MAC/EEPROM
285d58c4 31 * vnt_control_out_u8 - Write one byte to MEM/BB/MAC/EEPROM
53742906 32 * vnt_control_in_u8 - Read one byte from MEM/BB/MAC/EEPROM
92b96797
FB
33 * ControlvMaskByte - Read one byte from MEM/BB/MAC/EEPROM and clear/set some bits in the same address
34 *
35 * Revision History:
36 * 04-05-2004 Jerry Chen: Initial release
37 * 11-24-2004 Warren Hsu: Add ControlvWriteByte,ControlvReadByte,ControlvMaskByte
38 *
39 */
40
92b96797 41#include "int.h"
92b96797 42#include "rxtx.h"
92b96797 43#include "dpc.h"
92b96797 44#include "desc.h"
92b96797 45#include "device.h"
62c8526d 46#include "usbpipe.h"
92b96797 47
92b96797
FB
48//endpoint def
49//endpoint 0: control
50//endpoint 1: interrupt
51//endpoint 2: read bulk
52//endpoint 3: write bulk
53
92b96797
FB
54#define USB_CTL_WAIT 500 //ms
55
56#ifndef URB_ASYNC_UNLINK
57#define URB_ASYNC_UNLINK 0
58#endif
59
fe5d00eb
MP
60static void s_nsInterruptUsbIoCompleteRead(struct urb *urb);
61static void s_nsBulkInUsbIoCompleteRead(struct urb *urb);
62static void s_nsBulkOutIoCompleteWrite(struct urb *urb);
92b96797 63
1390b02a 64int vnt_control_out(struct vnt_private *priv, u8 request, u16 value,
0f06a739 65 u16 index, u16 length, u8 *buffer)
92b96797 66{
0f06a739 67 int status = 0;
92b96797 68
0f06a739 69 if (priv->Flags & fMP_DISCONNECTED)
e1feda13
MP
70 return STATUS_FAILURE;
71
0f06a739 72 mutex_lock(&priv->usb_lock);
c91b1869 73
0f06a739
MP
74 status = usb_control_msg(priv->usb,
75 usb_sndctrlpipe(priv->usb, 0), request, 0x40, value,
76 index, buffer, length, USB_CTL_WAIT);
ae5943de 77
0f06a739 78 mutex_unlock(&priv->usb_lock);
92b96797 79
0f06a739 80 if (status < (int)length)
92b96797 81 return STATUS_FAILURE;
ae5943de 82
7021b684 83 return STATUS_SUCCESS;
92b96797
FB
84}
85
285d58c4
MP
86void vnt_control_out_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 data)
87{
88 vnt_control_out(priv, MESSAGE_TYPE_WRITE,
89 reg_off, reg, sizeof(u8), &data);
90}
91
441c21c3 92int vnt_control_in(struct vnt_private *priv, u8 request, u16 value,
9af49fdb 93 u16 index, u16 length, u8 *buffer)
92b96797 94{
9af49fdb 95 int status;
731047f9 96
9af49fdb 97 if (priv->Flags & fMP_DISCONNECTED)
e1feda13 98 return STATUS_FAILURE;
ae5943de 99
9af49fdb 100 mutex_lock(&priv->usb_lock);
c91b1869 101
9af49fdb
MP
102 status = usb_control_msg(priv->usb,
103 usb_rcvctrlpipe(priv->usb, 0), request, 0xc0, value,
104 index, buffer, length, USB_CTL_WAIT);
92b96797 105
9af49fdb 106 mutex_unlock(&priv->usb_lock);
c91b1869 107
9af49fdb 108 if (status < (int)length)
0fb2af35 109 return STATUS_FAILURE;
fe5d00eb 110
0fb2af35 111 return STATUS_SUCCESS;
92b96797
FB
112}
113
53742906
MP
114void vnt_control_in_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 *data)
115{
116 vnt_control_in(priv, MESSAGE_TYPE_READ,
117 reg_off, reg, sizeof(u8), data);
118}
119
92b96797
FB
120/*
121 * Description:
122 * Allocates an usb interrupt in irp and calls USBD.
123 *
124 * Parameters:
125 * In:
126 * pDevice - Pointer to the adapter
127 * Out:
128 * none
129 *
130 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
131 *
132 */
fe5d00eb 133
5f38b783 134int PIPEnsInterruptRead(struct vnt_private *priv)
92b96797 135{
5f38b783 136 int status = STATUS_FAILURE;
92b96797 137
f764e00d 138 if (priv->int_buf.in_use == true)
5f38b783
MP
139 return STATUS_FAILURE;
140
f764e00d 141 priv->int_buf.in_use = true;
5f38b783
MP
142
143 usb_fill_int_urb(priv->pInterruptURB,
144 priv->usb,
b9d93d1c 145 usb_rcvintpipe(priv->usb, 1),
f764e00d 146 priv->int_buf.data_buf,
92b96797
FB
147 MAX_INTERRUPT_SIZE,
148 s_nsInterruptUsbIoCompleteRead,
5f38b783
MP
149 priv,
150 priv->int_interval);
92b96797 151
5f38b783
MP
152 status = usb_submit_urb(priv->pInterruptURB, GFP_ATOMIC);
153 if (status) {
8a660261 154 dev_dbg(&priv->usb->dev, "Submit int URB failed %d\n", status);
f764e00d 155 priv->int_buf.in_use = false;
59858f5e 156 }
92b96797 157
5f38b783 158 return status;
92b96797
FB
159}
160
92b96797
FB
161/*
162 * Description:
163 * Complete function of usb interrupt in irp.
164 *
165 * Parameters:
166 * In:
167 * pDevice - Pointer to the adapter
168 *
169 * Out:
170 * none
171 *
172 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
173 *
174 */
92b96797 175
fe5d00eb 176static void s_nsInterruptUsbIoCompleteRead(struct urb *urb)
92b96797 177{
599e4b5c 178 struct vnt_private *priv = urb->context;
d9ad7a98 179 int status;
92b96797 180
c98fbf90
MP
181 switch (urb->status) {
182 case 0:
183 case -ETIMEDOUT:
184 break;
185 case -ECONNRESET:
186 case -ENOENT:
187 case -ESHUTDOWN:
f764e00d 188 priv->int_buf.in_use = false;
c98fbf90
MP
189 return;
190 default:
191 break;
192 }
193
d9ad7a98 194 status = urb->status;
92b96797 195
d9ad7a98 196 if (status != STATUS_SUCCESS) {
f764e00d 197 priv->int_buf.in_use = false;
92b96797 198
8a660261 199 dev_dbg(&priv->usb->dev, "%s status = %d\n", __func__, status);
d9ad7a98 200 } else {
d9ad7a98
MP
201 INTnsProcessData(priv);
202 }
92b96797 203
d9ad7a98
MP
204 status = usb_submit_urb(priv->pInterruptURB, GFP_ATOMIC);
205 if (status) {
8a660261 206 dev_dbg(&priv->usb->dev, "Submit int URB failed %d\n", status);
247b4b68 207 } else {
f764e00d 208 priv->int_buf.in_use = true;
247b4b68 209 }
749627f2 210
d9ad7a98 211 return;
92b96797
FB
212}
213
214/*
215 * Description:
216 * Allocates an usb BulkIn irp and calls USBD.
217 *
218 * Parameters:
219 * In:
220 * pDevice - Pointer to the adapter
221 * Out:
222 * none
223 *
224 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
225 *
226 */
fe5d00eb 227
0b787d71 228int PIPEnsBulkInUsbRead(struct vnt_private *priv, struct vnt_rcb *rcb)
92b96797 229{
0b787d71
MP
230 int status = 0;
231 struct urb *urb;
92b96797 232
0b787d71
MP
233 if (priv->Flags & fMP_DISCONNECTED)
234 return STATUS_FAILURE;
92b96797 235
0b787d71
MP
236 urb = rcb->pUrb;
237 if (rcb->skb == NULL) {
8a660261 238 dev_dbg(&priv->usb->dev, "rcb->skb is null\n");
0b787d71
MP
239 return status;
240 }
92b96797 241
0b787d71
MP
242 usb_fill_bulk_urb(urb,
243 priv->usb,
244 usb_rcvbulkpipe(priv->usb, 2),
245 (void *) (rcb->skb->data),
92b96797
FB
246 MAX_TOTAL_SIZE_WITH_ALL_HEADERS,
247 s_nsBulkInUsbIoCompleteRead,
0b787d71 248 rcb);
92b96797 249
0b787d71
MP
250 status = usb_submit_urb(urb, GFP_ATOMIC);
251 if (status != 0) {
8a660261 252 dev_dbg(&priv->usb->dev, "Submit Rx URB failed %d\n", status);
92b96797
FB
253 return STATUS_FAILURE ;
254 }
92b96797 255
0b787d71
MP
256 rcb->Ref = 1;
257 rcb->bBoolInUse = true;
258
259 return status;
92b96797
FB
260}
261
92b96797
FB
262/*
263 * Description:
264 * Complete function of usb BulkIn irp.
265 *
266 * Parameters:
267 * In:
268 * pDevice - Pointer to the adapter
269 *
270 * Out:
271 * none
272 *
273 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
274 *
275 */
92b96797 276
fe5d00eb 277static void s_nsBulkInUsbIoCompleteRead(struct urb *urb)
92b96797 278{
599e4b5c 279 struct vnt_rcb *rcb = urb->context;
d4fa2ab0 280 struct vnt_private *priv = rcb->pDevice;
29b02373 281 unsigned long flags;
d4fa2ab0 282 int re_alloc_skb = false;
92b96797 283
67638980
MP
284 switch (urb->status) {
285 case 0:
67638980
MP
286 break;
287 case -ECONNRESET:
288 case -ENOENT:
289 case -ESHUTDOWN:
290 return;
291 case -ETIMEDOUT:
292 default:
8a660261 293 dev_dbg(&priv->usb->dev, "BULK In failed %d\n", urb->status);
67638980
MP
294 break;
295 }
92b96797 296
d4fa2ab0 297 if (urb->actual_length) {
29b02373 298 spin_lock_irqsave(&priv->lock, flags);
d4fa2ab0
MP
299
300 if (RXbBulkInProcessData(priv, rcb, urb->actual_length) == true)
301 re_alloc_skb = true;
302
29b02373 303 spin_unlock_irqrestore(&priv->lock, flags);
d4fa2ab0 304 }
92b96797 305
d4fa2ab0
MP
306 rcb->Ref--;
307 if (rcb->Ref == 0) {
8a660261
MP
308 dev_dbg(&priv->usb->dev,
309 "RxvFreeNormal %d\n", priv->NumRecvFreeList);
310
29b02373 311 spin_lock_irqsave(&priv->lock, flags);
d4fa2ab0
MP
312
313 RXvFreeRCB(rcb, re_alloc_skb);
314
29b02373 315 spin_unlock_irqrestore(&priv->lock, flags);
d4fa2ab0
MP
316 }
317
318 return;
92b96797
FB
319}
320
321/*
322 * Description:
323 * Allocates an usb BulkOut irp and calls USBD.
324 *
325 * Parameters:
326 * In:
327 * pDevice - Pointer to the adapter
328 * Out:
329 * none
330 *
331 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
332 *
333 */
fe5d00eb 334
3f38290e
MP
335int PIPEnsSendBulkOut(struct vnt_private *priv,
336 struct vnt_usb_send_context *context)
92b96797 337{
fe5d00eb 338 int status;
3f38290e 339 struct urb *urb;
92b96797 340
3f38290e 341 priv->bPWBitOn = false;
92b96797 342
3f38290e 343 if (!(MP_IS_READY(priv) && priv->Flags & fMP_POST_WRITES)) {
30a05b39 344 context->in_use = false;
13338303
MP
345 return STATUS_RESOURCES;
346 }
92b96797 347
30a05b39 348 urb = context->urb;
3f38290e
MP
349
350 usb_fill_bulk_urb(urb,
351 priv->usb,
352 usb_sndbulkpipe(priv->usb, 3),
30a05b39
MP
353 context->data,
354 context->buf_len,
da5c99fd 355 s_nsBulkOutIoCompleteWrite,
3f38290e
MP
356 context);
357
358 status = usb_submit_urb(urb, GFP_ATOMIC);
359 if (status != 0) {
8a660261
MP
360 dev_dbg(&priv->usb->dev, "Submit Tx URB failed %d\n", status);
361
30a05b39 362 context->in_use = false;
3f38290e
MP
363 return STATUS_FAILURE;
364 }
365
366 return STATUS_PENDING;
92b96797
FB
367}
368
369/*
370 * Description: s_nsBulkOutIoCompleteWrite
371 * 1a) Indicate to the protocol the status of the write.
372 * 1b) Return ownership of the packet to the protocol.
373 *
374 * 2) If any more packets are queue for sending, send another packet
375 * to USBD.
376 * If the attempt to send the packet to the driver fails,
377 * return ownership of the packet to the protocol and
378 * try another packet (until one succeeds).
379 *
380 * Parameters:
381 * In:
382 * pdoUsbDevObj - pointer to the USB device object which
383 * completed the irp
384 * pIrp - the irp which was completed by the
385 * device object
386 * pContext - the context given to IoSetCompletionRoutine
387 * before calling IoCallDriver on the irp
388 * The pContext is a pointer to the USB device object.
389 * Out:
390 * none
391 *
392 * Return Value: STATUS_MORE_PROCESSING_REQUIRED - allows the completion routine
393 * (IofCompleteRequest) to stop working on the irp.
394 *
395 */
fe5d00eb
MP
396
397static void s_nsBulkOutIoCompleteWrite(struct urb *urb)
92b96797 398{
599e4b5c 399 struct vnt_usb_send_context *context = urb->context;
30a05b39 400 struct vnt_private *priv = context->priv;
1450ba62 401 u8 context_type = context->type;
92b96797 402
e8152bfb
MP
403 switch (urb->status) {
404 case 0:
8a660261 405 dev_dbg(&priv->usb->dev, "Write %d bytes\n", context->buf_len);
e8152bfb
MP
406 break;
407 case -ECONNRESET:
408 case -ENOENT:
409 case -ESHUTDOWN:
30a05b39 410 context->in_use = false;
e8152bfb 411 return;
d1b2a11d 412 case -ETIMEDOUT:
e8152bfb 413 default:
8a660261 414 dev_dbg(&priv->usb->dev, "BULK Out failed %d\n", urb->status);
e8152bfb
MP
415 break;
416 }
417
21aa212c
MP
418 if (!netif_device_present(priv->dev))
419 return;
92b96797 420
21aa212c 421 if (CONTEXT_DATA_PACKET == context_type) {
30a05b39
MP
422 if (context->skb != NULL) {
423 dev_kfree_skb_irq(context->skb);
424 context->skb = NULL;
8a660261
MP
425 dev_dbg(&priv->usb->dev,
426 "tx %d bytes\n", context->buf_len);
21aa212c 427 }
92b96797 428
21aa212c 429 priv->dev->trans_start = jiffies;
21aa212c 430 }
92b96797 431
21aa212c
MP
432 if (priv->bLinkPass == true) {
433 if (netif_queue_stopped(priv->dev))
434 netif_wake_queue(priv->dev);
435 }
436
30a05b39 437 context->in_use = false;
21aa212c
MP
438
439 return;
92b96797 440}
This page took 0.568734 seconds and 5 git commands to generate.