summaryrefslogtreecommitdiffstats
path: root/drivers/usb/misc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/misc')
-rw-r--r--drivers/usb/misc/adutux.c31
-rw-r--r--drivers/usb/misc/auerswald.c6
-rw-r--r--drivers/usb/misc/berry_charge.c35
-rw-r--r--drivers/usb/misc/idmouse.c54
-rw-r--r--drivers/usb/misc/iowarrior.c26
-rw-r--r--drivers/usb/misc/ldusb.c33
-rw-r--r--drivers/usb/misc/legousbtower.c24
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.c38
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_con.c25
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_init.h2
-rw-r--r--drivers/usb/misc/usblcd.c67
11 files changed, 140 insertions, 201 deletions
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c
index 77145f9db04..d72c42e5f22 100644
--- a/drivers/usb/misc/adutux.c
+++ b/drivers/usb/misc/adutux.c
@@ -108,8 +108,6 @@ struct adu_device {
struct urb* interrupt_out_urb;
};
-/* prevent races between open() and disconnect */
-static DEFINE_MUTEX(disconnect_mutex);
static struct usb_driver adu_driver;
static void adu_debug_data(int level, const char *function, int size,
@@ -256,8 +254,6 @@ static int adu_open(struct inode *inode, struct file *file)
subminor = iminor(inode);
- mutex_lock(&disconnect_mutex);
-
interface = usb_find_interface(&adu_driver, subminor);
if (!interface) {
err("%s - error, can't find device for minor %d",
@@ -306,7 +302,6 @@ static int adu_open(struct inode *inode, struct file *file)
up(&dev->sem);
exit_no_device:
- mutex_unlock(&disconnect_mutex);
dbg(2,"%s : leave, return value %d ", __FUNCTION__, retval);
return retval;
@@ -318,12 +313,6 @@ static int adu_release_internal(struct adu_device *dev)
dbg(2," %s : enter", __FUNCTION__);
- if (dev->udev == NULL) {
- /* the device was unplugged before the file was released */
- adu_delete(dev);
- goto exit;
- }
-
/* decrement our usage count for the device */
--dev->open_count;
dbg(2," %s : open count %d", __FUNCTION__, dev->open_count);
@@ -332,7 +321,6 @@ static int adu_release_internal(struct adu_device *dev)
dev->open_count = 0;
}
-exit:
dbg(2," %s : leave", __FUNCTION__);
return retval;
}
@@ -367,8 +355,15 @@ static int adu_release(struct inode *inode, struct file *file)
goto exit;
}
- /* do the work */
- retval = adu_release_internal(dev);
+ if (dev->udev == NULL) {
+ /* the device was unplugged before the file was released */
+ up(&dev->sem);
+ adu_delete(dev);
+ dev = NULL;
+ } else {
+ /* do the work */
+ retval = adu_release_internal(dev);
+ }
exit:
if (dev)
@@ -831,19 +826,17 @@ static void adu_disconnect(struct usb_interface *interface)
dbg(2," %s : enter", __FUNCTION__);
- mutex_lock(&disconnect_mutex); /* not interruptible */
-
dev = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
- down(&dev->sem); /* not interruptible */
-
minor = dev->minor;
/* give back our minor */
usb_deregister_dev(interface, &adu_class);
dev->minor = 0;
+ down(&dev->sem); /* not interruptible */
+
/* if the device is not opened, then we clean up right now */
dbg(2," %s : open count %d", __FUNCTION__, dev->open_count);
if (!dev->open_count) {
@@ -854,8 +847,6 @@ static void adu_disconnect(struct usb_interface *interface)
up(&dev->sem);
}
- mutex_unlock(&disconnect_mutex);
-
dev_info(&interface->dev, "ADU device adutux%d now disconnected",
(minor - ADU_MINOR_BASE));
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
index cac1500cba6..1fd5fc220cd 100644
--- a/drivers/usb/misc/auerswald.c
+++ b/drivers/usb/misc/auerswald.c
@@ -2034,12 +2034,12 @@ static void auerswald_disconnect (struct usb_interface *intf)
if (!cp)
return;
- down (&cp->mutex);
- info ("device /dev/%s now disconnecting", cp->name);
-
/* give back our USB minor number */
usb_deregister_dev(intf, &auerswald_class);
+ down (&cp->mutex);
+ info ("device /dev/%s now disconnecting", cp->name);
+
/* Stop the interrupt endpoint */
auerswald_int_release (cp);
diff --git a/drivers/usb/misc/berry_charge.c b/drivers/usb/misc/berry_charge.c
index b15f2fd8dab..92c1d2768df 100644
--- a/drivers/usb/misc/berry_charge.c
+++ b/drivers/usb/misc/berry_charge.c
@@ -26,8 +26,11 @@
#define RIM_VENDOR 0x0fca
#define BLACKBERRY 0x0001
+#define BLACKBERRY_PEARL_DUAL 0x0004
+#define BLACKBERRY_PEARL 0x0006
static int debug;
+static int pearl_dual_mode = 1;
#ifdef dbg
#undef dbg
@@ -38,6 +41,8 @@ static int debug;
static struct usb_device_id id_table [] = {
{ USB_DEVICE(RIM_VENDOR, BLACKBERRY) },
+ { USB_DEVICE(RIM_VENDOR, BLACKBERRY_PEARL) },
+ { USB_DEVICE(RIM_VENDOR, BLACKBERRY_PEARL_DUAL) },
{ }, /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, id_table);
@@ -86,6 +91,30 @@ static int magic_charge(struct usb_device *udev)
return retval;
}
+static int magic_dual_mode(struct usb_device *udev)
+{
+ char *dummy_buffer = kzalloc(2, GFP_KERNEL);
+ int retval;
+
+ if (!dummy_buffer)
+ return -ENOMEM;
+
+ /* send magic command so that the Blackberry Pearl device exposes
+ * two interfaces: both the USB mass-storage one and one which can
+ * be used for database access. */
+ dbg(&udev->dev, "Sending magic pearl command\n");
+ retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+ 0xa9, 0xc0, 1, 1, dummy_buffer, 2, 100);
+ dbg(&udev->dev, "Magic pearl command returned %d\n", retval);
+
+ dbg(&udev->dev, "Calling set_configuration\n");
+ retval = usb_driver_set_configuration(udev, 1);
+ if (retval)
+ dev_err(&udev->dev, "Set Configuration failed :%d.\n", retval);
+
+ return retval;
+}
+
static int berry_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
@@ -105,6 +134,10 @@ static int berry_probe(struct usb_interface *intf,
/* turn the power on */
magic_charge(udev);
+ if ((le16_to_cpu(udev->descriptor.idProduct) == BLACKBERRY_PEARL) &&
+ (pearl_dual_mode))
+ magic_dual_mode(udev);
+
/* we don't really want to bind to the device, userspace programs can
* handle the syncing just fine, so get outta here. */
return -ENODEV;
@@ -138,3 +171,5 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@suse.de>");
module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug enabled or not");
+module_param(pearl_dual_mode, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(pearl_dual_mode, "Change Blackberry Pearl to run in dual mode");
diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c
index 8d0e360636e..e6fd024024f 100644
--- a/drivers/usb/misc/idmouse.c
+++ b/drivers/usb/misc/idmouse.c
@@ -119,9 +119,6 @@ static struct usb_driver idmouse_driver = {
.id_table = idmouse_table,
};
-/* prevent races between open() and disconnect() */
-static DEFINE_MUTEX(disconnect_mutex);
-
static int idmouse_create_image(struct usb_idmouse *dev)
{
int bytes_read;
@@ -211,21 +208,15 @@ static int idmouse_open(struct inode *inode, struct file *file)
struct usb_interface *interface;
int result;
- /* prevent disconnects */
- mutex_lock(&disconnect_mutex);
-
/* get the interface from minor number and driver information */
interface = usb_find_interface (&idmouse_driver, iminor (inode));
- if (!interface) {
- mutex_unlock(&disconnect_mutex);
+ if (!interface)
return -ENODEV;
- }
+
/* get the device information block from the interface */
dev = usb_get_intfdata(interface);
- if (!dev) {
- mutex_unlock(&disconnect_mutex);
+ if (!dev)
return -ENODEV;
- }
/* lock this device */
down(&dev->sem);
@@ -255,9 +246,6 @@ error:
/* unlock this device */
up(&dev->sem);
-
- /* unlock the disconnect semaphore */
- mutex_unlock(&disconnect_mutex);
return result;
}
@@ -265,15 +253,10 @@ static int idmouse_release(struct inode *inode, struct file *file)
{
struct usb_idmouse *dev;
- /* prevent a race condition with open() */
- mutex_lock(&disconnect_mutex);
-
dev = file->private_data;
- if (dev == NULL) {
- mutex_unlock(&disconnect_mutex);
+ if (dev == NULL)
return -ENODEV;
- }
/* lock our device */
down(&dev->sem);
@@ -281,7 +264,6 @@ static int idmouse_release(struct inode *inode, struct file *file)
/* are we really open? */
if (dev->open <= 0) {
up(&dev->sem);
- mutex_unlock(&disconnect_mutex);
return -ENODEV;
}
@@ -291,12 +273,9 @@ static int idmouse_release(struct inode *inode, struct file *file)
/* the device was unplugged before the file was released */
up(&dev->sem);
idmouse_delete(dev);
- mutex_unlock(&disconnect_mutex);
- return 0;
+ } else {
+ up(&dev->sem);
}
-
- up(&dev->sem);
- mutex_unlock(&disconnect_mutex);
return 0;
}
@@ -391,30 +370,27 @@ static void idmouse_disconnect(struct usb_interface *interface)
{
struct usb_idmouse *dev;
- /* prevent races with open() */
- mutex_lock(&disconnect_mutex);
-
/* get device structure */
dev = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
- /* lock it */
- down(&dev->sem);
-
/* give back our minor */
usb_deregister_dev(interface, &idmouse_class);
+ /* lock it */
+ down(&dev->sem);
+
/* prevent device read, write and ioctl */
dev->present = 0;
- /* unlock */
- up(&dev->sem);
-
/* if the device is opened, idmouse_release will clean this up */
- if (!dev->open)
+ if (!dev->open) {
+ up(&dev->sem);
idmouse_delete(dev);
-
- mutex_unlock(&disconnect_mutex);
+ } else {
+ /* unlock */
+ up(&dev->sem);
+ }
info("%s disconnected", DRIVER_DESC);
}
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c
index 3bb33f7bfa3..28548d18671 100644
--- a/drivers/usb/misc/iowarrior.c
+++ b/drivers/usb/misc/iowarrior.c
@@ -100,8 +100,6 @@ struct iowarrior {
/*--------------*/
/* globals */
/*--------------*/
-/* prevent races between open() and disconnect() */
-static DECLARE_MUTEX(disconnect_sem);
/*
* USB spec identifies 5 second timeouts.
@@ -600,22 +598,18 @@ static int iowarrior_open(struct inode *inode, struct file *file)
subminor = iminor(inode);
- /* prevent disconnects */
- down(&disconnect_sem);
-
interface = usb_find_interface(&iowarrior_driver, subminor);
if (!interface) {
err("%s - error, can't find device for minor %d", __FUNCTION__,
subminor);
- retval = -ENODEV;
- goto out;
+ return -ENODEV;
}
dev = usb_get_intfdata(interface);
- if (!dev) {
- retval = -ENODEV;
- goto out;
- }
+ if (!dev)
+ return -ENODEV;
+
+ mutex_lock(&dev->mutex);
/* Only one process can open each device, no sharing. */
if (dev->opened) {
@@ -636,7 +630,7 @@ static int iowarrior_open(struct inode *inode, struct file *file)
retval = 0;
out:
- up(&disconnect_sem);
+ mutex_unlock(&dev->mutex);
return retval;
}
@@ -868,19 +862,16 @@ static void iowarrior_disconnect(struct usb_interface *interface)
struct iowarrior *dev;
int minor;
- /* prevent races with open() */
- down(&disconnect_sem);
-
dev = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
- mutex_lock(&dev->mutex);
-
minor = dev->minor;
/* give back our minor */
usb_deregister_dev(interface, &iowarrior_class);
+ mutex_lock(&dev->mutex);
+
/* prevent device read, write and ioctl */
dev->present = 0;
@@ -898,7 +889,6 @@ static void iowarrior_disconnect(struct usb_interface *interface)
/* no process is using the device, cleanup now */
iowarrior_delete(dev);
}
- up(&disconnect_sem);
dev_info(&interface->dev, "I/O-Warror #%d now disconnected\n",
minor - IOWARRIOR_MINOR_BASE);
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
index 7bad4940476..5e950b90c54 100644
--- a/drivers/usb/misc/ldusb.c
+++ b/drivers/usb/misc/ldusb.c
@@ -176,9 +176,6 @@ struct ld_usb {
int interrupt_out_busy;
};
-/* prevent races between open() and disconnect() */
-static DEFINE_MUTEX(disconnect_mutex);
-
static struct usb_driver ld_usb_driver;
/**
@@ -298,35 +295,28 @@ static int ld_usb_open(struct inode *inode, struct file *file)
{
struct ld_usb *dev;
int subminor;
- int retval = 0;
+ int retval;
struct usb_interface *interface;
nonseekable_open(inode, file);
subminor = iminor(inode);
- mutex_lock(&disconnect_mutex);
-
interface = usb_find_interface(&ld_usb_driver, subminor);
if (!interface) {
err("%s - error, can't find device for minor %d\n",
__FUNCTION__, subminor);
- retval = -ENODEV;
- goto unlock_disconnect_exit;
+ return -ENODEV;
}
dev = usb_get_intfdata(interface);
- if (!dev) {
- retval = -ENODEV;
- goto unlock_disconnect_exit;
- }
+ if (!dev)
+ return -ENODEV;
/* lock this device */
- if (down_interruptible(&dev->sem)) {
- retval = -ERESTARTSYS;
- goto unlock_disconnect_exit;
- }
+ if (down_interruptible(&dev->sem))
+ return -ERESTARTSYS;
/* allow opening only once */
if (dev->open_count) {
@@ -366,9 +356,6 @@ static int ld_usb_open(struct inode *inode, struct file *file)
unlock_exit:
up(&dev->sem);
-unlock_disconnect_exit:
- mutex_unlock(&disconnect_mutex);
-
return retval;
}
@@ -766,18 +753,16 @@ static void ld_usb_disconnect(struct usb_interface *intf)
struct ld_usb *dev;
int minor;
- mutex_lock(&disconnect_mutex);
-
dev = usb_get_intfdata(intf);
usb_set_intfdata(intf, NULL);
- down(&dev->sem);
-
minor = intf->minor;
/* give back our minor */
usb_deregister_dev(intf, &ld_usb_class);
+ down(&dev->sem);
+
/* if the device is not opened, then we clean up right now */
if (!dev->open_count) {
up(&dev->sem);
@@ -787,8 +772,6 @@ static void ld_usb_disconnect(struct usb_interface *intf)
up(&dev->sem);
}
- mutex_unlock(&disconnect_mutex);
-
dev_info(&intf->dev, "LD USB Device #%d now disconnected\n",
(minor - USB_LD_MINOR_BASE));
}
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index 1713e19a789..2ed0daea894 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -254,9 +254,6 @@ static int tower_probe (struct usb_interface *interface, const struct usb_devic
static void tower_disconnect (struct usb_interface *interface);
-/* prevent races between open() and disconnect */
-static DEFINE_MUTEX (disconnect_mutex);
-
/* file operations needed when we register this driver */
static const struct file_operations tower_fops = {
.owner = THIS_MODULE,
@@ -344,28 +341,26 @@ static int tower_open (struct inode *inode, struct file *file)
nonseekable_open(inode, file);
subminor = iminor(inode);
- mutex_lock (&disconnect_mutex);
-
interface = usb_find_interface (&tower_driver, subminor);
if (!interface) {
err ("%s - error, can't find device for minor %d",
__FUNCTION__, subminor);
retval = -ENODEV;
- goto unlock_disconnect_exit;
+ goto exit;
}
dev = usb_get_intfdata(interface);
if (!dev) {
retval = -ENODEV;
- goto unlock_disconnect_exit;
+ goto exit;
}
/* lock this device */
if (down_interruptible (&dev->sem)) {
retval = -ERESTARTSYS;
- goto unlock_disconnect_exit;
+ goto exit;
}
/* allow opening only once */
@@ -421,9 +416,7 @@ static int tower_open (struct inode *inode, struct file *file)
unlock_exit:
up (&dev->sem);
-unlock_disconnect_exit:
- mutex_unlock (&disconnect_mutex);
-
+exit:
dbg(2, "%s: leave, return value %d ", __FUNCTION__, retval);
return retval;
@@ -993,19 +986,16 @@ static void tower_disconnect (struct usb_interface *interface)
dbg(2, "%s: enter", __FUNCTION__);
- mutex_lock (&disconnect_mutex);
-
dev = usb_get_intfdata (interface);
usb_set_intfdata (interface, NULL);
-
- down (&dev->sem);
-
minor = dev->minor;
/* give back our minor */
usb_deregister_dev (interface, &tower_class);
+ down (&dev->sem);
+
/* if the device is not opened, then we clean up right now */
if (!dev->open_count) {
up (&dev->sem);
@@ -1015,8 +1005,6 @@ static void tower_disconnect (struct usb_interface *interface)
up (&dev->sem);
}
- mutex_unlock (&disconnect_mutex);
-
info("LEGO USB Tower #%d now disconnected", (minor - LEGO_USB_TOWER_MINOR_BASE));
dbg(2, "%s: leave", __FUNCTION__);
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index 6f8b134a79c..9f37ba44c13 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -72,8 +72,6 @@ MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES
static struct usb_driver sisusb_driver;
-DEFINE_MUTEX(disconnect_mutex);
-
static void
sisusb_free_buffers(struct sisusb_usb_data *sisusb)
{
@@ -2511,31 +2509,24 @@ sisusb_open(struct inode *inode, struct file *file)
struct usb_interface *interface;
int subminor = iminor(inode);
- mutex_lock(&disconnect_mutex);
-
if (!(interface = usb_find_interface(&sisusb_driver, subminor))) {
printk(KERN_ERR "sisusb[%d]: Failed to find interface\n",
subminor);
- mutex_unlock(&disconnect_mutex);
return -ENODEV;
}
- if (!(sisusb = usb_get_intfdata(interface))) {
- mutex_unlock(&disconnect_mutex);
+ if (!(sisusb = usb_get_intfdata(interface)))
return -ENODEV;
- }
mutex_lock(&sisusb->lock);
if (!sisusb->present || !sisusb->ready) {
mutex_unlock(&sisusb->lock);
- mutex_unlock(&disconnect_mutex);
return -ENODEV;
}
if (sisusb->isopen) {
mutex_unlock(&sisusb->lock);
- mutex_unlock(&disconnect_mutex);
return -EBUSY;
}
@@ -2543,7 +2534,6 @@ sisusb_open(struct inode *inode, struct file *file)
if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) {
if (sisusb_init_gfxdevice(sisusb, 0)) {
mutex_unlock(&sisusb->lock);
- mutex_unlock(&disconnect_mutex);
printk(KERN_ERR
"sisusbvga[%d]: Failed to initialize "
"device\n",
@@ -2552,7 +2542,6 @@ sisusb_open(struct inode *inode, struct file *file)
}
} else {
mutex_unlock(&sisusb->lock);
- mutex_unlock(&disconnect_mutex);
printk(KERN_ERR
"sisusbvga[%d]: Device not attached to "
"USB 2.0 hub\n",
@@ -2570,8 +2559,6 @@ sisusb_open(struct inode *inode, struct file *file)
mutex_unlock(&sisusb->lock);
- mutex_unlock(&disconnect_mutex);
-
return 0;
}
@@ -2601,12 +2588,8 @@ sisusb_release(struct inode *inode, struct file *file)
struct sisusb_usb_data *sisusb;
int myminor;
- mutex_lock(&disconnect_mutex);
-
- if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) {
- mutex_unlock(&disconnect_mutex);
+ if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
return -ENODEV;
- }
mutex_lock(&sisusb->lock);
@@ -2626,8 +2609,6 @@ sisusb_release(struct inode *inode, struct file *file)
/* decrement the usage count on our device */
kref_put(&sisusb->kref, sisusb_delete);
- mutex_unlock(&disconnect_mutex);
-
return 0;
}
@@ -3383,12 +3364,9 @@ static void sisusb_disconnect(struct usb_interface *intf)
sisusb_console_exit(sisusb);
#endif
- /* The above code doesn't need the disconnect
- * semaphore to be down; its meaning is to
- * protect all other routines from the disconnect
- * case, not the other way round.
- */
- mutex_lock(&disconnect_mutex);
+ minor = sisusb->minor;
+
+ usb_deregister_dev(intf, &usb_sisusb_class);
mutex_lock(&sisusb->lock);
@@ -3396,12 +3374,8 @@ static void sisusb_disconnect(struct usb_interface *intf)
if (!sisusb_wait_all_out_complete(sisusb))
sisusb_kill_all_busy(sisusb);
- minor = sisusb->minor;
-
usb_set_intfdata(intf, NULL);
- usb_deregister_dev(intf, &usb_sisusb_class);
-
#ifdef SISUSB_OLD_CONFIG_COMPAT
if (sisusb->ioctl32registered) {
int ret;
@@ -3426,8 +3400,6 @@ static void sisusb_disconnect(struct usb_interface *intf)
/* decrement our usage count */
kref_put(&sisusb->kref, sisusb_delete);
- mutex_unlock(&disconnect_mutex);
-
printk(KERN_INFO "sisusbvga[%d]: Disconnected\n", minor);
}
diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c
index 5947afb0017..8d0edc867f3 100644
--- a/drivers/usb/misc/sisusbvga/sisusb_con.c
+++ b/drivers/usb/misc/sisusbvga/sisusb_con.c
@@ -214,18 +214,13 @@ sisusbcon_init(struct vc_data *c, int init)
* are set up/restored.
*/
- mutex_lock(&disconnect_mutex);
-
- if (!(sisusb = sisusb_get_sisusb(c->vc_num))) {
- mutex_unlock(&disconnect_mutex);
+ if (!(sisusb = sisusb_get_sisusb(c->vc_num)))
return;
- }
mutex_lock(&sisusb->lock);
if (!sisusb_sisusb_valid(sisusb)) {
mutex_unlock(&sisusb->lock);
- mutex_unlock(&disconnect_mutex);
return;
}
@@ -264,8 +259,6 @@ sisusbcon_init(struct vc_data *c, int init)
mutex_unlock(&sisusb->lock);
- mutex_unlock(&disconnect_mutex);
-
if (init) {
c->vc_cols = cols;
c->vc_rows = rows;
@@ -284,12 +277,8 @@ sisusbcon_deinit(struct vc_data *c)
* and others, ie not under our control.
*/
- mutex_lock(&disconnect_mutex);
-
- if (!(sisusb = sisusb_get_sisusb(c->vc_num))) {
- mutex_unlock(&disconnect_mutex);
+ if (!(sisusb = sisusb_get_sisusb(c->vc_num)))
return;
- }
mutex_lock(&sisusb->lock);
@@ -314,8 +303,6 @@ sisusbcon_deinit(struct vc_data *c)
/* decrement the usage count on our sisusb */
kref_put(&sisusb->kref, sisusb_delete);
-
- mutex_unlock(&disconnect_mutex);
}
/* interface routine */
@@ -1490,14 +1477,11 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
{
int i, ret, minor = sisusb->minor;
- mutex_lock(&disconnect_mutex);
-
mutex_lock(&sisusb->lock);
/* Erm.. that should not happen */
if (sisusb->haveconsole || !sisusb->SiS_Pr) {
mutex_unlock(&sisusb->lock);
- mutex_unlock(&disconnect_mutex);
return 1;
}
@@ -1508,14 +1492,12 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
first > MAX_NR_CONSOLES ||
last > MAX_NR_CONSOLES) {
mutex_unlock(&sisusb->lock);
- mutex_unlock(&disconnect_mutex);
return 1;
}
/* If gfxcore not initialized or no consoles given, quit graciously */
if (!sisusb->gfxinit || first < 1 || last < 1) {
mutex_unlock(&sisusb->lock);
- mutex_unlock(&disconnect_mutex);
return 0;
}
@@ -1526,7 +1508,6 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
/* Set up text mode (and upload default font) */
if (sisusb_reset_text_mode(sisusb, 1)) {
mutex_unlock(&sisusb->lock);
- mutex_unlock(&disconnect_mutex);
printk(KERN_ERR
"sisusbvga[%d]: Failed to set up text mode\n",
minor);
@@ -1550,7 +1531,6 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
/* Allocate screen buffer */
if (!(sisusb->scrbuf = (unsigned long)vmalloc(sisusb->scrbuf_size))) {
mutex_unlock(&sisusb->lock);
- mutex_unlock(&disconnect_mutex);
printk(KERN_ERR
"sisusbvga[%d]: Failed to allocate screen buffer\n",
minor);
@@ -1558,7 +1538,6 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
}
mutex_unlock(&sisusb->lock);
- mutex_unlock(&disconnect_mutex);
/* Now grab the desired console(s) */
ret = take_over_console(&sisusb_con, first - 1, last - 1, 0);
diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.h b/drivers/usb/misc/sisusbvga/sisusb_init.h
index f05f83268af..864bc0e9659 100644
--- a/drivers/usb/misc/sisusbvga/sisusb_init.h
+++ b/drivers/usb/misc/sisusbvga/sisusb_init.h
@@ -808,8 +808,6 @@ static const struct SiS_VCLKData SiSUSB_VCLKData[] =
{ 0x2b,0xc2, 35} /* 0x71 768@576@60 */
};
-extern struct mutex disconnect_mutex;
-
int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo);
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index 12bad8a205a..504f7221b0d 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -45,13 +45,13 @@ struct usb_lcd {
struct kref kref;
struct semaphore limit_sem; /* to stop writes at full throttle from
* using up all RAM */
+ struct usb_anchor submitted; /* URBs to wait for before suspend */
};
#define to_lcd_dev(d) container_of(d, struct usb_lcd, kref)
#define USB_LCD_CONCURRENT_WRITES 5
static struct usb_driver lcd_driver;
-static DEFINE_MUTEX(usb_lcd_open_mutex);
static void lcd_delete(struct kref *kref)
@@ -68,35 +68,35 @@ static int lcd_open(struct inode *inode, struct file *file)
{
struct usb_lcd *dev;
struct usb_interface *interface;
- int subminor;
- int retval = 0;
+ int subminor, r;
subminor = iminor(inode);
- mutex_lock(&usb_lcd_open_mutex);
interface = usb_find_interface(&lcd_driver, subminor);
if (!interface) {
err ("USBLCD: %s - error, can't find device for minor %d",
__FUNCTION__, subminor);
- retval = -ENODEV;
- goto exit;
+ return -ENODEV;
}
dev = usb_get_intfdata(interface);
- if (!dev) {
- retval = -ENODEV;
- goto exit;
- }
+ if (!dev)
+ return -ENODEV;
/* increment our usage count for the device */
kref_get(&dev->kref);
+ /* grab a power reference */
+ r = usb_autopm_get_interface(interface);
+ if (r < 0) {
+ kref_put(&dev->kref, lcd_delete);
+ return r;
+ }
+
/* save our object in the file's private structure */
file->private_data = dev;
-exit:
- mutex_unlock(&usb_lcd_open_mutex);
- return retval;
+ return 0;
}
static int lcd_release(struct inode *inode, struct file *file)
@@ -108,6 +108,7 @@ static int lcd_release(struct inode *inode, struct file *file)
return -ENODEV;
/* decrement the count on our device */
+ usb_autopm_put_interface(dev->interface);
kref_put(&dev->kref, lcd_delete);
return 0;
}
@@ -233,12 +234,14 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer, siz
usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
buf, count, lcd_write_bulk_callback, dev);
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ usb_anchor_urb(urb, &dev->submitted);
/* send the data out the bulk port */
retval = usb_submit_urb(urb, GFP_KERNEL);
if (retval) {
err("USBLCD: %s - failed submitting write urb, error %d", __FUNCTION__, retval);
- goto error;
+ goto error_unanchor;
}
/* release our reference to this urb, the USB core will eventually free it entirely */
@@ -246,7 +249,8 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer, siz
exit:
return count;
-
+error_unanchor:
+ usb_unanchor_urb(urb);
error:
usb_buffer_free(dev->udev, count, buf, urb->transfer_dma);
usb_free_urb(urb);
@@ -291,6 +295,7 @@ static int lcd_probe(struct usb_interface *interface, const struct usb_device_id
}
kref_init(&dev->kref);
sema_init(&dev->limit_sem, USB_LCD_CONCURRENT_WRITES);
+ init_usb_anchor(&dev->submitted);
dev->udev = usb_get_dev(interface_to_usbdev(interface));
dev->interface = interface;
@@ -358,22 +363,41 @@ error:
return retval;
}
+static void lcd_draw_down(struct usb_lcd *dev)
+{
+ int time;
+
+ time = usb_wait_anchor_empty_timeout(&dev->submitted, 1000);
+ if (!time)
+ usb_kill_anchored_urbs(&dev->submitted);
+}
+
+static int lcd_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ struct usb_lcd *dev = usb_get_intfdata(intf);
+
+ if (!dev)
+ return 0;
+ lcd_draw_down(dev);
+ return 0;
+}
+
+static int lcd_resume (struct usb_interface *intf)
+{
+ return 0;
+}
+
static void lcd_disconnect(struct usb_interface *interface)
{
struct usb_lcd *dev;
int minor = interface->minor;
- /* prevent skel_open() from racing skel_disconnect() */
- mutex_lock(&usb_lcd_open_mutex);
-
dev = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
/* give back our minor */
usb_deregister_dev(interface, &lcd_class);
- mutex_unlock(&usb_lcd_open_mutex);
-
/* decrement our usage count */
kref_put(&dev->kref, lcd_delete);
@@ -384,7 +408,10 @@ static struct usb_driver lcd_driver = {
.name = "usblcd",
.probe = lcd_probe,
.disconnect = lcd_disconnect,
+ .suspend = lcd_suspend,
+ .resume = lcd_resume,
.id_table = id_table,
+ .supports_autosuspend = 1,
};
static int __init usb_lcd_init(void)