Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* qcusbnet.c - gobi network device | 1 /* qcusbnet.c - gobi network device |
| 2 * Copyright (c) 2010, Code Aurora Forum. All rights reserved. | 2 * Copyright (c) 2010, Code Aurora Forum. All rights reserved. |
| 3 | 3 |
| 4 * This program is free software; you can redistribute it and/or modify | 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 | 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. | 6 * only version 2 as published by the Free Software Foundation. |
| 7 | 7 |
| 8 * This program is distributed in the hope that it will be useful, | 8 * This program is distributed in the hope that it will be useful, |
| 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 11 * GNU General Public License for more details. | 11 * GNU General Public License for more details. |
| 12 | 12 |
| 13 * You should have received a copy of the GNU General Public License | 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 | 14 * along with this program; if not, write to the Free Software |
| 15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | 15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| 16 * 02110-1301, USA. | 16 * 02110-1301, USA. |
| 17 */ | 17 */ |
| 18 | 18 |
| 19 #include "structs.h" | 19 #include "structs.h" |
| 20 #include "qmidevice.h" | 20 #include "qmidevice.h" |
| 21 #include "qmi.h" | 21 #include "qmi.h" |
| 22 #include "qcusbnet.h" | 22 #include "qcusbnet.h" |
| 23 | 23 |
| 24 #define DRIVER_VERSION "1.0.110+google" | 24 #define DRIVER_VERSION "1.0.110+google" |
| 25 #define DRIVER_AUTHOR "Qualcomm Innovation Center" | 25 #define DRIVER_AUTHOR "Qualcomm Innovation Center" |
| 26 #define DRIVER_DESC "gobi" | 26 #define DRIVER_DESC "gobi" |
| 27 | 27 |
| 28 static LIST_HEAD(qcusbnet_list); | |
| 29 static DEFINE_MUTEX(qcusbnet_lock); | |
| 30 | |
| 28 int qcusbnet_debug; | 31 int qcusbnet_debug; |
| 29 static struct class *devclass; | 32 static struct class *devclass; |
| 30 | 33 |
| 34 static void free_dev(struct kref *ref) | |
| 35 { | |
| 36 struct qcusbnet *dev = container_of(ref, struct qcusbnet, refcount); | |
| 37 list_del(&dev->node); | |
| 38 kfree(dev); | |
| 39 } | |
| 40 | |
| 41 void qcusbnet_put(struct qcusbnet *dev) | |
| 42 { | |
| 43 mutex_lock(&qcusbnet_lock); | |
| 44 kref_put(&dev->refcount, free_dev); | |
| 45 mutex_unlock(&qcusbnet_lock); | |
| 46 } | |
| 47 | |
| 48 struct qcusbnet *qcusbnet_get(struct qcusbnet *key) | |
| 49 { | |
| 50 /* Given a putative qcusbnet struct, return either the struct itself | |
| 51 * (with a ref taken) if the struct is still visible, or NULL if it's | |
| 52 * not. This prevents object-visibility races where someone is looking | |
| 53 * up an object as the last ref gets dropped; dropping the last ref and | |
| 54 * removing the object from the list are atomic with respect to getting | |
| 55 * a new ref. */ | |
| 56 struct qcusbnet *entry = NULL; | |
|
Mandeep Singh Baines
2011/03/16 20:49:41
Why initialize this?
Elly Fong-Jones
2011/03/16 21:23:09
Done.
| |
| 57 mutex_lock(&qcusbnet_lock); | |
| 58 list_for_each_entry(entry, &qcusbnet_list, node) { | |
| 59 if (entry == key) { | |
| 60 kref_get(&entry->refcount); | |
| 61 mutex_unlock(&qcusbnet_lock); | |
| 62 return entry; | |
| 63 } | |
| 64 } | |
| 65 mutex_unlock(&qcusbnet_lock); | |
| 66 return NULL; | |
| 67 } | |
| 68 | |
| 31 int qc_suspend(struct usb_interface *iface, pm_message_t event) | 69 int qc_suspend(struct usb_interface *iface, pm_message_t event) |
| 32 { | 70 { |
| 33 struct usbnet *usbnet; | 71 struct usbnet *usbnet; |
| 34 struct qcusbnet *dev; | 72 struct qcusbnet *dev; |
| 35 | 73 |
| 36 if (!iface) | 74 if (!iface) |
| 37 return -ENOMEM; | 75 return -ENOMEM; |
| 38 | 76 |
| 39 usbnet = usb_get_intfdata(iface); | 77 usbnet = usb_get_intfdata(iface); |
| 40 | 78 |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 178 | 216 |
| 179 static void qcnet_unbind(struct usbnet *usbnet, struct usb_interface *iface) | 217 static void qcnet_unbind(struct usbnet *usbnet, struct usb_interface *iface) |
| 180 { | 218 { |
| 181 struct qcusbnet *dev = (struct qcusbnet *)usbnet->data[0]; | 219 struct qcusbnet *dev = (struct qcusbnet *)usbnet->data[0]; |
| 182 | 220 |
| 183 netif_carrier_off(usbnet->net); | 221 netif_carrier_off(usbnet->net); |
| 184 qc_deregister(dev); | 222 qc_deregister(dev); |
| 185 | 223 |
| 186 kfree(usbnet->net->netdev_ops); | 224 kfree(usbnet->net->netdev_ops); |
| 187 usbnet->net->netdev_ops = NULL; | 225 usbnet->net->netdev_ops = NULL; |
| 188 | 226 » /* drop the list's ref */ |
| 189 » kfree(dev); | 227 » qcusbnet_put(dev); |
| 190 } | 228 } |
| 191 | 229 |
| 192 static void qcnet_urbhook(struct urb *urb) | 230 static void qcnet_urbhook(struct urb *urb) |
| 193 { | 231 { |
| 194 unsigned long flags; | 232 unsigned long flags; |
| 195 struct worker *worker = urb->context; | 233 struct worker *worker = urb->context; |
| 196 if (!worker) { | 234 if (!worker) { |
| 197 DBG("bad context\n"); | 235 DBG("bad context\n"); |
| 198 return; | 236 return; |
| 199 } | 237 } |
| (...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 587 usbnet->net->netdev_ops = netdevops; | 625 usbnet->net->netdev_ops = netdevops; |
| 588 | 626 |
| 589 memset(&(dev->usbnet->net->stats), 0, sizeof(struct net_device_stats)); | 627 memset(&(dev->usbnet->net->stats), 0, sizeof(struct net_device_stats)); |
| 590 | 628 |
| 591 dev->iface = iface; | 629 dev->iface = iface; |
| 592 memset(&(dev->meid), '0', 14); | 630 memset(&(dev->meid), '0', 14); |
| 593 | 631 |
| 594 DBG("Mac Address: %pM\n", dev->usbnet->net->dev_addr); | 632 DBG("Mac Address: %pM\n", dev->usbnet->net->dev_addr); |
| 595 | 633 |
| 596 dev->valid = false; | 634 dev->valid = false; |
| 597 » memset(&dev->qmi, 0, sizeof(struct qmidev)); | 635 » memset(&dev->qmi, 0, sizeof(dev->qmi)); |
| 598 | 636 |
| 599 dev->qmi.devclass = devclass; | 637 dev->qmi.devclass = devclass; |
| 600 | 638 |
| 639 kref_init(&dev->refcount); | |
| 640 INIT_LIST_HEAD(&dev->node); | |
| 601 INIT_LIST_HEAD(&dev->qmi.clients); | 641 INIT_LIST_HEAD(&dev->qmi.clients); |
| 602 init_completion(&dev->worker.work); | 642 init_completion(&dev->worker.work); |
| 603 spin_lock_init(&dev->qmi.clients_lock); | 643 spin_lock_init(&dev->qmi.clients_lock); |
| 604 | 644 |
| 605 dev->down = 0; | 645 dev->down = 0; |
| 606 qc_setdown(dev, DOWN_NO_NDIS_CONNECTION); | 646 qc_setdown(dev, DOWN_NO_NDIS_CONNECTION); |
| 607 qc_setdown(dev, DOWN_NET_IFACE_STOPPED); | 647 qc_setdown(dev, DOWN_NET_IFACE_STOPPED); |
| 608 | 648 |
| 609 status = qc_register(dev); | 649 status = qc_register(dev); |
| 610 if (status) { | 650 if (status) { |
| 611 qc_deregister(dev); | 651 qc_deregister(dev); |
| 652 } else { | |
| 653 mutex_lock(&qcusbnet_lock); | |
| 654 /* Give our initial ref to the list */ | |
| 655 list_add(&dev->node, &qcusbnet_list); | |
| 656 mutex_unlock(&qcusbnet_lock); | |
| 612 } | 657 } |
| 613 | 658 |
| 614 return status; | 659 return status; |
| 615 } | 660 } |
| 616 EXPORT_SYMBOL_GPL(qcnet_probe); | 661 EXPORT_SYMBOL_GPL(qcnet_probe); |
| 617 | 662 |
| 618 static struct usb_driver qcusbnet = { | 663 static struct usb_driver qcusbnet = { |
| 619 .name = "gobi", | 664 .name = "gobi", |
| 620 .id_table = qc_vidpids, | 665 .id_table = qc_vidpids, |
| 621 .probe = qcnet_probe, | 666 .probe = qcnet_probe, |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 644 } | 689 } |
| 645 module_exit(modexit); | 690 module_exit(modexit); |
| 646 | 691 |
| 647 MODULE_VERSION(DRIVER_VERSION); | 692 MODULE_VERSION(DRIVER_VERSION); |
| 648 MODULE_AUTHOR(DRIVER_AUTHOR); | 693 MODULE_AUTHOR(DRIVER_AUTHOR); |
| 649 MODULE_DESCRIPTION(DRIVER_DESC); | 694 MODULE_DESCRIPTION(DRIVER_DESC); |
| 650 MODULE_LICENSE("Dual BSD/GPL"); | 695 MODULE_LICENSE("Dual BSD/GPL"); |
| 651 | 696 |
| 652 module_param(qcusbnet_debug, bool, S_IRUGO | S_IWUSR); | 697 module_param(qcusbnet_debug, bool, S_IRUGO | S_IWUSR); |
| 653 MODULE_PARM_DESC(qcusbnet_debug, "Debugging enabled or not"); | 698 MODULE_PARM_DESC(qcusbnet_debug, "Debugging enabled or not"); |
| OLD | NEW |