Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Side by Side Diff: drivers/net/usb/gobi/qmidevice.c

Issue 6539018: CHROMIUM: Add gobi driver. (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/kernel.git@master
Patch Set: Remove config changes. Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « drivers/net/usb/gobi/qmidevice.h ('k') | drivers/net/usb/gobi/structs.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /* qmidevice.c - gobi QMI device
2 * Copyright (c) 2010, Code Aurora Forum. All rights reserved.
3
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301, USA.
17 */
18
19 #include "qmidevice.h"
20 #include "qcusbnet.h"
21
22 struct readreq {
23 struct list_head node;
24 void *data;
25 u16 tid;
26 u16 size;
27 };
28
29 struct notifyreq {
30 struct list_head node;
31 void (*func)(struct qcusbnet *, u16, void *);
32 u16 tid;
33 void *data;
34 };
35
36 struct client {
37 struct list_head node;
38 u16 cid;
39 struct list_head reads;
40 struct list_head notifies;
41 struct list_head urbs;
42 };
43
44 struct urbsetup {
45 u8 type;
46 u8 code;
47 u16 value;
48 u16 index;
49 u16 len;
50 };
51
52 struct qmihandle {
53 u16 cid;
54 struct qcusbnet *dev;
55 };
56
57 extern int qcusbnet_debug;
58 static int qcusbnet2k_fwdelay;
59
60 static bool device_valid(struct qcusbnet *dev);
61 static struct client *client_bycid(struct qcusbnet *dev, u16 cid);
62 static bool client_addread(struct qcusbnet *dev, u16 cid, u16 tid, void *data, u 16 size);
63 static bool client_delread(struct qcusbnet *dev, u16 cid, u16 tid, void **data, u16 *size);
64 static bool client_addnotify(struct qcusbnet *dev, u16 cid, u16 tid,
65 void (*hook)(struct qcusbnet *, u16 cid, void *),
66 void *data);
67 static bool client_notify(struct qcusbnet *dev, u16 cid, u16 tid);
68 static bool client_addurb(struct qcusbnet *dev, u16 cid, struct urb *urb);
69 static struct urb *client_delurb(struct qcusbnet *dev, u16 cid);
70
71 static int devqmi_open(struct inode *inode, struct file *file);
72 static int devqmi_ioctl(struct inode *inode, struct file *file, unsigned int cmd , unsigned long arg);
73 static int devqmi_close(struct file *file, fl_owner_t ftable);
74 static ssize_t devqmi_read(struct file *file, char __user *buf, size_t size,
75 loff_t *pos);
76 static ssize_t devqmi_write(struct file *file, const char __user *buf,
77 size_t size, loff_t *pos);
78
79 static bool qmi_ready(struct qcusbnet *dev, u16 timeout);
80 static void wds_callback(struct qcusbnet *dev, u16 cid, void *data);
81 static int setup_wds_callback(struct qcusbnet *dev);
82 static int qmidms_getmeid(struct qcusbnet *dev);
83
84 #define IOCTL_QMI_GET_SERVICE_FILE (0x8BE0 + 1)
85 #define IOCTL_QMI_GET_DEVICE_VIDPID (0x8BE0 + 2)
86 #define IOCTL_QMI_GET_DEVICE_MEID (0x8BE0 + 3)
87 #define CDC_GET_ENCAPSULATED_RESPONSE 0x01A1ll
88 #define CDC_CONNECTION_SPEED_CHANGE 0x08000000002AA1ll
89
90 static const struct file_operations devqmi_fops = {
91 .owner = THIS_MODULE,
92 .read = devqmi_read,
93 .write = devqmi_write,
94 .ioctl = devqmi_ioctl,
95 .open = devqmi_open,
96 .flush = devqmi_close,
97 };
98
99 #ifdef CONFIG_SMP
100 static inline void assert_locked(struct qcusbnet *dev)
101 {
102 BUG_ON(!spin_is_locked(&dev->qmi.clients_lock));
103 }
104 #else
105 static inline void assert_locked(struct qcusbnet *dev)
106 {
107
108 }
109 #endif
110
111 static bool device_valid(struct qcusbnet *dev)
112 {
113 return dev && dev->valid;
114 }
115
116 void qc_setdown(struct qcusbnet *dev, u8 reason)
117 {
118 set_bit(reason, &dev->down);
119 netif_carrier_off(dev->usbnet->net);
120 }
121
122 void qc_cleardown(struct qcusbnet *dev, u8 reason)
123 {
124 clear_bit(reason, &dev->down);
125 if (!dev->down)
126 netif_carrier_on(dev->usbnet->net);
127 }
128
129 bool qc_isdown(struct qcusbnet *dev, u8 reason)
130 {
131 return test_bit(reason, &dev->down);
132 }
133
134 static void read_callback(struct urb *urb)
135 {
136 struct list_head *node;
137 int result;
138 u16 cid;
139 struct client *client;
140 void *data;
141 void *copy;
142 u16 size;
143 struct qcusbnet *dev;
144 unsigned long flags;
145 u16 tid;
146
147 if (!urb) {
148 DBG("bad read URB\n");
149 return;
150 }
151
152 dev = urb->context;
153 if (!device_valid(dev)) {
154 DBG("Invalid device!\n");
155 return;
156 }
157
158 if (urb->status) {
159 DBG("Read status = %d\n", urb->status);
160 return;
161 }
162
163 DBG("Read %d bytes\n", urb->actual_length);
164
165 data = urb->transfer_buffer;
166 size = urb->actual_length;
167
168 print_hex_dump(KERN_INFO, "QCUSBNet2k: ", DUMP_PREFIX_OFFSET,
169 16, 1, data, size, true);
170
171 result = qmux_parse(&cid, data, size);
172 if (result < 0) {
173 DBG("Read error parsing QMUX %d\n", result);
174 return;
175 }
176
177 if (size < result + 3) {
178 DBG("Data buffer too small to parse\n");
179 return;
180 }
181
182 if (cid == QMICTL)
183 tid = *(u8 *)(data + result + 1);
184 else
185 tid = *(u16 *)(data + result + 1);
186 spin_lock_irqsave(&dev->qmi.clients_lock, flags);
187
188 list_for_each(node, &dev->qmi.clients) {
189 client = list_entry(node, struct client, node);
190 if (client->cid == cid || (client->cid | 0xff00) == cid) {
191 copy = kmalloc(size, GFP_ATOMIC);
192 memcpy(copy, data, size);
193 if (!client_addread(dev, client->cid, tid, copy, size)) {
194 DBG("Error allocating pReadMemListEntry "
195 "read will be discarded\n");
196 kfree(copy);
197 spin_unlock_irqrestore(&dev->qmi.clients_lock, f lags);
198 return;
199 }
200
201 DBG("Creating new readListEntry for client 0x%04X, TID % x\n",
202 cid, tid);
203
204 client_notify(dev, client->cid, tid);
205
206 if (cid >> 8 != 0xff)
207 break;
208 }
209 }
210
211 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
212 }
213
214 static void int_callback(struct urb *urb)
215 {
216 int status;
217 int interval;
218 struct qcusbnet *dev = (struct qcusbnet *)urb->context;
219
220 if (!device_valid(dev)) {
221 DBG("Invalid device!\n");
222 return;
223 }
224
225 if (urb->status) {
226 DBG("Int status = %d\n", urb->status);
227 if (urb->status != -EOVERFLOW)
228 return;
229 } else {
230 if ((urb->actual_length == 8) &&
231 (*(u64 *)urb->transfer_buffer == CDC_GET_ENCAPSULATED_RESPON SE)) {
232 usb_fill_control_urb(dev->qmi.readurb, dev->usbnet->udev ,
233 usb_rcvctrlpipe(dev->usbnet->udev, 0),
234 (unsigned char *)dev->qmi.readsetup ,
235 dev->qmi.readbuf,
236 DEFAULT_READ_URB_LENGTH,
237 read_callback, dev);
238 status = usb_submit_urb(dev->qmi.readurb, GFP_ATOMIC);
239 if (status) {
240 DBG("Error submitting Read URB %d\n", status);
241 return;
242 }
243 } else if ((urb->actual_length == 16) &&
244 (*(u64 *)urb->transfer_buffer == CDC_CONNECTION_SPEED _CHANGE)) {
245 /* if upstream or downstream is 0, stop traffic.
246 * Otherwise resume it */
247 if ((*(u32 *)(urb->transfer_buffer + 8) == 0) ||
248 (*(u32 *)(urb->transfer_buffer + 12) == 0)) {
249 qc_setdown(dev, DOWN_CDC_CONNECTION_SPEED);
250 DBG("traffic stopping due to CONNECTION_SPEED_CH ANGE\n");
251 } else {
252 qc_cleardown(dev, DOWN_CDC_CONNECTION_SPEED);
253 DBG("resuming traffic due to CONNECTION_SPEED_CH ANGE\n");
254 }
255 } else {
256 DBG("ignoring invalid interrupt in packet\n");
257 print_hex_dump(KERN_INFO, "QCUSBNet2k: ",
258 DUMP_PREFIX_OFFSET, 16, 1,
259 urb->transfer_buffer,
260 urb->actual_length, true);
261 }
262 }
263
264 interval = (dev->usbnet->udev->speed == USB_SPEED_HIGH) ? 7 : 3;
265
266 usb_fill_int_urb(urb, urb->dev, urb->pipe, urb->transfer_buffer,
267 urb->transfer_buffer_length, urb->complete,
268 urb->context, interval);
269 status = usb_submit_urb(urb, GFP_ATOMIC);
270 if (status)
271 DBG("Error re-submitting Int URB %d\n", status);
272 return;
273 }
274
275 int qc_startread(struct qcusbnet *dev)
276 {
277 int interval;
278
279 if (!device_valid(dev)) {
280 DBG("Invalid device!\n");
281 return -ENXIO;
282 }
283
284 dev->qmi.readurb = usb_alloc_urb(0, GFP_KERNEL);
285 if (!dev->qmi.readurb) {
286 DBG("Error allocating read urb\n");
287 return -ENOMEM;
288 }
289
290 dev->qmi.inturb = usb_alloc_urb(0, GFP_KERNEL);
291 if (!dev->qmi.inturb) {
292 usb_free_urb(dev->qmi.readurb);
293 DBG("Error allocating int urb\n");
294 return -ENOMEM;
295 }
296
297 dev->qmi.readbuf = kmalloc(DEFAULT_READ_URB_LENGTH, GFP_KERNEL);
298 if (!dev->qmi.readbuf) {
299 usb_free_urb(dev->qmi.readurb);
300 usb_free_urb(dev->qmi.inturb);
301 DBG("Error allocating read buffer\n");
302 return -ENOMEM;
303 }
304
305 dev->qmi.intbuf = kmalloc(DEFAULT_READ_URB_LENGTH, GFP_KERNEL);
306 if (!dev->qmi.intbuf) {
307 usb_free_urb(dev->qmi.readurb);
308 usb_free_urb(dev->qmi.inturb);
309 kfree(dev->qmi.readbuf);
310 DBG("Error allocating int buffer\n");
311 return -ENOMEM;
312 }
313
314 dev->qmi.readsetup = kmalloc(sizeof(*dev->qmi.readsetup), GFP_KERNEL);
315 if (!dev->qmi.readsetup) {
316 usb_free_urb(dev->qmi.readurb);
317 usb_free_urb(dev->qmi.inturb);
318 kfree(dev->qmi.readbuf);
319 kfree(dev->qmi.intbuf);
320 DBG("Error allocating setup packet buffer\n");
321 return -ENOMEM;
322 }
323
324 dev->qmi.readsetup->type = 0xA1;
325 dev->qmi.readsetup->code = 1;
326 dev->qmi.readsetup->value = 0;
327 dev->qmi.readsetup->index = 0;
328 dev->qmi.readsetup->len = DEFAULT_READ_URB_LENGTH;
329
330 interval = (dev->usbnet->udev->speed == USB_SPEED_HIGH) ? 7 : 3;
331
332 usb_fill_int_urb(dev->qmi.inturb, dev->usbnet->udev,
333 usb_rcvintpipe(dev->usbnet->udev, 0x81),
334 dev->qmi.intbuf, DEFAULT_READ_URB_LENGTH,
335 int_callback, dev, interval);
336 return usb_submit_urb(dev->qmi.inturb, GFP_KERNEL);
337 }
338
339 void qc_stopread(struct qcusbnet *dev)
340 {
341 if (dev->qmi.readurb) {
342 DBG("Killing read URB\n");
343 usb_kill_urb(dev->qmi.readurb);
344 }
345
346 if (dev->qmi.inturb) {
347 DBG("Killing int URB\n");
348 usb_kill_urb(dev->qmi.inturb);
349 }
350
351 kfree(dev->qmi.readsetup);
352 dev->qmi.readsetup = NULL;
353 kfree(dev->qmi.readbuf);
354 dev->qmi.readbuf = NULL;
355 kfree(dev->qmi.intbuf);
356 dev->qmi.intbuf = NULL;
357
358 usb_free_urb(dev->qmi.readurb);
359 dev->qmi.readurb = NULL;
360 usb_free_urb(dev->qmi.inturb);
361 dev->qmi.inturb = NULL;
362 }
363
364 static int read_async(struct qcusbnet *dev, u16 cid, u16 tid,
365 void (*hook)(struct qcusbnet *, u16, void *),
366 void *data)
367 {
368 struct list_head *node;
369 struct client *client;
370 struct readreq *readreq;
371
372 unsigned long flags;
373
374 if (!device_valid(dev)) {
375 DBG("Invalid device!\n");
376 return -ENXIO;
377 }
378
379 spin_lock_irqsave(&dev->qmi.clients_lock, flags);
380
381 client = client_bycid(dev, cid);
382 if (!client) {
383 DBG("Could not find matching client ID 0x%04X\n", cid);
384 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
385 return -ENXIO;
386 }
387
388 list_for_each(node, &client->reads) {
389 readreq = list_entry(node, struct readreq, node);
390 if (!tid || tid == readreq->tid) {
391 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
392 hook(dev, cid, data);
393 return 0;
394 }
395 }
396
397 if (!client_addnotify(dev, cid, tid, hook, data))
398 DBG("Unable to register for notification\n");
399
400 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
401 return 0;
402 }
403
404 static void upsem(struct qcusbnet *dev, u16 cid, void *data)
405 {
406 DBG("0x%04X\n", cid);
407 up((struct semaphore *)data);
408 }
409
410 static int read_sync(struct qcusbnet *dev, void **buf, u16 cid, u16 tid)
411 {
412 struct list_head *node;
413 int result;
414 struct client *client;
415 struct notifyreq *notify;
416 struct semaphore sem;
417 void *data;
418 unsigned long flags;
419 u16 size;
420
421 if (!device_valid(dev)) {
422 DBG("Invalid device!\n");
423 return -ENXIO;
424 }
425
426 spin_lock_irqsave(&dev->qmi.clients_lock, flags);
427
428 client = client_bycid(dev, cid);
429 if (!client) {
430 DBG("Could not find matching client ID 0x%04X\n", cid);
431 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
432 return -ENXIO;
433 }
434
435 while (!client_delread(dev, cid, tid, &data, &size)) {
436 sema_init(&sem, 0);
437 if (!client_addnotify(dev, cid, tid, upsem, &sem)) {
438 DBG("unable to register for notification\n");
439 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
440 return -EFAULT;
441 }
442
443 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
444
445 result = down_interruptible(&sem);
446 if (result) {
447 DBG("Interrupted %d\n", result);
448 spin_lock_irqsave(&dev->qmi.clients_lock, flags);
449 list_for_each(node, &client->notifies) {
450 notify = list_entry(node, struct notifyreq, node );
451 if (notify->data == &sem) {
452 list_del(&notify->node);
453 kfree(notify);
454 break;
455 }
456 }
457
458 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
459 return -EINTR;
460 }
461
462 if (!device_valid(dev)) {
463 DBG("Invalid device!\n");
464 return -ENXIO;
465 }
466
467 spin_lock_irqsave(&dev->qmi.clients_lock, flags);
468 }
469
470 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
471 *buf = data;
472 return size;
473 }
474
475 static void write_callback(struct urb *urb)
476 {
477 if (!urb) {
478 DBG("null urb\n");
479 return;
480 }
481
482 DBG("Write status/size %d/%d\n", urb->status, urb->actual_length);
483 up((struct semaphore *)urb->context);
484 }
485
486 static int write_sync(struct qcusbnet *dev, char *buf, int size, u16 cid)
487 {
488 int result;
489 struct semaphore sem;
490 struct urb *urb;
491 struct urbsetup setup;
492 unsigned long flags;
493
494 if (!device_valid(dev)) {
495 DBG("Invalid device!\n");
496 return -ENXIO;
497 }
498
499 urb = usb_alloc_urb(0, GFP_KERNEL);
500 if (!urb) {
501 DBG("URB mem error\n");
502 return -ENOMEM;
503 }
504
505 result = qmux_fill(cid, buf, size);
506 if (result < 0) {
507 usb_free_urb(urb);
508 return result;
509 }
510
511 /* CDC Send Encapsulated Request packet */
512 setup.type = 0x21;
513 setup.code = 0;
514 setup.value = 0;
515 setup.index = 0;
516 setup.len = 0;
517 setup.len = size;
518
519 usb_fill_control_urb(urb, dev->usbnet->udev,
520 usb_sndctrlpipe(dev->usbnet->udev, 0),
521 (unsigned char *)&setup, (void *)buf, size,
522 NULL, dev);
523
524 DBG("Actual Write:\n");
525 print_hex_dump(KERN_INFO, "QCUSBNet2k: ", DUMP_PREFIX_OFFSET,
526 16, 1, buf, size, true);
527
528 sema_init(&sem, 0);
529
530 urb->complete = write_callback;
531 urb->context = &sem;
532
533 result = usb_autopm_get_interface(dev->iface);
534 if (result < 0) {
535 DBG("unable to resume interface: %d\n", result);
536 if (result == -EPERM) {
537 qc_suspend(dev->iface, PMSG_SUSPEND);
538 }
539 return result;
540 }
541
542 spin_lock_irqsave(&dev->qmi.clients_lock, flags);
543
544 if (!client_addurb(dev, cid, urb)) {
545 usb_free_urb(urb);
546 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
547 usb_autopm_put_interface(dev->iface);
548 return -EINVAL;
549 }
550
551 result = usb_submit_urb(urb, GFP_KERNEL);
552 if (result < 0) {
553 DBG("submit URB error %d\n", result);
554 if (client_delurb(dev, cid) != urb) {
555 DBG("Didn't get write URB back\n");
556 }
557
558 usb_free_urb(urb);
559
560 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
561 usb_autopm_put_interface(dev->iface);
562 return result;
563 }
564
565 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
566 result = down_interruptible(&sem);
567 if (!device_valid(dev)) {
568 DBG("Invalid device!\n");
569 return -ENXIO;
570 }
571
572 usb_autopm_put_interface(dev->iface);
573 spin_lock_irqsave(&dev->qmi.clients_lock, flags);
574 if (client_delurb(dev, cid) != urb) {
575 DBG("Didn't get write URB back\n");
576 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
577 return -EINVAL;
578 }
579 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
580
581 if (!result) {
582 if (!urb->status) {
583 result = size;
584 } else {
585 DBG("bad status = %d\n", urb->status);
586 result = urb->status;
587 }
588 } else {
589 DBG("Interrupted %d !!!\n", result);
590 DBG("Device may be in bad state and need reset !!!\n");
591 usb_kill_urb(urb);
592 }
593
594 usb_free_urb(urb);
595 return result;
596 }
597
598 static int client_alloc(struct qcusbnet *dev, u8 type)
599 {
600 u16 cid;
601 struct client *client;
602 int result;
603 void *wbuf;
604 size_t wbufsize;
605 void *rbuf;
606 u16 rbufsize;
607 unsigned long flags;
608 u8 tid;
609
610 if (!device_valid(dev)) {
611 DBG("Invalid device!\n");
612 return -ENXIO;
613 }
614
615 if (type) {
616 tid = atomic_add_return(1, &dev->qmi.qmitid);
617 if (!tid)
618 atomic_add_return(1, &dev->qmi.qmitid);
619 wbuf = qmictl_new_getcid(tid, type, &wbufsize);
620 if (!wbuf)
621 return -ENOMEM;
622 result = write_sync(dev, wbuf, wbufsize, QMICTL);
623 kfree(wbuf);
624
625 if (result < 0)
626 return result;
627
628 result = read_sync(dev, &rbuf, QMICTL, tid);
629 if (result < 0) {
630 DBG("bad read data %d\n", result);
631 return result;
632 }
633 rbufsize = result;
634
635 result = qmictl_alloccid_resp(rbuf, rbufsize, &cid);
636 kfree(rbuf);
637
638 if (result < 0)
639 return result;
640 } else {
641 cid = 0;
642 }
643
644 spin_lock_irqsave(&dev->qmi.clients_lock, flags);
645 if (client_bycid(dev, cid)) {
646 DBG("Client memory already exists\n");
647 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
648 return -ETOOMANYREFS;
649 }
650
651 client = kmalloc(sizeof(*client), GFP_ATOMIC);
652 if (!client) {
653 DBG("Error allocating read list\n");
654 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
655 return -ENOMEM;
656 }
657
658 list_add_tail(&client->node, &dev->qmi.clients);
659 client->cid = cid;
660 INIT_LIST_HEAD(&client->reads);
661 INIT_LIST_HEAD(&client->notifies);
662 INIT_LIST_HEAD(&client->urbs);
663 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
664 return cid;
665 }
666
667 static void client_free(struct qcusbnet *dev, u16 cid)
668 {
669 struct list_head *node, *tmp;
670 int result;
671 struct client *client;
672 struct urb *urb;
673 void *data;
674 u16 size;
675 void *wbuf;
676 size_t wbufsize;
677 void *rbuf;
678 u16 rbufsize;
679 unsigned long flags;
680 u8 tid;
681
682 if (!device_valid(dev)) {
683 DBG("invalid device\n");
684 return;
685 }
686
687 DBG("releasing 0x%04X\n", cid);
688
689 if (cid != QMICTL) {
690 tid = atomic_add_return(1, &dev->qmi.qmitid);
691 if (!tid)
692 tid = atomic_add_return(1, &dev->qmi.qmitid);
693 wbuf = qmictl_new_releasecid(tid, cid, &wbufsize);
694 if (!wbuf) {
695 DBG("memory error\n");
696 } else {
697 result = write_sync(dev, wbuf, wbufsize, QMICTL);
698 kfree(wbuf);
699
700 if (result < 0) {
701 DBG("bad write status %d\n", result);
702 } else {
703 result = read_sync(dev, &rbuf, QMICTL, tid);
704 if (result < 0) {
705 DBG("bad read status %d\n", result);
706 } else {
707 rbufsize = result;
708 result = qmictl_freecid_resp(rbuf, rbufs ize);
709 kfree(rbuf);
710 if (result < 0)
711 DBG("error %d parsing response\n ", result);
712 }
713 }
714 }
715 }
716
717 spin_lock_irqsave(&dev->qmi.clients_lock, flags);
718 list_for_each_safe(node, tmp, &dev->qmi.clients) {
719 client = list_entry(node, struct client, node);
720 if (client->cid == cid) {
721 while (client_notify(dev, cid, 0)) {
722 ;
723 }
724
725 urb = client_delurb(dev, cid);
726 while (urb != NULL) {
727 usb_kill_urb(urb);
728 usb_free_urb(urb);
729 urb = client_delurb(dev, cid);
730 }
731
732 while (client_delread(dev, cid, 0, &data, &size))
733 kfree(data);
734
735 list_del(&client->node);
736 kfree(client);
737 }
738 }
739
740 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
741 }
742
743 struct client *client_bycid(struct qcusbnet *dev, u16 cid)
744 {
745 struct list_head *node;
746 struct client *client;
747
748 if (!device_valid(dev)) {
749 DBG("Invalid device\n");
750 return NULL;
751 }
752
753 assert_locked(dev);
754
755 list_for_each(node, &dev->qmi.clients) {
756 client = list_entry(node, struct client, node);
757 if (client->cid == cid)
758 return client;
759 }
760
761 DBG("Could not find client mem 0x%04X\n", cid);
762 return NULL;
763 }
764
765 static bool client_addread(struct qcusbnet *dev, u16 cid, u16 tid, void *data,
766 u16 size)
767 {
768 struct client *client;
769 struct readreq *req;
770
771 assert_locked(dev);
772
773 client = client_bycid(dev, cid);
774 if (!client) {
775 DBG("Could not find this client's memory 0x%04X\n", cid);
776 return false;
777 }
778
779 req = kmalloc(sizeof(*req), GFP_ATOMIC);
780 if (!req) {
781 DBG("Mem error\n");
782 return false;
783 }
784
785 req->data = data;
786 req->size = size;
787 req->tid = tid;
788
789 list_add_tail(&req->node, &client->reads);
790
791 return true;
792 }
793
794 static bool client_delread(struct qcusbnet *dev, u16 cid, u16 tid, void **data,
795 u16 *size)
796 {
797 struct client *client;
798 struct readreq *req;
799 struct list_head *node;
800
801 assert_locked(dev);
802
803 client = client_bycid(dev, cid);
804 if (!client) {
805 DBG("Could not find this client's memory 0x%04X\n", cid);
806 return false;
807 }
808
809 list_for_each(node, &client->reads) {
810 req = list_entry(node, struct readreq, node);
811 if (!tid || tid == req->tid) {
812 *data = req->data;
813 *size = req->size;
814 list_del(&req->node);
815 kfree(req);
816 return true;
817 }
818
819 DBG("skipping 0x%04X data TID = %x\n", cid, req->tid);
820 }
821
822 DBG("No read memory to pop, Client 0x%04X, TID = %x\n", cid, tid);
823 return false;
824 }
825
826 static bool client_addnotify(struct qcusbnet *dev, u16 cid, u16 tid,
827 void (*hook)(struct qcusbnet *, u16, void *),
828 void *data)
829 {
830 struct client *client;
831 struct notifyreq *req;
832
833 assert_locked(dev);
834
835 client = client_bycid(dev, cid);
836 if (!client) {
837 DBG("Could not find this client's memory 0x%04X\n", cid);
838 return false;
839 }
840
841 req = kmalloc(sizeof(*req), GFP_ATOMIC);
842 if (!req) {
843 DBG("Mem error\n");
844 return false;
845 }
846
847 list_add_tail(&req->node, &client->notifies);
848 req->func = hook;
849 req->data = data;
850 req->tid = tid;
851
852 return true;
853 }
854
855 static bool client_notify(struct qcusbnet *dev, u16 cid, u16 tid)
856 {
857 struct client *client;
858 struct notifyreq *delnotify, *notify;
859 struct list_head *node;
860
861 assert_locked(dev);
862
863 client = client_bycid(dev, cid);
864 if (!client) {
865 DBG("Could not find this client's memory 0x%04X\n", cid);
866 return false;
867 }
868
869 delnotify = NULL;
870
871 list_for_each(node, &client->notifies) {
872 notify = list_entry(node, struct notifyreq, node);
873 if (!tid || !notify->tid || tid == notify->tid) {
874 delnotify = notify;
875 break;
876 }
877
878 DBG("skipping data TID = %x\n", notify->tid);
879 }
880
881 if (delnotify) {
882 list_del(&delnotify->node);
883 if (delnotify->func) {
884 spin_unlock(&dev->qmi.clients_lock);
885 delnotify->func(dev, cid, delnotify->data);
886 spin_lock(&dev->qmi.clients_lock);
887 }
888 kfree(delnotify);
889 return true;
890 }
891
892 DBG("no one to notify for TID %x\n", tid);
893 return false;
894 }
895
896 static bool client_addurb(struct qcusbnet *dev, u16 cid, struct urb *urb)
897 {
898 struct client *client;
899 struct urbreq *req;
900
901 assert_locked(dev);
902
903 client = client_bycid(dev, cid);
904 if (!client) {
905 DBG("Could not find this client's memory 0x%04X\n", cid);
906 return false;
907 }
908
909 req = kmalloc(sizeof(*req), GFP_ATOMIC);
910 if (!req) {
911 DBG("Mem error\n");
912 return false;
913 }
914
915 req->urb = urb;
916 list_add_tail(&req->node, &client->urbs);
917
918 return true;
919 }
920
921 static struct urb *client_delurb(struct qcusbnet *dev, u16 cid)
922 {
923 struct client *client;
924 struct urbreq *req;
925 struct urb *urb;
926
927 assert_locked(dev);
928
929 client = client_bycid(dev, cid);
930 if (!client) {
931 DBG("Could not find this client's memory 0x%04X\n", cid);
932 return NULL;
933 }
934
935 if (list_empty(&client->urbs)) {
936 DBG("No URB's to pop\n");
937 return NULL;
938 }
939
940 req = list_first_entry(&client->urbs, struct urbreq, node);
941 list_del(&req->node);
942 urb = req->urb;
943 kfree(req);
944 return urb;
945 }
946
947 static int devqmi_open(struct inode *inode, struct file *file)
948 {
949 struct qmihandle *handle;
950 struct qmidev *qmidev = container_of(inode->i_cdev, struct qmidev, cdev) ;
951 struct qcusbnet *dev = container_of(qmidev, struct qcusbnet, qmi);
952
953 if (!device_valid(dev)) {
954 DBG("Invalid device\n");
955 return -ENXIO;
956 }
957
958 file->private_data = kmalloc(sizeof(struct qmihandle), GFP_KERNEL);
959 if (!file->private_data) {
960 DBG("Mem error\n");
961 return -ENOMEM;
962 }
963
964 handle = (struct qmihandle *)file->private_data;
965 handle->cid = (u16)-1;
966 handle->dev = dev;
967
968 DBG("%p %04x", handle, handle->cid);
969
970 return 0;
971 }
972
973 static int devqmi_ioctl(struct inode *inode, struct file *file, unsigned int cmd , unsigned long arg)
974 {
975 int result;
976 u32 vidpid;
977
978 struct qmihandle *handle = (struct qmihandle *)file->private_data;
979
980 DBG("%p %04x %08x", handle, handle->cid, cmd);
981
982 if (!handle) {
983 DBG("Bad file data\n");
984 return -EBADF;
985 }
986
987 if (!device_valid(handle->dev)) {
988 DBG("Invalid device! Updating f_ops\n");
989 file->f_op = file->f_dentry->d_inode->i_fop;
990 return -ENXIO;
991 }
992
993 switch (cmd) {
994 case IOCTL_QMI_GET_SERVICE_FILE:
995
996 DBG("Setting up QMI for service %lu\n", arg);
997 if (!(u8)arg) {
998 DBG("Cannot use QMICTL from userspace\n");
999 return -EINVAL;
1000 }
1001
1002 if (handle->cid != (u16)-1) {
1003 DBG("Close the current connection before opening a new o ne\n");
1004 return -EBADR;
1005 }
1006
1007 result = client_alloc(handle->dev, (u8)arg);
1008 if (result < 0)
1009 return result;
1010 handle->cid = result;
1011
1012 return 0;
1013 break;
1014
1015
1016 case IOCTL_QMI_GET_DEVICE_VIDPID:
1017 if (!arg) {
1018 DBG("Bad VIDPID buffer\n");
1019 return -EINVAL;
1020 }
1021
1022 if (!handle->dev->usbnet) {
1023 DBG("Bad usbnet\n");
1024 return -ENOMEM;
1025 }
1026
1027 if (!handle->dev->usbnet->udev) {
1028 DBG("Bad udev\n");
1029 return -ENOMEM;
1030 }
1031
1032 vidpid = ((le16_to_cpu(handle->dev->usbnet->udev->descriptor.idV endor) << 16)
1033 + le16_to_cpu(handle->dev->usbnet->udev->descriptor.id Product));
1034
1035 result = copy_to_user((unsigned int *)arg, &vidpid, 4);
1036 if (result)
1037 DBG("Copy to userspace failure\n");
1038
1039 return result;
1040 break;
1041
1042 case IOCTL_QMI_GET_DEVICE_MEID:
1043 if (!arg) {
1044 DBG("Bad MEID buffer\n");
1045 return -EINVAL;
1046 }
1047
1048 result = copy_to_user((unsigned int *)arg, &handle->dev->meid[0] , 14);
1049 if (result)
1050 DBG("copy to userspace failure\n");
1051
1052 return result;
1053 break;
1054 default:
1055 return -EBADRQC;
1056 }
1057 }
1058
1059 static int devqmi_close(struct file *file, fl_owner_t ftable)
1060 {
1061 struct qmihandle *handle = (struct qmihandle *)file->private_data;
1062 struct task_struct *task;
1063 struct fdtable *fdtable;
1064 int count = 0;
1065 int used = 0;
1066 unsigned long flags;
1067
1068 if (!handle) {
1069 DBG("bad file data\n");
1070 return -EBADF;
1071 }
1072
1073 if (file_count(file) != 1) {
1074 rcu_read_lock();
1075 for_each_process(task) {
1076 if (!task || !task->files)
1077 continue;
1078 spin_lock_irqsave(&task->files->file_lock, flags);
1079 fdtable = files_fdtable(task->files);
1080 for (count = 0; count < fdtable->max_fds; count++) {
1081 /* Before this function was called, this file wa s removed
1082 * from our task's file table so if we find it i n a file
1083 * table then it is being used by another task
1084 */
1085 if (fdtable->fd[count] == file) {
1086 used++;
1087 break;
1088 }
1089 }
1090 spin_unlock_irqrestore(&task->files->file_lock, flags);
1091 }
1092 rcu_read_unlock();
1093
1094 if (used > 0) {
1095 DBG("not closing, as this FD is open by %d other process \n", used);
1096 return 0;
1097 }
1098 }
1099
1100 if (!device_valid(handle->dev)) {
1101 DBG("Invalid device! Updating f_ops\n");
1102 file->f_op = file->f_dentry->d_inode->i_fop;
1103 return -ENXIO;
1104 }
1105
1106 DBG("0x%04X\n", handle->cid);
1107
1108 file->private_data = NULL;
1109
1110 if (handle->cid != (u16)-1)
1111 client_free(handle->dev, handle->cid);
1112
1113 kfree(handle);
1114 return 0;
1115 }
1116
1117 static ssize_t devqmi_read(struct file *file, char __user *buf, size_t size,
1118 loff_t *pos)
1119 {
1120 int result;
1121 void *data = NULL;
1122 void *smalldata;
1123 struct qmihandle *handle = (struct qmihandle *)file->private_data;
1124
1125 if (!handle) {
1126 DBG("Bad file data\n");
1127 return -EBADF;
1128 }
1129
1130 if (!device_valid(handle->dev)) {
1131 DBG("Invalid device! Updating f_ops\n");
1132 file->f_op = file->f_dentry->d_inode->i_fop;
1133 return -ENXIO;
1134 }
1135
1136 if (handle->cid == (u16)-1) {
1137 DBG("Client ID must be set before reading 0x%04X\n",
1138 handle->cid);
1139 return -EBADR;
1140 }
1141
1142 result = read_sync(handle->dev, &data, handle->cid, 0);
1143 if (result <= 0)
1144 return result;
1145
1146 result -= qmux_size;
1147 smalldata = data + qmux_size;
1148
1149 if (result > size) {
1150 DBG("Read data is too large for amount user has requested\n");
1151 kfree(data);
1152 return -EOVERFLOW;
1153 }
1154
1155 if (copy_to_user(buf, smalldata, result)) {
1156 DBG("Error copying read data to user\n");
1157 result = -EFAULT;
1158 }
1159
1160 kfree(data);
1161 return result;
1162 }
1163
1164 static ssize_t devqmi_write(struct file *file, const char __user * buf,
1165 size_t size, loff_t *pos)
1166 {
1167 int status;
1168 void *wbuf;
1169 struct qmihandle *handle = (struct qmihandle *)file->private_data;
1170
1171 if (!handle) {
1172 DBG("Bad file data\n");
1173 return -EBADF;
1174 }
1175
1176 if (!device_valid(handle->dev)) {
1177 DBG("Invalid device! Updating f_ops\n");
1178 file->f_op = file->f_dentry->d_inode->i_fop;
1179 return -ENXIO;
1180 }
1181
1182 if (handle->cid == (u16)-1) {
1183 DBG("Client ID must be set before writing 0x%04X\n",
1184 handle->cid);
1185 return -EBADR;
1186 }
1187
1188 wbuf = kmalloc(size + qmux_size, GFP_KERNEL);
1189 if (!wbuf)
1190 return -ENOMEM;
1191 status = copy_from_user(wbuf + qmux_size, buf, size);
1192 if (status) {
1193 DBG("Unable to copy data from userspace %d\n", status);
1194 kfree(wbuf);
1195 return status;
1196 }
1197
1198 status = write_sync(handle->dev, wbuf, size + qmux_size,
1199 handle->cid);
1200
1201 kfree(wbuf);
1202 if (status == size + qmux_size)
1203 return size;
1204 return status;
1205 }
1206
1207 int qc_register(struct qcusbnet *dev)
1208 {
1209 int result;
1210 int qmiidx = 0;
1211 dev_t devno;
1212 char *name;
1213
1214 dev->valid = true;
1215 result = client_alloc(dev, QMICTL);
1216 if (result) {
1217 dev->valid = false;
1218 return result;
1219 }
1220 atomic_set(&dev->qmi.qmitid, 1);
1221
1222 result = qc_startread(dev);
1223 if (result) {
1224 dev->valid = false;
1225 return result;
1226 }
1227
1228 if (!qmi_ready(dev, 30000)) {
1229 DBG("Device unresponsive to QMI\n");
1230 return -ETIMEDOUT;
1231 }
1232
1233 result = setup_wds_callback(dev);
1234 if (result) {
1235 dev->valid = false;
1236 return result;
1237 }
1238
1239 result = qmidms_getmeid(dev);
1240 if (result) {
1241 dev->valid = false;
1242 return result;
1243 }
1244
1245 result = alloc_chrdev_region(&devno, 0, 1, "qcqmi");
1246 if (result < 0)
1247 return result;
1248
1249 cdev_init(&dev->qmi.cdev, &devqmi_fops);
1250 dev->qmi.cdev.owner = THIS_MODULE;
1251 dev->qmi.cdev.ops = &devqmi_fops;
1252
1253 result = cdev_add(&dev->qmi.cdev, devno, 1);
1254 if (result) {
1255 DBG("error adding cdev\n");
1256 return result;
1257 }
1258
1259 name = strstr(dev->usbnet->net->name, "usb");
1260 if (!name) {
1261 DBG("Bad net name: %s\n", dev->usbnet->net->name);
1262 return -ENXIO;
1263 }
1264 name += strlen("usb");
1265 qmiidx = simple_strtoul(name, NULL, 10);
1266 if (qmiidx < 0) {
1267 DBG("Bad minor number\n");
1268 return -ENXIO;
1269 }
1270
1271 printk(KERN_INFO "creating qcqmi%d\n", qmiidx);
1272 device_create(dev->qmi.devclass, NULL, devno, NULL, "qcqmi%d", qmiidx);
1273
1274 dev->qmi.devnum = devno;
1275 return 0;
1276 }
1277
1278 void qc_deregister(struct qcusbnet *dev)
1279 {
1280 struct list_head *node, *tmp;
1281 struct client *client;
1282 struct inode *inode;
1283 struct list_head *inodes;
1284 struct task_struct *task;
1285 struct fdtable *fdtable;
1286 struct file *file;
1287 unsigned long flags;
1288 int count = 0;
1289
1290 if (!device_valid(dev)) {
1291 DBG("wrong device\n");
1292 return;
1293 }
1294
1295 list_for_each_safe(node, tmp, &dev->qmi.clients) {
1296 client = list_entry(node, struct client, node);
1297 DBG("release 0x%04X\n", client->cid);
1298 client_free(dev, client->cid);
1299 }
1300
1301 qc_stopread(dev);
1302 dev->valid = false;
1303 list_for_each(inodes, &dev->qmi.cdev.list) {
1304 inode = container_of(inodes, struct inode, i_devices);
1305 if (inode != NULL && !IS_ERR(inode)) {
1306 rcu_read_lock();
1307 for_each_process(task) {
1308 if (!task || !task->files)
1309 continue;
1310 spin_lock_irqsave(&task->files->file_lock, flags );
1311 fdtable = files_fdtable(task->files);
1312 for (count = 0; count < fdtable->max_fds; count+ +) {
1313 file = fdtable->fd[count];
1314 if (file != NULL && file->f_dentry != N ULL) {
1315 if (file->f_dentry->d_inode == i node) {
1316 rcu_assign_pointer(fdtab le->fd[count], NULL);
1317 spin_unlock_irqrestore(& task->files->file_lock, flags);
1318 DBG("forcing close of op en file handle\n");
1319 filp_close(file, task->f iles);
1320 spin_lock_irqsave(&task- >files->file_lock, flags);
1321 }
1322 }
1323 }
1324 spin_unlock_irqrestore(&task->files->file_lock, flags);
1325 }
1326 rcu_read_unlock();
1327 }
1328 }
1329
1330 if (!IS_ERR(dev->qmi.devclass))
1331 device_destroy(dev->qmi.devclass, dev->qmi.devnum);
1332 cdev_del(&dev->qmi.cdev);
1333 unregister_chrdev_region(dev->qmi.devnum, 1);
1334 }
1335
1336 static bool qmi_ready(struct qcusbnet *dev, u16 timeout)
1337 {
1338 int result;
1339 void *wbuf;
1340 size_t wbufsize;
1341 void *rbuf;
1342 u16 rbufsize;
1343 struct semaphore sem;
1344 u16 now;
1345 unsigned long flags;
1346 u8 tid;
1347
1348 if (!device_valid(dev)) {
1349 DBG("Invalid device\n");
1350 return -EFAULT;
1351 }
1352
1353
1354 for (now = 0; now < timeout; now += 100) {
1355 sema_init(&sem, 0);
1356
1357 tid = atomic_add_return(1, &dev->qmi.qmitid);
1358 if (!tid)
1359 tid = atomic_add_return(1, &dev->qmi.qmitid);
1360 kfree(wbuf);
1361 wbuf = qmictl_new_ready(tid, &wbufsize);
1362 if (!wbuf)
1363 return -ENOMEM;
1364
1365 result = read_async(dev, QMICTL, tid, upsem, &sem);
1366 if (result) {
1367 kfree(wbuf);
1368 return false;
1369 }
1370
1371 write_sync(dev, wbuf, wbufsize, QMICTL);
1372
1373 msleep(100);
1374 if (!down_trylock(&sem)) {
1375 spin_lock_irqsave(&dev->qmi.clients_lock, flags);
1376 if (client_delread(dev, QMICTL, tid, &rbuf, &rbufsize)) {
1377 spin_unlock_irqrestore(&dev->qmi.clients_lock, f lags);
1378 kfree(rbuf);
1379 break;
1380 }
1381 } else {
1382 spin_lock_irqsave(&dev->qmi.clients_lock, flags);
1383 client_notify(dev, QMICTL, tid);
1384 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
1385 }
1386 }
1387
1388 kfree(wbuf);
1389
1390 if (now >= timeout)
1391 return false;
1392
1393 DBG("QMI Ready after %u milliseconds\n", now);
1394
1395 /* 3580 and newer doesn't need a delay; older needs 5000ms */
1396 if (qcusbnet2k_fwdelay)
1397 msleep(qcusbnet2k_fwdelay * 1000);
1398
1399 return true;
1400 }
1401
1402 static void wds_callback(struct qcusbnet *dev, u16 cid, void *data)
1403 {
1404 bool ret;
1405 int result;
1406 void *rbuf;
1407 u16 rbufsize;
1408
1409 struct net_device_stats *stats = &(dev->usbnet->net->stats);
1410
1411 struct qmiwds_stats dstats = {
1412 .txok = (u32)-1,
1413 .rxok = (u32)-1,
1414 .txerr = (u32)-1,
1415 .rxerr = (u32)-1,
1416 .txofl = (u32)-1,
1417 .rxofl = (u32)-1,
1418 .txbytesok = (u64)-1,
1419 .rxbytesok = (u64)-1,
1420 };
1421 unsigned long flags;
1422
1423 if (!device_valid(dev)) {
1424 DBG("Invalid device\n");
1425 return;
1426 }
1427
1428 spin_lock_irqsave(&dev->qmi.clients_lock, flags);
1429 ret = client_delread(dev, cid, 0, &rbuf, &rbufsize);
1430 spin_unlock_irqrestore(&dev->qmi.clients_lock, flags);
1431
1432 if (!ret) {
1433 DBG("WDS callback failed to get data\n");
1434 return;
1435 }
1436
1437 dstats.linkstate = !qc_isdown(dev, DOWN_NO_NDIS_CONNECTION);
1438 dstats.reconfigure = false;
1439
1440 result = qmiwds_event_resp(rbuf, rbufsize, &dstats);
1441 if (result < 0) {
1442 DBG("bad WDS packet\n");
1443 } else {
1444 if (dstats.txofl != (u32)-1)
1445 stats->tx_fifo_errors = dstats.txofl;
1446
1447 if (dstats.rxofl != (u32)-1)
1448 stats->rx_fifo_errors = dstats.rxofl;
1449
1450 if (dstats.txerr != (u32)-1)
1451 stats->tx_errors = dstats.txerr;
1452
1453 if (dstats.rxerr != (u32)-1)
1454 stats->rx_errors = dstats.rxerr;
1455
1456 if (dstats.txok != (u32)-1)
1457 stats->tx_packets = dstats.txok + stats->tx_errors;
1458
1459 if (dstats.rxok != (u32)-1)
1460 stats->rx_packets = dstats.rxok + stats->rx_errors;
1461
1462 if (dstats.txbytesok != (u64)-1)
1463 stats->tx_bytes = dstats.txbytesok;
1464
1465 if (dstats.rxbytesok != (u64)-1)
1466 stats->rx_bytes = dstats.rxbytesok;
1467
1468 if (dstats.reconfigure) {
1469 DBG("Net device link reset\n");
1470 qc_setdown(dev, DOWN_NO_NDIS_CONNECTION);
1471 qc_cleardown(dev, DOWN_NO_NDIS_CONNECTION);
1472 } else {
1473 if (dstats.linkstate) {
1474 DBG("Net device link is connected\n");
1475 qc_cleardown(dev, DOWN_NO_NDIS_CONNECTION);
1476 } else {
1477 DBG("Net device link is disconnected\n");
1478 qc_setdown(dev, DOWN_NO_NDIS_CONNECTION);
1479 }
1480 }
1481 }
1482
1483 kfree(rbuf);
1484
1485 result = read_async(dev, cid, 0, wds_callback, data);
1486 if (result != 0)
1487 DBG("unable to setup next async read\n");
1488 }
1489
1490 static int setup_wds_callback(struct qcusbnet *dev)
1491 {
1492 int result;
1493 void *buf;
1494 size_t size;
1495 u16 cid;
1496
1497 if (!device_valid(dev)) {
1498 DBG("Invalid device\n");
1499 return -EFAULT;
1500 }
1501
1502 result = client_alloc(dev, QMIWDS);
1503 if (result < 0)
1504 return result;
1505 cid = result;
1506
1507 buf = qmiwds_new_seteventreport(1, &size);
1508 if (!buf)
1509 return -ENOMEM;
1510
1511 result = write_sync(dev, buf, size, cid);
1512 kfree(buf);
1513
1514 if (result < 0) {
1515 return result;
1516 }
1517
1518 buf = qmiwds_new_getpkgsrvcstatus(2, &size);
1519 if (buf == NULL)
1520 return -ENOMEM;
1521
1522 result = write_sync(dev, buf, size, cid);
1523 kfree(buf);
1524
1525 if (result < 0)
1526 return result;
1527
1528 result = read_async(dev, cid, 0, wds_callback, NULL);
1529 if (result) {
1530 DBG("unable to setup async read\n");
1531 return result;
1532 }
1533
1534 result = usb_control_msg(dev->usbnet->udev,
1535 usb_sndctrlpipe(dev->usbnet->udev, 0),
1536 0x22, 0x21, 1, 0, NULL, 0, 100);
1537 if (result < 0) {
1538 DBG("Bad SetControlLineState status %d\n", result);
1539 return result;
1540 }
1541
1542 return 0;
1543 }
1544
1545 static int qmidms_getmeid(struct qcusbnet *dev)
1546 {
1547 int result;
1548 void *wbuf;
1549 size_t wbufsize;
1550 void *rbuf;
1551 u16 rbufsize;
1552 u16 cid;
1553
1554 if (!device_valid(dev)) {
1555 DBG("Invalid device\n");
1556 return -EFAULT;
1557 }
1558
1559 result = client_alloc(dev, QMIDMS);
1560 if (result < 0)
1561 return result;
1562 cid = result;
1563
1564 wbuf = qmidms_new_getmeid(1, &wbufsize);
1565 if (!wbuf)
1566 return -ENOMEM;
1567
1568 result = write_sync(dev, wbuf, wbufsize, cid);
1569 kfree(wbuf);
1570
1571 if (result < 0)
1572 return result;
1573
1574 result = read_sync(dev, &rbuf, cid, 1);
1575 if (result < 0)
1576 return result;
1577 rbufsize = result;
1578
1579 result = qmidms_meid_resp(rbuf, rbufsize, &dev->meid[0], 14);
1580 kfree(rbuf);
1581
1582 if (result < 0) {
1583 DBG("bad get MEID resp\n");
1584 memset(&dev->meid[0], '0', 14);
1585 }
1586
1587 client_free(dev, cid);
1588 return 0;
1589 }
1590
1591 module_param(qcusbnet2k_fwdelay, int, S_IRUGO | S_IWUSR);
1592 MODULE_PARM_DESC(qcusbnet2k_fwdelay, "Delay for old firmware");
OLDNEW
« no previous file with comments | « drivers/net/usb/gobi/qmidevice.h ('k') | drivers/net/usb/gobi/structs.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698