aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/misc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/misc')
-rw-r--r--drivers/usb/misc/Kconfig1
-rw-r--r--drivers/usb/misc/ldusb.c2
-rw-r--r--drivers/usb/misc/rio500.c80
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.c15
-rw-r--r--drivers/usb/misc/usb251xb.c135
-rw-r--r--drivers/usb/misc/usb3503.c48
6 files changed, 164 insertions, 117 deletions
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index be04c117fe80..c97f270338bf 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -142,7 +142,6 @@ config USB_FTDI_ELAN
config USB_APPLEDISPLAY
tristate "Apple Cinema Display support"
- select BACKLIGHT_LCD_SUPPORT
select BACKLIGHT_CLASS_DEVICE
help
Say Y here if you want to control the backlight of Apple Cinema
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
index 006762b72ff5..6581774bdfa4 100644
--- a/drivers/usb/misc/ldusb.c
+++ b/drivers/usb/misc/ldusb.c
@@ -307,7 +307,7 @@ static int ld_usb_open(struct inode *inode, struct file *file)
int retval;
struct usb_interface *interface;
- nonseekable_open(inode, file);
+ stream_open(inode, file);
subminor = iminor(inode);
interface = usb_find_interface(&ld_usb_driver, subminor);
diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c
index 7b9adeb3e7aa..27e9c78a791e 100644
--- a/drivers/usb/misc/rio500.c
+++ b/drivers/usb/misc/rio500.c
@@ -51,7 +51,6 @@ struct rio_usb_data {
char *obuf, *ibuf; /* transfer buffers */
char bulk_in_ep, bulk_out_ep; /* Endpoint assignments */
wait_queue_head_t wait_q; /* for timeouts */
- struct mutex lock; /* general race avoidance */
};
static DEFINE_MUTEX(rio500_mutex);
@@ -63,10 +62,8 @@ static int open_rio(struct inode *inode, struct file *file)
/* against disconnect() */
mutex_lock(&rio500_mutex);
- mutex_lock(&(rio->lock));
if (rio->isopen || !rio->present) {
- mutex_unlock(&(rio->lock));
mutex_unlock(&rio500_mutex);
return -EBUSY;
}
@@ -74,7 +71,6 @@ static int open_rio(struct inode *inode, struct file *file)
init_waitqueue_head(&rio->wait_q);
- mutex_unlock(&(rio->lock));
dev_info(&rio->rio_dev->dev, "Rio opened.\n");
mutex_unlock(&rio500_mutex);
@@ -86,9 +82,20 @@ static int close_rio(struct inode *inode, struct file *file)
{
struct rio_usb_data *rio = &rio_instance;
- rio->isopen = 0;
+ /* against disconnect() */
+ mutex_lock(&rio500_mutex);
- dev_info(&rio->rio_dev->dev, "Rio closed.\n");
+ rio->isopen = 0;
+ if (!rio->present) {
+ /* cleanup has been delayed */
+ kfree(rio->ibuf);
+ kfree(rio->obuf);
+ rio->ibuf = NULL;
+ rio->obuf = NULL;
+ } else {
+ dev_info(&rio->rio_dev->dev, "Rio closed.\n");
+ }
+ mutex_unlock(&rio500_mutex);
return 0;
}
@@ -102,7 +109,7 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg)
int retries;
int retval=0;
- mutex_lock(&(rio->lock));
+ mutex_lock(&rio500_mutex);
/* Sanity check to make sure rio is connected, powered, etc */
if (rio->present == 0 || rio->rio_dev == NULL) {
retval = -ENODEV;
@@ -246,7 +253,7 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg)
err_out:
- mutex_unlock(&(rio->lock));
+ mutex_unlock(&rio500_mutex);
return retval;
}
@@ -266,12 +273,12 @@ write_rio(struct file *file, const char __user *buffer,
int errn = 0;
int intr;
- intr = mutex_lock_interruptible(&(rio->lock));
+ intr = mutex_lock_interruptible(&rio500_mutex);
if (intr)
return -EINTR;
/* Sanity check to make sure rio is connected, powered, etc */
if (rio->present == 0 || rio->rio_dev == NULL) {
- mutex_unlock(&(rio->lock));
+ mutex_unlock(&rio500_mutex);
return -ENODEV;
}
@@ -294,7 +301,7 @@ write_rio(struct file *file, const char __user *buffer,
goto error;
}
if (signal_pending(current)) {
- mutex_unlock(&(rio->lock));
+ mutex_unlock(&rio500_mutex);
return bytes_written ? bytes_written : -EINTR;
}
@@ -332,12 +339,12 @@ write_rio(struct file *file, const char __user *buffer,
buffer += copy_size;
} while (count > 0);
- mutex_unlock(&(rio->lock));
+ mutex_unlock(&rio500_mutex);
return bytes_written ? bytes_written : -EIO;
error:
- mutex_unlock(&(rio->lock));
+ mutex_unlock(&rio500_mutex);
return errn;
}
@@ -354,12 +361,12 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
char *ibuf;
int intr;
- intr = mutex_lock_interruptible(&(rio->lock));
+ intr = mutex_lock_interruptible(&rio500_mutex);
if (intr)
return -EINTR;
/* Sanity check to make sure rio is connected, powered, etc */
if (rio->present == 0 || rio->rio_dev == NULL) {
- mutex_unlock(&(rio->lock));
+ mutex_unlock(&rio500_mutex);
return -ENODEV;
}
@@ -370,11 +377,11 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
while (count > 0) {
if (signal_pending(current)) {
- mutex_unlock(&(rio->lock));
+ mutex_unlock(&rio500_mutex);
return read_count ? read_count : -EINTR;
}
if (!rio->rio_dev) {
- mutex_unlock(&(rio->lock));
+ mutex_unlock(&rio500_mutex);
return -ENODEV;
}
this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count;
@@ -392,7 +399,7 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
count = this_read = partial;
} else if (result == -ETIMEDOUT || result == 15) { /* FIXME: 15 ??? */
if (!maxretry--) {
- mutex_unlock(&(rio->lock));
+ mutex_unlock(&rio500_mutex);
dev_err(&rio->rio_dev->dev,
"read_rio: maxretry timeout\n");
return -ETIME;
@@ -402,19 +409,19 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
finish_wait(&rio->wait_q, &wait);
continue;
} else if (result != -EREMOTEIO) {
- mutex_unlock(&(rio->lock));
+ mutex_unlock(&rio500_mutex);
dev_err(&rio->rio_dev->dev,
"Read Whoops - result:%d partial:%u this_read:%u\n",
result, partial, this_read);
return -EIO;
} else {
- mutex_unlock(&(rio->lock));
+ mutex_unlock(&rio500_mutex);
return (0);
}
if (this_read) {
if (copy_to_user(buffer, ibuf, this_read)) {
- mutex_unlock(&(rio->lock));
+ mutex_unlock(&rio500_mutex);
return -EFAULT;
}
count -= this_read;
@@ -422,7 +429,7 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
buffer += this_read;
}
}
- mutex_unlock(&(rio->lock));
+ mutex_unlock(&rio500_mutex);
return read_count;
}
@@ -447,15 +454,23 @@ static int probe_rio(struct usb_interface *intf,
{
struct usb_device *dev = interface_to_usbdev(intf);
struct rio_usb_data *rio = &rio_instance;
- int retval;
+ int retval = 0;
- dev_info(&intf->dev, "USB Rio found at address %d\n", dev->devnum);
+ mutex_lock(&rio500_mutex);
+ if (rio->present) {
+ dev_info(&intf->dev, "Second USB Rio at address %d refused\n", dev->devnum);
+ retval = -EBUSY;
+ goto bail_out;
+ } else {
+ dev_info(&intf->dev, "USB Rio found at address %d\n", dev->devnum);
+ }
retval = usb_register_dev(intf, &usb_rio_class);
if (retval) {
dev_err(&dev->dev,
"Not able to get a minor for this device.\n");
- return -ENOMEM;
+ retval = -ENOMEM;
+ goto bail_out;
}
rio->rio_dev = dev;
@@ -464,7 +479,8 @@ static int probe_rio(struct usb_interface *intf,
dev_err(&dev->dev,
"probe_rio: Not enough memory for the output buffer\n");
usb_deregister_dev(intf, &usb_rio_class);
- return -ENOMEM;
+ retval = -ENOMEM;
+ goto bail_out;
}
dev_dbg(&intf->dev, "obuf address:%p\n", rio->obuf);
@@ -473,16 +489,17 @@ static int probe_rio(struct usb_interface *intf,
"probe_rio: Not enough memory for the input buffer\n");
usb_deregister_dev(intf, &usb_rio_class);
kfree(rio->obuf);
- return -ENOMEM;
+ retval = -ENOMEM;
+ goto bail_out;
}
dev_dbg(&intf->dev, "ibuf address:%p\n", rio->ibuf);
- mutex_init(&(rio->lock));
-
usb_set_intfdata (intf, rio);
rio->present = 1;
+bail_out:
+ mutex_unlock(&rio500_mutex);
- return 0;
+ return retval;
}
static void disconnect_rio(struct usb_interface *intf)
@@ -494,12 +511,10 @@ static void disconnect_rio(struct usb_interface *intf)
if (rio) {
usb_deregister_dev(intf, &usb_rio_class);
- mutex_lock(&(rio->lock));
if (rio->isopen) {
rio->isopen = 0;
/* better let it finish - the release will do whats needed */
rio->rio_dev = NULL;
- mutex_unlock(&(rio->lock));
mutex_unlock(&rio500_mutex);
return;
}
@@ -509,7 +524,6 @@ static void disconnect_rio(struct usb_interface *intf)
dev_info(&intf->dev, "USB Rio disconnected.\n");
rio->present = 0;
- mutex_unlock(&(rio->lock));
}
mutex_unlock(&rio500_mutex);
}
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index 9560fde621ee..ea06f1fed6fa 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -3029,6 +3029,13 @@ static int sisusb_probe(struct usb_interface *intf,
mutex_init(&(sisusb->lock));
+ sisusb->sisusb_dev = dev;
+ sisusb->vrambase = SISUSB_PCI_MEMBASE;
+ sisusb->mmiobase = SISUSB_PCI_MMIOBASE;
+ sisusb->mmiosize = SISUSB_PCI_MMIOSIZE;
+ sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
+ /* Everything else is zero */
+
/* Register device */
retval = usb_register_dev(intf, &usb_sisusb_class);
if (retval) {
@@ -3039,13 +3046,7 @@ static int sisusb_probe(struct usb_interface *intf,
goto error_1;
}
- sisusb->sisusb_dev = dev;
- sisusb->minor = intf->minor;
- sisusb->vrambase = SISUSB_PCI_MEMBASE;
- sisusb->mmiobase = SISUSB_PCI_MMIOBASE;
- sisusb->mmiosize = SISUSB_PCI_MMIOSIZE;
- sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
- /* Everything else is zero */
+ sisusb->minor = intf->minor;
/* Allocate buffers */
sisusb->ibufsize = SISUSB_IBUF_SIZE;
diff --git a/drivers/usb/misc/usb251xb.c b/drivers/usb/misc/usb251xb.c
index 04684849d683..4d6ae3795a88 100644
--- a/drivers/usb/misc/usb251xb.c
+++ b/drivers/usb/misc/usb251xb.c
@@ -12,6 +12,7 @@
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
+#include <linux/gpio/driver.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/nls.h>
@@ -222,11 +223,51 @@ static const struct usb251xb_data usb2517i_data = {
.product_str = "USB2517i",
};
+#ifdef CONFIG_GPIOLIB
+static int usb251xb_check_dev_children(struct device *dev, void *child)
+{
+ if (dev->type == &i2c_adapter_type) {
+ return device_for_each_child(dev, child,
+ usb251xb_check_dev_children);
+ }
+
+ return (dev == child);
+}
+
+static int usb251x_check_gpio_chip(struct usb251xb *hub)
+{
+ struct gpio_chip *gc = gpiod_to_chip(hub->gpio_reset);
+ struct i2c_adapter *adap = hub->i2c->adapter;
+ int ret;
+
+ if (!hub->gpio_reset)
+ return 0;
+
+ if (!gc)
+ return -EINVAL;
+
+ ret = usb251xb_check_dev_children(&adap->dev, gc->parent);
+ if (ret) {
+ dev_err(hub->dev, "Reset GPIO chip is at the same i2c-bus\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+#else
+static int usb251x_check_gpio_chip(struct usb251xb *hub)
+{
+ return 0;
+}
+#endif
+
static void usb251xb_reset(struct usb251xb *hub, int state)
{
if (!hub->gpio_reset)
return;
+ i2c_lock_bus(hub->i2c->adapter, I2C_LOCK_SEGMENT);
+
gpiod_set_value_cansleep(hub->gpio_reset, state);
/* wait for hub recovery/stabilization */
@@ -234,6 +275,8 @@ static void usb251xb_reset(struct usb251xb *hub, int state)
usleep_range(500, 750); /* >=500us at power on */
else
usleep_range(1, 10); /* >=1us at power down */
+
+ i2c_unlock_bus(hub->i2c->adapter, I2C_LOCK_SEGMENT);
}
static int usb251xb_connect(struct usb251xb *hub)
@@ -331,18 +374,31 @@ out_err:
}
#ifdef CONFIG_OF
+static void usb251xb_get_ports_field(struct usb251xb *hub,
+ const char *prop_name, u8 port_cnt, u8 *fld)
+{
+ struct device *dev = hub->dev;
+ struct property *prop;
+ const __be32 *p;
+ u32 port;
+
+ of_property_for_each_u32(dev->of_node, prop_name, prop, p, port) {
+ if ((port >= 1) && (port <= port_cnt))
+ *fld |= BIT(port);
+ else
+ dev_warn(dev, "port %u doesn't exist\n", port);
+ }
+}
+
static int usb251xb_get_ofdata(struct usb251xb *hub,
struct usb251xb_data *data)
{
struct device *dev = hub->dev;
struct device_node *np = dev->of_node;
- int len, err, i;
- u32 port, property_u32 = 0;
- const u32 *cproperty_u32;
+ int len, err;
+ u32 property_u32 = 0;
const char *cproperty_char;
char str[USB251XB_STRING_BUFSIZE / 2];
- struct property *prop;
- const __be32 *p;
if (!np) {
dev_err(dev, "failed to get ofdata\n");
@@ -444,46 +500,16 @@ static int usb251xb_get_ofdata(struct usb251xb *hub,
hub->conf_data3 |= BIT(0);
hub->non_rem_dev = USB251XB_DEF_NON_REMOVABLE_DEVICES;
- cproperty_u32 = of_get_property(np, "non-removable-ports", &len);
- if (cproperty_u32 && (len / sizeof(u32)) > 0) {
- for (i = 0; i < len / sizeof(u32); i++) {
- u32 port = be32_to_cpu(cproperty_u32[i]);
-
- if ((port >= 1) && (port <= data->port_cnt))
- hub->non_rem_dev |= BIT(port);
- else
- dev_warn(dev, "NRD port %u doesn't exist\n",
- port);
- }
- }
+ usb251xb_get_ports_field(hub, "non-removable-ports", data->port_cnt,
+ &hub->non_rem_dev);
hub->port_disable_sp = USB251XB_DEF_PORT_DISABLE_SELF;
- cproperty_u32 = of_get_property(np, "sp-disabled-ports", &len);
- if (cproperty_u32 && (len / sizeof(u32)) > 0) {
- for (i = 0; i < len / sizeof(u32); i++) {
- u32 port = be32_to_cpu(cproperty_u32[i]);
-
- if ((port >= 1) && (port <= data->port_cnt))
- hub->port_disable_sp |= BIT(port);
- else
- dev_warn(dev, "PDS port %u doesn't exist\n",
- port);
- }
- }
+ usb251xb_get_ports_field(hub, "sp-disabled-ports", data->port_cnt,
+ &hub->port_disable_sp);
hub->port_disable_bp = USB251XB_DEF_PORT_DISABLE_BUS;
- cproperty_u32 = of_get_property(np, "bp-disabled-ports", &len);
- if (cproperty_u32 && (len / sizeof(u32)) > 0) {
- for (i = 0; i < len / sizeof(u32); i++) {
- u32 port = be32_to_cpu(cproperty_u32[i]);
-
- if ((port >= 1) && (port <= data->port_cnt))
- hub->port_disable_bp |= BIT(port);
- else
- dev_warn(dev, "PDB port %u doesn't exist\n",
- port);
- }
- }
+ usb251xb_get_ports_field(hub, "bp-disabled-ports", data->port_cnt,
+ &hub->port_disable_bp);
hub->max_power_sp = USB251XB_DEF_MAX_POWER_SELF;
if (!of_property_read_u32(np, "sp-max-total-current-microamp",
@@ -546,10 +572,10 @@ static int usb251xb_get_ofdata(struct usb251xb *hub,
* register controls the USB DP/DM signal swapping for each port.
*/
hub->port_swap = USB251XB_DEF_PORT_SWAP;
- of_property_for_each_u32(np, "swap-dx-lanes", prop, p, port) {
- if (port <= data->port_cnt)
- hub->port_swap |= BIT(port);
- }
+ usb251xb_get_ports_field(hub, "swap-dx-lanes", data->port_cnt,
+ &hub->port_swap);
+ if (of_get_property(np, "swap-us-lanes", NULL))
+ hub->port_swap |= BIT(0);
/* The following parameters are currently not exposed to devicetree, but
* may be as soon as needed.
@@ -621,6 +647,25 @@ static int usb251xb_probe(struct usb251xb *hub)
}
}
+ /*
+ * usb251x SMBus-slave SCL lane is muxed with CFG_SEL0 pin. So if anyone
+ * tries to work with the bus at the moment the hub reset is released,
+ * it may cause an invalid config being latched by usb251x. Particularly
+ * one of the config modes makes the hub loading a default registers
+ * value without SMBus-slave interface activation. If the hub
+ * accidentally gets this mode, this will cause the driver SMBus-
+ * functions failure. Normally we could just lock the SMBus-segment the
+ * hub i2c-interface resides for the device-specific reset timing. But
+ * the GPIO controller, which is used to handle the hub reset, might be
+ * placed at the same i2c-bus segment. In this case an error should be
+ * returned since we can't safely use the GPIO controller to clear the
+ * reset state (it may affect the hub configuration) and we can't lock
+ * the i2c-bus segment (it will cause a deadlock).
+ */
+ err = usb251x_check_gpio_chip(hub);
+ if (err)
+ return err;
+
err = usb251xb_connect(hub);
if (err) {
dev_err(dev, "Failed to connect hub (%d)\n", err);
diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c
index d5141aa79dd4..72f39a9751b5 100644
--- a/drivers/usb/misc/usb3503.c
+++ b/drivers/usb/misc/usb3503.c
@@ -172,7 +172,6 @@ static int usb3503_probe(struct usb3503 *hub)
hub->gpio_reset = pdata->gpio_reset;
hub->mode = pdata->initial_mode;
} else if (np) {
- struct clk *clk;
u32 rate = 0;
hub->port_off_mask = 0;
@@ -198,34 +197,29 @@ static int usb3503_probe(struct usb3503 *hub)
}
}
- clk = devm_clk_get(dev, "refclk");
- if (IS_ERR(clk) && PTR_ERR(clk) != -ENOENT) {
+ hub->clk = devm_clk_get_optional(dev, "refclk");
+ if (IS_ERR(hub->clk)) {
dev_err(dev, "unable to request refclk (%ld)\n",
- PTR_ERR(clk));
- return PTR_ERR(clk);
+ PTR_ERR(hub->clk));
+ return PTR_ERR(hub->clk);
}
- if (!IS_ERR(clk)) {
- hub->clk = clk;
-
- if (rate != 0) {
- err = clk_set_rate(hub->clk, rate);
- if (err) {
- dev_err(dev,
- "unable to set reference clock rate to %d\n",
- (int) rate);
- return err;
- }
- }
-
- err = clk_prepare_enable(hub->clk);
+ if (rate != 0) {
+ err = clk_set_rate(hub->clk, rate);
if (err) {
dev_err(dev,
- "unable to enable reference clock\n");
+ "unable to set reference clock rate to %d\n",
+ (int)rate);
return err;
}
}
+ err = clk_prepare_enable(hub->clk);
+ if (err) {
+ dev_err(dev, "unable to enable reference clock\n");
+ return err;
+ }
+
property = of_get_property(np, "disabled-ports", &len);
if (property && (len / sizeof(u32)) > 0) {
int i;
@@ -324,8 +318,7 @@ static int usb3503_i2c_remove(struct i2c_client *i2c)
struct usb3503 *hub;
hub = i2c_get_clientdata(i2c);
- if (hub->clk)
- clk_disable_unprepare(hub->clk);
+ clk_disable_unprepare(hub->clk);
return 0;
}
@@ -348,8 +341,7 @@ static int usb3503_platform_remove(struct platform_device *pdev)
struct usb3503 *hub;
hub = platform_get_drvdata(pdev);
- if (hub->clk)
- clk_disable_unprepare(hub->clk);
+ clk_disable_unprepare(hub->clk);
return 0;
}
@@ -358,18 +350,14 @@ static int usb3503_platform_remove(struct platform_device *pdev)
static int usb3503_suspend(struct usb3503 *hub)
{
usb3503_switch_mode(hub, USB3503_MODE_STANDBY);
-
- if (hub->clk)
- clk_disable_unprepare(hub->clk);
+ clk_disable_unprepare(hub->clk);
return 0;
}
static int usb3503_resume(struct usb3503 *hub)
{
- if (hub->clk)
- clk_prepare_enable(hub->clk);
-
+ clk_prepare_enable(hub->clk);
usb3503_switch_mode(hub, hub->mode);
return 0;