Skip to content

Commit

Permalink
Merge tag 'usb-5.2-rc3' of git://git.kernel.org/pub/scm/linux/kernel/…
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
torvalds committed May 31, 2019
2 parents ca19180 + 3ea3091 commit e49c854
Show file tree
Hide file tree
Showing 12 changed files with 182 additions and 153 deletions.
66 changes: 13 additions & 53 deletions Documentation/usb/rio.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
====

Expand Down
33 changes: 20 additions & 13 deletions drivers/media/usb/siano/smsusb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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) {
Expand All @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions drivers/usb/core/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions drivers/usb/core/quirks.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 },

Expand Down
3 changes: 3 additions & 0 deletions drivers/usb/host/xhci-debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
26 changes: 19 additions & 7 deletions drivers/usb/host/xhci-ring.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand All @@ -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);
}
Expand Down
24 changes: 11 additions & 13 deletions drivers/usb/host/xhci.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
*/

#include <linux/pci.h>
#include <linux/iopoll.h>
#include <linux/irq.h>
#include <linux/log2.h>
#include <linux/module.h>
Expand Down Expand Up @@ -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
Expand All @@ -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;
}

/*
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion drivers/usb/host/xhci.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading

0 comments on commit e49c854

Please sign in to comment.