diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/net/usb/usbnet.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'drivers/net/usb/usbnet.c')
-rw-r--r-- | drivers/net/usb/usbnet.c | 100 |
1 files changed, 73 insertions, 27 deletions
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index ca7fc9df1ccf..ce395fe5de26 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <linux/usb/usbnet.h> | 45 | #include <linux/usb/usbnet.h> |
46 | #include <linux/slab.h> | 46 | #include <linux/slab.h> |
47 | #include <linux/kernel.h> | 47 | #include <linux/kernel.h> |
48 | #include <linux/pm_runtime.h> | ||
48 | 49 | ||
49 | #define DRIVER_VERSION "22-Aug-2005" | 50 | #define DRIVER_VERSION "22-Aug-2005" |
50 | 51 | ||
@@ -108,7 +109,7 @@ int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf) | |||
108 | 109 | ||
109 | /* take the first altsetting with in-bulk + out-bulk; | 110 | /* take the first altsetting with in-bulk + out-bulk; |
110 | * remember any status endpoint, just in case; | 111 | * remember any status endpoint, just in case; |
111 | * ignore other endpoints and altsetttings. | 112 | * ignore other endpoints and altsettings. |
112 | */ | 113 | */ |
113 | for (ep = 0; ep < alt->desc.bNumEndpoints; ep++) { | 114 | for (ep = 0; ep < alt->desc.bNumEndpoints; ep++) { |
114 | struct usb_host_endpoint *e; | 115 | struct usb_host_endpoint *e; |
@@ -386,18 +387,27 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) | |||
386 | static inline void rx_process (struct usbnet *dev, struct sk_buff *skb) | 387 | static inline void rx_process (struct usbnet *dev, struct sk_buff *skb) |
387 | { | 388 | { |
388 | if (dev->driver_info->rx_fixup && | 389 | if (dev->driver_info->rx_fixup && |
389 | !dev->driver_info->rx_fixup (dev, skb)) | 390 | !dev->driver_info->rx_fixup (dev, skb)) { |
390 | goto error; | 391 | /* With RX_ASSEMBLE, rx_fixup() must update counters */ |
392 | if (!(dev->driver_info->flags & FLAG_RX_ASSEMBLE)) | ||
393 | dev->net->stats.rx_errors++; | ||
394 | goto done; | ||
395 | } | ||
391 | // else network stack removes extra byte if we forced a short packet | 396 | // else network stack removes extra byte if we forced a short packet |
392 | 397 | ||
393 | if (skb->len) | 398 | if (skb->len) { |
394 | usbnet_skb_return (dev, skb); | 399 | /* all data was already cloned from skb inside the driver */ |
395 | else { | 400 | if (dev->driver_info->flags & FLAG_MULTI_PACKET) |
396 | netif_dbg(dev, rx_err, dev->net, "drop\n"); | 401 | dev_kfree_skb_any(skb); |
397 | error: | 402 | else |
398 | dev->net->stats.rx_errors++; | 403 | usbnet_skb_return(dev, skb); |
399 | skb_queue_tail (&dev->done, skb); | 404 | return; |
400 | } | 405 | } |
406 | |||
407 | netif_dbg(dev, rx_err, dev->net, "drop\n"); | ||
408 | dev->net->stats.rx_errors++; | ||
409 | done: | ||
410 | skb_queue_tail(&dev->done, skb); | ||
401 | } | 411 | } |
402 | 412 | ||
403 | /*-------------------------------------------------------------------------*/ | 413 | /*-------------------------------------------------------------------------*/ |
@@ -635,6 +645,7 @@ int usbnet_stop (struct net_device *net) | |||
635 | struct driver_info *info = dev->driver_info; | 645 | struct driver_info *info = dev->driver_info; |
636 | int retval; | 646 | int retval; |
637 | 647 | ||
648 | clear_bit(EVENT_DEV_OPEN, &dev->flags); | ||
638 | netif_stop_queue (net); | 649 | netif_stop_queue (net); |
639 | 650 | ||
640 | netif_info(dev, ifdown, dev->net, | 651 | netif_info(dev, ifdown, dev->net, |
@@ -726,6 +737,7 @@ int usbnet_open (struct net_device *net) | |||
726 | } | 737 | } |
727 | } | 738 | } |
728 | 739 | ||
740 | set_bit(EVENT_DEV_OPEN, &dev->flags); | ||
729 | netif_start_queue (net); | 741 | netif_start_queue (net); |
730 | netif_info(dev, ifup, dev->net, | 742 | netif_info(dev, ifup, dev->net, |
731 | "open: enable queueing (rx %d, tx %d) mtu %d %s framing\n", | 743 | "open: enable queueing (rx %d, tx %d) mtu %d %s framing\n", |
@@ -925,8 +937,10 @@ fail_halt: | |||
925 | if (urb != NULL) { | 937 | if (urb != NULL) { |
926 | clear_bit (EVENT_RX_MEMORY, &dev->flags); | 938 | clear_bit (EVENT_RX_MEMORY, &dev->flags); |
927 | status = usb_autopm_get_interface(dev->intf); | 939 | status = usb_autopm_get_interface(dev->intf); |
928 | if (status < 0) | 940 | if (status < 0) { |
941 | usb_free_urb(urb); | ||
929 | goto fail_lowmem; | 942 | goto fail_lowmem; |
943 | } | ||
930 | if (rx_submit (dev, urb, GFP_KERNEL) == -ENOLINK) | 944 | if (rx_submit (dev, urb, GFP_KERNEL) == -ENOLINK) |
931 | resched = 0; | 945 | resched = 0; |
932 | usb_autopm_put_interface(dev->intf); | 946 | usb_autopm_put_interface(dev->intf); |
@@ -970,7 +984,8 @@ static void tx_complete (struct urb *urb) | |||
970 | struct usbnet *dev = entry->dev; | 984 | struct usbnet *dev = entry->dev; |
971 | 985 | ||
972 | if (urb->status == 0) { | 986 | if (urb->status == 0) { |
973 | dev->net->stats.tx_packets++; | 987 | if (!(dev->driver_info->flags & FLAG_MULTI_PACKET)) |
988 | dev->net->stats.tx_packets++; | ||
974 | dev->net->stats.tx_bytes += entry->length; | 989 | dev->net->stats.tx_bytes += entry->length; |
975 | } else { | 990 | } else { |
976 | dev->net->stats.tx_errors++; | 991 | dev->net->stats.tx_errors++; |
@@ -1043,8 +1058,13 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, | |||
1043 | if (info->tx_fixup) { | 1058 | if (info->tx_fixup) { |
1044 | skb = info->tx_fixup (dev, skb, GFP_ATOMIC); | 1059 | skb = info->tx_fixup (dev, skb, GFP_ATOMIC); |
1045 | if (!skb) { | 1060 | if (!skb) { |
1046 | netif_dbg(dev, tx_err, dev->net, "can't tx_fixup skb\n"); | 1061 | if (netif_msg_tx_err(dev)) { |
1047 | goto drop; | 1062 | netif_dbg(dev, tx_err, dev->net, "can't tx_fixup skb\n"); |
1063 | goto drop; | ||
1064 | } else { | ||
1065 | /* cdc_ncm collected packet; waits for more */ | ||
1066 | goto not_drop; | ||
1067 | } | ||
1048 | } | 1068 | } |
1049 | } | 1069 | } |
1050 | length = skb->len; | 1070 | length = skb->len; |
@@ -1066,13 +1086,18 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, | |||
1066 | /* don't assume the hardware handles USB_ZERO_PACKET | 1086 | /* don't assume the hardware handles USB_ZERO_PACKET |
1067 | * NOTE: strictly conforming cdc-ether devices should expect | 1087 | * NOTE: strictly conforming cdc-ether devices should expect |
1068 | * the ZLP here, but ignore the one-byte packet. | 1088 | * the ZLP here, but ignore the one-byte packet. |
1089 | * NOTE2: CDC NCM specification is different from CDC ECM when | ||
1090 | * handling ZLP/short packets, so cdc_ncm driver will make short | ||
1091 | * packet itself if needed. | ||
1069 | */ | 1092 | */ |
1070 | if (length % dev->maxpacket == 0) { | 1093 | if (length % dev->maxpacket == 0) { |
1071 | if (!(info->flags & FLAG_SEND_ZLP)) { | 1094 | if (!(info->flags & FLAG_SEND_ZLP)) { |
1072 | urb->transfer_buffer_length++; | 1095 | if (!(info->flags & FLAG_MULTI_PACKET)) { |
1073 | if (skb_tailroom(skb)) { | 1096 | urb->transfer_buffer_length++; |
1074 | skb->data[skb->len] = 0; | 1097 | if (skb_tailroom(skb)) { |
1075 | __skb_put(skb, 1); | 1098 | skb->data[skb->len] = 0; |
1099 | __skb_put(skb, 1); | ||
1100 | } | ||
1076 | } | 1101 | } |
1077 | } else | 1102 | } else |
1078 | urb->transfer_flags |= URB_ZERO_PACKET; | 1103 | urb->transfer_flags |= URB_ZERO_PACKET; |
@@ -1121,6 +1146,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, | |||
1121 | netif_dbg(dev, tx_err, dev->net, "drop, code %d\n", retval); | 1146 | netif_dbg(dev, tx_err, dev->net, "drop, code %d\n", retval); |
1122 | drop: | 1147 | drop: |
1123 | dev->net->stats.tx_dropped++; | 1148 | dev->net->stats.tx_dropped++; |
1149 | not_drop: | ||
1124 | if (skb) | 1150 | if (skb) |
1125 | dev_kfree_skb_any (skb); | 1151 | dev_kfree_skb_any (skb); |
1126 | usb_free_urb (urb); | 1152 | usb_free_urb (urb); |
@@ -1230,12 +1256,14 @@ void usbnet_disconnect (struct usb_interface *intf) | |||
1230 | net = dev->net; | 1256 | net = dev->net; |
1231 | unregister_netdev (net); | 1257 | unregister_netdev (net); |
1232 | 1258 | ||
1233 | /* we don't hold rtnl here ... */ | 1259 | cancel_work_sync(&dev->kevent); |
1234 | flush_scheduled_work (); | ||
1235 | 1260 | ||
1236 | if (dev->driver_info->unbind) | 1261 | if (dev->driver_info->unbind) |
1237 | dev->driver_info->unbind (dev, intf); | 1262 | dev->driver_info->unbind (dev, intf); |
1238 | 1263 | ||
1264 | usb_kill_urb(dev->interrupt); | ||
1265 | usb_free_urb(dev->interrupt); | ||
1266 | |||
1239 | free_netdev(net); | 1267 | free_netdev(net); |
1240 | usb_put_dev (xdev); | 1268 | usb_put_dev (xdev); |
1241 | } | 1269 | } |
@@ -1273,6 +1301,16 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) | |||
1273 | struct usb_device *xdev; | 1301 | struct usb_device *xdev; |
1274 | int status; | 1302 | int status; |
1275 | const char *name; | 1303 | const char *name; |
1304 | struct usb_driver *driver = to_usb_driver(udev->dev.driver); | ||
1305 | |||
1306 | /* usbnet already took usb runtime pm, so have to enable the feature | ||
1307 | * for usb interface, otherwise usb_autopm_get_interface may return | ||
1308 | * failure if USB_SUSPEND(RUNTIME_PM) is enabled. | ||
1309 | */ | ||
1310 | if (!driver->supports_autosuspend) { | ||
1311 | driver->supports_autosuspend = 1; | ||
1312 | pm_runtime_enable(&udev->dev); | ||
1313 | } | ||
1276 | 1314 | ||
1277 | name = udev->dev.driver->name; | 1315 | name = udev->dev.driver->name; |
1278 | info = (struct driver_info *) prod->driver_info; | 1316 | info = (struct driver_info *) prod->driver_info; |
@@ -1347,7 +1385,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) | |||
1347 | // else "eth%d" when there's reasonable doubt. userspace | 1385 | // else "eth%d" when there's reasonable doubt. userspace |
1348 | // can rename the link if it knows better. | 1386 | // can rename the link if it knows better. |
1349 | if ((dev->driver_info->flags & FLAG_ETHER) != 0 && | 1387 | if ((dev->driver_info->flags & FLAG_ETHER) != 0 && |
1350 | (net->dev_addr [0] & 0x02) == 0) | 1388 | ((dev->driver_info->flags & FLAG_POINTTOPOINT) == 0 || |
1389 | (net->dev_addr [0] & 0x02) == 0)) | ||
1351 | strcpy (net->name, "eth%d"); | 1390 | strcpy (net->name, "eth%d"); |
1352 | /* WLAN devices should always be named "wlan%d" */ | 1391 | /* WLAN devices should always be named "wlan%d" */ |
1353 | if ((dev->driver_info->flags & FLAG_WLAN) != 0) | 1392 | if ((dev->driver_info->flags & FLAG_WLAN) != 0) |
@@ -1464,6 +1503,10 @@ int usbnet_resume (struct usb_interface *intf) | |||
1464 | int retval; | 1503 | int retval; |
1465 | 1504 | ||
1466 | if (!--dev->suspend_count) { | 1505 | if (!--dev->suspend_count) { |
1506 | /* resume interrupt URBs */ | ||
1507 | if (dev->interrupt && test_bit(EVENT_DEV_OPEN, &dev->flags)) | ||
1508 | usb_submit_urb(dev->interrupt, GFP_NOIO); | ||
1509 | |||
1467 | spin_lock_irq(&dev->txq.lock); | 1510 | spin_lock_irq(&dev->txq.lock); |
1468 | while ((res = usb_get_from_anchor(&dev->deferred))) { | 1511 | while ((res = usb_get_from_anchor(&dev->deferred))) { |
1469 | 1512 | ||
@@ -1482,9 +1525,12 @@ int usbnet_resume (struct usb_interface *intf) | |||
1482 | smp_mb(); | 1525 | smp_mb(); |
1483 | clear_bit(EVENT_DEV_ASLEEP, &dev->flags); | 1526 | clear_bit(EVENT_DEV_ASLEEP, &dev->flags); |
1484 | spin_unlock_irq(&dev->txq.lock); | 1527 | spin_unlock_irq(&dev->txq.lock); |
1485 | if (!(dev->txq.qlen >= TX_QLEN(dev))) | 1528 | |
1486 | netif_start_queue(dev->net); | 1529 | if (test_bit(EVENT_DEV_OPEN, &dev->flags)) { |
1487 | tasklet_schedule (&dev->bh); | 1530 | if (!(dev->txq.qlen >= TX_QLEN(dev))) |
1531 | netif_start_queue(dev->net); | ||
1532 | tasklet_schedule (&dev->bh); | ||
1533 | } | ||
1488 | } | 1534 | } |
1489 | return 0; | 1535 | return 0; |
1490 | } | 1536 | } |
@@ -1495,9 +1541,9 @@ EXPORT_SYMBOL_GPL(usbnet_resume); | |||
1495 | 1541 | ||
1496 | static int __init usbnet_init(void) | 1542 | static int __init usbnet_init(void) |
1497 | { | 1543 | { |
1498 | /* compiler should optimize this out */ | 1544 | /* Compiler should optimize this out. */ |
1499 | BUILD_BUG_ON (sizeof (((struct sk_buff *)0)->cb) | 1545 | BUILD_BUG_ON( |
1500 | < sizeof (struct skb_data)); | 1546 | FIELD_SIZEOF(struct sk_buff, cb) < sizeof(struct skb_data)); |
1501 | 1547 | ||
1502 | random_ether_addr(node_id); | 1548 | random_ether_addr(node_id); |
1503 | return 0; | 1549 | return 0; |