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