From 457163c4c7c69ee7f92c31bd48be332316824a14 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 26 Jun 2013 16:30:38 -0700 Subject: USB: ldusb: remove custom dbg_info() macro We want to get rid of CONFIG_USB_DEBUG, so remove the reliance of the ldusb driver on it. Don't use the custom macro, or a special module parameter, instead, rely on the in-kernel dynamic debugging infrastructure, which is much easier to use, and consistant across the whole kernel. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/ldusb.c | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) (limited to 'drivers/usb/misc') diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index ac762299eaa8..b1d59532ac22 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c @@ -129,19 +129,6 @@ MODULE_DESCRIPTION("LD USB Driver"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("LD USB Devices"); -#ifdef CONFIG_USB_DEBUG - static int debug = 1; -#else - static int debug = 0; -#endif - -/* Use our own dbg macro */ -#define dbg_info(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0) - -/* Module parameters */ -module_param(debug, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); - /* All interrupt in transfers are collected in a ring buffer to * avoid racing conditions and get better performance of the driver. */ @@ -256,8 +243,9 @@ static void ld_usb_interrupt_in_callback(struct urb *urb) status == -ESHUTDOWN) { goto exit; } else { - dbg_info(&dev->intf->dev, "%s: nonzero status received: %d\n", - __func__, status); + dev_dbg(&dev->intf->dev, + "%s: nonzero status received: %d\n", __func__, + status); spin_lock(&dev->rbsl); goto resubmit; /* maybe we can recover */ } @@ -272,8 +260,8 @@ static void ld_usb_interrupt_in_callback(struct urb *urb) *actual_buffer = urb->actual_length; memcpy(actual_buffer+1, dev->interrupt_in_buffer, urb->actual_length); dev->ring_head = next_ring_head; - dbg_info(&dev->intf->dev, "%s: received %d bytes\n", - __func__, urb->actual_length); + dev_dbg(&dev->intf->dev, "%s: received %d bytes\n", + __func__, urb->actual_length); } else { dev_warn(&dev->intf->dev, "Ring buffer overflow, %d bytes dropped\n", @@ -310,9 +298,9 @@ static void ld_usb_interrupt_out_callback(struct urb *urb) if (status && !(status == -ENOENT || status == -ECONNRESET || status == -ESHUTDOWN)) - dbg_info(&dev->intf->dev, - "%s - nonzero write interrupt status received: %d\n", - __func__, status); + dev_dbg(&dev->intf->dev, + "%s - nonzero write interrupt status received: %d\n", + __func__, status); dev->interrupt_out_busy = 0; wake_up_interruptible(&dev->write_wait); @@ -585,7 +573,8 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer, bytes_to_write = min(count, write_buffer_size*dev->interrupt_out_endpoint_size); if (bytes_to_write < count) dev_warn(&dev->intf->dev, "Write buffer overflow, %zd bytes dropped\n",count-bytes_to_write); - dbg_info(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n", __func__, count, bytes_to_write); + dev_dbg(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n", + __func__, count, bytes_to_write); if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write)) { retval = -EFAULT; -- cgit v1.2.3 From d26f6e57e71169bab907bdf716021b2d19bd09f0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 26 Jun 2013 16:30:39 -0700 Subject: USB: legotower: remove unneeded tracing macros Remove the unneeded tracing macros in this driver. The kernel has a built-in trace function that can be used if this is really still needed. Cc: Juergen Stuber Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/legousbtower.c | 42 +---------------------------------------- 1 file changed, 1 insertion(+), 41 deletions(-) (limited to 'drivers/usb/misc') diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index 80894791c020..93c95d09f04e 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -318,8 +318,6 @@ static inline void lego_usb_tower_debug_data (int level, const char *function, i */ static inline void tower_delete (struct lego_usb_tower *dev) { - dbg(2, "%s: enter", __func__); - tower_abort_transfers (dev); /* free data structures */ @@ -329,8 +327,6 @@ static inline void tower_delete (struct lego_usb_tower *dev) kfree (dev->interrupt_in_buffer); kfree (dev->interrupt_out_buffer); kfree (dev); - - dbg(2, "%s: leave", __func__); } @@ -346,8 +342,6 @@ static int tower_open (struct inode *inode, struct file *file) struct tower_reset_reply reset_reply; int result; - dbg(2, "%s: enter", __func__); - nonseekable_open(inode, file); subminor = iminor(inode); @@ -435,8 +429,6 @@ unlock_exit: mutex_unlock(&dev->lock); exit: - dbg(2, "%s: leave, return value %d ", __func__, retval); - return retval; } @@ -448,8 +440,6 @@ static int tower_release (struct inode *inode, struct file *file) struct lego_usb_tower *dev; int retval = 0; - dbg(2, "%s: enter", __func__); - dev = file->private_data; if (dev == NULL) { @@ -491,7 +481,6 @@ unlock_exit: exit: mutex_unlock(&open_disc_mutex); exit_nolock: - dbg(2, "%s: leave, return value %d", __func__, retval); return retval; } @@ -502,11 +491,9 @@ exit_nolock: */ static void tower_abort_transfers (struct lego_usb_tower *dev) { - dbg(2, "%s: enter", __func__); - if (dev == NULL) { dbg(1, "%s: dev is null", __func__); - goto exit; + return; } /* shutdown transfer */ @@ -518,9 +505,6 @@ static void tower_abort_transfers (struct lego_usb_tower *dev) } if (dev->interrupt_out_busy && dev->udev) usb_kill_urb(dev->interrupt_out_urb); - -exit: - dbg(2, "%s: leave", __func__); } @@ -553,8 +537,6 @@ static unsigned int tower_poll (struct file *file, poll_table *wait) struct lego_usb_tower *dev; unsigned int mask = 0; - dbg(2, "%s: enter", __func__); - dev = file->private_data; if (!dev->udev) @@ -571,8 +553,6 @@ static unsigned int tower_poll (struct file *file, poll_table *wait) mask |= POLLOUT | POLLWRNORM; } - dbg(2, "%s: leave, mask = %d", __func__, mask); - return mask; } @@ -597,8 +577,6 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count, int retval = 0; unsigned long timeout = 0; - dbg(2, "%s: enter, count = %Zd", __func__, count); - dev = file->private_data; /* lock this object */ @@ -672,7 +650,6 @@ unlock_exit: mutex_unlock(&dev->lock); exit: - dbg(2, "%s: leave, return value %d", __func__, retval); return retval; } @@ -686,8 +663,6 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t size_t bytes_to_write; int retval = 0; - dbg(2, "%s: enter, count = %Zd", __func__, count); - dev = file->private_data; /* lock this object */ @@ -757,8 +732,6 @@ unlock_exit: mutex_unlock(&dev->lock); exit: - dbg(2, "%s: leave, return value %d", __func__, retval); - return retval; } @@ -772,8 +745,6 @@ static void tower_interrupt_in_callback (struct urb *urb) int status = urb->status; int retval; - dbg(4, "%s: enter, status %d", __func__, status); - lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); if (status) { @@ -817,7 +788,6 @@ exit: wake_up_interruptible (&dev->read_wait); lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); - dbg(4, "%s: leave, status %d", __func__, status); } @@ -829,7 +799,6 @@ static void tower_interrupt_out_callback (struct urb *urb) struct lego_usb_tower *dev = urb->context; int status = urb->status; - dbg(4, "%s: enter, status %d", __func__, status); lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); /* sync/async unlink faults aren't errors */ @@ -844,7 +813,6 @@ static void tower_interrupt_out_callback (struct urb *urb) wake_up_interruptible(&dev->write_wait); lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); - dbg(4, "%s: leave, status %d", __func__, status); } @@ -866,8 +834,6 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device int retval = -ENOMEM; int result; - dbg(2, "%s: enter", __func__); - /* allocate memory for our device state and initialize it */ dev = kmalloc (sizeof(struct lego_usb_tower), GFP_KERNEL); @@ -993,8 +959,6 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device exit: - dbg(2, "%s: leave, return value 0x%.8lx (dev)", __func__, (long) dev); - return retval; error: @@ -1013,8 +977,6 @@ static void tower_disconnect (struct usb_interface *interface) struct lego_usb_tower *dev; int minor; - dbg(2, "%s: enter", __func__); - dev = usb_get_intfdata (interface); mutex_lock(&open_disc_mutex); usb_set_intfdata (interface, NULL); @@ -1041,8 +1003,6 @@ static void tower_disconnect (struct usb_interface *interface) dev_info(&interface->dev, "LEGO USB Tower #%d now disconnected\n", (minor - LEGO_USB_TOWER_MINOR_BASE)); - - dbg(2, "%s: leave", __func__); } module_usb_driver(tower_driver); -- cgit v1.2.3 From fef526cae700471ba37279e41b88e1c3bfdda1b9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 26 Jun 2013 16:30:40 -0700 Subject: USB: legousbtower: remove custom debug macro Don't use a custom debug macro for just one driver, instead rely on the in-kernel dynamic debugging logic, which can handle this much better. Cc: Juergen Stuber Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/legousbtower.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'drivers/usb/misc') diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index 93c95d09f04e..4a5a8b16d7b5 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -443,7 +443,6 @@ static int tower_release (struct inode *inode, struct file *file) dev = file->private_data; if (dev == NULL) { - dbg(1, "%s: object is NULL", __func__); retval = -ENODEV; goto exit_nolock; } @@ -455,7 +454,8 @@ static int tower_release (struct inode *inode, struct file *file) } if (dev->open_count != 1) { - dbg(1, "%s: device not opened exactly once", __func__); + dev_dbg(&dev->udev->dev, "%s: device not opened exactly once\n", + __func__); retval = -ENODEV; goto unlock_exit; } @@ -491,10 +491,8 @@ exit_nolock: */ static void tower_abort_transfers (struct lego_usb_tower *dev) { - if (dev == NULL) { - dbg(1, "%s: dev is null", __func__); + if (dev == NULL) return; - } /* shutdown transfer */ if (dev->interrupt_in_running) { @@ -594,7 +592,7 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count, /* verify that we actually have some data to read */ if (count == 0) { - dbg(1, "%s: read request of 0 bytes", __func__); + dev_dbg(&dev->udev->dev, "read request of 0 bytes\n"); goto unlock_exit; } @@ -680,7 +678,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t /* verify that we actually have some data to write */ if (count == 0) { - dbg(1, "%s: write request of 0 bytes", __func__); + dev_dbg(&dev->udev->dev, "write request of 0 bytes\n"); goto unlock_exit; } @@ -698,7 +696,8 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t /* write the data into interrupt_out_buffer from userspace */ bytes_to_write = min_t(int, count, write_buffer_size); - dbg(4, "%s: count = %Zd, bytes_to_write = %Zd", __func__, count, bytes_to_write); + dev_dbg(&dev->udev->dev, "%s: count = %Zd, bytes_to_write = %Zd\n", + __func__, count, bytes_to_write); if (copy_from_user (dev->interrupt_out_buffer, buffer, bytes_to_write)) { retval = -EFAULT; @@ -753,7 +752,9 @@ static void tower_interrupt_in_callback (struct urb *urb) status == -ESHUTDOWN) { goto exit; } else { - dbg(1, "%s: nonzero status received: %d", __func__, status); + dev_dbg(&dev->udev->dev, + "%s: nonzero status received: %d\n", __func__, + status); goto resubmit; /* maybe we can recover */ } } @@ -766,7 +767,8 @@ static void tower_interrupt_in_callback (struct urb *urb) urb->actual_length); dev->read_buffer_length += urb->actual_length; dev->read_last_arrival = jiffies; - dbg(3, "%s: received %d bytes", __func__, urb->actual_length); + dev_dbg(&dev->udev->dev, "%s: received %d bytes\n", + __func__, urb->actual_length); } else { printk(KERN_WARNING "%s: read_buffer overflow, %d bytes dropped", __func__, urb->actual_length); } @@ -805,8 +807,9 @@ static void tower_interrupt_out_callback (struct urb *urb) if (status && !(status == -ENOENT || status == -ECONNRESET || status == -ESHUTDOWN)) { - dbg(1, "%s - nonzero write bulk status received: %d", - __func__, status); + dev_dbg(&dev->udev->dev, + "%s: nonzero write bulk status received: %d\n", __func__, + status); } dev->interrupt_out_busy = 0; -- cgit v1.2.3 From 4dae99638097b254c863c541368598f5a80e41bf Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 26 Jun 2013 16:30:41 -0700 Subject: USB: legotower: remove custom debug macro and module parameter Now that we don't use the dbg() macro, remove it, and the module parameter. Also fix up the "dump_data" function to properly use the dynamic debug core and the correct printk options, and don't call it twice per function, as the data doesn't change from the beginning and the end of the call. Cc: Juergen Stuber Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/legousbtower.c | 43 +++++++++-------------------------------- 1 file changed, 9 insertions(+), 34 deletions(-) (limited to 'drivers/usb/misc') diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index 4a5a8b16d7b5..6df99dc4fe87 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -87,28 +87,11 @@ #include -#ifdef CONFIG_USB_DEBUG - static int debug = 4; -#else - static int debug = 0; -#endif - -/* Use our own dbg macro */ -#undef dbg -#define dbg(lvl, format, arg...) \ -do { \ - if (debug >= lvl) \ - printk(KERN_DEBUG "%s: " format "\n", __FILE__, ##arg); \ -} while (0) - /* Version Information */ #define DRIVER_VERSION "v0.96" #define DRIVER_AUTHOR "Juergen Stuber " #define DRIVER_DESC "LEGO USB Tower Driver" -/* Module parameters */ -module_param(debug, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); /* The defaults are chosen to work with the latest versions of leJOS and NQC. */ @@ -298,18 +281,12 @@ static struct usb_driver tower_driver = { /** * lego_usb_tower_debug_data */ -static inline void lego_usb_tower_debug_data (int level, const char *function, int size, const unsigned char *data) +static inline void lego_usb_tower_debug_data(struct device *dev, + const char *function, int size, + const unsigned char *data) { - int i; - - if (debug < level) - return; - - printk (KERN_DEBUG "%s: %s - length = %d, data = ", __FILE__, function, size); - for (i = 0; i < size; ++i) { - printk ("%.2x ", data[i]); - } - printk ("\n"); + dev_dbg(dev, "%s - length = %d, data = %*ph\n", + function, size, size, data); } @@ -744,7 +721,8 @@ static void tower_interrupt_in_callback (struct urb *urb) int status = urb->status; int retval; - lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); + lego_usb_tower_debug_data(&dev->udev->dev, __func__, + urb->actual_length, urb->transfer_buffer); if (status) { if (status == -ENOENT || @@ -788,8 +766,6 @@ resubmit: exit: dev->interrupt_in_done = 1; wake_up_interruptible (&dev->read_wait); - - lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); } @@ -801,7 +777,8 @@ static void tower_interrupt_out_callback (struct urb *urb) struct lego_usb_tower *dev = urb->context; int status = urb->status; - lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); + lego_usb_tower_debug_data(&dev->udev->dev, __func__, + urb->actual_length, urb->transfer_buffer); /* sync/async unlink faults aren't errors */ if (status && !(status == -ENOENT || @@ -814,8 +791,6 @@ static void tower_interrupt_out_callback (struct urb *urb) dev->interrupt_out_busy = 0; wake_up_interruptible(&dev->write_wait); - - lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); } -- cgit v1.2.3 From 38726bf5417972ff51b8f047ab4e79f0333f2cf0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 26 Jun 2013 16:30:42 -0700 Subject: USB: legotower: remove direct calls to printk() Use the pr_* calls instead, which are much more descriptive. Cc: Juergen Stuber Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/legousbtower.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/usb/misc') diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index 6df99dc4fe87..eb37c9542052 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -75,6 +75,8 @@ * - move reset into open to clean out spurious data */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -325,8 +327,7 @@ static int tower_open (struct inode *inode, struct file *file) interface = usb_find_interface (&tower_driver, subminor); if (!interface) { - printk(KERN_ERR "%s - error, can't find device for minor %d\n", - __func__, subminor); + pr_err("error, can't find device for minor %d\n", subminor); retval = -ENODEV; goto exit; } @@ -563,7 +564,7 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count, /* verify that the device wasn't unplugged */ if (dev->udev == NULL) { retval = -ENODEV; - printk(KERN_ERR "legousbtower: No device or device unplugged %d\n", retval); + pr_err("No device or device unplugged %d\n", retval); goto unlock_exit; } @@ -649,7 +650,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t /* verify that the device wasn't unplugged */ if (dev->udev == NULL) { retval = -ENODEV; - printk(KERN_ERR "legousbtower: No device or device unplugged %d\n", retval); + pr_err("No device or device unplugged %d\n", retval); goto unlock_exit; } @@ -748,7 +749,8 @@ static void tower_interrupt_in_callback (struct urb *urb) dev_dbg(&dev->udev->dev, "%s: received %d bytes\n", __func__, urb->actual_length); } else { - printk(KERN_WARNING "%s: read_buffer overflow, %d bytes dropped", __func__, urb->actual_length); + pr_warn("read_buffer overflow, %d bytes dropped\n", + urb->actual_length); } spin_unlock (&dev->read_buffer_lock); } -- cgit v1.2.3 From 6e42a15803ddbeb3a6f8f64bf599398a0ef5912b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 26 Jun 2013 16:30:43 -0700 Subject: USB: adutux: remove unneeded tracing macros Remove the unneeded tracing macros in this driver. The kernel has a built-in trace function that can be used if this is really still needed. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/adutux.c | 41 +---------------------------------------- 1 file changed, 1 insertion(+), 40 deletions(-) (limited to 'drivers/usb/misc') diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index eb3c8c142fa9..e8a9e16789f5 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -147,11 +147,9 @@ static void adu_abort_transfers(struct adu_device *dev) { unsigned long flags; - dbg(2, " %s : enter", __func__); - if (dev->udev == NULL) { dbg(1, " %s : udev is null", __func__); - goto exit; + return; } /* shutdown transfer */ @@ -170,15 +168,10 @@ static void adu_abort_transfers(struct adu_device *dev) usb_kill_urb(dev->interrupt_out_urb); } else spin_unlock_irqrestore(&dev->buflock, flags); - -exit: - dbg(2, " %s : leave", __func__); } static void adu_delete(struct adu_device *dev) { - dbg(2, "%s enter", __func__); - /* free data structures */ usb_free_urb(dev->interrupt_in_urb); usb_free_urb(dev->interrupt_out_urb); @@ -187,8 +180,6 @@ static void adu_delete(struct adu_device *dev) kfree(dev->interrupt_in_buffer); kfree(dev->interrupt_out_buffer); kfree(dev); - - dbg(2, "%s : leave", __func__); } static void adu_interrupt_in_callback(struct urb *urb) @@ -196,7 +187,6 @@ static void adu_interrupt_in_callback(struct urb *urb) struct adu_device *dev = urb->context; int status = urb->status; - dbg(4, " %s : enter, status %d", __func__, status); adu_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); @@ -234,7 +224,6 @@ exit: wake_up_interruptible(&dev->read_wait); adu_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); - dbg(4, " %s : leave, status %d", __func__, status); } static void adu_interrupt_out_callback(struct urb *urb) @@ -242,7 +231,6 @@ static void adu_interrupt_out_callback(struct urb *urb) struct adu_device *dev = urb->context; int status = urb->status; - dbg(4, " %s : enter, status %d", __func__, status); adu_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); if (status != 0) { @@ -262,7 +250,6 @@ exit: adu_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); - dbg(4, " %s : leave, status %d", __func__, status); } static int adu_open(struct inode *inode, struct file *file) @@ -272,8 +259,6 @@ static int adu_open(struct inode *inode, struct file *file) int subminor; int retval; - dbg(2, "%s : enter", __func__); - subminor = iminor(inode); retval = mutex_lock_interruptible(&adutux_mutex); @@ -333,14 +318,11 @@ static int adu_open(struct inode *inode, struct file *file) exit_no_device: mutex_unlock(&adutux_mutex); exit_no_lock: - dbg(2, "%s : leave, return value %d ", __func__, retval); return retval; } static void adu_release_internal(struct adu_device *dev) { - dbg(2, " %s : enter", __func__); - /* decrement our usage count for the device */ --dev->open_count; dbg(2, " %s : open count %d", __func__, dev->open_count); @@ -348,8 +330,6 @@ static void adu_release_internal(struct adu_device *dev) adu_abort_transfers(dev); dev->open_count = 0; } - - dbg(2, " %s : leave", __func__); } static int adu_release(struct inode *inode, struct file *file) @@ -357,8 +337,6 @@ static int adu_release(struct inode *inode, struct file *file) struct adu_device *dev; int retval = 0; - dbg(2, " %s : enter", __func__); - if (file == NULL) { dbg(1, " %s : file is NULL", __func__); retval = -ENODEV; @@ -389,7 +367,6 @@ static int adu_release(struct inode *inode, struct file *file) unlock: mutex_unlock(&adutux_mutex); exit: - dbg(2, " %s : leave, return value %d", __func__, retval); return retval; } @@ -406,11 +383,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, unsigned long flags; DECLARE_WAITQUEUE(wait, current); - dbg(2, " %s : enter, count = %Zd, file=%p", __func__, count, file); - dev = file->private_data; - dbg(2, " %s : dev=%p", __func__, dev); - if (mutex_lock_interruptible(&dev->mtx)) return -ERESTARTSYS; @@ -552,7 +525,6 @@ exit: /* unlock the device */ mutex_unlock(&dev->mtx); - dbg(2, " %s : leave, return value %d", __func__, retval); return retval; } @@ -567,8 +539,6 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, unsigned long flags; int retval; - dbg(2, " %s : enter, count = %Zd", __func__, count); - dev = file->private_data; retval = mutex_lock_interruptible(&dev->mtx); @@ -665,7 +635,6 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, exit: mutex_unlock(&dev->mtx); exit_nolock: - dbg(2, " %s : leave, return value %d", __func__, retval); return retval; exit_onqueue: @@ -711,8 +680,6 @@ static int adu_probe(struct usb_interface *interface, int out_end_size; int i; - dbg(2, " %s : enter", __func__); - if (udev == NULL) { dev_err(&interface->dev, "udev is NULL.\n"); goto exit; @@ -833,8 +800,6 @@ static int adu_probe(struct usb_interface *interface, udev->descriptor.idProduct, dev->serial_number, (dev->minor - ADU_MINOR_BASE)); exit: - dbg(2, " %s : leave, return value %p (dev)", __func__, dev); - return retval; error: @@ -852,8 +817,6 @@ static void adu_disconnect(struct usb_interface *interface) struct adu_device *dev; int minor; - dbg(2, " %s : enter", __func__); - dev = usb_get_intfdata(interface); mutex_lock(&dev->mtx); /* not interruptible */ @@ -874,8 +837,6 @@ static void adu_disconnect(struct usb_interface *interface) dev_info(&interface->dev, "ADU device adutux%d now disconnected\n", (minor - ADU_MINOR_BASE)); - - dbg(2, " %s : leave", __func__); } /* usb specific object needed to register this driver with the usb subsystem */ -- cgit v1.2.3 From 66d4bc30d128e7c7ac4cf64aa78cb76e971cec5b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 26 Jun 2013 16:30:44 -0700 Subject: USB: adutux: remove custom debug macro Don't use a custom debug macro for just one driver, instead rely on the in-kernel dynamic debugging logic, which can handle this much better. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/adutux.c | 97 ++++++++++++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 39 deletions(-) (limited to 'drivers/usb/misc') diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index e8a9e16789f5..885f99322a84 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -147,10 +147,8 @@ static void adu_abort_transfers(struct adu_device *dev) { unsigned long flags; - if (dev->udev == NULL) { - dbg(1, " %s : udev is null", __func__); + if (dev->udev == NULL) return; - } /* shutdown transfer */ @@ -195,8 +193,9 @@ static void adu_interrupt_in_callback(struct urb *urb) if (status != 0) { if ((status != -ENOENT) && (status != -ECONNRESET) && (status != -ESHUTDOWN)) { - dbg(1, " %s : nonzero status received: %d", - __func__, status); + dev_dbg(&dev->udev->dev, + "%s : nonzero status received: %d\n", + __func__, status); } goto exit; } @@ -210,10 +209,11 @@ static void adu_interrupt_in_callback(struct urb *urb) dev->interrupt_in_buffer, urb->actual_length); dev->read_buffer_length += urb->actual_length; - dbg(2, " %s reading %d ", __func__, - urb->actual_length); + dev_dbg(&dev->udev->dev,"%s reading %d\n", __func__, + urb->actual_length); } else { - dbg(1, " %s : read_buffer overflow", __func__); + dev_dbg(&dev->udev->dev,"%s : read_buffer overflow\n", + __func__); } } @@ -236,8 +236,9 @@ static void adu_interrupt_out_callback(struct urb *urb) if (status != 0) { if ((status != -ENOENT) && (status != -ECONNRESET)) { - dbg(1, " %s :nonzero status received: %d", - __func__, status); + dev_dbg(&dev->udev->dev, + "%s :nonzero status received: %d\n", __func__, + status); } goto exit; } @@ -262,10 +263,8 @@ static int adu_open(struct inode *inode, struct file *file) subminor = iminor(inode); retval = mutex_lock_interruptible(&adutux_mutex); - if (retval) { - dbg(2, "%s : mutex lock failed", __func__); + if (retval) goto exit_no_lock; - } interface = usb_find_interface(&adu_driver, subminor); if (!interface) { @@ -288,7 +287,8 @@ static int adu_open(struct inode *inode, struct file *file) } ++dev->open_count; - dbg(2, "%s : open count %d", __func__, dev->open_count); + dev_dbg(&dev->udev->dev, "%s: open count %d\n", __func__, + dev->open_count); /* save device in the file's private structure */ file->private_data = dev; @@ -325,7 +325,8 @@ static void adu_release_internal(struct adu_device *dev) { /* decrement our usage count for the device */ --dev->open_count; - dbg(2, " %s : open count %d", __func__, dev->open_count); + dev_dbg(&dev->udev->dev, "%s : open count %d\n", __func__, + dev->open_count); if (dev->open_count <= 0) { adu_abort_transfers(dev); dev->open_count = 0; @@ -338,14 +339,12 @@ static int adu_release(struct inode *inode, struct file *file) int retval = 0; if (file == NULL) { - dbg(1, " %s : file is NULL", __func__); retval = -ENODEV; goto exit; } dev = file->private_data; if (dev == NULL) { - dbg(1, " %s : object is NULL", __func__); retval = -ENODEV; goto exit; } @@ -353,7 +352,7 @@ static int adu_release(struct inode *inode, struct file *file) mutex_lock(&adutux_mutex); /* not interruptible */ if (dev->open_count <= 0) { - dbg(1, " %s : device not opened", __func__); + dev_dbg(&dev->udev->dev, "%s : device not opened\n", __func__); retval = -ENODEV; goto unlock; } @@ -397,17 +396,19 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, /* verify that some data was requested */ if (count == 0) { - dbg(1, " %s : read request of 0 bytes", __func__); + dev_dbg(&dev->udev->dev, "%s : read request of 0 bytes\n", + __func__); goto exit; } timeout = COMMAND_TIMEOUT; - dbg(2, " %s : about to start looping", __func__); + dev_dbg(&dev->udev->dev, "%s : about to start looping\n", __func__); while (bytes_to_read) { int data_in_secondary = dev->secondary_tail - dev->secondary_head; - dbg(2, " %s : while, data_in_secondary=%d, status=%d", - __func__, data_in_secondary, - dev->interrupt_in_urb->status); + dev_dbg(&dev->udev->dev, + "%s : while, data_in_secondary=%d, status=%d\n", + __func__, data_in_secondary, + dev->interrupt_in_urb->status); if (data_in_secondary) { /* drain secondary buffer */ @@ -430,8 +431,9 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, if (dev->read_buffer_length) { /* we secure access to the primary */ char *tmp; - dbg(2, " %s : swap, read_buffer_length = %d", - __func__, dev->read_buffer_length); + dev_dbg(&dev->udev->dev, + "%s : swap, read_buffer_length = %d\n", + __func__, dev->read_buffer_length); tmp = dev->read_buffer_secondary; dev->read_buffer_secondary = dev->read_buffer_primary; dev->read_buffer_primary = tmp; @@ -446,10 +448,14 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, if (!dev->read_urb_finished) { /* somebody is doing IO */ spin_unlock_irqrestore(&dev->buflock, flags); - dbg(2, " %s : submitted already", __func__); + dev_dbg(&dev->udev->dev, + "%s : submitted already\n", + __func__); } else { /* we must initiate input */ - dbg(2, " %s : initiate input", __func__); + dev_dbg(&dev->udev->dev, + "%s : initiate input\n", + __func__); dev->read_urb_finished = 0; spin_unlock_irqrestore(&dev->buflock, flags); @@ -467,7 +473,9 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, if (retval == -ENOMEM) { retval = bytes_read ? bytes_read : -ENOMEM; } - dbg(2, " %s : submit failed", __func__); + dev_dbg(&dev->udev->dev, + "%s : submit failed\n", + __func__); goto exit; } } @@ -486,13 +494,16 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, remove_wait_queue(&dev->read_wait, &wait); if (timeout <= 0) { - dbg(2, " %s : timeout", __func__); + dev_dbg(&dev->udev->dev, + "%s : timeout\n", __func__); retval = bytes_read ? bytes_read : -ETIMEDOUT; goto exit; } if (signal_pending(current)) { - dbg(2, " %s : signal pending", __func__); + dev_dbg(&dev->udev->dev, + "%s : signal pending\n", + __func__); retval = bytes_read ? bytes_read : -EINTR; goto exit; } @@ -555,7 +566,8 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, /* verify that we actually have some data to write */ if (count == 0) { - dbg(1, " %s : write request of 0 bytes", __func__); + dev_dbg(&dev->udev->dev, "%s : write request of 0 bytes\n", + __func__); goto exit; } @@ -568,13 +580,15 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, mutex_unlock(&dev->mtx); if (signal_pending(current)) { - dbg(1, " %s : interrupted", __func__); + dev_dbg(&dev->udev->dev, "%s : interrupted\n", + __func__); set_current_state(TASK_RUNNING); retval = -EINTR; goto exit_onqueue; } if (schedule_timeout(COMMAND_TIMEOUT) == 0) { - dbg(1, "%s - command timed out.", __func__); + dev_dbg(&dev->udev->dev, + "%s - command timed out.\n", __func__); retval = -ETIMEDOUT; goto exit_onqueue; } @@ -585,18 +599,22 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, goto exit_nolock; } - dbg(4, " %s : in progress, count = %Zd", __func__, count); + dev_dbg(&dev->udev->dev, + "%s : in progress, count = %Zd\n", + __func__, count); } else { spin_unlock_irqrestore(&dev->buflock, flags); set_current_state(TASK_RUNNING); remove_wait_queue(&dev->write_wait, &waita); - dbg(4, " %s : sending, count = %Zd", __func__, count); + dev_dbg(&dev->udev->dev, "%s : sending, count = %Zd\n", + __func__, count); /* write the data into interrupt_out_buffer from userspace */ buffer_size = usb_endpoint_maxp(dev->interrupt_out_endpoint); bytes_to_write = count > buffer_size ? buffer_size : count; - dbg(4, " %s : buffer_size = %Zd, count = %Zd, bytes_to_write = %Zd", - __func__, buffer_size, count, bytes_to_write); + dev_dbg(&dev->udev->dev, + "%s : buffer_size = %Zd, count = %Zd, bytes_to_write = %Zd\n", + __func__, buffer_size, count, bytes_to_write); if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write) != 0) { retval = -EFAULT; @@ -779,7 +797,7 @@ static int adu_probe(struct usb_interface *interface, dev_err(&interface->dev, "Could not retrieve serial number\n"); goto error; } - dbg(2, " %s : serial_number=%s", __func__, dev->serial_number); + dev_dbg(&interface->dev,"serial_number=%s", dev->serial_number); /* we can register the device now, as it is ready */ usb_set_intfdata(interface, dev); @@ -829,7 +847,8 @@ static void adu_disconnect(struct usb_interface *interface) usb_set_intfdata(interface, NULL); /* if the device is not opened, then we clean up right now */ - dbg(2, " %s : open count %d", __func__, dev->open_count); + dev_dbg(&dev->udev->dev, "%s : open count %d\n", + __func__, dev->open_count); if (!dev->open_count) adu_delete(dev); -- cgit v1.2.3 From 1ef37c6047fef8b65d62aa908d9795101b5244d6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 26 Jun 2013 16:30:45 -0700 Subject: USB: adutux: remove custom debug macro and module parameter Now that we don't use the dbg() macro, remove it, and the module parameter. Also fix up the "dump_data" function to properly use the dynamic debug core and the correct printk options, and don't call it twice per function, as the data doesn't change from the beginning and the end of the call. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/adutux.c | 50 +++++++++-------------------------------------- 1 file changed, 9 insertions(+), 41 deletions(-) (limited to 'drivers/usb/misc') diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index 885f99322a84..2a4793647580 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -27,30 +27,11 @@ #include #include -#ifdef CONFIG_USB_DEBUG -static int debug = 5; -#else -static int debug = 1; -#endif - -/* Use our own dbg macro */ -#undef dbg -#define dbg(lvl, format, arg...) \ -do { \ - if (debug >= lvl) \ - printk(KERN_DEBUG "%s: " format "\n", __FILE__, ##arg); \ -} while (0) - - /* Version Information */ #define DRIVER_VERSION "v0.0.13" #define DRIVER_AUTHOR "John Homppi" #define DRIVER_DESC "adutux (see www.ontrak.net)" -/* Module parameters */ -module_param(debug, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); - /* Define these values to match your device */ #define ADU_VENDOR_ID 0x0a07 #define ADU_PRODUCT_ID 0x0064 @@ -124,19 +105,11 @@ static DEFINE_MUTEX(adutux_mutex); static struct usb_driver adu_driver; -static void adu_debug_data(int level, const char *function, int size, - const unsigned char *data) +static inline void adu_debug_data(struct device *dev, const char *function, + int size, const unsigned char *data) { - int i; - - if (debug < level) - return; - - printk(KERN_DEBUG "%s: %s - length = %d, data = ", - __FILE__, function, size); - for (i = 0; i < size; ++i) - printk("%.2x ", data[i]); - printk("\n"); + dev_dbg(dev, "%s - length = %d, data = %*ph\n", + function, size, size, data); } /** @@ -185,8 +158,8 @@ static void adu_interrupt_in_callback(struct urb *urb) struct adu_device *dev = urb->context; int status = urb->status; - adu_debug_data(5, __func__, urb->actual_length, - urb->transfer_buffer); + adu_debug_data(&dev->udev->dev, __func__, + urb->actual_length, urb->transfer_buffer); spin_lock(&dev->buflock); @@ -222,8 +195,6 @@ exit: spin_unlock(&dev->buflock); /* always wake up so we recover from errors */ wake_up_interruptible(&dev->read_wait); - adu_debug_data(5, __func__, urb->actual_length, - urb->transfer_buffer); } static void adu_interrupt_out_callback(struct urb *urb) @@ -231,7 +202,8 @@ static void adu_interrupt_out_callback(struct urb *urb) struct adu_device *dev = urb->context; int status = urb->status; - adu_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); + adu_debug_data(&dev->udev->dev, __func__, + urb->actual_length, urb->transfer_buffer); if (status != 0) { if ((status != -ENOENT) && @@ -240,17 +212,13 @@ static void adu_interrupt_out_callback(struct urb *urb) "%s :nonzero status received: %d\n", __func__, status); } - goto exit; + return; } spin_lock(&dev->buflock); dev->out_urb_finished = 1; wake_up(&dev->write_wait); spin_unlock(&dev->buflock); -exit: - - adu_debug_data(5, __func__, urb->actual_length, - urb->transfer_buffer); } static int adu_open(struct inode *inode, struct file *file) -- cgit v1.2.3 From 28f47c34c75222abefac95a5740b246e065de35f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 26 Jun 2013 16:30:46 -0700 Subject: USB: adutux: remove direct calls to printk() Use the pr_* calls instead, which are much more descriptive. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/adutux.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/usb/misc') diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index 2a4793647580..7078e9bf0fc0 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -18,6 +18,8 @@ * */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -236,8 +238,8 @@ static int adu_open(struct inode *inode, struct file *file) interface = usb_find_interface(&adu_driver, subminor); if (!interface) { - printk(KERN_ERR "adutux: %s - error, can't find device for " - "minor %d\n", __func__, subminor); + pr_err("%s - error, can't find device for minor %d\n", + __func__, subminor); retval = -ENODEV; goto exit_no_device; } @@ -357,8 +359,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, /* verify that the device wasn't unplugged */ if (dev->udev == NULL) { retval = -ENODEV; - printk(KERN_ERR "adutux: No device or device unplugged %d\n", - retval); + pr_err("No device or device unplugged %d\n", retval); goto exit; } @@ -527,8 +528,7 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, /* verify that the device wasn't unplugged */ if (dev->udev == NULL) { retval = -ENODEV; - printk(KERN_ERR "adutux: No device or device unplugged %d\n", - retval); + pr_err("No device or device unplugged %d\n", retval); goto exit; } -- cgit v1.2.3 From 4ce10417e840ab58717d2c91986d8684c6858c3f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 26 Jun 2013 16:30:47 -0700 Subject: USB: misc: remove CONFIG_USB_DEBUG from Makefile Now that no usb misc driver is looking for CONFIG_USB_DEBUG, or DEBUG, don't enable it in the Makefile, as that's pointless. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/Makefile | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/usb/misc') diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index 3e1bd70b06ea..5a896f319118 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -2,9 +2,6 @@ # Makefile for the rest of the USB drivers # (the ones that don't fit into any other categories) # - -ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG - obj-$(CONFIG_USB_ADUTUX) += adutux.o obj-$(CONFIG_USB_APPLEDISPLAY) += appledisplay.o obj-$(CONFIG_USB_CYPRESS_CY7C63) += cypress_cy7c63.o -- cgit v1.2.3 From 1353aa53851e3bc7f2c6365753d9c2783c34f882 Mon Sep 17 00:00:00 2001 From: Manu Gautam Date: Tue, 2 Jul 2013 20:13:51 -0700 Subject: usb: misc: EHSET Test Fixture device driver for host compliance An Embedded Host High-Speed Electrical Test (EHSET) test fixture is used to initiate test modes on a host controller in order to perform the high speed electrical testing procedure for USB-IF compliance. When this test fixture is connected to a host, it can enumerate as one of several selectable VID/PID pairs, each corresponding to one of the following test modes: * TEST_SE0_NAK * TEST_J * TEST_K * TEST_PACKET * HS_HOST_PORT_SUSPEND_RESUME * SINGLE_STEP_GET_DEV_DESC * SINGLE_STEP_SET_FEATURE The USB EHSET procedure can be found here: http://www.usb.org/developers/onthego/EHSET_v1.01.pdf Signed-off-by: Manu Gautam [jackp@codeaurora.org: imported from commit 073c9409 on codeaurora.org; minor cleanup and updated author email] Signed-off-by: Jack Pham Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/Kconfig | 13 +++++ drivers/usb/misc/Makefile | 1 + drivers/usb/misc/ehset.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+) create mode 100644 drivers/usb/misc/ehset.c (limited to 'drivers/usb/misc') diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index a51e7d6afda9..ca91420f5c21 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -200,6 +200,19 @@ config USB_TEST See for more information, including sample test device firmware and "how to use it". +config USB_EHSET_TEST_FIXTURE + tristate "USB EHSET Test Fixture driver" + help + Say Y here if you want to support the special test fixture device + used for the USB-IF Embedded Host High-Speed Electrical Test procedure. + + When the test fixture is connected, it can enumerate as one of several + VID/PID pairs. This driver then initiates a corresponding test mode on + the downstream port to which the test fixture is attached. + + See for more + information. + config USB_ISIGHTFW tristate "iSight firmware loading support" select FW_LOADER diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index 5a896f319118..e748fd5dbe94 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_USB_LED) += usbled.o obj-$(CONFIG_USB_LEGOTOWER) += legousbtower.o obj-$(CONFIG_USB_RIO500) += rio500.o obj-$(CONFIG_USB_TEST) += usbtest.o +obj-$(CONFIG_USB_EHSET_TEST_FIXTURE) += ehset.o obj-$(CONFIG_USB_TRANCEVIBRATOR) += trancevibrator.o obj-$(CONFIG_USB_USS720) += uss720.o obj-$(CONFIG_USB_SEVSEG) += usbsevseg.o diff --git a/drivers/usb/misc/ehset.c b/drivers/usb/misc/ehset.c new file mode 100644 index 000000000000..d2864b3f41fe --- /dev/null +++ b/drivers/usb/misc/ehset.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include + +#define TEST_SE0_NAK_PID 0x0101 +#define TEST_J_PID 0x0102 +#define TEST_K_PID 0x0103 +#define TEST_PACKET_PID 0x0104 +#define TEST_HS_HOST_PORT_SUSPEND_RESUME 0x0106 +#define TEST_SINGLE_STEP_GET_DEV_DESC 0x0107 +#define TEST_SINGLE_STEP_SET_FEATURE 0x0108 + +static int ehset_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + int ret = -EINVAL; + struct usb_device *dev = interface_to_usbdev(intf); + struct usb_device *hub_udev = dev->parent; + struct usb_device_descriptor *buf; + u8 portnum = dev->portnum; + u16 test_pid = le16_to_cpu(dev->descriptor.idProduct); + + switch (test_pid) { + case TEST_SE0_NAK_PID: + ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0), + USB_REQ_SET_FEATURE, USB_RT_PORT, + USB_PORT_FEAT_TEST, + (TEST_SE0_NAK << 8) | portnum, + NULL, 0, 1000); + break; + case TEST_J_PID: + ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0), + USB_REQ_SET_FEATURE, USB_RT_PORT, + USB_PORT_FEAT_TEST, + (TEST_J << 8) | portnum, + NULL, 0, 1000); + break; + case TEST_K_PID: + ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0), + USB_REQ_SET_FEATURE, USB_RT_PORT, + USB_PORT_FEAT_TEST, + (TEST_K << 8) | portnum, + NULL, 0, 1000); + break; + case TEST_PACKET_PID: + ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0), + USB_REQ_SET_FEATURE, USB_RT_PORT, + USB_PORT_FEAT_TEST, + (TEST_PACKET << 8) | portnum, + NULL, 0, 1000); + break; + case TEST_HS_HOST_PORT_SUSPEND_RESUME: + /* Test: wait for 15secs -> suspend -> 15secs delay -> resume */ + msleep(15 * 1000); + ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0), + USB_REQ_SET_FEATURE, USB_RT_PORT, + USB_PORT_FEAT_SUSPEND, portnum, + NULL, 0, 1000); + if (ret < 0) + break; + + msleep(15 * 1000); + ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0), + USB_REQ_CLEAR_FEATURE, USB_RT_PORT, + USB_PORT_FEAT_SUSPEND, portnum, + NULL, 0, 1000); + break; + case TEST_SINGLE_STEP_GET_DEV_DESC: + /* Test: wait for 15secs -> GetDescriptor request */ + msleep(15 * 1000); + buf = kmalloc(USB_DT_DEVICE_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, + USB_DT_DEVICE << 8, 0, + buf, USB_DT_DEVICE_SIZE, + USB_CTRL_GET_TIMEOUT); + kfree(buf); + break; + case TEST_SINGLE_STEP_SET_FEATURE: + /* unsupported for now */ + default: + dev_err(&intf->dev, "%s: unsupported PID: 0x%x\n", + __func__, test_pid); + } + + return (ret < 0) ? ret : 0; +} + +static void ehset_disconnect(struct usb_interface *intf) +{ +} + +static const struct usb_device_id ehset_id_table[] = { + { USB_DEVICE(0x1a0a, TEST_SE0_NAK_PID) }, + { USB_DEVICE(0x1a0a, TEST_J_PID) }, + { USB_DEVICE(0x1a0a, TEST_K_PID) }, + { USB_DEVICE(0x1a0a, TEST_PACKET_PID) }, + { USB_DEVICE(0x1a0a, TEST_HS_HOST_PORT_SUSPEND_RESUME) }, + { USB_DEVICE(0x1a0a, TEST_SINGLE_STEP_GET_DEV_DESC) }, + { USB_DEVICE(0x1a0a, TEST_SINGLE_STEP_SET_FEATURE) }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, ehset_id_table); + +static struct usb_driver ehset_driver = { + .name = "usb_ehset_test", + .probe = ehset_probe, + .disconnect = ehset_disconnect, + .id_table = ehset_id_table, +}; + +module_usb_driver(ehset_driver); + +MODULE_DESCRIPTION("USB Driver for EHSET Test Fixture"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From b977a3068a284b2ad4612cdb8ca326cbd2a7ffc9 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 30 Jul 2013 17:05:28 +0900 Subject: usb: misc: usb3503: use dev_get_platdata() Use the wrapper function for retrieving the platform data instead of accessing dev->platform_data directly. Signed-off-by: Jingoo Han Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/usb3503.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb/misc') diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c index c3578393ddef..cbb6b7841653 100644 --- a/drivers/usb/misc/usb3503.c +++ b/drivers/usb/misc/usb3503.c @@ -179,7 +179,7 @@ err_hubmode: static int usb3503_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { - struct usb3503_platform_data *pdata = i2c->dev.platform_data; + struct usb3503_platform_data *pdata = dev_get_platdata(&i2c->dev); struct device_node *np = i2c->dev.of_node; struct usb3503 *hub; int err = -ENOMEM; -- cgit v1.2.3 From 15b7336e02d998720c5ace47036f7e539365bb05 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 30 Jul 2013 15:35:40 -0400 Subject: USB: simplify the interface of usb_get_status() This patch simplifies the interface presented by usb_get_status(). Instead of forcing callers to check for the proper data length and convert the status value to host byte order, the function will now do these things itself. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 10 ++-------- drivers/usb/core/message.c | 13 +++++++++---- drivers/usb/misc/usbtest.c | 9 ++++----- 3 files changed, 15 insertions(+), 17 deletions(-) (limited to 'drivers/usb/misc') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index c881830af55f..11a92198bfc7 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1464,11 +1464,10 @@ static int hub_configure(struct usb_hub *hub, * and battery-powered root hubs (may provide just 8 mA). */ ret = usb_get_status(hdev, USB_RECIP_DEVICE, 0, &hubstatus); - if (ret < 2) { + if (ret) { message = "can't get hub status"; goto fail; } - le16_to_cpus(&hubstatus); hcd = bus_to_hcd(hdev->bus); if (hdev == hdev->bus->root_hub) { if (hcd->power_budget > 0) @@ -3101,8 +3100,6 @@ static int finish_port_resume(struct usb_device *udev) if (status == 0) { devstatus = 0; status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus); - if (status >= 0) - status = (status > 0 ? 0 : -ENODEV); /* If a normal resume failed, try doing a reset-resume */ if (status && !udev->reset_resume && udev->persist_enabled) { @@ -3123,7 +3120,6 @@ static int finish_port_resume(struct usb_device *udev) */ } else if (udev->actconfig && !udev->reset_resume) { if (!hub_is_superspeed(udev->parent)) { - le16_to_cpus(&devstatus); if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), @@ -3135,7 +3131,6 @@ static int finish_port_resume(struct usb_device *udev) } else { status = usb_get_status(udev, USB_RECIP_INTERFACE, 0, &devstatus); - le16_to_cpus(&devstatus); if (!status && devstatus & (USB_INTRF_STAT_FUNC_RW_CAP | USB_INTRF_STAT_FUNC_RW)) status = @@ -4481,11 +4476,10 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstat); - if (status < 2) { + if (status) { dev_dbg(&udev->dev, "get status %d ?\n", status); goto loop_disable; } - le16_to_cpus(&devstat); if ((devstat & (1 << USB_DEVICE_SELF_POWERED)) == 0) { dev_err(&udev->dev, "can't connect bus-powered hub " diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index e7ee1e451660..6549a975b0c5 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -934,13 +934,13 @@ int usb_get_device_descriptor(struct usb_device *dev, unsigned int size) * * This call is synchronous, and may not be used in an interrupt context. * - * Returns the number of bytes received on success, or else the status code - * returned by the underlying usb_control_msg() call. + * Returns 0 and the status value in *@data (in host byte order) on success, + * or else the status code from the underlying usb_control_msg() call. */ int usb_get_status(struct usb_device *dev, int type, int target, void *data) { int ret; - u16 *status = kmalloc(sizeof(*status), GFP_KERNEL); + __le16 *status = kmalloc(sizeof(*status), GFP_KERNEL); if (!status) return -ENOMEM; @@ -949,7 +949,12 @@ int usb_get_status(struct usb_device *dev, int type, int target, void *data) USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, status, sizeof(*status), USB_CTRL_GET_TIMEOUT); - *(u16 *)data = *status; + if (ret == 2) { + *(u16 *) data = le16_to_cpu(*status); + ret = 0; + } else if (ret >= 0) { + ret = -EIO; + } kfree(status); return ret; } diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 8b4ca1cb450a..aa28ac8c7607 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -747,9 +747,9 @@ static int ch9_postconfig(struct usbtest_dev *dev) /* [9.4.5] get_status always works */ retval = usb_get_status(udev, USB_RECIP_DEVICE, 0, dev->buf); - if (retval != 2) { + if (retval) { dev_err(&iface->dev, "get dev status --> %d\n", retval); - return (retval < 0) ? retval : -EDOM; + return retval; } /* FIXME configuration.bmAttributes says if we could try to set/clear @@ -758,9 +758,9 @@ static int ch9_postconfig(struct usbtest_dev *dev) retval = usb_get_status(udev, USB_RECIP_INTERFACE, iface->altsetting[0].desc.bInterfaceNumber, dev->buf); - if (retval != 2) { + if (retval) { dev_err(&iface->dev, "get interface status --> %d\n", retval); - return (retval < 0) ? retval : -EDOM; + return retval; } /* FIXME get status for each endpoint in the interface */ @@ -1351,7 +1351,6 @@ static int verify_halted(struct usbtest_dev *tdev, int ep, struct urb *urb) ep, retval); return retval; } - le16_to_cpus(&status); if (status != 1) { ERROR(tdev, "ep %02x bogus status: %04x != 1\n", ep, status); return -EINVAL; -- cgit v1.2.3 From 42416cc81f4990ad8d425b41a0fc8cd985eb5fa5 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 7 Aug 2013 20:28:24 +0100 Subject: usb: misc: Fix swapped properties in usb3503 DT parsing The intn and connect GPIO properties are swapped in the code which will cause failures at runtime if these are connected, fix the code. There are currently no in-tree users of this device to check or update. Signed-off-by: Mark Brown Acked-by: Olof Johansson Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/usb3503.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/usb/misc') diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c index cbb6b7841653..4e3a2d2fc450 100644 --- a/drivers/usb/misc/usb3503.c +++ b/drivers/usb/misc/usb3503.c @@ -215,10 +215,10 @@ static int usb3503_probe(struct i2c_client *i2c, const struct i2c_device_id *id) } } - hub->gpio_intn = of_get_named_gpio(np, "connect-gpios", 0); + hub->gpio_intn = of_get_named_gpio(np, "intn-gpios", 0); if (hub->gpio_intn == -EPROBE_DEFER) return -EPROBE_DEFER; - hub->gpio_connect = of_get_named_gpio(np, "intn-gpios", 0); + hub->gpio_connect = of_get_named_gpio(np, "connect-gpios", 0); if (hub->gpio_connect == -EPROBE_DEFER) return -EPROBE_DEFER; hub->gpio_reset = of_get_named_gpio(np, "reset-gpios", 0); -- cgit v1.2.3 From cffedd6794bb32c4fbc03600fac61beca7950f08 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 7 Aug 2013 22:02:54 +0100 Subject: usb: misc: usb3503: Convert to devm_ APIs Saves us a bit of code. Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/usb3503.c | 42 +++++++----------------------------------- 1 file changed, 7 insertions(+), 35 deletions(-) (limited to 'drivers/usb/misc') diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c index 4e3a2d2fc450..41b422824c87 100644 --- a/drivers/usb/misc/usb3503.c +++ b/drivers/usb/misc/usb3503.c @@ -187,7 +187,7 @@ static int usb3503_probe(struct i2c_client *i2c, const struct i2c_device_id *id) const u32 *property; int len; - hub = kzalloc(sizeof(struct usb3503), GFP_KERNEL); + hub = devm_kzalloc(&i2c->dev, sizeof(struct usb3503), GFP_KERNEL); if (!hub) { dev_err(&i2c->dev, "private data alloc fail\n"); return err; @@ -229,35 +229,35 @@ static int usb3503_probe(struct i2c_client *i2c, const struct i2c_device_id *id) } if (gpio_is_valid(hub->gpio_intn)) { - err = gpio_request_one(hub->gpio_intn, + err = devm_gpio_request_one(&i2c->dev, hub->gpio_intn, GPIOF_OUT_INIT_HIGH, "usb3503 intn"); if (err) { dev_err(&i2c->dev, "unable to request GPIO %d as connect pin (%d)\n", hub->gpio_intn, err); - goto err_out; + return err; } } if (gpio_is_valid(hub->gpio_connect)) { - err = gpio_request_one(hub->gpio_connect, + err = devm_gpio_request_one(&i2c->dev, hub->gpio_connect, GPIOF_OUT_INIT_HIGH, "usb3503 connect"); if (err) { dev_err(&i2c->dev, "unable to request GPIO %d as connect pin (%d)\n", hub->gpio_connect, err); - goto err_gpio_connect; + return err; } } if (gpio_is_valid(hub->gpio_reset)) { - err = gpio_request_one(hub->gpio_reset, + err = devm_gpio_request_one(&i2c->dev, hub->gpio_reset, GPIOF_OUT_INIT_LOW, "usb3503 reset"); if (err) { dev_err(&i2c->dev, "unable to request GPIO %d as reset pin (%d)\n", hub->gpio_reset, err); - goto err_gpio_reset; + return err; } } @@ -267,33 +267,6 @@ static int usb3503_probe(struct i2c_client *i2c, const struct i2c_device_id *id) (hub->mode == USB3503_MODE_HUB) ? "hub" : "standby"); return 0; - -err_gpio_reset: - if (gpio_is_valid(hub->gpio_connect)) - gpio_free(hub->gpio_connect); -err_gpio_connect: - if (gpio_is_valid(hub->gpio_intn)) - gpio_free(hub->gpio_intn); -err_out: - kfree(hub); - - return err; -} - -static int usb3503_remove(struct i2c_client *i2c) -{ - struct usb3503 *hub = i2c_get_clientdata(i2c); - - if (gpio_is_valid(hub->gpio_intn)) - gpio_free(hub->gpio_intn); - if (gpio_is_valid(hub->gpio_connect)) - gpio_free(hub->gpio_connect); - if (gpio_is_valid(hub->gpio_reset)) - gpio_free(hub->gpio_reset); - - kfree(hub); - - return 0; } static const struct i2c_device_id usb3503_id[] = { @@ -316,7 +289,6 @@ static struct i2c_driver usb3503_driver = { .of_match_table = of_match_ptr(usb3503_of_match), }, .probe = usb3503_probe, - .remove = usb3503_remove, .id_table = usb3503_id, }; -- cgit v1.2.3 From 24455b09b4838cdc0165af0f24ca63ec9ad54e44 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 9 Aug 2013 11:41:49 +0100 Subject: usb: misc: usb3503: Use gpio_set_value_cansleep() The /RESET GPIO is not manipulated from atomic context so support GPIOs that can't be written from atomic context by using _cansleep(). Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/usb3503.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb/misc') diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c index 41b422824c87..2e9e100a182e 100644 --- a/drivers/usb/misc/usb3503.c +++ b/drivers/usb/misc/usb3503.c @@ -103,7 +103,7 @@ static int usb3503_clear_bits(struct i2c_client *client, char reg, char req) static int usb3503_reset(int gpio_reset, int state) { if (gpio_is_valid(gpio_reset)) - gpio_set_value(gpio_reset, state); + gpio_set_value_cansleep(gpio_reset, state); /* Wait T_HUBINIT == 4ms for hub logic to stabilize */ if (state) -- cgit v1.2.3 From 8e7245b8386cb1dc941e10a4c97307e3f48da5da Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 9 Aug 2013 11:41:51 +0100 Subject: usb: misc: usb3503: Actively manage Hub Connect GPIO If the connect signal is pulled high then the device will start up meaning that if we just pull it high on probe then the device will start running prior to the configuration being written out. Fix this by pulling the GPIO low when we reset and only pulling it high when configuration is finished. Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/usb3503.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers/usb/misc') diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c index 2e9e100a182e..4b6572a37e87 100644 --- a/drivers/usb/misc/usb3503.c +++ b/drivers/usb/misc/usb3503.c @@ -100,10 +100,13 @@ static int usb3503_clear_bits(struct i2c_client *client, char reg, char req) return 0; } -static int usb3503_reset(int gpio_reset, int state) +static int usb3503_reset(struct usb3503 *hub, int state) { - if (gpio_is_valid(gpio_reset)) - gpio_set_value_cansleep(gpio_reset, state); + if (!state && gpio_is_valid(hub->gpio_connect)) + gpio_set_value_cansleep(hub->gpio_connect, 0); + + if (gpio_is_valid(hub->gpio_reset)) + gpio_set_value_cansleep(hub->gpio_reset, state); /* Wait T_HUBINIT == 4ms for hub logic to stabilize */ if (state) @@ -119,7 +122,7 @@ static int usb3503_switch_mode(struct usb3503 *hub, enum usb3503_mode mode) switch (mode) { case USB3503_MODE_HUB: - usb3503_reset(hub->gpio_reset, 1); + usb3503_reset(hub, 1); /* SP_ILOCK: set connect_n, config_n for config */ err = usb3503_write_register(i2c, USB3503_SP_ILOCK, @@ -156,12 +159,15 @@ static int usb3503_switch_mode(struct usb3503 *hub, enum usb3503_mode mode) goto err_hubmode; } + if (gpio_is_valid(hub->gpio_connect)) + gpio_set_value_cansleep(hub->gpio_connect, 1); + hub->mode = mode; dev_info(&i2c->dev, "switched to HUB mode\n"); break; case USB3503_MODE_STANDBY: - usb3503_reset(hub->gpio_reset, 0); + usb3503_reset(hub, 0); hub->mode = mode; dev_info(&i2c->dev, "switched to STANDBY mode\n"); @@ -241,7 +247,7 @@ static int usb3503_probe(struct i2c_client *i2c, const struct i2c_device_id *id) if (gpio_is_valid(hub->gpio_connect)) { err = devm_gpio_request_one(&i2c->dev, hub->gpio_connect, - GPIOF_OUT_INIT_HIGH, "usb3503 connect"); + GPIOF_OUT_INIT_LOW, "usb3503 connect"); if (err) { dev_err(&i2c->dev, "unable to request GPIO %d as connect pin (%d)\n", -- cgit v1.2.3 From 68b14134be55eca7340b9a8b3ec4cb8f79622a3c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 9 Aug 2013 11:41:52 +0100 Subject: usb: misc: usb3503: Convert to regmap This will give access to the diagnostic infrastructure regmap has but the main point is to support future refactoring. Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/Kconfig | 1 + drivers/usb/misc/usb3503.c | 93 ++++++++++++++++++---------------------------- 2 files changed, 37 insertions(+), 57 deletions(-) (limited to 'drivers/usb/misc') diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index ca91420f5c21..e2b21c1d9c40 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -246,5 +246,6 @@ config USB_EZUSB_FX2 config USB_HSIC_USB3503 tristate "USB3503 HSIC to USB20 Driver" depends on I2C + select REGMAP help This option enables support for SMSC USB3503 HSIC to USB 2.0 Driver. diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c index 4b6572a37e87..f2c0356b7148 100644 --- a/drivers/usb/misc/usb3503.c +++ b/drivers/usb/misc/usb3503.c @@ -26,6 +26,7 @@ #include #include #include +#include #define USB3503_VIDL 0x00 #define USB3503_VIDM 0x01 @@ -50,56 +51,18 @@ #define USB3503_CFGP 0xee #define USB3503_CLKSUSP (1 << 7) +#define USB3503_RESET 0xff + struct usb3503 { enum usb3503_mode mode; - struct i2c_client *client; + struct regmap *regmap; + struct device *dev; u8 port_off_mask; int gpio_intn; int gpio_reset; int gpio_connect; }; -static int usb3503_write_register(struct i2c_client *client, - char reg, char data) -{ - return i2c_smbus_write_byte_data(client, reg, data); -} - -static int usb3503_read_register(struct i2c_client *client, char reg) -{ - return i2c_smbus_read_byte_data(client, reg); -} - -static int usb3503_set_bits(struct i2c_client *client, char reg, char req) -{ - int err; - - err = usb3503_read_register(client, reg); - if (err < 0) - return err; - - err = usb3503_write_register(client, reg, err | req); - if (err < 0) - return err; - - return 0; -} - -static int usb3503_clear_bits(struct i2c_client *client, char reg, char req) -{ - int err; - - err = usb3503_read_register(client, reg); - if (err < 0) - return err; - - err = usb3503_write_register(client, reg, err & ~req); - if (err < 0) - return err; - - return 0; -} - static int usb3503_reset(struct usb3503 *hub, int state) { if (!state && gpio_is_valid(hub->gpio_connect)) @@ -117,7 +80,7 @@ static int usb3503_reset(struct usb3503 *hub, int state) static int usb3503_switch_mode(struct usb3503 *hub, enum usb3503_mode mode) { - struct i2c_client *i2c = hub->client; + struct device *dev = hub->dev; int err = 0; switch (mode) { @@ -125,37 +88,40 @@ static int usb3503_switch_mode(struct usb3503 *hub, enum usb3503_mode mode) usb3503_reset(hub, 1); /* SP_ILOCK: set connect_n, config_n for config */ - err = usb3503_write_register(i2c, USB3503_SP_ILOCK, + err = regmap_write(hub->regmap, USB3503_SP_ILOCK, (USB3503_SPILOCK_CONNECT | USB3503_SPILOCK_CONFIG)); if (err < 0) { - dev_err(&i2c->dev, "SP_ILOCK failed (%d)\n", err); + dev_err(dev, "SP_ILOCK failed (%d)\n", err); goto err_hubmode; } /* PDS : Disable For Self Powered Operation */ if (hub->port_off_mask) { - err = usb3503_set_bits(i2c, USB3503_PDS, + err = regmap_update_bits(hub->regmap, USB3503_PDS, + hub->port_off_mask, hub->port_off_mask); if (err < 0) { - dev_err(&i2c->dev, "PDS failed (%d)\n", err); + dev_err(dev, "PDS failed (%d)\n", err); goto err_hubmode; } } /* CFG1 : SELF_BUS_PWR -> Self-Powerd operation */ - err = usb3503_set_bits(i2c, USB3503_CFG1, USB3503_SELF_BUS_PWR); + err = regmap_update_bits(hub->regmap, USB3503_CFG1, + USB3503_SELF_BUS_PWR, + USB3503_SELF_BUS_PWR); if (err < 0) { - dev_err(&i2c->dev, "CFG1 failed (%d)\n", err); + dev_err(dev, "CFG1 failed (%d)\n", err); goto err_hubmode; } /* SP_LOCK: clear connect_n, config_n for hub connect */ - err = usb3503_clear_bits(i2c, USB3503_SP_ILOCK, - (USB3503_SPILOCK_CONNECT - | USB3503_SPILOCK_CONFIG)); + err = regmap_update_bits(hub->regmap, USB3503_SP_ILOCK, + (USB3503_SPILOCK_CONNECT + | USB3503_SPILOCK_CONFIG), 0); if (err < 0) { - dev_err(&i2c->dev, "SP_ILOCK failed (%d)\n", err); + dev_err(dev, "SP_ILOCK failed (%d)\n", err); goto err_hubmode; } @@ -163,18 +129,18 @@ static int usb3503_switch_mode(struct usb3503 *hub, enum usb3503_mode mode) gpio_set_value_cansleep(hub->gpio_connect, 1); hub->mode = mode; - dev_info(&i2c->dev, "switched to HUB mode\n"); + dev_info(dev, "switched to HUB mode\n"); break; case USB3503_MODE_STANDBY: usb3503_reset(hub, 0); hub->mode = mode; - dev_info(&i2c->dev, "switched to STANDBY mode\n"); + dev_info(dev, "switched to STANDBY mode\n"); break; default: - dev_err(&i2c->dev, "unknown mode is request\n"); + dev_err(dev, "unknown mode is request\n"); err = -EINVAL; break; } @@ -183,6 +149,13 @@ err_hubmode: return err; } +static const struct regmap_config usb3503_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = USB3503_RESET, +}; + static int usb3503_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct usb3503_platform_data *pdata = dev_get_platdata(&i2c->dev); @@ -200,7 +173,13 @@ static int usb3503_probe(struct i2c_client *i2c, const struct i2c_device_id *id) } i2c_set_clientdata(i2c, hub); - hub->client = i2c; + hub->regmap = devm_regmap_init_i2c(i2c, &usb3503_regmap_config); + if (IS_ERR(hub->regmap)) { + err = PTR_ERR(hub->regmap); + dev_err(&i2c->dev, "Failed to initialise regmap: %d\n", err); + return err; + } + hub->dev = &i2c->dev; if (pdata) { hub->port_off_mask = pdata->port_off_mask; -- cgit v1.2.3 From 2487e3ee33dd6c4fa3dabbe11bc988883be81f1e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 9 Aug 2013 11:41:53 +0100 Subject: usb: misc: usb3503: Factor out I2C probe In preparation for supporting operation without an I2C control interface factor out the I2C-specific parts of the probe routine from those that don't do any register I/O. Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/usb3503.c | 77 ++++++++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 34 deletions(-) (limited to 'drivers/usb/misc') diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c index f2c0356b7148..ca0f789d78a3 100644 --- a/drivers/usb/misc/usb3503.c +++ b/drivers/usb/misc/usb3503.c @@ -156,31 +156,16 @@ static const struct regmap_config usb3503_regmap_config = { .max_register = USB3503_RESET, }; -static int usb3503_probe(struct i2c_client *i2c, const struct i2c_device_id *id) +static int usb3503_probe(struct usb3503 *hub) { - struct usb3503_platform_data *pdata = dev_get_platdata(&i2c->dev); - struct device_node *np = i2c->dev.of_node; - struct usb3503 *hub; - int err = -ENOMEM; + struct device *dev = hub->dev; + struct usb3503_platform_data *pdata = dev_get_platdata(dev); + struct device_node *np = dev->of_node; + int err; u32 mode = USB3503_MODE_UNKNOWN; const u32 *property; int len; - hub = devm_kzalloc(&i2c->dev, sizeof(struct usb3503), GFP_KERNEL); - if (!hub) { - dev_err(&i2c->dev, "private data alloc fail\n"); - return err; - } - - i2c_set_clientdata(i2c, hub); - hub->regmap = devm_regmap_init_i2c(i2c, &usb3503_regmap_config); - if (IS_ERR(hub->regmap)) { - err = PTR_ERR(hub->regmap); - dev_err(&i2c->dev, "Failed to initialise regmap: %d\n", err); - return err; - } - hub->dev = &i2c->dev; - if (pdata) { hub->port_off_mask = pdata->port_off_mask; hub->gpio_intn = pdata->gpio_intn; @@ -214,46 +199,70 @@ static int usb3503_probe(struct i2c_client *i2c, const struct i2c_device_id *id) } if (gpio_is_valid(hub->gpio_intn)) { - err = devm_gpio_request_one(&i2c->dev, hub->gpio_intn, + err = devm_gpio_request_one(dev, hub->gpio_intn, GPIOF_OUT_INIT_HIGH, "usb3503 intn"); if (err) { - dev_err(&i2c->dev, - "unable to request GPIO %d as connect pin (%d)\n", - hub->gpio_intn, err); + dev_err(dev, + "unable to request GPIO %d as connect pin (%d)\n", + hub->gpio_intn, err); return err; } } if (gpio_is_valid(hub->gpio_connect)) { - err = devm_gpio_request_one(&i2c->dev, hub->gpio_connect, + err = devm_gpio_request_one(dev, hub->gpio_connect, GPIOF_OUT_INIT_LOW, "usb3503 connect"); if (err) { - dev_err(&i2c->dev, - "unable to request GPIO %d as connect pin (%d)\n", - hub->gpio_connect, err); + dev_err(dev, + "unable to request GPIO %d as connect pin (%d)\n", + hub->gpio_connect, err); return err; } } if (gpio_is_valid(hub->gpio_reset)) { - err = devm_gpio_request_one(&i2c->dev, hub->gpio_reset, + err = devm_gpio_request_one(dev, hub->gpio_reset, GPIOF_OUT_INIT_LOW, "usb3503 reset"); if (err) { - dev_err(&i2c->dev, - "unable to request GPIO %d as reset pin (%d)\n", - hub->gpio_reset, err); + dev_err(dev, + "unable to request GPIO %d as reset pin (%d)\n", + hub->gpio_reset, err); return err; } } usb3503_switch_mode(hub, hub->mode); - dev_info(&i2c->dev, "%s: probed on %s mode\n", __func__, + dev_info(dev, "%s: probed on %s mode\n", __func__, (hub->mode == USB3503_MODE_HUB) ? "hub" : "standby"); return 0; } +static int usb3503_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct usb3503 *hub; + int err; + + hub = devm_kzalloc(&i2c->dev, sizeof(struct usb3503), GFP_KERNEL); + if (!hub) { + dev_err(&i2c->dev, "private data alloc fail\n"); + return -ENOMEM; + } + + i2c_set_clientdata(i2c, hub); + hub->regmap = devm_regmap_init_i2c(i2c, &usb3503_regmap_config); + if (IS_ERR(hub->regmap)) { + err = PTR_ERR(hub->regmap); + dev_err(&i2c->dev, "Failed to initialise regmap: %d\n", err); + return err; + } + hub->dev = &i2c->dev; + + return usb3503_probe(hub); +} + static const struct i2c_device_id usb3503_id[] = { { USB3503_I2C_NAME, 0 }, { } @@ -273,7 +282,7 @@ static struct i2c_driver usb3503_driver = { .name = USB3503_I2C_NAME, .of_match_table = of_match_ptr(usb3503_of_match), }, - .probe = usb3503_probe, + .probe = usb3503_i2c_probe, .id_table = usb3503_id, }; -- cgit v1.2.3 From dd8e670d2775c02169a3b9e4c8d84c8652342836 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 9 Aug 2013 11:41:54 +0100 Subject: usb: misc: usb3503: Fix typos in error messages Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/usb3503.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/usb/misc') diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c index ca0f789d78a3..777102e05c3b 100644 --- a/drivers/usb/misc/usb3503.c +++ b/drivers/usb/misc/usb3503.c @@ -140,7 +140,7 @@ static int usb3503_switch_mode(struct usb3503 *hub, enum usb3503_mode mode) break; default: - dev_err(dev, "unknown mode is request\n"); + dev_err(dev, "unknown mode is requested\n"); err = -EINVAL; break; } @@ -233,7 +233,7 @@ static int usb3503_probe(struct usb3503 *hub) usb3503_switch_mode(hub, hub->mode); - dev_info(dev, "%s: probed on %s mode\n", __func__, + dev_info(dev, "%s: probed in %s mode\n", __func__, (hub->mode == USB3503_MODE_HUB) ? "hub" : "standby"); return 0; -- cgit v1.2.3 From e5a0c874ec7babc1931a67489b292de152d2a641 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 9 Aug 2013 11:41:55 +0100 Subject: usb: misc: usb3503: Default to hub mode Since there is no runtime interface for changing modes this is probably the most sensible default. Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/usb3503.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb/misc') diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c index 777102e05c3b..8f5dff20dcb4 100644 --- a/drivers/usb/misc/usb3503.c +++ b/drivers/usb/misc/usb3503.c @@ -162,7 +162,7 @@ static int usb3503_probe(struct usb3503 *hub) struct usb3503_platform_data *pdata = dev_get_platdata(dev); struct device_node *np = dev->of_node; int err; - u32 mode = USB3503_MODE_UNKNOWN; + u32 mode = USB3503_MODE_HUB; const u32 *property; int len; -- cgit v1.2.3 From 5bdd1f4a1daf398042203b72430891dfc40c0fa6 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 9 Aug 2013 11:41:56 +0100 Subject: usb: misc: usb3503: Add USB3503A to the compatible list There are no software visible differences that I am aware of but in case any are discovered allow the DTS to specify exactly which device is present. Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/usb/usb3503.txt | 2 +- drivers/usb/misc/usb3503.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/usb/misc') diff --git a/Documentation/devicetree/bindings/usb/usb3503.txt b/Documentation/devicetree/bindings/usb/usb3503.txt index 8c5be48b43c8..cd60f7e4eb57 100644 --- a/Documentation/devicetree/bindings/usb/usb3503.txt +++ b/Documentation/devicetree/bindings/usb/usb3503.txt @@ -1,7 +1,7 @@ SMSC USB3503 High-Speed Hub Controller Required properties: -- compatible: Should be "smsc,usb3503". +- compatible: Should be "smsc,usb3503" or "smsc,usb3503a". - reg: Specifies the i2c slave address, it should be 0x08. - connect-gpios: Should specify GPIO for connect. - disabled-ports: Should specify the ports unused. diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c index 8f5dff20dcb4..da45ed971332 100644 --- a/drivers/usb/misc/usb3503.c +++ b/drivers/usb/misc/usb3503.c @@ -272,6 +272,7 @@ MODULE_DEVICE_TABLE(i2c, usb3503_id); #ifdef CONFIG_OF static const struct of_device_id usb3503_of_match[] = { { .compatible = "smsc,usb3503", }, + { .compatible = "smsc,usb3503a", }, {}, }; MODULE_DEVICE_TABLE(of, usb3503_of_match); -- cgit v1.2.3 From 3f0d1c67fa20d524fdcb4a7dcda19ed76c59be44 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 9 Aug 2013 11:41:58 +0100 Subject: usb: misc: usb3503: Support operation with no I2C control Refactor so that register writes for configuration are only performed if the device has a regmap provided and also register as a platform driver. This allows the driver to be used to manage GPIO based control of the device. Signed-off-by: Mark Brown Cc: devicetree@vger.kernel.org Reviewed-by: Dongjin Kim Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/usb/usb3503.txt | 3 +- drivers/usb/misc/usb3503.c | 93 ++++++++++++++++++----- 2 files changed, 78 insertions(+), 18 deletions(-) (limited to 'drivers/usb/misc') diff --git a/Documentation/devicetree/bindings/usb/usb3503.txt b/Documentation/devicetree/bindings/usb/usb3503.txt index 44a03f338424..a018da4a7ad7 100644 --- a/Documentation/devicetree/bindings/usb/usb3503.txt +++ b/Documentation/devicetree/bindings/usb/usb3503.txt @@ -2,9 +2,10 @@ SMSC USB3503 High-Speed Hub Controller Required properties: - compatible: Should be "smsc,usb3503" or "smsc,usb3503a". -- reg: Specifies the i2c slave address, it should be 0x08. Optional properties: +- reg: Specifies the i2c slave address, it is required and should be 0x08 + if I2C is used. - connect-gpios: Should specify GPIO for connect. - disabled-ports: Should specify the ports unused. '1' or '2' or '3' are availe for this property to describe the port diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c index da45ed971332..a31641e18d19 100644 --- a/drivers/usb/misc/usb3503.c +++ b/drivers/usb/misc/usb3503.c @@ -78,22 +78,21 @@ static int usb3503_reset(struct usb3503 *hub, int state) return 0; } -static int usb3503_switch_mode(struct usb3503 *hub, enum usb3503_mode mode) +static int usb3503_connect(struct usb3503 *hub) { struct device *dev = hub->dev; - int err = 0; + int err; - switch (mode) { - case USB3503_MODE_HUB: - usb3503_reset(hub, 1); + usb3503_reset(hub, 1); + if (hub->regmap) { /* SP_ILOCK: set connect_n, config_n for config */ err = regmap_write(hub->regmap, USB3503_SP_ILOCK, - (USB3503_SPILOCK_CONNECT + (USB3503_SPILOCK_CONNECT | USB3503_SPILOCK_CONFIG)); if (err < 0) { dev_err(dev, "SP_ILOCK failed (%d)\n", err); - goto err_hubmode; + return err; } /* PDS : Disable For Self Powered Operation */ @@ -103,7 +102,7 @@ static int usb3503_switch_mode(struct usb3503 *hub, enum usb3503_mode mode) hub->port_off_mask); if (err < 0) { dev_err(dev, "PDS failed (%d)\n", err); - goto err_hubmode; + return err; } } @@ -113,7 +112,7 @@ static int usb3503_switch_mode(struct usb3503 *hub, enum usb3503_mode mode) USB3503_SELF_BUS_PWR); if (err < 0) { dev_err(dev, "CFG1 failed (%d)\n", err); - goto err_hubmode; + return err; } /* SP_LOCK: clear connect_n, config_n for hub connect */ @@ -122,14 +121,27 @@ static int usb3503_switch_mode(struct usb3503 *hub, enum usb3503_mode mode) | USB3503_SPILOCK_CONFIG), 0); if (err < 0) { dev_err(dev, "SP_ILOCK failed (%d)\n", err); - goto err_hubmode; + return err; } + } - if (gpio_is_valid(hub->gpio_connect)) - gpio_set_value_cansleep(hub->gpio_connect, 1); + if (gpio_is_valid(hub->gpio_connect)) + gpio_set_value_cansleep(hub->gpio_connect, 1); - hub->mode = mode; - dev_info(dev, "switched to HUB mode\n"); + hub->mode = USB3503_MODE_HUB; + dev_info(dev, "switched to HUB mode\n"); + + return 0; +} + +static int usb3503_switch_mode(struct usb3503 *hub, enum usb3503_mode mode) +{ + struct device *dev = hub->dev; + int err = 0; + + switch (mode) { + case USB3503_MODE_HUB: + err = usb3503_connect(hub); break; case USB3503_MODE_STANDBY: @@ -145,7 +157,6 @@ static int usb3503_switch_mode(struct usb3503 *hub, enum usb3503_mode mode) break; } -err_hubmode: return err; } @@ -198,6 +209,9 @@ static int usb3503_probe(struct usb3503 *hub) hub->mode = mode; } + if (hub->port_off_mask && !hub->regmap) + dev_err(dev, "Ports disabled with no control interface\n"); + if (gpio_is_valid(hub->gpio_intn)) { err = devm_gpio_request_one(dev, hub->gpio_intn, GPIOF_OUT_INIT_HIGH, "usb3503 intn"); @@ -263,6 +277,20 @@ static int usb3503_i2c_probe(struct i2c_client *i2c, return usb3503_probe(hub); } +static int usb3503_platform_probe(struct platform_device *pdev) +{ + struct usb3503 *hub; + + hub = devm_kzalloc(&pdev->dev, sizeof(struct usb3503), GFP_KERNEL); + if (!hub) { + dev_err(&pdev->dev, "private data alloc fail\n"); + return -ENOMEM; + } + hub->dev = &pdev->dev; + + return usb3503_probe(hub); +} + static const struct i2c_device_id usb3503_id[] = { { USB3503_I2C_NAME, 0 }, { } @@ -278,7 +306,7 @@ static const struct of_device_id usb3503_of_match[] = { MODULE_DEVICE_TABLE(of, usb3503_of_match); #endif -static struct i2c_driver usb3503_driver = { +static struct i2c_driver usb3503_i2c_driver = { .driver = { .name = USB3503_I2C_NAME, .of_match_table = of_match_ptr(usb3503_of_match), @@ -287,7 +315,38 @@ static struct i2c_driver usb3503_driver = { .id_table = usb3503_id, }; -module_i2c_driver(usb3503_driver); +static struct platform_driver usb3503_platform_driver = { + .driver = { + .name = USB3503_I2C_NAME, + .of_match_table = of_match_ptr(usb3503_of_match), + .owner = THIS_MODULE, + }, + .probe = usb3503_platform_probe, +}; + +static int __init usb3503_init(void) +{ + int err; + + err = i2c_register_driver(THIS_MODULE, &usb3503_i2c_driver); + if (err != 0) + pr_err("usb3503: Failed to register I2C driver: %d\n", err); + + err = platform_driver_register(&usb3503_platform_driver); + if (err != 0) + pr_err("usb3503: Failed to register platform driver: %d\n", + err); + + return 0; +} +module_init(usb3503_init); + +static void __exit usb3503_exit(void) +{ + platform_driver_unregister(&usb3503_platform_driver); + i2c_del_driver(&usb3503_i2c_driver); +} +module_exit(usb3503_exit); MODULE_AUTHOR("Dongjin Kim "); MODULE_DESCRIPTION("USB3503 USB HUB driver"); -- cgit v1.2.3 From 9841f37a1cca5357c1fd198b1068c12955aa632f Mon Sep 17 00:00:00 2001 From: Manu Gautam Date: Thu, 8 Aug 2013 16:49:24 -0700 Subject: usb: ehci: Add support for SINGLE_STEP_SET_FEATURE test of EHSET The USB Embedded High-speed Host Electrical Test (EHSET) defines the SINGLE_STEP_SET_FEATURE test as follows: 1) The host enumerates the test device with VID:0x1A0A, PID:0x0108 2) The host sends the SETUP stage of a GetDescriptor(Device) 3) The device ACKs the request 4) The host issues SOFs for 15 seconds allowing the test operator to raise the scope trigger just above the SOF voltage level 5) The host sends the IN packet 6) The device sends data in response, triggering the scope 7) The host sends an ACK in response to the data This patch adds additional handling to the EHCI hub driver and allows the EHSET driver to initiate this test mode by issuing a a SetFeature request to the root hub with a Test Selector value of 0x06. From there it mimics ehci_urb_enqueue() but separately submits QTDs for the SETUP and DATA/STATUS stages in order to insert a delay in between. Signed-off-by: Manu Gautam Acked-by: Alan Stern [jackp@codeaurora.org: imported from commit c2084930 on codeaurora.org; minor cleanup and updated author email] Signed-off-by: Jack Pham Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hub.c | 144 +++++++++++++++++++++++++++++++++++++++++++- drivers/usb/host/ehci-q.c | 101 +++++++++++++++++++++++++++++++ drivers/usb/misc/ehset.c | 20 +++++- 3 files changed, 263 insertions(+), 2 deletions(-) (limited to 'drivers/usb/misc') diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 269a2e8ad0ab..d0d4cc151e71 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -711,6 +711,142 @@ ehci_hub_descriptor ( desc->wHubCharacteristics = cpu_to_le16(temp); } +/*-------------------------------------------------------------------------*/ +#define EHSET_TEST_SINGLE_STEP_SET_FEATURE 0x06 + +static void usb_ehset_completion(struct urb *urb) +{ + struct completion *done = urb->context; + + complete(done); +} +static int submit_single_step_set_feature( + struct usb_hcd *hcd, + struct urb *urb, + int is_setup +); + +/* + * Allocate and initialize a control URB. This request will be used by the + * EHSET SINGLE_STEP_SET_FEATURE test in which the DATA and STATUS stages + * of the GetDescriptor request are sent 15 seconds after the SETUP stage. + * Return NULL if failed. + */ +static struct urb *request_single_step_set_feature_urb( + struct usb_device *udev, + void *dr, + void *buf, + struct completion *done +) { + struct urb *urb; + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + struct usb_host_endpoint *ep; + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) + return NULL; + + urb->pipe = usb_rcvctrlpipe(udev, 0); + ep = (usb_pipein(urb->pipe) ? udev->ep_in : udev->ep_out) + [usb_pipeendpoint(urb->pipe)]; + if (!ep) { + usb_free_urb(urb); + return NULL; + } + + urb->ep = ep; + urb->dev = udev; + urb->setup_packet = (void *)dr; + urb->transfer_buffer = buf; + urb->transfer_buffer_length = USB_DT_DEVICE_SIZE; + urb->complete = usb_ehset_completion; + urb->status = -EINPROGRESS; + urb->actual_length = 0; + urb->transfer_flags = URB_DIR_IN; + usb_get_urb(urb); + atomic_inc(&urb->use_count); + atomic_inc(&urb->dev->urbnum); + urb->setup_dma = dma_map_single( + hcd->self.controller, + urb->setup_packet, + sizeof(struct usb_ctrlrequest), + DMA_TO_DEVICE); + urb->transfer_dma = dma_map_single( + hcd->self.controller, + urb->transfer_buffer, + urb->transfer_buffer_length, + DMA_FROM_DEVICE); + urb->context = done; + return urb; +} + +static int ehset_single_step_set_feature(struct usb_hcd *hcd, int port) +{ + int retval = -ENOMEM; + struct usb_ctrlrequest *dr; + struct urb *urb; + struct usb_device *udev; + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + struct usb_device_descriptor *buf; + DECLARE_COMPLETION_ONSTACK(done); + + /* Obtain udev of the rhub's child port */ + udev = usb_hub_find_child(hcd->self.root_hub, port); + if (!udev) { + ehci_err(ehci, "No device attached to the RootHub\n"); + return -ENODEV; + } + buf = kmalloc(USB_DT_DEVICE_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); + if (!dr) { + kfree(buf); + return -ENOMEM; + } + + /* Fill Setup packet for GetDescriptor */ + dr->bRequestType = USB_DIR_IN; + dr->bRequest = USB_REQ_GET_DESCRIPTOR; + dr->wValue = cpu_to_le16(USB_DT_DEVICE << 8); + dr->wIndex = 0; + dr->wLength = cpu_to_le16(USB_DT_DEVICE_SIZE); + urb = request_single_step_set_feature_urb(udev, dr, buf, &done); + if (!urb) + goto cleanup; + + /* Submit just the SETUP stage */ + retval = submit_single_step_set_feature(hcd, urb, 1); + if (retval) + goto out1; + if (!wait_for_completion_timeout(&done, msecs_to_jiffies(2000))) { + usb_kill_urb(urb); + retval = -ETIMEDOUT; + ehci_err(ehci, "%s SETUP stage timed out on ep0\n", __func__); + goto out1; + } + msleep(15 * 1000); + + /* Complete remaining DATA and STATUS stages using the same URB */ + urb->status = -EINPROGRESS; + usb_get_urb(urb); + atomic_inc(&urb->use_count); + atomic_inc(&urb->dev->urbnum); + retval = submit_single_step_set_feature(hcd, urb, 0); + if (!retval && !wait_for_completion_timeout(&done, + msecs_to_jiffies(2000))) { + usb_kill_urb(urb); + retval = -ETIMEDOUT; + ehci_err(ehci, "%s IN stage timed out on ep0\n", __func__); + } +out1: + usb_free_urb(urb); +cleanup: + kfree(dr); + kfree(buf); + return retval; +} /*-------------------------------------------------------------------------*/ static int ehci_hub_control ( @@ -1086,7 +1222,13 @@ static int ehci_hub_control ( * about the EHCI-specific stuff. */ case USB_PORT_FEAT_TEST: - if (!selector || selector > 5) + if (selector == EHSET_TEST_SINGLE_STEP_SET_FEATURE) { + spin_unlock_irqrestore(&ehci->lock, flags); + retval = ehset_single_step_set_feature(hcd, + wIndex); + spin_lock_irqsave(&ehci->lock, flags); + break; + } else if (!selector || selector > 5) goto error; spin_unlock_irqrestore(&ehci->lock, flags); ehci_quiesce(ehci); diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index b637a65e1e52..903d00dd6683 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -1138,6 +1138,107 @@ submit_async ( return rc; } +/*-------------------------------------------------------------------------*/ +/* + * This function creates the qtds and submits them for the + * SINGLE_STEP_SET_FEATURE Test. + * This is done in two parts: first SETUP req for GetDesc is sent then + * 15 seconds later, the IN stage for GetDesc starts to req data from dev + * + * is_setup : i/p arguement decides which of the two stage needs to be + * performed; TRUE - SETUP and FALSE - IN+STATUS + * Returns 0 if success + */ +static int submit_single_step_set_feature( + struct usb_hcd *hcd, + struct urb *urb, + int is_setup +) { + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + struct list_head qtd_list; + struct list_head *head; + + struct ehci_qtd *qtd, *qtd_prev; + dma_addr_t buf; + int len, maxpacket; + u32 token; + + INIT_LIST_HEAD(&qtd_list); + head = &qtd_list; + + /* URBs map to sequences of QTDs: one logical transaction */ + qtd = ehci_qtd_alloc(ehci, GFP_KERNEL); + if (unlikely(!qtd)) + return -1; + list_add_tail(&qtd->qtd_list, head); + qtd->urb = urb; + + token = QTD_STS_ACTIVE; + token |= (EHCI_TUNE_CERR << 10); + + len = urb->transfer_buffer_length; + /* + * Check if the request is to perform just the SETUP stage (getDesc) + * as in SINGLE_STEP_SET_FEATURE test, DATA stage (IN) happens + * 15 secs after the setup + */ + if (is_setup) { + /* SETUP pid */ + qtd_fill(ehci, qtd, urb->setup_dma, + sizeof(struct usb_ctrlrequest), + token | (2 /* "setup" */ << 8), 8); + + submit_async(ehci, urb, &qtd_list, GFP_ATOMIC); + return 0; /*Return now; we shall come back after 15 seconds*/ + } + + /* + * IN: data transfer stage: buffer setup : start the IN txn phase for + * the get_Desc SETUP which was sent 15seconds back + */ + token ^= QTD_TOGGLE; /*We need to start IN with DATA-1 Pid-sequence*/ + buf = urb->transfer_dma; + + token |= (1 /* "in" */ << 8); /*This is IN stage*/ + + maxpacket = max_packet(usb_maxpacket(urb->dev, urb->pipe, 0)); + + qtd_fill(ehci, qtd, buf, len, token, maxpacket); + + /* + * Our IN phase shall always be a short read; so keep the queue running + * and let it advance to the next qtd which zero length OUT status + */ + qtd->hw_alt_next = EHCI_LIST_END(ehci); + + /* STATUS stage for GetDesc control request */ + token ^= 0x0100; /* "in" <--> "out" */ + token |= QTD_TOGGLE; /* force DATA1 */ + + qtd_prev = qtd; + qtd = ehci_qtd_alloc(ehci, GFP_ATOMIC); + if (unlikely(!qtd)) + goto cleanup; + qtd->urb = urb; + qtd_prev->hw_next = QTD_NEXT(ehci, qtd->qtd_dma); + list_add_tail(&qtd->qtd_list, head); + + /* dont fill any data in such packets */ + qtd_fill(ehci, qtd, 0, 0, token, 0); + + /* by default, enable interrupt on urb completion */ + if (likely(!(urb->transfer_flags & URB_NO_INTERRUPT))) + qtd->hw_token |= cpu_to_hc32(ehci, QTD_IOC); + + submit_async(ehci, urb, &qtd_list, GFP_KERNEL); + + return 0; + +cleanup: + qtd_list_free(ehci, urb, head); + return -1; +} + /*-------------------------------------------------------------------------*/ static void single_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh) diff --git a/drivers/usb/misc/ehset.c b/drivers/usb/misc/ehset.c index d2864b3f41fe..c31b4a33e6bb 100644 --- a/drivers/usb/misc/ehset.c +++ b/drivers/usb/misc/ehset.c @@ -96,7 +96,25 @@ static int ehset_probe(struct usb_interface *intf, kfree(buf); break; case TEST_SINGLE_STEP_SET_FEATURE: - /* unsupported for now */ + /* + * GetDescriptor SETUP request -> 15secs delay -> IN & STATUS + * + * Note, this test is only supported on root hubs since the + * SetPortFeature handling can only be done inside the HCD's + * hub_control callback function. + */ + if (hub_udev != dev->bus->root_hub) { + dev_err(&intf->dev, "SINGLE_STEP_SET_FEATURE test only supported on root hub\n"); + break; + } + + ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0), + USB_REQ_SET_FEATURE, USB_RT_PORT, + USB_PORT_FEAT_TEST, + (6 << 8) | portnum, + NULL, 0, 60 * 1000); + + break; default: dev_err(&intf->dev, "%s: unsupported PID: 0x%x\n", __func__, test_pid); -- cgit v1.2.3 From 9821aa9de97ccaaa16297d42a2c5a532c0032097 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 13 Aug 2013 13:27:40 +0200 Subject: USB: uss720: fix DMA-buffer allocation Make sure the USB control request is allocated separately from containing structure to prevent potential memory corruption on non-cache-coherent systems. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/uss720.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) (limited to 'drivers/usb/misc') diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c index e129cf661223..40ef40affe83 100644 --- a/drivers/usb/misc/uss720.c +++ b/drivers/usb/misc/uss720.c @@ -75,7 +75,7 @@ struct uss720_async_request { struct list_head asynclist; struct completion compl; struct urb *urb; - struct usb_ctrlrequest dr; + struct usb_ctrlrequest *dr; __u8 reg[7]; }; @@ -98,6 +98,7 @@ static void destroy_async(struct kref *kref) if (likely(rq->urb)) usb_free_urb(rq->urb); + kfree(rq->dr); spin_lock_irqsave(&priv->asynclock, flags); list_del_init(&rq->asynclist); spin_unlock_irqrestore(&priv->asynclock, flags); @@ -120,7 +121,7 @@ static void async_complete(struct urb *urb) if (status) { dev_err(&urb->dev->dev, "async_complete: urb error %d\n", status); - } else if (rq->dr.bRequest == 3) { + } else if (rq->dr->bRequest == 3) { memcpy(priv->reg, rq->reg, sizeof(priv->reg)); #if 0 dev_dbg(&priv->usbdev->dev, @@ -152,7 +153,7 @@ static struct uss720_async_request *submit_async_request(struct parport_uss720_p usbdev = priv->usbdev; if (!usbdev) return NULL; - rq = kmalloc(sizeof(struct uss720_async_request), mem_flags); + rq = kzalloc(sizeof(struct uss720_async_request), mem_flags); if (!rq) { dev_err(&usbdev->dev, "submit_async_request out of memory\n"); return NULL; @@ -168,13 +169,18 @@ static struct uss720_async_request *submit_async_request(struct parport_uss720_p dev_err(&usbdev->dev, "submit_async_request out of memory\n"); return NULL; } - rq->dr.bRequestType = requesttype; - rq->dr.bRequest = request; - rq->dr.wValue = cpu_to_le16(value); - rq->dr.wIndex = cpu_to_le16(index); - rq->dr.wLength = cpu_to_le16((request == 3) ? sizeof(rq->reg) : 0); + rq->dr = kmalloc(sizeof(*rq->dr), mem_flags); + if (!rq->dr) { + kref_put(&rq->ref_count, destroy_async); + return NULL; + } + rq->dr->bRequestType = requesttype; + rq->dr->bRequest = request; + rq->dr->wValue = cpu_to_le16(value); + rq->dr->wIndex = cpu_to_le16(index); + rq->dr->wLength = cpu_to_le16((request == 3) ? sizeof(rq->reg) : 0); usb_fill_control_urb(rq->urb, usbdev, (requesttype & 0x80) ? usb_rcvctrlpipe(usbdev, 0) : usb_sndctrlpipe(usbdev, 0), - (unsigned char *)&rq->dr, + (unsigned char *)rq->dr, (request == 3) ? rq->reg : NULL, (request == 3) ? sizeof(rq->reg) : 0, async_complete, rq); /* rq->urb->transfer_flags |= URB_ASYNC_UNLINK; */ spin_lock_irqsave(&priv->asynclock, flags); -- cgit v1.2.3