Merge branch 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
[pandora-kernel.git] / drivers / usb / host / xhci-ring.c
index 952e2de..940321b 100644 (file)
@@ -185,7 +185,7 @@ static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer
  *                     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;
@@ -212,11 +212,13 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring,
                                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 |=
@@ -1329,10 +1331,8 @@ static void handle_port_status(struct xhci_hcd *xhci,
 
                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) {
@@ -1342,10 +1342,8 @@ static void handle_port_status(struct xhci_hcd *xhci,
                        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 +
@@ -1356,6 +1354,10 @@ static void handle_port_status(struct xhci_hcd *xhci,
                }
        }
 
+       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);
@@ -2192,7 +2194,8 @@ cleanup:
                        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,
@@ -2409,7 +2412,7 @@ irqreturn_t xhci_msi_irq(int irq, struct usb_hcd *hcd)
  *                     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;
@@ -2419,7 +2422,7 @@ static void queue_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,
        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);
 }
 
 /*
@@ -2427,7 +2430,7 @@ static void queue_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,
  * 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) {
@@ -2469,10 +2472,11 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
                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);
@@ -2505,6 +2509,7 @@ static int prepare_transfer(struct xhci_hcd *xhci,
                unsigned int num_trbs,
                struct urb *urb,
                unsigned int td_index,
+               bool isoc,
                gfp_t mem_flags)
 {
        int ret;
@@ -2522,7 +2527,7 @@ static int prepare_transfer(struct xhci_hcd *xhci,
 
        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;
 
@@ -2711,7 +2716,7 @@ static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len,
         * 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);
 }
@@ -2741,11 +2746,11 @@ 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_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;
 
@@ -2840,7 +2845,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                        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,
@@ -2931,7 +2936,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 
        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;
 
@@ -2948,7 +2953,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 
        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 -
@@ -3003,7 +3008,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                        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,
@@ -3063,7 +3068,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                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;
 
@@ -3096,7 +3101,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                }
        }
 
-       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),
@@ -3116,7 +3121,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        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,
@@ -3132,7 +3137,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                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),
@@ -3269,7 +3274,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                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++;
@@ -3281,7 +3286,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                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;
@@ -3351,7 +3357,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                                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,
@@ -3433,7 +3439,7 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags,
         * 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;
 
@@ -3492,7 +3498,7 @@ static int queue_command(struct xhci_hcd *xhci, u32 field1, u32 field2,
                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)
@@ -3500,8 +3506,8 @@ static int queue_command(struct xhci_hcd *xhci, u32 field1, u32 field2,
                                        "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;
 }