.. | .. |
---|
277 | 277 | trace_xhci_inc_enq(ring); |
---|
278 | 278 | } |
---|
279 | 279 | |
---|
| 280 | +static int xhci_num_trbs_to(struct xhci_segment *start_seg, union xhci_trb *start, |
---|
| 281 | + struct xhci_segment *end_seg, union xhci_trb *end, |
---|
| 282 | + unsigned int num_segs) |
---|
| 283 | +{ |
---|
| 284 | + union xhci_trb *last_on_seg; |
---|
| 285 | + int num = 0; |
---|
| 286 | + int i = 0; |
---|
| 287 | + |
---|
| 288 | + do { |
---|
| 289 | + if (start_seg == end_seg && end >= start) |
---|
| 290 | + return num + (end - start); |
---|
| 291 | + last_on_seg = &start_seg->trbs[TRBS_PER_SEGMENT - 1]; |
---|
| 292 | + num += last_on_seg - start; |
---|
| 293 | + start_seg = start_seg->next; |
---|
| 294 | + start = start_seg->trbs; |
---|
| 295 | + } while (i++ <= num_segs); |
---|
| 296 | + |
---|
| 297 | + return -EINVAL; |
---|
| 298 | +} |
---|
| 299 | + |
---|
280 | 300 | /* |
---|
281 | 301 | * Check to see if there's room to enqueue num_trbs on the ring and make sure |
---|
282 | 302 | * enqueue pointer will not advance into dequeue segment. See rules above. |
---|
.. | .. |
---|
1182 | 1202 | struct xhci_virt_ep *ep; |
---|
1183 | 1203 | struct xhci_ring *ring; |
---|
1184 | 1204 | |
---|
1185 | | - ep = &xhci->devs[slot_id]->eps[ep_index]; |
---|
| 1205 | + ep = xhci_get_virt_ep(xhci, slot_id, ep_index); |
---|
| 1206 | + if (!ep) |
---|
| 1207 | + return; |
---|
| 1208 | + |
---|
1186 | 1209 | if ((ep->ep_state & EP_HAS_STREAMS) || |
---|
1187 | 1210 | (ep->ep_state & EP_GETTING_NO_STREAMS)) { |
---|
1188 | 1211 | int stream_id; |
---|
.. | .. |
---|
2198 | 2221 | u32 trb_comp_code) |
---|
2199 | 2222 | { |
---|
2200 | 2223 | struct xhci_ep_ctx *ep_ctx; |
---|
| 2224 | + int trbs_freed; |
---|
2201 | 2225 | |
---|
2202 | 2226 | ep_ctx = xhci_get_ep_ctx(xhci, ep->vdev->out_ctx, ep->ep_index); |
---|
2203 | 2227 | |
---|
.. | .. |
---|
2269 | 2293 | } |
---|
2270 | 2294 | |
---|
2271 | 2295 | /* Update ring dequeue pointer */ |
---|
| 2296 | + trbs_freed = xhci_num_trbs_to(ep_ring->deq_seg, ep_ring->dequeue, |
---|
| 2297 | + td->last_trb_seg, td->last_trb, |
---|
| 2298 | + ep_ring->num_segs); |
---|
| 2299 | + if (trbs_freed < 0) |
---|
| 2300 | + xhci_dbg(xhci, "Failed to count freed trbs at TD finish\n"); |
---|
| 2301 | + else |
---|
| 2302 | + ep_ring->num_trbs_free += trbs_freed; |
---|
2272 | 2303 | ep_ring->dequeue = td->last_trb; |
---|
2273 | 2304 | ep_ring->deq_seg = td->last_trb_seg; |
---|
2274 | | - ep_ring->num_trbs_free += td->num_trbs - 1; |
---|
2275 | 2305 | inc_deq(xhci, ep_ring); |
---|
2276 | 2306 | |
---|
2277 | 2307 | return xhci_td_cleanup(xhci, td, ep_ring, td->status); |
---|