0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #define edstring(ed_type) ({ char *temp; \
0014 switch (ed_type) { \
0015 case PIPE_CONTROL: temp = "ctrl"; break; \
0016 case PIPE_BULK: temp = "bulk"; break; \
0017 case PIPE_INTERRUPT: temp = "intr"; break; \
0018 default: temp = "isoc"; break; \
0019 } temp;})
0020 #define pipestring(pipe) edstring(usb_pipetype(pipe))
0021
0022
0023 #define ohci_dbg_sw(ohci, next, size, format, arg...) \
0024 do { \
0025 if (next != NULL) { \
0026 unsigned s_len; \
0027 s_len = scnprintf (*next, *size, format, ## arg ); \
0028 *size -= s_len; *next += s_len; \
0029 } else \
0030 ohci_dbg(ohci,format, ## arg ); \
0031 } while (0);
0032
0033
0034 #define ohci_dbg_nosw(ohci, next, size, format, arg...) \
0035 do { \
0036 unsigned s_len; \
0037 s_len = scnprintf(*next, *size, format, ## arg); \
0038 *size -= s_len; *next += s_len; \
0039 } while (0);
0040
0041
0042 static void ohci_dump_intr_mask (
0043 struct ohci_hcd *ohci,
0044 char *label,
0045 u32 mask,
0046 char **next,
0047 unsigned *size)
0048 {
0049 ohci_dbg_sw (ohci, next, size, "%s 0x%08x%s%s%s%s%s%s%s%s%s\n",
0050 label,
0051 mask,
0052 (mask & OHCI_INTR_MIE) ? " MIE" : "",
0053 (mask & OHCI_INTR_OC) ? " OC" : "",
0054 (mask & OHCI_INTR_RHSC) ? " RHSC" : "",
0055 (mask & OHCI_INTR_FNO) ? " FNO" : "",
0056 (mask & OHCI_INTR_UE) ? " UE" : "",
0057 (mask & OHCI_INTR_RD) ? " RD" : "",
0058 (mask & OHCI_INTR_SF) ? " SF" : "",
0059 (mask & OHCI_INTR_WDH) ? " WDH" : "",
0060 (mask & OHCI_INTR_SO) ? " SO" : ""
0061 );
0062 }
0063
0064 static void maybe_print_eds (
0065 struct ohci_hcd *ohci,
0066 char *label,
0067 u32 value,
0068 char **next,
0069 unsigned *size)
0070 {
0071 if (value)
0072 ohci_dbg_sw (ohci, next, size, "%s %08x\n", label, value);
0073 }
0074
0075 static char *hcfs2string (int state)
0076 {
0077 switch (state) {
0078 case OHCI_USB_RESET: return "reset";
0079 case OHCI_USB_RESUME: return "resume";
0080 case OHCI_USB_OPER: return "operational";
0081 case OHCI_USB_SUSPEND: return "suspend";
0082 }
0083 return "?";
0084 }
0085
0086 static const char *rh_state_string(struct ohci_hcd *ohci)
0087 {
0088 switch (ohci->rh_state) {
0089 case OHCI_RH_HALTED:
0090 return "halted";
0091 case OHCI_RH_SUSPENDED:
0092 return "suspended";
0093 case OHCI_RH_RUNNING:
0094 return "running";
0095 }
0096 return "?";
0097 }
0098
0099
0100 static void
0101 ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size)
0102 {
0103 struct ohci_regs __iomem *regs = controller->regs;
0104 u32 temp;
0105
0106 temp = ohci_readl (controller, ®s->revision) & 0xff;
0107 ohci_dbg_sw (controller, next, size,
0108 "OHCI %d.%d, %s legacy support registers, rh state %s\n",
0109 0x03 & (temp >> 4), (temp & 0x0f),
0110 (temp & 0x0100) ? "with" : "NO",
0111 rh_state_string(controller));
0112
0113 temp = ohci_readl (controller, ®s->control);
0114 ohci_dbg_sw (controller, next, size,
0115 "control 0x%03x%s%s%s HCFS=%s%s%s%s%s CBSR=%d\n",
0116 temp,
0117 (temp & OHCI_CTRL_RWE) ? " RWE" : "",
0118 (temp & OHCI_CTRL_RWC) ? " RWC" : "",
0119 (temp & OHCI_CTRL_IR) ? " IR" : "",
0120 hcfs2string (temp & OHCI_CTRL_HCFS),
0121 (temp & OHCI_CTRL_BLE) ? " BLE" : "",
0122 (temp & OHCI_CTRL_CLE) ? " CLE" : "",
0123 (temp & OHCI_CTRL_IE) ? " IE" : "",
0124 (temp & OHCI_CTRL_PLE) ? " PLE" : "",
0125 temp & OHCI_CTRL_CBSR
0126 );
0127
0128 temp = ohci_readl (controller, ®s->cmdstatus);
0129 ohci_dbg_sw (controller, next, size,
0130 "cmdstatus 0x%05x SOC=%d%s%s%s%s\n", temp,
0131 (temp & OHCI_SOC) >> 16,
0132 (temp & OHCI_OCR) ? " OCR" : "",
0133 (temp & OHCI_BLF) ? " BLF" : "",
0134 (temp & OHCI_CLF) ? " CLF" : "",
0135 (temp & OHCI_HCR) ? " HCR" : ""
0136 );
0137
0138 ohci_dump_intr_mask (controller, "intrstatus",
0139 ohci_readl (controller, ®s->intrstatus),
0140 next, size);
0141 ohci_dump_intr_mask (controller, "intrenable",
0142 ohci_readl (controller, ®s->intrenable),
0143 next, size);
0144
0145
0146 maybe_print_eds (controller, "ed_periodcurrent",
0147 ohci_readl (controller, ®s->ed_periodcurrent),
0148 next, size);
0149
0150 maybe_print_eds (controller, "ed_controlhead",
0151 ohci_readl (controller, ®s->ed_controlhead),
0152 next, size);
0153 maybe_print_eds (controller, "ed_controlcurrent",
0154 ohci_readl (controller, ®s->ed_controlcurrent),
0155 next, size);
0156
0157 maybe_print_eds (controller, "ed_bulkhead",
0158 ohci_readl (controller, ®s->ed_bulkhead),
0159 next, size);
0160 maybe_print_eds (controller, "ed_bulkcurrent",
0161 ohci_readl (controller, ®s->ed_bulkcurrent),
0162 next, size);
0163
0164 maybe_print_eds (controller, "donehead",
0165 ohci_readl (controller, ®s->donehead), next, size);
0166 }
0167
0168 #define dbg_port_sw(hc,num,value,next,size) \
0169 ohci_dbg_sw (hc, next, size, \
0170 "roothub.portstatus [%d] " \
0171 "0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n", \
0172 num, temp, \
0173 (temp & RH_PS_PRSC) ? " PRSC" : "", \
0174 (temp & RH_PS_OCIC) ? " OCIC" : "", \
0175 (temp & RH_PS_PSSC) ? " PSSC" : "", \
0176 (temp & RH_PS_PESC) ? " PESC" : "", \
0177 (temp & RH_PS_CSC) ? " CSC" : "", \
0178 \
0179 (temp & RH_PS_LSDA) ? " LSDA" : "", \
0180 (temp & RH_PS_PPS) ? " PPS" : "", \
0181 (temp & RH_PS_PRS) ? " PRS" : "", \
0182 (temp & RH_PS_POCI) ? " POCI" : "", \
0183 (temp & RH_PS_PSS) ? " PSS" : "", \
0184 \
0185 (temp & RH_PS_PES) ? " PES" : "", \
0186 (temp & RH_PS_CCS) ? " CCS" : "" \
0187 );
0188
0189
0190 static void
0191 ohci_dump_roothub (
0192 struct ohci_hcd *controller,
0193 int verbose,
0194 char **next,
0195 unsigned *size)
0196 {
0197 u32 temp, i;
0198
0199 temp = roothub_a (controller);
0200 if (temp == ~(u32)0)
0201 return;
0202
0203 if (verbose) {
0204 ohci_dbg_sw (controller, next, size,
0205 "roothub.a %08x POTPGT=%d%s%s%s%s%s NDP=%d(%d)\n", temp,
0206 ((temp & RH_A_POTPGT) >> 24) & 0xff,
0207 (temp & RH_A_NOCP) ? " NOCP" : "",
0208 (temp & RH_A_OCPM) ? " OCPM" : "",
0209 (temp & RH_A_DT) ? " DT" : "",
0210 (temp & RH_A_NPS) ? " NPS" : "",
0211 (temp & RH_A_PSM) ? " PSM" : "",
0212 (temp & RH_A_NDP), controller->num_ports
0213 );
0214 temp = roothub_b (controller);
0215 ohci_dbg_sw (controller, next, size,
0216 "roothub.b %08x PPCM=%04x DR=%04x\n",
0217 temp,
0218 (temp & RH_B_PPCM) >> 16,
0219 (temp & RH_B_DR)
0220 );
0221 temp = roothub_status (controller);
0222 ohci_dbg_sw (controller, next, size,
0223 "roothub.status %08x%s%s%s%s%s%s\n",
0224 temp,
0225 (temp & RH_HS_CRWE) ? " CRWE" : "",
0226 (temp & RH_HS_OCIC) ? " OCIC" : "",
0227 (temp & RH_HS_LPSC) ? " LPSC" : "",
0228 (temp & RH_HS_DRWE) ? " DRWE" : "",
0229 (temp & RH_HS_OCI) ? " OCI" : "",
0230 (temp & RH_HS_LPS) ? " LPS" : ""
0231 );
0232 }
0233
0234 for (i = 0; i < controller->num_ports; i++) {
0235 temp = roothub_portstatus (controller, i);
0236 dbg_port_sw (controller, i, temp, next, size);
0237 }
0238 }
0239
0240 static void ohci_dump(struct ohci_hcd *controller)
0241 {
0242 ohci_dbg (controller, "OHCI controller state\n");
0243
0244
0245 ohci_dump_status (controller, NULL, NULL);
0246 if (controller->hcca)
0247 ohci_dbg (controller,
0248 "hcca frame #%04x\n", ohci_frame_no(controller));
0249 ohci_dump_roothub (controller, 1, NULL, NULL);
0250 }
0251
0252 static const char data0 [] = "DATA0";
0253 static const char data1 [] = "DATA1";
0254
0255 static void ohci_dump_td (const struct ohci_hcd *ohci, const char *label,
0256 const struct td *td)
0257 {
0258 u32 tmp = hc32_to_cpup (ohci, &td->hwINFO);
0259
0260 ohci_dbg (ohci, "%s td %p%s; urb %p index %d; hw next td %08x\n",
0261 label, td,
0262 (tmp & TD_DONE) ? " (DONE)" : "",
0263 td->urb, td->index,
0264 hc32_to_cpup (ohci, &td->hwNextTD));
0265 if ((tmp & TD_ISO) == 0) {
0266 const char *toggle, *pid;
0267 u32 cbp, be;
0268
0269 switch (tmp & TD_T) {
0270 case TD_T_DATA0: toggle = data0; break;
0271 case TD_T_DATA1: toggle = data1; break;
0272 case TD_T_TOGGLE: toggle = "(CARRY)"; break;
0273 default: toggle = "(?)"; break;
0274 }
0275 switch (tmp & TD_DP) {
0276 case TD_DP_SETUP: pid = "SETUP"; break;
0277 case TD_DP_IN: pid = "IN"; break;
0278 case TD_DP_OUT: pid = "OUT"; break;
0279 default: pid = "(bad pid)"; break;
0280 }
0281 ohci_dbg (ohci, " info %08x CC=%x %s DI=%d %s %s\n", tmp,
0282 TD_CC_GET(tmp), toggle,
0283 (tmp & TD_DI) >> 21, pid,
0284 (tmp & TD_R) ? "R" : "");
0285 cbp = hc32_to_cpup (ohci, &td->hwCBP);
0286 be = hc32_to_cpup (ohci, &td->hwBE);
0287 ohci_dbg (ohci, " cbp %08x be %08x (len %d)\n", cbp, be,
0288 cbp ? (be + 1 - cbp) : 0);
0289 } else {
0290 unsigned i;
0291 ohci_dbg (ohci, " info %08x CC=%x FC=%d DI=%d SF=%04x\n", tmp,
0292 TD_CC_GET(tmp),
0293 (tmp >> 24) & 0x07,
0294 (tmp & TD_DI) >> 21,
0295 tmp & 0x0000ffff);
0296 ohci_dbg (ohci, " bp0 %08x be %08x\n",
0297 hc32_to_cpup (ohci, &td->hwCBP) & ~0x0fff,
0298 hc32_to_cpup (ohci, &td->hwBE));
0299 for (i = 0; i < MAXPSW; i++) {
0300 u16 psw = ohci_hwPSW (ohci, td, i);
0301 int cc = (psw >> 12) & 0x0f;
0302 ohci_dbg (ohci, " psw [%d] = %2x, CC=%x %s=%d\n", i,
0303 psw, cc,
0304 (cc >= 0x0e) ? "OFFSET" : "SIZE",
0305 psw & 0x0fff);
0306 }
0307 }
0308 }
0309
0310
0311 static void __maybe_unused
0312 ohci_dump_ed (const struct ohci_hcd *ohci, const char *label,
0313 const struct ed *ed, int verbose)
0314 {
0315 u32 tmp = hc32_to_cpu (ohci, ed->hwINFO);
0316 char *type = "";
0317
0318 ohci_dbg (ohci, "%s, ed %p state 0x%x type %s; next ed %08x\n",
0319 label,
0320 ed, ed->state, edstring (ed->type),
0321 hc32_to_cpup (ohci, &ed->hwNextED));
0322 switch (tmp & (ED_IN|ED_OUT)) {
0323 case ED_OUT: type = "-OUT"; break;
0324 case ED_IN: type = "-IN"; break;
0325
0326 }
0327 ohci_dbg (ohci,
0328 " info %08x MAX=%d%s%s%s%s EP=%d%s DEV=%d\n", tmp,
0329 0x03ff & (tmp >> 16),
0330 (tmp & ED_DEQUEUE) ? " DQ" : "",
0331 (tmp & ED_ISO) ? " ISO" : "",
0332 (tmp & ED_SKIP) ? " SKIP" : "",
0333 (tmp & ED_LOWSPEED) ? " LOW" : "",
0334 0x000f & (tmp >> 7),
0335 type,
0336 0x007f & tmp);
0337 tmp = hc32_to_cpup (ohci, &ed->hwHeadP);
0338 ohci_dbg (ohci, " tds: head %08x %s%s tail %08x%s\n",
0339 tmp,
0340 (tmp & ED_C) ? data1 : data0,
0341 (tmp & ED_H) ? " HALT" : "",
0342 hc32_to_cpup (ohci, &ed->hwTailP),
0343 verbose ? "" : " (not listing)");
0344 if (verbose) {
0345 struct list_head *tmp;
0346
0347
0348
0349
0350 list_for_each (tmp, &ed->td_list) {
0351 struct td *td;
0352 td = list_entry (tmp, struct td, td_list);
0353 ohci_dump_td (ohci, " ->", td);
0354 }
0355 }
0356 }
0357
0358
0359
0360 static int debug_async_open(struct inode *, struct file *);
0361 static int debug_periodic_open(struct inode *, struct file *);
0362 static int debug_registers_open(struct inode *, struct file *);
0363 static int debug_async_open(struct inode *, struct file *);
0364 static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*);
0365 static int debug_close(struct inode *, struct file *);
0366
0367 static const struct file_operations debug_async_fops = {
0368 .owner = THIS_MODULE,
0369 .open = debug_async_open,
0370 .read = debug_output,
0371 .release = debug_close,
0372 .llseek = default_llseek,
0373 };
0374 static const struct file_operations debug_periodic_fops = {
0375 .owner = THIS_MODULE,
0376 .open = debug_periodic_open,
0377 .read = debug_output,
0378 .release = debug_close,
0379 .llseek = default_llseek,
0380 };
0381 static const struct file_operations debug_registers_fops = {
0382 .owner = THIS_MODULE,
0383 .open = debug_registers_open,
0384 .read = debug_output,
0385 .release = debug_close,
0386 .llseek = default_llseek,
0387 };
0388
0389 static struct dentry *ohci_debug_root;
0390
0391 struct debug_buffer {
0392 ssize_t (*fill_func)(struct debug_buffer *);
0393 struct ohci_hcd *ohci;
0394 struct mutex mutex;
0395 size_t count;
0396 char *page;
0397 };
0398
0399 static ssize_t
0400 show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed)
0401 {
0402 unsigned temp, size = count;
0403
0404 if (!ed)
0405 return 0;
0406
0407
0408 while (ed->ed_prev)
0409 ed = ed->ed_prev;
0410
0411
0412 while (ed) {
0413 u32 info = hc32_to_cpu (ohci, ed->hwINFO);
0414 u32 headp = hc32_to_cpu (ohci, ed->hwHeadP);
0415 struct list_head *entry;
0416 struct td *td;
0417
0418 temp = scnprintf (buf, size,
0419 "ed/%p %cs dev%d ep%d%s max %d %08x%s%s %s",
0420 ed,
0421 (info & ED_LOWSPEED) ? 'l' : 'f',
0422 info & 0x7f,
0423 (info >> 7) & 0xf,
0424 (info & ED_IN) ? "in" : "out",
0425 0x03ff & (info >> 16),
0426 info,
0427 (info & ED_SKIP) ? " s" : "",
0428 (headp & ED_H) ? " H" : "",
0429 (headp & ED_C) ? data1 : data0);
0430 size -= temp;
0431 buf += temp;
0432
0433 list_for_each (entry, &ed->td_list) {
0434 u32 cbp, be;
0435
0436 td = list_entry (entry, struct td, td_list);
0437 info = hc32_to_cpup (ohci, &td->hwINFO);
0438 cbp = hc32_to_cpup (ohci, &td->hwCBP);
0439 be = hc32_to_cpup (ohci, &td->hwBE);
0440 temp = scnprintf (buf, size,
0441 "\n\ttd %p %s %d cc=%x urb %p (%08x)",
0442 td,
0443 ({ char *pid;
0444 switch (info & TD_DP) {
0445 case TD_DP_SETUP: pid = "setup"; break;
0446 case TD_DP_IN: pid = "in"; break;
0447 case TD_DP_OUT: pid = "out"; break;
0448 default: pid = "(?)"; break;
0449 } pid;}),
0450 cbp ? (be + 1 - cbp) : 0,
0451 TD_CC_GET (info), td->urb, info);
0452 size -= temp;
0453 buf += temp;
0454 }
0455
0456 temp = scnprintf (buf, size, "\n");
0457 size -= temp;
0458 buf += temp;
0459
0460 ed = ed->ed_next;
0461 }
0462 return count - size;
0463 }
0464
0465 static ssize_t fill_async_buffer(struct debug_buffer *buf)
0466 {
0467 struct ohci_hcd *ohci;
0468 size_t temp, size;
0469 unsigned long flags;
0470
0471 ohci = buf->ohci;
0472 size = PAGE_SIZE;
0473
0474
0475 spin_lock_irqsave (&ohci->lock, flags);
0476 temp = show_list(ohci, buf->page, size, ohci->ed_controltail);
0477 temp += show_list(ohci, buf->page + temp, size - temp,
0478 ohci->ed_bulktail);
0479 spin_unlock_irqrestore (&ohci->lock, flags);
0480
0481 return temp;
0482 }
0483
0484 #define DBG_SCHED_LIMIT 64
0485
0486 static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
0487 {
0488 struct ohci_hcd *ohci;
0489 struct ed **seen, *ed;
0490 unsigned long flags;
0491 unsigned temp, size, seen_count;
0492 char *next;
0493 unsigned i;
0494
0495 seen = kmalloc_array(DBG_SCHED_LIMIT, sizeof(*seen), GFP_ATOMIC);
0496 if (!seen)
0497 return 0;
0498 seen_count = 0;
0499
0500 ohci = buf->ohci;
0501 next = buf->page;
0502 size = PAGE_SIZE;
0503
0504 temp = scnprintf (next, size, "size = %d\n", NUM_INTS);
0505 size -= temp;
0506 next += temp;
0507
0508
0509 spin_lock_irqsave (&ohci->lock, flags);
0510 for (i = 0; i < NUM_INTS; i++) {
0511 ed = ohci->periodic[i];
0512 if (!ed)
0513 continue;
0514
0515 temp = scnprintf (next, size, "%2d [%3d]:", i, ohci->load [i]);
0516 size -= temp;
0517 next += temp;
0518
0519 do {
0520 temp = scnprintf (next, size, " ed%d/%p",
0521 ed->interval, ed);
0522 size -= temp;
0523 next += temp;
0524 for (temp = 0; temp < seen_count; temp++) {
0525 if (seen [temp] == ed)
0526 break;
0527 }
0528
0529
0530 if (temp == seen_count) {
0531 u32 info = hc32_to_cpu (ohci, ed->hwINFO);
0532 struct list_head *entry;
0533 unsigned qlen = 0;
0534
0535
0536 list_for_each (entry, &ed->td_list)
0537 qlen++;
0538
0539 temp = scnprintf (next, size,
0540 " (%cs dev%d ep%d%s-%s qlen %u"
0541 " max %d %08x%s%s)",
0542 (info & ED_LOWSPEED) ? 'l' : 'f',
0543 info & 0x7f,
0544 (info >> 7) & 0xf,
0545 (info & ED_IN) ? "in" : "out",
0546 (info & ED_ISO) ? "iso" : "int",
0547 qlen,
0548 0x03ff & (info >> 16),
0549 info,
0550 (info & ED_SKIP) ? " K" : "",
0551 (ed->hwHeadP &
0552 cpu_to_hc32(ohci, ED_H)) ?
0553 " H" : "");
0554 size -= temp;
0555 next += temp;
0556
0557 if (seen_count < DBG_SCHED_LIMIT)
0558 seen [seen_count++] = ed;
0559
0560 ed = ed->ed_next;
0561
0562 } else {
0563
0564 temp = 0;
0565 ed = NULL;
0566 }
0567
0568 } while (ed);
0569
0570 temp = scnprintf (next, size, "\n");
0571 size -= temp;
0572 next += temp;
0573 }
0574 spin_unlock_irqrestore (&ohci->lock, flags);
0575 kfree (seen);
0576
0577 return PAGE_SIZE - size;
0578 }
0579 #undef DBG_SCHED_LIMIT
0580
0581 static ssize_t fill_registers_buffer(struct debug_buffer *buf)
0582 {
0583 struct usb_hcd *hcd;
0584 struct ohci_hcd *ohci;
0585 struct ohci_regs __iomem *regs;
0586 unsigned long flags;
0587 unsigned temp, size;
0588 char *next;
0589 u32 rdata;
0590
0591 ohci = buf->ohci;
0592 hcd = ohci_to_hcd(ohci);
0593 regs = ohci->regs;
0594 next = buf->page;
0595 size = PAGE_SIZE;
0596
0597 spin_lock_irqsave (&ohci->lock, flags);
0598
0599
0600
0601 ohci_dbg_nosw(ohci, &next, &size,
0602 "bus %s, device %s\n"
0603 "%s\n"
0604 "%s\n",
0605 hcd->self.controller->bus->name,
0606 dev_name(hcd->self.controller),
0607 hcd->product_desc,
0608 hcd_name);
0609
0610 if (!HCD_HW_ACCESSIBLE(hcd)) {
0611 size -= scnprintf (next, size,
0612 "SUSPENDED (no register access)\n");
0613 goto done;
0614 }
0615
0616 ohci_dump_status(ohci, &next, &size);
0617
0618
0619 if (ohci->hcca)
0620 ohci_dbg_nosw(ohci, &next, &size,
0621 "hcca frame 0x%04x\n", ohci_frame_no(ohci));
0622
0623
0624 rdata = ohci_readl (ohci, ®s->fminterval);
0625 temp = scnprintf (next, size,
0626 "fmintvl 0x%08x %sFSMPS=0x%04x FI=0x%04x\n",
0627 rdata, (rdata >> 31) ? "FIT " : "",
0628 (rdata >> 16) & 0xefff, rdata & 0xffff);
0629 size -= temp;
0630 next += temp;
0631
0632 rdata = ohci_readl (ohci, ®s->fmremaining);
0633 temp = scnprintf (next, size, "fmremaining 0x%08x %sFR=0x%04x\n",
0634 rdata, (rdata >> 31) ? "FRT " : "",
0635 rdata & 0x3fff);
0636 size -= temp;
0637 next += temp;
0638
0639 rdata = ohci_readl (ohci, ®s->periodicstart);
0640 temp = scnprintf (next, size, "periodicstart 0x%04x\n",
0641 rdata & 0x3fff);
0642 size -= temp;
0643 next += temp;
0644
0645 rdata = ohci_readl (ohci, ®s->lsthresh);
0646 temp = scnprintf (next, size, "lsthresh 0x%04x\n",
0647 rdata & 0x3fff);
0648 size -= temp;
0649 next += temp;
0650
0651 temp = scnprintf (next, size, "hub poll timer %s\n",
0652 HCD_POLL_RH(ohci_to_hcd(ohci)) ? "ON" : "off");
0653 size -= temp;
0654 next += temp;
0655
0656
0657 ohci_dump_roothub (ohci, 1, &next, &size);
0658
0659 done:
0660 spin_unlock_irqrestore (&ohci->lock, flags);
0661
0662 return PAGE_SIZE - size;
0663 }
0664
0665 static struct debug_buffer *alloc_buffer(struct ohci_hcd *ohci,
0666 ssize_t (*fill_func)(struct debug_buffer *))
0667 {
0668 struct debug_buffer *buf;
0669
0670 buf = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL);
0671
0672 if (buf) {
0673 buf->ohci = ohci;
0674 buf->fill_func = fill_func;
0675 mutex_init(&buf->mutex);
0676 }
0677
0678 return buf;
0679 }
0680
0681 static int fill_buffer(struct debug_buffer *buf)
0682 {
0683 int ret;
0684
0685 if (!buf->page)
0686 buf->page = (char *)get_zeroed_page(GFP_KERNEL);
0687
0688 if (!buf->page) {
0689 ret = -ENOMEM;
0690 goto out;
0691 }
0692
0693 ret = buf->fill_func(buf);
0694
0695 if (ret >= 0) {
0696 buf->count = ret;
0697 ret = 0;
0698 }
0699
0700 out:
0701 return ret;
0702 }
0703
0704 static ssize_t debug_output(struct file *file, char __user *user_buf,
0705 size_t len, loff_t *offset)
0706 {
0707 struct debug_buffer *buf = file->private_data;
0708 int ret;
0709
0710 mutex_lock(&buf->mutex);
0711 if (buf->count == 0) {
0712 ret = fill_buffer(buf);
0713 if (ret != 0) {
0714 mutex_unlock(&buf->mutex);
0715 goto out;
0716 }
0717 }
0718 mutex_unlock(&buf->mutex);
0719
0720 ret = simple_read_from_buffer(user_buf, len, offset,
0721 buf->page, buf->count);
0722
0723 out:
0724 return ret;
0725
0726 }
0727
0728 static int debug_close(struct inode *inode, struct file *file)
0729 {
0730 struct debug_buffer *buf = file->private_data;
0731
0732 if (buf) {
0733 if (buf->page)
0734 free_page((unsigned long)buf->page);
0735 kfree(buf);
0736 }
0737
0738 return 0;
0739 }
0740 static int debug_async_open(struct inode *inode, struct file *file)
0741 {
0742 file->private_data = alloc_buffer(inode->i_private, fill_async_buffer);
0743
0744 return file->private_data ? 0 : -ENOMEM;
0745 }
0746
0747 static int debug_periodic_open(struct inode *inode, struct file *file)
0748 {
0749 file->private_data = alloc_buffer(inode->i_private,
0750 fill_periodic_buffer);
0751
0752 return file->private_data ? 0 : -ENOMEM;
0753 }
0754
0755 static int debug_registers_open(struct inode *inode, struct file *file)
0756 {
0757 file->private_data = alloc_buffer(inode->i_private,
0758 fill_registers_buffer);
0759
0760 return file->private_data ? 0 : -ENOMEM;
0761 }
0762 static inline void create_debug_files (struct ohci_hcd *ohci)
0763 {
0764 struct usb_bus *bus = &ohci_to_hcd(ohci)->self;
0765 struct dentry *root;
0766
0767 root = debugfs_create_dir(bus->bus_name, ohci_debug_root);
0768 ohci->debug_dir = root;
0769
0770 debugfs_create_file("async", S_IRUGO, root, ohci, &debug_async_fops);
0771 debugfs_create_file("periodic", S_IRUGO, root, ohci,
0772 &debug_periodic_fops);
0773 debugfs_create_file("registers", S_IRUGO, root, ohci,
0774 &debug_registers_fops);
0775
0776 ohci_dbg (ohci, "created debug files\n");
0777 }
0778
0779 static inline void remove_debug_files (struct ohci_hcd *ohci)
0780 {
0781 debugfs_remove_recursive(ohci->debug_dir);
0782 }
0783
0784
0785