Skip to content

Commit

Permalink
Merge tag 'for-usb-next-2012-11-12' of git://git.kernel.org/pub/scm/l…
Browse files Browse the repository at this point in the history
…inux/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 commit 68e5254 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 (commit bba18e3) and one
  for xHCI hosts with the TI redriver (commit b0e4e60).  Commit 4525c0a
  makes the xHCI driver work correctly on the SiBridge xHCI host (and
  perhaps other 1.0 xHCI host controllers).  Commit 392a07a fixes a bug in
  the Intel Panther Point xHCI host bandwidth checking checking.

  Commits 2611bd1 and 77b8476 are trivial cleanup patches.

  Sarah Sharp"
  • Loading branch information
Greg Kroah-Hartman committed Nov 12, 2012
2 parents 2f02bc8 + 77b8476 commit 51f1206
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 40 deletions.
9 changes: 7 additions & 2 deletions drivers/usb/host/xhci-mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}

Expand Down
16 changes: 6 additions & 10 deletions drivers/usb/host/xhci-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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)
Expand Down
34 changes: 20 additions & 14 deletions drivers/usb/host/xhci-ring.c
Original file line number Diff line number Diff line change
Expand Up @@ -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, "
Expand Down Expand Up @@ -3071,27 +3071,28 @@ 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)
*
* 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
Expand All @@ -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,
Expand All @@ -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],
Expand Down Expand Up @@ -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 |
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 |
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 |
Expand Down
32 changes: 19 additions & 13 deletions drivers/usb/host/xhci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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, "
Expand Down Expand Up @@ -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;
Expand All @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion drivers/usb/host/xhci.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 51f1206

Please sign in to comment.