aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/usb
diff options
context:
space:
mode:
authorDavid Brownell <dbrownell@users.sourceforge.net>2008-11-16 03:36:08 -0500
committerDavid S. Miller <davem@davemloft.net>2008-11-16 03:36:08 -0500
commitcda2836dc66f814aecc58370251566e1c225c8d3 (patch)
treeebb381e9ed2a3a93621690b886b4e241a5fa4c81 /drivers/net/usb
parent74ad0a5421edc6ef13a4059c6076cd7a4f3a1fd5 (diff)
pegasus: minor resource shrinkage
Make pegasus driver not allocate a workqueue until the driver is bound to some device, which will need that workqueue if the device is brought up. This conserves resources when the driver is linked but there's no pegasus device connected. Also shrink the runtime footprint a smidgeon by moving some init-only code into its proper section, and move an obnoxious (frequent and meaningless) message to be debug-only. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: David S. Miller <davem@davemloft.net>
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