mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 05:02:12 +00:00
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
This commit is contained in:
commit
e49c8547fb
@ -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 @@ err_port:
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user