Re: [PATCH] xhci: Transfer ring link TRB activation change.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, May 11, 2010 at 4:03 AM, John Youn <John.Youn@xxxxxxxxxxxx> wrote:
> Change transfer ring behavior to not follow/activate link TRBs
> until active TRBs are queued after it.  This change affects
> the behavior when a TD ends just before a link TRB.
>
> Signed-off-by: John Youn <johnyoun@xxxxxxxxxxxx>
> Signed-off-by: Sarah Sharp <sarah.a.sharp@xxxxxxxxxxxxxxx>
> ---
>
> Forwarding to Greg KH
>
>  drivers/usb/host/xhci-ring.c |   71 ++++++++++++++++++++++++++++++++++--------
>  1 files changed, 58 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
> index b648efa..74d0c2d 100644
> --- a/drivers/usb/host/xhci-ring.c
> +++ b/drivers/usb/host/xhci-ring.c
> @@ -112,6 +112,12 @@ static inline int last_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,
>                return (trb->link.control & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK);
>  }
>
> +static inline int enqueue_is_link_trb(struct xhci_ring *ring)
> +{
> +       struct xhci_link_trb *link = &ring->enqueue->link;
> +       return ((link->control & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK));
> +}
> +
>  /* Updates trb to point to the next TRB in the ring, and updates seg if the next
>  * TRB is in a new segment.  This does not skip over link TRBs, and it does not
>  * effect the ring dequeue or enqueue pointers.
> @@ -193,20 +199,15 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer
>        while (last_trb(xhci, ring, ring->enq_seg, next)) {
>                if (!consumer) {
>                        if (ring != xhci->event_ring) {
> -                               /* If we're not dealing with 0.95 hardware,
> -                                * carry over the chain bit of the previous TRB
> -                                * (which may mean the chain bit is cleared).
> -                                */
> -                               if (!xhci_link_trb_quirk(xhci)) {
> -                                       next->link.control &= ~TRB_CHAIN;
> -                                       next->link.control |= chain;
> +                               if (chain) {
> +                                       next->link.control |= TRB_CHAIN;
> +
> +                                       /* Give this link TRB to the hardware */
> +                                       wmb();
> +                                       next->link.control ^= TRB_CYCLE;
> +                               } else {
> +                                       break;
>                                }
> -                               /* Give this link TRB to the hardware */
> -                               wmb();
> -                               if (next->link.control & TRB_CYCLE)
> -                                       next->link.control &= (u32) ~TRB_CYCLE;
> -                               else
> -                                       next->link.control |= (u32) TRB_CYCLE;
>                        }
>                        /* Toggle the cycle bit after the last ring segment. */
>                        if (last_trb_on_last_seg(xhci, ring, ring->enq_seg, next)) {
> @@ -243,6 +244,13 @@ static int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring,
>        union xhci_trb *enq = ring->enqueue;
>        struct xhci_segment *enq_seg = ring->enq_seg;
>
> +       /* If we are currently pointing to a link TRB, advance the
> +        * enqueue pointer before checking for space */

Please see Documentation/CodingStyle for multi-line comments.

> +       while (last_trb(xhci, ring, enq_seg, enq)) {
> +               enq_seg = enq_seg->next;
> +               enq = enq_seg->trbs;
> +       }
> +
>        /* Check if ring is empty */
>        if (enq == ring->dequeue)
>                return 1;
> @@ -1703,6 +1711,43 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
>                xhci_err(xhci, "ERROR no room on ep ring\n");
>                return -ENOMEM;
>        }
> +
> +       if (enqueue_is_link_trb(ep_ring)) {
> +               struct xhci_ring *ring = ep_ring;
> +               union xhci_trb *next;
> +               unsigned long long addr;
> +
> +               xhci_dbg(xhci, "prepare_ring: pointing to link trb\n");
> +               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.
> +                        */

Same here.

> +                       if (!xhci_link_trb_quirk(xhci))
> +                               next->link.control &= ~TRB_CHAIN;
> +                       else
> +                               next->link.control |= TRB_CHAIN;
> +
> +                       wmb();
> +                       next->link.control ^= (u32) TRB_CYCLE;
> +
> +                       /* Toggle the cycle bit after the last ring segment. */
> +                       if (last_trb_on_last_seg(xhci, ring, ring->enq_seg, next)) {
> +                               ring->cycle_state = (ring->cycle_state ? 0 : 1);
> +                               if (!in_interrupt()) {
> +                                       xhci_dbg(xhci, "queue_trb: Toggle cycle "
> +                                               "state for ring %p = %i\n",
> +                                               ring, (unsigned int)ring->cycle_state);
> +                               }
> +                       }
> +                       ring->enq_seg = ring->enq_seg->next;
> +                       ring->enqueue = ring->enq_seg->trbs;
> +                       next = ring->enqueue;
> +               }
> +       }
> +
>        return 0;
>  }
>
> --
> 1.6.6.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux