- patches.drivers/0001-xHCI-Fix-TD-Size-calculation-on-1.0-hosts.patch:
[opensuse:kernel-source.git] / patches.drivers / 0001-xHCI-Fix-TD-Size-calculation-on-1.0-hosts.patch
1 From e315ef6735ca3c926c9f18f9906b2566cc569abb Mon Sep 17 00:00:00 2001
2 From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
3 Date: Thu, 25 Oct 2012 15:56:40 -0700
4 Subject: [PATCH] xHCI: Fix TD Size calculation on 1.0 hosts.
5 References: bnc#795957
6 Git-Commit: 4525c0a10dff7ad3669763c28016c7daffc3900e
7 Patch-Mainline: v3.8
8
9 The xHCI 1.0 specification made a change to the TD Size field in TRBs.
10 The value is now the number of packets that remain to be sent in the TD,
11 not including this TRB.  The TD Size value for the last TRB in a TD must
12 always be zero.
13
14 The xHCI function xhci_v1_0_td_remainder() attempts to calculate this,
15 but it gets it wrong.  First, it erroneously reuses the old
16 xhci_td_remainder function, which will right shift the value by 10.  The
17 xHCI 1.0 spec as of June 2011 says nothing about right shifting by 10.
18 Second, it does not set the TD size for the last TRB in a TD to zero.
19
20 Third, it uses roundup instead of DIV_ROUND_UP.  The total packet count
21 is supposed to be the total number of bytes in this TD, divided by the
22 max packet size, rounded up.  DIV_ROUND_UP is the right function to use
23 in that case.
24
25 With the old code, a TD on an endpoint with max packet size 1024 would
26 be set up like so:
27 TRB 1, TRB length = 600 bytes, TD size = 0
28 TRB 1, TRB length = 200 bytes, TD size = 0
29 TRB 1, TRB length = 100 bytes, TD size = 0
30
31 With the new code, the TD would be set up like this:
32 TRB 1, TRB length = 600 bytes, TD size = 1
33 TRB 1, TRB length = 200 bytes, TD size = 1
34 TRB 1, TRB length = 100 bytes, TD size = 0
35
36 This commit should be backported to kernels as old as 3.0, that contain
37 the commit 4da6e6f247a2601ab9f1e63424e4d944ed4124f3 "xhci 1.0: Update TD
38 size field format."
39
40 Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
41 Reported-by: Chintan Mehta <chintan.mehta@sibridgetech.com>
42 Reported-by: Shimmer Huang <shimmering.h@gmail.com>
43 Tested-by: Bhavik Kothari <bhavik.kothari@sibridgetech.com>
44 Tested-by: Shimmer Huang <shimmering.h@gmail.com>
45 Signed-off-by: Oliver Neukum <oneukum@suse.de>
46 Cc: stable@vger.kernel.org
47 ---
48  drivers/usb/host/xhci-ring.c |   32 +++++++++++++++++++-------------
49  1 file changed, 19 insertions(+), 13 deletions(-)
50
51 diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
52 index 61d85a2..ef6fcd8 100644
53 --- a/drivers/usb/host/xhci-ring.c
54 +++ b/drivers/usb/host/xhci-ring.c
55 @@ -3054,11 +3054,11 @@ static u32 xhci_td_remainder(unsigned int remainder)
56  }
57  
58  /*
59 - * For xHCI 1.0 host controllers, TD size is the number of packets remaining in
60 - * the TD (*not* including this TRB).
61 + * For xHCI 1.0 host controllers, TD size is the number of max packet sized
62 + * packets remaining in the TD (*not* including this TRB).
63   *
64   * Total TD packet count = total_packet_count =
65 - *     roundup(TD size in bytes / wMaxPacketSize)
66 + *     DIV_ROUND_UP(TD size in bytes / wMaxPacketSize)
67   *
68   * Packets transferred up to and including this TRB = packets_transferred =
69   *     rounddown(total bytes transferred including this TRB / wMaxPacketSize)
70 @@ -3066,15 +3066,16 @@ static u32 xhci_td_remainder(unsigned int remainder)
71   * TD size = total_packet_count - packets_transferred
72   *
73   * It must fit in bits 21:17, so it can't be bigger than 31.
74 + * The last TRB in a TD must have the TD size set to zero.
75   */
76 -
77  static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len,
78 -               unsigned int total_packet_count, struct urb *urb)
79 +               unsigned int total_packet_count, struct urb *urb,
80 +               unsigned int num_trbs_left)
81  {
82         int packets_transferred;
83  
84         /* One TRB with a zero-length data packet. */
85 -       if (running_total == 0 && trb_buff_len == 0)
86 +       if (num_trbs_left == 0 || (running_total == 0 && trb_buff_len == 0))
87                 return 0;
88  
89         /* All the TRB queueing functions don't count the current TRB in
90 @@ -3083,7 +3084,9 @@ static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len,
91         packets_transferred = (running_total + trb_buff_len) /
92                 usb_endpoint_maxp(&urb->ep->desc);
93  
94 -       return xhci_td_remainder(total_packet_count - packets_transferred);
95 +       if ((total_packet_count - packets_transferred) > 31)
96 +               return 31 << 17;
97 +       return (total_packet_count - packets_transferred) << 17;
98  }
99  
100  static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
101 @@ -3110,7 +3113,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
102  
103         num_trbs = count_sg_trbs_needed(xhci, urb);
104         num_sgs = urb->num_mapped_sgs;
105 -       total_packet_count = roundup(urb->transfer_buffer_length,
106 +       total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length,
107                         usb_endpoint_maxp(&urb->ep->desc));
108  
109         trb_buff_len = prepare_transfer(xhci, xhci->devs[slot_id],
110 @@ -3200,7 +3203,8 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
111                                         running_total);
112                 } else {
113                         remainder = xhci_v1_0_td_remainder(running_total,
114 -                                       trb_buff_len, total_packet_count, urb);
115 +                                       trb_buff_len, total_packet_count, urb,
116 +                                       num_trbs - 1);
117                 }
118                 length_field = TRB_LEN(trb_buff_len) |
119                         remainder |
120 @@ -3317,7 +3321,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
121         start_cycle = ep_ring->cycle_state;
122  
123         running_total = 0;
124 -       total_packet_count = roundup(urb->transfer_buffer_length,
125 +       total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length,
126                         usb_endpoint_maxp(&urb->ep->desc));
127         /* How much data is in the first TRB? */
128         addr = (u64) urb->transfer_dma;
129 @@ -3363,7 +3367,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
130                                         running_total);
131                 } else {
132                         remainder = xhci_v1_0_td_remainder(running_total,
133 -                                       trb_buff_len, total_packet_count, urb);
134 +                                       trb_buff_len, total_packet_count, urb,
135 +                                       num_trbs - 1);
136                 }
137                 length_field = TRB_LEN(trb_buff_len) |
138                         remainder |
139 @@ -3638,7 +3643,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
140                 addr = start_addr + urb->iso_frame_desc[i].offset;
141                 td_len = urb->iso_frame_desc[i].length;
142                 td_remain_len = td_len;
143 -               total_packet_count = roundup(td_len,
144 +               total_packet_count = DIV_ROUND_UP(td_len,
145                                 usb_endpoint_maxp(&urb->ep->desc));
146                 /* A zero-length transfer still involves at least one packet. */
147                 if (total_packet_count == 0)
148 @@ -3718,7 +3723,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
149                         } else {
150                                 remainder = xhci_v1_0_td_remainder(
151                                                 running_total, trb_buff_len,
152 -                                               total_packet_count, urb);
153 +                                               total_packet_count, urb,
154 +                                               (trbs_per_td - j - 1));
155                         }
156                         length_field = TRB_LEN(trb_buff_len) |
157                                 remainder |
158 -- 
159 1.7.10.4
160