aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/usb')
-rw-r--r--drivers/net/usb/pegasus.c36
1 files changed, 26 insertions, 10 deletions
diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c
index c073929c4d75..075e8e94225e 100644
--- a/drivers/net/usb/pegasus.c
+++ b/drivers/net/usb/pegasus.c
@@ -1213,7 +1213,7 @@ static void pegasus_set_multicast(struct net_device *net)
1213 pegasus->eth_regs[EthCtrl0] |= RX_MULTICAST; 1213 pegasus->eth_regs[EthCtrl0] |= RX_MULTICAST;
1214 pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS; 1214 pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS;
1215 if (netif_msg_link(pegasus)) 1215 if (netif_msg_link(pegasus))
1216 pr_info("%s: set allmulti\n", net->name); 1216 pr_debug("%s: set allmulti\n", net->name);
1217 } else { 1217 } else {
1218 pegasus->eth_regs[EthCtrl0] &= ~RX_MULTICAST; 1218 pegasus->eth_regs[EthCtrl0] &= ~RX_MULTICAST;
1219 pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS; 1219 pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS;
@@ -1273,6 +1273,7 @@ static inline void setup_pegasus_II(pegasus_t * pegasus)
1273} 1273}
1274 1274
1275 1275
1276static int pegasus_count;
1276static struct workqueue_struct *pegasus_workqueue = NULL; 1277static struct workqueue_struct *pegasus_workqueue = NULL;
1277#define CARRIER_CHECK_DELAY (2 * HZ) 1278#define CARRIER_CHECK_DELAY (2 * HZ)
1278 1279
@@ -1301,6 +1302,18 @@ static int pegasus_blacklisted(struct usb_device *udev)
1301 return 0; 1302 return 0;
1302} 1303}
1303 1304
1305/* we rely on probe() and remove() being serialized so we
1306 * don't need extra locking on pegasus_count.
1307 */
1308static void pegasus_dec_workqueue(void)
1309{
1310 pegasus_count--;
1311 if (pegasus_count == 0) {
1312 destroy_workqueue(pegasus_workqueue);
1313 pegasus_workqueue = NULL;
1314 }
1315}
1316
1304static int pegasus_probe(struct usb_interface *intf, 1317static int pegasus_probe(struct usb_interface *intf,
1305 const struct usb_device_id *id) 1318 const struct usb_device_id *id)
1306{ 1319{
@@ -1310,12 +1323,17 @@ static int pegasus_probe(struct usb_interface *intf,
1310 int dev_index = id - pegasus_ids; 1323 int dev_index = id - pegasus_ids;
1311 int res = -ENOMEM; 1324 int res = -ENOMEM;
1312 1325
1313 usb_get_dev(dev); 1326 if (pegasus_blacklisted(dev))
1327 return -ENODEV;
1314 1328
1315 if (pegasus_blacklisted(dev)) { 1329 if (pegasus_count == 0) {
1316 res = -ENODEV; 1330 pegasus_workqueue = create_singlethread_workqueue("pegasus");
1317 goto out; 1331 if (!pegasus_workqueue)
1332 return -ENOMEM;
1318 } 1333 }
1334 pegasus_count++;
1335
1336 usb_get_dev(dev);
1319 1337
1320 net = alloc_etherdev(sizeof(struct pegasus)); 1338 net = alloc_etherdev(sizeof(struct pegasus));
1321 if (!net) { 1339 if (!net) {
@@ -1400,6 +1418,7 @@ out1:
1400 free_netdev(net); 1418 free_netdev(net);
1401out: 1419out:
1402 usb_put_dev(dev); 1420 usb_put_dev(dev);
1421 pegasus_dec_workqueue();
1403 return res; 1422 return res;
1404} 1423}
1405 1424
@@ -1425,6 +1444,7 @@ static void pegasus_disconnect(struct usb_interface *intf)
1425 pegasus->rx_skb = NULL; 1444 pegasus->rx_skb = NULL;
1426 } 1445 }
1427 free_netdev(pegasus->net); 1446 free_netdev(pegasus->net);
1447 pegasus_dec_workqueue();
1428} 1448}
1429 1449
1430static int pegasus_suspend (struct usb_interface *intf, pm_message_t message) 1450static int pegasus_suspend (struct usb_interface *intf, pm_message_t message)
@@ -1468,7 +1488,7 @@ static struct usb_driver pegasus_driver = {
1468 .resume = pegasus_resume, 1488 .resume = pegasus_resume,
1469}; 1489};
1470 1490
1471static void parse_id(char *id) 1491static void __init parse_id(char *id)
1472{ 1492{
1473 unsigned int vendor_id=0, device_id=0, flags=0, i=0; 1493 unsigned int vendor_id=0, device_id=0, flags=0, i=0;
1474 char *token, *name=NULL; 1494 char *token, *name=NULL;
@@ -1504,15 +1524,11 @@ static int __init pegasus_init(void)
1504 pr_info("%s: %s, " DRIVER_DESC "\n", driver_name, DRIVER_VERSION); 1524 pr_info("%s: %s, " DRIVER_DESC "\n", driver_name, DRIVER_VERSION);
1505 if (devid) 1525 if (devid)
1506 parse_id(devid); 1526 parse_id(devid);
1507 pegasus_workqueue = create_singlethread_workqueue("pegasus");
1508 if (!pegasus_workqueue)
1509 return -ENOMEM;
1510 return usb_register(&pegasus_driver); 1527 return usb_register(&pegasus_driver);
1511} 1528}
1512 1529
1513static void __exit pegasus_exit(void) 1530static void __exit pegasus_exit(void)
1514{ 1531{
1515 destroy_workqueue(pegasus_workqueue);
1516 usb_deregister(&pegasus_driver); 1532 usb_deregister(&pegasus_driver);
1517} 1533}
1518 1534