static int wdm_suspend(struct usb_interface *intf, pm_message_t message) { struct wdm_device *desc = usb_get_intfdata(intf); int rv = 0; dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor); /* if this is an autosuspend the caller does the locking */ if (!PMSG_IS_AUTO(message)) mutex_lock(&desc->lock); spin_lock_irq(&desc->iuspin); if (PMSG_IS_AUTO(message) && (test_bit(WDM_IN_USE, &desc->flags) || test_bit(WDM_RESPONDING, &desc->flags))) { spin_unlock_irq(&desc->iuspin); rv = -EBUSY; } else { set_bit(WDM_SUSPENDING, &desc->flags); spin_unlock_irq(&desc->iuspin); /* callback submits work - order is essential */ kill_urbs(desc); cancel_work_sync(&desc->rxwork); } if (!PMSG_IS_AUTO(message)) mutex_unlock(&desc->lock); return rv; }
static void wdm_disconnect(struct usb_interface *intf) { struct wdm_device *desc; unsigned long flags; usb_deregister_dev(intf, &wdm_class); mutex_lock(&wdm_mutex); desc = usb_get_intfdata(intf); /* the spinlock makes sure no new urbs are generated in the callbacks */ spin_lock_irqsave(&desc->iuspin, flags); set_bit(WDM_DISCONNECTING, &desc->flags); set_bit(WDM_READ, &desc->flags); /* to terminate pending flushes */ clear_bit(WDM_IN_USE, &desc->flags); spin_unlock_irqrestore(&desc->iuspin, flags); mutex_lock(&desc->lock); kill_urbs(desc); cancel_work_sync(&desc->rxwork); mutex_unlock(&desc->lock); wake_up_all(&desc->wait); if (!desc->count) cleanup(desc); mutex_unlock(&wdm_mutex); }
static int wdm_release(struct inode *inode, struct file *file) { struct wdm_device *desc = file->private_data; mutex_lock(&wdm_mutex); /* using write lock to protect desc->count */ mutex_lock(&desc->wlock); desc->count--; mutex_unlock(&desc->wlock); if (!desc->count) { if (!test_bit(WDM_DISCONNECTING, &desc->flags)) { dev_dbg(&desc->intf->dev, "wdm_release: cleanup"); kill_urbs(desc); desc->intf->needs_remote_wakeup = 0; } else { /* must avoid dev_printk here as desc->intf is invalid */ pr_debug(KBUILD_MODNAME " %s: device gone - cleaning up\n", __func__); cleanup(desc); } } mutex_unlock(&wdm_mutex); return 0; }
static int wdm_release(struct inode *inode, struct file *file) { struct wdm_device *desc = file->private_data; mutex_lock(&wdm_mutex); mutex_lock(&desc->lock); desc->count--; mutex_unlock(&desc->lock); if (!desc->count) { dev_dbg(&desc->intf->dev, "wdm_release: cleanup"); kill_urbs(desc); if (!test_bit(WDM_DISCONNECTING, &desc->flags)) desc->intf->needs_remote_wakeup = 0; } mutex_unlock(&wdm_mutex); return 0; }
static int wdm_pre_reset(struct usb_interface *intf) { struct wdm_device *desc = usb_get_intfdata(intf); kill_urbs(desc); /* * we notify everybody using poll of * an exceptional situation * must be done before recovery lest a spontaneous * message from the device is lost */ spin_lock_irq(&desc->iuspin); desc->rerr = -EINTR; spin_unlock_irq(&desc->iuspin); wake_up_all(&desc->wait); mutex_lock(&desc->lock); return 0; }
static int wdm_suspend(struct usb_interface *intf, pm_message_t message) { struct wdm_device *desc = usb_get_intfdata(intf); int rv = 0; dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor); mutex_lock(&desc->plock); #ifdef CONFIG_PM if (interface_to_usbdev(desc->intf)->auto_pm && test_bit(WDM_IN_USE, &desc->flags)) { rv = -EBUSY; } else { #endif cancel_work_sync(&desc->rxwork); kill_urbs(desc); #ifdef CONFIG_PM } #endif mutex_unlock(&desc->plock); return rv; }