1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#include <linux/module.h>
28#include <linux/device.h>
29#include <linux/dmapool.h>
30#include <linux/kernel.h>
31#include <linux/delay.h>
32#include <linux/ioport.h>
33#include <linux/sched.h>
34#include <linux/vmalloc.h>
35#include <linux/errno.h>
36#include <linux/init.h>
37#include <linux/hrtimer.h>
38#include <linux/list.h>
39#include <linux/interrupt.h>
40#include <linux/usb.h>
41#include <linux/usb/hcd.h>
42#include <linux/moduleparam.h>
43#include <linux/dma-mapping.h>
44#include <linux/debugfs.h>
45#include <linux/slab.h>
46#include <linux/uaccess.h>
47#include <linux/platform_device.h>
48
49#include <asm/byteorder.h>
50#include <asm/io.h>
51#include <asm/irq.h>
52#include <asm/unaligned.h>
53
54
55#define DRIVER_AUTHOR "Yuan-Hsin Chen"
56#define DRIVER_DESC "FUSBH200 Host Controller (EHCI) Driver"
57
58static const char hcd_name [] = "fusbh200_hcd";
59
60#undef FUSBH200_URB_TRACE
61
62
63#define FUSBH200_TUNE_CERR 3
64#define FUSBH200_TUNE_RL_HS 4
65#define FUSBH200_TUNE_RL_TT 0
66#define FUSBH200_TUNE_MULT_HS 1
67#define FUSBH200_TUNE_MULT_TT 1
68
69
70
71
72
73
74#define FUSBH200_TUNE_FLS 1
75
76
77static int log2_irq_thresh = 0;
78module_param (log2_irq_thresh, int, S_IRUGO);
79MODULE_PARM_DESC (log2_irq_thresh, "log2 IRQ latency, 1-64 microframes");
80
81
82static unsigned park = 0;
83module_param (park, uint, S_IRUGO);
84MODULE_PARM_DESC (park, "park setting; 1-3 back-to-back async packets");
85
86
87static unsigned int hird;
88module_param(hird, int, S_IRUGO);
89MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us");
90
91#define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
92
93#include "fusbh200.h"
94
95
96
97#define fusbh200_dbg(fusbh200, fmt, args...) \
98 dev_dbg (fusbh200_to_hcd(fusbh200)->self.controller , fmt , ## args )
99#define fusbh200_err(fusbh200, fmt, args...) \
100 dev_err (fusbh200_to_hcd(fusbh200)->self.controller , fmt , ## args )
101#define fusbh200_info(fusbh200, fmt, args...) \
102 dev_info (fusbh200_to_hcd(fusbh200)->self.controller , fmt , ## args )
103#define fusbh200_warn(fusbh200, fmt, args...) \
104 dev_warn (fusbh200_to_hcd(fusbh200)->self.controller , fmt , ## args )
105
106
107
108
109
110static void dbg_hcs_params (struct fusbh200_hcd *fusbh200, char *label)
111{
112 u32 params = fusbh200_readl(fusbh200, &fusbh200->caps->hcs_params);
113
114 fusbh200_dbg (fusbh200,
115 "%s hcs_params 0x%x ports=%d\n",
116 label, params,
117 HCS_N_PORTS (params)
118 );
119}
120
121
122
123
124
125static void dbg_hcc_params (struct fusbh200_hcd *fusbh200, char *label)
126{
127 u32 params = fusbh200_readl(fusbh200, &fusbh200->caps->hcc_params);
128
129 fusbh200_dbg (fusbh200,
130 "%s hcc_params %04x uframes %s%s\n",
131 label,
132 params,
133 HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024",
134 HCC_CANPARK(params) ? " park" : "");
135}
136
137static void __maybe_unused
138dbg_qtd (const char *label, struct fusbh200_hcd *fusbh200, struct fusbh200_qtd *qtd)
139{
140 fusbh200_dbg(fusbh200, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd,
141 hc32_to_cpup(fusbh200, &qtd->hw_next),
142 hc32_to_cpup(fusbh200, &qtd->hw_alt_next),
143 hc32_to_cpup(fusbh200, &qtd->hw_token),
144 hc32_to_cpup(fusbh200, &qtd->hw_buf [0]));
145 if (qtd->hw_buf [1])
146 fusbh200_dbg(fusbh200, " p1=%08x p2=%08x p3=%08x p4=%08x\n",
147 hc32_to_cpup(fusbh200, &qtd->hw_buf[1]),
148 hc32_to_cpup(fusbh200, &qtd->hw_buf[2]),
149 hc32_to_cpup(fusbh200, &qtd->hw_buf[3]),
150 hc32_to_cpup(fusbh200, &qtd->hw_buf[4]));
151}
152
153static void __maybe_unused
154dbg_qh (const char *label, struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
155{
156 struct fusbh200_qh_hw *hw = qh->hw;
157
158 fusbh200_dbg (fusbh200, "%s qh %p n%08x info %x %x qtd %x\n", label,
159 qh, hw->hw_next, hw->hw_info1, hw->hw_info2, hw->hw_current);
160 dbg_qtd("overlay", fusbh200, (struct fusbh200_qtd *) &hw->hw_qtd_next);
161}
162
163static void __maybe_unused
164dbg_itd (const char *label, struct fusbh200_hcd *fusbh200, struct fusbh200_itd *itd)
165{
166 fusbh200_dbg (fusbh200, "%s [%d] itd %p, next %08x, urb %p\n",
167 label, itd->frame, itd, hc32_to_cpu(fusbh200, itd->hw_next),
168 itd->urb);
169 fusbh200_dbg (fusbh200,
170 " trans: %08x %08x %08x %08x %08x %08x %08x %08x\n",
171 hc32_to_cpu(fusbh200, itd->hw_transaction[0]),
172 hc32_to_cpu(fusbh200, itd->hw_transaction[1]),
173 hc32_to_cpu(fusbh200, itd->hw_transaction[2]),
174 hc32_to_cpu(fusbh200, itd->hw_transaction[3]),
175 hc32_to_cpu(fusbh200, itd->hw_transaction[4]),
176 hc32_to_cpu(fusbh200, itd->hw_transaction[5]),
177 hc32_to_cpu(fusbh200, itd->hw_transaction[6]),
178 hc32_to_cpu(fusbh200, itd->hw_transaction[7]));
179 fusbh200_dbg (fusbh200,
180 " buf: %08x %08x %08x %08x %08x %08x %08x\n",
181 hc32_to_cpu(fusbh200, itd->hw_bufp[0]),
182 hc32_to_cpu(fusbh200, itd->hw_bufp[1]),
183 hc32_to_cpu(fusbh200, itd->hw_bufp[2]),
184 hc32_to_cpu(fusbh200, itd->hw_bufp[3]),
185 hc32_to_cpu(fusbh200, itd->hw_bufp[4]),
186 hc32_to_cpu(fusbh200, itd->hw_bufp[5]),
187 hc32_to_cpu(fusbh200, itd->hw_bufp[6]));
188 fusbh200_dbg (fusbh200, " index: %d %d %d %d %d %d %d %d\n",
189 itd->index[0], itd->index[1], itd->index[2],
190 itd->index[3], itd->index[4], itd->index[5],
191 itd->index[6], itd->index[7]);
192}
193
194static int __maybe_unused
195dbg_status_buf (char *buf, unsigned len, const char *label, u32 status)
196{
197 return scnprintf (buf, len,
198 "%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s",
199 label, label [0] ? " " : "", status,
200 (status & STS_ASS) ? " Async" : "",
201 (status & STS_PSS) ? " Periodic" : "",
202 (status & STS_RECL) ? " Recl" : "",
203 (status & STS_HALT) ? " Halt" : "",
204 (status & STS_IAA) ? " IAA" : "",
205 (status & STS_FATAL) ? " FATAL" : "",
206 (status & STS_FLR) ? " FLR" : "",
207 (status & STS_PCD) ? " PCD" : "",
208 (status & STS_ERR) ? " ERR" : "",
209 (status & STS_INT) ? " INT" : ""
210 );
211}
212
213static int __maybe_unused
214dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable)
215{
216 return scnprintf (buf, len,
217 "%s%sintrenable %02x%s%s%s%s%s%s",
218 label, label [0] ? " " : "", enable,
219 (enable & STS_IAA) ? " IAA" : "",
220 (enable & STS_FATAL) ? " FATAL" : "",
221 (enable & STS_FLR) ? " FLR" : "",
222 (enable & STS_PCD) ? " PCD" : "",
223 (enable & STS_ERR) ? " ERR" : "",
224 (enable & STS_INT) ? " INT" : ""
225 );
226}
227
228static const char *const fls_strings [] =
229 { "1024", "512", "256", "??" };
230
231static int
232dbg_command_buf (char *buf, unsigned len, const char *label, u32 command)
233{
234 return scnprintf (buf, len,
235 "%s%scommand %07x %s=%d ithresh=%d%s%s%s "
236 "period=%s%s %s",
237 label, label [0] ? " " : "", command,
238 (command & CMD_PARK) ? " park" : "(park)",
239 CMD_PARK_CNT (command),
240 (command >> 16) & 0x3f,
241 (command & CMD_IAAD) ? " IAAD" : "",
242 (command & CMD_ASE) ? " Async" : "",
243 (command & CMD_PSE) ? " Periodic" : "",
244 fls_strings [(command >> 2) & 0x3],
245 (command & CMD_RESET) ? " Reset" : "",
246 (command & CMD_RUN) ? "RUN" : "HALT"
247 );
248}
249
250static int
251dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status)
252{
253 char *sig;
254
255
256 switch (status & (3 << 10)) {
257 case 0 << 10: sig = "se0"; break;
258 case 1 << 10: sig = "k"; break;
259 case 2 << 10: sig = "j"; break;
260 default: sig = "?"; break;
261 }
262
263 return scnprintf (buf, len,
264 "%s%sport:%d status %06x %d "
265 "sig=%s%s%s%s%s%s%s%s",
266 label, label [0] ? " " : "", port, status,
267 status>>25,
268 sig,
269 (status & PORT_RESET) ? " RESET" : "",
270 (status & PORT_SUSPEND) ? " SUSPEND" : "",
271 (status & PORT_RESUME) ? " RESUME" : "",
272 (status & PORT_PEC) ? " PEC" : "",
273 (status & PORT_PE) ? " PE" : "",
274 (status & PORT_CSC) ? " CSC" : "",
275 (status & PORT_CONNECT) ? " CONNECT" : "");
276}
277
278
279#define dbg_status(fusbh200, label, status) { \
280 char _buf [80]; \
281 dbg_status_buf (_buf, sizeof _buf, label, status); \
282 fusbh200_dbg (fusbh200, "%s\n", _buf); \
283}
284
285#define dbg_cmd(fusbh200, label, command) { \
286 char _buf [80]; \
287 dbg_command_buf (_buf, sizeof _buf, label, command); \
288 fusbh200_dbg (fusbh200, "%s\n", _buf); \
289}
290
291#define dbg_port(fusbh200, label, port, status) { \
292 char _buf [80]; \
293 dbg_port_buf (_buf, sizeof _buf, label, port, status); \
294 fusbh200_dbg (fusbh200, "%s\n", _buf); \
295}
296
297
298
299
300
301static int debug_async_open(struct inode *, struct file *);
302static int debug_periodic_open(struct inode *, struct file *);
303static int debug_registers_open(struct inode *, struct file *);
304static int debug_async_open(struct inode *, struct file *);
305
306static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*);
307static int debug_close(struct inode *, struct file *);
308
309static const struct file_operations debug_async_fops = {
310 .owner = THIS_MODULE,
311 .open = debug_async_open,
312 .read = debug_output,
313 .release = debug_close,
314 .llseek = default_llseek,
315};
316static const struct file_operations debug_periodic_fops = {
317 .owner = THIS_MODULE,
318 .open = debug_periodic_open,
319 .read = debug_output,
320 .release = debug_close,
321 .llseek = default_llseek,
322};
323static const struct file_operations debug_registers_fops = {
324 .owner = THIS_MODULE,
325 .open = debug_registers_open,
326 .read = debug_output,
327 .release = debug_close,
328 .llseek = default_llseek,
329};
330
331static struct dentry *fusbh200_debug_root;
332
333struct debug_buffer {
334 ssize_t (*fill_func)(struct debug_buffer *);
335 struct usb_bus *bus;
336 struct mutex mutex;
337 size_t count;
338 char *output_buf;
339 size_t alloc_size;
340};
341
342#define speed_char(info1) ({ char tmp; \
343 switch (info1 & (3 << 12)) { \
344 case QH_FULL_SPEED: tmp = 'f'; break; \
345 case QH_LOW_SPEED: tmp = 'l'; break; \
346 case QH_HIGH_SPEED: tmp = 'h'; break; \
347 default: tmp = '?'; break; \
348 } tmp; })
349
350static inline char token_mark(struct fusbh200_hcd *fusbh200, __hc32 token)
351{
352 __u32 v = hc32_to_cpu(fusbh200, token);
353
354 if (v & QTD_STS_ACTIVE)
355 return '*';
356 if (v & QTD_STS_HALT)
357 return '-';
358 if (!IS_SHORT_READ (v))
359 return ' ';
360
361 return '/';
362}
363
364static void qh_lines (
365 struct fusbh200_hcd *fusbh200,
366 struct fusbh200_qh *qh,
367 char **nextp,
368 unsigned *sizep
369)
370{
371 u32 scratch;
372 u32 hw_curr;
373 struct fusbh200_qtd *td;
374 unsigned temp;
375 unsigned size = *sizep;
376 char *next = *nextp;
377 char mark;
378 __le32 list_end = FUSBH200_LIST_END(fusbh200);
379 struct fusbh200_qh_hw *hw = qh->hw;
380
381 if (hw->hw_qtd_next == list_end)
382 mark = '@';
383 else
384 mark = token_mark(fusbh200, hw->hw_token);
385 if (mark == '/') {
386 if ((hw->hw_alt_next & QTD_MASK(fusbh200))
387 == fusbh200->async->hw->hw_alt_next)
388 mark = '#';
389 else if (hw->hw_alt_next == list_end)
390 mark = '.';
391
392 }
393 scratch = hc32_to_cpup(fusbh200, &hw->hw_info1);
394 hw_curr = (mark == '*') ? hc32_to_cpup(fusbh200, &hw->hw_current) : 0;
395 temp = scnprintf (next, size,
396 "qh/%p dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)",
397 qh, scratch & 0x007f,
398 speed_char (scratch),
399 (scratch >> 8) & 0x000f,
400 scratch, hc32_to_cpup(fusbh200, &hw->hw_info2),
401 hc32_to_cpup(fusbh200, &hw->hw_token), mark,
402 (cpu_to_hc32(fusbh200, QTD_TOGGLE) & hw->hw_token)
403 ? "data1" : "data0",
404 (hc32_to_cpup(fusbh200, &hw->hw_alt_next) >> 1) & 0x0f);
405 size -= temp;
406 next += temp;
407
408
409 list_for_each_entry(td, &qh->qtd_list, qtd_list) {
410 scratch = hc32_to_cpup(fusbh200, &td->hw_token);
411 mark = ' ';
412 if (hw_curr == td->qtd_dma)
413 mark = '*';
414 else if (hw->hw_qtd_next == cpu_to_hc32(fusbh200, td->qtd_dma))
415 mark = '+';
416 else if (QTD_LENGTH (scratch)) {
417 if (td->hw_alt_next == fusbh200->async->hw->hw_alt_next)
418 mark = '#';
419 else if (td->hw_alt_next != list_end)
420 mark = '/';
421 }
422 temp = snprintf (next, size,
423 "\n\t%p%c%s len=%d %08x urb %p",
424 td, mark, ({ char *tmp;
425 switch ((scratch>>8)&0x03) {
426 case 0: tmp = "out"; break;
427 case 1: tmp = "in"; break;
428 case 2: tmp = "setup"; break;
429 default: tmp = "?"; break;
430 } tmp;}),
431 (scratch >> 16) & 0x7fff,
432 scratch,
433 td->urb);
434 if (size < temp)
435 temp = size;
436 size -= temp;
437 next += temp;
438 if (temp == size)
439 goto done;
440 }
441
442 temp = snprintf (next, size, "\n");
443 if (size < temp)
444 temp = size;
445 size -= temp;
446 next += temp;
447
448done:
449 *sizep = size;
450 *nextp = next;
451}
452
453static ssize_t fill_async_buffer(struct debug_buffer *buf)
454{
455 struct usb_hcd *hcd;
456 struct fusbh200_hcd *fusbh200;
457 unsigned long flags;
458 unsigned temp, size;
459 char *next;
460 struct fusbh200_qh *qh;
461
462 hcd = bus_to_hcd(buf->bus);
463 fusbh200 = hcd_to_fusbh200 (hcd);
464 next = buf->output_buf;
465 size = buf->alloc_size;
466
467 *next = 0;
468
469
470
471
472
473 spin_lock_irqsave (&fusbh200->lock, flags);
474 for (qh = fusbh200->async->qh_next.qh; size > 0 && qh; qh = qh->qh_next.qh)
475 qh_lines (fusbh200, qh, &next, &size);
476 if (fusbh200->async_unlink && size > 0) {
477 temp = scnprintf(next, size, "\nunlink =\n");
478 size -= temp;
479 next += temp;
480
481 for (qh = fusbh200->async_unlink; size > 0 && qh;
482 qh = qh->unlink_next)
483 qh_lines (fusbh200, qh, &next, &size);
484 }
485 spin_unlock_irqrestore (&fusbh200->lock, flags);
486
487 return strlen(buf->output_buf);
488}
489
490#define DBG_SCHED_LIMIT 64
491static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
492{
493 struct usb_hcd *hcd;
494 struct fusbh200_hcd *fusbh200;
495 unsigned long flags;
496 union fusbh200_shadow p, *seen;
497 unsigned temp, size, seen_count;
498 char *next;
499 unsigned i;
500 __hc32 tag;
501
502 seen = kmalloc(DBG_SCHED_LIMIT * sizeof *seen, GFP_ATOMIC);
503 if (!seen)
504 return 0;
505 seen_count = 0;
506
507 hcd = bus_to_hcd(buf->bus);
508 fusbh200 = hcd_to_fusbh200 (hcd);
509 next = buf->output_buf;
510 size = buf->alloc_size;
511
512 temp = scnprintf (next, size, "size = %d\n", fusbh200->periodic_size);
513 size -= temp;
514 next += temp;
515
516
517
518
519 spin_lock_irqsave (&fusbh200->lock, flags);
520 for (i = 0; i < fusbh200->periodic_size; i++) {
521 p = fusbh200->pshadow [i];
522 if (likely (!p.ptr))
523 continue;
524 tag = Q_NEXT_TYPE(fusbh200, fusbh200->periodic [i]);
525
526 temp = scnprintf (next, size, "%4d: ", i);
527 size -= temp;
528 next += temp;
529
530 do {
531 struct fusbh200_qh_hw *hw;
532
533 switch (hc32_to_cpu(fusbh200, tag)) {
534 case Q_TYPE_QH:
535 hw = p.qh->hw;
536 temp = scnprintf (next, size, " qh%d-%04x/%p",
537 p.qh->period,
538 hc32_to_cpup(fusbh200,
539 &hw->hw_info2)
540
541 & (QH_CMASK | QH_SMASK),
542 p.qh);
543 size -= temp;
544 next += temp;
545
546 for (temp = 0; temp < seen_count; temp++) {
547 if (seen [temp].ptr != p.ptr)
548 continue;
549 if (p.qh->qh_next.ptr) {
550 temp = scnprintf (next, size,
551 " ...");
552 size -= temp;
553 next += temp;
554 }
555 break;
556 }
557
558 if (temp == seen_count) {
559 u32 scratch = hc32_to_cpup(fusbh200,
560 &hw->hw_info1);
561 struct fusbh200_qtd *qtd;
562 char *type = "";
563
564
565 temp = 0;
566 list_for_each_entry (qtd,
567 &p.qh->qtd_list,
568 qtd_list) {
569 temp++;
570 switch (0x03 & (hc32_to_cpu(
571 fusbh200,
572 qtd->hw_token) >> 8)) {
573 case 0: type = "out"; continue;
574 case 1: type = "in"; continue;
575 }
576 }
577
578 temp = scnprintf (next, size,
579 " (%c%d ep%d%s "
580 "[%d/%d] q%d p%d)",
581 speed_char (scratch),
582 scratch & 0x007f,
583 (scratch >> 8) & 0x000f, type,
584 p.qh->usecs, p.qh->c_usecs,
585 temp,
586 0x7ff & (scratch >> 16));
587
588 if (seen_count < DBG_SCHED_LIMIT)
589 seen [seen_count++].qh = p.qh;
590 } else
591 temp = 0;
592 tag = Q_NEXT_TYPE(fusbh200, hw->hw_next);
593 p = p.qh->qh_next;
594 break;
595 case Q_TYPE_FSTN:
596 temp = scnprintf (next, size,
597 " fstn-%8x/%p", p.fstn->hw_prev,
598 p.fstn);
599 tag = Q_NEXT_TYPE(fusbh200, p.fstn->hw_next);
600 p = p.fstn->fstn_next;
601 break;
602 case Q_TYPE_ITD:
603 temp = scnprintf (next, size,
604 " itd/%p", p.itd);
605 tag = Q_NEXT_TYPE(fusbh200, p.itd->hw_next);
606 p = p.itd->itd_next;
607 break;
608 }
609 size -= temp;
610 next += temp;
611 } while (p.ptr);
612
613 temp = scnprintf (next, size, "\n");
614 size -= temp;
615 next += temp;
616 }
617 spin_unlock_irqrestore (&fusbh200->lock, flags);
618 kfree (seen);
619
620 return buf->alloc_size - size;
621}
622#undef DBG_SCHED_LIMIT
623
624static const char *rh_state_string(struct fusbh200_hcd *fusbh200)
625{
626 switch (fusbh200->rh_state) {
627 case FUSBH200_RH_HALTED:
628 return "halted";
629 case FUSBH200_RH_SUSPENDED:
630 return "suspended";
631 case FUSBH200_RH_RUNNING:
632 return "running";
633 case FUSBH200_RH_STOPPING:
634 return "stopping";
635 }
636 return "?";
637}
638
639static ssize_t fill_registers_buffer(struct debug_buffer *buf)
640{
641 struct usb_hcd *hcd;
642 struct fusbh200_hcd *fusbh200;
643 unsigned long flags;
644 unsigned temp, size, i;
645 char *next, scratch [80];
646 static char fmt [] = "%*s\n";
647 static char label [] = "";
648
649 hcd = bus_to_hcd(buf->bus);
650 fusbh200 = hcd_to_fusbh200 (hcd);
651 next = buf->output_buf;
652 size = buf->alloc_size;
653
654 spin_lock_irqsave (&fusbh200->lock, flags);
655
656 if (!HCD_HW_ACCESSIBLE(hcd)) {
657 size = scnprintf (next, size,
658 "bus %s, device %s\n"
659 "%s\n"
660 "SUSPENDED (no register access)\n",
661 hcd->self.controller->bus->name,
662 dev_name(hcd->self.controller),
663 hcd->product_desc);
664 goto done;
665 }
666
667
668 i = HC_VERSION(fusbh200, fusbh200_readl(fusbh200, &fusbh200->caps->hc_capbase));
669 temp = scnprintf (next, size,
670 "bus %s, device %s\n"
671 "%s\n"
672 "EHCI %x.%02x, rh state %s\n",
673 hcd->self.controller->bus->name,
674 dev_name(hcd->self.controller),
675 hcd->product_desc,
676 i >> 8, i & 0x0ff, rh_state_string(fusbh200));
677 size -= temp;
678 next += temp;
679
680
681 i = fusbh200_readl(fusbh200, &fusbh200->caps->hcs_params);
682 temp = scnprintf (next, size, "structural params 0x%08x\n", i);
683 size -= temp;
684 next += temp;
685
686 i = fusbh200_readl(fusbh200, &fusbh200->caps->hcc_params);
687 temp = scnprintf (next, size, "capability params 0x%08x\n", i);
688 size -= temp;
689 next += temp;
690
691
692 temp = dbg_status_buf (scratch, sizeof scratch, label,
693 fusbh200_readl(fusbh200, &fusbh200->regs->status));
694 temp = scnprintf (next, size, fmt, temp, scratch);
695 size -= temp;
696 next += temp;
697
698 temp = dbg_command_buf (scratch, sizeof scratch, label,
699 fusbh200_readl(fusbh200, &fusbh200->regs->command));
700 temp = scnprintf (next, size, fmt, temp, scratch);
701 size -= temp;
702 next += temp;
703
704 temp = dbg_intr_buf (scratch, sizeof scratch, label,
705 fusbh200_readl(fusbh200, &fusbh200->regs->intr_enable));
706 temp = scnprintf (next, size, fmt, temp, scratch);
707 size -= temp;
708 next += temp;
709
710 temp = scnprintf (next, size, "uframe %04x\n",
711 fusbh200_read_frame_index(fusbh200));
712 size -= temp;
713 next += temp;
714
715 if (fusbh200->async_unlink) {
716 temp = scnprintf(next, size, "async unlink qh %p\n",
717 fusbh200->async_unlink);
718 size -= temp;
719 next += temp;
720 }
721
722 temp = scnprintf (next, size,
723 "irq normal %ld err %ld iaa %ld (lost %ld)\n",
724 fusbh200->stats.normal, fusbh200->stats.error, fusbh200->stats.iaa,
725 fusbh200->stats.lost_iaa);
726 size -= temp;
727 next += temp;
728
729 temp = scnprintf (next, size, "complete %ld unlink %ld\n",
730 fusbh200->stats.complete, fusbh200->stats.unlink);
731 size -= temp;
732 next += temp;
733
734done:
735 spin_unlock_irqrestore (&fusbh200->lock, flags);
736
737 return buf->alloc_size - size;
738}
739
740static struct debug_buffer *alloc_buffer(struct usb_bus *bus,
741 ssize_t (*fill_func)(struct debug_buffer *))
742{
743 struct debug_buffer *buf;
744
745 buf = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL);
746
747 if (buf) {
748 buf->bus = bus;
749 buf->fill_func = fill_func;
750 mutex_init(&buf->mutex);
751 buf->alloc_size = PAGE_SIZE;
752 }
753
754 return buf;
755}
756
757static int fill_buffer(struct debug_buffer *buf)
758{
759 int ret = 0;
760
761 if (!buf->output_buf)
762 buf->output_buf = vmalloc(buf->alloc_size);
763
764 if (!buf->output_buf) {
765 ret = -ENOMEM;
766 goto out;
767 }
768
769 ret = buf->fill_func(buf);
770
771 if (ret >= 0) {
772 buf->count = ret;
773 ret = 0;
774 }
775
776out:
777 return ret;
778}
779
780static ssize_t debug_output(struct file *file, char __user *user_buf,
781 size_t len, loff_t *offset)
782{
783 struct debug_buffer *buf = file->private_data;
784 int ret = 0;
785
786 mutex_lock(&buf->mutex);
787 if (buf->count == 0) {
788 ret = fill_buffer(buf);
789 if (ret != 0) {
790 mutex_unlock(&buf->mutex);
791 goto out;
792 }
793 }
794 mutex_unlock(&buf->mutex);
795
796 ret = simple_read_from_buffer(user_buf, len, offset,
797 buf->output_buf, buf->count);
798
799out:
800 return ret;
801
802}
803
804static int debug_close(struct inode *inode, struct file *file)
805{
806 struct debug_buffer *buf = file->private_data;
807
808 if (buf) {
809 vfree(buf->output_buf);
810 kfree(buf);
811 }
812
813 return 0;
814}
815static int debug_async_open(struct inode *inode, struct file *file)
816{
817 file->private_data = alloc_buffer(inode->i_private, fill_async_buffer);
818
819 return file->private_data ? 0 : -ENOMEM;
820}
821
822static int debug_periodic_open(struct inode *inode, struct file *file)
823{
824 struct debug_buffer *buf;
825 buf = alloc_buffer(inode->i_private, fill_periodic_buffer);
826 if (!buf)
827 return -ENOMEM;
828
829 buf->alloc_size = (sizeof(void *) == 4 ? 6 : 8)*PAGE_SIZE;
830 file->private_data = buf;
831 return 0;
832}
833
834static int debug_registers_open(struct inode *inode, struct file *file)
835{
836 file->private_data = alloc_buffer(inode->i_private,
837 fill_registers_buffer);
838
839 return file->private_data ? 0 : -ENOMEM;
840}
841
842static inline void create_debug_files (struct fusbh200_hcd *fusbh200)
843{
844 struct usb_bus *bus = &fusbh200_to_hcd(fusbh200)->self;
845
846 fusbh200->debug_dir = debugfs_create_dir(bus->bus_name, fusbh200_debug_root);
847 if (!fusbh200->debug_dir)
848 return;
849
850 if (!debugfs_create_file("async", S_IRUGO, fusbh200->debug_dir, bus,
851 &debug_async_fops))
852 goto file_error;
853
854 if (!debugfs_create_file("periodic", S_IRUGO, fusbh200->debug_dir, bus,
855 &debug_periodic_fops))
856 goto file_error;
857
858 if (!debugfs_create_file("registers", S_IRUGO, fusbh200->debug_dir, bus,
859 &debug_registers_fops))
860 goto file_error;
861
862 return;
863
864file_error:
865 debugfs_remove_recursive(fusbh200->debug_dir);
866}
867
868static inline void remove_debug_files (struct fusbh200_hcd *fusbh200)
869{
870 debugfs_remove_recursive(fusbh200->debug_dir);
871}
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892static int handshake (struct fusbh200_hcd *fusbh200, void __iomem *ptr,
893 u32 mask, u32 done, int usec)
894{
895 u32 result;
896
897 do {
898 result = fusbh200_readl(fusbh200, ptr);
899 if (result == ~(u32)0)
900 return -ENODEV;
901 result &= mask;
902 if (result == done)
903 return 0;
904 udelay (1);
905 usec--;
906 } while (usec > 0);
907 return -ETIMEDOUT;
908}
909
910
911
912
913
914static int fusbh200_halt (struct fusbh200_hcd *fusbh200)
915{
916 u32 temp;
917
918 spin_lock_irq(&fusbh200->lock);
919
920
921 fusbh200_writel(fusbh200, 0, &fusbh200->regs->intr_enable);
922
923
924
925
926
927 fusbh200->command &= ~CMD_RUN;
928 temp = fusbh200_readl(fusbh200, &fusbh200->regs->command);
929 temp &= ~(CMD_RUN | CMD_IAAD);
930 fusbh200_writel(fusbh200, temp, &fusbh200->regs->command);
931
932 spin_unlock_irq(&fusbh200->lock);
933 synchronize_irq(fusbh200_to_hcd(fusbh200)->irq);
934
935 return handshake(fusbh200, &fusbh200->regs->status,
936 STS_HALT, STS_HALT, 16 * 125);
937}
938
939
940
941
942
943static int fusbh200_reset (struct fusbh200_hcd *fusbh200)
944{
945 int retval;
946 u32 command = fusbh200_readl(fusbh200, &fusbh200->regs->command);
947
948
949
950 if (fusbh200->debug && !dbgp_reset_prep(fusbh200_to_hcd(fusbh200)))
951 fusbh200->debug = NULL;
952
953 command |= CMD_RESET;
954 dbg_cmd (fusbh200, "reset", command);
955 fusbh200_writel(fusbh200, command, &fusbh200->regs->command);
956 fusbh200->rh_state = FUSBH200_RH_HALTED;
957 fusbh200->next_statechange = jiffies;
958 retval = handshake (fusbh200, &fusbh200->regs->command,
959 CMD_RESET, 0, 250 * 1000);
960
961 if (retval)
962 return retval;
963
964 if (fusbh200->debug)
965 dbgp_external_startup(fusbh200_to_hcd(fusbh200));
966
967 fusbh200->port_c_suspend = fusbh200->suspended_ports =
968 fusbh200->resuming_ports = 0;
969 return retval;
970}
971
972
973
974
975
976static void fusbh200_quiesce (struct fusbh200_hcd *fusbh200)
977{
978 u32 temp;
979
980 if (fusbh200->rh_state != FUSBH200_RH_RUNNING)
981 return;
982
983
984 temp = (fusbh200->command << 10) & (STS_ASS | STS_PSS);
985 handshake(fusbh200, &fusbh200->regs->status, STS_ASS | STS_PSS, temp, 16 * 125);
986
987
988 spin_lock_irq(&fusbh200->lock);
989 fusbh200->command &= ~(CMD_ASE | CMD_PSE);
990 fusbh200_writel(fusbh200, fusbh200->command, &fusbh200->regs->command);
991 spin_unlock_irq(&fusbh200->lock);
992
993
994 handshake(fusbh200, &fusbh200->regs->status, STS_ASS | STS_PSS, 0, 16 * 125);
995}
996
997
998
999static void end_unlink_async(struct fusbh200_hcd *fusbh200);
1000static void unlink_empty_async(struct fusbh200_hcd *fusbh200);
1001static void fusbh200_work(struct fusbh200_hcd *fusbh200);
1002static void start_unlink_intr(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh);
1003static void end_unlink_intr(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh);
1004
1005
1006
1007
1008static void fusbh200_set_command_bit(struct fusbh200_hcd *fusbh200, u32 bit)
1009{
1010 fusbh200->command |= bit;
1011 fusbh200_writel(fusbh200, fusbh200->command, &fusbh200->regs->command);
1012
1013
1014 fusbh200_readl(fusbh200, &fusbh200->regs->command);
1015}
1016
1017
1018static void fusbh200_clear_command_bit(struct fusbh200_hcd *fusbh200, u32 bit)
1019{
1020 fusbh200->command &= ~bit;
1021 fusbh200_writel(fusbh200, fusbh200->command, &fusbh200->regs->command);
1022
1023
1024 fusbh200_readl(fusbh200, &fusbh200->regs->command);
1025}
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057static unsigned event_delays_ns[] = {
1058 1 * NSEC_PER_MSEC,
1059 1 * NSEC_PER_MSEC,
1060 1 * NSEC_PER_MSEC,
1061 1125 * NSEC_PER_USEC,
1062 2 * NSEC_PER_MSEC,
1063 6 * NSEC_PER_MSEC,
1064 10 * NSEC_PER_MSEC,
1065 10 * NSEC_PER_MSEC,
1066 15 * NSEC_PER_MSEC,
1067 100 * NSEC_PER_MSEC,
1068};
1069
1070
1071static void fusbh200_enable_event(struct fusbh200_hcd *fusbh200, unsigned event,
1072 bool resched)
1073{
1074 ktime_t *timeout = &fusbh200->hr_timeouts[event];
1075
1076 if (resched)
1077 *timeout = ktime_add(ktime_get(),
1078 ktime_set(0, event_delays_ns[event]));
1079 fusbh200->enabled_hrtimer_events |= (1 << event);
1080
1081
1082 if (event < fusbh200->next_hrtimer_event) {
1083 fusbh200->next_hrtimer_event = event;
1084 hrtimer_start_range_ns(&fusbh200->hrtimer, *timeout,
1085 NSEC_PER_MSEC, HRTIMER_MODE_ABS);
1086 }
1087}
1088
1089
1090
1091static void fusbh200_poll_ASS(struct fusbh200_hcd *fusbh200)
1092{
1093 unsigned actual, want;
1094
1095
1096 if (fusbh200->rh_state != FUSBH200_RH_RUNNING)
1097 return;
1098
1099 want = (fusbh200->command & CMD_ASE) ? STS_ASS : 0;
1100 actual = fusbh200_readl(fusbh200, &fusbh200->regs->status) & STS_ASS;
1101
1102 if (want != actual) {
1103
1104
1105 if (fusbh200->ASS_poll_count++ < 20) {
1106 fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_POLL_ASS, true);
1107 return;
1108 }
1109 fusbh200_dbg(fusbh200, "Waited too long for the async schedule status (%x/%x), giving up\n",
1110 want, actual);
1111 }
1112 fusbh200->ASS_poll_count = 0;
1113
1114
1115 if (want == 0) {
1116 if (fusbh200->async_count > 0)
1117 fusbh200_set_command_bit(fusbh200, CMD_ASE);
1118
1119 } else {
1120 if (fusbh200->async_count == 0) {
1121
1122
1123 fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_DISABLE_ASYNC,
1124 true);
1125 }
1126 }
1127}
1128
1129
1130static void fusbh200_disable_ASE(struct fusbh200_hcd *fusbh200)
1131{
1132 fusbh200_clear_command_bit(fusbh200, CMD_ASE);
1133}
1134
1135
1136
1137static void fusbh200_poll_PSS(struct fusbh200_hcd *fusbh200)
1138{
1139 unsigned actual, want;
1140
1141
1142 if (fusbh200->rh_state != FUSBH200_RH_RUNNING)
1143 return;
1144
1145 want = (fusbh200->command & CMD_PSE) ? STS_PSS : 0;
1146 actual = fusbh200_readl(fusbh200, &fusbh200->regs->status) & STS_PSS;
1147
1148 if (want != actual) {
1149
1150
1151 if (fusbh200->PSS_poll_count++ < 20) {
1152 fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_POLL_PSS, true);
1153 return;
1154 }
1155 fusbh200_dbg(fusbh200, "Waited too long for the periodic schedule status (%x/%x), giving up\n",
1156 want, actual);
1157 }
1158 fusbh200->PSS_poll_count = 0;
1159
1160
1161 if (want == 0) {
1162 if (fusbh200->periodic_count > 0)
1163 fusbh200_set_command_bit(fusbh200, CMD_PSE);
1164
1165 } else {
1166 if (fusbh200->periodic_count == 0) {
1167
1168
1169 fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_DISABLE_PERIODIC,
1170 true);
1171 }
1172 }
1173}
1174
1175
1176static void fusbh200_disable_PSE(struct fusbh200_hcd *fusbh200)
1177{
1178 fusbh200_clear_command_bit(fusbh200, CMD_PSE);
1179}
1180
1181
1182
1183static void fusbh200_handle_controller_death(struct fusbh200_hcd *fusbh200)
1184{
1185 if (!(fusbh200_readl(fusbh200, &fusbh200->regs->status) & STS_HALT)) {
1186
1187
1188 if (fusbh200->died_poll_count++ < 5) {
1189
1190 fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_POLL_DEAD, true);
1191 return;
1192 }
1193 fusbh200_warn(fusbh200, "Waited too long for the controller to stop, giving up\n");
1194 }
1195
1196
1197 fusbh200->rh_state = FUSBH200_RH_HALTED;
1198 fusbh200_writel(fusbh200, 0, &fusbh200->regs->intr_enable);
1199 fusbh200_work(fusbh200);
1200 end_unlink_async(fusbh200);
1201
1202
1203}
1204
1205
1206
1207static void fusbh200_handle_intr_unlinks(struct fusbh200_hcd *fusbh200)
1208{
1209 bool stopped = (fusbh200->rh_state < FUSBH200_RH_RUNNING);
1210
1211
1212
1213
1214
1215
1216
1217
1218 fusbh200->intr_unlinking = true;
1219 while (fusbh200->intr_unlink) {
1220 struct fusbh200_qh *qh = fusbh200->intr_unlink;
1221
1222 if (!stopped && qh->unlink_cycle == fusbh200->intr_unlink_cycle)
1223 break;
1224 fusbh200->intr_unlink = qh->unlink_next;
1225 qh->unlink_next = NULL;
1226 end_unlink_intr(fusbh200, qh);
1227 }
1228
1229
1230 if (fusbh200->intr_unlink) {
1231 fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_UNLINK_INTR, true);
1232 ++fusbh200->intr_unlink_cycle;
1233 }
1234 fusbh200->intr_unlinking = false;
1235}
1236
1237
1238
1239static void start_free_itds(struct fusbh200_hcd *fusbh200)
1240{
1241 if (!(fusbh200->enabled_hrtimer_events & BIT(FUSBH200_HRTIMER_FREE_ITDS))) {
1242 fusbh200->last_itd_to_free = list_entry(
1243 fusbh200->cached_itd_list.prev,
1244 struct fusbh200_itd, itd_list);
1245 fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_FREE_ITDS, true);
1246 }
1247}
1248
1249
1250static void end_free_itds(struct fusbh200_hcd *fusbh200)
1251{
1252 struct fusbh200_itd *itd, *n;
1253
1254 if (fusbh200->rh_state < FUSBH200_RH_RUNNING) {
1255 fusbh200->last_itd_to_free = NULL;
1256 }
1257
1258 list_for_each_entry_safe(itd, n, &fusbh200->cached_itd_list, itd_list) {
1259 list_del(&itd->itd_list);
1260 dma_pool_free(fusbh200->itd_pool, itd, itd->itd_dma);
1261 if (itd == fusbh200->last_itd_to_free)
1262 break;
1263 }
1264
1265 if (!list_empty(&fusbh200->cached_itd_list))
1266 start_free_itds(fusbh200);
1267}
1268
1269
1270
1271static void fusbh200_iaa_watchdog(struct fusbh200_hcd *fusbh200)
1272{
1273 if (fusbh200->rh_state != FUSBH200_RH_RUNNING)
1274 return;
1275
1276
1277
1278
1279
1280
1281
1282 if (fusbh200->async_iaa) {
1283 u32 cmd, status;
1284
1285
1286
1287
1288
1289
1290
1291 cmd = fusbh200_readl(fusbh200, &fusbh200->regs->command);
1292
1293
1294
1295
1296
1297
1298
1299
1300 status = fusbh200_readl(fusbh200, &fusbh200->regs->status);
1301 if ((status & STS_IAA) || !(cmd & CMD_IAAD)) {
1302 COUNT(fusbh200->stats.lost_iaa);
1303 fusbh200_writel(fusbh200, STS_IAA, &fusbh200->regs->status);
1304 }
1305
1306 fusbh200_dbg(fusbh200, "IAA watchdog: status %x cmd %x\n",
1307 status, cmd);
1308 end_unlink_async(fusbh200);
1309 }
1310}
1311
1312
1313
1314static void turn_on_io_watchdog(struct fusbh200_hcd *fusbh200)
1315{
1316
1317 if (fusbh200->rh_state != FUSBH200_RH_RUNNING ||
1318 (fusbh200->enabled_hrtimer_events &
1319 BIT(FUSBH200_HRTIMER_IO_WATCHDOG)))
1320 return;
1321
1322
1323
1324
1325
1326 if (fusbh200->isoc_count > 0 || (fusbh200->need_io_watchdog &&
1327 fusbh200->async_count + fusbh200->intr_count > 0))
1328 fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_IO_WATCHDOG, true);
1329}
1330
1331
1332
1333
1334
1335
1336
1337static void (*event_handlers[])(struct fusbh200_hcd *) = {
1338 fusbh200_poll_ASS,
1339 fusbh200_poll_PSS,
1340 fusbh200_handle_controller_death,
1341 fusbh200_handle_intr_unlinks,
1342 end_free_itds,
1343 unlink_empty_async,
1344 fusbh200_iaa_watchdog,
1345 fusbh200_disable_PSE,
1346 fusbh200_disable_ASE,
1347 fusbh200_work,
1348};
1349
1350static enum hrtimer_restart fusbh200_hrtimer_func(struct hrtimer *t)
1351{
1352 struct fusbh200_hcd *fusbh200 = container_of(t, struct fusbh200_hcd, hrtimer);
1353 ktime_t now;
1354 unsigned long events;
1355 unsigned long flags;
1356 unsigned e;
1357
1358 spin_lock_irqsave(&fusbh200->lock, flags);
1359
1360 events = fusbh200->enabled_hrtimer_events;
1361 fusbh200->enabled_hrtimer_events = 0;
1362 fusbh200->next_hrtimer_event = FUSBH200_HRTIMER_NO_EVENT;
1363
1364
1365
1366
1367
1368 now = ktime_get();
1369 for_each_set_bit(e, &events, FUSBH200_HRTIMER_NUM_EVENTS) {
1370 if (now.tv64 >= fusbh200->hr_timeouts[e].tv64)
1371 event_handlers[e](fusbh200);
1372 else
1373 fusbh200_enable_event(fusbh200, e, false);
1374 }
1375
1376 spin_unlock_irqrestore(&fusbh200->lock, flags);
1377 return HRTIMER_NORESTART;
1378}
1379
1380
1381
1382#define fusbh200_bus_suspend NULL
1383#define fusbh200_bus_resume NULL
1384
1385
1386
1387static int check_reset_complete (
1388 struct fusbh200_hcd *fusbh200,
1389 int index,
1390 u32 __iomem *status_reg,
1391 int port_status
1392) {
1393 if (!(port_status & PORT_CONNECT))
1394 return port_status;
1395
1396
1397 if (!(port_status & PORT_PE)) {
1398
1399 fusbh200_dbg (fusbh200,
1400 "Failed to enable port %d on root hub TT\n",
1401 index+1);
1402 return port_status;
1403 } else {
1404 fusbh200_dbg(fusbh200, "port %d reset complete, port enabled\n",
1405 index + 1);
1406 }
1407
1408 return port_status;
1409}
1410
1411
1412
1413
1414
1415
1416static int
1417fusbh200_hub_status_data (struct usb_hcd *hcd, char *buf)
1418{
1419 struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200 (hcd);
1420 u32 temp, status;
1421 u32 mask;
1422 int retval = 1;
1423 unsigned long flags;
1424
1425
1426 buf [0] = 0;
1427
1428
1429
1430
1431 status = fusbh200->resuming_ports;
1432
1433 mask = PORT_CSC | PORT_PEC;
1434
1435
1436
1437
1438
1439 spin_lock_irqsave (&fusbh200->lock, flags);
1440
1441 temp = fusbh200_readl(fusbh200, &fusbh200->regs->port_status);
1442
1443
1444
1445
1446
1447
1448
1449
1450 if ((temp & mask) != 0 || test_bit(0, &fusbh200->port_c_suspend)
1451 || (fusbh200->reset_done[0] && time_after_eq(
1452 jiffies, fusbh200->reset_done[0]))) {
1453 buf [0] |= 1 << 1;
1454 status = STS_PCD;
1455 }
1456
1457 spin_unlock_irqrestore (&fusbh200->lock, flags);
1458 return status ? retval : 0;
1459}
1460
1461
1462
1463static void
1464fusbh200_hub_descriptor (
1465 struct fusbh200_hcd *fusbh200,
1466 struct usb_hub_descriptor *desc
1467) {
1468 int ports = HCS_N_PORTS (fusbh200->hcs_params);
1469 u16 temp;
1470
1471 desc->bDescriptorType = USB_DT_HUB;
1472 desc->bPwrOn2PwrGood = 10;
1473 desc->bHubContrCurrent = 0;
1474
1475 desc->bNbrPorts = ports;
1476 temp = 1 + (ports / 8);
1477 desc->bDescLength = 7 + 2 * temp;
1478
1479
1480 memset(&desc->u.hs.DeviceRemovable[0], 0, temp);
1481 memset(&desc->u.hs.DeviceRemovable[temp], 0xff, temp);
1482
1483 temp = HUB_CHAR_INDV_PORT_OCPM;
1484 temp |= HUB_CHAR_NO_LPSM;
1485 desc->wHubCharacteristics = cpu_to_le16(temp);
1486}
1487
1488
1489
1490static int fusbh200_hub_control (
1491 struct usb_hcd *hcd,
1492 u16 typeReq,
1493 u16 wValue,
1494 u16 wIndex,
1495 char *buf,
1496 u16 wLength
1497) {
1498 struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200 (hcd);
1499 int ports = HCS_N_PORTS (fusbh200->hcs_params);
1500 u32 __iomem *status_reg = &fusbh200->regs->port_status;
1501 u32 temp, temp1, status;
1502 unsigned long flags;
1503 int retval = 0;
1504 unsigned selector;
1505
1506
1507
1508
1509
1510
1511
1512
1513 spin_lock_irqsave (&fusbh200->lock, flags);
1514 switch (typeReq) {
1515 case ClearHubFeature:
1516 switch (wValue) {
1517 case C_HUB_LOCAL_POWER:
1518 case C_HUB_OVER_CURRENT:
1519
1520 break;
1521 default:
1522 goto error;
1523 }
1524 break;
1525 case ClearPortFeature:
1526 if (!wIndex || wIndex > ports)
1527 goto error;
1528 wIndex--;
1529 temp = fusbh200_readl(fusbh200, status_reg);
1530 temp &= ~PORT_RWC_BITS;
1531
1532
1533
1534
1535
1536
1537
1538
1539 switch (wValue) {
1540 case USB_PORT_FEAT_ENABLE:
1541 fusbh200_writel(fusbh200, temp & ~PORT_PE, status_reg);
1542 break;
1543 case USB_PORT_FEAT_C_ENABLE:
1544 fusbh200_writel(fusbh200, temp | PORT_PEC, status_reg);
1545 break;
1546 case USB_PORT_FEAT_SUSPEND:
1547 if (temp & PORT_RESET)
1548 goto error;
1549 if (!(temp & PORT_SUSPEND))
1550 break;
1551 if ((temp & PORT_PE) == 0)
1552 goto error;
1553
1554 fusbh200_writel(fusbh200, temp | PORT_RESUME, status_reg);
1555 fusbh200->reset_done[wIndex] = jiffies
1556 + msecs_to_jiffies(USB_RESUME_TIMEOUT);
1557 break;
1558 case USB_PORT_FEAT_C_SUSPEND:
1559 clear_bit(wIndex, &fusbh200->port_c_suspend);
1560 break;
1561 case USB_PORT_FEAT_C_CONNECTION:
1562 fusbh200_writel(fusbh200, temp | PORT_CSC, status_reg);
1563 break;
1564 case USB_PORT_FEAT_C_OVER_CURRENT:
1565 fusbh200_writel(fusbh200, temp | BMISR_OVC, &fusbh200->regs->bmisr);
1566 break;
1567 case USB_PORT_FEAT_C_RESET:
1568
1569 break;
1570 default:
1571 goto error;
1572 }
1573 fusbh200_readl(fusbh200, &fusbh200->regs->command);
1574 break;
1575 case GetHubDescriptor:
1576 fusbh200_hub_descriptor (fusbh200, (struct usb_hub_descriptor *)
1577 buf);
1578 break;
1579 case GetHubStatus:
1580
1581 memset (buf, 0, 4);
1582
1583 break;
1584 case GetPortStatus:
1585 if (!wIndex || wIndex > ports)
1586 goto error;
1587 wIndex--;
1588 status = 0;
1589 temp = fusbh200_readl(fusbh200, status_reg);
1590
1591
1592 if (temp & PORT_CSC)
1593 status |= USB_PORT_STAT_C_CONNECTION << 16;
1594 if (temp & PORT_PEC)
1595 status |= USB_PORT_STAT_C_ENABLE << 16;
1596
1597 temp1 = fusbh200_readl(fusbh200, &fusbh200->regs->bmisr);
1598 if (temp1 & BMISR_OVC)
1599 status |= USB_PORT_STAT_C_OVERCURRENT << 16;
1600
1601
1602 if (temp & PORT_RESUME) {
1603
1604
1605 if (!fusbh200->reset_done[wIndex]) {
1606
1607 fusbh200->reset_done[wIndex] = jiffies
1608 + msecs_to_jiffies(20);
1609
1610 mod_timer(&fusbh200_to_hcd(fusbh200)->rh_timer,
1611 fusbh200->reset_done[wIndex]);
1612 }
1613
1614
1615 else if (time_after_eq(jiffies,
1616 fusbh200->reset_done[wIndex])) {
1617 clear_bit(wIndex, &fusbh200->suspended_ports);
1618 set_bit(wIndex, &fusbh200->port_c_suspend);
1619 fusbh200->reset_done[wIndex] = 0;
1620
1621
1622 temp = fusbh200_readl(fusbh200, status_reg);
1623 fusbh200_writel(fusbh200,
1624 temp & ~(PORT_RWC_BITS | PORT_RESUME),
1625 status_reg);
1626 clear_bit(wIndex, &fusbh200->resuming_ports);
1627 retval = handshake(fusbh200, status_reg,
1628 PORT_RESUME, 0, 2000 );
1629 if (retval != 0) {
1630 fusbh200_err(fusbh200,
1631 "port %d resume error %d\n",
1632 wIndex + 1, retval);
1633 goto error;
1634 }
1635 temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10));
1636 }
1637 }
1638
1639
1640 if ((temp & PORT_RESET)
1641 && time_after_eq(jiffies,
1642 fusbh200->reset_done[wIndex])) {
1643 status |= USB_PORT_STAT_C_RESET << 16;
1644 fusbh200->reset_done [wIndex] = 0;
1645 clear_bit(wIndex, &fusbh200->resuming_ports);
1646
1647
1648 fusbh200_writel(fusbh200, temp & ~(PORT_RWC_BITS | PORT_RESET),
1649 status_reg);
1650
1651
1652
1653 retval = handshake(fusbh200, status_reg,
1654 PORT_RESET, 0, 1000);
1655 if (retval != 0) {
1656 fusbh200_err (fusbh200, "port %d reset error %d\n",
1657 wIndex + 1, retval);
1658 goto error;
1659 }
1660
1661
1662 temp = check_reset_complete (fusbh200, wIndex, status_reg,
1663 fusbh200_readl(fusbh200, status_reg));
1664 }
1665
1666 if (!(temp & (PORT_RESUME|PORT_RESET))) {
1667 fusbh200->reset_done[wIndex] = 0;
1668 clear_bit(wIndex, &fusbh200->resuming_ports);
1669 }
1670
1671
1672 if ((temp & PORT_CONNECT) &&
1673 test_bit(wIndex, &fusbh200->companion_ports)) {
1674 temp &= ~PORT_RWC_BITS;
1675 fusbh200_writel(fusbh200, temp, status_reg);
1676 fusbh200_dbg(fusbh200, "port %d --> companion\n", wIndex + 1);
1677 temp = fusbh200_readl(fusbh200, status_reg);
1678 }
1679
1680
1681
1682
1683
1684
1685
1686 if (temp & PORT_CONNECT) {
1687 status |= USB_PORT_STAT_CONNECTION;
1688 status |= fusbh200_port_speed(fusbh200, temp);
1689 }
1690 if (temp & PORT_PE)
1691 status |= USB_PORT_STAT_ENABLE;
1692
1693
1694 if (temp & (PORT_SUSPEND|PORT_RESUME)) {
1695 status |= USB_PORT_STAT_SUSPEND;
1696 } else if (test_bit(wIndex, &fusbh200->suspended_ports)) {
1697 clear_bit(wIndex, &fusbh200->suspended_ports);
1698 clear_bit(wIndex, &fusbh200->resuming_ports);
1699 fusbh200->reset_done[wIndex] = 0;
1700 if (temp & PORT_PE)
1701 set_bit(wIndex, &fusbh200->port_c_suspend);
1702 }
1703
1704 temp1 = fusbh200_readl(fusbh200, &fusbh200->regs->bmisr);
1705 if (temp1 & BMISR_OVC)
1706 status |= USB_PORT_STAT_OVERCURRENT;
1707 if (temp & PORT_RESET)
1708 status |= USB_PORT_STAT_RESET;
1709 if (test_bit(wIndex, &fusbh200->port_c_suspend))
1710 status |= USB_PORT_STAT_C_SUSPEND << 16;
1711
1712 if (status & ~0xffff)
1713 dbg_port(fusbh200, "GetStatus", wIndex + 1, temp);
1714 put_unaligned_le32(status, buf);
1715 break;
1716 case SetHubFeature:
1717 switch (wValue) {
1718 case C_HUB_LOCAL_POWER:
1719 case C_HUB_OVER_CURRENT:
1720
1721 break;
1722 default:
1723 goto error;
1724 }
1725 break;
1726 case SetPortFeature:
1727 selector = wIndex >> 8;
1728 wIndex &= 0xff;
1729
1730 if (!wIndex || wIndex > ports)
1731 goto error;
1732 wIndex--;
1733 temp = fusbh200_readl(fusbh200, status_reg);
1734 temp &= ~PORT_RWC_BITS;
1735 switch (wValue) {
1736 case USB_PORT_FEAT_SUSPEND:
1737 if ((temp & PORT_PE) == 0
1738 || (temp & PORT_RESET) != 0)
1739 goto error;
1740
1741
1742
1743
1744
1745 fusbh200_writel(fusbh200, temp | PORT_SUSPEND, status_reg);
1746 set_bit(wIndex, &fusbh200->suspended_ports);
1747 break;
1748 case USB_PORT_FEAT_RESET:
1749 if (temp & PORT_RESUME)
1750 goto error;
1751
1752
1753
1754
1755 fusbh200_dbg(fusbh200, "port %d reset\n", wIndex + 1);
1756 temp |= PORT_RESET;
1757 temp &= ~PORT_PE;
1758
1759
1760
1761
1762
1763 fusbh200->reset_done [wIndex] = jiffies
1764 + msecs_to_jiffies (50);
1765 fusbh200_writel(fusbh200, temp, status_reg);
1766 break;
1767
1768
1769
1770
1771
1772
1773
1774 case USB_PORT_FEAT_TEST:
1775 if (!selector || selector > 5)
1776 goto error;
1777 spin_unlock_irqrestore(&fusbh200->lock, flags);
1778 fusbh200_quiesce(fusbh200);
1779 spin_lock_irqsave(&fusbh200->lock, flags);
1780
1781
1782 temp = fusbh200_readl(fusbh200, status_reg) & ~PORT_RWC_BITS;
1783 if (temp & PORT_PE)
1784 fusbh200_writel(fusbh200, temp | PORT_SUSPEND,
1785 status_reg);
1786
1787 spin_unlock_irqrestore(&fusbh200->lock, flags);
1788 fusbh200_halt(fusbh200);
1789 spin_lock_irqsave(&fusbh200->lock, flags);
1790
1791 temp = fusbh200_readl(fusbh200, status_reg);
1792 temp |= selector << 16;
1793 fusbh200_writel(fusbh200, temp, status_reg);
1794 break;
1795
1796 default:
1797 goto error;
1798 }
1799 fusbh200_readl(fusbh200, &fusbh200->regs->command);
1800 break;
1801
1802 default:
1803error:
1804
1805 retval = -EPIPE;
1806 }
1807 spin_unlock_irqrestore (&fusbh200->lock, flags);
1808 return retval;
1809}
1810
1811static void __maybe_unused fusbh200_relinquish_port(struct usb_hcd *hcd,
1812 int portnum)
1813{
1814 return;
1815}
1816
1817static int __maybe_unused fusbh200_port_handed_over(struct usb_hcd *hcd,
1818 int portnum)
1819{
1820 return 0;
1821}
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838static inline void fusbh200_qtd_init(struct fusbh200_hcd *fusbh200, struct fusbh200_qtd *qtd,
1839 dma_addr_t dma)
1840{
1841 memset (qtd, 0, sizeof *qtd);
1842 qtd->qtd_dma = dma;
1843 qtd->hw_token = cpu_to_hc32(fusbh200, QTD_STS_HALT);
1844 qtd->hw_next = FUSBH200_LIST_END(fusbh200);
1845 qtd->hw_alt_next = FUSBH200_LIST_END(fusbh200);
1846 INIT_LIST_HEAD (&qtd->qtd_list);
1847}
1848
1849static struct fusbh200_qtd *fusbh200_qtd_alloc (struct fusbh200_hcd *fusbh200, gfp_t flags)
1850{
1851 struct fusbh200_qtd *qtd;
1852 dma_addr_t dma;
1853
1854 qtd = dma_pool_alloc (fusbh200->qtd_pool, flags, &dma);
1855 if (qtd != NULL) {
1856 fusbh200_qtd_init(fusbh200, qtd, dma);
1857 }
1858 return qtd;
1859}
1860
1861static inline void fusbh200_qtd_free (struct fusbh200_hcd *fusbh200, struct fusbh200_qtd *qtd)
1862{
1863 dma_pool_free (fusbh200->qtd_pool, qtd, qtd->qtd_dma);
1864}
1865
1866
1867static void qh_destroy(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
1868{
1869
1870 if (!list_empty (&qh->qtd_list) || qh->qh_next.ptr) {
1871 fusbh200_dbg (fusbh200, "unused qh not empty!\n");
1872 BUG ();
1873 }
1874 if (qh->dummy)
1875 fusbh200_qtd_free (fusbh200, qh->dummy);
1876 dma_pool_free(fusbh200->qh_pool, qh->hw, qh->qh_dma);
1877 kfree(qh);
1878}
1879
1880static struct fusbh200_qh *fusbh200_qh_alloc (struct fusbh200_hcd *fusbh200, gfp_t flags)
1881{
1882 struct fusbh200_qh *qh;
1883 dma_addr_t dma;
1884
1885 qh = kzalloc(sizeof *qh, GFP_ATOMIC);
1886 if (!qh)
1887 goto done;
1888 qh->hw = (struct fusbh200_qh_hw *)
1889 dma_pool_alloc(fusbh200->qh_pool, flags, &dma);
1890 if (!qh->hw)
1891 goto fail;
1892 memset(qh->hw, 0, sizeof *qh->hw);
1893 qh->qh_dma = dma;
1894
1895 INIT_LIST_HEAD (&qh->qtd_list);
1896
1897
1898 qh->dummy = fusbh200_qtd_alloc (fusbh200, flags);
1899 if (qh->dummy == NULL) {
1900 fusbh200_dbg (fusbh200, "no dummy td\n");
1901 goto fail1;
1902 }
1903done:
1904 return qh;
1905fail1:
1906 dma_pool_free(fusbh200->qh_pool, qh->hw, qh->qh_dma);
1907fail:
1908 kfree(qh);
1909 return NULL;
1910}
1911
1912
1913
1914
1915
1916
1917
1918
1919static void fusbh200_mem_cleanup (struct fusbh200_hcd *fusbh200)
1920{
1921 if (fusbh200->async)
1922 qh_destroy(fusbh200, fusbh200->async);
1923 fusbh200->async = NULL;
1924
1925 if (fusbh200->dummy)
1926 qh_destroy(fusbh200, fusbh200->dummy);
1927 fusbh200->dummy = NULL;
1928
1929
1930 if (fusbh200->qtd_pool)
1931 dma_pool_destroy (fusbh200->qtd_pool);
1932 fusbh200->qtd_pool = NULL;
1933
1934 if (fusbh200->qh_pool) {
1935 dma_pool_destroy (fusbh200->qh_pool);
1936 fusbh200->qh_pool = NULL;
1937 }
1938
1939 if (fusbh200->itd_pool)
1940 dma_pool_destroy (fusbh200->itd_pool);
1941 fusbh200->itd_pool = NULL;
1942
1943 if (fusbh200->periodic)
1944 dma_free_coherent (fusbh200_to_hcd(fusbh200)->self.controller,
1945 fusbh200->periodic_size * sizeof (u32),
1946 fusbh200->periodic, fusbh200->periodic_dma);
1947 fusbh200->periodic = NULL;
1948
1949
1950 kfree(fusbh200->pshadow);
1951 fusbh200->pshadow = NULL;
1952}
1953
1954
1955static int fusbh200_mem_init (struct fusbh200_hcd *fusbh200, gfp_t flags)
1956{
1957 int i;
1958
1959
1960 fusbh200->qtd_pool = dma_pool_create ("fusbh200_qtd",
1961 fusbh200_to_hcd(fusbh200)->self.controller,
1962 sizeof (struct fusbh200_qtd),
1963 32 ,
1964 4096 );
1965 if (!fusbh200->qtd_pool) {
1966 goto fail;
1967 }
1968
1969
1970 fusbh200->qh_pool = dma_pool_create ("fusbh200_qh",
1971 fusbh200_to_hcd(fusbh200)->self.controller,
1972 sizeof(struct fusbh200_qh_hw),
1973 32 ,
1974 4096 );
1975 if (!fusbh200->qh_pool) {
1976 goto fail;
1977 }
1978 fusbh200->async = fusbh200_qh_alloc (fusbh200, flags);
1979 if (!fusbh200->async) {
1980 goto fail;
1981 }
1982
1983
1984 fusbh200->itd_pool = dma_pool_create ("fusbh200_itd",
1985 fusbh200_to_hcd(fusbh200)->self.controller,
1986 sizeof (struct fusbh200_itd),
1987 64 ,
1988 4096 );
1989 if (!fusbh200->itd_pool) {
1990 goto fail;
1991 }
1992
1993
1994 fusbh200->periodic = (__le32 *)
1995 dma_alloc_coherent (fusbh200_to_hcd(fusbh200)->self.controller,
1996 fusbh200->periodic_size * sizeof(__le32),
1997 &fusbh200->periodic_dma, 0);
1998 if (fusbh200->periodic == NULL) {
1999 goto fail;
2000 }
2001
2002 for (i = 0; i < fusbh200->periodic_size; i++)
2003 fusbh200->periodic[i] = FUSBH200_LIST_END(fusbh200);
2004
2005
2006 fusbh200->pshadow = kcalloc(fusbh200->periodic_size, sizeof(void *), flags);
2007 if (fusbh200->pshadow != NULL)
2008 return 0;
2009
2010fail:
2011 fusbh200_dbg (fusbh200, "couldn't init memory\n");
2012 fusbh200_mem_cleanup (fusbh200);
2013 return -ENOMEM;
2014}
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038static int
2039qtd_fill(struct fusbh200_hcd *fusbh200, struct fusbh200_qtd *qtd, dma_addr_t buf,
2040 size_t len, int token, int maxpacket)
2041{
2042 int i, count;
2043 u64 addr = buf;
2044
2045
2046 qtd->hw_buf[0] = cpu_to_hc32(fusbh200, (u32)addr);
2047 qtd->hw_buf_hi[0] = cpu_to_hc32(fusbh200, (u32)(addr >> 32));
2048 count = 0x1000 - (buf & 0x0fff);
2049 if (likely (len < count))
2050 count = len;
2051 else {
2052 buf += 0x1000;
2053 buf &= ~0x0fff;
2054
2055
2056 for (i = 1; count < len && i < 5; i++) {
2057 addr = buf;
2058 qtd->hw_buf[i] = cpu_to_hc32(fusbh200, (u32)addr);
2059 qtd->hw_buf_hi[i] = cpu_to_hc32(fusbh200,
2060 (u32)(addr >> 32));
2061 buf += 0x1000;
2062 if ((count + 0x1000) < len)
2063 count += 0x1000;
2064 else
2065 count = len;
2066 }
2067
2068
2069 if (count != len)
2070 count -= (count % maxpacket);
2071 }
2072 qtd->hw_token = cpu_to_hc32(fusbh200, (count << 16) | token);
2073 qtd->length = count;
2074
2075 return count;
2076}
2077
2078
2079
2080static inline void
2081qh_update (struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh, struct fusbh200_qtd *qtd)
2082{
2083 struct fusbh200_qh_hw *hw = qh->hw;
2084
2085
2086 BUG_ON(qh->qh_state != QH_STATE_IDLE);
2087
2088 hw->hw_qtd_next = QTD_NEXT(fusbh200, qtd->qtd_dma);
2089 hw->hw_alt_next = FUSBH200_LIST_END(fusbh200);
2090
2091
2092
2093
2094
2095
2096 if (!(hw->hw_info1 & cpu_to_hc32(fusbh200, QH_TOGGLE_CTL))) {
2097 unsigned is_out, epnum;
2098
2099 is_out = qh->is_out;
2100 epnum = (hc32_to_cpup(fusbh200, &hw->hw_info1) >> 8) & 0x0f;
2101 if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) {
2102 hw->hw_token &= ~cpu_to_hc32(fusbh200, QTD_TOGGLE);
2103 usb_settoggle (qh->dev, epnum, is_out, 1);
2104 }
2105 }
2106
2107 hw->hw_token &= cpu_to_hc32(fusbh200, QTD_TOGGLE | QTD_STS_PING);
2108}
2109
2110
2111
2112
2113
2114static void
2115qh_refresh (struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
2116{
2117 struct fusbh200_qtd *qtd;
2118
2119 if (list_empty (&qh->qtd_list))
2120 qtd = qh->dummy;
2121 else {
2122 qtd = list_entry (qh->qtd_list.next,
2123 struct fusbh200_qtd, qtd_list);
2124
2125
2126
2127
2128
2129
2130
2131 if (cpu_to_hc32(fusbh200, qtd->qtd_dma) == qh->hw->hw_current) {
2132 qh->hw->hw_qtd_next = qtd->hw_next;
2133 qtd = NULL;
2134 }
2135 }
2136
2137 if (qtd)
2138 qh_update (fusbh200, qh, qtd);
2139}
2140
2141
2142
2143static void qh_link_async(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh);
2144
2145static void fusbh200_clear_tt_buffer_complete(struct usb_hcd *hcd,
2146 struct usb_host_endpoint *ep)
2147{
2148 struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200(hcd);
2149 struct fusbh200_qh *qh = ep->hcpriv;
2150 unsigned long flags;
2151
2152 spin_lock_irqsave(&fusbh200->lock, flags);
2153 qh->clearing_tt = 0;
2154 if (qh->qh_state == QH_STATE_IDLE && !list_empty(&qh->qtd_list)
2155 && fusbh200->rh_state == FUSBH200_RH_RUNNING)
2156 qh_link_async(fusbh200, qh);
2157 spin_unlock_irqrestore(&fusbh200->lock, flags);
2158}
2159
2160static void fusbh200_clear_tt_buffer(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh,
2161 struct urb *urb, u32 token)
2162{
2163
2164
2165
2166
2167
2168
2169
2170 if (urb->dev->tt && !usb_pipeint(urb->pipe) && !qh->clearing_tt) {
2171 struct usb_device *tt = urb->dev->tt->hub;
2172
2173 dev_dbg(&tt->dev,
2174 "clear tt buffer port %d, a%d ep%d t%08x\n",
2175 urb->dev->ttport, urb->dev->devnum,
2176 usb_pipeendpoint(urb->pipe), token);
2177
2178 if (urb->dev->tt->hub !=
2179 fusbh200_to_hcd(fusbh200)->self.root_hub) {
2180 if (usb_hub_clear_tt_buffer(urb) == 0)
2181 qh->clearing_tt = 1;
2182 }
2183 }
2184}
2185
2186static int qtd_copy_status (
2187 struct fusbh200_hcd *fusbh200,
2188 struct urb *urb,
2189 size_t length,
2190 u32 token
2191)
2192{
2193 int status = -EINPROGRESS;
2194
2195
2196 if (likely (QTD_PID (token) != 2))
2197 urb->actual_length += length - QTD_LENGTH (token);
2198
2199
2200 if (unlikely(urb->unlinked))
2201 return status;
2202
2203
2204 if (unlikely (IS_SHORT_READ (token)))
2205 status = -EREMOTEIO;
2206
2207
2208 if (token & QTD_STS_HALT) {
2209 if (token & QTD_STS_BABBLE) {
2210
2211 status = -EOVERFLOW;
2212
2213 } else if (QTD_CERR(token)) {
2214 status = -EPIPE;
2215
2216
2217
2218
2219
2220 } else if (token & QTD_STS_MMF) {
2221
2222 status = -EPROTO;
2223 } else if (token & QTD_STS_DBE) {
2224 status = (QTD_PID (token) == 1)
2225 ? -ENOSR
2226 : -ECOMM;
2227 } else if (token & QTD_STS_XACT) {
2228
2229 fusbh200_dbg(fusbh200, "devpath %s ep%d%s 3strikes\n",
2230 urb->dev->devpath,
2231 usb_pipeendpoint(urb->pipe),
2232 usb_pipein(urb->pipe) ? "in" : "out");
2233 status = -EPROTO;
2234 } else {
2235 status = -EPROTO;
2236 }
2237
2238 fusbh200_dbg(fusbh200,
2239 "dev%d ep%d%s qtd token %08x --> status %d\n",
2240 usb_pipedevice (urb->pipe),
2241 usb_pipeendpoint (urb->pipe),
2242 usb_pipein (urb->pipe) ? "in" : "out",
2243 token, status);
2244 }
2245
2246 return status;
2247}
2248
2249static void
2250fusbh200_urb_done(struct fusbh200_hcd *fusbh200, struct urb *urb, int status)
2251__releases(fusbh200->lock)
2252__acquires(fusbh200->lock)
2253{
2254 if (likely (urb->hcpriv != NULL)) {
2255 struct fusbh200_qh *qh = (struct fusbh200_qh *) urb->hcpriv;
2256
2257
2258 if ((qh->hw->hw_info2 & cpu_to_hc32(fusbh200, QH_SMASK)) != 0) {
2259
2260
2261 fusbh200_to_hcd(fusbh200)->self.bandwidth_int_reqs--;
2262 }
2263 }
2264
2265 if (unlikely(urb->unlinked)) {
2266 COUNT(fusbh200->stats.unlink);
2267 } else {
2268
2269 if (status == -EINPROGRESS || status == -EREMOTEIO)
2270 status = 0;
2271 COUNT(fusbh200->stats.complete);
2272 }
2273
2274#ifdef FUSBH200_URB_TRACE
2275 fusbh200_dbg (fusbh200,
2276 "%s %s urb %p ep%d%s status %d len %d/%d\n",
2277 __func__, urb->dev->devpath, urb,
2278 usb_pipeendpoint (urb->pipe),
2279 usb_pipein (urb->pipe) ? "in" : "out",
2280 status,
2281 urb->actual_length, urb->transfer_buffer_length);
2282#endif
2283
2284
2285 usb_hcd_unlink_urb_from_ep(fusbh200_to_hcd(fusbh200), urb);
2286 spin_unlock (&fusbh200->lock);
2287 usb_hcd_giveback_urb(fusbh200_to_hcd(fusbh200), urb, status);
2288 spin_lock (&fusbh200->lock);
2289}
2290
2291static int qh_schedule (struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh);
2292
2293
2294
2295
2296
2297
2298static unsigned
2299qh_completions (struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
2300{
2301 struct fusbh200_qtd *last, *end = qh->dummy;
2302 struct list_head *entry, *tmp;
2303 int last_status;
2304 int stopped;
2305 unsigned count = 0;
2306 u8 state;
2307 struct fusbh200_qh_hw *hw = qh->hw;
2308
2309 if (unlikely (list_empty (&qh->qtd_list)))
2310 return count;
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322 state = qh->qh_state;
2323 qh->qh_state = QH_STATE_COMPLETING;
2324 stopped = (state == QH_STATE_IDLE);
2325
2326 rescan:
2327 last = NULL;
2328 last_status = -EINPROGRESS;
2329 qh->needs_rescan = 0;
2330
2331
2332
2333
2334
2335
2336 list_for_each_safe (entry, tmp, &qh->qtd_list) {
2337 struct fusbh200_qtd *qtd;
2338 struct urb *urb;
2339 u32 token = 0;
2340
2341 qtd = list_entry (entry, struct fusbh200_qtd, qtd_list);
2342 urb = qtd->urb;
2343
2344
2345 if (last) {
2346 if (likely (last->urb != urb)) {
2347 fusbh200_urb_done(fusbh200, last->urb, last_status);
2348 count++;
2349 last_status = -EINPROGRESS;
2350 }
2351 fusbh200_qtd_free (fusbh200, last);
2352 last = NULL;
2353 }
2354
2355
2356 if (qtd == end)
2357 break;
2358
2359
2360 rmb ();
2361 token = hc32_to_cpu(fusbh200, qtd->hw_token);
2362
2363
2364 retry_xacterr:
2365 if ((token & QTD_STS_ACTIVE) == 0) {
2366
2367
2368 if (token & QTD_STS_DBE)
2369 fusbh200_dbg(fusbh200,
2370 "detected DataBufferErr for urb %p ep%d%s len %d, qtd %p [qh %p]\n",
2371 urb,
2372 usb_endpoint_num(&urb->ep->desc),
2373 usb_endpoint_dir_in(&urb->ep->desc) ? "in" : "out",
2374 urb->transfer_buffer_length,
2375 qtd,
2376 qh);
2377
2378
2379
2380
2381 if ((token & QTD_STS_HALT) != 0) {
2382
2383
2384
2385
2386 if ((token & QTD_STS_XACT) &&
2387 QTD_CERR(token) == 0 &&
2388 ++qh->xacterrs < QH_XACTERR_MAX &&
2389 !urb->unlinked) {
2390 fusbh200_dbg(fusbh200,
2391 "detected XactErr len %zu/%zu retry %d\n",
2392 qtd->length - QTD_LENGTH(token), qtd->length, qh->xacterrs);
2393
2394
2395
2396
2397
2398
2399 token &= ~QTD_STS_HALT;
2400 token |= QTD_STS_ACTIVE |
2401 (FUSBH200_TUNE_CERR << 10);
2402 qtd->hw_token = cpu_to_hc32(fusbh200,
2403 token);
2404 wmb();
2405 hw->hw_token = cpu_to_hc32(fusbh200,
2406 token);
2407 goto retry_xacterr;
2408 }
2409 stopped = 1;
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420 } else if (IS_SHORT_READ (token)
2421 && !(qtd->hw_alt_next
2422 & FUSBH200_LIST_END(fusbh200))) {
2423 stopped = 1;
2424 }
2425
2426
2427 } else if (likely (!stopped
2428 && fusbh200->rh_state >= FUSBH200_RH_RUNNING)) {
2429 break;
2430
2431
2432 } else {
2433 stopped = 1;
2434
2435
2436 if (fusbh200->rh_state < FUSBH200_RH_RUNNING)
2437 last_status = -ESHUTDOWN;
2438
2439
2440
2441
2442 else if (last_status == -EINPROGRESS && !urb->unlinked)
2443 continue;
2444
2445
2446 if (state == QH_STATE_IDLE
2447 && cpu_to_hc32(fusbh200, qtd->qtd_dma)
2448 == hw->hw_current) {
2449 token = hc32_to_cpu(fusbh200, hw->hw_token);
2450
2451
2452
2453
2454
2455 fusbh200_clear_tt_buffer(fusbh200, qh, urb, token);
2456 }
2457 }
2458
2459
2460
2461
2462
2463
2464
2465
2466 if (last_status == -EINPROGRESS) {
2467 last_status = qtd_copy_status(fusbh200, urb,
2468 qtd->length, token);
2469 if (last_status == -EREMOTEIO
2470 && (qtd->hw_alt_next
2471 & FUSBH200_LIST_END(fusbh200)))
2472 last_status = -EINPROGRESS;
2473
2474
2475
2476
2477 if (unlikely(last_status != -EINPROGRESS &&
2478 last_status != -EREMOTEIO)) {
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488 if (last_status != -EPIPE)
2489 fusbh200_clear_tt_buffer(fusbh200, qh, urb,
2490 token);
2491 }
2492 }
2493
2494
2495
2496
2497 if (stopped && qtd->qtd_list.prev != &qh->qtd_list) {
2498 last = list_entry (qtd->qtd_list.prev,
2499 struct fusbh200_qtd, qtd_list);
2500 last->hw_next = qtd->hw_next;
2501 }
2502
2503
2504 list_del (&qtd->qtd_list);
2505 last = qtd;
2506
2507
2508 qh->xacterrs = 0;
2509 }
2510
2511
2512 if (likely (last != NULL)) {
2513 fusbh200_urb_done(fusbh200, last->urb, last_status);
2514 count++;
2515 fusbh200_qtd_free (fusbh200, last);
2516 }
2517
2518
2519 if (unlikely(qh->needs_rescan)) {
2520
2521 if (state == QH_STATE_IDLE)
2522 goto rescan;
2523
2524
2525
2526
2527
2528
2529 if (state != QH_STATE_LINKED)
2530 qh->needs_rescan = 0;
2531 }
2532
2533
2534 qh->qh_state = state;
2535
2536
2537
2538
2539
2540 if (stopped != 0 || hw->hw_qtd_next == FUSBH200_LIST_END(fusbh200)) {
2541 switch (state) {
2542 case QH_STATE_IDLE:
2543 qh_refresh(fusbh200, qh);
2544 break;
2545 case QH_STATE_LINKED:
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559 qh->needs_rescan = 1;
2560 break;
2561
2562 }
2563 }
2564
2565 return count;
2566}
2567
2568
2569
2570
2571#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
2572
2573#define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
2574
2575
2576
2577
2578
2579static void qtd_list_free (
2580 struct fusbh200_hcd *fusbh200,
2581 struct urb *urb,
2582 struct list_head *qtd_list
2583) {
2584 struct list_head *entry, *temp;
2585
2586 list_for_each_safe (entry, temp, qtd_list) {
2587 struct fusbh200_qtd *qtd;
2588
2589 qtd = list_entry (entry, struct fusbh200_qtd, qtd_list);
2590 list_del (&qtd->qtd_list);
2591 fusbh200_qtd_free (fusbh200, qtd);
2592 }
2593}
2594
2595
2596
2597
2598static struct list_head *
2599qh_urb_transaction (
2600 struct fusbh200_hcd *fusbh200,
2601 struct urb *urb,
2602 struct list_head *head,
2603 gfp_t flags
2604) {
2605 struct fusbh200_qtd *qtd, *qtd_prev;
2606 dma_addr_t buf;
2607 int len, this_sg_len, maxpacket;
2608 int is_input;
2609 u32 token;
2610 int i;
2611 struct scatterlist *sg;
2612
2613
2614
2615
2616 qtd = fusbh200_qtd_alloc (fusbh200, flags);
2617 if (unlikely (!qtd))
2618 return NULL;
2619 list_add_tail (&qtd->qtd_list, head);
2620 qtd->urb = urb;
2621
2622 token = QTD_STS_ACTIVE;
2623 token |= (FUSBH200_TUNE_CERR << 10);
2624
2625
2626 len = urb->transfer_buffer_length;
2627 is_input = usb_pipein (urb->pipe);
2628 if (usb_pipecontrol (urb->pipe)) {
2629
2630 qtd_fill(fusbh200, qtd, urb->setup_dma,
2631 sizeof (struct usb_ctrlrequest),
2632 token | (2 << 8), 8);
2633
2634
2635 token ^= QTD_TOGGLE;
2636 qtd_prev = qtd;
2637 qtd = fusbh200_qtd_alloc (fusbh200, flags);
2638 if (unlikely (!qtd))
2639 goto cleanup;
2640 qtd->urb = urb;
2641 qtd_prev->hw_next = QTD_NEXT(fusbh200, qtd->qtd_dma);
2642 list_add_tail (&qtd->qtd_list, head);
2643
2644
2645 if (len == 0)
2646 token |= (1 << 8);
2647 }
2648
2649
2650
2651
2652 i = urb->num_mapped_sgs;
2653 if (len > 0 && i > 0) {
2654 sg = urb->sg;
2655 buf = sg_dma_address(sg);
2656
2657
2658
2659
2660 this_sg_len = min_t(int, sg_dma_len(sg), len);
2661 } else {
2662 sg = NULL;
2663 buf = urb->transfer_dma;
2664 this_sg_len = len;
2665 }
2666
2667 if (is_input)
2668 token |= (1 << 8);
2669
2670
2671 maxpacket = max_packet(usb_maxpacket(urb->dev, urb->pipe, !is_input));
2672
2673
2674
2675
2676
2677
2678 for (;;) {
2679 int this_qtd_len;
2680
2681 this_qtd_len = qtd_fill(fusbh200, qtd, buf, this_sg_len, token,
2682 maxpacket);
2683 this_sg_len -= this_qtd_len;
2684 len -= this_qtd_len;
2685 buf += this_qtd_len;
2686
2687
2688
2689
2690
2691
2692 if (is_input)
2693 qtd->hw_alt_next = fusbh200->async->hw->hw_alt_next;
2694
2695
2696 if ((maxpacket & (this_qtd_len + (maxpacket - 1))) == 0)
2697 token ^= QTD_TOGGLE;
2698
2699 if (likely(this_sg_len <= 0)) {
2700 if (--i <= 0 || len <= 0)
2701 break;
2702 sg = sg_next(sg);
2703 buf = sg_dma_address(sg);
2704 this_sg_len = min_t(int, sg_dma_len(sg), len);
2705 }
2706
2707 qtd_prev = qtd;
2708 qtd = fusbh200_qtd_alloc (fusbh200, flags);
2709 if (unlikely (!qtd))
2710 goto cleanup;
2711 qtd->urb = urb;
2712 qtd_prev->hw_next = QTD_NEXT(fusbh200, qtd->qtd_dma);
2713 list_add_tail (&qtd->qtd_list, head);
2714 }
2715
2716
2717
2718
2719
2720
2721 if (likely ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0
2722 || usb_pipecontrol (urb->pipe)))
2723 qtd->hw_alt_next = FUSBH200_LIST_END(fusbh200);
2724
2725
2726
2727
2728
2729
2730 if (likely (urb->transfer_buffer_length != 0)) {
2731 int one_more = 0;
2732
2733 if (usb_pipecontrol (urb->pipe)) {
2734 one_more = 1;
2735 token ^= 0x0100;
2736 token |= QTD_TOGGLE;
2737 } else if (usb_pipeout(urb->pipe)
2738 && (urb->transfer_flags & URB_ZERO_PACKET)
2739 && !(urb->transfer_buffer_length % maxpacket)) {
2740 one_more = 1;
2741 }
2742 if (one_more) {
2743 qtd_prev = qtd;
2744 qtd = fusbh200_qtd_alloc (fusbh200, flags);
2745 if (unlikely (!qtd))
2746 goto cleanup;
2747 qtd->urb = urb;
2748 qtd_prev->hw_next = QTD_NEXT(fusbh200, qtd->qtd_dma);
2749 list_add_tail (&qtd->qtd_list, head);
2750
2751
2752 qtd_fill(fusbh200, qtd, 0, 0, token, 0);
2753 }
2754 }
2755
2756
2757 if (likely (!(urb->transfer_flags & URB_NO_INTERRUPT)))
2758 qtd->hw_token |= cpu_to_hc32(fusbh200, QTD_IOC);
2759 return head;
2760
2761cleanup:
2762 qtd_list_free (fusbh200, urb, head);
2763 return NULL;
2764}
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783static struct fusbh200_qh *
2784qh_make (
2785 struct fusbh200_hcd *fusbh200,
2786 struct urb *urb,
2787 gfp_t flags
2788) {
2789 struct fusbh200_qh *qh = fusbh200_qh_alloc (fusbh200, flags);
2790 u32 info1 = 0, info2 = 0;
2791 int is_input, type;
2792 int maxp = 0;
2793 struct usb_tt *tt = urb->dev->tt;
2794 struct fusbh200_qh_hw *hw;
2795
2796 if (!qh)
2797 return qh;
2798
2799
2800
2801
2802 info1 |= usb_pipeendpoint (urb->pipe) << 8;
2803 info1 |= usb_pipedevice (urb->pipe) << 0;
2804
2805 is_input = usb_pipein (urb->pipe);
2806 type = usb_pipetype (urb->pipe);
2807 maxp = usb_maxpacket (urb->dev, urb->pipe, !is_input);
2808
2809
2810
2811
2812 if (max_packet(maxp) > 1024) {
2813 fusbh200_dbg(fusbh200, "bogus qh maxpacket %d\n", max_packet(maxp));
2814 goto done;
2815 }
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825 if (type == PIPE_INTERRUPT) {
2826 qh->usecs = NS_TO_US(usb_calc_bus_time(USB_SPEED_HIGH,
2827 is_input, 0,
2828 hb_mult(maxp) * max_packet(maxp)));
2829 qh->start = NO_FRAME;
2830
2831 if (urb->dev->speed == USB_SPEED_HIGH) {
2832 qh->c_usecs = 0;
2833 qh->gap_uf = 0;
2834
2835 qh->period = urb->interval >> 3;
2836 if (qh->period == 0 && urb->interval != 1) {
2837
2838
2839
2840
2841 urb->interval = 1;
2842 } else if (qh->period > fusbh200->periodic_size) {
2843 qh->period = fusbh200->periodic_size;
2844 urb->interval = qh->period << 3;
2845 }
2846 } else {
2847 int think_time;
2848
2849
2850 qh->gap_uf = 1 + usb_calc_bus_time (urb->dev->speed,
2851 is_input, 0, maxp) / (125 * 1000);
2852
2853
2854 if (is_input) {
2855 qh->c_usecs = qh->usecs + HS_USECS (0);
2856 qh->usecs = HS_USECS (1);
2857 } else {
2858 qh->usecs += HS_USECS (1);
2859 qh->c_usecs = HS_USECS (0);
2860 }
2861
2862 think_time = tt ? tt->think_time : 0;
2863 qh->tt_usecs = NS_TO_US (think_time +
2864 usb_calc_bus_time (urb->dev->speed,
2865 is_input, 0, max_packet (maxp)));
2866 qh->period = urb->interval;
2867 if (qh->period > fusbh200->periodic_size) {
2868 qh->period = fusbh200->periodic_size;
2869 urb->interval = qh->period;
2870 }
2871 }
2872 }
2873
2874
2875 qh->dev = urb->dev;
2876
2877
2878 switch (urb->dev->speed) {
2879 case USB_SPEED_LOW:
2880 info1 |= QH_LOW_SPEED;
2881
2882
2883 case USB_SPEED_FULL:
2884
2885 if (type != PIPE_INTERRUPT)
2886 info1 |= (FUSBH200_TUNE_RL_TT << 28);
2887 if (type == PIPE_CONTROL) {
2888 info1 |= QH_CONTROL_EP;
2889 info1 |= QH_TOGGLE_CTL;
2890 }
2891 info1 |= maxp << 16;
2892
2893 info2 |= (FUSBH200_TUNE_MULT_TT << 30);
2894
2895
2896
2897
2898 if (fusbh200_has_fsl_portno_bug(fusbh200))
2899 info2 |= (urb->dev->ttport-1) << 23;
2900 else
2901 info2 |= urb->dev->ttport << 23;
2902
2903
2904
2905
2906 if (tt && tt->hub != fusbh200_to_hcd(fusbh200)->self.root_hub)
2907 info2 |= tt->hub->devnum << 16;
2908
2909
2910
2911 break;
2912
2913 case USB_SPEED_HIGH:
2914 info1 |= QH_HIGH_SPEED;
2915 if (type == PIPE_CONTROL) {
2916 info1 |= (FUSBH200_TUNE_RL_HS << 28);
2917 info1 |= 64 << 16;
2918 info1 |= QH_TOGGLE_CTL;
2919 info2 |= (FUSBH200_TUNE_MULT_HS << 30);
2920 } else if (type == PIPE_BULK) {
2921 info1 |= (FUSBH200_TUNE_RL_HS << 28);
2922
2923
2924
2925
2926
2927
2928 info1 |= max_packet(maxp) << 16;
2929 info2 |= (FUSBH200_TUNE_MULT_HS << 30);
2930 } else {
2931 info1 |= max_packet (maxp) << 16;
2932 info2 |= hb_mult (maxp) << 30;
2933 }
2934 break;
2935 default:
2936 fusbh200_dbg(fusbh200, "bogus dev %p speed %d\n", urb->dev,
2937 urb->dev->speed);
2938done:
2939 qh_destroy(fusbh200, qh);
2940 return NULL;
2941 }
2942
2943
2944
2945
2946 qh->qh_state = QH_STATE_IDLE;
2947 hw = qh->hw;
2948 hw->hw_info1 = cpu_to_hc32(fusbh200, info1);
2949 hw->hw_info2 = cpu_to_hc32(fusbh200, info2);
2950 qh->is_out = !is_input;
2951 usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1);
2952 qh_refresh (fusbh200, qh);
2953 return qh;
2954}
2955
2956
2957
2958static void enable_async(struct fusbh200_hcd *fusbh200)
2959{
2960 if (fusbh200->async_count++)
2961 return;
2962
2963
2964 fusbh200->enabled_hrtimer_events &= ~BIT(FUSBH200_HRTIMER_DISABLE_ASYNC);
2965
2966
2967 fusbh200_poll_ASS(fusbh200);
2968 turn_on_io_watchdog(fusbh200);
2969}
2970
2971static void disable_async(struct fusbh200_hcd *fusbh200)
2972{
2973 if (--fusbh200->async_count)
2974 return;
2975
2976
2977 WARN_ON(fusbh200->async->qh_next.qh || fusbh200->async_unlink);
2978
2979
2980 fusbh200_poll_ASS(fusbh200);
2981}
2982
2983
2984
2985static void qh_link_async (struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
2986{
2987 __hc32 dma = QH_NEXT(fusbh200, qh->qh_dma);
2988 struct fusbh200_qh *head;
2989
2990
2991 if (unlikely(qh->clearing_tt))
2992 return;
2993
2994 WARN_ON(qh->qh_state != QH_STATE_IDLE);
2995
2996
2997 qh_refresh(fusbh200, qh);
2998
2999
3000 head = fusbh200->async;
3001 qh->qh_next = head->qh_next;
3002 qh->hw->hw_next = head->hw->hw_next;
3003 wmb ();
3004
3005 head->qh_next.qh = qh;
3006 head->hw->hw_next = dma;
3007
3008 qh->xacterrs = 0;
3009 qh->qh_state = QH_STATE_LINKED;
3010
3011
3012 enable_async(fusbh200);
3013}
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023static struct fusbh200_qh *qh_append_tds (
3024 struct fusbh200_hcd *fusbh200,
3025 struct urb *urb,
3026 struct list_head *qtd_list,
3027 int epnum,
3028 void **ptr
3029)
3030{
3031 struct fusbh200_qh *qh = NULL;
3032 __hc32 qh_addr_mask = cpu_to_hc32(fusbh200, 0x7f);
3033
3034 qh = (struct fusbh200_qh *) *ptr;
3035 if (unlikely (qh == NULL)) {
3036
3037 qh = qh_make (fusbh200, urb, GFP_ATOMIC);
3038 *ptr = qh;
3039 }
3040 if (likely (qh != NULL)) {
3041 struct fusbh200_qtd *qtd;
3042
3043 if (unlikely (list_empty (qtd_list)))
3044 qtd = NULL;
3045 else
3046 qtd = list_entry (qtd_list->next, struct fusbh200_qtd,
3047 qtd_list);
3048
3049
3050 if (unlikely (epnum == 0)) {
3051
3052
3053 if (usb_pipedevice (urb->pipe) == 0)
3054 qh->hw->hw_info1 &= ~qh_addr_mask;
3055 }
3056
3057
3058
3059
3060 if (likely (qtd != NULL)) {
3061 struct fusbh200_qtd *dummy;
3062 dma_addr_t dma;
3063 __hc32 token;
3064
3065
3066
3067
3068
3069
3070 token = qtd->hw_token;
3071 qtd->hw_token = HALT_BIT(fusbh200);
3072
3073 dummy = qh->dummy;
3074
3075 dma = dummy->qtd_dma;
3076 *dummy = *qtd;
3077 dummy->qtd_dma = dma;
3078
3079 list_del (&qtd->qtd_list);
3080 list_add (&dummy->qtd_list, qtd_list);
3081 list_splice_tail(qtd_list, &qh->qtd_list);
3082
3083 fusbh200_qtd_init(fusbh200, qtd, qtd->qtd_dma);
3084 qh->dummy = qtd;
3085
3086
3087 dma = qtd->qtd_dma;
3088 qtd = list_entry (qh->qtd_list.prev,
3089 struct fusbh200_qtd, qtd_list);
3090 qtd->hw_next = QTD_NEXT(fusbh200, dma);
3091
3092
3093 wmb ();
3094 dummy->hw_token = token;
3095
3096 urb->hcpriv = qh;
3097 }
3098 }
3099 return qh;
3100}
3101
3102
3103
3104static int
3105submit_async (
3106 struct fusbh200_hcd *fusbh200,
3107 struct urb *urb,
3108 struct list_head *qtd_list,
3109 gfp_t mem_flags
3110) {
3111 int epnum;
3112 unsigned long flags;
3113 struct fusbh200_qh *qh = NULL;
3114 int rc;
3115
3116 epnum = urb->ep->desc.bEndpointAddress;
3117
3118#ifdef FUSBH200_URB_TRACE
3119 {
3120 struct fusbh200_qtd *qtd;
3121 qtd = list_entry(qtd_list->next, struct fusbh200_qtd, qtd_list);
3122 fusbh200_dbg(fusbh200,
3123 "%s %s urb %p ep%d%s len %d, qtd %p [qh %p]\n",
3124 __func__, urb->dev->devpath, urb,
3125 epnum & 0x0f, (epnum & USB_DIR_IN) ? "in" : "out",
3126 urb->transfer_buffer_length,
3127 qtd, urb->ep->hcpriv);
3128 }
3129#endif
3130
3131 spin_lock_irqsave (&fusbh200->lock, flags);
3132 if (unlikely(!HCD_HW_ACCESSIBLE(fusbh200_to_hcd(fusbh200)))) {
3133 rc = -ESHUTDOWN;
3134 goto done;
3135 }
3136 rc = usb_hcd_link_urb_to_ep(fusbh200_to_hcd(fusbh200), urb);
3137 if (unlikely(rc))
3138 goto done;
3139
3140 qh = qh_append_tds(fusbh200, urb, qtd_list, epnum, &urb->ep->hcpriv);
3141 if (unlikely(qh == NULL)) {
3142 usb_hcd_unlink_urb_from_ep(fusbh200_to_hcd(fusbh200), urb);
3143 rc = -ENOMEM;
3144 goto done;
3145 }
3146
3147
3148
3149
3150 if (likely (qh->qh_state == QH_STATE_IDLE))
3151 qh_link_async(fusbh200, qh);
3152 done:
3153 spin_unlock_irqrestore (&fusbh200->lock, flags);
3154 if (unlikely (qh == NULL))
3155 qtd_list_free (fusbh200, urb, qtd_list);
3156 return rc;
3157}
3158
3159
3160
3161static void single_unlink_async(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
3162{
3163 struct fusbh200_qh *prev;
3164
3165
3166 qh->qh_state = QH_STATE_UNLINK;
3167 if (fusbh200->async_unlink)
3168 fusbh200->async_unlink_last->unlink_next = qh;
3169 else
3170 fusbh200->async_unlink = qh;
3171 fusbh200->async_unlink_last = qh;
3172
3173
3174 prev = fusbh200->async;
3175 while (prev->qh_next.qh != qh)
3176 prev = prev->qh_next.qh;
3177
3178 prev->hw->hw_next = qh->hw->hw_next;
3179 prev->qh_next = qh->qh_next;
3180 if (fusbh200->qh_scan_next == qh)
3181 fusbh200->qh_scan_next = qh->qh_next.qh;
3182}
3183
3184static void start_iaa_cycle(struct fusbh200_hcd *fusbh200, bool nested)
3185{
3186
3187
3188
3189
3190 if (fusbh200->async_iaa || fusbh200->async_unlinking)
3191 return;
3192
3193
3194 fusbh200->async_iaa = fusbh200->async_unlink;
3195 fusbh200->async_unlink = NULL;
3196
3197
3198 if (unlikely(fusbh200->rh_state < FUSBH200_RH_RUNNING)) {
3199 if (!nested)
3200 end_unlink_async(fusbh200);
3201
3202
3203 } else if (likely(fusbh200->rh_state == FUSBH200_RH_RUNNING)) {
3204
3205 wmb();
3206
3207 fusbh200_writel(fusbh200, fusbh200->command | CMD_IAAD,
3208 &fusbh200->regs->command);
3209 fusbh200_readl(fusbh200, &fusbh200->regs->command);
3210 fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_IAA_WATCHDOG, true);
3211 }
3212}
3213
3214
3215
3216static void end_unlink_async(struct fusbh200_hcd *fusbh200)
3217{
3218 struct fusbh200_qh *qh;
3219
3220
3221 restart:
3222 fusbh200->async_unlinking = true;
3223 while (fusbh200->async_iaa) {
3224 qh = fusbh200->async_iaa;
3225 fusbh200->async_iaa = qh->unlink_next;
3226 qh->unlink_next = NULL;
3227
3228 qh->qh_state = QH_STATE_IDLE;
3229 qh->qh_next.qh = NULL;
3230
3231 qh_completions(fusbh200, qh);
3232 if (!list_empty(&qh->qtd_list) &&
3233 fusbh200->rh_state == FUSBH200_RH_RUNNING)
3234 qh_link_async(fusbh200, qh);
3235 disable_async(fusbh200);
3236 }
3237 fusbh200->async_unlinking = false;
3238
3239
3240 if (fusbh200->async_unlink) {
3241 start_iaa_cycle(fusbh200, true);
3242 if (unlikely(fusbh200->rh_state < FUSBH200_RH_RUNNING))
3243 goto restart;
3244 }
3245}
3246
3247static void unlink_empty_async(struct fusbh200_hcd *fusbh200)
3248{
3249 struct fusbh200_qh *qh, *next;
3250 bool stopped = (fusbh200->rh_state < FUSBH200_RH_RUNNING);
3251 bool check_unlinks_later = false;
3252
3253
3254 next = fusbh200->async->qh_next.qh;
3255 while (next) {
3256 qh = next;
3257 next = qh->qh_next.qh;
3258
3259 if (list_empty(&qh->qtd_list) &&
3260 qh->qh_state == QH_STATE_LINKED) {
3261 if (!stopped && qh->unlink_cycle ==
3262 fusbh200->async_unlink_cycle)
3263 check_unlinks_later = true;
3264 else
3265 single_unlink_async(fusbh200, qh);
3266 }
3267 }
3268
3269
3270 if (fusbh200->async_unlink)
3271 start_iaa_cycle(fusbh200, false);
3272
3273
3274 if (check_unlinks_later) {
3275 fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_ASYNC_UNLINKS, true);
3276 ++fusbh200->async_unlink_cycle;
3277 }
3278}
3279
3280
3281
3282
3283static void start_unlink_async(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
3284{
3285
3286
3287
3288
3289
3290 if (qh->qh_state != QH_STATE_LINKED) {
3291 if (qh->qh_state == QH_STATE_COMPLETING)
3292 qh->needs_rescan = 1;
3293 return;
3294 }
3295
3296 single_unlink_async(fusbh200, qh);
3297 start_iaa_cycle(fusbh200, false);
3298}
3299
3300
3301
3302static void scan_async (struct fusbh200_hcd *fusbh200)
3303{
3304 struct fusbh200_qh *qh;
3305 bool check_unlinks_later = false;
3306
3307 fusbh200->qh_scan_next = fusbh200->async->qh_next.qh;
3308 while (fusbh200->qh_scan_next) {
3309 qh = fusbh200->qh_scan_next;
3310 fusbh200->qh_scan_next = qh->qh_next.qh;
3311 rescan:
3312
3313 if (!list_empty(&qh->qtd_list)) {
3314 int temp;
3315
3316
3317
3318
3319
3320
3321
3322
3323 temp = qh_completions(fusbh200, qh);
3324 if (qh->needs_rescan) {
3325 start_unlink_async(fusbh200, qh);
3326 } else if (list_empty(&qh->qtd_list)
3327 && qh->qh_state == QH_STATE_LINKED) {
3328 qh->unlink_cycle = fusbh200->async_unlink_cycle;
3329 check_unlinks_later = true;
3330 } else if (temp != 0)
3331 goto rescan;
3332 }
3333 }
3334
3335
3336
3337
3338
3339
3340
3341 if (check_unlinks_later && fusbh200->rh_state == FUSBH200_RH_RUNNING &&
3342 !(fusbh200->enabled_hrtimer_events &
3343 BIT(FUSBH200_HRTIMER_ASYNC_UNLINKS))) {
3344 fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_ASYNC_UNLINKS, true);
3345 ++fusbh200->async_unlink_cycle;
3346 }
3347}
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362static int fusbh200_get_frame (struct usb_hcd *hcd);
3363
3364
3365
3366
3367
3368
3369
3370
3371static union fusbh200_shadow *
3372periodic_next_shadow(struct fusbh200_hcd *fusbh200, union fusbh200_shadow *periodic,
3373 __hc32 tag)
3374{
3375 switch (hc32_to_cpu(fusbh200, tag)) {
3376 case Q_TYPE_QH:
3377 return &periodic->qh->qh_next;
3378 case Q_TYPE_FSTN:
3379 return &periodic->fstn->fstn_next;
3380 default:
3381 return &periodic->itd->itd_next;
3382 }
3383}
3384
3385static __hc32 *
3386shadow_next_periodic(struct fusbh200_hcd *fusbh200, union fusbh200_shadow *periodic,
3387 __hc32 tag)
3388{
3389 switch (hc32_to_cpu(fusbh200, tag)) {
3390
3391 case Q_TYPE_QH:
3392 return &periodic->qh->hw->hw_next;
3393
3394 default:
3395 return periodic->hw_next;
3396 }
3397}
3398
3399
3400static void periodic_unlink (struct fusbh200_hcd *fusbh200, unsigned frame, void *ptr)
3401{
3402 union fusbh200_shadow *prev_p = &fusbh200->pshadow[frame];
3403 __hc32 *hw_p = &fusbh200->periodic[frame];
3404 union fusbh200_shadow here = *prev_p;
3405
3406
3407 while (here.ptr && here.ptr != ptr) {
3408 prev_p = periodic_next_shadow(fusbh200, prev_p,
3409 Q_NEXT_TYPE(fusbh200, *hw_p));
3410 hw_p = shadow_next_periodic(fusbh200, &here,
3411 Q_NEXT_TYPE(fusbh200, *hw_p));
3412 here = *prev_p;
3413 }
3414
3415 if (!here.ptr)
3416 return;
3417
3418
3419
3420
3421 *prev_p = *periodic_next_shadow(fusbh200, &here,
3422 Q_NEXT_TYPE(fusbh200, *hw_p));
3423
3424 *hw_p = *shadow_next_periodic(fusbh200, &here,
3425 Q_NEXT_TYPE(fusbh200, *hw_p));
3426}
3427
3428
3429static unsigned short
3430periodic_usecs (struct fusbh200_hcd *fusbh200, unsigned frame, unsigned uframe)
3431{
3432 __hc32 *hw_p = &fusbh200->periodic [frame];
3433 union fusbh200_shadow *q = &fusbh200->pshadow [frame];
3434 unsigned usecs = 0;
3435 struct fusbh200_qh_hw *hw;
3436
3437 while (q->ptr) {
3438 switch (hc32_to_cpu(fusbh200, Q_NEXT_TYPE(fusbh200, *hw_p))) {
3439 case Q_TYPE_QH:
3440 hw = q->qh->hw;
3441
3442 if (hw->hw_info2 & cpu_to_hc32(fusbh200, 1 << uframe))
3443 usecs += q->qh->usecs;
3444
3445 if (hw->hw_info2 & cpu_to_hc32(fusbh200,
3446 1 << (8 + uframe)))
3447 usecs += q->qh->c_usecs;
3448 hw_p = &hw->hw_next;
3449 q = &q->qh->qh_next;
3450 break;
3451
3452 default:
3453
3454
3455
3456 if (q->fstn->hw_prev != FUSBH200_LIST_END(fusbh200)) {
3457 fusbh200_dbg (fusbh200, "ignoring FSTN cost ...\n");
3458 }
3459 hw_p = &q->fstn->hw_next;
3460 q = &q->fstn->fstn_next;
3461 break;
3462 case Q_TYPE_ITD:
3463 if (q->itd->hw_transaction[uframe])
3464 usecs += q->itd->stream->usecs;
3465 hw_p = &q->itd->hw_next;
3466 q = &q->itd->itd_next;
3467 break;
3468 }
3469 }
3470 if (usecs > fusbh200->uframe_periodic_max)
3471 fusbh200_err (fusbh200, "uframe %d sched overrun: %d usecs\n",
3472 frame * 8 + uframe, usecs);
3473 return usecs;
3474}
3475
3476
3477
3478static int same_tt (struct usb_device *dev1, struct usb_device *dev2)
3479{
3480 if (!dev1->tt || !dev2->tt)
3481 return 0;
3482 if (dev1->tt != dev2->tt)
3483 return 0;
3484 if (dev1->tt->multi)
3485 return dev1->ttport == dev2->ttport;
3486 else
3487 return 1;
3488}
3489
3490
3491
3492
3493
3494static int tt_no_collision (
3495 struct fusbh200_hcd *fusbh200,
3496 unsigned period,
3497 struct usb_device *dev,
3498 unsigned frame,
3499 u32 uf_mask
3500)
3501{
3502 if (period == 0)
3503 return 0;
3504
3505
3506
3507
3508
3509 for (; frame < fusbh200->periodic_size; frame += period) {
3510 union fusbh200_shadow here;
3511 __hc32 type;
3512 struct fusbh200_qh_hw *hw;
3513
3514 here = fusbh200->pshadow [frame];
3515 type = Q_NEXT_TYPE(fusbh200, fusbh200->periodic [frame]);
3516 while (here.ptr) {
3517 switch (hc32_to_cpu(fusbh200, type)) {
3518 case Q_TYPE_ITD:
3519 type = Q_NEXT_TYPE(fusbh200, here.itd->hw_next);
3520 here = here.itd->itd_next;
3521 continue;
3522 case Q_TYPE_QH:
3523 hw = here.qh->hw;
3524 if (same_tt (dev, here.qh->dev)) {
3525 u32 mask;
3526
3527 mask = hc32_to_cpu(fusbh200,
3528 hw->hw_info2);
3529
3530 mask |= mask >> 8;
3531 if (mask & uf_mask)
3532 break;
3533 }
3534 type = Q_NEXT_TYPE(fusbh200, hw->hw_next);
3535 here = here.qh->qh_next;
3536 continue;
3537
3538 default:
3539 fusbh200_dbg (fusbh200,
3540 "periodic frame %d bogus type %d\n",
3541 frame, type);
3542 }
3543
3544
3545 return 0;
3546 }
3547 }
3548
3549
3550 return 1;
3551}
3552
3553
3554
3555static void enable_periodic(struct fusbh200_hcd *fusbh200)
3556{
3557 if (fusbh200->periodic_count++)
3558 return;
3559
3560
3561 fusbh200->enabled_hrtimer_events &= ~BIT(FUSBH200_HRTIMER_DISABLE_PERIODIC);
3562
3563
3564 fusbh200_poll_PSS(fusbh200);
3565 turn_on_io_watchdog(fusbh200);
3566}
3567
3568static void disable_periodic(struct fusbh200_hcd *fusbh200)
3569{
3570 if (--fusbh200->periodic_count)
3571 return;
3572
3573
3574 fusbh200_poll_PSS(fusbh200);
3575}
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585static void qh_link_periodic(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
3586{
3587 unsigned i;
3588 unsigned period = qh->period;
3589
3590 dev_dbg (&qh->dev->dev,
3591 "link qh%d-%04x/%p start %d [%d/%d us]\n",
3592 period, hc32_to_cpup(fusbh200, &qh->hw->hw_info2)
3593 & (QH_CMASK | QH_SMASK),
3594 qh, qh->start, qh->usecs, qh->c_usecs);
3595
3596
3597 if (period == 0)
3598 period = 1;
3599
3600 for (i = qh->start; i < fusbh200->periodic_size; i += period) {
3601 union fusbh200_shadow *prev = &fusbh200->pshadow[i];
3602 __hc32 *hw_p = &fusbh200->periodic[i];
3603 union fusbh200_shadow here = *prev;
3604 __hc32 type = 0;
3605
3606
3607 while (here.ptr) {
3608 type = Q_NEXT_TYPE(fusbh200, *hw_p);
3609 if (type == cpu_to_hc32(fusbh200, Q_TYPE_QH))
3610 break;
3611 prev = periodic_next_shadow(fusbh200, prev, type);
3612 hw_p = shadow_next_periodic(fusbh200, &here, type);
3613 here = *prev;
3614 }
3615
3616
3617
3618
3619 while (here.ptr && qh != here.qh) {
3620 if (qh->period > here.qh->period)
3621 break;
3622 prev = &here.qh->qh_next;
3623 hw_p = &here.qh->hw->hw_next;
3624 here = *prev;
3625 }
3626
3627 if (qh != here.qh) {
3628 qh->qh_next = here;
3629 if (here.qh)
3630 qh->hw->hw_next = *hw_p;
3631 wmb ();
3632 prev->qh = qh;
3633 *hw_p = QH_NEXT (fusbh200, qh->qh_dma);
3634 }
3635 }
3636 qh->qh_state = QH_STATE_LINKED;
3637 qh->xacterrs = 0;
3638
3639
3640 fusbh200_to_hcd(fusbh200)->self.bandwidth_allocated += qh->period
3641 ? ((qh->usecs + qh->c_usecs) / qh->period)
3642 : (qh->usecs * 8);
3643
3644 list_add(&qh->intr_node, &fusbh200->intr_qh_list);
3645
3646
3647 ++fusbh200->intr_count;
3648 enable_periodic(fusbh200);
3649}
3650
3651static void qh_unlink_periodic(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
3652{
3653 unsigned i;
3654 unsigned period;
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672 if ((period = qh->period) == 0)
3673 period = 1;
3674
3675 for (i = qh->start; i < fusbh200->periodic_size; i += period)
3676 periodic_unlink (fusbh200, i, qh);
3677
3678
3679 fusbh200_to_hcd(fusbh200)->self.bandwidth_allocated -= qh->period
3680 ? ((qh->usecs + qh->c_usecs) / qh->period)
3681 : (qh->usecs * 8);
3682
3683 dev_dbg (&qh->dev->dev,
3684 "unlink qh%d-%04x/%p start %d [%d/%d us]\n",
3685 qh->period,
3686 hc32_to_cpup(fusbh200, &qh->hw->hw_info2) & (QH_CMASK | QH_SMASK),
3687 qh, qh->start, qh->usecs, qh->c_usecs);
3688
3689
3690 qh->qh_state = QH_STATE_UNLINK;
3691 qh->qh_next.ptr = NULL;
3692
3693 if (fusbh200->qh_scan_next == qh)
3694 fusbh200->qh_scan_next = list_entry(qh->intr_node.next,
3695 struct fusbh200_qh, intr_node);
3696 list_del(&qh->intr_node);
3697}
3698
3699static void start_unlink_intr(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
3700{
3701
3702
3703
3704
3705 if (qh->qh_state != QH_STATE_LINKED) {
3706 if (qh->qh_state == QH_STATE_COMPLETING)
3707 qh->needs_rescan = 1;
3708 return;
3709 }
3710
3711 qh_unlink_periodic (fusbh200, qh);
3712
3713
3714 wmb();
3715
3716
3717
3718
3719
3720
3721 qh->unlink_cycle = fusbh200->intr_unlink_cycle;
3722
3723
3724 if (fusbh200->intr_unlink)
3725 fusbh200->intr_unlink_last->unlink_next = qh;
3726 else
3727 fusbh200->intr_unlink = qh;
3728 fusbh200->intr_unlink_last = qh;
3729
3730 if (fusbh200->intr_unlinking)
3731 ;
3732 else if (fusbh200->rh_state < FUSBH200_RH_RUNNING)
3733 fusbh200_handle_intr_unlinks(fusbh200);
3734 else if (fusbh200->intr_unlink == qh) {
3735 fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_UNLINK_INTR, true);
3736 ++fusbh200->intr_unlink_cycle;
3737 }
3738}
3739
3740static void end_unlink_intr(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
3741{
3742 struct fusbh200_qh_hw *hw = qh->hw;
3743 int rc;
3744
3745 qh->qh_state = QH_STATE_IDLE;
3746 hw->hw_next = FUSBH200_LIST_END(fusbh200);
3747
3748 qh_completions(fusbh200, qh);
3749
3750
3751 if (!list_empty(&qh->qtd_list) && fusbh200->rh_state == FUSBH200_RH_RUNNING) {
3752 rc = qh_schedule(fusbh200, qh);
3753
3754
3755
3756
3757
3758
3759
3760 if (rc != 0)
3761 fusbh200_err(fusbh200, "can't reschedule qh %p, err %d\n",
3762 qh, rc);
3763 }
3764
3765
3766 --fusbh200->intr_count;
3767 disable_periodic(fusbh200);
3768}
3769
3770
3771
3772static int check_period (
3773 struct fusbh200_hcd *fusbh200,
3774 unsigned frame,
3775 unsigned uframe,
3776 unsigned period,
3777 unsigned usecs
3778) {
3779 int claimed;
3780
3781
3782
3783
3784 if (uframe >= 8)
3785 return 0;
3786
3787
3788 usecs = fusbh200->uframe_periodic_max - usecs;
3789
3790
3791
3792
3793 if (unlikely (period == 0)) {
3794 do {
3795 for (uframe = 0; uframe < 7; uframe++) {
3796 claimed = periodic_usecs (fusbh200, frame, uframe);
3797 if (claimed > usecs)
3798 return 0;
3799 }
3800 } while ((frame += 1) < fusbh200->periodic_size);
3801
3802
3803 } else {
3804 do {
3805 claimed = periodic_usecs (fusbh200, frame, uframe);
3806 if (claimed > usecs)
3807 return 0;
3808 } while ((frame += period) < fusbh200->periodic_size);
3809 }
3810
3811
3812 return 1;
3813}
3814
3815static int check_intr_schedule (
3816 struct fusbh200_hcd *fusbh200,
3817 unsigned frame,
3818 unsigned uframe,
3819 const struct fusbh200_qh *qh,
3820 __hc32 *c_maskp
3821)
3822{
3823 int retval = -ENOSPC;
3824 u8 mask = 0;
3825
3826 if (qh->c_usecs && uframe >= 6)
3827 goto done;
3828
3829 if (!check_period (fusbh200, frame, uframe, qh->period, qh->usecs))
3830 goto done;
3831 if (!qh->c_usecs) {
3832 retval = 0;
3833 *c_maskp = 0;
3834 goto done;
3835 }
3836
3837
3838
3839
3840
3841
3842
3843
3844 mask = 0x03 << (uframe + qh->gap_uf);
3845 *c_maskp = cpu_to_hc32(fusbh200, mask << 8);
3846
3847 mask |= 1 << uframe;
3848 if (tt_no_collision (fusbh200, qh->period, qh->dev, frame, mask)) {
3849 if (!check_period (fusbh200, frame, uframe + qh->gap_uf + 1,
3850 qh->period, qh->c_usecs))
3851 goto done;
3852 if (!check_period (fusbh200, frame, uframe + qh->gap_uf,
3853 qh->period, qh->c_usecs))
3854 goto done;
3855 retval = 0;
3856 }
3857done:
3858 return retval;
3859}
3860
3861
3862
3863
3864static int qh_schedule(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
3865{
3866 int status;
3867 unsigned uframe;
3868 __hc32 c_mask;
3869 unsigned frame;
3870 struct fusbh200_qh_hw *hw = qh->hw;
3871
3872 qh_refresh(fusbh200, qh);
3873 hw->hw_next = FUSBH200_LIST_END(fusbh200);
3874 frame = qh->start;
3875
3876
3877 if (frame < qh->period) {
3878 uframe = ffs(hc32_to_cpup(fusbh200, &hw->hw_info2) & QH_SMASK);
3879 status = check_intr_schedule (fusbh200, frame, --uframe,
3880 qh, &c_mask);
3881 } else {
3882 uframe = 0;
3883 c_mask = 0;
3884 status = -ENOSPC;
3885 }
3886
3887
3888
3889
3890 if (status) {
3891
3892 if (qh->period) {
3893 int i;
3894
3895 for (i = qh->period; status && i > 0; --i) {
3896 frame = ++fusbh200->random_frame % qh->period;
3897 for (uframe = 0; uframe < 8; uframe++) {
3898 status = check_intr_schedule (fusbh200,
3899 frame, uframe, qh,
3900 &c_mask);
3901 if (status == 0)
3902 break;
3903 }
3904 }
3905
3906
3907 } else {
3908 frame = 0;
3909 status = check_intr_schedule (fusbh200, 0, 0, qh, &c_mask);
3910 }
3911 if (status)
3912 goto done;
3913 qh->start = frame;
3914
3915
3916 hw->hw_info2 &= cpu_to_hc32(fusbh200, ~(QH_CMASK | QH_SMASK));
3917 hw->hw_info2 |= qh->period
3918 ? cpu_to_hc32(fusbh200, 1 << uframe)
3919 : cpu_to_hc32(fusbh200, QH_SMASK);
3920 hw->hw_info2 |= c_mask;
3921 } else
3922 fusbh200_dbg (fusbh200, "reused qh %p schedule\n", qh);
3923
3924
3925 qh_link_periodic(fusbh200, qh);
3926done:
3927 return status;
3928}
3929
3930static int intr_submit (
3931 struct fusbh200_hcd *fusbh200,
3932 struct urb *urb,
3933 struct list_head *qtd_list,
3934 gfp_t mem_flags
3935) {
3936 unsigned epnum;
3937 unsigned long flags;
3938 struct fusbh200_qh *qh;
3939 int status;
3940 struct list_head empty;
3941
3942
3943 epnum = urb->ep->desc.bEndpointAddress;
3944
3945 spin_lock_irqsave (&fusbh200->lock, flags);
3946
3947 if (unlikely(!HCD_HW_ACCESSIBLE(fusbh200_to_hcd(fusbh200)))) {
3948 status = -ESHUTDOWN;
3949 goto done_not_linked;
3950 }
3951 status = usb_hcd_link_urb_to_ep(fusbh200_to_hcd(fusbh200), urb);
3952 if (unlikely(status))
3953 goto done_not_linked;
3954
3955
3956 INIT_LIST_HEAD (&empty);
3957 qh = qh_append_tds(fusbh200, urb, &empty, epnum, &urb->ep->hcpriv);
3958 if (qh == NULL) {
3959 status = -ENOMEM;
3960 goto done;
3961 }
3962 if (qh->qh_state == QH_STATE_IDLE) {
3963 if ((status = qh_schedule (fusbh200, qh)) != 0)
3964 goto done;
3965 }
3966
3967
3968 qh = qh_append_tds(fusbh200, urb, qtd_list, epnum, &urb->ep->hcpriv);
3969 BUG_ON (qh == NULL);
3970
3971
3972 fusbh200_to_hcd(fusbh200)->self.bandwidth_int_reqs++;
3973
3974done:
3975 if (unlikely(status))
3976 usb_hcd_unlink_urb_from_ep(fusbh200_to_hcd(fusbh200), urb);
3977done_not_linked:
3978 spin_unlock_irqrestore (&fusbh200->lock, flags);
3979 if (status)
3980 qtd_list_free (fusbh200, urb, qtd_list);
3981
3982 return status;
3983}
3984
3985static void scan_intr(struct fusbh200_hcd *fusbh200)
3986{
3987 struct fusbh200_qh *qh;
3988
3989 list_for_each_entry_safe(qh, fusbh200->qh_scan_next, &fusbh200->intr_qh_list,
3990 intr_node) {
3991 rescan:
3992
3993 if (!list_empty(&qh->qtd_list)) {
3994 int temp;
3995
3996
3997
3998
3999
4000
4001
4002
4003 temp = qh_completions(fusbh200, qh);
4004 if (unlikely(qh->needs_rescan ||
4005 (list_empty(&qh->qtd_list) &&
4006 qh->qh_state == QH_STATE_LINKED)))
4007 start_unlink_intr(fusbh200, qh);
4008 else if (temp != 0)
4009 goto rescan;
4010 }
4011 }
4012}
4013
4014
4015
4016
4017
4018static struct fusbh200_iso_stream *
4019iso_stream_alloc (gfp_t mem_flags)
4020{
4021 struct fusbh200_iso_stream *stream;
4022
4023 stream = kzalloc(sizeof *stream, mem_flags);
4024 if (likely (stream != NULL)) {
4025 INIT_LIST_HEAD(&stream->td_list);
4026 INIT_LIST_HEAD(&stream->free_list);
4027 stream->next_uframe = -1;
4028 }
4029 return stream;
4030}
4031
4032static void
4033iso_stream_init (
4034 struct fusbh200_hcd *fusbh200,
4035 struct fusbh200_iso_stream *stream,
4036 struct usb_device *dev,
4037 int pipe,
4038 unsigned interval
4039)
4040{
4041 u32 buf1;
4042 unsigned epnum, maxp;
4043 int is_input;
4044 long bandwidth;
4045 unsigned multi;
4046
4047
4048
4049
4050
4051 epnum = usb_pipeendpoint (pipe);
4052 is_input = usb_pipein (pipe) ? USB_DIR_IN : 0;
4053 maxp = usb_maxpacket(dev, pipe, !is_input);
4054 if (is_input) {
4055 buf1 = (1 << 11);
4056 } else {
4057 buf1 = 0;
4058 }
4059
4060 maxp = max_packet(maxp);
4061 multi = hb_mult(maxp);
4062 buf1 |= maxp;
4063 maxp *= multi;
4064
4065 stream->buf0 = cpu_to_hc32(fusbh200, (epnum << 8) | dev->devnum);
4066 stream->buf1 = cpu_to_hc32(fusbh200, buf1);
4067 stream->buf2 = cpu_to_hc32(fusbh200, multi);
4068
4069
4070
4071
4072 if (dev->speed == USB_SPEED_FULL) {
4073 interval <<= 3;
4074 stream->usecs = NS_TO_US(usb_calc_bus_time(dev->speed,
4075 is_input, 1, maxp));
4076 stream->usecs /= 8;
4077 } else {
4078 stream->highspeed = 1;
4079 stream->usecs = HS_USECS_ISO (maxp);
4080 }
4081 bandwidth = stream->usecs * 8;
4082 bandwidth /= interval;
4083
4084 stream->bandwidth = bandwidth;
4085 stream->udev = dev;
4086 stream->bEndpointAddress = is_input | epnum;
4087 stream->interval = interval;
4088 stream->maxp = maxp;
4089}
4090
4091static struct fusbh200_iso_stream *
4092iso_stream_find (struct fusbh200_hcd *fusbh200, struct urb *urb)
4093{
4094 unsigned epnum;
4095 struct fusbh200_iso_stream *stream;
4096 struct usb_host_endpoint *ep;
4097 unsigned long flags;
4098
4099 epnum = usb_pipeendpoint (urb->pipe);
4100 if (usb_pipein(urb->pipe))
4101 ep = urb->dev->ep_in[epnum];
4102 else
4103 ep = urb->dev->ep_out[epnum];
4104
4105 spin_lock_irqsave (&fusbh200->lock, flags);
4106 stream = ep->hcpriv;
4107
4108 if (unlikely (stream == NULL)) {
4109 stream = iso_stream_alloc(GFP_ATOMIC);
4110 if (likely (stream != NULL)) {
4111 ep->hcpriv = stream;
4112 stream->ep = ep;
4113 iso_stream_init(fusbh200, stream, urb->dev, urb->pipe,
4114 urb->interval);
4115 }
4116
4117
4118 } else if (unlikely (stream->hw != NULL)) {
4119 fusbh200_dbg (fusbh200, "dev %s ep%d%s, not iso??\n",
4120 urb->dev->devpath, epnum,
4121 usb_pipein(urb->pipe) ? "in" : "out");
4122 stream = NULL;
4123 }
4124
4125 spin_unlock_irqrestore (&fusbh200->lock, flags);
4126 return stream;
4127}
4128
4129
4130
4131
4132
4133static struct fusbh200_iso_sched *
4134iso_sched_alloc (unsigned packets, gfp_t mem_flags)
4135{
4136 struct fusbh200_iso_sched *iso_sched;
4137 int size = sizeof *iso_sched;
4138
4139 size += packets * sizeof (struct fusbh200_iso_packet);
4140 iso_sched = kzalloc(size, mem_flags);
4141 if (likely (iso_sched != NULL)) {
4142 INIT_LIST_HEAD (&iso_sched->td_list);
4143 }
4144 return iso_sched;
4145}
4146
4147static inline void
4148itd_sched_init(
4149 struct fusbh200_hcd *fusbh200,
4150 struct fusbh200_iso_sched *iso_sched,
4151 struct fusbh200_iso_stream *stream,
4152 struct urb *urb
4153)
4154{
4155 unsigned i;
4156 dma_addr_t dma = urb->transfer_dma;
4157
4158
4159 iso_sched->span = urb->number_of_packets * stream->interval;
4160
4161
4162
4163
4164 for (i = 0; i < urb->number_of_packets; i++) {
4165 struct fusbh200_iso_packet *uframe = &iso_sched->packet [i];
4166 unsigned length;
4167 dma_addr_t buf;
4168 u32 trans;
4169
4170 length = urb->iso_frame_desc [i].length;
4171 buf = dma + urb->iso_frame_desc [i].offset;
4172
4173 trans = FUSBH200_ISOC_ACTIVE;
4174 trans |= buf & 0x0fff;
4175 if (unlikely (((i + 1) == urb->number_of_packets))
4176 && !(urb->transfer_flags & URB_NO_INTERRUPT))
4177 trans |= FUSBH200_ITD_IOC;
4178 trans |= length << 16;
4179 uframe->transaction = cpu_to_hc32(fusbh200, trans);
4180
4181
4182 uframe->bufp = (buf & ~(u64)0x0fff);
4183 buf += length;
4184 if (unlikely ((uframe->bufp != (buf & ~(u64)0x0fff))))
4185 uframe->cross = 1;
4186 }
4187}
4188
4189static void
4190iso_sched_free (
4191 struct fusbh200_iso_stream *stream,
4192 struct fusbh200_iso_sched *iso_sched
4193)
4194{
4195 if (!iso_sched)
4196 return;
4197
4198 list_splice (&iso_sched->td_list, &stream->free_list);
4199 kfree (iso_sched);
4200}
4201
4202static int
4203itd_urb_transaction (
4204 struct fusbh200_iso_stream *stream,
4205 struct fusbh200_hcd *fusbh200,
4206 struct urb *urb,
4207 gfp_t mem_flags
4208)
4209{
4210 struct fusbh200_itd *itd;
4211 dma_addr_t itd_dma;
4212 int i;
4213 unsigned num_itds;
4214 struct fusbh200_iso_sched *sched;
4215 unsigned long flags;
4216
4217 sched = iso_sched_alloc (urb->number_of_packets, mem_flags);
4218 if (unlikely (sched == NULL))
4219 return -ENOMEM;
4220
4221 itd_sched_init(fusbh200, sched, stream, urb);
4222
4223 if (urb->interval < 8)
4224 num_itds = 1 + (sched->span + 7) / 8;
4225 else
4226 num_itds = urb->number_of_packets;
4227
4228
4229 spin_lock_irqsave (&fusbh200->lock, flags);
4230 for (i = 0; i < num_itds; i++) {
4231
4232
4233
4234
4235
4236 if (likely(!list_empty(&stream->free_list))) {
4237 itd = list_first_entry(&stream->free_list,
4238 struct fusbh200_itd, itd_list);
4239 if (itd->frame == fusbh200->now_frame)
4240 goto alloc_itd;
4241 list_del (&itd->itd_list);
4242 itd_dma = itd->itd_dma;
4243 } else {
4244 alloc_itd:
4245 spin_unlock_irqrestore (&fusbh200->lock, flags);
4246 itd = dma_pool_alloc (fusbh200->itd_pool, mem_flags,
4247 &itd_dma);
4248 spin_lock_irqsave (&fusbh200->lock, flags);
4249 if (!itd) {
4250 iso_sched_free(stream, sched);
4251 spin_unlock_irqrestore(&fusbh200->lock, flags);
4252 return -ENOMEM;
4253 }
4254 }
4255
4256 memset (itd, 0, sizeof *itd);
4257 itd->itd_dma = itd_dma;
4258 list_add (&itd->itd_list, &sched->td_list);
4259 }
4260 spin_unlock_irqrestore (&fusbh200->lock, flags);
4261
4262
4263 urb->hcpriv = sched;
4264 urb->error_count = 0;
4265 return 0;
4266}
4267
4268
4269
4270static inline int
4271itd_slot_ok (
4272 struct fusbh200_hcd *fusbh200,
4273 u32 mod,
4274 u32 uframe,
4275 u8 usecs,
4276 u32 period
4277)
4278{
4279 uframe %= period;
4280 do {
4281
4282 if (periodic_usecs (fusbh200, uframe >> 3, uframe & 0x7)
4283 > (fusbh200->uframe_periodic_max - usecs))
4284 return 0;
4285
4286
4287 uframe += period;
4288 } while (uframe < mod);
4289 return 1;
4290}
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303#define SCHEDULE_SLOP 80
4304
4305static int
4306iso_stream_schedule (
4307 struct fusbh200_hcd *fusbh200,
4308 struct urb *urb,
4309 struct fusbh200_iso_stream *stream
4310)
4311{
4312 u32 now, next, start, period, span;
4313 int status;
4314 unsigned mod = fusbh200->periodic_size << 3;
4315 struct fusbh200_iso_sched *sched = urb->hcpriv;
4316
4317 period = urb->interval;
4318 span = sched->span;
4319
4320 if (span > mod - SCHEDULE_SLOP) {
4321 fusbh200_dbg (fusbh200, "iso request %p too long\n", urb);
4322 status = -EFBIG;
4323 goto fail;
4324 }
4325
4326 now = fusbh200_read_frame_index(fusbh200) & (mod - 1);
4327
4328
4329
4330
4331
4332
4333 if (likely (!list_empty (&stream->td_list))) {
4334 u32 excess;
4335
4336
4337
4338
4339
4340
4341 if (!stream->highspeed && fusbh200->fs_i_thresh)
4342 next = now + fusbh200->i_thresh;
4343 else
4344 next = now;
4345
4346
4347
4348
4349
4350 excess = (stream->next_uframe - period - next) & (mod - 1);
4351 if (excess >= mod - 2 * SCHEDULE_SLOP)
4352 start = next + excess - mod + period *
4353 DIV_ROUND_UP(mod - excess, period);
4354 else
4355 start = next + excess + period;
4356 if (start - now >= mod) {
4357 fusbh200_dbg(fusbh200, "request %p would overflow (%d+%d >= %d)\n",
4358 urb, start - now - period, period,
4359 mod);
4360 status = -EFBIG;
4361 goto fail;
4362 }
4363 }
4364
4365
4366
4367
4368
4369
4370
4371 else {
4372 int done = 0;
4373 start = SCHEDULE_SLOP + (now & ~0x07);
4374
4375
4376
4377
4378
4379
4380
4381
4382 next = start;
4383 start += period;
4384 do {
4385 start--;
4386
4387 if (itd_slot_ok(fusbh200, mod, start,
4388 stream->usecs, period))
4389 done = 1;
4390 } while (start > next && !done);
4391
4392
4393 if (!done) {
4394 fusbh200_dbg(fusbh200, "iso resched full %p (now %d max %d)\n",
4395 urb, now, now + mod);
4396 status = -ENOSPC;
4397 goto fail;
4398 }
4399 }
4400
4401
4402 if (unlikely(start - now + span - period
4403 >= mod - 2 * SCHEDULE_SLOP)) {
4404 fusbh200_dbg(fusbh200, "request %p would overflow (%d+%d >= %d)\n",
4405 urb, start - now, span - period,
4406 mod - 2 * SCHEDULE_SLOP);
4407 status = -EFBIG;
4408 goto fail;
4409 }
4410
4411 stream->next_uframe = start & (mod - 1);
4412
4413
4414 urb->start_frame = stream->next_uframe;
4415 if (!stream->highspeed)
4416 urb->start_frame >>= 3;
4417
4418
4419 if (fusbh200->isoc_count == 0)
4420 fusbh200->next_frame = now >> 3;
4421 return 0;
4422
4423 fail:
4424 iso_sched_free(stream, sched);
4425 urb->hcpriv = NULL;
4426 return status;
4427}
4428
4429
4430
4431static inline void
4432itd_init(struct fusbh200_hcd *fusbh200, struct fusbh200_iso_stream *stream,
4433 struct fusbh200_itd *itd)
4434{
4435 int i;
4436
4437
4438 itd->hw_next = FUSBH200_LIST_END(fusbh200);
4439 itd->hw_bufp [0] = stream->buf0;
4440 itd->hw_bufp [1] = stream->buf1;
4441 itd->hw_bufp [2] = stream->buf2;
4442
4443 for (i = 0; i < 8; i++)
4444 itd->index[i] = -1;
4445
4446
4447}
4448
4449static inline void
4450itd_patch(
4451 struct fusbh200_hcd *fusbh200,
4452 struct fusbh200_itd *itd,
4453 struct fusbh200_iso_sched *iso_sched,
4454 unsigned index,
4455 u16 uframe
4456)
4457{
4458 struct fusbh200_iso_packet *uf = &iso_sched->packet [index];
4459 unsigned pg = itd->pg;
4460
4461
4462
4463 uframe &= 0x07;
4464 itd->index [uframe] = index;
4465
4466 itd->hw_transaction[uframe] = uf->transaction;
4467 itd->hw_transaction[uframe] |= cpu_to_hc32(fusbh200, pg << 12);
4468 itd->hw_bufp[pg] |= cpu_to_hc32(fusbh200, uf->bufp & ~(u32)0);
4469 itd->hw_bufp_hi[pg] |= cpu_to_hc32(fusbh200, (u32)(uf->bufp >> 32));
4470
4471
4472 if (unlikely (uf->cross)) {
4473 u64 bufp = uf->bufp + 4096;
4474
4475 itd->pg = ++pg;
4476 itd->hw_bufp[pg] |= cpu_to_hc32(fusbh200, bufp & ~(u32)0);
4477 itd->hw_bufp_hi[pg] |= cpu_to_hc32(fusbh200, (u32)(bufp >> 32));
4478 }
4479}
4480
4481static inline void
4482itd_link (struct fusbh200_hcd *fusbh200, unsigned frame, struct fusbh200_itd *itd)
4483{
4484 union fusbh200_shadow *prev = &fusbh200->pshadow[frame];
4485 __hc32 *hw_p = &fusbh200->periodic[frame];
4486 union fusbh200_shadow here = *prev;
4487 __hc32 type = 0;
4488
4489
4490 while (here.ptr) {
4491 type = Q_NEXT_TYPE(fusbh200, *hw_p);
4492 if (type == cpu_to_hc32(fusbh200, Q_TYPE_QH))
4493 break;
4494 prev = periodic_next_shadow(fusbh200, prev, type);
4495 hw_p = shadow_next_periodic(fusbh200, &here, type);
4496 here = *prev;
4497 }
4498
4499 itd->itd_next = here;
4500 itd->hw_next = *hw_p;
4501 prev->itd = itd;
4502 itd->frame = frame;
4503 wmb ();
4504 *hw_p = cpu_to_hc32(fusbh200, itd->itd_dma | Q_TYPE_ITD);
4505}
4506
4507
4508static void itd_link_urb(
4509 struct fusbh200_hcd *fusbh200,
4510 struct urb *urb,
4511 unsigned mod,
4512 struct fusbh200_iso_stream *stream
4513)
4514{
4515 int packet;
4516 unsigned next_uframe, uframe, frame;
4517 struct fusbh200_iso_sched *iso_sched = urb->hcpriv;
4518 struct fusbh200_itd *itd;
4519
4520 next_uframe = stream->next_uframe & (mod - 1);
4521
4522 if (unlikely (list_empty(&stream->td_list))) {
4523 fusbh200_to_hcd(fusbh200)->self.bandwidth_allocated
4524 += stream->bandwidth;
4525 fusbh200_dbg(fusbh200,
4526 "schedule devp %s ep%d%s-iso period %d start %d.%d\n",
4527 urb->dev->devpath, stream->bEndpointAddress & 0x0f,
4528 (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out",
4529 urb->interval,
4530 next_uframe >> 3, next_uframe & 0x7);
4531 }
4532
4533
4534 for (packet = 0, itd = NULL; packet < urb->number_of_packets; ) {
4535 if (itd == NULL) {
4536
4537
4538
4539
4540
4541 itd = list_entry (iso_sched->td_list.next,
4542 struct fusbh200_itd, itd_list);
4543 list_move_tail (&itd->itd_list, &stream->td_list);
4544 itd->stream = stream;
4545 itd->urb = urb;
4546 itd_init (fusbh200, stream, itd);
4547 }
4548
4549 uframe = next_uframe & 0x07;
4550 frame = next_uframe >> 3;
4551
4552 itd_patch(fusbh200, itd, iso_sched, packet, uframe);
4553
4554 next_uframe += stream->interval;
4555 next_uframe &= mod - 1;
4556 packet++;
4557
4558
4559 if (((next_uframe >> 3) != frame)
4560 || packet == urb->number_of_packets) {
4561 itd_link(fusbh200, frame & (fusbh200->periodic_size - 1), itd);
4562 itd = NULL;
4563 }
4564 }
4565 stream->next_uframe = next_uframe;
4566
4567
4568 iso_sched_free (stream, iso_sched);
4569 urb->hcpriv = NULL;
4570
4571 ++fusbh200->isoc_count;
4572 enable_periodic(fusbh200);
4573}
4574
4575#define ISO_ERRS (FUSBH200_ISOC_BUF_ERR | FUSBH200_ISOC_BABBLE | FUSBH200_ISOC_XACTERR)
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587static bool itd_complete(struct fusbh200_hcd *fusbh200, struct fusbh200_itd *itd)
4588{
4589 struct urb *urb = itd->urb;
4590 struct usb_iso_packet_descriptor *desc;
4591 u32 t;
4592 unsigned uframe;
4593 int urb_index = -1;
4594 struct fusbh200_iso_stream *stream = itd->stream;
4595 struct usb_device *dev;
4596 bool retval = false;
4597
4598
4599 for (uframe = 0; uframe < 8; uframe++) {
4600 if (likely (itd->index[uframe] == -1))
4601 continue;
4602 urb_index = itd->index[uframe];
4603 desc = &urb->iso_frame_desc [urb_index];
4604
4605 t = hc32_to_cpup(fusbh200, &itd->hw_transaction [uframe]);
4606 itd->hw_transaction [uframe] = 0;
4607
4608
4609 if (unlikely (t & ISO_ERRS)) {
4610 urb->error_count++;
4611 if (t & FUSBH200_ISOC_BUF_ERR)
4612 desc->status = usb_pipein (urb->pipe)
4613 ? -ENOSR
4614 : -ECOMM;
4615 else if (t & FUSBH200_ISOC_BABBLE)
4616 desc->status = -EOVERFLOW;
4617 else
4618 desc->status = -EPROTO;
4619
4620
4621 if (!(t & FUSBH200_ISOC_BABBLE)) {
4622 desc->actual_length = fusbh200_itdlen(urb, desc, t);
4623 urb->actual_length += desc->actual_length;
4624 }
4625 } else if (likely ((t & FUSBH200_ISOC_ACTIVE) == 0)) {
4626 desc->status = 0;
4627 desc->actual_length = fusbh200_itdlen(urb, desc, t);
4628 urb->actual_length += desc->actual_length;
4629 } else {
4630
4631 desc->status = -EXDEV;
4632 }
4633 }
4634
4635
4636 if (likely ((urb_index + 1) != urb->number_of_packets))
4637 goto done;
4638
4639
4640
4641
4642
4643
4644
4645 dev = urb->dev;
4646 fusbh200_urb_done(fusbh200, urb, 0);
4647 retval = true;
4648 urb = NULL;
4649
4650 --fusbh200->isoc_count;
4651 disable_periodic(fusbh200);
4652
4653 if (unlikely(list_is_singular(&stream->td_list))) {
4654 fusbh200_to_hcd(fusbh200)->self.bandwidth_allocated
4655 -= stream->bandwidth;
4656 fusbh200_dbg(fusbh200,
4657 "deschedule devp %s ep%d%s-iso\n",
4658 dev->devpath, stream->bEndpointAddress & 0x0f,
4659 (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
4660 }
4661
4662done:
4663 itd->urb = NULL;
4664
4665
4666 list_move_tail(&itd->itd_list, &stream->free_list);
4667
4668
4669 if (list_empty(&stream->td_list)) {
4670 list_splice_tail_init(&stream->free_list,
4671 &fusbh200->cached_itd_list);
4672 start_free_itds(fusbh200);
4673 }
4674
4675 return retval;
4676}
4677
4678
4679
4680static int itd_submit (struct fusbh200_hcd *fusbh200, struct urb *urb,
4681 gfp_t mem_flags)
4682{
4683 int status = -EINVAL;
4684 unsigned long flags;
4685 struct fusbh200_iso_stream *stream;
4686
4687
4688 stream = iso_stream_find (fusbh200, urb);
4689 if (unlikely (stream == NULL)) {
4690 fusbh200_dbg (fusbh200, "can't get iso stream\n");
4691 return -ENOMEM;
4692 }
4693 if (unlikely (urb->interval != stream->interval &&
4694 fusbh200_port_speed(fusbh200, 0) == USB_PORT_STAT_HIGH_SPEED)) {
4695 fusbh200_dbg (fusbh200, "can't change iso interval %d --> %d\n",
4696 stream->interval, urb->interval);
4697 goto done;
4698 }
4699
4700#ifdef FUSBH200_URB_TRACE
4701 fusbh200_dbg (fusbh200,
4702 "%s %s urb %p ep%d%s len %d, %d pkts %d uframes [%p]\n",
4703 __func__, urb->dev->devpath, urb,
4704 usb_pipeendpoint (urb->pipe),
4705 usb_pipein (urb->pipe) ? "in" : "out",
4706 urb->transfer_buffer_length,
4707 urb->number_of_packets, urb->interval,
4708 stream);
4709#endif
4710
4711
4712 status = itd_urb_transaction (stream, fusbh200, urb, mem_flags);
4713 if (unlikely (status < 0)) {
4714 fusbh200_dbg (fusbh200, "can't init itds\n");
4715 goto done;
4716 }
4717
4718
4719 spin_lock_irqsave (&fusbh200->lock, flags);
4720 if (unlikely(!HCD_HW_ACCESSIBLE(fusbh200_to_hcd(fusbh200)))) {
4721 status = -ESHUTDOWN;
4722 goto done_not_linked;
4723 }
4724 status = usb_hcd_link_urb_to_ep(fusbh200_to_hcd(fusbh200), urb);
4725 if (unlikely(status))
4726 goto done_not_linked;
4727 status = iso_stream_schedule(fusbh200, urb, stream);
4728 if (likely (status == 0))
4729 itd_link_urb (fusbh200, urb, fusbh200->periodic_size << 3, stream);
4730 else
4731 usb_hcd_unlink_urb_from_ep(fusbh200_to_hcd(fusbh200), urb);
4732 done_not_linked:
4733 spin_unlock_irqrestore (&fusbh200->lock, flags);
4734 done:
4735 return status;
4736}
4737
4738
4739
4740static void scan_isoc(struct fusbh200_hcd *fusbh200)
4741{
4742 unsigned uf, now_frame, frame;
4743 unsigned fmask = fusbh200->periodic_size - 1;
4744 bool modified, live;
4745
4746
4747
4748
4749
4750
4751 if (fusbh200->rh_state >= FUSBH200_RH_RUNNING) {
4752 uf = fusbh200_read_frame_index(fusbh200);
4753 now_frame = (uf >> 3) & fmask;
4754 live = true;
4755 } else {
4756 now_frame = (fusbh200->next_frame - 1) & fmask;
4757 live = false;
4758 }
4759 fusbh200->now_frame = now_frame;
4760
4761 frame = fusbh200->next_frame;
4762 for (;;) {
4763 union fusbh200_shadow q, *q_p;
4764 __hc32 type, *hw_p;
4765
4766restart:
4767
4768 q_p = &fusbh200->pshadow [frame];
4769 hw_p = &fusbh200->periodic [frame];
4770 q.ptr = q_p->ptr;
4771 type = Q_NEXT_TYPE(fusbh200, *hw_p);
4772 modified = false;
4773
4774 while (q.ptr != NULL) {
4775 switch (hc32_to_cpu(fusbh200, type)) {
4776 case Q_TYPE_ITD:
4777
4778
4779
4780
4781
4782 if (frame == now_frame && live) {
4783 rmb();
4784 for (uf = 0; uf < 8; uf++) {
4785 if (q.itd->hw_transaction[uf] &
4786 ITD_ACTIVE(fusbh200))
4787 break;
4788 }
4789 if (uf < 8) {
4790 q_p = &q.itd->itd_next;
4791 hw_p = &q.itd->hw_next;
4792 type = Q_NEXT_TYPE(fusbh200,
4793 q.itd->hw_next);
4794 q = *q_p;
4795 break;
4796 }
4797 }
4798
4799
4800
4801
4802
4803
4804 *q_p = q.itd->itd_next;
4805 *hw_p = q.itd->hw_next;
4806 type = Q_NEXT_TYPE(fusbh200, q.itd->hw_next);
4807 wmb();
4808 modified = itd_complete (fusbh200, q.itd);
4809 q = *q_p;
4810 break;
4811 default:
4812 fusbh200_dbg(fusbh200, "corrupt type %d frame %d shadow %p\n",
4813 type, frame, q.ptr);
4814
4815
4816 case Q_TYPE_QH:
4817 case Q_TYPE_FSTN:
4818
4819 q.ptr = NULL;
4820 break;
4821 }
4822
4823
4824 if (unlikely(modified && fusbh200->isoc_count > 0))
4825 goto restart;
4826 }
4827
4828
4829 if (frame == now_frame)
4830 break;
4831 frame = (frame + 1) & fmask;
4832 }
4833 fusbh200->next_frame = now_frame;
4834}
4835
4836
4837
4838
4839static ssize_t show_uframe_periodic_max(struct device *dev,
4840 struct device_attribute *attr,
4841 char *buf)
4842{
4843 struct fusbh200_hcd *fusbh200;
4844 int n;
4845
4846 fusbh200 = hcd_to_fusbh200(bus_to_hcd(dev_get_drvdata(dev)));
4847 n = scnprintf(buf, PAGE_SIZE, "%d\n", fusbh200->uframe_periodic_max);
4848 return n;
4849}
4850
4851
4852static ssize_t store_uframe_periodic_max(struct device *dev,
4853 struct device_attribute *attr,
4854 const char *buf, size_t count)
4855{
4856 struct fusbh200_hcd *fusbh200;
4857 unsigned uframe_periodic_max;
4858 unsigned frame, uframe;
4859 unsigned short allocated_max;
4860 unsigned long flags;
4861 ssize_t ret;
4862
4863 fusbh200 = hcd_to_fusbh200(bus_to_hcd(dev_get_drvdata(dev)));
4864 if (kstrtouint(buf, 0, &uframe_periodic_max) < 0)
4865 return -EINVAL;
4866
4867 if (uframe_periodic_max < 100 || uframe_periodic_max >= 125) {
4868 fusbh200_info(fusbh200, "rejecting invalid request for "
4869 "uframe_periodic_max=%u\n", uframe_periodic_max);
4870 return -EINVAL;
4871 }
4872
4873 ret = -EINVAL;
4874
4875
4876
4877
4878
4879 spin_lock_irqsave (&fusbh200->lock, flags);
4880
4881
4882
4883
4884
4885
4886 if (uframe_periodic_max < fusbh200->uframe_periodic_max) {
4887 allocated_max = 0;
4888
4889 for (frame = 0; frame < fusbh200->periodic_size; ++frame)
4890 for (uframe = 0; uframe < 7; ++uframe)
4891 allocated_max = max(allocated_max,
4892 periodic_usecs (fusbh200, frame, uframe));
4893
4894 if (allocated_max > uframe_periodic_max) {
4895 fusbh200_info(fusbh200,
4896 "cannot decrease uframe_periodic_max because "
4897 "periodic bandwidth is already allocated "
4898 "(%u > %u)\n",
4899 allocated_max, uframe_periodic_max);
4900 goto out_unlock;
4901 }
4902 }
4903
4904
4905
4906 fusbh200_info(fusbh200, "setting max periodic bandwidth to %u%% "
4907 "(== %u usec/uframe)\n",
4908 100*uframe_periodic_max/125, uframe_periodic_max);
4909
4910 if (uframe_periodic_max != 100)
4911 fusbh200_warn(fusbh200, "max periodic bandwidth set is non-standard\n");
4912
4913 fusbh200->uframe_periodic_max = uframe_periodic_max;
4914 ret = count;
4915
4916out_unlock:
4917 spin_unlock_irqrestore (&fusbh200->lock, flags);
4918 return ret;
4919}
4920static DEVICE_ATTR(uframe_periodic_max, 0644, show_uframe_periodic_max, store_uframe_periodic_max);
4921
4922
4923static inline int create_sysfs_files(struct fusbh200_hcd *fusbh200)
4924{
4925 struct device *controller = fusbh200_to_hcd(fusbh200)->self.controller;
4926 int i = 0;
4927
4928 if (i)
4929 goto out;
4930
4931 i = device_create_file(controller, &dev_attr_uframe_periodic_max);
4932out:
4933 return i;
4934}
4935
4936static inline void remove_sysfs_files(struct fusbh200_hcd *fusbh200)
4937{
4938 struct device *controller = fusbh200_to_hcd(fusbh200)->self.controller;
4939
4940 device_remove_file(controller, &dev_attr_uframe_periodic_max);
4941}
4942
4943
4944
4945
4946
4947
4948static void fusbh200_turn_off_all_ports(struct fusbh200_hcd *fusbh200)
4949{
4950 u32 __iomem *status_reg = &fusbh200->regs->port_status;
4951
4952 fusbh200_writel(fusbh200, PORT_RWC_BITS, status_reg);
4953}
4954
4955
4956
4957
4958
4959static void fusbh200_silence_controller(struct fusbh200_hcd *fusbh200)
4960{
4961 fusbh200_halt(fusbh200);
4962
4963 spin_lock_irq(&fusbh200->lock);
4964 fusbh200->rh_state = FUSBH200_RH_HALTED;
4965 fusbh200_turn_off_all_ports(fusbh200);
4966 spin_unlock_irq(&fusbh200->lock);
4967}
4968
4969
4970
4971
4972
4973static void fusbh200_shutdown(struct usb_hcd *hcd)
4974{
4975 struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200(hcd);
4976
4977 spin_lock_irq(&fusbh200->lock);
4978 fusbh200->shutdown = true;
4979 fusbh200->rh_state = FUSBH200_RH_STOPPING;
4980 fusbh200->enabled_hrtimer_events = 0;
4981 spin_unlock_irq(&fusbh200->lock);
4982
4983 fusbh200_silence_controller(fusbh200);
4984
4985 hrtimer_cancel(&fusbh200->hrtimer);
4986}
4987
4988
4989
4990
4991
4992
4993
4994static void fusbh200_work (struct fusbh200_hcd *fusbh200)
4995{
4996
4997
4998
4999
5000 if (fusbh200->scanning) {
5001 fusbh200->need_rescan = true;
5002 return;
5003 }
5004 fusbh200->scanning = true;
5005
5006 rescan:
5007 fusbh200->need_rescan = false;
5008 if (fusbh200->async_count)
5009 scan_async(fusbh200);
5010 if (fusbh200->intr_count > 0)
5011 scan_intr(fusbh200);
5012 if (fusbh200->isoc_count > 0)
5013 scan_isoc(fusbh200);
5014 if (fusbh200->need_rescan)
5015 goto rescan;
5016 fusbh200->scanning = false;
5017
5018
5019
5020
5021
5022 turn_on_io_watchdog(fusbh200);
5023}
5024
5025
5026
5027
5028static void fusbh200_stop (struct usb_hcd *hcd)
5029{
5030 struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200 (hcd);
5031
5032 fusbh200_dbg (fusbh200, "stop\n");
5033
5034
5035
5036 spin_lock_irq(&fusbh200->lock);
5037 fusbh200->enabled_hrtimer_events = 0;
5038 spin_unlock_irq(&fusbh200->lock);
5039
5040 fusbh200_quiesce(fusbh200);
5041 fusbh200_silence_controller(fusbh200);
5042 fusbh200_reset (fusbh200);
5043
5044 hrtimer_cancel(&fusbh200->hrtimer);
5045 remove_sysfs_files(fusbh200);
5046 remove_debug_files (fusbh200);
5047
5048
5049 spin_lock_irq (&fusbh200->lock);
5050 end_free_itds(fusbh200);
5051 spin_unlock_irq (&fusbh200->lock);
5052 fusbh200_mem_cleanup (fusbh200);
5053
5054 fusbh200_dbg(fusbh200, "irq normal %ld err %ld iaa %ld (lost %ld)\n",
5055 fusbh200->stats.normal, fusbh200->stats.error, fusbh200->stats.iaa,
5056 fusbh200->stats.lost_iaa);
5057 fusbh200_dbg (fusbh200, "complete %ld unlink %ld\n",
5058 fusbh200->stats.complete, fusbh200->stats.unlink);
5059
5060 dbg_status (fusbh200, "fusbh200_stop completed",
5061 fusbh200_readl(fusbh200, &fusbh200->regs->status));
5062}
5063
5064
5065static int hcd_fusbh200_init(struct usb_hcd *hcd)
5066{
5067 struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200(hcd);
5068 u32 temp;
5069 int retval;
5070 u32 hcc_params;
5071 struct fusbh200_qh_hw *hw;
5072
5073 spin_lock_init(&fusbh200->lock);
5074
5075
5076
5077
5078 fusbh200->need_io_watchdog = 1;
5079
5080 hrtimer_init(&fusbh200->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
5081 fusbh200->hrtimer.function = fusbh200_hrtimer_func;
5082 fusbh200->next_hrtimer_event = FUSBH200_HRTIMER_NO_EVENT;
5083
5084 hcc_params = fusbh200_readl(fusbh200, &fusbh200->caps->hcc_params);
5085
5086
5087
5088
5089
5090 fusbh200->uframe_periodic_max = 100;
5091
5092
5093
5094
5095
5096 fusbh200->periodic_size = DEFAULT_I_TDPS;
5097 INIT_LIST_HEAD(&fusbh200->intr_qh_list);
5098 INIT_LIST_HEAD(&fusbh200->cached_itd_list);
5099
5100 if (HCC_PGM_FRAMELISTLEN(hcc_params)) {
5101
5102 switch (FUSBH200_TUNE_FLS) {
5103 case 0: fusbh200->periodic_size = 1024; break;
5104 case 1: fusbh200->periodic_size = 512; break;
5105 case 2: fusbh200->periodic_size = 256; break;
5106 default: BUG();
5107 }
5108 }
5109 if ((retval = fusbh200_mem_init(fusbh200, GFP_KERNEL)) < 0)
5110 return retval;
5111
5112
5113 fusbh200->i_thresh = 2;
5114
5115
5116
5117
5118
5119
5120
5121
5122 fusbh200->async->qh_next.qh = NULL;
5123 hw = fusbh200->async->hw;
5124 hw->hw_next = QH_NEXT(fusbh200, fusbh200->async->qh_dma);
5125 hw->hw_info1 = cpu_to_hc32(fusbh200, QH_HEAD);
5126 hw->hw_token = cpu_to_hc32(fusbh200, QTD_STS_HALT);
5127 hw->hw_qtd_next = FUSBH200_LIST_END(fusbh200);
5128 fusbh200->async->qh_state = QH_STATE_LINKED;
5129 hw->hw_alt_next = QTD_NEXT(fusbh200, fusbh200->async->dummy->qtd_dma);
5130
5131
5132 if (log2_irq_thresh < 0 || log2_irq_thresh > 6)
5133 log2_irq_thresh = 0;
5134 temp = 1 << (16 + log2_irq_thresh);
5135 if (HCC_CANPARK(hcc_params)) {
5136
5137
5138
5139
5140
5141
5142
5143 if (park) {
5144 park = min(park, (unsigned) 3);
5145 temp |= CMD_PARK;
5146 temp |= park << 8;
5147 }
5148 fusbh200_dbg(fusbh200, "park %d\n", park);
5149 }
5150 if (HCC_PGM_FRAMELISTLEN(hcc_params)) {
5151
5152 temp &= ~(3 << 2);
5153 temp |= (FUSBH200_TUNE_FLS << 2);
5154 }
5155 fusbh200->command = temp;
5156
5157
5158 if (!(hcd->driver->flags & HCD_LOCAL_MEM))
5159 hcd->self.sg_tablesize = ~0;
5160 return 0;
5161}
5162
5163
5164static int fusbh200_run (struct usb_hcd *hcd)
5165{
5166 struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200 (hcd);
5167 u32 temp;
5168 u32 hcc_params;
5169
5170 hcd->uses_new_polling = 1;
5171
5172
5173
5174 fusbh200_writel(fusbh200, fusbh200->periodic_dma, &fusbh200->regs->frame_list);
5175 fusbh200_writel(fusbh200, (u32)fusbh200->async->qh_dma, &fusbh200->regs->async_next);
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189 hcc_params = fusbh200_readl(fusbh200, &fusbh200->caps->hcc_params);
5190
5191
5192
5193 fusbh200->command &= ~(CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET);
5194 fusbh200->command |= CMD_RUN;
5195 fusbh200_writel(fusbh200, fusbh200->command, &fusbh200->regs->command);
5196 dbg_cmd (fusbh200, "init", fusbh200->command);
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212 down_write(&ehci_cf_port_reset_rwsem);
5213 fusbh200->rh_state = FUSBH200_RH_RUNNING;
5214 fusbh200_readl(fusbh200, &fusbh200->regs->command);
5215 msleep(5);
5216 up_write(&ehci_cf_port_reset_rwsem);
5217 fusbh200->last_periodic_enable = ktime_get_real();
5218
5219 temp = HC_VERSION(fusbh200, fusbh200_readl(fusbh200, &fusbh200->caps->hc_capbase));
5220 fusbh200_info (fusbh200,
5221 "USB %x.%x started, EHCI %x.%02x\n",
5222 ((fusbh200->sbrn & 0xf0)>>4), (fusbh200->sbrn & 0x0f),
5223 temp >> 8, temp & 0xff);
5224
5225 fusbh200_writel(fusbh200, INTR_MASK,
5226 &fusbh200->regs->intr_enable);
5227
5228
5229
5230
5231
5232 create_debug_files(fusbh200);
5233 create_sysfs_files(fusbh200);
5234
5235 return 0;
5236}
5237
5238static int fusbh200_setup(struct usb_hcd *hcd)
5239{
5240 struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200(hcd);
5241 int retval;
5242
5243 fusbh200->regs = (void __iomem *)fusbh200->caps +
5244 HC_LENGTH(fusbh200, fusbh200_readl(fusbh200, &fusbh200->caps->hc_capbase));
5245 dbg_hcs_params(fusbh200, "reset");
5246 dbg_hcc_params(fusbh200, "reset");
5247
5248
5249 fusbh200->hcs_params = fusbh200_readl(fusbh200, &fusbh200->caps->hcs_params);
5250
5251 fusbh200->sbrn = HCD_USB2;
5252
5253
5254 retval = hcd_fusbh200_init(hcd);
5255 if (retval)
5256 return retval;
5257
5258 retval = fusbh200_halt(fusbh200);
5259 if (retval)
5260 return retval;
5261
5262 fusbh200_reset(fusbh200);
5263
5264 return 0;
5265}
5266
5267
5268
5269static irqreturn_t fusbh200_irq (struct usb_hcd *hcd)
5270{
5271 struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200 (hcd);
5272 u32 status, masked_status, pcd_status = 0, cmd;
5273 int bh;
5274
5275 spin_lock (&fusbh200->lock);
5276
5277 status = fusbh200_readl(fusbh200, &fusbh200->regs->status);
5278
5279
5280 if (status == ~(u32) 0) {
5281 fusbh200_dbg (fusbh200, "device removed\n");
5282 goto dead;
5283 }
5284
5285
5286
5287
5288
5289 masked_status = status & (INTR_MASK | STS_FLR);
5290
5291
5292 if (!masked_status || unlikely(fusbh200->rh_state == FUSBH200_RH_HALTED)) {
5293 spin_unlock(&fusbh200->lock);
5294 return IRQ_NONE;
5295 }
5296
5297
5298 fusbh200_writel(fusbh200, masked_status, &fusbh200->regs->status);
5299 cmd = fusbh200_readl(fusbh200, &fusbh200->regs->command);
5300 bh = 0;
5301
5302
5303 if (likely ((status & (STS_INT|STS_ERR)) != 0)) {
5304 if (likely ((status & STS_ERR) == 0))
5305 COUNT (fusbh200->stats.normal);
5306 else
5307 COUNT (fusbh200->stats.error);
5308 bh = 1;
5309 }
5310
5311
5312 if (status & STS_IAA) {
5313
5314
5315 fusbh200->enabled_hrtimer_events &= ~BIT(FUSBH200_HRTIMER_IAA_WATCHDOG);
5316
5317
5318
5319
5320
5321
5322
5323
5324 if (fusbh200->next_hrtimer_event == FUSBH200_HRTIMER_IAA_WATCHDOG)
5325 ++fusbh200->next_hrtimer_event;
5326
5327
5328 if (cmd & CMD_IAAD)
5329 fusbh200_dbg(fusbh200, "IAA with IAAD still set?\n");
5330 if (fusbh200->async_iaa) {
5331 COUNT(fusbh200->stats.iaa);
5332 end_unlink_async(fusbh200);
5333 } else
5334 fusbh200_dbg(fusbh200, "IAA with nothing unlinked?\n");
5335 }
5336
5337
5338 if (status & STS_PCD) {
5339 int pstatus;
5340 u32 __iomem *status_reg = &fusbh200->regs->port_status;
5341
5342
5343 pcd_status = status;
5344
5345
5346 if (fusbh200->rh_state == FUSBH200_RH_SUSPENDED)
5347 usb_hcd_resume_root_hub(hcd);
5348
5349 pstatus = fusbh200_readl(fusbh200, status_reg);
5350
5351 if (test_bit(0, &fusbh200->suspended_ports) &&
5352 ((pstatus & PORT_RESUME) ||
5353 !(pstatus & PORT_SUSPEND)) &&
5354 (pstatus & PORT_PE) &&
5355 fusbh200->reset_done[0] == 0) {
5356
5357
5358
5359
5360
5361
5362 fusbh200->reset_done[0] = jiffies + msecs_to_jiffies(25);
5363 set_bit(0, &fusbh200->resuming_ports);
5364 fusbh200_dbg (fusbh200, "port 1 remote wakeup\n");
5365 mod_timer(&hcd->rh_timer, fusbh200->reset_done[0]);
5366 }
5367 }
5368
5369
5370 if (unlikely ((status & STS_FATAL) != 0)) {
5371 fusbh200_err(fusbh200, "fatal error\n");
5372 dbg_cmd(fusbh200, "fatal", cmd);
5373 dbg_status(fusbh200, "fatal", status);
5374dead:
5375 usb_hc_died(hcd);
5376
5377
5378 fusbh200->shutdown = true;
5379 fusbh200->rh_state = FUSBH200_RH_STOPPING;
5380 fusbh200->command &= ~(CMD_RUN | CMD_ASE | CMD_PSE);
5381 fusbh200_writel(fusbh200, fusbh200->command, &fusbh200->regs->command);
5382 fusbh200_writel(fusbh200, 0, &fusbh200->regs->intr_enable);
5383 fusbh200_handle_controller_death(fusbh200);
5384
5385
5386 bh = 0;
5387 }
5388
5389 if (bh)
5390 fusbh200_work (fusbh200);
5391 spin_unlock (&fusbh200->lock);
5392 if (pcd_status)
5393 usb_hcd_poll_rh_status(hcd);
5394 return IRQ_HANDLED;
5395}
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411static int fusbh200_urb_enqueue (
5412 struct usb_hcd *hcd,
5413 struct urb *urb,
5414 gfp_t mem_flags
5415) {
5416 struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200 (hcd);
5417 struct list_head qtd_list;
5418
5419 INIT_LIST_HEAD (&qtd_list);
5420
5421 switch (usb_pipetype (urb->pipe)) {
5422 case PIPE_CONTROL:
5423
5424
5425
5426 if (urb->transfer_buffer_length > (16 * 1024))
5427 return -EMSGSIZE;
5428
5429
5430 default:
5431 if (!qh_urb_transaction (fusbh200, urb, &qtd_list, mem_flags))
5432 return -ENOMEM;
5433 return submit_async(fusbh200, urb, &qtd_list, mem_flags);
5434
5435 case PIPE_INTERRUPT:
5436 if (!qh_urb_transaction (fusbh200, urb, &qtd_list, mem_flags))
5437 return -ENOMEM;
5438 return intr_submit(fusbh200, urb, &qtd_list, mem_flags);
5439
5440 case PIPE_ISOCHRONOUS:
5441 return itd_submit (fusbh200, urb, mem_flags);
5442 }
5443}
5444
5445
5446
5447
5448
5449static int fusbh200_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
5450{
5451 struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200 (hcd);
5452 struct fusbh200_qh *qh;
5453 unsigned long flags;
5454 int rc;
5455
5456 spin_lock_irqsave (&fusbh200->lock, flags);
5457 rc = usb_hcd_check_unlink_urb(hcd, urb, status);
5458 if (rc)
5459 goto done;
5460
5461 switch (usb_pipetype (urb->pipe)) {
5462
5463
5464 default:
5465 qh = (struct fusbh200_qh *) urb->hcpriv;
5466 if (!qh)
5467 break;
5468 switch (qh->qh_state) {
5469 case QH_STATE_LINKED:
5470 case QH_STATE_COMPLETING:
5471 start_unlink_async(fusbh200, qh);
5472 break;
5473 case QH_STATE_UNLINK:
5474 case QH_STATE_UNLINK_WAIT:
5475
5476 break;
5477 case QH_STATE_IDLE:
5478
5479 qh_completions(fusbh200, qh);
5480 break;
5481 }
5482 break;
5483
5484 case PIPE_INTERRUPT:
5485 qh = (struct fusbh200_qh *) urb->hcpriv;
5486 if (!qh)
5487 break;
5488 switch (qh->qh_state) {
5489 case QH_STATE_LINKED:
5490 case QH_STATE_COMPLETING:
5491 start_unlink_intr(fusbh200, qh);
5492 break;
5493 case QH_STATE_IDLE:
5494 qh_completions (fusbh200, qh);
5495 break;
5496 default:
5497 fusbh200_dbg (fusbh200, "bogus qh %p state %d\n",
5498 qh, qh->qh_state);
5499 goto done;
5500 }
5501 break;
5502
5503 case PIPE_ISOCHRONOUS:
5504
5505
5506
5507
5508 break;
5509 }
5510done:
5511 spin_unlock_irqrestore (&fusbh200->lock, flags);
5512 return rc;
5513}
5514
5515
5516
5517
5518
5519static void
5520fusbh200_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
5521{
5522 struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200 (hcd);
5523 unsigned long flags;
5524 struct fusbh200_qh *qh, *tmp;
5525
5526
5527
5528
5529rescan:
5530 spin_lock_irqsave (&fusbh200->lock, flags);
5531 qh = ep->hcpriv;
5532 if (!qh)
5533 goto done;
5534
5535
5536
5537
5538 if (qh->hw == NULL) {
5539 struct fusbh200_iso_stream *stream = ep->hcpriv;
5540
5541 if (!list_empty(&stream->td_list))
5542 goto idle_timeout;
5543
5544
5545 kfree(stream);
5546 goto done;
5547 }
5548
5549 if (fusbh200->rh_state < FUSBH200_RH_RUNNING)
5550 qh->qh_state = QH_STATE_IDLE;
5551 switch (qh->qh_state) {
5552 case QH_STATE_LINKED:
5553 case QH_STATE_COMPLETING:
5554 for (tmp = fusbh200->async->qh_next.qh;
5555 tmp && tmp != qh;
5556 tmp = tmp->qh_next.qh)
5557 continue;
5558
5559
5560
5561 if (tmp)
5562 start_unlink_async(fusbh200, qh);
5563
5564 case QH_STATE_UNLINK:
5565 case QH_STATE_UNLINK_WAIT:
5566idle_timeout:
5567 spin_unlock_irqrestore (&fusbh200->lock, flags);
5568 schedule_timeout_uninterruptible(1);
5569 goto rescan;
5570 case QH_STATE_IDLE:
5571 if (qh->clearing_tt)
5572 goto idle_timeout;
5573 if (list_empty (&qh->qtd_list)) {
5574 qh_destroy(fusbh200, qh);
5575 break;
5576 }
5577
5578 default:
5579
5580
5581
5582 fusbh200_err (fusbh200, "qh %p (#%02x) state %d%s\n",
5583 qh, ep->desc.bEndpointAddress, qh->qh_state,
5584 list_empty (&qh->qtd_list) ? "" : "(has tds)");
5585 break;
5586 }
5587 done:
5588 ep->hcpriv = NULL;
5589 spin_unlock_irqrestore (&fusbh200->lock, flags);
5590}
5591
5592static void
5593fusbh200_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
5594{
5595 struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200(hcd);
5596 struct fusbh200_qh *qh;
5597 int eptype = usb_endpoint_type(&ep->desc);
5598 int epnum = usb_endpoint_num(&ep->desc);
5599 int is_out = usb_endpoint_dir_out(&ep->desc);
5600 unsigned long flags;
5601
5602 if (eptype != USB_ENDPOINT_XFER_BULK && eptype != USB_ENDPOINT_XFER_INT)
5603 return;
5604
5605 spin_lock_irqsave(&fusbh200->lock, flags);
5606 qh = ep->hcpriv;
5607
5608
5609
5610
5611
5612
5613 if (qh) {
5614 usb_settoggle(qh->dev, epnum, is_out, 0);
5615 if (!list_empty(&qh->qtd_list)) {
5616 WARN_ONCE(1, "clear_halt for a busy endpoint\n");
5617 } else if (qh->qh_state == QH_STATE_LINKED ||
5618 qh->qh_state == QH_STATE_COMPLETING) {
5619
5620
5621
5622
5623
5624 if (eptype == USB_ENDPOINT_XFER_BULK)
5625 start_unlink_async(fusbh200, qh);
5626 else
5627 start_unlink_intr(fusbh200, qh);
5628 }
5629 }
5630 spin_unlock_irqrestore(&fusbh200->lock, flags);
5631}
5632
5633static int fusbh200_get_frame (struct usb_hcd *hcd)
5634{
5635 struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200 (hcd);
5636 return (fusbh200_read_frame_index(fusbh200) >> 3) % fusbh200->periodic_size;
5637}
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647MODULE_DESCRIPTION(DRIVER_DESC);
5648MODULE_AUTHOR (DRIVER_AUTHOR);
5649MODULE_LICENSE ("GPL");
5650
5651static const struct hc_driver fusbh200_fusbh200_hc_driver = {
5652 .description = hcd_name,
5653 .product_desc = "Faraday USB2.0 Host Controller",
5654 .hcd_priv_size = sizeof(struct fusbh200_hcd),
5655
5656
5657
5658
5659 .irq = fusbh200_irq,
5660 .flags = HCD_MEMORY | HCD_USB2,
5661
5662
5663
5664
5665 .reset = hcd_fusbh200_init,
5666 .start = fusbh200_run,
5667 .stop = fusbh200_stop,
5668 .shutdown = fusbh200_shutdown,
5669
5670
5671
5672
5673 .urb_enqueue = fusbh200_urb_enqueue,
5674 .urb_dequeue = fusbh200_urb_dequeue,
5675 .endpoint_disable = fusbh200_endpoint_disable,
5676 .endpoint_reset = fusbh200_endpoint_reset,
5677
5678
5679
5680
5681 .get_frame_number = fusbh200_get_frame,
5682
5683
5684
5685
5686 .hub_status_data = fusbh200_hub_status_data,
5687 .hub_control = fusbh200_hub_control,
5688 .bus_suspend = fusbh200_bus_suspend,
5689 .bus_resume = fusbh200_bus_resume,
5690
5691 .relinquish_port = fusbh200_relinquish_port,
5692 .port_handed_over = fusbh200_port_handed_over,
5693
5694 .clear_tt_buffer_complete = fusbh200_clear_tt_buffer_complete,
5695};
5696
5697static void fusbh200_init(struct fusbh200_hcd *fusbh200)
5698{
5699 u32 reg;
5700
5701 reg = fusbh200_readl(fusbh200, &fusbh200->regs->bmcsr);
5702 reg |= BMCSR_INT_POLARITY;
5703 reg &= ~BMCSR_VBUS_OFF;
5704 fusbh200_writel(fusbh200, reg, &fusbh200->regs->bmcsr);
5705
5706 reg = fusbh200_readl(fusbh200, &fusbh200->regs->bmier);
5707 fusbh200_writel(fusbh200, reg | BMIER_OVC_EN | BMIER_VBUS_ERR_EN,
5708 &fusbh200->regs->bmier);
5709}
5710
5711
5712
5713
5714
5715
5716
5717
5718static int fusbh200_hcd_probe(struct platform_device *pdev)
5719{
5720 struct device *dev = &pdev->dev;
5721 struct usb_hcd *hcd;
5722 struct resource *res;
5723 int irq;
5724 int retval = -ENODEV;
5725 struct fusbh200_hcd *fusbh200;
5726
5727 if (usb_disabled())
5728 return -ENODEV;
5729
5730 pdev->dev.power.power_state = PMSG_ON;
5731
5732 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
5733 if (!res) {
5734 dev_err(dev,
5735 "Found HC with no IRQ. Check %s setup!\n",
5736 dev_name(dev));
5737 return -ENODEV;
5738 }
5739
5740 irq = res->start;
5741
5742 hcd = usb_create_hcd(&fusbh200_fusbh200_hc_driver, dev,
5743 dev_name(dev));
5744 if (!hcd) {
5745 dev_err(dev, "failed to create hcd with err %d\n", retval);
5746 retval = -ENOMEM;
5747 goto fail_create_hcd;
5748 }
5749
5750 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
5751 if (!res) {
5752 dev_err(dev,
5753 "Found HC with no register addr. Check %s setup!\n",
5754 dev_name(dev));
5755 retval = -ENODEV;
5756 goto fail_request_resource;
5757 }
5758
5759 hcd->rsrc_start = res->start;
5760 hcd->rsrc_len = resource_size(res);
5761 hcd->has_tt = 1;
5762
5763 if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
5764 fusbh200_fusbh200_hc_driver.description)) {
5765 dev_dbg(dev, "controller already in use\n");
5766 retval = -EBUSY;
5767 goto fail_request_resource;
5768 }
5769
5770 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
5771 if (!res) {
5772 dev_err(dev,
5773 "Found HC with no register addr. Check %s setup!\n",
5774 dev_name(dev));
5775 retval = -ENODEV;
5776 goto fail_request_resource;
5777 }
5778
5779 hcd->regs = ioremap_nocache(res->start, resource_size(res));
5780 if (hcd->regs == NULL) {
5781 dev_dbg(dev, "error mapping memory\n");
5782 retval = -EFAULT;
5783 goto fail_ioremap;
5784 }
5785
5786 fusbh200 = hcd_to_fusbh200(hcd);
5787
5788 fusbh200->caps = hcd->regs;
5789
5790 retval = fusbh200_setup(hcd);
5791 if (retval)
5792 goto fail_add_hcd;
5793
5794 fusbh200_init(fusbh200);
5795
5796 retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
5797 if (retval) {
5798 dev_err(dev, "failed to add hcd with err %d\n", retval);
5799 goto fail_add_hcd;
5800 }
5801 device_wakeup_enable(hcd->self.controller);
5802
5803 return retval;
5804
5805fail_add_hcd:
5806 iounmap(hcd->regs);
5807fail_ioremap:
5808 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
5809fail_request_resource:
5810 usb_put_hcd(hcd);
5811fail_create_hcd:
5812 dev_err(dev, "init %s fail, %d\n", dev_name(dev), retval);
5813 return retval;
5814}
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824static int fusbh200_hcd_remove(struct platform_device *pdev)
5825{
5826 struct device *dev = &pdev->dev;
5827 struct usb_hcd *hcd = dev_get_drvdata(dev);
5828
5829 if (!hcd)
5830 return 0;
5831
5832 usb_remove_hcd(hcd);
5833 iounmap(hcd->regs);
5834 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
5835 usb_put_hcd(hcd);
5836
5837 return 0;
5838}
5839
5840static struct platform_driver fusbh200_hcd_fusbh200_driver = {
5841 .driver = {
5842 .name = "fusbh200",
5843 },
5844 .probe = fusbh200_hcd_probe,
5845 .remove = fusbh200_hcd_remove,
5846};
5847
5848static int __init fusbh200_hcd_init(void)
5849{
5850 int retval = 0;
5851
5852 if (usb_disabled())
5853 return -ENODEV;
5854
5855 printk(KERN_INFO "%s: " DRIVER_DESC "\n", hcd_name);
5856 set_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
5857 if (test_bit(USB_UHCI_LOADED, &usb_hcds_loaded) ||
5858 test_bit(USB_OHCI_LOADED, &usb_hcds_loaded))
5859 printk(KERN_WARNING "Warning! fusbh200_hcd should always be loaded"
5860 " before uhci_hcd and ohci_hcd, not after\n");
5861
5862 pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd\n",
5863 hcd_name,
5864 sizeof(struct fusbh200_qh), sizeof(struct fusbh200_qtd),
5865 sizeof(struct fusbh200_itd));
5866
5867 fusbh200_debug_root = debugfs_create_dir("fusbh200", usb_debug_root);
5868 if (!fusbh200_debug_root) {
5869 retval = -ENOENT;
5870 goto err_debug;
5871 }
5872
5873 retval = platform_driver_register(&fusbh200_hcd_fusbh200_driver);
5874 if (retval < 0)
5875 goto clean;
5876 return retval;
5877
5878 platform_driver_unregister(&fusbh200_hcd_fusbh200_driver);
5879clean:
5880 debugfs_remove(fusbh200_debug_root);
5881 fusbh200_debug_root = NULL;
5882err_debug:
5883 clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
5884 return retval;
5885}
5886module_init(fusbh200_hcd_init);
5887
5888static void __exit fusbh200_hcd_cleanup(void)
5889{
5890 platform_driver_unregister(&fusbh200_hcd_fusbh200_driver);
5891 debugfs_remove(fusbh200_debug_root);
5892 clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
5893}
5894module_exit(fusbh200_hcd_cleanup);
5895