* prepare_transfer()?
*/
static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring,
- bool consumer, bool more_trbs_coming)
+ bool consumer, bool more_trbs_coming, bool isoc)
{
u32 chain;
union xhci_trb *next;
if (!chain && !more_trbs_coming)
break;
- /* If we're not dealing with 0.95 hardware,
+ /* If we're not dealing with 0.95 hardware or
+ * isoc rings on AMD 0.96 host,
* carry over the chain bit of the previous TRB
* (which may mean the chain bit is cleared).
*/
- if (!xhci_link_trb_quirk(xhci)) {
+ if (!(isoc && (xhci->quirks & XHCI_AMD_0x96_HOST))
+ && !xhci_link_trb_quirk(xhci)) {
next->link.control &=
cpu_to_le32(~TRB_CHAIN);
next->link.control |=
if (DEV_SUPERSPEED(temp)) {
xhci_dbg(xhci, "resume SS port %d\n", port_id);
- temp = xhci_port_state_to_neutral(temp);
- temp &= ~PORT_PLS_MASK;
- temp |= PORT_LINK_STROBE | XDEV_U0;
- xhci_writel(xhci, temp, port_array[faked_port_index]);
+ xhci_set_link_state(xhci, port_array, faked_port_index,
+ XDEV_U0);
slot_id = xhci_find_slot_id_by_port(hcd, xhci,
faked_port_index);
if (!slot_id) {
xhci_ring_device(xhci, slot_id);
xhci_dbg(xhci, "resume SS port %d finished\n", port_id);
/* Clear PORT_PLC */
- temp = xhci_readl(xhci, port_array[faked_port_index]);
- temp = xhci_port_state_to_neutral(temp);
- temp |= PORT_PLC;
- xhci_writel(xhci, temp, port_array[faked_port_index]);
+ xhci_test_and_clear_bit(xhci, port_array,
+ faked_port_index, PORT_PLC);
} else {
xhci_dbg(xhci, "resume HS port %d\n", port_id);
bus_state->resume_done[faked_port_index] = jiffies +
}
}
+ if (hcd->speed != HCD_USB3)
+ xhci_test_and_clear_bit(xhci, port_array, faked_port_index,
+ PORT_PLC);
+
cleanup:
/* Update event ring dequeue pointer before dropping the lock */
inc_deq(xhci, xhci->event_ring, true);
if ((urb->actual_length != urb->transfer_buffer_length &&
(urb->transfer_flags &
URB_SHORT_NOT_OK)) ||
- status != 0)
+ (status != 0 &&
+ !usb_endpoint_xfer_isoc(&urb->ep->desc)))
xhci_dbg(xhci, "Giveback URB %p, len = %d, "
"expected = %x, status = %d\n",
urb, urb->actual_length,
* prepare_transfer()?
*/
static void queue_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,
- bool consumer, bool more_trbs_coming,
+ bool consumer, bool more_trbs_coming, bool isoc,
u32 field1, u32 field2, u32 field3, u32 field4)
{
struct xhci_generic_trb *trb;
trb->field[1] = cpu_to_le32(field2);
trb->field[2] = cpu_to_le32(field3);
trb->field[3] = cpu_to_le32(field4);
- inc_enq(xhci, ring, consumer, more_trbs_coming);
+ inc_enq(xhci, ring, consumer, more_trbs_coming, isoc);
}
/*
* FIXME allocate segments if the ring is full.
*/
static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
- u32 ep_state, unsigned int num_trbs, gfp_t mem_flags)
+ u32 ep_state, unsigned int num_trbs, bool isoc, gfp_t mem_flags)
{
/* Make sure the endpoint has been added to xHC schedule */
switch (ep_state) {
next = ring->enqueue;
while (last_trb(xhci, ring, ring->enq_seg, next)) {
- /* If we're not dealing with 0.95 hardware,
- * clear the chain bit.
+ /* If we're not dealing with 0.95 hardware or isoc rings
+ * on AMD 0.96 host, clear the chain bit.
*/
- if (!xhci_link_trb_quirk(xhci))
+ if (!xhci_link_trb_quirk(xhci) && !(isoc &&
+ (xhci->quirks & XHCI_AMD_0x96_HOST)))
next->link.control &= cpu_to_le32(~TRB_CHAIN);
else
next->link.control |= cpu_to_le32(TRB_CHAIN);
unsigned int num_trbs,
struct urb *urb,
unsigned int td_index,
+ bool isoc,
gfp_t mem_flags)
{
int ret;
ret = prepare_ring(xhci, ep_ring,
le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK,
- num_trbs, mem_flags);
+ num_trbs, isoc, mem_flags);
if (ret)
return ret;
* running_total.
*/
packets_transferred = (running_total + trb_buff_len) /
- le16_to_cpu(urb->ep->desc.wMaxPacketSize);
+ usb_endpoint_maxp(&urb->ep->desc);
return xhci_td_remainder(total_packet_count - packets_transferred);
}
num_trbs = count_sg_trbs_needed(xhci, urb);
num_sgs = urb->num_sgs;
total_packet_count = roundup(urb->transfer_buffer_length,
- le16_to_cpu(urb->ep->desc.wMaxPacketSize));
+ usb_endpoint_maxp(&urb->ep->desc));
trb_buff_len = prepare_transfer(xhci, xhci->devs[slot_id],
ep_index, urb->stream_id,
- num_trbs, urb, 0, mem_flags);
+ num_trbs, urb, 0, false, mem_flags);
if (trb_buff_len < 0)
return trb_buff_len;
more_trbs_coming = true;
else
more_trbs_coming = false;
- queue_trb(xhci, ep_ring, false, more_trbs_coming,
+ queue_trb(xhci, ep_ring, false, more_trbs_coming, false,
lower_32_bits(addr),
upper_32_bits(addr),
length_field,
ret = prepare_transfer(xhci, xhci->devs[slot_id],
ep_index, urb->stream_id,
- num_trbs, urb, 0, mem_flags);
+ num_trbs, urb, 0, false, mem_flags);
if (ret < 0)
return ret;
running_total = 0;
total_packet_count = roundup(urb->transfer_buffer_length,
- le16_to_cpu(urb->ep->desc.wMaxPacketSize));
+ usb_endpoint_maxp(&urb->ep->desc));
/* How much data is in the first TRB? */
addr = (u64) urb->transfer_dma;
trb_buff_len = TRB_MAX_BUFF_SIZE -
more_trbs_coming = true;
else
more_trbs_coming = false;
- queue_trb(xhci, ep_ring, false, more_trbs_coming,
+ queue_trb(xhci, ep_ring, false, more_trbs_coming, false,
lower_32_bits(addr),
upper_32_bits(addr),
length_field,
num_trbs++;
ret = prepare_transfer(xhci, xhci->devs[slot_id],
ep_index, urb->stream_id,
- num_trbs, urb, 0, mem_flags);
+ num_trbs, urb, 0, false, mem_flags);
if (ret < 0)
return ret;
}
}
- queue_trb(xhci, ep_ring, false, true,
+ queue_trb(xhci, ep_ring, false, true, false,
setup->bRequestType | setup->bRequest << 8 | le16_to_cpu(setup->wValue) << 16,
le16_to_cpu(setup->wIndex) | le16_to_cpu(setup->wLength) << 16,
TRB_LEN(8) | TRB_INTR_TARGET(0),
if (urb->transfer_buffer_length > 0) {
if (setup->bRequestType & USB_DIR_IN)
field |= TRB_DIR_IN;
- queue_trb(xhci, ep_ring, false, true,
+ queue_trb(xhci, ep_ring, false, true, false,
lower_32_bits(urb->transfer_dma),
upper_32_bits(urb->transfer_dma),
length_field,
field = 0;
else
field = TRB_DIR_IN;
- queue_trb(xhci, ep_ring, false, false,
+ queue_trb(xhci, ep_ring, false, false, false,
0,
0,
TRB_INTR_TARGET(0),
td_len = urb->iso_frame_desc[i].length;
td_remain_len = td_len;
total_packet_count = roundup(td_len,
- le16_to_cpu(urb->ep->desc.wMaxPacketSize));
+ usb_endpoint_maxp(&urb->ep->desc));
/* A zero-length transfer still involves at least one packet. */
if (total_packet_count == 0)
total_packet_count++;
trbs_per_td = count_isoc_trbs_needed(xhci, urb, i);
ret = prepare_transfer(xhci, xhci->devs[slot_id], ep_index,
- urb->stream_id, trbs_per_td, urb, i, mem_flags);
+ urb->stream_id, trbs_per_td, urb, i, true,
+ mem_flags);
if (ret < 0) {
if (i == 0)
return ret;
remainder |
TRB_INTR_TARGET(0);
- queue_trb(xhci, ep_ring, false, more_trbs_coming,
+ queue_trb(xhci, ep_ring, false, more_trbs_coming, true,
lower_32_bits(addr),
upper_32_bits(addr),
length_field,
* Do not insert any td of the urb to the ring if the check failed.
*/
ret = prepare_ring(xhci, ep_ring, le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK,
- num_trbs, mem_flags);
+ num_trbs, true, mem_flags);
if (ret)
return ret;
reserved_trbs++;
ret = prepare_ring(xhci, xhci->cmd_ring, EP_STATE_RUNNING,
- reserved_trbs, GFP_ATOMIC);
+ reserved_trbs, false, GFP_ATOMIC);
if (ret < 0) {
xhci_err(xhci, "ERR: No room for command on command ring\n");
if (command_must_succeed)
"unfailable commands failed.\n");
return ret;
}
- queue_trb(xhci, xhci->cmd_ring, false, false, field1, field2, field3,
- field4 | xhci->cmd_ring->cycle_state);
+ queue_trb(xhci, xhci->cmd_ring, false, false, false, field1, field2,
+ field3, field4 | xhci->cmd_ring->cycle_state);
return 0;
}