int usbnet_suspend (struct usb_interface *intf, pm_message_t message) { struct usbnet *dev = usb_get_intfdata(intf); pr_info("%s+\n", __func__); if (!dev->suspend_count++) { spin_lock_irq(&dev->txq.lock); /* don't autosuspend while transmitting */ if (dev->txq.qlen && (message.event & PM_EVENT_AUTO)) { spin_unlock_irq(&dev->txq.lock); --dev->suspend_count; return -EBUSY; } else { set_bit(EVENT_DEV_ASLEEP, &dev->flags); spin_unlock_irq(&dev->txq.lock); } /* * accelerate emptying of the rx and queues, to avoid * having everything error out. */ pr_info("%s+:d\n", __func__); netif_device_detach (dev->net); pr_info("%s+:t\n", __func__); usbnet_terminate_urbs(dev); pr_info("%s+:k\n", __func__); usb_kill_urb(dev->interrupt); /* * reattach so runtime management can use and * wake the device */ pr_info("%s+:a\n", __func__); netif_device_attach (dev->net); } pr_info("%s-\n", __func__); return 0; }
int usbnet_suspend (struct usb_interface *intf, pm_message_t message) { struct usbnet *dev = usb_get_intfdata(intf); if (!dev->suspend_count++) { #if defined(CONFIG_ERICSSON_F3307_ENABLE) spin_lock_irq(&dev->txq.lock); /* don't autosuspend while transmitting */ if (dev->txq.qlen && (message.event & PM_EVENT_AUTO)) { spin_unlock_irq(&dev->txq.lock); return -EBUSY; } else { set_bit(EVENT_DEV_ASLEEP, &dev->flags); spin_unlock_irq(&dev->txq.lock); } #endif /* * accelerate emptying of the rx and queues, to avoid * having everything error out. */ netif_device_detach (dev->net); #if !defined(CONFIG_ERICSSON_F3307_ENABLE) (void) unlink_urbs (dev, &dev->rxq); (void) unlink_urbs (dev, &dev->txq); #else usbnet_terminate_urbs(dev); usb_kill_urb(dev->interrupt); #endif /* * reattach so runtime management can use and * wake the device */ netif_device_attach (dev->net); } return 0; }
static int rmnet_usb_suspend(struct usb_interface *iface, pm_message_t message) { struct usbnet *unet = usb_get_intfdata(iface); struct rmnet_ctrl_dev *dev; int i, n, rdev_cnt, unet_id; int retval = 0; rdev_cnt = unet->data[4] ? no_rmnet_insts_per_dev : 1; for (n = 0; n < rdev_cnt; n++) { unet_id = n + unet->driver_info->data * no_rmnet_insts_per_dev; unet = unet->data[4] ? unet_list[unet_id] : usb_get_intfdata(iface); dev = (struct rmnet_ctrl_dev *)unet->data[1]; spin_lock_irq(&unet->txq.lock); if (work_busy(&dev->get_encap_work) || unet->txq.qlen) { spin_unlock_irq(&unet->txq.lock); retval = -EBUSY; goto abort_suspend; } set_bit(EVENT_DEV_ASLEEP, &unet->flags); spin_unlock_irq(&unet->txq.lock); usb_kill_anchored_urbs(&dev->rx_submitted); if (work_busy(&dev->get_encap_work)) { spin_lock_irq(&unet->txq.lock); clear_bit(EVENT_DEV_ASLEEP, &unet->flags); spin_unlock_irq(&unet->txq.lock); retval = -EBUSY; goto abort_suspend; } } for (n = 0; n < rdev_cnt; n++) { unet_id = n + unet->driver_info->data * no_rmnet_insts_per_dev; unet = unet->data[4] ? unet_list[unet_id] : usb_get_intfdata(iface); dev = (struct rmnet_ctrl_dev *)unet->data[1]; netif_device_detach(unet->net); usbnet_terminate_urbs(unet); netif_device_attach(unet->net); } #if defined(CONFIG_MONITOR_STREAMING_PORT_SOCKET) && defined(CONFIG_MSM_NONSMD_PACKET_FILTER) if (use_extend_suspend_timer) { if (original_autosuspend_timer != 0) { struct usb_device *udev= unet->udev; if (udev) { use_extend_suspend_timer= false; pm_runtime_set_autosuspend_delay(&udev->dev, original_autosuspend_timer); dev_err(&udev->dev, "is_streaming_sock_connectted:%d pm_runtime_set_autosuspend_delay %d\n", is_streaming_sock_connectted, original_autosuspend_timer); } } } #endif return 0; abort_suspend: for (i = 0; i < n; i++) { unet_id = i + unet->driver_info->data * no_rmnet_insts_per_dev; unet = unet->data[4] ? unet_list[unet_id] : usb_get_intfdata(iface); dev = (struct rmnet_ctrl_dev *)unet->data[1]; rmnet_usb_ctrl_start_rx(dev); spin_lock_irq(&unet->txq.lock); clear_bit(EVENT_DEV_ASLEEP, &unet->flags); spin_unlock_irq(&unet->txq.lock); } return retval; }
static int rmnet_usb_suspend(struct usb_interface *iface, pm_message_t message) { struct usbnet *unet = usb_get_intfdata(iface); struct rmnet_ctrl_dev *dev; int i, n, rdev_cnt, unet_id; int retval = 0; rdev_cnt = unet->data[4] ? no_rmnet_insts_per_dev : 1; for (n = 0; n < rdev_cnt; n++) { unet_id = n + unet->driver_info->data * no_rmnet_insts_per_dev; unet = unet->data[4] ? unet_list[unet_id] : usb_get_intfdata(iface); dev = (struct rmnet_ctrl_dev *)unet->data[1]; spin_lock_irq(&unet->txq.lock); if (work_busy(&dev->get_encap_work) || unet->txq.qlen) { spin_unlock_irq(&unet->txq.lock); retval = -EBUSY; goto abort_suspend; } set_bit(EVENT_DEV_ASLEEP, &unet->flags); spin_unlock_irq(&unet->txq.lock); usb_kill_anchored_urbs(&dev->rx_submitted); if (work_busy(&dev->get_encap_work)) { spin_lock_irq(&unet->txq.lock); clear_bit(EVENT_DEV_ASLEEP, &unet->flags); spin_unlock_irq(&unet->txq.lock); retval = -EBUSY; goto abort_suspend; } } for (n = 0; n < rdev_cnt; n++) { unet_id = n + unet->driver_info->data * no_rmnet_insts_per_dev; unet = unet->data[4] ? unet_list[unet_id] : usb_get_intfdata(iface); dev = (struct rmnet_ctrl_dev *)unet->data[1]; netif_device_detach(unet->net); usbnet_terminate_urbs(unet); netif_device_attach(unet->net); } return 0; abort_suspend: for (i = 0; i < n; i++) { unet_id = i + unet->driver_info->data * no_rmnet_insts_per_dev; unet = unet->data[4] ? unet_list[unet_id] : usb_get_intfdata(iface); dev = (struct rmnet_ctrl_dev *)unet->data[1]; rmnet_usb_ctrl_start_rx(dev); spin_lock_irq(&unet->txq.lock); clear_bit(EVENT_DEV_ASLEEP, &unet->flags); spin_unlock_irq(&unet->txq.lock); } return retval; }
int usbnet_stop (struct net_device *net) { struct usbnet *dev = netdev_priv(net); struct driver_info *info = dev->driver_info; #if !defined(CONFIG_ERICSSON_F3307_ENABLE) int temp; #endif int retval; #if !defined(CONFIG_ERICSSON_F3307_ENABLE) DECLARE_WAIT_QUEUE_HEAD_ONSTACK (unlink_wakeup); DECLARE_WAITQUEUE (wait, current); #endif netif_stop_queue (net); if (netif_msg_ifdown (dev)) devinfo (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld", net->stats.rx_packets, net->stats.tx_packets, net->stats.rx_errors, net->stats.tx_errors ); /* 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 !defined(CONFIG_ERICSSON_F3307_ENABLE) 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); } #else if (!(info->flags & FLAG_AVOID_UNLINK_URBS)) usbnet_terminate_urbs(dev); #endif 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), * else workers could deadlock; so make workers a NOP. */ dev->flags = 0; del_timer_sync (&dev->delay); tasklet_kill (&dev->bh); #if !defined(CONFIG_ERICSSON_F3307_ENABLE) usb_autopm_put_interface(dev->intf); #else if (info->manage_power) info->manage_power(dev, 0); else usb_autopm_put_interface(dev->intf); #endif return 0; }