1
0
Fork 0

USB fixes for 5.2-rc3

Here are some tiny USB fixes for a number of reported issues for
 5.2-rc3.
 
 Nothing huge here, just a small collection of xhci and other driver bugs
 that syzbot has been finding in some drivers.  There is also a usbip fix
 and a fix for the usbip fix in here :)
 
 All have been in linux-next with no reported issues.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCXPCDwQ8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+yli6QCaAmaLPqpgO12vsYlD7KYfktM7wYEAnjD+L73Z
 Sc9htZ4BudpBzjK3FPyH
 =rCpe
 -----END PGP SIGNATURE-----

Merge tag 'usb-5.2-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb

Pull USB fixes from Greg KH:
 "Here are some tiny USB fixes for a number of reported issues for
  5.2-rc3.

  Nothing huge here, just a small collection of xhci and other driver
  bugs that syzbot has been finding in some drivers. There is also a
  usbip fix and a fix for the usbip fix in here :)

  All have been in linux-next with no reported issues"

* tag 'usb-5.2-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  usbip: usbip_host: fix stub_dev lock context imbalance regression
  media: smsusb: better handle optional alignment
  xhci: Use %zu for printing size_t type
  xhci: Convert xhci_handshake() to use readl_poll_timeout_atomic()
  xhci: Fix immediate data transfer if buffer is already DMA mapped
  usb: xhci: avoid null pointer deref when bos field is NULL
  usb: xhci: Fix a potential null pointer dereference in xhci_debugfs_create_endpoint()
  xhci: update bounce buffer with correct sg num
  media: usb: siano: Fix false-positive "uninitialized variable" warning
  USB: rio500: update Documentation
  USB: rio500: simplify locking
  USB: rio500: fix memory leak in close after disconnect
  USB: rio500: refuse more than one device at a time
  usbip: usbip_host: fix BUG: sleeping function called from invalid context
  USB: sisusbvga: fix oops in error path of sisusb_probe
  USB: Add LPM quirk for Surface Dock GigE adapter
  media: usb: siano: Fix general protection fault in smsusb
  usb: mtu3: fix up undefined reference to usb_debug_root
  USB: Fix slab-out-of-bounds write in usb_get_bos_descriptor
hifive-unleashed-5.2
Linus Torvalds 2019-05-31 08:16:31 -07:00
commit e49c8547fb
12 changed files with 182 additions and 153 deletions

View File

@ -76,70 +76,30 @@ Additional Information and userspace tools
Requirements Requirements
============ ============
A host with a USB port. Ideally, either a UHCI (Intel) or OHCI A host with a USB port running a Linux kernel with RIO 500 support enabled.
(Compaq and others) hardware port should work.
A Linux development kernel (2.3.x) with USB support enabled or a The driver is a module called rio500, which should be automatically loaded
backported version to linux-2.2.x. See http://www.linux-usb.org for as you plug in your device. If that fails you can manually load it with
more information on accomplishing this.
A Linux kernel with RIO 500 support enabled. modprobe rio500
'lspci' which is only needed to determine the type of USB hardware Udev should automatically create a device node as soon as plug in your device.
available in your machine. If that fails, you can manually add a device for the USB rio500::
Configuration
Using `lspci -v`, determine the type of USB hardware available.
If you see something like::
USB Controller: ......
Flags: .....
I/O ports at ....
Then you have a UHCI based controller.
If you see something like::
USB Controller: .....
Flags: ....
Memory at .....
Then you have a OHCI based controller.
Using `make menuconfig` or your preferred method for configuring the
kernel, select 'Support for USB', 'OHCI/UHCI' depending on your
hardware (determined from the steps above), 'USB Diamond Rio500 support', and
'Preliminary USB device filesystem'. Compile and install the modules
(you may need to execute `depmod -a` to update the module
dependencies).
Add a device for the USB rio500::
mknod /dev/usb/rio500 c 180 64 mknod /dev/usb/rio500 c 180 64
Set appropriate permissions for /dev/usb/rio500 (don't forget about In that case, set appropriate permissions for /dev/usb/rio500 (don't forget
group and world permissions). Both read and write permissions are about group and world permissions). Both read and write permissions are
required for proper operation. required for proper operation.
Load the appropriate modules (if compiled as modules):
OHCI::
modprobe usbcore
modprobe usb-ohci
modprobe rio500
UHCI::
modprobe usbcore
modprobe usb-uhci (or uhci)
modprobe rio500
That's it. The Rio500 Utils at: http://rio500.sourceforge.net should That's it. The Rio500 Utils at: http://rio500.sourceforge.net should
be able to access the rio500. be able to access the rio500.
Limits
======
You can use only a single rio500 device at a time with your computer.
Bugs Bugs
==== ====

View File

@ -389,6 +389,7 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
struct smsusb_device_t *dev; struct smsusb_device_t *dev;
void *mdev; void *mdev;
int i, rc; int i, rc;
int align = 0;
/* create device object */ /* create device object */
dev = kzalloc(sizeof(struct smsusb_device_t), GFP_KERNEL); dev = kzalloc(sizeof(struct smsusb_device_t), GFP_KERNEL);
@ -400,6 +401,24 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
dev->udev = interface_to_usbdev(intf); dev->udev = interface_to_usbdev(intf);
dev->state = SMSUSB_DISCONNECTED; dev->state = SMSUSB_DISCONNECTED;
for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
struct usb_endpoint_descriptor *desc =
&intf->cur_altsetting->endpoint[i].desc;
if (desc->bEndpointAddress & USB_DIR_IN) {
dev->in_ep = desc->bEndpointAddress;
align = usb_endpoint_maxp(desc) - sizeof(struct sms_msg_hdr);
} else {
dev->out_ep = desc->bEndpointAddress;
}
}
pr_debug("in_ep = %02x, out_ep = %02x\n", dev->in_ep, dev->out_ep);
if (!dev->in_ep || !dev->out_ep || align < 0) { /* Missing endpoints? */
smsusb_term_device(intf);
return -ENODEV;
}
params.device_type = sms_get_board(board_id)->type; params.device_type = sms_get_board(board_id)->type;
switch (params.device_type) { switch (params.device_type) {
@ -414,24 +433,12 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
/* fall-thru */ /* fall-thru */
default: default:
dev->buffer_size = USB2_BUFFER_SIZE; dev->buffer_size = USB2_BUFFER_SIZE;
dev->response_alignment = dev->response_alignment = align;
le16_to_cpu(dev->udev->ep_in[1]->desc.wMaxPacketSize) -
sizeof(struct sms_msg_hdr);
params.flags |= SMS_DEVICE_FAMILY2; params.flags |= SMS_DEVICE_FAMILY2;
break; break;
} }
for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
if (intf->cur_altsetting->endpoint[i].desc. bEndpointAddress & USB_DIR_IN)
dev->in_ep = intf->cur_altsetting->endpoint[i].desc.bEndpointAddress;
else
dev->out_ep = intf->cur_altsetting->endpoint[i].desc.bEndpointAddress;
}
pr_debug("in_ep = %02x, out_ep = %02x\n",
dev->in_ep, dev->out_ep);
params.device = &dev->udev->dev; params.device = &dev->udev->dev;
params.usb_device = dev->udev; params.usb_device = dev->udev;
params.buffer_size = dev->buffer_size; params.buffer_size = dev->buffer_size;

View File

@ -932,8 +932,8 @@ int usb_get_bos_descriptor(struct usb_device *dev)
/* Get BOS descriptor */ /* Get BOS descriptor */
ret = usb_get_descriptor(dev, USB_DT_BOS, 0, bos, USB_DT_BOS_SIZE); ret = usb_get_descriptor(dev, USB_DT_BOS, 0, bos, USB_DT_BOS_SIZE);
if (ret < USB_DT_BOS_SIZE) { if (ret < USB_DT_BOS_SIZE || bos->bLength < USB_DT_BOS_SIZE) {
dev_err(ddev, "unable to get BOS descriptor\n"); dev_err(ddev, "unable to get BOS descriptor or descriptor too short\n");
if (ret >= 0) if (ret >= 0)
ret = -ENOMSG; ret = -ENOMSG;
kfree(bos); kfree(bos);

View File

@ -209,6 +209,9 @@ static const struct usb_device_id usb_quirk_list[] = {
/* Microsoft LifeCam-VX700 v2.0 */ /* Microsoft LifeCam-VX700 v2.0 */
{ USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME }, { USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME },
/* Microsoft Surface Dock Ethernet (RTL8153 GigE) */
{ USB_DEVICE(0x045e, 0x07c6), .driver_info = USB_QUIRK_NO_LPM },
/* Cherry Stream G230 2.0 (G85-231) and 3.0 (G85-232) */ /* Cherry Stream G230 2.0 (G85-231) and 3.0 (G85-232) */
{ USB_DEVICE(0x046a, 0x0023), .driver_info = USB_QUIRK_RESET_RESUME }, { USB_DEVICE(0x046a, 0x0023), .driver_info = USB_QUIRK_RESET_RESUME },

View File

@ -440,6 +440,9 @@ void xhci_debugfs_create_endpoint(struct xhci_hcd *xhci,
struct xhci_ep_priv *epriv; struct xhci_ep_priv *epriv;
struct xhci_slot_priv *spriv = dev->debugfs_private; struct xhci_slot_priv *spriv = dev->debugfs_private;
if (!spriv)
return;
if (spriv->eps[ep_index]) if (spriv->eps[ep_index])
return; return;

View File

@ -656,6 +656,7 @@ static void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci,
struct device *dev = xhci_to_hcd(xhci)->self.controller; struct device *dev = xhci_to_hcd(xhci)->self.controller;
struct xhci_segment *seg = td->bounce_seg; struct xhci_segment *seg = td->bounce_seg;
struct urb *urb = td->urb; struct urb *urb = td->urb;
size_t len;
if (!ring || !seg || !urb) if (!ring || !seg || !urb)
return; return;
@ -666,11 +667,14 @@ static void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci,
return; return;
} }
/* for in tranfers we need to copy the data from bounce to sg */
sg_pcopy_from_buffer(urb->sg, urb->num_mapped_sgs, seg->bounce_buf,
seg->bounce_len, seg->bounce_offs);
dma_unmap_single(dev, seg->bounce_dma, ring->bounce_buf_len, dma_unmap_single(dev, seg->bounce_dma, ring->bounce_buf_len,
DMA_FROM_DEVICE); DMA_FROM_DEVICE);
/* for in tranfers we need to copy the data from bounce to sg */
len = sg_pcopy_from_buffer(urb->sg, urb->num_sgs, seg->bounce_buf,
seg->bounce_len, seg->bounce_offs);
if (len != seg->bounce_len)
xhci_warn(xhci, "WARN Wrong bounce buffer read length: %zu != %d\n",
len, seg->bounce_len);
seg->bounce_len = 0; seg->bounce_len = 0;
seg->bounce_offs = 0; seg->bounce_offs = 0;
} }
@ -3127,6 +3131,7 @@ static int xhci_align_td(struct xhci_hcd *xhci, struct urb *urb, u32 enqd_len,
unsigned int unalign; unsigned int unalign;
unsigned int max_pkt; unsigned int max_pkt;
u32 new_buff_len; u32 new_buff_len;
size_t len;
max_pkt = usb_endpoint_maxp(&urb->ep->desc); max_pkt = usb_endpoint_maxp(&urb->ep->desc);
unalign = (enqd_len + *trb_buff_len) % max_pkt; unalign = (enqd_len + *trb_buff_len) % max_pkt;
@ -3157,8 +3162,12 @@ static int xhci_align_td(struct xhci_hcd *xhci, struct urb *urb, u32 enqd_len,
/* create a max max_pkt sized bounce buffer pointed to by last trb */ /* create a max max_pkt sized bounce buffer pointed to by last trb */
if (usb_urb_dir_out(urb)) { if (usb_urb_dir_out(urb)) {
sg_pcopy_to_buffer(urb->sg, urb->num_mapped_sgs, len = sg_pcopy_to_buffer(urb->sg, urb->num_sgs,
seg->bounce_buf, new_buff_len, enqd_len); seg->bounce_buf, new_buff_len, enqd_len);
if (len != seg->bounce_len)
xhci_warn(xhci,
"WARN Wrong bounce buffer write length: %zu != %d\n",
len, seg->bounce_len);
seg->bounce_dma = dma_map_single(dev, seg->bounce_buf, seg->bounce_dma = dma_map_single(dev, seg->bounce_buf,
max_pkt, DMA_TO_DEVICE); max_pkt, DMA_TO_DEVICE);
} else { } else {
@ -3423,11 +3432,14 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
if (urb->transfer_buffer_length > 0) { if (urb->transfer_buffer_length > 0) {
u32 length_field, remainder; u32 length_field, remainder;
u64 addr;
if (xhci_urb_suitable_for_idt(urb)) { if (xhci_urb_suitable_for_idt(urb)) {
memcpy(&urb->transfer_dma, urb->transfer_buffer, memcpy(&addr, urb->transfer_buffer,
urb->transfer_buffer_length); urb->transfer_buffer_length);
field |= TRB_IDT; field |= TRB_IDT;
} else {
addr = (u64) urb->transfer_dma;
} }
remainder = xhci_td_remainder(xhci, 0, remainder = xhci_td_remainder(xhci, 0,
@ -3440,8 +3452,8 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
if (setup->bRequestType & USB_DIR_IN) if (setup->bRequestType & USB_DIR_IN)
field |= TRB_DIR_IN; field |= TRB_DIR_IN;
queue_trb(xhci, ep_ring, true, queue_trb(xhci, ep_ring, true,
lower_32_bits(urb->transfer_dma), lower_32_bits(addr),
upper_32_bits(urb->transfer_dma), upper_32_bits(addr),
length_field, length_field,
field | ep_ring->cycle_state); field | ep_ring->cycle_state);
} }

View File

@ -9,6 +9,7 @@
*/ */
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/iopoll.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/log2.h> #include <linux/log2.h>
#include <linux/module.h> #include <linux/module.h>
@ -52,7 +53,6 @@ static bool td_on_ring(struct xhci_td *td, struct xhci_ring *ring)
return false; return false;
} }
/* TODO: copied from ehci-hcd.c - can this be refactored? */
/* /*
* xhci_handshake - spin reading hc until handshake completes or fails * xhci_handshake - spin reading hc until handshake completes or fails
* @ptr: address of hc register to be read * @ptr: address of hc register to be read
@ -69,18 +69,16 @@ static bool td_on_ring(struct xhci_td *td, struct xhci_ring *ring)
int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, int usec) int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, int usec)
{ {
u32 result; u32 result;
int ret;
do { ret = readl_poll_timeout_atomic(ptr, result,
result = readl(ptr); (result & mask) == done ||
if (result == ~(u32)0) /* card removed */ result == U32_MAX,
return -ENODEV; 1, usec);
result &= mask; if (result == U32_MAX) /* card removed */
if (result == done) return -ENODEV;
return 0;
udelay(1); return ret;
usec--;
} while (usec > 0);
return -ETIMEDOUT;
} }
/* /*
@ -4320,7 +4318,6 @@ static int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
pm_addr = ports[port_num]->addr + PORTPMSC; pm_addr = ports[port_num]->addr + PORTPMSC;
pm_val = readl(pm_addr); pm_val = readl(pm_addr);
hlpm_addr = ports[port_num]->addr + PORTHLPMC; hlpm_addr = ports[port_num]->addr + PORTHLPMC;
field = le32_to_cpu(udev->bos->ext_cap->bmAttributes);
xhci_dbg(xhci, "%s port %d USB2 hardware LPM\n", xhci_dbg(xhci, "%s port %d USB2 hardware LPM\n",
enable ? "enable" : "disable", port_num + 1); enable ? "enable" : "disable", port_num + 1);
@ -4332,6 +4329,7 @@ static int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
* default one which works with mixed HIRD and BESL * default one which works with mixed HIRD and BESL
* systems. See XHCI_DEFAULT_BESL definition in xhci.h * systems. See XHCI_DEFAULT_BESL definition in xhci.h
*/ */
field = le32_to_cpu(udev->bos->ext_cap->bmAttributes);
if ((field & USB_BESL_SUPPORT) && if ((field & USB_BESL_SUPPORT) &&
(field & USB_BESL_BASELINE_VALID)) (field & USB_BESL_BASELINE_VALID))
hird = USB_GET_BESL_BASELINE(field); hird = USB_GET_BESL_BASELINE(field);

View File

@ -2160,7 +2160,8 @@ static inline bool xhci_urb_suitable_for_idt(struct urb *urb)
{ {
if (!usb_endpoint_xfer_isoc(&urb->ep->desc) && usb_urb_dir_out(urb) && if (!usb_endpoint_xfer_isoc(&urb->ep->desc) && usb_urb_dir_out(urb) &&
usb_endpoint_maxp(&urb->ep->desc) >= TRB_IDT_MAX_SIZE && usb_endpoint_maxp(&urb->ep->desc) >= TRB_IDT_MAX_SIZE &&
urb->transfer_buffer_length <= TRB_IDT_MAX_SIZE) urb->transfer_buffer_length <= TRB_IDT_MAX_SIZE &&
!(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
return true; return true;
return false; return false;

View File

@ -51,7 +51,6 @@ struct rio_usb_data {
char *obuf, *ibuf; /* transfer buffers */ char *obuf, *ibuf; /* transfer buffers */
char bulk_in_ep, bulk_out_ep; /* Endpoint assignments */ char bulk_in_ep, bulk_out_ep; /* Endpoint assignments */
wait_queue_head_t wait_q; /* for timeouts */ wait_queue_head_t wait_q; /* for timeouts */
struct mutex lock; /* general race avoidance */
}; };
static DEFINE_MUTEX(rio500_mutex); static DEFINE_MUTEX(rio500_mutex);
@ -63,10 +62,8 @@ static int open_rio(struct inode *inode, struct file *file)
/* against disconnect() */ /* against disconnect() */
mutex_lock(&rio500_mutex); mutex_lock(&rio500_mutex);
mutex_lock(&(rio->lock));
if (rio->isopen || !rio->present) { if (rio->isopen || !rio->present) {
mutex_unlock(&(rio->lock));
mutex_unlock(&rio500_mutex); mutex_unlock(&rio500_mutex);
return -EBUSY; return -EBUSY;
} }
@ -74,7 +71,6 @@ static int open_rio(struct inode *inode, struct file *file)
init_waitqueue_head(&rio->wait_q); init_waitqueue_head(&rio->wait_q);
mutex_unlock(&(rio->lock));
dev_info(&rio->rio_dev->dev, "Rio opened.\n"); dev_info(&rio->rio_dev->dev, "Rio opened.\n");
mutex_unlock(&rio500_mutex); mutex_unlock(&rio500_mutex);
@ -86,9 +82,20 @@ static int close_rio(struct inode *inode, struct file *file)
{ {
struct rio_usb_data *rio = &rio_instance; struct rio_usb_data *rio = &rio_instance;
rio->isopen = 0; /* against disconnect() */
mutex_lock(&rio500_mutex);
dev_info(&rio->rio_dev->dev, "Rio closed.\n"); rio->isopen = 0;
if (!rio->present) {
/* cleanup has been delayed */
kfree(rio->ibuf);
kfree(rio->obuf);
rio->ibuf = NULL;
rio->obuf = NULL;
} else {
dev_info(&rio->rio_dev->dev, "Rio closed.\n");
}
mutex_unlock(&rio500_mutex);
return 0; return 0;
} }
@ -102,7 +109,7 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg)
int retries; int retries;
int retval=0; int retval=0;
mutex_lock(&(rio->lock)); mutex_lock(&rio500_mutex);
/* Sanity check to make sure rio is connected, powered, etc */ /* Sanity check to make sure rio is connected, powered, etc */
if (rio->present == 0 || rio->rio_dev == NULL) { if (rio->present == 0 || rio->rio_dev == NULL) {
retval = -ENODEV; retval = -ENODEV;
@ -246,7 +253,7 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg)
err_out: err_out:
mutex_unlock(&(rio->lock)); mutex_unlock(&rio500_mutex);
return retval; return retval;
} }
@ -266,12 +273,12 @@ write_rio(struct file *file, const char __user *buffer,
int errn = 0; int errn = 0;
int intr; int intr;
intr = mutex_lock_interruptible(&(rio->lock)); intr = mutex_lock_interruptible(&rio500_mutex);
if (intr) if (intr)
return -EINTR; return -EINTR;
/* Sanity check to make sure rio is connected, powered, etc */ /* Sanity check to make sure rio is connected, powered, etc */
if (rio->present == 0 || rio->rio_dev == NULL) { if (rio->present == 0 || rio->rio_dev == NULL) {
mutex_unlock(&(rio->lock)); mutex_unlock(&rio500_mutex);
return -ENODEV; return -ENODEV;
} }
@ -294,7 +301,7 @@ write_rio(struct file *file, const char __user *buffer,
goto error; goto error;
} }
if (signal_pending(current)) { if (signal_pending(current)) {
mutex_unlock(&(rio->lock)); mutex_unlock(&rio500_mutex);
return bytes_written ? bytes_written : -EINTR; return bytes_written ? bytes_written : -EINTR;
} }
@ -332,12 +339,12 @@ write_rio(struct file *file, const char __user *buffer,
buffer += copy_size; buffer += copy_size;
} while (count > 0); } while (count > 0);
mutex_unlock(&(rio->lock)); mutex_unlock(&rio500_mutex);
return bytes_written ? bytes_written : -EIO; return bytes_written ? bytes_written : -EIO;
error: error:
mutex_unlock(&(rio->lock)); mutex_unlock(&rio500_mutex);
return errn; return errn;
} }
@ -354,12 +361,12 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
char *ibuf; char *ibuf;
int intr; int intr;
intr = mutex_lock_interruptible(&(rio->lock)); intr = mutex_lock_interruptible(&rio500_mutex);
if (intr) if (intr)
return -EINTR; return -EINTR;
/* Sanity check to make sure rio is connected, powered, etc */ /* Sanity check to make sure rio is connected, powered, etc */
if (rio->present == 0 || rio->rio_dev == NULL) { if (rio->present == 0 || rio->rio_dev == NULL) {
mutex_unlock(&(rio->lock)); mutex_unlock(&rio500_mutex);
return -ENODEV; return -ENODEV;
} }
@ -370,11 +377,11 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
while (count > 0) { while (count > 0) {
if (signal_pending(current)) { if (signal_pending(current)) {
mutex_unlock(&(rio->lock)); mutex_unlock(&rio500_mutex);
return read_count ? read_count : -EINTR; return read_count ? read_count : -EINTR;
} }
if (!rio->rio_dev) { if (!rio->rio_dev) {
mutex_unlock(&(rio->lock)); mutex_unlock(&rio500_mutex);
return -ENODEV; return -ENODEV;
} }
this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count; this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count;
@ -392,7 +399,7 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
count = this_read = partial; count = this_read = partial;
} else if (result == -ETIMEDOUT || result == 15) { /* FIXME: 15 ??? */ } else if (result == -ETIMEDOUT || result == 15) { /* FIXME: 15 ??? */
if (!maxretry--) { if (!maxretry--) {
mutex_unlock(&(rio->lock)); mutex_unlock(&rio500_mutex);
dev_err(&rio->rio_dev->dev, dev_err(&rio->rio_dev->dev,
"read_rio: maxretry timeout\n"); "read_rio: maxretry timeout\n");
return -ETIME; return -ETIME;
@ -402,19 +409,19 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
finish_wait(&rio->wait_q, &wait); finish_wait(&rio->wait_q, &wait);
continue; continue;
} else if (result != -EREMOTEIO) { } else if (result != -EREMOTEIO) {
mutex_unlock(&(rio->lock)); mutex_unlock(&rio500_mutex);
dev_err(&rio->rio_dev->dev, dev_err(&rio->rio_dev->dev,
"Read Whoops - result:%d partial:%u this_read:%u\n", "Read Whoops - result:%d partial:%u this_read:%u\n",
result, partial, this_read); result, partial, this_read);
return -EIO; return -EIO;
} else { } else {
mutex_unlock(&(rio->lock)); mutex_unlock(&rio500_mutex);
return (0); return (0);
} }
if (this_read) { if (this_read) {
if (copy_to_user(buffer, ibuf, this_read)) { if (copy_to_user(buffer, ibuf, this_read)) {
mutex_unlock(&(rio->lock)); mutex_unlock(&rio500_mutex);
return -EFAULT; return -EFAULT;
} }
count -= this_read; count -= this_read;
@ -422,7 +429,7 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
buffer += this_read; buffer += this_read;
} }
} }
mutex_unlock(&(rio->lock)); mutex_unlock(&rio500_mutex);
return read_count; return read_count;
} }
@ -447,15 +454,23 @@ static int probe_rio(struct usb_interface *intf,
{ {
struct usb_device *dev = interface_to_usbdev(intf); struct usb_device *dev = interface_to_usbdev(intf);
struct rio_usb_data *rio = &rio_instance; struct rio_usb_data *rio = &rio_instance;
int retval; int retval = 0;
dev_info(&intf->dev, "USB Rio found at address %d\n", dev->devnum); mutex_lock(&rio500_mutex);
if (rio->present) {
dev_info(&intf->dev, "Second USB Rio at address %d refused\n", dev->devnum);
retval = -EBUSY;
goto bail_out;
} else {
dev_info(&intf->dev, "USB Rio found at address %d\n", dev->devnum);
}
retval = usb_register_dev(intf, &usb_rio_class); retval = usb_register_dev(intf, &usb_rio_class);
if (retval) { if (retval) {
dev_err(&dev->dev, dev_err(&dev->dev,
"Not able to get a minor for this device.\n"); "Not able to get a minor for this device.\n");
return -ENOMEM; retval = -ENOMEM;
goto bail_out;
} }
rio->rio_dev = dev; rio->rio_dev = dev;
@ -464,7 +479,8 @@ static int probe_rio(struct usb_interface *intf,
dev_err(&dev->dev, dev_err(&dev->dev,
"probe_rio: Not enough memory for the output buffer\n"); "probe_rio: Not enough memory for the output buffer\n");
usb_deregister_dev(intf, &usb_rio_class); usb_deregister_dev(intf, &usb_rio_class);
return -ENOMEM; retval = -ENOMEM;
goto bail_out;
} }
dev_dbg(&intf->dev, "obuf address:%p\n", rio->obuf); dev_dbg(&intf->dev, "obuf address:%p\n", rio->obuf);
@ -473,16 +489,17 @@ static int probe_rio(struct usb_interface *intf,
"probe_rio: Not enough memory for the input buffer\n"); "probe_rio: Not enough memory for the input buffer\n");
usb_deregister_dev(intf, &usb_rio_class); usb_deregister_dev(intf, &usb_rio_class);
kfree(rio->obuf); kfree(rio->obuf);
return -ENOMEM; retval = -ENOMEM;
goto bail_out;
} }
dev_dbg(&intf->dev, "ibuf address:%p\n", rio->ibuf); dev_dbg(&intf->dev, "ibuf address:%p\n", rio->ibuf);
mutex_init(&(rio->lock));
usb_set_intfdata (intf, rio); usb_set_intfdata (intf, rio);
rio->present = 1; rio->present = 1;
bail_out:
mutex_unlock(&rio500_mutex);
return 0; return retval;
} }
static void disconnect_rio(struct usb_interface *intf) static void disconnect_rio(struct usb_interface *intf)
@ -494,12 +511,10 @@ static void disconnect_rio(struct usb_interface *intf)
if (rio) { if (rio) {
usb_deregister_dev(intf, &usb_rio_class); usb_deregister_dev(intf, &usb_rio_class);
mutex_lock(&(rio->lock));
if (rio->isopen) { if (rio->isopen) {
rio->isopen = 0; rio->isopen = 0;
/* better let it finish - the release will do whats needed */ /* better let it finish - the release will do whats needed */
rio->rio_dev = NULL; rio->rio_dev = NULL;
mutex_unlock(&(rio->lock));
mutex_unlock(&rio500_mutex); mutex_unlock(&rio500_mutex);
return; return;
} }
@ -509,7 +524,6 @@ static void disconnect_rio(struct usb_interface *intf)
dev_info(&intf->dev, "USB Rio disconnected.\n"); dev_info(&intf->dev, "USB Rio disconnected.\n");
rio->present = 0; rio->present = 0;
mutex_unlock(&(rio->lock));
} }
mutex_unlock(&rio500_mutex); mutex_unlock(&rio500_mutex);
} }

View File

@ -3029,6 +3029,13 @@ static int sisusb_probe(struct usb_interface *intf,
mutex_init(&(sisusb->lock)); mutex_init(&(sisusb->lock));
sisusb->sisusb_dev = dev;
sisusb->vrambase = SISUSB_PCI_MEMBASE;
sisusb->mmiobase = SISUSB_PCI_MMIOBASE;
sisusb->mmiosize = SISUSB_PCI_MMIOSIZE;
sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
/* Everything else is zero */
/* Register device */ /* Register device */
retval = usb_register_dev(intf, &usb_sisusb_class); retval = usb_register_dev(intf, &usb_sisusb_class);
if (retval) { if (retval) {
@ -3039,13 +3046,7 @@ static int sisusb_probe(struct usb_interface *intf,
goto error_1; goto error_1;
} }
sisusb->sisusb_dev = dev; sisusb->minor = intf->minor;
sisusb->minor = intf->minor;
sisusb->vrambase = SISUSB_PCI_MEMBASE;
sisusb->mmiobase = SISUSB_PCI_MMIOBASE;
sisusb->mmiosize = SISUSB_PCI_MMIOSIZE;
sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
/* Everything else is zero */
/* Allocate buffers */ /* Allocate buffers */
sisusb->ibufsize = SISUSB_IBUF_SIZE; sisusb->ibufsize = SISUSB_IBUF_SIZE;

View File

@ -528,8 +528,7 @@ void ssusb_dr_debugfs_init(struct ssusb_mtk *ssusb)
void ssusb_debugfs_create_root(struct ssusb_mtk *ssusb) void ssusb_debugfs_create_root(struct ssusb_mtk *ssusb)
{ {
ssusb->dbgfs_root = ssusb->dbgfs_root = debugfs_create_dir(dev_name(ssusb->dev), NULL);
debugfs_create_dir(dev_name(ssusb->dev), usb_debug_root);
} }
void ssusb_debugfs_remove_root(struct ssusb_mtk *ssusb) void ssusb_debugfs_remove_root(struct ssusb_mtk *ssusb)

View File

@ -301,9 +301,17 @@ static int stub_probe(struct usb_device *udev)
const char *udev_busid = dev_name(&udev->dev); const char *udev_busid = dev_name(&udev->dev);
struct bus_id_priv *busid_priv; struct bus_id_priv *busid_priv;
int rc = 0; int rc = 0;
char save_status;
dev_dbg(&udev->dev, "Enter probe\n"); dev_dbg(&udev->dev, "Enter probe\n");
/* Not sure if this is our device. Allocate here to avoid
* calling alloc while holding busid_table lock.
*/
sdev = stub_device_alloc(udev);
if (!sdev)
return -ENOMEM;
/* check we should claim or not by busid_table */ /* check we should claim or not by busid_table */
busid_priv = get_busid_priv(udev_busid); busid_priv = get_busid_priv(udev_busid);
if (!busid_priv || (busid_priv->status == STUB_BUSID_REMOV) || if (!busid_priv || (busid_priv->status == STUB_BUSID_REMOV) ||
@ -318,6 +326,9 @@ static int stub_probe(struct usb_device *udev)
* See driver_probe_device() in driver/base/dd.c * See driver_probe_device() in driver/base/dd.c
*/ */
rc = -ENODEV; rc = -ENODEV;
if (!busid_priv)
goto sdev_free;
goto call_put_busid_priv; goto call_put_busid_priv;
} }
@ -337,12 +348,6 @@ static int stub_probe(struct usb_device *udev)
goto call_put_busid_priv; goto call_put_busid_priv;
} }
/* ok, this is my device */
sdev = stub_device_alloc(udev);
if (!sdev) {
rc = -ENOMEM;
goto call_put_busid_priv;
}
dev_info(&udev->dev, dev_info(&udev->dev,
"usbip-host: register new device (bus %u dev %u)\n", "usbip-host: register new device (bus %u dev %u)\n",
@ -352,9 +357,16 @@ static int stub_probe(struct usb_device *udev)
/* set private data to usb_device */ /* set private data to usb_device */
dev_set_drvdata(&udev->dev, sdev); dev_set_drvdata(&udev->dev, sdev);
busid_priv->sdev = sdev; busid_priv->sdev = sdev;
busid_priv->udev = udev; busid_priv->udev = udev;
save_status = busid_priv->status;
busid_priv->status = STUB_BUSID_ALLOC;
/* release the busid_lock */
put_busid_priv(busid_priv);
/* /*
* Claim this hub port. * Claim this hub port.
* It doesn't matter what value we pass as owner * It doesn't matter what value we pass as owner
@ -372,10 +384,8 @@ static int stub_probe(struct usb_device *udev)
dev_err(&udev->dev, "stub_add_files for %s\n", udev_busid); dev_err(&udev->dev, "stub_add_files for %s\n", udev_busid);
goto err_files; goto err_files;
} }
busid_priv->status = STUB_BUSID_ALLOC;
rc = 0; return 0;
goto call_put_busid_priv;
err_files: err_files:
usb_hub_release_port(udev->parent, udev->portnum, usb_hub_release_port(udev->parent, udev->portnum,
@ -384,23 +394,30 @@ err_port:
dev_set_drvdata(&udev->dev, NULL); dev_set_drvdata(&udev->dev, NULL);
usb_put_dev(udev); usb_put_dev(udev);
/* we already have busid_priv, just lock busid_lock */
spin_lock(&busid_priv->busid_lock);
busid_priv->sdev = NULL; busid_priv->sdev = NULL;
stub_device_free(sdev); busid_priv->status = save_status;
spin_unlock(&busid_priv->busid_lock);
/* lock is released - go to free */
goto sdev_free;
call_put_busid_priv: call_put_busid_priv:
/* release the busid_lock */
put_busid_priv(busid_priv); put_busid_priv(busid_priv);
sdev_free:
stub_device_free(sdev);
return rc; return rc;
} }
static void shutdown_busid(struct bus_id_priv *busid_priv) static void shutdown_busid(struct bus_id_priv *busid_priv)
{ {
if (busid_priv->sdev && !busid_priv->shutdown_busid) { usbip_event_add(&busid_priv->sdev->ud, SDEV_EVENT_REMOVED);
busid_priv->shutdown_busid = 1;
usbip_event_add(&busid_priv->sdev->ud, SDEV_EVENT_REMOVED);
/* wait for the stop of the event handler */ /* wait for the stop of the event handler */
usbip_stop_eh(&busid_priv->sdev->ud); usbip_stop_eh(&busid_priv->sdev->ud);
}
} }
/* /*
@ -427,11 +444,16 @@ static void stub_disconnect(struct usb_device *udev)
/* get stub_device */ /* get stub_device */
if (!sdev) { if (!sdev) {
dev_err(&udev->dev, "could not get device"); dev_err(&udev->dev, "could not get device");
goto call_put_busid_priv; /* release busid_lock */
put_busid_priv(busid_priv);
return;
} }
dev_set_drvdata(&udev->dev, NULL); dev_set_drvdata(&udev->dev, NULL);
/* release busid_lock before call to remove device files */
put_busid_priv(busid_priv);
/* /*
* NOTE: rx/tx threads are invoked for each usb_device. * NOTE: rx/tx threads are invoked for each usb_device.
*/ */
@ -442,27 +464,36 @@ static void stub_disconnect(struct usb_device *udev)
(struct usb_dev_state *) udev); (struct usb_dev_state *) udev);
if (rc) { if (rc) {
dev_dbg(&udev->dev, "unable to release port\n"); dev_dbg(&udev->dev, "unable to release port\n");
goto call_put_busid_priv; return;
} }
/* If usb reset is called from event handler */ /* If usb reset is called from event handler */
if (usbip_in_eh(current)) if (usbip_in_eh(current))
goto call_put_busid_priv; return;
/* we already have busid_priv, just lock busid_lock */
spin_lock(&busid_priv->busid_lock);
if (!busid_priv->shutdown_busid)
busid_priv->shutdown_busid = 1;
/* release busid_lock */
spin_unlock(&busid_priv->busid_lock);
/* shutdown the current connection */ /* shutdown the current connection */
shutdown_busid(busid_priv); shutdown_busid(busid_priv);
usb_put_dev(sdev->udev); usb_put_dev(sdev->udev);
/* we already have busid_priv, just lock busid_lock */
spin_lock(&busid_priv->busid_lock);
/* free sdev */ /* free sdev */
busid_priv->sdev = NULL; busid_priv->sdev = NULL;
stub_device_free(sdev); stub_device_free(sdev);
if (busid_priv->status == STUB_BUSID_ALLOC) if (busid_priv->status == STUB_BUSID_ALLOC)
busid_priv->status = STUB_BUSID_ADDED; busid_priv->status = STUB_BUSID_ADDED;
/* release busid_lock */
call_put_busid_priv: spin_unlock(&busid_priv->busid_lock);
put_busid_priv(busid_priv); return;
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM