summaryrefslogtreecommitdiffstats
path: root/drivers/usb/misc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/misc')
-rw-r--r--drivers/usb/misc/auerswald.c10
-rw-r--r--drivers/usb/misc/ftdi-elan.c12
-rw-r--r--drivers/usb/misc/ldusb.c35
3 files changed, 41 insertions, 16 deletions
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
index 88fb56d5db8..cac1500cba6 100644
--- a/drivers/usb/misc/auerswald.c
+++ b/drivers/usb/misc/auerswald.c
@@ -1822,16 +1822,10 @@ static int auerchar_release (struct inode *inode, struct file *file)
pauerswald_t cp;
dbg("release");
- /* get the mutexes */
- if (down_interruptible (&ccp->mutex)) {
- return -ERESTARTSYS;
- }
+ down(&ccp->mutex);
cp = ccp->auerdev;
if (cp) {
- if (down_interruptible (&cp->mutex)) {
- up (&ccp->mutex);
- return -ERESTARTSYS;
- }
+ down(&cp->mutex);
/* remove an open service */
auerswald_removeservice (cp, &ccp->scontext);
/* detach from device */
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
index e2172e5cf15..e0f122e131d 100644
--- a/drivers/usb/misc/ftdi-elan.c
+++ b/drivers/usb/misc/ftdi-elan.c
@@ -73,6 +73,13 @@ static struct list_head ftdi_static_list;
#include "usb_u132.h"
#include <asm/io.h>
#include "../core/hcd.h"
+
+ /* FIXME ohci.h is ONLY for internal use by the OHCI driver.
+ * If you're going to try stuff like this, you need to split
+ * out shareable stuff (register declarations?) into its own
+ * file, maybe name <linux/usb/ohci.h>
+ */
+
#include "../host/ohci.h"
/* Define these values to match your devices*/
#define USB_FTDI_ELAN_VENDOR_ID 0x0403
@@ -2300,10 +2307,7 @@ static int ftdi_elan_checkingPCI(struct usb_ftdi *ftdi)
offsetof(struct ohci_regs, member), 0, data);
#define ftdi_write_pcimem(ftdi, member, data) ftdi_elan_write_pcimem(ftdi, \
offsetof(struct ohci_regs, member), 0, data);
-#define OHCI_QUIRK_AMD756 0x01
-#define OHCI_QUIRK_SUPERIO 0x02
-#define OHCI_QUIRK_INITRESET 0x04
-#define OHCI_BIG_ENDIAN 0x08
+
#define OHCI_CONTROL_INIT OHCI_CTRL_CBSR
#define OHCI_INTR_INIT (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | \
OHCI_INTR_WDH)
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
index 11555bde655..7bad4940476 100644
--- a/drivers/usb/misc/ldusb.c
+++ b/drivers/usb/misc/ldusb.c
@@ -165,6 +165,8 @@ struct ld_usb {
size_t interrupt_in_endpoint_size;
int interrupt_in_running;
int interrupt_in_done;
+ int buffer_overflow;
+ spinlock_t rbsl;
char* interrupt_out_buffer;
struct usb_endpoint_descriptor* interrupt_out_endpoint;
@@ -230,10 +232,12 @@ static void ld_usb_interrupt_in_callback(struct urb *urb)
} else {
dbg_info(&dev->intf->dev, "%s: nonzero status received: %d\n",
__FUNCTION__, urb->status);
+ spin_lock(&dev->rbsl);
goto resubmit; /* maybe we can recover */
}
}
+ spin_lock(&dev->rbsl);
if (urb->actual_length > 0) {
next_ring_head = (dev->ring_head+1) % ring_buffer_size;
if (next_ring_head != dev->ring_tail) {
@@ -244,21 +248,25 @@ static void ld_usb_interrupt_in_callback(struct urb *urb)
dev->ring_head = next_ring_head;
dbg_info(&dev->intf->dev, "%s: received %d bytes\n",
__FUNCTION__, urb->actual_length);
- } else
+ } else {
dev_warn(&dev->intf->dev,
"Ring buffer overflow, %d bytes dropped\n",
urb->actual_length);
+ dev->buffer_overflow = 1;
+ }
}
resubmit:
/* resubmit if we're still running */
- if (dev->interrupt_in_running && dev->intf) {
+ if (dev->interrupt_in_running && !dev->buffer_overflow && dev->intf) {
retval = usb_submit_urb(dev->interrupt_in_urb, GFP_ATOMIC);
- if (retval)
+ if (retval) {
dev_err(&dev->intf->dev,
"usb_submit_urb failed (%d)\n", retval);
+ dev->buffer_overflow = 1;
+ }
}
-
+ spin_unlock(&dev->rbsl);
exit:
dev->interrupt_in_done = 1;
wake_up_interruptible(&dev->read_wait);
@@ -330,6 +338,7 @@ static int ld_usb_open(struct inode *inode, struct file *file)
/* initialize in direction */
dev->ring_head = 0;
dev->ring_tail = 0;
+ dev->buffer_overflow = 0;
usb_fill_int_urb(dev->interrupt_in_urb,
interface_to_usbdev(interface),
usb_rcvintpipe(interface_to_usbdev(interface),
@@ -439,6 +448,7 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count,
size_t *actual_buffer;
size_t bytes_to_read;
int retval = 0;
+ int rv;
dev = file->private_data;
@@ -460,7 +470,10 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count,
}
/* wait for data */
+ spin_lock_irq(&dev->rbsl);
if (dev->ring_head == dev->ring_tail) {
+ dev->interrupt_in_done = 0;
+ spin_unlock_irq(&dev->rbsl);
if (file->f_flags & O_NONBLOCK) {
retval = -EAGAIN;
goto unlock_exit;
@@ -468,6 +481,8 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count,
retval = wait_event_interruptible(dev->read_wait, dev->interrupt_in_done);
if (retval < 0)
goto unlock_exit;
+ } else {
+ spin_unlock_irq(&dev->rbsl);
}
/* actual_buffer contains actual_length + interrupt_in_buffer */
@@ -486,6 +501,17 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count,
retval = bytes_to_read;
+ spin_lock_irq(&dev->rbsl);
+ if (dev->buffer_overflow) {
+ dev->buffer_overflow = 0;
+ spin_unlock_irq(&dev->rbsl);
+ rv = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
+ if (rv < 0)
+ dev->buffer_overflow = 1;
+ } else {
+ spin_unlock_irq(&dev->rbsl);
+ }
+
unlock_exit:
/* unlock the device */
up(&dev->sem);
@@ -635,6 +661,7 @@ static int ld_usb_probe(struct usb_interface *intf, const struct usb_device_id *
goto exit;
}
init_MUTEX(&dev->sem);
+ spin_lock_init(&dev->rbsl);
dev->intf = intf;
init_waitqueue_head(&dev->read_wait);
init_waitqueue_head(&dev->write_wait);