^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * UHCI-specific debugging code. Invaluable when something
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * goes wrong, but don't get in my face.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Kernel visible pointers are surrounded in []s and bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * visible pointers are surrounded in ()s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * (C) Copyright 1999 Linus Torvalds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * (C) Copyright 1999-2001 Johannes Erdfelt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/debugfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "uhci-hcd.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define EXTRA_SPACE 1024
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) static struct dentry *uhci_debugfs_root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #ifdef CONFIG_DYNAMIC_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /* Handle REALLY large printks so we don't overflow buffers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static void lprintk(char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) char *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /* Just write one line at a time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) while (buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) p = strchr(buf, '\n');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) if (p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) *p = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) printk(KERN_DEBUG "%s\n", buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) buf = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) if (buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) buf++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static int uhci_show_td(struct uhci_hcd *uhci, struct uhci_td *td, char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) int len, int space)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) char *out = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) char *spid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) u32 status, token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) status = td_status(uhci, td);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) out += sprintf(out, "%*s[%p] link (%08x) ", space, "", td,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) hc32_to_cpu(uhci, td->link));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) out += sprintf(out, "e%d %s%s%s%s%s%s%s%s%s%sLength=%x ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) ((status >> 27) & 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) (status & TD_CTRL_SPD) ? "SPD " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) (status & TD_CTRL_LS) ? "LS " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) (status & TD_CTRL_IOC) ? "IOC " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) (status & TD_CTRL_ACTIVE) ? "Active " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) (status & TD_CTRL_STALLED) ? "Stalled " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) (status & TD_CTRL_DBUFERR) ? "DataBufErr " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) (status & TD_CTRL_BABBLE) ? "Babble " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) (status & TD_CTRL_NAK) ? "NAK " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) (status & TD_CTRL_CRCTIMEO) ? "CRC/Timeo " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) (status & TD_CTRL_BITSTUFF) ? "BitStuff " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) status & 0x7ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) token = td_token(uhci, td);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) switch (uhci_packetid(token)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) case USB_PID_SETUP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) spid = "SETUP";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) case USB_PID_OUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) spid = "OUT";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) case USB_PID_IN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) spid = "IN";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) spid = "?";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) out += sprintf(out, "MaxLen=%x DT%d EndPt=%x Dev=%x, PID=%x(%s) ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) token >> 21,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) ((token >> 19) & 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) (token >> 15) & 15,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) (token >> 8) & 127,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) (token & 0xff),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) spid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) out += sprintf(out, "(buf=%08x)\n", hc32_to_cpu(uhci, td->buffer));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) out += sprintf(out, " ...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return out - buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) char *buf, int len, int space)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) char *out = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct uhci_td *td;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) int i, nactive, ninactive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) char *ptype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) out += sprintf(out, "urb_priv [%p] ", urbp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) out += sprintf(out, "urb [%p] ", urbp->urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) out += sprintf(out, "qh [%p] ", urbp->qh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) out += sprintf(out, "Dev=%d ", usb_pipedevice(urbp->urb->pipe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) out += sprintf(out, "EP=%x(%s) ", usb_pipeendpoint(urbp->urb->pipe),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) (usb_pipein(urbp->urb->pipe) ? "IN" : "OUT"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) switch (usb_pipetype(urbp->urb->pipe)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) case PIPE_ISOCHRONOUS: ptype = "ISO"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) case PIPE_INTERRUPT: ptype = "INT"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) case PIPE_BULK: ptype = "BLK"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) case PIPE_CONTROL: ptype = "CTL"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) out += sprintf(out, "%s%s", ptype, (urbp->fsbr ? " FSBR" : ""));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) out += sprintf(out, " Actlen=%d%s", urbp->urb->actual_length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) (urbp->qh->type == USB_ENDPOINT_XFER_CONTROL ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) "-8" : ""));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (urbp->urb->unlinked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) out += sprintf(out, " Unlinked=%d", urbp->urb->unlinked);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) out += sprintf(out, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) i = nactive = ninactive = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) list_for_each_entry(td, &urbp->td_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (urbp->qh->type != USB_ENDPOINT_XFER_ISOC &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) (++i <= 10 || debug > 2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) out += sprintf(out, "%*s%d: ", space + 2, "", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) out += uhci_show_td(uhci, td, out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) len - (out - buf), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) goto tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (td_status(uhci, td) & TD_CTRL_ACTIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) ++nactive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) ++ninactive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (nactive + ninactive > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) out += sprintf(out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) "%*s[skipped %d inactive and %d active TDs]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) space, "", ninactive, nactive);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) out += sprintf(out, " ...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) tail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return out - buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) static int uhci_show_qh(struct uhci_hcd *uhci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) struct uhci_qh *qh, char *buf, int len, int space)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) char *out = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) int i, nurbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) __hc32 element = qh_element(qh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) char *qtype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) switch (qh->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) case USB_ENDPOINT_XFER_ISOC: qtype = "ISO"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) case USB_ENDPOINT_XFER_INT: qtype = "INT"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) case USB_ENDPOINT_XFER_BULK: qtype = "BLK"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) case USB_ENDPOINT_XFER_CONTROL: qtype = "CTL"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) default: qtype = "Skel" ; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) out += sprintf(out, "%*s[%p] %s QH link (%08x) element (%08x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) space, "", qh, qtype,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) hc32_to_cpu(uhci, qh->link),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) hc32_to_cpu(uhci, element));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (qh->type == USB_ENDPOINT_XFER_ISOC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) out += sprintf(out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) "%*s period %d phase %d load %d us, frame %x desc [%p]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) space, "", qh->period, qh->phase, qh->load,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) qh->iso_frame, qh->iso_packet_desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) else if (qh->type == USB_ENDPOINT_XFER_INT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) out += sprintf(out, "%*s period %d phase %d load %d us\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) space, "", qh->period, qh->phase, qh->load);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (element & UHCI_PTR_QH(uhci))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) out += sprintf(out, "%*s Element points to QH (bug?)\n", space, "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (element & UHCI_PTR_DEPTH(uhci))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) out += sprintf(out, "%*s Depth traverse\n", space, "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (element & cpu_to_hc32(uhci, 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) out += sprintf(out, "%*s Bit 3 set (bug?)\n", space, "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (!(element & ~(UHCI_PTR_QH(uhci) | UHCI_PTR_DEPTH(uhci))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) out += sprintf(out, "%*s Element is NULL (bug?)\n", space, "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (list_empty(&qh->queue)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) out += sprintf(out, "%*s queue is empty\n", space, "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (qh == uhci->skel_async_qh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) out += uhci_show_td(uhci, uhci->term_td, out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) len - (out - buf), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) goto tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) struct urb_priv *urbp = list_entry(qh->queue.next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) struct urb_priv, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct uhci_td *td = list_entry(urbp->td_list.next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) struct uhci_td, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (element != LINK_TO_TD(uhci, td))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) out += sprintf(out, "%*s Element != First TD\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) space, "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) i = nurbs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) list_for_each_entry(urbp, &qh->queue, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (++i <= 10) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) out += uhci_show_urbp(uhci, urbp, out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) len - (out - buf), space + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) goto tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) ++nurbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (nurbs > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) out += sprintf(out, "%*s Skipped %d URBs\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) space, "", nurbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (qh->dummy_td) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) out += sprintf(out, "%*s Dummy TD\n", space, "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) out += uhci_show_td(uhci, qh->dummy_td, out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) len - (out - buf), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) goto tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) out += sprintf(out, " ...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) tail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) return out - buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) static int uhci_show_sc(int port, unsigned short status, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return sprintf(buf, " stat%d = %04x %s%s%s%s%s%s%s%s%s%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) (status & USBPORTSC_SUSP) ? " Suspend" : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) (status & USBPORTSC_OCC) ? " OverCurrentChange" : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) (status & USBPORTSC_OC) ? " OverCurrent" : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) (status & USBPORTSC_PR) ? " Reset" : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) (status & USBPORTSC_LSDA) ? " LowSpeed" : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) (status & USBPORTSC_RD) ? " ResumeDetect" : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) (status & USBPORTSC_PEC) ? " EnableChange" : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) (status & USBPORTSC_PE) ? " Enabled" : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) (status & USBPORTSC_CSC) ? " ConnectChange" : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) (status & USBPORTSC_CCS) ? " Connected" : "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) static int uhci_show_root_hub_state(struct uhci_hcd *uhci, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) char *rh_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) switch (uhci->rh_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) case UHCI_RH_RESET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) rh_state = "reset"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) case UHCI_RH_SUSPENDED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) rh_state = "suspended"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) case UHCI_RH_AUTO_STOPPED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) rh_state = "auto-stopped"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) case UHCI_RH_RESUMING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) rh_state = "resuming"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) case UHCI_RH_SUSPENDING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) rh_state = "suspending"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) case UHCI_RH_RUNNING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) rh_state = "running"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) case UHCI_RH_RUNNING_NODEVS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) rh_state = "running, no devs"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) rh_state = "?"; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return sprintf(buf, "Root-hub state: %s FSBR: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) rh_state, uhci->fsbr_is_on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) char *out = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) unsigned short usbcmd, usbstat, usbint, usbfrnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) unsigned int flbaseadd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) unsigned char sof;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) unsigned short portsc1, portsc2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) usbcmd = uhci_readw(uhci, USBCMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) usbstat = uhci_readw(uhci, USBSTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) usbint = uhci_readw(uhci, USBINTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) usbfrnum = uhci_readw(uhci, USBFRNUM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) flbaseadd = uhci_readl(uhci, USBFLBASEADD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) sof = uhci_readb(uhci, USBSOF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) portsc1 = uhci_readw(uhci, USBPORTSC1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) portsc2 = uhci_readw(uhci, USBPORTSC2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) out += sprintf(out, " usbcmd = %04x %s%s%s%s%s%s%s%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) usbcmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) (usbcmd & USBCMD_MAXP) ? "Maxp64 " : "Maxp32 ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) (usbcmd & USBCMD_CF) ? "CF " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) (usbcmd & USBCMD_SWDBG) ? "SWDBG " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) (usbcmd & USBCMD_FGR) ? "FGR " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) (usbcmd & USBCMD_EGSM) ? "EGSM " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) (usbcmd & USBCMD_GRESET) ? "GRESET " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) (usbcmd & USBCMD_HCRESET) ? "HCRESET " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) (usbcmd & USBCMD_RS) ? "RS " : "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) out += sprintf(out, " usbstat = %04x %s%s%s%s%s%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) usbstat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) (usbstat & USBSTS_HCH) ? "HCHalted " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) (usbstat & USBSTS_HCPE) ? "HostControllerProcessError " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) (usbstat & USBSTS_HSE) ? "HostSystemError " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) (usbstat & USBSTS_RD) ? "ResumeDetect " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) (usbstat & USBSTS_ERROR) ? "USBError " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) (usbstat & USBSTS_USBINT) ? "USBINT " : "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) out += sprintf(out, " usbint = %04x\n", usbint);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) out += sprintf(out, " usbfrnum = (%d)%03x\n", (usbfrnum >> 10) & 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 0xfff & (4*(unsigned int)usbfrnum));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) out += sprintf(out, " flbaseadd = %08x\n", flbaseadd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) out += sprintf(out, " sof = %02x\n", sof);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) out += uhci_show_sc(1, portsc1, out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) out += uhci_show_sc(2, portsc2, out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) out += sprintf(out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) "Most recent frame: %x (%d) Last ISO frame: %x (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) uhci->frame_number, uhci->frame_number & 1023,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) uhci->last_iso_frame, uhci->last_iso_frame & 1023);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) out += sprintf(out, " ...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) return out - buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) char *out = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) struct uhci_qh *qh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) struct uhci_td *td;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) struct list_head *tmp, *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) int nframes, nerrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) __hc32 link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) __hc32 fsbr_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) static const char * const qh_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) "unlink", "iso", "int128", "int64", "int32", "int16",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) "int8", "int4", "int2", "async", "term"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) out += uhci_show_root_hub_state(uhci, out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) out += sprintf(out, "HC status\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) out += uhci_show_status(uhci, out, len - (out - buf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) goto tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) out += sprintf(out, "Periodic load table\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) for (i = 0; i < MAX_PHASE; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) out += sprintf(out, "\t%d", uhci->load[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (i % 8 == 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) *out++ = '\n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) out += sprintf(out, "Total: %d, #INT: %d, #ISO: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) uhci->total_load,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) uhci_to_hcd(uhci)->self.bandwidth_int_reqs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) uhci_to_hcd(uhci)->self.bandwidth_isoc_reqs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (debug <= 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) goto tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) out += sprintf(out, "Frame List\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) nframes = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) nerrs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) for (i = 0; i < UHCI_NUMFRAMES; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) __hc32 qh_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) j = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) td = uhci->frame_cpu[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) link = uhci->frame[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (!td)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) goto check_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if (nframes > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) out += sprintf(out, "- Frame %d -> (%08x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) i, hc32_to_cpu(uhci, link));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) j = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) head = &td->fl_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) tmp = head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) td = list_entry(tmp, struct uhci_td, fl_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) tmp = tmp->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (link != LINK_TO_TD(uhci, td)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (nframes > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) out += sprintf(out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) " link does not match list entry!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) ++nerrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) if (nframes > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) out += uhci_show_td(uhci, td, out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) len - (out - buf), 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) goto tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) link = td->link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) } while (tmp != head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) check_link:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) qh_dma = uhci_frame_skel_link(uhci, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (link != qh_dma) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (nframes > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (!j) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) out += sprintf(out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) "- Frame %d -> (%08x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) i, hc32_to_cpu(uhci, link));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) j = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) out += sprintf(out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) " link does not match QH (%08x)!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) hc32_to_cpu(uhci, qh_dma));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) ++nerrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) nframes -= j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if (nerrs > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) out += sprintf(out, "Skipped %d bad links\n", nerrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) out += sprintf(out, "Skeleton QHs\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) fsbr_link = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) for (i = 0; i < UHCI_NUM_SKELQH; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) int cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) qh = uhci->skelqh[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) out += sprintf(out, "- skel_%s_qh\n", qh_names[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) out += uhci_show_qh(uhci, qh, out, len - (out - buf), 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) goto tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) /* Last QH is the Terminating QH, it's different */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) if (i == SKEL_TERM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if (qh_element(qh) != LINK_TO_TD(uhci, uhci->term_td)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) out += sprintf(out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) " skel_term_qh element is not set to term_td!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) link = fsbr_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (!link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) link = LINK_TO_QH(uhci, uhci->skel_term_qh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) goto check_qh_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) head = &qh->node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) tmp = head->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) while (tmp != head) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) qh = list_entry(tmp, struct uhci_qh, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) tmp = tmp->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (++cnt <= 10) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) out += uhci_show_qh(uhci, qh, out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) len - (out - buf), 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) goto tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) if (!fsbr_link && qh->skel >= SKEL_FSBR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) fsbr_link = LINK_TO_QH(uhci, qh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if ((cnt -= 10) > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) out += sprintf(out, " Skipped %d QHs\n", cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) link = UHCI_PTR_TERM(uhci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if (i <= SKEL_ISO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) else if (i < SKEL_ASYNC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) link = LINK_TO_QH(uhci, uhci->skel_async_qh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) else if (!uhci->fsbr_is_on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) link = LINK_TO_QH(uhci, uhci->skel_term_qh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) check_qh_link:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (qh->link != link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) out += sprintf(out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) " last QH not linked to next skeleton!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (out - buf > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) out += sprintf(out, " ...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) tail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) return out - buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) #ifdef CONFIG_DEBUG_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) #define MAX_OUTPUT (64 * 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) struct uhci_debug {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) char *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) static int uhci_debug_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) struct uhci_hcd *uhci = inode->i_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) struct uhci_debug *up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) up = kmalloc(sizeof(*up), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (!up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) up->data = kmalloc(MAX_OUTPUT, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) if (!up->data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) kfree(up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) up->size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) spin_lock_irqsave(&uhci->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) if (uhci->is_initialized)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) up->size = uhci_sprint_schedule(uhci, up->data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) MAX_OUTPUT - EXTRA_SPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) spin_unlock_irqrestore(&uhci->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) file->private_data = up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) static loff_t uhci_debug_lseek(struct file *file, loff_t off, int whence)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) struct uhci_debug *up = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) return no_seek_end_llseek_size(file, off, whence, up->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) static ssize_t uhci_debug_read(struct file *file, char __user *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) size_t nbytes, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) struct uhci_debug *up = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) return simple_read_from_buffer(buf, nbytes, ppos, up->data, up->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) static int uhci_debug_release(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) struct uhci_debug *up = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) kfree(up->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) kfree(up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) static const struct file_operations uhci_debug_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) .open = uhci_debug_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) .llseek = uhci_debug_lseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) .read = uhci_debug_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) .release = uhci_debug_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) #define UHCI_DEBUG_OPS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) #endif /* CONFIG_DEBUG_FS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) #else /* CONFIG_DYNAMIC_DEBUG*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) static inline void lprintk(char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) static inline int uhci_show_qh(struct uhci_hcd *uhci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) struct uhci_qh *qh, char *buf, int len, int space)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) static inline int uhci_sprint_schedule(struct uhci_hcd *uhci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) char *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) #endif