Hi Greg,
Here's 11 xHCI bug fixes for 3.4. Some of the patches fix issues with crashes on system resume related to VIA xHCI host controllers accessing bad memory addresses. The patches change the register restore ordering, so I had several vendors confirm that the patches don't break their xHCI hosts. Elric Fu confirms this patchset fixes the VIA issue, Alex He confirms the changes does not break suspend/resume on AMD xHCI systems, and I've made sure it doesn't break Intel host controllers. I have not heard back from Felipe about the TI host, so at this point, I'm just going to send them off. Several of the patches are marked for stable. Please pull. Sarah Sharp -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJPhfEEAAoJEBMGWMLi1Gc5JFAQAJv2SSrLqEem7OX1srAIPFjs NjO2hQQ090syGQcWU4pa7PSY85iWt4/1dzvE5l1R7yH1bYhP8fvhFtcsbVQguHPJ 4pDpLN5w2GMbEEjeWBrAjYOuIrF72kvxY5IeHglqTGBrIt2ELJENYIxKa84jmA6g B1iSZYgN3RGh/T1Fr0DvyUB3fXUvTzeY48hesel2ITbxjQGZ/NKBcf6SObH/D0Sq d7HxFp3YNYV4+y/Agex9CEUpTv7t8Pf0WX8O6OmLlr57Lo43Hh7iEWu8d7NL1DVL gQENBLbsjWSWDwU7mUQc2tHIH0t7ji+agFWGMv9m9YaThX44sg9JD/jdpcjIQ6TQ cbJdUVpVHR5D2pXw1MM9Rsd5st2adPbJO1UfQiTm7IKmrkXOQvbfqfvUisjIY1nY Ohbk+Q1bd0Q/lY3iOR63VtKEBlRqOazaHXQx8lGG5UahwwQgVmc8zzdCAcqxyDPN xFYZWfmPDarQ5h3rU4dugzZR7alEsaO+uTX4pN9ZVrY5f1NRruRpHroqWkQtpWVL XnHHkU1CNFG61UgupM35C2Y9cBQ5tfEud7YYUMzVqPE7HSYzXtA8HtnilQL0fd3z 34LdR10rG9z9/Li1khYpe4wwF47FUHLpLo+/CyEv+Czr0gSyMhBT9nhm8+SQdac3 ywr5U0BmWTTrabNe5PQx =LRhW -----END PGP SIGNATURE----- Merge tag 'for-usb-linus-2012-04-11' of git://git.kernel.org/pub/scm/linux/kernel/git/sarah/xhci into usb-linus Hi Greg, Here's 11 xHCI bug fixes for 3.4. Some of the patches fix issues with crashes on system resume related to VIA xHCI host controllers accessing bad memory addresses. The patches change the register restore ordering, so I had several vendors confirm that the patches don't break their xHCI hosts. Elric Fu confirms this patchset fixes the VIA issue, Alex He confirms the changes does not break suspend/resume on AMD xHCI systems, and I've made sure it doesn't break Intel host controllers. I have not heard back from Felipe about the TI host, so at this point, I'm just going to send them off. Several of the patches are marked for stable. Please pull. Sarah Sharp
This commit is contained in:
Коммит
5c15c9a63d
|
@ -3163,6 +3163,22 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
|
|||
if (retval)
|
||||
goto fail;
|
||||
|
||||
/*
|
||||
* Some superspeed devices have finished the link training process
|
||||
* and attached to a superspeed hub port, but the device descriptor
|
||||
* got from those devices show they aren't superspeed devices. Warm
|
||||
* reset the port attached by the devices can fix them.
|
||||
*/
|
||||
if ((udev->speed == USB_SPEED_SUPER) &&
|
||||
(le16_to_cpu(udev->descriptor.bcdUSB) < 0x0300)) {
|
||||
dev_err(&udev->dev, "got a wrong device descriptor, "
|
||||
"warm reset device\n");
|
||||
hub_port_reset(hub, port1, udev,
|
||||
HUB_BH_RESET_TIME, true);
|
||||
retval = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (udev->descriptor.bMaxPacketSize0 == 0xff ||
|
||||
udev->speed == USB_SPEED_SUPER)
|
||||
i = 512;
|
||||
|
|
|
@ -825,9 +825,13 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
/* Disable any BIOS SMIs */
|
||||
writel(XHCI_LEGACY_DISABLE_SMI,
|
||||
base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET);
|
||||
val = readl(base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET);
|
||||
/* Mask off (turn off) any enabled SMIs */
|
||||
val &= XHCI_LEGACY_DISABLE_SMI;
|
||||
/* Mask all SMI events bits, RW1C */
|
||||
val |= XHCI_LEGACY_SMI_EVENTS;
|
||||
/* Disable any BIOS SMIs and clear all SMI events*/
|
||||
writel(val, base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET);
|
||||
|
||||
if (usb_is_intel_switchable_xhci(pdev))
|
||||
usb_enable_xhci_ports(pdev);
|
||||
|
|
|
@ -119,7 +119,7 @@ static void xhci_print_command_reg(struct xhci_hcd *xhci)
|
|||
xhci_dbg(xhci, " Event Interrupts %s\n",
|
||||
(temp & CMD_EIE) ? "enabled " : "disabled");
|
||||
xhci_dbg(xhci, " Host System Error Interrupts %s\n",
|
||||
(temp & CMD_EIE) ? "enabled " : "disabled");
|
||||
(temp & CMD_HSEIE) ? "enabled " : "disabled");
|
||||
xhci_dbg(xhci, " HC has %sfinished light reset\n",
|
||||
(temp & CMD_LRESET) ? "not " : "");
|
||||
}
|
||||
|
|
|
@ -62,8 +62,9 @@
|
|||
/* USB Legacy Support Control and Status Register - section 7.1.2 */
|
||||
/* Add this offset, plus the value of xECP in HCCPARAMS to the base address */
|
||||
#define XHCI_LEGACY_CONTROL_OFFSET (0x04)
|
||||
/* bits 1:2, 5:12, and 17:19 need to be preserved; bits 21:28 should be zero */
|
||||
#define XHCI_LEGACY_DISABLE_SMI ((0x3 << 1) + (0xff << 5) + (0x7 << 17))
|
||||
/* bits 1:3, 5:12, and 17:19 need to be preserved; bits 21:28 should be zero */
|
||||
#define XHCI_LEGACY_DISABLE_SMI ((0x7 << 1) + (0xff << 5) + (0x7 << 17))
|
||||
#define XHCI_LEGACY_SMI_EVENTS (0x7 << 29)
|
||||
|
||||
/* USB 2.0 xHCI 0.96 L1C capability - section 7.2.2.1.3.2 */
|
||||
#define XHCI_L1C (1 << 16)
|
||||
|
|
|
@ -1796,11 +1796,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
|
|||
int i;
|
||||
|
||||
/* Free the Event Ring Segment Table and the actual Event Ring */
|
||||
if (xhci->ir_set) {
|
||||
xhci_writel(xhci, 0, &xhci->ir_set->erst_size);
|
||||
xhci_write_64(xhci, 0, &xhci->ir_set->erst_base);
|
||||
xhci_write_64(xhci, 0, &xhci->ir_set->erst_dequeue);
|
||||
}
|
||||
size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries);
|
||||
if (xhci->erst.entries)
|
||||
dma_free_coherent(&pdev->dev, size,
|
||||
|
@ -1812,7 +1807,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
|
|||
xhci->event_ring = NULL;
|
||||
xhci_dbg(xhci, "Freed event ring\n");
|
||||
|
||||
xhci_write_64(xhci, 0, &xhci->op_regs->cmd_ring);
|
||||
if (xhci->cmd_ring)
|
||||
xhci_ring_free(xhci, xhci->cmd_ring);
|
||||
xhci->cmd_ring = NULL;
|
||||
|
@ -1841,7 +1835,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
|
|||
xhci->medium_streams_pool = NULL;
|
||||
xhci_dbg(xhci, "Freed medium stream array pool\n");
|
||||
|
||||
xhci_write_64(xhci, 0, &xhci->op_regs->dcbaa_ptr);
|
||||
if (xhci->dcbaa)
|
||||
dma_free_coherent(&pdev->dev, sizeof(*xhci->dcbaa),
|
||||
xhci->dcbaa, xhci->dcbaa->dma);
|
||||
|
@ -2459,6 +2452,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
|
|||
|
||||
fail:
|
||||
xhci_warn(xhci, "Couldn't initialize memory\n");
|
||||
xhci_halt(xhci);
|
||||
xhci_reset(xhci);
|
||||
xhci_mem_cleanup(xhci);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
|
|
@ -95,6 +95,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
|
|||
xhci->quirks |= XHCI_RESET_ON_RESUME;
|
||||
xhci_dbg(xhci, "QUIRK: Resetting on resume\n");
|
||||
}
|
||||
if (pdev->vendor == PCI_VENDOR_ID_VIA)
|
||||
xhci->quirks |= XHCI_RESET_ON_RESUME;
|
||||
}
|
||||
|
||||
/* called during probe() after chip reset completes */
|
||||
|
@ -326,7 +328,7 @@ int __init xhci_register_pci(void)
|
|||
return pci_register_driver(&xhci_pci_driver);
|
||||
}
|
||||
|
||||
void __exit xhci_unregister_pci(void)
|
||||
void xhci_unregister_pci(void)
|
||||
{
|
||||
pci_unregister_driver(&xhci_pci_driver);
|
||||
}
|
||||
|
|
|
@ -2417,7 +2417,7 @@ hw_died:
|
|||
u32 irq_pending;
|
||||
/* Acknowledge the PCI interrupt */
|
||||
irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending);
|
||||
irq_pending |= 0x3;
|
||||
irq_pending |= IMAN_IP;
|
||||
xhci_writel(xhci, irq_pending, &xhci->ir_set->irq_pending);
|
||||
}
|
||||
|
||||
|
@ -2734,7 +2734,7 @@ int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
|||
urb->dev->speed == USB_SPEED_FULL)
|
||||
urb->interval /= 8;
|
||||
}
|
||||
return xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index);
|
||||
return xhci_queue_bulk_tx(xhci, mem_flags, urb, slot_id, ep_index);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3514,7 +3514,7 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags,
|
|||
}
|
||||
ep_ring->num_trbs_free_temp = ep_ring->num_trbs_free;
|
||||
|
||||
return xhci_queue_isoc_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index);
|
||||
return xhci_queue_isoc_tx(xhci, mem_flags, urb, slot_id, ep_index);
|
||||
}
|
||||
|
||||
/**** Command Ring Operations ****/
|
||||
|
|
|
@ -106,6 +106,9 @@ int xhci_halt(struct xhci_hcd *xhci)
|
|||
STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC);
|
||||
if (!ret)
|
||||
xhci->xhc_state |= XHCI_STATE_HALTED;
|
||||
else
|
||||
xhci_warn(xhci, "Host not halted after %u microseconds.\n",
|
||||
XHCI_MAX_HALT_USEC);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -664,11 +667,11 @@ static void xhci_save_registers(struct xhci_hcd *xhci)
|
|||
xhci->s3.dev_nt = xhci_readl(xhci, &xhci->op_regs->dev_notification);
|
||||
xhci->s3.dcbaa_ptr = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr);
|
||||
xhci->s3.config_reg = xhci_readl(xhci, &xhci->op_regs->config_reg);
|
||||
xhci->s3.irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending);
|
||||
xhci->s3.irq_control = xhci_readl(xhci, &xhci->ir_set->irq_control);
|
||||
xhci->s3.erst_size = xhci_readl(xhci, &xhci->ir_set->erst_size);
|
||||
xhci->s3.erst_base = xhci_read_64(xhci, &xhci->ir_set->erst_base);
|
||||
xhci->s3.erst_dequeue = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
|
||||
xhci->s3.irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending);
|
||||
xhci->s3.irq_control = xhci_readl(xhci, &xhci->ir_set->irq_control);
|
||||
}
|
||||
|
||||
static void xhci_restore_registers(struct xhci_hcd *xhci)
|
||||
|
@ -677,10 +680,11 @@ static void xhci_restore_registers(struct xhci_hcd *xhci)
|
|||
xhci_writel(xhci, xhci->s3.dev_nt, &xhci->op_regs->dev_notification);
|
||||
xhci_write_64(xhci, xhci->s3.dcbaa_ptr, &xhci->op_regs->dcbaa_ptr);
|
||||
xhci_writel(xhci, xhci->s3.config_reg, &xhci->op_regs->config_reg);
|
||||
xhci_writel(xhci, xhci->s3.irq_pending, &xhci->ir_set->irq_pending);
|
||||
xhci_writel(xhci, xhci->s3.irq_control, &xhci->ir_set->irq_control);
|
||||
xhci_writel(xhci, xhci->s3.erst_size, &xhci->ir_set->erst_size);
|
||||
xhci_write_64(xhci, xhci->s3.erst_base, &xhci->ir_set->erst_base);
|
||||
xhci_write_64(xhci, xhci->s3.erst_dequeue, &xhci->ir_set->erst_dequeue);
|
||||
xhci_writel(xhci, xhci->s3.irq_pending, &xhci->ir_set->irq_pending);
|
||||
xhci_writel(xhci, xhci->s3.irq_control, &xhci->ir_set->irq_control);
|
||||
}
|
||||
|
||||
static void xhci_set_cmd_ring_deq(struct xhci_hcd *xhci)
|
||||
|
|
|
@ -205,6 +205,10 @@ struct xhci_op_regs {
|
|||
#define CMD_PM_INDEX (1 << 11)
|
||||
/* bits 12:31 are reserved (and should be preserved on writes). */
|
||||
|
||||
/* IMAN - Interrupt Management Register */
|
||||
#define IMAN_IP (1 << 1)
|
||||
#define IMAN_IE (1 << 0)
|
||||
|
||||
/* USBSTS - USB status - status bitmasks */
|
||||
/* HC not running - set to 1 when run/stop bit is cleared. */
|
||||
#define STS_HALT XHCI_STS_HALT
|
||||
|
|
Загрузка…
Ссылка в новой задаче