Commit e49c8547 authored by Linus Torvalds's avatar Linus Torvalds

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
parents ca191804 3ea3091f
......@@ -76,70 +76,30 @@ Additional Information and userspace tools
Requirements
============
A host with a USB port. Ideally, either a UHCI (Intel) or OHCI
(Compaq and others) hardware port should work.
A host with a USB port running a Linux kernel with RIO 500 support enabled.
A Linux development kernel (2.3.x) with USB support enabled or a
backported version to linux-2.2.x. See http://www.linux-usb.org for
more information on accomplishing this.
The driver is a module called rio500, which should be automatically loaded
as you plug in your device. If that fails you can manually load it with
A Linux kernel with RIO 500 support enabled.
modprobe rio500
'lspci' which is only needed to determine the type of USB hardware
available in your machine.
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::
Udev should automatically create a device node as soon as plug in your device.
If that fails, you can manually add a device for the USB rio500::
mknod /dev/usb/rio500 c 180 64
Set appropriate permissions for /dev/usb/rio500 (don't forget about
group and world permissions). Both read and write permissions are
In that case, set appropriate permissions for /dev/usb/rio500 (don't forget
about group and world permissions). Both read and write permissions are
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
be able to access the rio500.
Limits
======
You can use only a single rio500 device at a time with your computer.
Bugs
====
......
......@@ -389,6 +389,7 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
struct smsusb_device_t *dev;
void *mdev;
int i, rc;
int align = 0;
/* create device object */
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->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;
switch (params.device_type) {
......@@ -414,24 +433,12 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
/* fall-thru */
default:
dev->buffer_size = USB2_BUFFER_SIZE;
dev->response_alignment =
le16_to_cpu(dev->udev->ep_in[1]->desc.wMaxPacketSize) -
sizeof(struct sms_msg_hdr);
dev->response_alignment = align;
params.flags |= SMS_DEVICE_FAMILY2;
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.usb_device = dev->udev;
params.buffer_size = dev->buffer_size;
......
......@@ -932,8 +932,8 @@ int usb_get_bos_descriptor(struct usb_device *dev)
/* Get BOS descriptor */
ret = usb_get_descriptor(dev, USB_DT_BOS, 0, bos, USB_DT_BOS_SIZE);
if (ret < USB_DT_BOS_SIZE) {
dev_err(ddev, "unable to get BOS descriptor\n");
if (ret < USB_DT_BOS_SIZE || bos->bLength < USB_DT_BOS_SIZE) {
dev_err(ddev, "unable to get BOS descriptor or descriptor too short\n");
if (ret >= 0)
ret = -ENOMSG;
kfree(bos);
......
......@@ -209,6 +209,9 @@ static const struct usb_device_id usb_quirk_list[] = {
/* Microsoft LifeCam-VX700 v2.0 */
{ 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) */
{ USB_DEVICE(0x046a, 0x0023), .driver_info = USB_QUIRK_RESET_RESUME },
......
......@@ -440,6 +440,9 @@ void xhci_debugfs_create_endpoint(struct xhci_hcd *xhci,
struct xhci_ep_priv *epriv;
struct xhci_slot_priv *spriv = dev->debugfs_private;
if (!spriv)
return;
if (spriv->eps[ep_index])
return;
......
......@@ -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 xhci_segment *seg = td->bounce_seg;
struct urb *urb = td->urb;
size_t len;
if (!ring || !seg || !urb)
return;
......@@ -666,11 +667,14 @@ static void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci,
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_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_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 max_pkt;
u32 new_buff_len;
size_t len;
max_pkt = usb_endpoint_maxp(&urb->ep->desc);
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 */
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);
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,
max_pkt, DMA_TO_DEVICE);
} else {
......@@ -3423,11 +3432,14 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
if (urb->transfer_buffer_length > 0) {
u32 length_field, remainder;
u64 addr;
if (xhci_urb_suitable_for_idt(urb)) {
memcpy(&urb->transfer_dma, urb->transfer_buffer,
memcpy(&addr, urb->transfer_buffer,
urb->transfer_buffer_length);
field |= TRB_IDT;
} else {
addr = (u64) urb->transfer_dma;
}
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)
field |= TRB_DIR_IN;
queue_trb(xhci, ep_ring, true,
lower_32_bits(urb->transfer_dma),
upper_32_bits(urb->transfer_dma),
lower_32_bits(addr),
upper_32_bits(addr),
length_field,
field | ep_ring->cycle_state);
}
......
......@@ -9,6 +9,7 @@
*/
#include <linux/pci.h>
#include <linux/iopoll.h>
#include <linux/irq.h>
#include <linux/log2.h>
#include <linux/module.h>
......@@ -52,7 +53,6 @@ static bool td_on_ring(struct xhci_td *td, struct xhci_ring *ring)
return false;
}
/* TODO: copied from ehci-hcd.c - can this be refactored? */
/*
* xhci_handshake - spin reading hc until handshake completes or fails
* @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)
{
u32 result;
int ret;
do {
result = readl(ptr);
if (result == ~(u32)0) /* card removed */
return -ENODEV;
result &= mask;
if (result == done)
return 0;
udelay(1);
usec--;
} while (usec > 0);
return -ETIMEDOUT;
ret = readl_poll_timeout_atomic(ptr, result,
(result & mask) == done ||
result == U32_MAX,
1, usec);
if (result == U32_MAX) /* card removed */
return -ENODEV;
return ret;
}
/*
......@@ -4320,7 +4318,6 @@ static int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
pm_addr = ports[port_num]->addr + PORTPMSC;
pm_val = readl(pm_addr);
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",
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
* systems. See XHCI_DEFAULT_BESL definition in xhci.h
*/
field = le32_to_cpu(udev->bos->ext_cap->bmAttributes);
if ((field & USB_BESL_SUPPORT) &&
(field & USB_BESL_BASELINE_VALID))
hird = USB_GET_BESL_BASELINE(field);
......
......@@ -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) &&
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 false;
......
......@@ -51,7 +51,6 @@ struct rio_usb_data {
char *obuf, *ibuf; /* transfer buffers */
char bulk_in_ep, bulk_out_ep; /* Endpoint assignments */
wait_queue_head_t wait_q; /* for timeouts */
struct mutex lock; /* general race avoidance */
};
static DEFINE_MUTEX(rio500_mutex);
......@@ -63,10 +62,8 @@ static int open_rio(struct inode *inode, struct file *file)
/* against disconnect() */
mutex_lock(&rio500_mutex);
mutex_lock(&(rio->lock));
if (rio->isopen || !rio->present) {
mutex_unlock(&(rio->lock));
mutex_unlock(&rio500_mutex);
return -EBUSY;
}
......@@ -74,7 +71,6 @@ static int open_rio(struct inode *inode, struct file *file)
init_waitqueue_head(&rio->wait_q);
mutex_unlock(&(rio->lock));
dev_info(&rio->rio_dev->dev, "Rio opened.\n");
mutex_unlock(&rio500_mutex);
......@@ -86,9 +82,20 @@ static int close_rio(struct inode *inode, struct file *file)
{
struct rio_usb_data *rio = &rio_instance;
rio->isopen = 0;
/* against disconnect() */
mutex_lock(&rio500_mutex);
dev_info(&rio->rio_dev->dev, "Rio closed.\n");
rio->isopen = 0;
if (!rio->present) {
/* cleanup has been delayed */
kfree(rio->ibuf);
kfree(rio->obuf);
rio->ibuf = NULL;
rio->obuf = NULL;
} else {
dev_info(&rio->rio_dev->dev, "Rio closed.\n");
}
mutex_unlock(&rio500_mutex);
return 0;
}
......@@ -102,7 +109,7 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg)
int retries;
int retval=0;
mutex_lock(&(rio->lock));
mutex_lock(&rio500_mutex);
/* Sanity check to make sure rio is connected, powered, etc */
if (rio->present == 0 || rio->rio_dev == NULL) {
retval = -ENODEV;
......@@ -246,7 +253,7 @@ static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg)
err_out:
mutex_unlock(&(rio->lock));
mutex_unlock(&rio500_mutex);
return retval;
}
......@@ -266,12 +273,12 @@ write_rio(struct file *file, const char __user *buffer,
int errn = 0;
int intr;
intr = mutex_lock_interruptible(&(rio->lock));
intr = mutex_lock_interruptible(&rio500_mutex);
if (intr)
return -EINTR;
/* Sanity check to make sure rio is connected, powered, etc */
if (rio->present == 0 || rio->rio_dev == NULL) {
mutex_unlock(&(rio->lock));
mutex_unlock(&rio500_mutex);
return -ENODEV;
}
......@@ -294,7 +301,7 @@ write_rio(struct file *file, const char __user *buffer,
goto error;
}
if (signal_pending(current)) {
mutex_unlock(&(rio->lock));
mutex_unlock(&rio500_mutex);
return bytes_written ? bytes_written : -EINTR;
}
......@@ -332,12 +339,12 @@ write_rio(struct file *file, const char __user *buffer,
buffer += copy_size;
} while (count > 0);
mutex_unlock(&(rio->lock));
mutex_unlock(&rio500_mutex);
return bytes_written ? bytes_written : -EIO;
error:
mutex_unlock(&(rio->lock));
mutex_unlock(&rio500_mutex);
return errn;
}
......@@ -354,12 +361,12 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
char *ibuf;
int intr;
intr = mutex_lock_interruptible(&(rio->lock));
intr = mutex_lock_interruptible(&rio500_mutex);
if (intr)
return -EINTR;
/* Sanity check to make sure rio is connected, powered, etc */
if (rio->present == 0 || rio->rio_dev == NULL) {
mutex_unlock(&(rio->lock));
mutex_unlock(&rio500_mutex);
return -ENODEV;
}
......@@ -370,11 +377,11 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
while (count > 0) {
if (signal_pending(current)) {
mutex_unlock(&(rio->lock));
mutex_unlock(&rio500_mutex);
return read_count ? read_count : -EINTR;
}
if (!rio->rio_dev) {
mutex_unlock(&(rio->lock));
mutex_unlock(&rio500_mutex);
return -ENODEV;
}
this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count;
......@@ -392,7 +399,7 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
count = this_read = partial;
} else if (result == -ETIMEDOUT || result == 15) { /* FIXME: 15 ??? */
if (!maxretry--) {
mutex_unlock(&(rio->lock));
mutex_unlock(&rio500_mutex);
dev_err(&rio->rio_dev->dev,
"read_rio: maxretry timeout\n");
return -ETIME;
......@@ -402,19 +409,19 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
finish_wait(&rio->wait_q, &wait);
continue;
} else if (result != -EREMOTEIO) {
mutex_unlock(&(rio->lock));
mutex_unlock(&rio500_mutex);
dev_err(&rio->rio_dev->dev,
"Read Whoops - result:%d partial:%u this_read:%u\n",
result, partial, this_read);
return -EIO;
} else {
mutex_unlock(&(rio->lock));
mutex_unlock(&rio500_mutex);
return (0);
}
if (this_read) {
if (copy_to_user(buffer, ibuf, this_read)) {
mutex_unlock(&(rio->lock));
mutex_unlock(&rio500_mutex);
return -EFAULT;
}
count -= this_read;
......@@ -422,7 +429,7 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
buffer += this_read;
}
}
mutex_unlock(&(rio->lock));
mutex_unlock(&rio500_mutex);
return read_count;
}
......@@ -447,15 +454,23 @@ static int probe_rio(struct usb_interface *intf,
{
struct usb_device *dev = interface_to_usbdev(intf);
struct rio_usb_data *rio = &rio_instance;
int retval;
int retval = 0;
dev_info(&intf->dev, "USB Rio found at address %d\n", dev->devnum);
mutex_lock(&rio500_mutex);
if (rio->present) {
dev_info(&intf->dev, "Second USB Rio at address %d refused\n", dev->devnum);
retval = -EBUSY;
goto bail_out;
} else {
dev_info(&intf->dev, "USB Rio found at address %d\n", dev->devnum);
}
retval = usb_register_dev(intf, &usb_rio_class);
if (retval) {
dev_err(&dev->dev,
"Not able to get a minor for this device.\n");
return -ENOMEM;
retval = -ENOMEM;
goto bail_out;
}
rio->rio_dev = dev;
......@@ -464,7 +479,8 @@ static int probe_rio(struct usb_interface *intf,
dev_err(&dev->dev,
"probe_rio: Not enough memory for the output buffer\n");
usb_deregister_dev(intf, &usb_rio_class);
return -ENOMEM;
retval = -ENOMEM;
goto bail_out;
}
dev_dbg(&intf->dev, "obuf address:%p\n", rio->obuf);
......@@ -473,16 +489,17 @@ static int probe_rio(struct usb_interface *intf,
"probe_rio: Not enough memory for the input buffer\n");
usb_deregister_dev(intf, &usb_rio_class);
kfree(rio->obuf);
return -ENOMEM;
retval = -ENOMEM;
goto bail_out;
}
dev_dbg(&intf->dev, "ibuf address:%p\n", rio->ibuf);
mutex_init(&(rio->lock));
usb_set_intfdata (intf, rio);
rio->present = 1;
bail_out:
mutex_unlock(&rio500_mutex);
return 0;
return retval;
}
static void disconnect_rio(struct usb_interface *intf)
......@@ -494,12 +511,10 @@ static void disconnect_rio(struct usb_interface *intf)
if (rio) {
usb_deregister_dev(intf, &usb_rio_class);
mutex_lock(&(rio->lock));
if (rio->isopen) {
rio->isopen = 0;
/* better let it finish - the release will do whats needed */
rio->rio_dev = NULL;
mutex_unlock(&(rio->lock));
mutex_unlock(&rio500_mutex);
return;
}
......@@ -509,7 +524,6 @@ static void disconnect_rio(struct usb_interface *intf)
dev_info(&intf->dev, "USB Rio disconnected.\n");
rio->present = 0;
mutex_unlock(&(rio->lock));
}
mutex_unlock(&rio500_mutex);
}
......
......@@ -3029,6 +3029,13 @@ static int sisusb_probe(struct usb_interface *intf,
mutex_init(&(sisusb->lock));
sisusb->sisusb_dev = dev;
sisusb->vrambase = SISUSB_PCI_MEMBASE;
sisusb->mmiobase = SISUSB_PCI_MMIOBASE;
sisusb->mmiosize = SISUSB_PCI_MMIOSIZE;
sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
/* Everything else is zero */
/* Register device */
retval = usb_register_dev(intf, &usb_sisusb_class);
if (retval) {
......@@ -3039,13 +3046,7 @@ static int sisusb_probe(struct usb_interface *intf,
goto error_1;
}
sisusb->sisusb_dev = dev;
sisusb->minor = intf->minor;
sisusb->vrambase = SISUSB_PCI_MEMBASE;
sisusb->mmiobase = SISUSB_PCI_MMIOBASE;
sisusb->mmiosize = SISUSB_PCI_MMIOSIZE;
sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
/* Everything else is zero */
sisusb->minor = intf->minor;
/* Allocate buffers */
sisusb->ibufsize = SISUSB_IBUF_SIZE;
......
......@@ -528,8 +528,7 @@ void ssusb_dr_debugfs_init(struct ssusb_mtk *ssusb)
void ssusb_debugfs_create_root(struct ssusb_mtk *ssusb)
{
ssusb->dbgfs_root =
debugfs_create_dir(dev_name(ssusb->dev), usb_debug_root);
ssusb->dbgfs_root = debugfs_create_dir(dev_name(ssusb->dev), NULL);
}
void ssusb_debugfs_remove_root(struct ssusb_mtk *ssusb)
......
......@@ -301,9 +301,17 @@ static int stub_probe(struct usb_device *udev)
const char *udev_busid = dev_name(&udev->dev);
struct bus_id_priv *busid_priv;
int rc = 0;
char save_status;
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 */
busid_priv = get_busid_priv(udev_busid);
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
*/
rc = -ENODEV;
if (!busid_priv)
goto sdev_free;
goto call_put_busid_priv;
}
......@@ -337,12 +348,6 @@ static int stub_probe(struct usb_device *udev)
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,
"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 */
dev_set_drvdata(&udev->dev, sdev);
busid_priv->sdev = sdev;
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.
* 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);
goto err_files;
}
busid_priv->status = STUB_BUSID_ALLOC;
rc = 0;
goto call_put_busid_priv;
return 0;
err_files:
usb_hub_release_port(udev->parent, udev->portnum,
......@@ -384,23 +394,30 @@ static int stub_probe(struct usb_device *udev)
dev_set_drvdata(&udev->dev, NULL);
usb_put_dev(udev);
/* we already have busid_priv, just lock busid_lock */
spin_lock(&busid_priv->busid_lock);
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:
/* release the busid_lock */
put_busid_priv(busid_priv);
sdev_free:
stub_device_free(sdev);
return rc;
}
static void shutdown_busid(struct bus_id_priv *busid_priv)
{
if (busid_priv->sdev && !busid_priv->shutdown_busid) {
busid_priv->shutdown_busid = 1;
usbip_event_add(&busid_priv->sdev->ud, SDEV_EVENT_REMOVED);
usbip_event_add(&busid_priv->sdev->ud, SDEV_EVENT_REMOVED);
/* wait for the stop of the event handler */
usbip_stop_eh(&busid_priv->sdev->ud);
}
/* wait for the stop of the event handler */
usbip_stop_eh(&busid_priv->sdev->ud);
}
/*
......@@ -427,11 +444,16 @@ static void stub_disconnect(struct usb_device *udev)
/* get stub_device */
if (!sdev) {
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);
/* release busid_lock before call to remove device files */
put_busid_priv(busid_priv);
/*
* 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);
if (rc) {
dev_dbg(&udev->dev, "unable to release port\n");
goto call_put_busid_priv;
return;
}
/* If usb reset is called from event handler */
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_busid(busid_priv);
usb_put_dev(sdev->udev);
/* we already have busid_priv, just lock busid_lock */
spin_lock(&busid_priv->busid_lock);
/* free sdev */
busid_priv->sdev = NULL;
stub_device_free(sdev);
if (busid_priv->status == STUB_BUSID_ALLOC)
busid_priv->status = STUB_BUSID_ADDED;
call_put_busid_priv:
put_busid_priv(busid_priv);
/* release busid_lock */
spin_unlock(&busid_priv->busid_lock);
return;
}
#ifdef CONFIG_PM
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment