aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/dwc2/hcd.h
diff options
context:
space:
mode:
authorDouglas Anderson <dianders@chromium.org>2016-01-28 21:20:12 -0500
committerFelipe Balbi <balbi@kernel.org>2016-03-04 08:14:45 -0500
commit9f9f09b048f5fdfded26149defd61b737b314ba0 (patch)
tree934d7d7ccbcf1e53d7fbc3a01418eb62fbfcb4ca /drivers/usb/dwc2/hcd.h
parent9cf1a601d2affe9c2633ac47ac875c035dd1eb69 (diff)
usb: dwc2: host: Totally redo the microframe scheduler
This totally reimplements the microframe scheduler in dwc2 to attempt to handle periodic splits properly. The old code didn't even try, so this was a significant effort since periodic splits are one of the most complicated things in USB. I've attempted to keep the old "don't use the microframe" schduler around for now, but not sure it's needed. It has also only been lightly tested. I think it's pretty certain that this scheduler isn't perfect and might have some bugs, but it seems much better than what was there before. With this change my stressful USB test (USB webcam + USB audio + some keyboards) crackles less. Acked-by: John Youn <johnyoun@synopsys.com> Signed-off-by: Douglas Anderson <dianders@chromium.org> Tested-by: Heiko Stuebner <heiko@sntech.de> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Signed-off-by: Felipe Balbi <balbi@kernel.org>
Diffstat (limited to 'drivers/usb/dwc2/hcd.h')
-rw-r--r--drivers/usb/dwc2/hcd.h79
1 files changed, 73 insertions, 6 deletions
diff --git a/drivers/usb/dwc2/hcd.h b/drivers/usb/dwc2/hcd.h
index fd266ac53a28..140b1511a131 100644
--- a/drivers/usb/dwc2/hcd.h
+++ b/drivers/usb/dwc2/hcd.h
@@ -212,6 +212,43 @@ enum dwc2_transaction_type {
212 DWC2_TRANSACTION_ALL, 212 DWC2_TRANSACTION_ALL,
213}; 213};
214 214
215/* The number of elements per LS bitmap (per port on multi_tt) */
216#define DWC2_ELEMENTS_PER_LS_BITMAP DIV_ROUND_UP(DWC2_LS_SCHEDULE_SLICES, \
217 BITS_PER_LONG)
218
219/**
220 * struct dwc2_tt - dwc2 data associated with a usb_tt
221 *
222 * @refcount: Number of Queue Heads (QHs) holding a reference.
223 * @usb_tt: Pointer back to the official usb_tt.
224 * @periodic_bitmaps: Bitmap for which parts of the 1ms frame are accounted
225 * for already. Each is DWC2_ELEMENTS_PER_LS_BITMAP
226 * elements (so sizeof(long) times that in bytes).
227 *
228 * This structure is stored in the hcpriv of the official usb_tt.
229 */
230struct dwc2_tt {
231 int refcount;
232 struct usb_tt *usb_tt;
233 unsigned long periodic_bitmaps[];
234};
235
236/**
237 * struct dwc2_hs_transfer_time - Info about a transfer on the high speed bus.
238 *
239 * @start_schedule_usecs: The start time on the main bus schedule. Note that
240 * the main bus schedule is tightly packed and this
241 * time should be interpreted as tightly packed (so
242 * uFrame 0 starts at 0 us, uFrame 1 starts at 100 us
243 * instead of 125 us).
244 * @duration_us: How long this transfer goes.
245 */
246
247struct dwc2_hs_transfer_time {
248 u32 start_schedule_us;
249 u16 duration_us;
250};
251
215/** 252/**
216 * struct dwc2_qh - Software queue head structure 253 * struct dwc2_qh - Software queue head structure
217 * 254 *
@@ -237,18 +274,33 @@ enum dwc2_transaction_type {
237 * @td_first: Index of first activated isochronous transfer descriptor 274 * @td_first: Index of first activated isochronous transfer descriptor
238 * @td_last: Index of last activated isochronous transfer descriptor 275 * @td_last: Index of last activated isochronous transfer descriptor
239 * @host_us: Bandwidth in microseconds per transfer as seen by host 276 * @host_us: Bandwidth in microseconds per transfer as seen by host
277 * @device_us: Bandwidth in microseconds per transfer as seen by device
240 * @host_interval: Interval between transfers as seen by the host. If 278 * @host_interval: Interval between transfers as seen by the host. If
241 * the host is high speed and the device is low speed this 279 * the host is high speed and the device is low speed this
242 * will be 8 times device interval. 280 * will be 8 times device interval.
243 * @next_active_frame: (Micro)frame before we next need to put something on 281 * @device_interval: Interval between transfers as seen by the device.
282 * interval.
283 * @next_active_frame: (Micro)frame _before_ we next need to put something on
244 * the bus. We'll move the qh to active here. If the 284 * the bus. We'll move the qh to active here. If the
245 * host is in high speed mode this will be a uframe. If 285 * host is in high speed mode this will be a uframe. If
246 * the host is in low speed mode this will be a full frame. 286 * the host is in low speed mode this will be a full frame.
247 * @start_active_frame: If we are partway through a split transfer, this will be 287 * @start_active_frame: If we are partway through a split transfer, this will be
248 * what next_active_frame was when we started. Otherwise 288 * what next_active_frame was when we started. Otherwise
249 * it should always be the same as next_active_frame. 289 * it should always be the same as next_active_frame.
250 * @assigned_uframe: The uframe (0 -7) assigned by dwc2_find_uframe(). 290 * @num_hs_transfers: Number of transfers in hs_transfers.
251 * @frame_usecs: Internal variable used by the microframe scheduler 291 * Normally this is 1 but can be more than one for splits.
292 * Always >= 1 unless the host is in low/full speed mode.
293 * @hs_transfers: Transfers that are scheduled as seen by the high speed
294 * bus. Not used if host is in low or full speed mode (but
295 * note that it IS USED if the device is low or full speed
296 * as long as the HOST is in high speed mode).
297 * @ls_start_schedule_slice: Start time (in slices) on the low speed bus
298 * schedule that's being used by this device. This
299 * will be on the periodic_bitmap in a
300 * "struct dwc2_tt". Not used if this device is high
301 * speed. Note that this is in "schedule slice" which
302 * is tightly packed.
303 * @ls_duration_us: Duration on the low speed bus schedule.
252 * @ntd: Actual number of transfer descriptors in a list 304 * @ntd: Actual number of transfer descriptors in a list
253 * @qtd_list: List of QTDs for this QH 305 * @qtd_list: List of QTDs for this QH
254 * @channel: Host channel currently processing transfers for this QH 306 * @channel: Host channel currently processing transfers for this QH
@@ -261,8 +313,12 @@ enum dwc2_transaction_type {
261 * descriptor and indicates original XferSize value for the 313 * descriptor and indicates original XferSize value for the
262 * descriptor 314 * descriptor
263 * @unreserve_timer: Timer for releasing periodic reservation. 315 * @unreserve_timer: Timer for releasing periodic reservation.
316 * @dwc2_tt: Pointer to our tt info (or NULL if no tt).
317 * @ttport: Port number within our tt.
264 * @tt_buffer_dirty True if clear_tt_buffer_complete is pending 318 * @tt_buffer_dirty True if clear_tt_buffer_complete is pending
265 * @unreserve_pending: True if we planned to unreserve but haven't yet. 319 * @unreserve_pending: True if we planned to unreserve but haven't yet.
320 * @schedule_low_speed: True if we have a low/full speed component (either the
321 * host is in low/full speed mode or do_split).
266 * 322 *
267 * A Queue Head (QH) holds the static characteristics of an endpoint and 323 * A Queue Head (QH) holds the static characteristics of an endpoint and
268 * maintains a list of transfers (QTDs) for that endpoint. A QH structure may 324 * maintains a list of transfers (QTDs) for that endpoint. A QH structure may
@@ -280,11 +336,14 @@ struct dwc2_qh {
280 u8 td_first; 336 u8 td_first;
281 u8 td_last; 337 u8 td_last;
282 u16 host_us; 338 u16 host_us;
339 u16 device_us;
283 u16 host_interval; 340 u16 host_interval;
341 u16 device_interval;
284 u16 next_active_frame; 342 u16 next_active_frame;
285 u16 start_active_frame; 343 u16 start_active_frame;
286 u16 assigned_uframe; 344 s16 num_hs_transfers;
287 u16 frame_usecs[8]; 345 struct dwc2_hs_transfer_time hs_transfers[DWC2_HS_SCHEDULE_UFRAMES];
346 u32 ls_start_schedule_slice;
288 u16 ntd; 347 u16 ntd;
289 struct list_head qtd_list; 348 struct list_head qtd_list;
290 struct dwc2_host_chan *channel; 349 struct dwc2_host_chan *channel;
@@ -294,8 +353,11 @@ struct dwc2_qh {
294 u32 desc_list_sz; 353 u32 desc_list_sz;
295 u32 *n_bytes; 354 u32 *n_bytes;
296 struct timer_list unreserve_timer; 355 struct timer_list unreserve_timer;
356 struct dwc2_tt *dwc_tt;
357 int ttport;
297 unsigned tt_buffer_dirty:1; 358 unsigned tt_buffer_dirty:1;
298 unsigned unreserve_pending:1; 359 unsigned unreserve_pending:1;
360 unsigned schedule_low_speed:1;
299}; 361};
300 362
301/** 363/**
@@ -462,7 +524,6 @@ extern void dwc2_hcd_queue_transactions(struct dwc2_hsotg *hsotg,
462 524
463/* Schedule Queue Functions */ 525/* Schedule Queue Functions */
464/* Implemented in hcd_queue.c */ 526/* Implemented in hcd_queue.c */
465extern void dwc2_hcd_init_usecs(struct dwc2_hsotg *hsotg);
466extern struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg, 527extern struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg,
467 struct dwc2_hcd_urb *urb, 528 struct dwc2_hcd_urb *urb,
468 gfp_t mem_flags); 529 gfp_t mem_flags);
@@ -728,6 +789,12 @@ extern void dwc2_host_start(struct dwc2_hsotg *hsotg);
728extern void dwc2_host_disconnect(struct dwc2_hsotg *hsotg); 789extern void dwc2_host_disconnect(struct dwc2_hsotg *hsotg);
729extern void dwc2_host_hub_info(struct dwc2_hsotg *hsotg, void *context, 790extern void dwc2_host_hub_info(struct dwc2_hsotg *hsotg, void *context,
730 int *hub_addr, int *hub_port); 791 int *hub_addr, int *hub_port);
792extern struct dwc2_tt *dwc2_host_get_tt_info(struct dwc2_hsotg *hsotg,
793 void *context, gfp_t mem_flags,
794 int *ttport);
795
796extern void dwc2_host_put_tt_info(struct dwc2_hsotg *hsotg,
797 struct dwc2_tt *dwc_tt);
731extern int dwc2_host_get_speed(struct dwc2_hsotg *hsotg, void *context); 798extern int dwc2_host_get_speed(struct dwc2_hsotg *hsotg, void *context);
732extern void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, 799extern void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
733 int status); 800 int status);