Skip to content

Commit

Permalink
Merge tag 'usb-3.14-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 is a bunch of USB fixes for 3.14-rc3.  Most of these are xhci
  reverts, fixing a bunch of reported issues with USB 3 host controller
  issues that loads of people have been hitting (with the exception of
  kernel developers, all of our machines seem to be working fine, which
  is why these took so long to get resolved...)

  There are some other minor fixes and new device ids, as ususal.  All
  have been in linux-next successfully"

* tag 'usb-3.14-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (22 commits)
  usb: option: blacklist ZTE MF667 net interface
  Revert "usb: xhci: Link TRB must not occur within a USB payload burst"
  Revert "xhci: Avoid infinite loop when sg urb requires too many trbs"
  Revert "xhci: Set scatter-gather limit to avoid failed block writes."
  xhci 1.0: Limit arbitrarily-aligned scatter gather.
  Modpost: fixed USB alias generation for ranges including 0x9 and 0xA
  usb: core: Fix potential memory leak adding dyn USBdevice IDs
  USB: ftdi_sio: add Tagsys RFID Reader IDs
  usb: qcserial: add Netgear Aircard 340U
  usb-storage: enable multi-LUN scanning when needed
  USB: simple: add Dynastream ANT USB-m Stick device support
  usb-storage: add unusual-devs entry for BlackBerry 9000
  usb-storage: restrict bcdDevice range for Super Top in Cypress ATACB
  usb: phy: move some error messages to debug
  usb: ftdi_sio: add Mindstorms EV3 console adapter
  usb: dwc2: fix memory corruption in dwc2 driver
  usb: dwc2: fix role switch breakage
  usb: dwc2: bail out early when booting with "nousb"
  Revert "xhci: replace xhci_read_64() with readq()"
  Revert "xhci: replace xhci_write_64() with writeq()"
  ...
  • Loading branch information
Linus Torvalds committed Feb 15, 2014
2 parents 40a215f + 3635c7e commit ca03339
Show file tree
Hide file tree
Showing 25 changed files with 138 additions and 135 deletions.
24 changes: 17 additions & 7 deletions drivers/usb/core/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,10 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,
dynid->id.idProduct = idProduct;
dynid->id.match_flags = USB_DEVICE_ID_MATCH_DEVICE;
if (fields > 2 && bInterfaceClass) {
if (bInterfaceClass > 255)
return -EINVAL;
if (bInterfaceClass > 255) {
retval = -EINVAL;
goto fail;
}

dynid->id.bInterfaceClass = (u8)bInterfaceClass;
dynid->id.match_flags |= USB_DEVICE_ID_MATCH_INT_CLASS;
Expand All @@ -73,17 +75,21 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,
if (fields > 4) {
const struct usb_device_id *id = id_table;

if (!id)
return -ENODEV;
if (!id) {
retval = -ENODEV;
goto fail;
}

for (; id->match_flags; id++)
if (id->idVendor == refVendor && id->idProduct == refProduct)
break;

if (id->match_flags)
if (id->match_flags) {
dynid->id.driver_info = id->driver_info;
else
return -ENODEV;
} else {
retval = -ENODEV;
goto fail;
}
}

spin_lock(&dynids->lock);
Expand All @@ -95,6 +101,10 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,
if (retval)
return retval;
return count;

fail:
kfree(dynid);
return retval;
}
EXPORT_SYMBOL_GPL(usb_store_new_id);

Expand Down
1 change: 0 additions & 1 deletion drivers/usb/core/hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1032,7 +1032,6 @@ static int register_root_hub(struct usb_hcd *hcd)
dev_name(&usb_dev->dev), retval);
return retval;
}
usb_dev->lpm_capable = usb_device_supports_lpm(usb_dev);
}

retval = usb_new_device (usb_dev);
Expand Down
7 changes: 1 addition & 6 deletions drivers/usb/core/hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev)
return usb_get_intfdata(hdev->actconfig->interface[0]);
}

int usb_device_supports_lpm(struct usb_device *udev)
static int usb_device_supports_lpm(struct usb_device *udev)
{
/* USB 2.1 (and greater) devices indicate LPM support through
* their USB 2.0 Extended Capabilities BOS descriptor.
Expand All @@ -149,11 +149,6 @@ int usb_device_supports_lpm(struct usb_device *udev)
"Power management will be impacted.\n");
return 0;
}

/* udev is root hub */
if (!udev->parent)
return 1;

if (udev->parent->lpm_capable)
return 1;

Expand Down
1 change: 0 additions & 1 deletion drivers/usb/core/usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ extern int usb_get_device_descriptor(struct usb_device *dev,
unsigned int size);
extern int usb_get_bos_descriptor(struct usb_device *dev);
extern void usb_release_bos_descriptor(struct usb_device *dev);
extern int usb_device_supports_lpm(struct usb_device *udev);
extern char *usb_cache_string(struct usb_device *udev, int index);
extern int usb_set_configuration(struct usb_device *dev, int configuration);
extern int usb_choose_configuration(struct usb_device *udev);
Expand Down
2 changes: 1 addition & 1 deletion drivers/usb/dwc2/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
int retval = 0;

if (!select_phy)
return -ENODEV;
return 0;

usbcfg = readl(hsotg->regs + GUSBCFG);

Expand Down
11 changes: 0 additions & 11 deletions drivers/usb/dwc2/hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -2565,25 +2565,14 @@ static void _dwc2_hcd_endpoint_reset(struct usb_hcd *hcd,
struct usb_host_endpoint *ep)
{
struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
int is_control = usb_endpoint_xfer_control(&ep->desc);
int is_out = usb_endpoint_dir_out(&ep->desc);
int epnum = usb_endpoint_num(&ep->desc);
struct usb_device *udev;
unsigned long flags;

dev_dbg(hsotg->dev,
"DWC OTG HCD EP RESET: bEndpointAddress=0x%02x\n",
ep->desc.bEndpointAddress);

udev = to_usb_device(hsotg->dev);

spin_lock_irqsave(&hsotg->lock, flags);

usb_settoggle(udev, epnum, is_out, 0);
if (is_control)
usb_settoggle(udev, epnum, !is_out, 0);
dwc2_hcd_endpoint_reset(hsotg, ep);

spin_unlock_irqrestore(&hsotg->lock, flags);
}

Expand Down
3 changes: 3 additions & 0 deletions drivers/usb/dwc2/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ static int dwc2_driver_probe(struct platform_device *dev)
int retval;
int irq;

if (usb_disabled())
return -ENODEV;

match = of_match_device(dwc2_of_match_table, &dev->dev);
if (match && match->data) {
params = match->data;
Expand Down
6 changes: 3 additions & 3 deletions drivers/usb/host/xhci-dbg.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,12 +203,12 @@ void xhci_print_ir_set(struct xhci_hcd *xhci, int set_num)
addr, (unsigned int)temp);

addr = &ir_set->erst_base;
temp_64 = readq(addr);
temp_64 = xhci_read_64(xhci, addr);
xhci_dbg(xhci, " %p: ir_set.erst_base = @%08llx\n",
addr, temp_64);

addr = &ir_set->erst_dequeue;
temp_64 = readq(addr);
temp_64 = xhci_read_64(xhci, addr);
xhci_dbg(xhci, " %p: ir_set.erst_dequeue = @%08llx\n",
addr, temp_64);
}
Expand Down Expand Up @@ -412,7 +412,7 @@ void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci)
{
u64 val;

val = readq(&xhci->op_regs->cmd_ring);
val = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
xhci_dbg(xhci, "// xHC command ring deq ptr low bits + flags = @%08x\n",
lower_32_bits(val));
xhci_dbg(xhci, "// xHC command ring deq ptr high bits = @%08x\n",
Expand Down
14 changes: 7 additions & 7 deletions drivers/usb/host/xhci-mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -1958,7 +1958,7 @@ static void xhci_set_hc_event_deq(struct xhci_hcd *xhci)
xhci_warn(xhci, "WARN something wrong with SW event ring "
"dequeue ptr.\n");
/* Update HC event ring dequeue pointer */
temp = readq(&xhci->ir_set->erst_dequeue);
temp = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
temp &= ERST_PTR_MASK;
/* Don't clear the EHB bit (which is RW1C) because
* there might be more events to service.
Expand All @@ -1967,7 +1967,7 @@ static void xhci_set_hc_event_deq(struct xhci_hcd *xhci)
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"// Write event ring dequeue pointer, "
"preserving EHB bit");
writeq(((u64) deq & (u64) ~ERST_PTR_MASK) | temp,
xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp,
&xhci->ir_set->erst_dequeue);
}

Expand Down Expand Up @@ -2269,7 +2269,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"// Device context base array address = 0x%llx (DMA), %p (virt)",
(unsigned long long)xhci->dcbaa->dma, xhci->dcbaa);
writeq(dma, &xhci->op_regs->dcbaa_ptr);
xhci_write_64(xhci, dma, &xhci->op_regs->dcbaa_ptr);

/*
* Initialize the ring segment pool. The ring must be a contiguous
Expand Down Expand Up @@ -2312,13 +2312,13 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
(unsigned long long)xhci->cmd_ring->first_seg->dma);

/* Set the address in the Command Ring Control register */
val_64 = readq(&xhci->op_regs->cmd_ring);
val_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) |
(xhci->cmd_ring->first_seg->dma & (u64) ~CMD_RING_RSVD_BITS) |
xhci->cmd_ring->cycle_state;
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"// Setting command ring address to 0x%x", val);
writeq(val_64, &xhci->op_regs->cmd_ring);
xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring);
xhci_dbg_cmd_ptrs(xhci);

xhci->lpm_command = xhci_alloc_command(xhci, true, true, flags);
Expand Down Expand Up @@ -2396,10 +2396,10 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"// Set ERST base address for ir_set 0 = 0x%llx",
(unsigned long long)xhci->erst.erst_dma_addr);
val_64 = readq(&xhci->ir_set->erst_base);
val_64 = xhci_read_64(xhci, &xhci->ir_set->erst_base);
val_64 &= ERST_PTR_MASK;
val_64 |= (xhci->erst.erst_dma_addr & (u64) ~ERST_PTR_MASK);
writeq(val_64, &xhci->ir_set->erst_base);
xhci_write_64(xhci, val_64, &xhci->ir_set->erst_base);

/* Set the event ring dequeue address */
xhci_set_hc_event_deq(xhci);
Expand Down
5 changes: 5 additions & 0 deletions drivers/usb/host/xhci-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,11 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
"QUIRK: Resetting on resume");
xhci->quirks |= XHCI_TRUST_TX_LENGTH;
}
if (pdev->vendor == PCI_VENDOR_ID_RENESAS &&
pdev->device == 0x0015 &&
pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG &&
pdev->subsystem_device == 0xc0cd)
xhci->quirks |= XHCI_RESET_ON_RESUME;
if (pdev->vendor == PCI_VENDOR_ID_VIA)
xhci->quirks |= XHCI_RESET_ON_RESUME;
}
Expand Down
68 changes: 10 additions & 58 deletions drivers/usb/host/xhci-ring.c
Original file line number Diff line number Diff line change
Expand Up @@ -307,13 +307,14 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)
return 0;
}

temp_64 = readq(&xhci->op_regs->cmd_ring);
temp_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
if (!(temp_64 & CMD_RING_RUNNING)) {
xhci_dbg(xhci, "Command ring had been stopped\n");
return 0;
}
xhci->cmd_ring_state = CMD_RING_STATE_ABORTED;
writeq(temp_64 | CMD_RING_ABORT, &xhci->op_regs->cmd_ring);
xhci_write_64(xhci, temp_64 | CMD_RING_ABORT,
&xhci->op_regs->cmd_ring);

/* Section 4.6.1.2 of xHCI 1.0 spec says software should
* time the completion od all xHCI commands, including
Expand Down Expand Up @@ -2864,8 +2865,9 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
/* Clear the event handler busy flag (RW1C);
* the event ring should be empty.
*/
temp_64 = readq(&xhci->ir_set->erst_dequeue);
writeq(temp_64 | ERST_EHB, &xhci->ir_set->erst_dequeue);
temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
xhci_write_64(xhci, temp_64 | ERST_EHB,
&xhci->ir_set->erst_dequeue);
spin_unlock(&xhci->lock);

return IRQ_HANDLED;
Expand All @@ -2877,7 +2879,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
*/
while (xhci_handle_event(xhci) > 0) {}

temp_64 = readq(&xhci->ir_set->erst_dequeue);
temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
/* If necessary, update the HW's version of the event ring deq ptr. */
if (event_ring_deq != xhci->event_ring->dequeue) {
deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg,
Expand All @@ -2892,7 +2894,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)

/* Clear the event handler busy flag (RW1C); event ring is empty. */
temp_64 |= ERST_EHB;
writeq(temp_64, &xhci->ir_set->erst_dequeue);
xhci_write_64(xhci, temp_64, &xhci->ir_set->erst_dequeue);

spin_unlock(&xhci->lock);

Expand Down Expand Up @@ -2965,58 +2967,8 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
}

while (1) {
if (room_on_ring(xhci, ep_ring, num_trbs)) {
union xhci_trb *trb = ep_ring->enqueue;
unsigned int usable = ep_ring->enq_seg->trbs +
TRBS_PER_SEGMENT - 1 - trb;
u32 nop_cmd;

/*
* Section 4.11.7.1 TD Fragments states that a link
* TRB must only occur at the boundary between
* data bursts (eg 512 bytes for 480M).
* While it is possible to split a large fragment
* we don't know the size yet.
* Simplest solution is to fill the trb before the
* LINK with nop commands.
*/
if (num_trbs == 1 || num_trbs <= usable || usable == 0)
break;

if (ep_ring->type != TYPE_BULK)
/*
* While isoc transfers might have a buffer that
* crosses a 64k boundary it is unlikely.
* Since we can't add NOPs without generating
* gaps in the traffic just hope it never
* happens at the end of the ring.
* This could be fixed by writing a LINK TRB
* instead of the first NOP - however the
* TRB_TYPE_LINK_LE32() calls would all need
* changing to check the ring length.
*/
break;

if (num_trbs >= TRBS_PER_SEGMENT) {
xhci_err(xhci, "Too many fragments %d, max %d\n",
num_trbs, TRBS_PER_SEGMENT - 1);
return -EINVAL;
}

nop_cmd = cpu_to_le32(TRB_TYPE(TRB_TR_NOOP) |
ep_ring->cycle_state);
ep_ring->num_trbs_free -= usable;
do {
trb->generic.field[0] = 0;
trb->generic.field[1] = 0;
trb->generic.field[2] = 0;
trb->generic.field[3] = nop_cmd;
trb++;
} while (--usable);
ep_ring->enqueue = trb;
if (room_on_ring(xhci, ep_ring, num_trbs))
break;
}
if (room_on_ring(xhci, ep_ring, num_trbs))
break;

if (ep_ring == xhci->cmd_ring) {
xhci_err(xhci, "Do not support expand command ring\n");
Expand Down
Loading

0 comments on commit ca03339

Please sign in to comment.