mirror of
https://github.com/torvalds/linux.git
synced 2024-12-22 10:56:40 +00:00
xHCI patches for 3.8
Hi Greg, Here's some xHCI bug fixes. There's nothing major in here that can't wait for 3.8. The NULL pointer deref that commit68e5254
fixes hasn't ever been reported in the three years that the xHCI driver has been available, so it can wait a few more weeks. There's two quirk updates, one for Fresco Logic (commitbba18e3
) and one for xHCI hosts with the TI redriver (commitb0e4e60
). Commit4525c0a
makes the xHCI driver work correctly on the SiBridge xHCI host (and perhaps other 1.0 xHCI host controllers). Commit392a07a
fixes a bug in the Intel Panther Point xHCI host bandwidth checking checking. Commits 2611bd1 and77b8476
are trivial cleanup patches. Sarah Sharp -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJQoWZQAAoJEBMGWMLi1Gc53l8P/R05/ZTz+2VsdiotzqOnvJVJ b3h2ja4YLy5rtcU5nyn8yEISJVKVowt4w+J9lEVWj8ZtbLptAvQlUjM+2HCdgrTr RF5p4Y+5Wa0BHosqya4YPkQFu2ZMEDqgkpbfNU4q0hjrJEwUiB8XNfN2CqoO9RNk wQhEISQzhL2bmlgoKejlaU+csW4F1RZ1778SIWS/mj6zqtwc5JBn5J8o/DavJehk b2BGCRTKTtVnnP+N5LcWuJQg1tdi48ngigqo0VOqxjFTZ/w5YMLDZfXOBy/91lTI 8i6hKwU1/LH5hPQf+e8K9H3TbiVUg3TAe7UovstPd9UrVS0xbNgKydjhP0y6/Ozy 4TnmaQK4IQEGUVwzYLwIKCRrEZ32CNPIzm+ZU82MsMJH2rB0pP4yp1Gcu/IXTQJg wAyRNeheKiz6HqYeWE5ZuGK8h8Sodd+LJQeMl+ma/mlx6LvI/wpas8U13qTyOXsV E2UzqP4LrnMWtF8sEVnHa85hLvpdYLJDHMGrHHCb2OIgBuVmmf+U+xq7bZBIdeHZ iF66czS3ltdgXzimZfHpdTU/i12j3wGQ+si+b5d5GjjgBPJsQTecZD0GtOX4kQ5d 3roFyW8JY7IEVT8dNRtJsi5sG+DOmtFWycCxA0BicTqa1VVahQoBCQY6UYtce5yD b0F5ZWeaGmee9zXSgpWD =aiNz -----END PGP SIGNATURE----- Merge tag 'for-usb-next-2012-11-12' of git://git.kernel.org/pub/scm/linux/kernel/git/sarah/xhci into usb-next XHCI patches from Sarah: "xHCI patches for 3.8 Hi Greg, Here's some xHCI bug fixes. There's nothing major in here that can't wait for 3.8. The NULL pointer deref that commit68e5254
fixes hasn't ever been reported in the three years that the xHCI driver has been available, so it can wait a few more weeks. There's two quirk updates, one for Fresco Logic (commitbba18e3
) and one for xHCI hosts with the TI redriver (commitb0e4e60
). Commit4525c0a
makes the xHCI driver work correctly on the SiBridge xHCI host (and perhaps other 1.0 xHCI host controllers). Commit392a07a
fixes a bug in the Intel Panther Point xHCI host bandwidth checking checking. Commits 2611bd1 and77b8476
are trivial cleanup patches. Sarah Sharp"
This commit is contained in:
commit
51f1206f60
@ -205,7 +205,12 @@ static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci,
|
||||
|
||||
next = xhci_segment_alloc(xhci, cycle_state, flags);
|
||||
if (!next) {
|
||||
xhci_free_segments_for_ring(xhci, *first);
|
||||
prev = *first;
|
||||
while (prev) {
|
||||
next = prev->next;
|
||||
xhci_segment_free(xhci, prev);
|
||||
prev = next;
|
||||
}
|
||||
return -ENOMEM;
|
||||
}
|
||||
xhci_link_segments(xhci, prev, next, type);
|
||||
@ -258,7 +263,7 @@ static struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci,
|
||||
return ring;
|
||||
|
||||
fail:
|
||||
xhci_ring_free(xhci, ring);
|
||||
kfree(ring);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
/* Device for a quirk */
|
||||
#define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73
|
||||
#define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000
|
||||
#define PCI_DEVICE_ID_FRESCO_LOGIC_FL1400 0x1400
|
||||
|
||||
#define PCI_VENDOR_ID_ETRON 0x1b6f
|
||||
#define PCI_DEVICE_ID_ASROCK_P67 0x7023
|
||||
@ -58,8 +59,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
|
||||
|
||||
/* Look for vendor-specific quirks */
|
||||
if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC &&
|
||||
pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK) {
|
||||
if (pdev->revision == 0x0) {
|
||||
(pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK ||
|
||||
pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_FL1400)) {
|
||||
if (pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK &&
|
||||
pdev->revision == 0x0) {
|
||||
xhci->quirks |= XHCI_RESET_EP_QUIRK;
|
||||
xhci_dbg(xhci, "QUIRK: Fresco Logic xHC needs configure"
|
||||
" endpoint cmd after reset endpoint\n");
|
||||
@ -218,15 +221,8 @@ static void xhci_pci_remove(struct pci_dev *dev)
|
||||
static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
|
||||
{
|
||||
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||
int retval = 0;
|
||||
|
||||
if (hcd->state != HC_STATE_SUSPENDED ||
|
||||
xhci->shared_hcd->state != HC_STATE_SUSPENDED)
|
||||
return -EINVAL;
|
||||
|
||||
retval = xhci_suspend(xhci);
|
||||
|
||||
return retval;
|
||||
return xhci_suspend(xhci);
|
||||
}
|
||||
|
||||
static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
|
||||
|
@ -318,7 +318,7 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)
|
||||
* seconds), then it should assume that the there are
|
||||
* larger problems with the xHC and assert HCRST.
|
||||
*/
|
||||
ret = handshake(xhci, &xhci->op_regs->cmd_ring,
|
||||
ret = xhci_handshake(xhci, &xhci->op_regs->cmd_ring,
|
||||
CMD_RING_RUNNING, 0, 5 * 1000 * 1000);
|
||||
if (ret < 0) {
|
||||
xhci_err(xhci, "Stopped the command ring failed, "
|
||||
@ -3071,11 +3071,11 @@ static u32 xhci_td_remainder(unsigned int remainder)
|
||||
}
|
||||
|
||||
/*
|
||||
* For xHCI 1.0 host controllers, TD size is the number of packets remaining in
|
||||
* the TD (*not* including this TRB).
|
||||
* For xHCI 1.0 host controllers, TD size is the number of max packet sized
|
||||
* packets remaining in the TD (*not* including this TRB).
|
||||
*
|
||||
* Total TD packet count = total_packet_count =
|
||||
* roundup(TD size in bytes / wMaxPacketSize)
|
||||
* DIV_ROUND_UP(TD size in bytes / wMaxPacketSize)
|
||||
*
|
||||
* Packets transferred up to and including this TRB = packets_transferred =
|
||||
* rounddown(total bytes transferred including this TRB / wMaxPacketSize)
|
||||
@ -3083,15 +3083,16 @@ static u32 xhci_td_remainder(unsigned int remainder)
|
||||
* TD size = total_packet_count - packets_transferred
|
||||
*
|
||||
* It must fit in bits 21:17, so it can't be bigger than 31.
|
||||
* The last TRB in a TD must have the TD size set to zero.
|
||||
*/
|
||||
|
||||
static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len,
|
||||
unsigned int total_packet_count, struct urb *urb)
|
||||
unsigned int total_packet_count, struct urb *urb,
|
||||
unsigned int num_trbs_left)
|
||||
{
|
||||
int packets_transferred;
|
||||
|
||||
/* One TRB with a zero-length data packet. */
|
||||
if (running_total == 0 && trb_buff_len == 0)
|
||||
if (num_trbs_left == 0 || (running_total == 0 && trb_buff_len == 0))
|
||||
return 0;
|
||||
|
||||
/* All the TRB queueing functions don't count the current TRB in
|
||||
@ -3100,7 +3101,9 @@ static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len,
|
||||
packets_transferred = (running_total + trb_buff_len) /
|
||||
usb_endpoint_maxp(&urb->ep->desc);
|
||||
|
||||
return xhci_td_remainder(total_packet_count - packets_transferred);
|
||||
if ((total_packet_count - packets_transferred) > 31)
|
||||
return 31 << 17;
|
||||
return (total_packet_count - packets_transferred) << 17;
|
||||
}
|
||||
|
||||
static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
||||
@ -3127,7 +3130,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
||||
|
||||
num_trbs = count_sg_trbs_needed(xhci, urb);
|
||||
num_sgs = urb->num_mapped_sgs;
|
||||
total_packet_count = roundup(urb->transfer_buffer_length,
|
||||
total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length,
|
||||
usb_endpoint_maxp(&urb->ep->desc));
|
||||
|
||||
trb_buff_len = prepare_transfer(xhci, xhci->devs[slot_id],
|
||||
@ -3210,7 +3213,8 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
||||
running_total);
|
||||
} else {
|
||||
remainder = xhci_v1_0_td_remainder(running_total,
|
||||
trb_buff_len, total_packet_count, urb);
|
||||
trb_buff_len, total_packet_count, urb,
|
||||
num_trbs - 1);
|
||||
}
|
||||
length_field = TRB_LEN(trb_buff_len) |
|
||||
remainder |
|
||||
@ -3318,7 +3322,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
||||
start_cycle = ep_ring->cycle_state;
|
||||
|
||||
running_total = 0;
|
||||
total_packet_count = roundup(urb->transfer_buffer_length,
|
||||
total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length,
|
||||
usb_endpoint_maxp(&urb->ep->desc));
|
||||
/* How much data is in the first TRB? */
|
||||
addr = (u64) urb->transfer_dma;
|
||||
@ -3364,7 +3368,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
||||
running_total);
|
||||
} else {
|
||||
remainder = xhci_v1_0_td_remainder(running_total,
|
||||
trb_buff_len, total_packet_count, urb);
|
||||
trb_buff_len, total_packet_count, urb,
|
||||
num_trbs - 1);
|
||||
}
|
||||
length_field = TRB_LEN(trb_buff_len) |
|
||||
remainder |
|
||||
@ -3627,7 +3632,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
||||
addr = start_addr + urb->iso_frame_desc[i].offset;
|
||||
td_len = urb->iso_frame_desc[i].length;
|
||||
td_remain_len = td_len;
|
||||
total_packet_count = roundup(td_len,
|
||||
total_packet_count = DIV_ROUND_UP(td_len,
|
||||
usb_endpoint_maxp(&urb->ep->desc));
|
||||
/* A zero-length transfer still involves at least one packet. */
|
||||
if (total_packet_count == 0)
|
||||
@ -3706,7 +3711,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
||||
} else {
|
||||
remainder = xhci_v1_0_td_remainder(
|
||||
running_total, trb_buff_len,
|
||||
total_packet_count, urb);
|
||||
total_packet_count, urb,
|
||||
(trbs_per_td - j - 1));
|
||||
}
|
||||
length_field = TRB_LEN(trb_buff_len) |
|
||||
remainder |
|
||||
|
@ -40,7 +40,7 @@ MODULE_PARM_DESC(link_quirk, "Don't clear the chain bit on a link TRB");
|
||||
|
||||
/* TODO: copied from ehci-hcd.c - can this be refactored? */
|
||||
/*
|
||||
* handshake - spin reading hc until handshake completes or fails
|
||||
* xhci_handshake - spin reading hc until handshake completes or fails
|
||||
* @ptr: address of hc register to be read
|
||||
* @mask: bits to look at in result of read
|
||||
* @done: value of those bits when handshake succeeds
|
||||
@ -52,7 +52,7 @@ MODULE_PARM_DESC(link_quirk, "Don't clear the chain bit on a link TRB");
|
||||
* handshake done). There are two failure modes: "usec" have passed (major
|
||||
* hardware flakeout), or the register reads as all-ones (hardware removed).
|
||||
*/
|
||||
int handshake(struct xhci_hcd *xhci, void __iomem *ptr,
|
||||
int xhci_handshake(struct xhci_hcd *xhci, void __iomem *ptr,
|
||||
u32 mask, u32 done, int usec)
|
||||
{
|
||||
u32 result;
|
||||
@ -103,7 +103,7 @@ int xhci_halt(struct xhci_hcd *xhci)
|
||||
xhci_dbg(xhci, "// Halt the HC\n");
|
||||
xhci_quiesce(xhci);
|
||||
|
||||
ret = handshake(xhci, &xhci->op_regs->status,
|
||||
ret = xhci_handshake(xhci, &xhci->op_regs->status,
|
||||
STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC);
|
||||
if (!ret) {
|
||||
xhci->xhc_state |= XHCI_STATE_HALTED;
|
||||
@ -132,7 +132,7 @@ static int xhci_start(struct xhci_hcd *xhci)
|
||||
* Wait for the HCHalted Status bit to be 0 to indicate the host is
|
||||
* running.
|
||||
*/
|
||||
ret = handshake(xhci, &xhci->op_regs->status,
|
||||
ret = xhci_handshake(xhci, &xhci->op_regs->status,
|
||||
STS_HALT, 0, XHCI_MAX_HALT_USEC);
|
||||
if (ret == -ETIMEDOUT)
|
||||
xhci_err(xhci, "Host took too long to start, "
|
||||
@ -167,7 +167,7 @@ int xhci_reset(struct xhci_hcd *xhci)
|
||||
command |= CMD_RESET;
|
||||
xhci_writel(xhci, command, &xhci->op_regs->command);
|
||||
|
||||
ret = handshake(xhci, &xhci->op_regs->command,
|
||||
ret = xhci_handshake(xhci, &xhci->op_regs->command,
|
||||
CMD_RESET, 0, 10 * 1000 * 1000);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -177,7 +177,7 @@ int xhci_reset(struct xhci_hcd *xhci)
|
||||
* xHCI cannot write to any doorbells or operational registers other
|
||||
* than status until the "Controller Not Ready" flag is cleared.
|
||||
*/
|
||||
ret = handshake(xhci, &xhci->op_regs->status,
|
||||
ret = xhci_handshake(xhci, &xhci->op_regs->status,
|
||||
STS_CNR, 0, 10 * 1000 * 1000);
|
||||
|
||||
for (i = 0; i < 2; ++i) {
|
||||
@ -480,7 +480,7 @@ static bool compliance_mode_recovery_timer_quirk_check(void)
|
||||
if (strstr(dmi_product_name, "Z420") ||
|
||||
strstr(dmi_product_name, "Z620") ||
|
||||
strstr(dmi_product_name, "Z820") ||
|
||||
strstr(dmi_product_name, "Z1"))
|
||||
strstr(dmi_product_name, "Z1 Workstation"))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@ -880,6 +880,10 @@ int xhci_suspend(struct xhci_hcd *xhci)
|
||||
struct usb_hcd *hcd = xhci_to_hcd(xhci);
|
||||
u32 command;
|
||||
|
||||
if (hcd->state != HC_STATE_SUSPENDED ||
|
||||
xhci->shared_hcd->state != HC_STATE_SUSPENDED)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irq(&xhci->lock);
|
||||
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
|
||||
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
|
||||
@ -890,7 +894,7 @@ int xhci_suspend(struct xhci_hcd *xhci)
|
||||
command = xhci_readl(xhci, &xhci->op_regs->command);
|
||||
command &= ~CMD_RUN;
|
||||
xhci_writel(xhci, command, &xhci->op_regs->command);
|
||||
if (handshake(xhci, &xhci->op_regs->status,
|
||||
if (xhci_handshake(xhci, &xhci->op_regs->status,
|
||||
STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC)) {
|
||||
xhci_warn(xhci, "WARN: xHC CMD_RUN timeout\n");
|
||||
spin_unlock_irq(&xhci->lock);
|
||||
@ -905,7 +909,8 @@ int xhci_suspend(struct xhci_hcd *xhci)
|
||||
command = xhci_readl(xhci, &xhci->op_regs->command);
|
||||
command |= CMD_CSS;
|
||||
xhci_writel(xhci, command, &xhci->op_regs->command);
|
||||
if (handshake(xhci, &xhci->op_regs->status, STS_SAVE, 0, 10 * 1000)) {
|
||||
if (xhci_handshake(xhci, &xhci->op_regs->status,
|
||||
STS_SAVE, 0, 10 * 1000)) {
|
||||
xhci_warn(xhci, "WARN: xHC save state timeout\n");
|
||||
spin_unlock_irq(&xhci->lock);
|
||||
return -ETIMEDOUT;
|
||||
@ -967,7 +972,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
|
||||
command = xhci_readl(xhci, &xhci->op_regs->command);
|
||||
command |= CMD_CRS;
|
||||
xhci_writel(xhci, command, &xhci->op_regs->command);
|
||||
if (handshake(xhci, &xhci->op_regs->status,
|
||||
if (xhci_handshake(xhci, &xhci->op_regs->status,
|
||||
STS_RESTORE, 0, 10 * 1000)) {
|
||||
xhci_warn(xhci, "WARN: xHC restore state timeout\n");
|
||||
spin_unlock_irq(&xhci->lock);
|
||||
@ -1035,7 +1040,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
|
||||
command = xhci_readl(xhci, &xhci->op_regs->command);
|
||||
command |= CMD_RUN;
|
||||
xhci_writel(xhci, command, &xhci->op_regs->command);
|
||||
handshake(xhci, &xhci->op_regs->status, STS_HALT,
|
||||
xhci_handshake(xhci, &xhci->op_regs->status, STS_HALT,
|
||||
0, 250 * 1000);
|
||||
|
||||
/* step 5: walk topology and initialize portsc,
|
||||
@ -2254,7 +2259,7 @@ static bool xhci_is_async_ep(unsigned int ep_type)
|
||||
|
||||
static bool xhci_is_sync_in_ep(unsigned int ep_type)
|
||||
{
|
||||
return (ep_type == ISOC_IN_EP || ep_type != INT_IN_EP);
|
||||
return (ep_type == ISOC_IN_EP || ep_type == INT_IN_EP);
|
||||
}
|
||||
|
||||
static unsigned int xhci_get_ss_bw_consumed(struct xhci_bw_info *ep_bw)
|
||||
@ -3874,7 +3879,8 @@ static int xhci_usb2_software_lpm_test(struct usb_hcd *hcd,
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
|
||||
/* Check L1 Status */
|
||||
ret = handshake(xhci, pm_addr, PORT_L1S_MASK, PORT_L1S_SUCCESS, 125);
|
||||
ret = xhci_handshake(xhci, pm_addr,
|
||||
PORT_L1S_MASK, PORT_L1S_SUCCESS, 125);
|
||||
if (ret != -ETIMEDOUT) {
|
||||
/* enter L1 successfully */
|
||||
temp = xhci_readl(xhci, addr);
|
||||
|
@ -1720,7 +1720,7 @@ static inline void xhci_unregister_plat(void)
|
||||
|
||||
/* xHCI host controller glue */
|
||||
typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *);
|
||||
int handshake(struct xhci_hcd *xhci, void __iomem *ptr,
|
||||
int xhci_handshake(struct xhci_hcd *xhci, void __iomem *ptr,
|
||||
u32 mask, u32 done, int usec);
|
||||
void xhci_quiesce(struct xhci_hcd *xhci);
|
||||
int xhci_halt(struct xhci_hcd *xhci);
|
||||
|
Loading…
Reference in New Issue
Block a user