ehci-q.c 29.8 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
/*
David Brownell's avatar
USB  
David Brownell committed
2
 * Copyright (c) 2001-2002 by David Brownell
Linus Torvalds's avatar
Linus Torvalds committed
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 * 
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/* this file is part of ehci-hcd.c */

/*-------------------------------------------------------------------------*/

/*
24
 * EHCI hardware queue manipulation ... the core.  QH/QTD manipulation.
Linus Torvalds's avatar
Linus Torvalds committed
25 26 27 28
 *
 * Control, bulk, and interrupt traffic all use "qh" lists.  They list "qtd"
 * entries describing USB transactions, max 16-20kB/entry (with 4kB-aligned
 * buffers needed for the larger number).  We use one QH per endpoint, queue
David Brownell's avatar
David Brownell committed
29
 * multiple urbs (all three types) per endpoint.  URBs may need several qtds.
Linus Torvalds's avatar
Linus Torvalds committed
30 31 32
 *
 * ISO traffic uses "ISO TD" (itd, and sitd) records, and (along with
 * interrupts) needs careful scheduling.  Performance improvements can be
33
 * an ongoing challenge.  That's in "ehci-sched.c".
Linus Torvalds's avatar
Linus Torvalds committed
34 35 36 37 38 39 40 41 42 43 44 45
 * 
 * USB 1.1 devices are handled (a) by "companion" OHCI or UHCI root hubs,
 * or otherwise through transaction translators (TTs) in USB 2.0 hubs using
 * (b) special fields in qh entries or (c) split iso entries.  TTs will
 * buffer low/full speed data so the host collects it at high speed.
 */

/*-------------------------------------------------------------------------*/

/* fill a qtd, returning how much of the buffer we were able to queue up */

static int
46 47
qtd_fill (struct ehci_qtd *qtd, dma_addr_t buf, size_t len,
		int token, int maxpacket)
Linus Torvalds's avatar
Linus Torvalds committed
48 49
{
	int	i, count;
David Brownell's avatar
David Brownell committed
50
	u64	addr = buf;
Linus Torvalds's avatar
Linus Torvalds committed
51 52

	/* one buffer entry per 4K ... first might be short or unaligned */
David Brownell's avatar
David Brownell committed
53 54
	qtd->hw_buf [0] = cpu_to_le32 ((u32)addr);
	qtd->hw_buf_hi [0] = cpu_to_le32 ((u32)(addr >> 32));
Linus Torvalds's avatar
Linus Torvalds committed
55 56 57 58 59 60 61 62 63
	count = 0x1000 - (buf & 0x0fff);	/* rest of that page */
	if (likely (len < count))		/* ... iff needed */
		count = len;
	else {
		buf +=  0x1000;
		buf &= ~0x0fff;

		/* per-qtd limit: from 16K to 20K (best alignment) */
		for (i = 1; count < len && i < 5; i++) {
David Brownell's avatar
David Brownell committed
64
			addr = buf;
Linus Torvalds's avatar
Linus Torvalds committed
65 66 67 68 69 70 71 72
			qtd->hw_buf [i] = cpu_to_le32 ((u32)addr);
			qtd->hw_buf_hi [i] = cpu_to_le32 ((u32)(addr >> 32));
			buf += 0x1000;
			if ((count + 0x1000) < len)
				count += 0x1000;
			else
				count = len;
		}
73 74 75 76

		/* short packets may only terminate transfers */
		if (count != len)
			count -= (count % maxpacket);
Linus Torvalds's avatar
Linus Torvalds committed
77 78 79 80 81 82 83 84 85 86 87
	}
	qtd->hw_token = cpu_to_le32 ((count << 16) | token);
	qtd->length = count;

	return count;
}

/*-------------------------------------------------------------------------*/

/* update halted (but potentially linked) qh */

88
static inline void
89
qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
Linus Torvalds's avatar
Linus Torvalds committed
90 91
{
	qh->hw_qtd_next = QTD_NEXT (qtd->qtd_dma);
92
	qh->hw_alt_next = EHCI_LIST_END;
Linus Torvalds's avatar
Linus Torvalds committed
93 94

	/* HC must see latest qtd and qh data before we clear ACTIVE+HALT */
95
	wmb ();
Linus Torvalds's avatar
Linus Torvalds committed
96 97 98 99 100
	qh->hw_token &= __constant_cpu_to_le32 (QTD_TOGGLE | QTD_STS_PING);
}

/*-------------------------------------------------------------------------*/

101
static void qtd_copy_status (
102 103 104 105 106
	struct ehci_hcd *ehci,
	struct urb *urb,
	size_t length,
	u32 token
)
Linus Torvalds's avatar
Linus Torvalds committed
107 108 109 110 111 112
{
	/* count IN/OUT bytes, not SETUP (even short packets) */
	if (likely (QTD_PID (token) != 2))
		urb->actual_length += length - QTD_LENGTH (token);

	/* don't modify error codes */
113 114 115 116 117 118 119 120 121
	if (unlikely (urb->status != -EINPROGRESS))
		return;

	/* force cleanup after short read; not always an error */
	if (unlikely (IS_SHORT_READ (token)))
		urb->status = -EREMOTEIO;

	/* serious "can't proceed" faults reported by the hardware */
	if (token & QTD_STS_HALT) {
Linus Torvalds's avatar
Linus Torvalds committed
122
		if (token & QTD_STS_BABBLE) {
123
			/* FIXME "must" disable babbling device's port too */
Linus Torvalds's avatar
Linus Torvalds committed
124
			urb->status = -EOVERFLOW;
125 126 127 128 129 130 131 132 133 134
		} else if (token & QTD_STS_MMF) {
			/* fs/ls interrupt xfer missed the complete-split */
			urb->status = -EPROTO;
		} else if (token & QTD_STS_DBE) {
			urb->status = (QTD_PID (token) == 1) /* IN ? */
				? -ENOSR  /* hc couldn't read data */
				: -ECOMM; /* hc couldn't write data */
		} else if (token & QTD_STS_XACT) {
			/* timeout, bad crc, wrong PID, etc; retried */
			if (QTD_CERR (token))
Linus Torvalds's avatar
Linus Torvalds committed
135
				urb->status = -EPIPE;
136
			else {
137 138 139 140
				ehci_dbg (ehci, "devpath %s ep%d%s 3strikes\n",
					urb->dev->devpath,
					usb_pipeendpoint (urb->pipe),
					usb_pipein (urb->pipe) ? "in" : "out");
141 142 143 144
				urb->status = -EPROTO;
			}
		/* CERR nonzero + no errors + halt --> stall */
		} else if (QTD_CERR (token))
Linus Torvalds's avatar
Linus Torvalds committed
145 146 147
			urb->status = -EPIPE;
		else	/* unknown */
			urb->status = -EPROTO;
148

149 150
		ehci_vdbg (ehci,
			"dev%d ep%d%s qtd token %08x --> status %d\n",
151
			usb_pipedevice (urb->pipe),
Linus Torvalds's avatar
Linus Torvalds committed
152
			usb_pipeendpoint (urb->pipe),
Linus Torvalds's avatar
Linus Torvalds committed
153 154 155 156 157 158 159 160 161 162 163
			usb_pipein (urb->pipe) ? "in" : "out",
			token, urb->status);

		/* stall indicates some recovery action is needed */
		if (urb->status == -EPIPE) {
			int	pipe = urb->pipe;

			if (!usb_pipecontrol (pipe))
				usb_endpoint_halt (urb->dev,
					usb_pipeendpoint (pipe),
					usb_pipeout (pipe));
164 165 166

		/* if async CSPLIT failed, try cleaning out the TT buffer */
		} else if (urb->dev->tt && !usb_pipeint (urb->pipe)
167
				&& ((token & QTD_STS_MMF) != 0
168 169 170 171
					|| QTD_CERR(token) == 0)
				&& (!ehci_is_ARC(ehci)
                	                || urb->dev->tt->hub !=
						ehci->hcd.self.root_hub)) {
172
#ifdef DEBUG
173 174 175 176 177
			struct usb_device *tt = urb->dev->tt->hub;
			dev_dbg (&tt->dev,
				"clear tt buffer port %d, a%d ep%d t%08x\n",
				urb->dev->ttport, urb->dev->devnum,
				usb_pipeendpoint (urb->pipe), token);
178
#endif /* DEBUG */
179
			usb_hub_tt_clear_buffer (urb->dev, urb->pipe);
Linus Torvalds's avatar
Linus Torvalds committed
180 181 182 183
		}
	}
}

184 185
static void
ehci_urb_done (struct ehci_hcd *ehci, struct urb *urb, struct pt_regs *regs)
David Brownell's avatar
David Brownell committed
186
{
Linus Torvalds's avatar
Linus Torvalds committed
187
	if (likely (urb->hcpriv != 0)) {
188 189 190
		struct ehci_qh	*qh = (struct ehci_qh *) urb->hcpriv;

		/* S-mask in a QH means it's an interrupt urb */
191
		if ((qh->hw_info2 & __constant_cpu_to_le32 (0x00ff)) != 0) {
192 193

			/* ... update hc-wide periodic stats (for usbfs) */
194
			hcd_to_bus (&ehci->hcd)->bandwidth_int_reqs--;
195 196
		}
		qh_put (ehci, qh);
Linus Torvalds's avatar
Linus Torvalds committed
197 198
	}

199 200
	spin_lock (&urb->lock);
	urb->hcpriv = 0;
201 202 203 204 205 206 207 208
	switch (urb->status) {
	case -EINPROGRESS:		/* success */
		urb->status = 0;
	default:			/* fault */
		COUNT (ehci->stats.complete);
		break;
	case -EREMOTEIO:		/* fault or normal */
		if (!(urb->transfer_flags & URB_SHORT_NOT_OK))
Linus Torvalds's avatar
Linus Torvalds committed
209
			urb->status = 0;
David Brownell's avatar
David Brownell committed
210
		COUNT (ehci->stats.complete);
211 212 213
		break;
	case -ECONNRESET:		/* canceled */
	case -ENOENT:
David Brownell's avatar
David Brownell committed
214
		COUNT (ehci->stats.unlink);
215 216
		break;
	}
217
	spin_unlock (&urb->lock);
David Brownell's avatar
David Brownell committed
218

219 220 221 222 223 224 225 226 227 228
#ifdef EHCI_URB_TRACE
	ehci_dbg (ehci,
		"%s %s urb %p ep%d%s status %d len %d/%d\n",
		__FUNCTION__, urb->dev->devpath, urb,
		usb_pipeendpoint (urb->pipe),
		usb_pipein (urb->pipe) ? "in" : "out",
		urb->status,
		urb->actual_length, urb->transfer_buffer_length);
#endif

David Brownell's avatar
David Brownell committed
229
	/* complete() can reenter this HCD */
David Brownell's avatar
David Brownell committed
230
	spin_unlock (&ehci->lock);
231
	usb_hcd_giveback_urb (&ehci->hcd, urb, regs);
David Brownell's avatar
David Brownell committed
232
	spin_lock (&ehci->lock);
Linus Torvalds's avatar
Linus Torvalds committed
233 234 235 236
}


/*
David Brownell's avatar
David Brownell committed
237
 * Process and free completed qtds for a qh, returning URBs to drivers.
David Brownell's avatar
David Brownell committed
238 239
 * Chases up to qh->hw_current.  Returns number of completions called,
 * indicating how much "real" work we did.
Linus Torvalds's avatar
Linus Torvalds committed
240
 */
241
#define HALT_BIT __constant_cpu_to_le32(QTD_STS_HALT)
David Brownell's avatar
David Brownell committed
242
static unsigned
243
qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh, struct pt_regs *regs)
244
{
245
	struct ehci_qtd		*last = 0, *end = qh->dummy;
246
	struct list_head	*entry, *tmp;
247
	int			stopped;
David Brownell's avatar
David Brownell committed
248
	unsigned		count = 0;
249 250
	int			do_status = 0;
	u8			state;
Linus Torvalds's avatar
Linus Torvalds committed
251

252
	if (unlikely (list_empty (&qh->qtd_list)))
David Brownell's avatar
David Brownell committed
253
		return count;
Linus Torvalds's avatar
Linus Torvalds committed
254

255 256 257 258 259 260 261 262 263 264
	/* completions (or tasks on other cpus) must never clobber HALT
	 * till we've gone through and cleaned everything up, even when
	 * they add urbs to this qh's queue or mark them for unlinking.
	 *
	 * NOTE:  unlinking expects to be done in queue order.
	 */
	state = qh->qh_state;
	qh->qh_state = QH_STATE_COMPLETING;
	stopped = (state == QH_STATE_IDLE);

265 266 267 268 269 270 271 272
	/* remove de-activated QTDs from front of queue.
	 * after faults (including short reads), cleanup this urb
	 * then let the queue advance.
	 * if queue is stopped, handles unlinks.
	 */
	list_for_each_safe (entry, tmp, &qh->qtd_list) {
		struct ehci_qtd	*qtd;
		struct urb	*urb;
Linus Torvalds's avatar
Linus Torvalds committed
273 274
		u32		token = 0;

275 276 277
		qtd = list_entry (entry, struct ehci_qtd, qtd_list);
		urb = qtd->urb;

Linus Torvalds's avatar
Linus Torvalds committed
278 279
		/* clean up any state from previous QTD ...*/
		if (last) {
David Brownell's avatar
David Brownell committed
280
			if (likely (last->urb != urb)) {
281
				ehci_urb_done (ehci, last->urb, regs);
David Brownell's avatar
David Brownell committed
282 283
				count++;
			}
284
			ehci_qtd_free (ehci, last);
Linus Torvalds's avatar
Linus Torvalds committed
285
			last = 0;
Linus Torvalds's avatar
Linus Torvalds committed
286
		}
Linus Torvalds's avatar
Linus Torvalds committed
287

288 289 290 291
		/* ignore urbs submitted during completions we reported */
		if (qtd == end)
			break;

292
		/* hardware copies qtd out of qh overlay */
293
		rmb ();
294
		token = le32_to_cpu (qtd->hw_token);
Linus Torvalds's avatar
Linus Torvalds committed
295

296 297
		/* always clean up qtds the hc de-activated */
		if ((token & QTD_STS_ACTIVE) == 0) {
298

299 300 301 302 303
			if ((token & QTD_STS_HALT) != 0) {
				stopped = 1;

			/* magic dummy for some short reads; qh won't advance */
			} else if (IS_SHORT_READ (token)
304 305 306
					&& (qh->hw_alt_next & QTD_MASK)
						== ehci->async->hw_alt_next) {
				stopped = 1;
307
				goto halt;
308
			}
Linus Torvalds's avatar
Linus Torvalds committed
309

310
		/* stop scanning when we reach qtds the hc is using */
311
		} else if (likely (!stopped
312
				&& HCD_IS_RUNNING (ehci->hcd.state))) {
313 314 315
			break;

		} else {
316 317
			stopped = 1;

318
			/* ignore active urbs unless some previous qtd
319 320 321
			 * for the urb faulted (including short read) or
			 * its urb was canceled.  we may patch qh or qtds.
			 */
322 323 324 325 326 327 328
			if (likely (urb->status == -EINPROGRESS))
				continue;
			
			/* issue status after short control reads */
			if (unlikely (do_status != 0)
					&& QTD_PID (token) == 0 /* OUT */) {
				do_status = 0;
329 330
				continue;
			}
331 332 333 334 335 336 337 338 339 340 341

			/* token in overlay may be most current */
			if (state == QH_STATE_IDLE
					&& cpu_to_le32 (qtd->qtd_dma)
						== qh->hw_current)
				token = le32_to_cpu (qh->hw_token);

			/* force halt for unlinked or blocked qh, so we'll
			 * patch the qh later and so that completions can't
			 * activate it while we "know" it's stopped.
			 */
342 343 344 345 346 347 348 349
			if ((HALT_BIT & qh->hw_token) == 0) {
halt:
				qh->hw_token |= HALT_BIT;
				wmb ();
			}
		}
 
		/* remove it from the queue */
350
		spin_lock (&urb->lock);
351
		qtd_copy_status (ehci, urb, qtd->length, token);
352 353
		do_status = (urb->status == -EREMOTEIO)
				&& usb_pipecontrol (urb->pipe);
354 355
		spin_unlock (&urb->lock);

356 357 358 359 360
		if (stopped && qtd->qtd_list.prev != &qh->qtd_list) {
			last = list_entry (qtd->qtd_list.prev,
					struct ehci_qtd, qtd_list);
			last->hw_next = qtd->hw_next;
		}
361
		list_del (&qtd->qtd_list);
362
		last = qtd;
Linus Torvalds's avatar
Linus Torvalds committed
363 364
	}

David Brownell's avatar
David Brownell committed
365 366
	/* last urb's completion might still need calling */
	if (likely (last != 0)) {
367
		ehci_urb_done (ehci, last->urb, regs);
David Brownell's avatar
David Brownell committed
368
		count++;
David Brownell's avatar
David Brownell committed
369 370 371
		ehci_qtd_free (ehci, last);
	}

372 373 374
	/* restore original state; caller must unlink or relink */
	qh->qh_state = state;

375
	/* update qh after fault cleanup */
376 377 378
	if (unlikely (stopped != 0)
			/* some EHCI 0.95 impls will overlay dummy qtds */ 
			|| qh->hw_qtd_next == EHCI_LIST_END) {
379 380 381 382 383 384 385 386 387 388 389
		if (list_empty (&qh->qtd_list))
			end = qh->dummy;
		else {
			end = list_entry (qh->qtd_list.next,
					struct ehci_qtd, qtd_list);
			/* first qtd may already be partially processed */
			if (cpu_to_le32 (end->qtd_dma) == qh->hw_current)
				end = 0;
		}
		if (end)
			qh_update (ehci, qh, end);
Linus Torvalds's avatar
Linus Torvalds committed
390 391
	}

David Brownell's avatar
David Brownell committed
392
	return count;
Linus Torvalds's avatar
Linus Torvalds committed
393 394 395 396
}

/*-------------------------------------------------------------------------*/

397 398 399 400 401
// high bandwidth multiplier, as encoded in highspeed endpoint descriptors
#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
// ... and packet size, for any kind of endpoint descriptor
#define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)

402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421
/*
 * reverse of qh_urb_transaction:  free a list of TDs.
 * used for cleanup after errors, before HC sees an URB's TDs.
 */
static void qtd_list_free (
	struct ehci_hcd		*ehci,
	struct urb		*urb,
	struct list_head	*qtd_list
) {
	struct list_head	*entry, *temp;

	list_for_each_safe (entry, temp, qtd_list) {
		struct ehci_qtd	*qtd;

		qtd = list_entry (entry, struct ehci_qtd, qtd_list);
		list_del (&qtd->qtd_list);
		ehci_qtd_free (ehci, qtd);
	}
}

Linus Torvalds's avatar
Linus Torvalds committed
422 423 424 425 426 427 428 429 430 431 432
/*
 * create a list of filled qtds for this URB; won't link into qh.
 */
static struct list_head *
qh_urb_transaction (
	struct ehci_hcd		*ehci,
	struct urb		*urb,
	struct list_head	*head,
	int			flags
) {
	struct ehci_qtd		*qtd, *qtd_prev;
433
	dma_addr_t		buf;
Linus Torvalds's avatar
Linus Torvalds committed
434
	int			len, maxpacket;
435
	int			is_input;
Linus Torvalds's avatar
Linus Torvalds committed
436 437 438 439 440 441 442 443 444 445 446 447 448 449 450
	u32			token;

	/*
	 * URBs map to sequences of QTDs:  one logical transaction
	 */
	qtd = ehci_qtd_alloc (ehci, flags);
	if (unlikely (!qtd))
		return 0;
	list_add_tail (&qtd->qtd_list, head);
	qtd->urb = urb;

	token = QTD_STS_ACTIVE;
	token |= (EHCI_TUNE_CERR << 10);
	/* for split transactions, SplitXState initialized to zero */

David Brownell's avatar
David Brownell committed
451 452
	len = urb->transfer_buffer_length;
	is_input = usb_pipein (urb->pipe);
Linus Torvalds's avatar
Linus Torvalds committed
453 454
	if (usb_pipecontrol (urb->pipe)) {
		/* SETUP pid */
455
		qtd_fill (qtd, urb->setup_dma, sizeof (struct usb_ctrlrequest),
456
			token | (2 /* "setup" */ << 8), 8);
Linus Torvalds's avatar
Linus Torvalds committed
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471

		/* ... and always at least one more pid */
		token ^= QTD_TOGGLE;
		qtd_prev = qtd;
		qtd = ehci_qtd_alloc (ehci, flags);
		if (unlikely (!qtd))
			goto cleanup;
		qtd->urb = urb;
		qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
		list_add_tail (&qtd->qtd_list, head);
	} 

	/*
	 * data transfer stage:  buffer setup
	 */
472 473 474 475
	if (likely (len > 0))
		buf = urb->transfer_dma;
	else
		buf = 0;
Linus Torvalds's avatar
Linus Torvalds committed
476

477
	// FIXME this 'buf' check break some zlps...
David Brownell's avatar
David Brownell committed
478
	if (!buf || is_input)
Linus Torvalds's avatar
Linus Torvalds committed
479 480 481
		token |= (1 /* "in" */ << 8);
	/* else it's already initted to "out" pid (0 << 8) */

482
	maxpacket = max_packet(usb_maxpacket(urb->dev, urb->pipe, !is_input));
Linus Torvalds's avatar
Linus Torvalds committed
483 484 485 486 487 488 489 490 491

	/*
	 * buffer gets wrapped in one or more qtds;
	 * last one may be "short" (including zero len)
	 * and may serve as a control status ack
	 */
	for (;;) {
		int this_qtd_len;

492
		this_qtd_len = qtd_fill (qtd, buf, len, token, maxpacket);
Linus Torvalds's avatar
Linus Torvalds committed
493 494
		len -= this_qtd_len;
		buf += this_qtd_len;
495 496
		if (is_input)
			qtd->hw_alt_next = ehci->async->hw_alt_next;
Linus Torvalds's avatar
Linus Torvalds committed
497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513

		/* qh makes control packets use qtd toggle; maybe switch it */
		if ((maxpacket & (this_qtd_len + (maxpacket - 1))) == 0)
			token ^= QTD_TOGGLE;

		if (likely (len <= 0))
			break;

		qtd_prev = qtd;
		qtd = ehci_qtd_alloc (ehci, flags);
		if (unlikely (!qtd))
			goto cleanup;
		qtd->urb = urb;
		qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
		list_add_tail (&qtd->qtd_list, head);
	}

514 515 516 517 518 519 520
	/* unless the bulk/interrupt caller wants a chance to clean
	 * up after short reads, hc should advance qh past this urb
	 */
	if (likely ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0
				|| usb_pipecontrol (urb->pipe)))
		qtd->hw_alt_next = EHCI_LIST_END;

Linus Torvalds's avatar
Linus Torvalds committed
521 522 523 524 525 526 527 528 529 530 531 532
	/*
	 * control requests may need a terminating data "status" ack;
	 * bulk ones may need a terminating short packet (zero length).
	 */
	if (likely (buf != 0)) {
		int	one_more = 0;

		if (usb_pipecontrol (urb->pipe)) {
			one_more = 1;
			token ^= 0x0100;	/* "in" <--> "out"  */
			token |= QTD_TOGGLE;	/* force DATA1 */
		} else if (usb_pipebulk (urb->pipe)
533
				&& (urb->transfer_flags & URB_ZERO_PACKET)
Linus Torvalds's avatar
Linus Torvalds committed
534 535 536 537 538 539 540 541 542 543 544 545 546
				&& !(urb->transfer_buffer_length % maxpacket)) {
			one_more = 1;
		}
		if (one_more) {
			qtd_prev = qtd;
			qtd = ehci_qtd_alloc (ehci, flags);
			if (unlikely (!qtd))
				goto cleanup;
			qtd->urb = urb;
			qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
			list_add_tail (&qtd->qtd_list, head);

			/* never any data in such packets */
547
			qtd_fill (qtd, 0, 0, token, 0);
Linus Torvalds's avatar
Linus Torvalds committed
548 549 550 551
		}
	}

	/* by default, enable interrupt on urb completion */
552
	if (likely (!(urb->transfer_flags & URB_NO_INTERRUPT)))
Linus Torvalds's avatar
Linus Torvalds committed
553 554 555 556
		qtd->hw_token |= __constant_cpu_to_le32 (QTD_IOC);
	return head;

cleanup:
557
	qtd_list_free (ehci, urb, head);
Linus Torvalds's avatar
Linus Torvalds committed
558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581
	return 0;
}

/*-------------------------------------------------------------------------*/

/*
 * Hardware maintains data toggle (like OHCI) ... here we (re)initialize
 * the hardware data toggle in the QH, and set the pseudo-toggle in udev
 * so we can see if usb_clear_halt() was called.  NOP for control, since
 * we set up qh->hw_info1 to always use the QTD toggle bits. 
 */
static inline void
clear_toggle (struct usb_device *udev, int ep, int is_out, struct ehci_qh *qh)
{
	vdbg ("clear toggle, dev %d ep 0x%x-%s",
		udev->devnum, ep, is_out ? "out" : "in");
	qh->hw_token &= ~__constant_cpu_to_le32 (QTD_TOGGLE);
	usb_settoggle (udev, ep, is_out, 1);
}

// Would be best to create all qh's from config descriptors,
// when each interface/altsetting is established.  Unlink
// any previous qh and cancel its urbs first; endpoints are
// implicitly reset then (data toggle too).
582
// That'd mean updating how usbcore talks to HCDs. (2.7?)
Linus Torvalds's avatar
Linus Torvalds committed
583 584 585 586 587 588 589 590 591 592 593


/*
 * Each QH holds a qtd list; a QH is used for everything except iso.
 *
 * For interrupt urbs, the scheduler must set the microframe scheduling
 * mask(s) each time the QH gets scheduled.  For highspeed, that's
 * just one microframe in the s-mask.  For split interrupt transactions
 * there are additional complications: c-mask, maybe FSTNs.
 */
static struct ehci_qh *
594
qh_make (
Linus Torvalds's avatar
Linus Torvalds committed
595 596 597 598 599 600
	struct ehci_hcd		*ehci,
	struct urb		*urb,
	int			flags
) {
	struct ehci_qh		*qh = ehci_qh_alloc (ehci, flags);
	u32			info1 = 0, info2 = 0;
David Brownell's avatar
David Brownell committed
601 602
	int			is_input, type;
	int			maxp = 0;
Linus Torvalds's avatar
Linus Torvalds committed
603 604 605 606 607 608 609 610 611 612

	if (!qh)
		return qh;

	/*
	 * init endpoint/device data for this QH
	 */
	info1 |= usb_pipeendpoint (urb->pipe) << 8;
	info1 |= usb_pipedevice (urb->pipe) << 0;

David Brownell's avatar
David Brownell committed
613 614 615 616 617 618 619 620 621 622 623 624 625 626 627
	is_input = usb_pipein (urb->pipe);
	type = usb_pipetype (urb->pipe);
	maxp = usb_maxpacket (urb->dev, urb->pipe, !is_input);

	/* Compute interrupt scheduling parameters just once, and save.
	 * - allowing for high bandwidth, how many nsec/uframe are used?
	 * - split transactions need a second CSPLIT uframe; same question
	 * - splits also need a schedule gap (for full/low speed I/O)
	 * - qh has a polling interval
	 *
	 * For control/bulk requests, the HC or TT handles these.
	 */
	if (type == PIPE_INTERRUPT) {
		qh->usecs = usb_calc_bus_time (USB_SPEED_HIGH, is_input, 0,
				hb_mult (maxp) * max_packet (maxp));
628
		qh->start = NO_FRAME;
David Brownell's avatar
David Brownell committed
629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656

		if (urb->dev->speed == USB_SPEED_HIGH) {
			qh->c_usecs = 0;
			qh->gap_uf = 0;

			/* FIXME handle HS periods of less than 1 frame. */
			qh->period = urb->interval >> 3;
			if (qh->period < 1) {
				dbg ("intr period %d uframes, NYET!",
						urb->interval);
				goto done;
			}
		} else {
			/* gap is f(FS/LS transfer times) */
			qh->gap_uf = 1 + usb_calc_bus_time (urb->dev->speed,
					is_input, 0, maxp) / (125 * 1000);

			/* FIXME this just approximates SPLIT/CSPLIT times */
			if (is_input) {		// SPLIT, gap, CSPLIT+DATA
				qh->c_usecs = qh->usecs + HS_USECS (0);
				qh->usecs = HS_USECS (1);
			} else {		// SPLIT+DATA, gap, CSPLIT
				qh->usecs += HS_USECS (1);
				qh->c_usecs = HS_USECS (0);
			}

			qh->period = urb->interval;
		}
657 658 659

		/* support for tt scheduling */
		qh->dev = usb_get_dev (urb->dev);
David Brownell's avatar
David Brownell committed
660 661
	}

Linus Torvalds's avatar
Linus Torvalds committed
662 663 664 665 666 667 668 669
	/* using TT? */
	switch (urb->dev->speed) {
	case USB_SPEED_LOW:
		info1 |= (1 << 12);	/* EPS "low" */
		/* FALL THROUGH */

	case USB_SPEED_FULL:
		/* EPS 0 means "full" */
670 671
		if (type != PIPE_INTERRUPT)
			info1 |= (EHCI_TUNE_RL_TT << 28);
David Brownell's avatar
David Brownell committed
672
		if (type == PIPE_CONTROL) {
Linus Torvalds's avatar
Linus Torvalds committed
673 674 675
			info1 |= (1 << 27);	/* for TT */
			info1 |= 1 << 14;	/* toggle from qtd */
		}
David Brownell's avatar
David Brownell committed
676
		info1 |= maxp << 16;
Linus Torvalds's avatar
Linus Torvalds committed
677 678 679

		info2 |= (EHCI_TUNE_MULT_TT << 30);
		info2 |= urb->dev->ttport << 23;
680 681 682 683 684 685 686

		/* set the address of the TT; for ARC's integrated
		 * root hub tt, leave it zeroed.
		 */
		if (!ehci_is_ARC(ehci)
				|| urb->dev->tt->hub != ehci->hcd.self.root_hub)
			info2 |= urb->dev->tt->hub->devnum << 16;
Linus Torvalds's avatar
Linus Torvalds committed
687

David Brownell's avatar
David Brownell committed
688 689
		/* NOTE:  if (PIPE_INTERRUPT) { scheduler sets c-mask } */

Linus Torvalds's avatar
Linus Torvalds committed
690 691 692 693
		break;

	case USB_SPEED_HIGH:		/* no TT involved */
		info1 |= (2 << 12);	/* EPS "high" */
David Brownell's avatar
David Brownell committed
694
		if (type == PIPE_CONTROL) {
695
			info1 |= (EHCI_TUNE_RL_HS << 28);
Linus Torvalds's avatar
Linus Torvalds committed
696 697
			info1 |= 64 << 16;	/* usb2 fixed maxpacket */
			info1 |= 1 << 14;	/* toggle from qtd */
David Brownell's avatar
USB  
David Brownell committed
698
			info2 |= (EHCI_TUNE_MULT_HS << 30);
David Brownell's avatar
David Brownell committed
699
		} else if (type == PIPE_BULK) {
700
			info1 |= (EHCI_TUNE_RL_HS << 28);
Linus Torvalds's avatar
Linus Torvalds committed
701 702
			info1 |= 512 << 16;	/* usb2 fixed maxpacket */
			info2 |= (EHCI_TUNE_MULT_HS << 30);
David Brownell's avatar
David Brownell committed
703 704 705
		} else {		/* PIPE_INTERRUPT */
			info1 |= max_packet (maxp) << 16;
			info2 |= hb_mult (maxp) << 30;
David Brownell's avatar
USB  
David Brownell committed
706
		}
Linus Torvalds's avatar
Linus Torvalds committed
707
		break;
David Brownell's avatar
David Brownell committed
708
	default:
David Brownell's avatar
David Brownell committed
709
 		dbg ("bogus dev %p speed %d", urb->dev, urb->dev->speed);
David Brownell's avatar
David Brownell committed
710 711 712
done:
		qh_put (ehci, qh);
		return 0;
Linus Torvalds's avatar
Linus Torvalds committed
713 714
	}

David Brownell's avatar
David Brownell committed
715
	/* NOTE:  if (PIPE_INTERRUPT) { scheduler sets s-mask } */
Linus Torvalds's avatar
Linus Torvalds committed
716

717
	/* init as live, toggle clear, advance to dummy */
Linus Torvalds's avatar
Linus Torvalds committed
718 719 720
	qh->qh_state = QH_STATE_IDLE;
	qh->hw_info1 = cpu_to_le32 (info1);
	qh->hw_info2 = cpu_to_le32 (info2);
721 722
	qh_update (ehci, qh, qh->dummy);
	usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1);
Linus Torvalds's avatar
Linus Torvalds committed
723 724 725 726 727 728 729 730 731 732
	return qh;
}

/*-------------------------------------------------------------------------*/

/* move qh (and its qtds) onto async queue; maybe enable queue.  */

static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
{
	u32		dma = QH_NEXT (qh->qh_dma);
733
	struct ehci_qh	*head;
Linus Torvalds's avatar
Linus Torvalds committed
734

735 736
	/* (re)start the async schedule? */
	head = ehci->async;
737
	timer_action_done (ehci, TIMER_ASYNC_OFF);
738
	if (!head->qh_next.qh) {
Linus Torvalds's avatar
Linus Torvalds committed
739 740
		u32	cmd = readl (&ehci->regs->command);

741 742 743 744 745 746 747 748
		if (!(cmd & CMD_ASE)) {
			/* in case a clear of CMD_ASE didn't take yet */
			(void) handshake (&ehci->regs->status, STS_ASS, 0, 150);
			cmd |= CMD_ASE | CMD_RUN;
			writel (cmd, &ehci->regs->command);
			ehci->hcd.state = USB_STATE_RUNNING;
			/* posted write need not be known to HC yet ... */
		}
Linus Torvalds's avatar
Linus Torvalds committed
749
	}
750

751
	qh->hw_token &= ~HALT_BIT;
David Brownell's avatar
David Brownell committed
752

753 754 755 756 757 758 759 760
	/* splice right after start */
	qh->qh_next = head->qh_next;
	qh->hw_next = head->hw_next;
	wmb ();

	head->qh_next.qh = qh;
	head->hw_next = dma;

Linus Torvalds's avatar
Linus Torvalds committed
761 762 763 764 765 766
	qh->qh_state = QH_STATE_LINKED;
	/* qtd completions reported later by interrupt */
}

/*-------------------------------------------------------------------------*/

767 768
#define	QH_ADDR_MASK	__constant_le32_to_cpu(0x7f)

David Brownell's avatar
David Brownell committed
769 770 771 772 773 774 775
/*
 * For control/bulk/interrupt, return QH with these TDs appended.
 * Allocates and initializes the QH if necessary.
 * Returns null if it can't allocate a QH it needs to.
 * If the QH has TDs (urbs) already, that's great.
 */
static struct ehci_qh *qh_append_tds (
Linus Torvalds's avatar
Linus Torvalds committed
776 777 778
	struct ehci_hcd		*ehci,
	struct urb		*urb,
	struct list_head	*qtd_list,
David Brownell's avatar
David Brownell committed
779 780 781 782
	int			epnum,
	void			**ptr
)
{
Linus Torvalds's avatar
Linus Torvalds committed
783 784
	struct ehci_qh		*qh = 0;

David Brownell's avatar
David Brownell committed
785
	qh = (struct ehci_qh *) *ptr;
786 787
	if (unlikely (qh == 0)) {
		/* can't sleep here, we have ehci->lock... */
788
		qh = qh_make (ehci, urb, GFP_ATOMIC);
789 790
		*ptr = qh;
	}
Linus Torvalds's avatar
Linus Torvalds committed
791
	if (likely (qh != 0)) {
David Brownell's avatar
David Brownell committed
792 793
		struct ehci_qtd	*qtd;

794 795 796 797 798
		if (unlikely (list_empty (qtd_list)))
			qtd = 0;
		else
			qtd = list_entry (qtd_list->next, struct ehci_qtd,
					qtd_list);
Linus Torvalds's avatar
Linus Torvalds committed
799

800 801 802
		/* control qh may need patching after enumeration */
		if (unlikely (epnum == 0)) {
			/* set_address changes the address */
803
			if ((qh->hw_info1 & QH_ADDR_MASK) == 0)
804 805 806 807
				qh->hw_info1 |= cpu_to_le32 (
						usb_pipedevice (urb->pipe));

			/* for full speed, ep0 maxpacket can grow */
808 809
			else if (!(qh->hw_info1
					& __constant_cpu_to_le32 (0x3 << 12))) {
810 811 812 813 814 815 816 817 818 819
				u32	info, max;

				info = le32_to_cpu (qh->hw_info1);
				max = urb->dev->descriptor.bMaxPacketSize0;
				if (max > (0x07ff & (info >> 16))) {
					info &= ~(0x07ff << 16);
					info |= max << 16;
					qh->hw_info1 = cpu_to_le32 (info);
				}
			}
820 821 822

                        /* usb_reset_device() briefly reverts to address 0 */
                        if (usb_pipedevice (urb->pipe) == 0)
823
                                qh->hw_info1 &= ~QH_ADDR_MASK;
824
		}
Linus Torvalds's avatar
Linus Torvalds committed
825

826 827 828 829 830 831
		/* usb_clear_halt() means qh data toggle gets reset */
		if (unlikely (!usb_gettoggle (urb->dev,
					(epnum & 0x0f), !(epnum & 0x10)))
				&& !usb_pipecontrol (urb->pipe)) {
			/* "never happens": drivers do stall cleanup right */
			if (qh->qh_state != QH_STATE_IDLE
832
					&& !list_empty (&qh->qtd_list)
833
					&& qh->qh_state != QH_STATE_COMPLETING)
834 835 836 837 838 839 840 841 842 843 844 845 846 847 848
				ehci_warn (ehci, "clear toggle dev%d "
						"ep%d%s: not idle\n",
						usb_pipedevice (urb->pipe),
						epnum & 0x0f,
						usb_pipein (urb->pipe)
							? "in" : "out");
			/* else we know this overlay write is safe */
			clear_toggle (urb->dev,
				epnum & 0x0f, !(epnum & 0x10), qh);
		}

		/* just one way to queue requests: swap with the dummy qtd.
		 * only hc or qh_completions() usually modify the overlay.
		 */
		if (likely (qtd != 0)) {
849 850 851 852 853 854 855 856 857 858
			struct ehci_qtd		*dummy;
			dma_addr_t		dma;
			u32			token;

			/* to avoid racing the HC, use the dummy td instead of
			 * the first td of our list (becomes new dummy).  both
			 * tds stay deactivated until we're done, when the
			 * HC is allowed to fetch the old dummy (4.10.2).
			 */
			token = qtd->hw_token;
859
			qtd->hw_token = HALT_BIT;
David Brownell's avatar
David Brownell committed
860
			wmb ();
861 862 863 864 865
			dummy = qh->dummy;

			dma = dummy->qtd_dma;
			*dummy = *qtd;
			dummy->qtd_dma = dma;
866

867 868
			list_del (&qtd->qtd_list);
			list_add (&dummy->qtd_list, qtd_list);
869
			__list_splice (qtd_list, qh->qtd_list.prev);
870 871 872 873 874

			ehci_qtd_init (qtd, qtd->qtd_dma);
			qh->dummy = qtd;

			/* hc must see the new dummy at list end */
David Brownell's avatar
David Brownell committed
875
			dma = qtd->qtd_dma;
876
			qtd = list_entry (qh->qtd_list.prev,
Linus Torvalds's avatar
Linus Torvalds committed
877
					struct ehci_qtd, qtd_list);
878
			qtd->hw_next = QTD_NEXT (dma);
Linus Torvalds's avatar
Linus Torvalds committed
879

880
			/* let the hc process these next qtds */
881
			wmb ();
882
			dummy->hw_token = token;
Linus Torvalds's avatar
Linus Torvalds committed
883

884
			urb->hcpriv = qh_get (qh);
Linus Torvalds's avatar
Linus Torvalds committed
885 886
		}
	}
David Brownell's avatar
David Brownell committed
887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907
	return qh;
}

/*-------------------------------------------------------------------------*/

static int
submit_async (
	struct ehci_hcd		*ehci,
	struct urb		*urb,
	struct list_head	*qtd_list,
	int			mem_flags
) {
	struct ehci_qtd		*qtd;
	struct hcd_dev		*dev;
	int			epnum;
	unsigned long		flags;
	struct ehci_qh		*qh = 0;

	qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd_list);
	dev = (struct hcd_dev *)urb->dev->hcpriv;
	epnum = usb_pipeendpoint (urb->pipe);
David Brownell's avatar
David Brownell committed
908
	if (usb_pipein (urb->pipe) && !usb_pipecontrol (urb->pipe))
David Brownell's avatar
David Brownell committed
909 910
		epnum |= 0x10;

911 912 913 914 915 916
#ifdef EHCI_URB_TRACE
	ehci_dbg (ehci,
		"%s %s urb %p ep%d%s len %d, qtd %p [qh %p]\n",
		__FUNCTION__, urb->dev->devpath, urb,
		epnum & 0x0f, usb_pipein (urb->pipe) ? "in" : "out",
		urb->transfer_buffer_length,
David Brownell's avatar
David Brownell committed
917
		qtd, dev ? dev->ep [epnum] : (void *)~0);
918
#endif
David Brownell's avatar
David Brownell committed
919 920 921

	spin_lock_irqsave (&ehci->lock, flags);
	qh = qh_append_tds (ehci, urb, qtd_list, epnum, &dev->ep [epnum]);
Linus Torvalds's avatar
Linus Torvalds committed
922 923 924 925 926 927

	/* Control/bulk operations through TTs don't need scheduling,
	 * the HC and TT handle it when the TT has a buffer ready.
	 */
	if (likely (qh != 0)) {
		if (likely (qh->qh_state == QH_STATE_IDLE))
928
			qh_link_async (ehci, qh_get (qh));
Linus Torvalds's avatar
Linus Torvalds committed
929 930
	}
	spin_unlock_irqrestore (&ehci->lock, flags);
931 932 933 934 935
	if (unlikely (qh == 0)) {
		qtd_list_free (ehci, urb, qtd_list);
		return -ENOMEM;
	}
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
936 937 938 939 940 941
}

/*-------------------------------------------------------------------------*/

/* the async qh for the qtds being reclaimed are now unlinked from the HC */

942 943
static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh);

944
static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs)
Linus Torvalds's avatar
Linus Torvalds committed
945 946
{
	struct ehci_qh		*qh = ehci->reclaim;
947
	struct ehci_qh		*next;
Linus Torvalds's avatar
Linus Torvalds committed
948

949
	timer_action_done (ehci, TIMER_IAA_WATCHDOG);
David Brownell's avatar
David Brownell committed
950

951
	// qh->hw_next = cpu_to_le32 (qh->qh_dma);
Linus Torvalds's avatar
Linus Torvalds committed
952 953
	qh->qh_state = QH_STATE_IDLE;
	qh->qh_next.qh = 0;
954
	qh_put (ehci, qh);			// refcount from reclaim 
Linus Torvalds's avatar
Linus Torvalds committed
955

956 957
	/* other unlink(s) may be pending (in QH_STATE_UNLINK_WAIT) */
	next = qh->reclaim;
958 959
	ehci->reclaim = next;
	ehci->reclaim_ready = 0;
960 961
	qh->reclaim = 0;

962
	qh_completions (ehci, qh, regs);
Linus Torvalds's avatar
Linus Torvalds committed
963 964 965 966

	if (!list_empty (&qh->qtd_list)
			&& HCD_IS_RUNNING (ehci->hcd.state))
		qh_link_async (ehci, qh);
967
	else {
968
		qh_put (ehci, qh);		// refcount from async list
969

970 971 972 973
		/* it's not free to turn the async schedule on/off; leave it
		 * active but idle for a while once it empties.
		 */
		if (HCD_IS_RUNNING (ehci->hcd.state)
974 975
				&& ehci->async->qh_next.qh == 0)
			timer_action (ehci, TIMER_ASYNC_OFF);
976
	}
977

978 979
	if (next) {
		ehci->reclaim = 0;
980
		start_unlink_async (ehci, next);
981
	}
Linus Torvalds's avatar
Linus Torvalds committed
982 983 984 985 986 987 988 989 990 991 992 993
}

/* makes sure the async qh will become idle */
/* caller must own ehci->lock */

static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
{
	int		cmd = readl (&ehci->regs->command);
	struct ehci_qh	*prev;

#ifdef DEBUG
	if (ehci->reclaim
994 995
			|| (qh->qh_state != QH_STATE_LINKED
				&& qh->qh_state != QH_STATE_UNLINK_WAIT)
Linus Torvalds's avatar
Linus Torvalds committed
996 997 998 999 1000 1001 1002 1003
#ifdef CONFIG_SMP
// this macro lies except on SMP compiles
			|| !spin_is_locked (&ehci->lock)
#endif
			)
		BUG ();
#endif

1004 1005
	/* stop async schedule right now? */
	if (unlikely (qh == ehci->async)) {
Linus Torvalds's avatar
Linus Torvalds committed
1006 1007
		/* can't get here without STS_ASS set */
		if (ehci->hcd.state != USB_STATE_HALT) {
David Brownell's avatar
David Brownell committed
1008
			writel (cmd & ~CMD_ASE, &ehci->regs->command);
1009 1010
			wmb ();
			// handshake later, if we need to
Linus Torvalds's avatar
Linus Torvalds committed
1011
		}
1012
		timer_action_done (ehci, TIMER_ASYNC_OFF);
Linus Torvalds's avatar
Linus Torvalds committed
1013 1014 1015
		return;
	} 

1016 1017 1018
	qh->qh_state = QH_STATE_UNLINK;
	ehci->reclaim = qh = qh_get (qh);

Linus Torvalds's avatar
Linus Torvalds committed
1019
	prev = ehci->async;
1020
	while (prev->qh_next.qh != qh)
Linus Torvalds's avatar
Linus Torvalds committed
1021 1022 1023 1024
		prev = prev->qh_next.qh;

	prev->hw_next = qh->hw_next;
	prev->qh_next = qh->qh_next;
1025
	wmb ();
Linus Torvalds's avatar
Linus Torvalds committed
1026

1027
	if (unlikely (ehci->hcd.state == USB_STATE_HALT)) {
1028 1029 1030
		/* if (unlikely (qh->reclaim != 0))
		 * 	this will recurse, probably not much
		 */
1031 1032 1033 1034
		end_unlink_async (ehci, NULL);
		return;
	}

Linus Torvalds's avatar
Linus Torvalds committed
1035 1036 1037
	ehci->reclaim_ready = 0;
	cmd |= CMD_IAAD;
	writel (cmd, &ehci->regs->command);
1038 1039
	(void) readl (&ehci->regs->command);
	timer_action (ehci, TIMER_IAA_WATCHDOG);
Linus Torvalds's avatar
Linus Torvalds committed
1040 1041 1042 1043
}

/*-------------------------------------------------------------------------*/

David Brownell's avatar
David Brownell committed
1044
static void
1045
scan_async (struct ehci_hcd *ehci, struct pt_regs *regs)
Linus Torvalds's avatar
Linus Torvalds committed
1046 1047
{
	struct ehci_qh		*qh;
1048
	enum ehci_timer_action	action = TIMER_IO_WATCHDOG;
Linus Torvalds's avatar
Linus Torvalds committed
1049

1050 1051
	if (!++(ehci->stamp))
		ehci->stamp++;
1052
	timer_action_done (ehci, TIMER_ASYNC_SHRINK);
Linus Torvalds's avatar
Linus Torvalds committed
1053
rescan:
1054
	qh = ehci->async->qh_next.qh;
Linus Torvalds's avatar
Linus Torvalds committed
1055 1056 1057
	if (likely (qh != 0)) {
		do {
			/* clean any finished work for this qh */
1058 1059
			if (!list_empty (&qh->qtd_list)
					&& qh->stamp != ehci->stamp) {
1060
				int temp;
Linus Torvalds's avatar
Linus Torvalds committed
1061

1062
				/* unlinks could happen here; completion
1063 1064 1065
				 * reporting drops the lock.  rescan using
				 * the latest schedule, but don't rescan
				 * qhs we already finished (no looping).
1066 1067
				 */
				qh = qh_get (qh);
1068
				qh->stamp = ehci->stamp;
1069
				temp = qh_completions (ehci, qh, regs);
1070
				qh_put (ehci, qh);
1071 1072 1073
				if (temp != 0) {
					goto rescan;
				}
Linus Torvalds's avatar
Linus Torvalds committed
1074 1075
			}

1076 1077 1078 1079 1080
			/* unlink idle entries, reducing HC PCI usage as well
			 * as HCD schedule-scanning costs.  delay for any qh
			 * we just scanned, there's a not-unusual case that it
			 * doesn't stay idle for long.
			 * (plus, avoids some kind of re-activation race.)
David Brownell's avatar
David Brownell committed
1081
			 */
1082 1083
			if (list_empty (&qh->qtd_list)) {
				if (qh->stamp == ehci->stamp)
1084
					action = TIMER_ASYNC_SHRINK;
1085 1086
				else if (!ehci->reclaim
					    && qh->qh_state == QH_STATE_LINKED)
1087
					start_unlink_async (ehci, qh);
Linus Torvalds's avatar
Linus Torvalds committed
1088
			}
David Brownell's avatar
David Brownell committed
1089

Linus Torvalds's avatar
Linus Torvalds committed
1090
			qh = qh->qh_next.qh;
1091
		} while (qh);
Linus Torvalds's avatar
Linus Torvalds committed
1092
	}
1093 1094
	if (action == TIMER_ASYNC_SHRINK)
		timer_action (ehci, TIMER_ASYNC_SHRINK);
Linus Torvalds's avatar
Linus Torvalds committed
1095
}