From: Albert H. <he...@us...> - 2009-12-09 18:40:27
|
Update of /cvsroot/gc-linux/linux/drivers/net/usb In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv21229/drivers/net/usb Modified Files: usbnet.c Log Message: Forward to v2.6.32. Index: usbnet.c =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/net/usb/usbnet.c,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** usbnet.c 9 Dec 2009 18:18:07 -0000 1.10 --- usbnet.c 9 Dec 2009 18:40:10 -0000 1.11 *************** *** 234,237 **** --- 234,242 ---- int status; + if (test_bit(EVENT_RX_PAUSED, &dev->flags)) { + skb_queue_tail(&dev->rxq_pause, skb); + return; + } + skb->protocol = eth_type_trans (skb, dev->net); dev->net->stats.rx_packets++; *************** *** 527,530 **** --- 532,570 ---- /*-------------------------------------------------------------------------*/ + void usbnet_pause_rx(struct usbnet *dev) + { + set_bit(EVENT_RX_PAUSED, &dev->flags); + + if (netif_msg_rx_status(dev)) + devdbg(dev, "paused rx queue enabled"); + } + EXPORT_SYMBOL_GPL(usbnet_pause_rx); + + void usbnet_resume_rx(struct usbnet *dev) + { + struct sk_buff *skb; + int num = 0; + + clear_bit(EVENT_RX_PAUSED, &dev->flags); + + while ((skb = skb_dequeue(&dev->rxq_pause)) != NULL) { + usbnet_skb_return(dev, skb); + num++; + } + + tasklet_schedule(&dev->bh); + + if (netif_msg_rx_status(dev)) + devdbg(dev, "paused rx queue disabled, %d skbs requeued", num); + } + EXPORT_SYMBOL_GPL(usbnet_resume_rx); + + void usbnet_purge_paused_rxq(struct usbnet *dev) + { + skb_queue_purge(&dev->rxq_pause); + } + EXPORT_SYMBOL_GPL(usbnet_purge_paused_rxq); + + /*-------------------------------------------------------------------------*/ // unlink pending rx/tx; completion handlers do all other cleanup *************** *** 576,580 **** --- 616,622 ---- { struct usbnet *dev = netdev_priv(net); + struct driver_info *info = dev->driver_info; int temp; + int retval; DECLARE_WAIT_QUEUE_HEAD_ONSTACK (unlink_wakeup); DECLARE_WAITQUEUE (wait, current); *************** *** 588,609 **** ); ! // ensure there are no more active urbs ! add_wait_queue (&unlink_wakeup, &wait); ! dev->wait = &unlink_wakeup; ! temp = unlink_urbs (dev, &dev->txq) + unlink_urbs (dev, &dev->rxq); ! // maybe wait for deletions to finish. ! while (!skb_queue_empty(&dev->rxq) ! && !skb_queue_empty(&dev->txq) ! && !skb_queue_empty(&dev->done)) { ! msleep(UNLINK_TIMEOUT_MS); ! if (netif_msg_ifdown (dev)) ! devdbg (dev, "waited for %d urb completions", temp); } - dev->wait = NULL; - remove_wait_queue (&unlink_wakeup, &wait); usb_kill_urb(dev->interrupt); /* deferred work (task, timer, softirq) must also stop. * can't flush_scheduled_work() until we drop rtnl (later), --- 630,669 ---- ); ! /* allow minidriver to stop correctly (wireless devices to turn off ! * radio etc) */ ! if (info->stop) { ! retval = info->stop(dev); ! if (retval < 0 && netif_msg_ifdown(dev)) ! devinfo(dev, ! "stop fail (%d) usbnet usb-%s-%s, %s", ! retval, ! dev->udev->bus->bus_name, dev->udev->devpath, ! info->description); ! } ! if (!(info->flags & FLAG_AVOID_UNLINK_URBS)) { ! /* ensure there are no more active urbs */ ! add_wait_queue(&unlink_wakeup, &wait); ! dev->wait = &unlink_wakeup; ! temp = unlink_urbs(dev, &dev->txq) + ! unlink_urbs(dev, &dev->rxq); ! ! /* maybe wait for deletions to finish. */ ! while (!skb_queue_empty(&dev->rxq) ! && !skb_queue_empty(&dev->txq) ! && !skb_queue_empty(&dev->done)) { ! msleep(UNLINK_TIMEOUT_MS); ! if (netif_msg_ifdown(dev)) ! devdbg(dev, "waited for %d urb completions", ! temp); ! } ! dev->wait = NULL; ! remove_wait_queue(&unlink_wakeup, &wait); } usb_kill_urb(dev->interrupt); + usbnet_purge_paused_rxq(dev); + /* deferred work (task, timer, softirq) must also stop. * can't flush_scheduled_work() until we drop rtnl (later), *************** *** 795,799 **** /* drivers may override default ethtool_ops in their bind() routine */ ! static struct ethtool_ops usbnet_ethtool_ops = { .get_settings = usbnet_get_settings, .set_settings = usbnet_set_settings, --- 855,859 ---- /* drivers may override default ethtool_ops in their bind() routine */ ! static const struct ethtool_ops usbnet_ethtool_ops = { .get_settings = usbnet_get_settings, .set_settings = usbnet_set_settings, *************** *** 948,960 **** /*-------------------------------------------------------------------------*/ ! int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net) { struct usbnet *dev = netdev_priv(net); int length; - int retval = NET_XMIT_SUCCESS; struct urb *urb = NULL; struct skb_data *entry; struct driver_info *info = dev->driver_info; unsigned long flags; // some devices want funky USB-level framing, for --- 1008,1021 ---- /*-------------------------------------------------------------------------*/ ! netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, ! struct net_device *net) { struct usbnet *dev = netdev_priv(net); int length; struct urb *urb = NULL; struct skb_data *entry; struct driver_info *info = dev->driver_info; unsigned long flags; + int retval; // some devices want funky USB-level framing, for *************** *** 989,993 **** * the ZLP here, but ignore the one-byte packet. */ ! if ((length % dev->maxpacket) == 0) { urb->transfer_buffer_length++; if (skb_tailroom(skb)) { --- 1050,1054 ---- * the ZLP here, but ignore the one-byte packet. */ ! if (!(info->flags & FLAG_SEND_ZLP) && (length % dev->maxpacket) == 0) { urb->transfer_buffer_length++; if (skb_tailroom(skb)) { *************** *** 1020,1024 **** devdbg (dev, "drop, code %d", retval); drop: - retval = NET_XMIT_SUCCESS; dev->net->stats.tx_dropped++; if (skb) --- 1081,1084 ---- *************** *** 1029,1033 **** length, skb->protocol); } ! return retval; } EXPORT_SYMBOL_GPL(usbnet_start_xmit); --- 1089,1093 ---- length, skb->protocol); } ! return NETDEV_TX_OK; } EXPORT_SYMBOL_GPL(usbnet_start_xmit); *************** *** 1096,1100 **** - /*------------------------------------------------------------------------- * --- 1156,1159 ---- *************** *** 1193,1196 **** --- 1252,1256 ---- skb_queue_head_init (&dev->txq); skb_queue_head_init (&dev->done); + skb_queue_head_init(&dev->rxq_pause); dev->bh.func = usbnet_bh; dev->bh.data = (unsigned long) dev; |