diff options
Diffstat (limited to 'drivers/usb/host/uhci-debug.c')
-rw-r--r-- | drivers/usb/host/uhci-debug.c | 178 |
1 files changed, 120 insertions, 58 deletions
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index fc0b0daac93d..455737546525 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c | |||
@@ -16,6 +16,8 @@ | |||
16 | 16 | ||
17 | #include "uhci-hcd.h" | 17 | #include "uhci-hcd.h" |
18 | 18 | ||
19 | #define EXTRA_SPACE 1024 | ||
20 | |||
19 | static struct dentry *uhci_debugfs_root; | 21 | static struct dentry *uhci_debugfs_root; |
20 | 22 | ||
21 | #ifdef DEBUG | 23 | #ifdef DEBUG |
@@ -44,10 +46,6 @@ static int uhci_show_td(struct uhci_hcd *uhci, struct uhci_td *td, char *buf, | |||
44 | char *spid; | 46 | char *spid; |
45 | u32 status, token; | 47 | u32 status, token; |
46 | 48 | ||
47 | /* Try to make sure there's enough memory */ | ||
48 | if (len < 160) | ||
49 | return 0; | ||
50 | |||
51 | status = td_status(uhci, td); | 49 | status = td_status(uhci, td); |
52 | out += sprintf(out, "%*s[%p] link (%08x) ", space, "", td, | 50 | out += sprintf(out, "%*s[%p] link (%08x) ", space, "", td, |
53 | hc32_to_cpu(uhci, td->link)); | 51 | hc32_to_cpu(uhci, td->link)); |
@@ -64,6 +62,8 @@ static int uhci_show_td(struct uhci_hcd *uhci, struct uhci_td *td, char *buf, | |||
64 | (status & TD_CTRL_CRCTIMEO) ? "CRC/Timeo " : "", | 62 | (status & TD_CTRL_CRCTIMEO) ? "CRC/Timeo " : "", |
65 | (status & TD_CTRL_BITSTUFF) ? "BitStuff " : "", | 63 | (status & TD_CTRL_BITSTUFF) ? "BitStuff " : "", |
66 | status & 0x7ff); | 64 | status & 0x7ff); |
65 | if (out - buf > len) | ||
66 | goto done; | ||
67 | 67 | ||
68 | token = td_token(uhci, td); | 68 | token = td_token(uhci, td); |
69 | switch (uhci_packetid(token)) { | 69 | switch (uhci_packetid(token)) { |
@@ -90,6 +90,9 @@ static int uhci_show_td(struct uhci_hcd *uhci, struct uhci_td *td, char *buf, | |||
90 | spid); | 90 | spid); |
91 | out += sprintf(out, "(buf=%08x)\n", hc32_to_cpu(uhci, td->buffer)); | 91 | out += sprintf(out, "(buf=%08x)\n", hc32_to_cpu(uhci, td->buffer)); |
92 | 92 | ||
93 | done: | ||
94 | if (out - buf > len) | ||
95 | out += sprintf(out, " ...\n"); | ||
93 | return out - buf; | 96 | return out - buf; |
94 | } | 97 | } |
95 | 98 | ||
@@ -101,8 +104,6 @@ static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, | |||
101 | int i, nactive, ninactive; | 104 | int i, nactive, ninactive; |
102 | char *ptype; | 105 | char *ptype; |
103 | 106 | ||
104 | if (len < 200) | ||
105 | return 0; | ||
106 | 107 | ||
107 | out += sprintf(out, "urb_priv [%p] ", urbp); | 108 | out += sprintf(out, "urb_priv [%p] ", urbp); |
108 | out += sprintf(out, "urb [%p] ", urbp->urb); | 109 | out += sprintf(out, "urb [%p] ", urbp->urb); |
@@ -110,6 +111,8 @@ static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, | |||
110 | out += sprintf(out, "Dev=%d ", usb_pipedevice(urbp->urb->pipe)); | 111 | out += sprintf(out, "Dev=%d ", usb_pipedevice(urbp->urb->pipe)); |
111 | out += sprintf(out, "EP=%x(%s) ", usb_pipeendpoint(urbp->urb->pipe), | 112 | out += sprintf(out, "EP=%x(%s) ", usb_pipeendpoint(urbp->urb->pipe), |
112 | (usb_pipein(urbp->urb->pipe) ? "IN" : "OUT")); | 113 | (usb_pipein(urbp->urb->pipe) ? "IN" : "OUT")); |
114 | if (out - buf > len) | ||
115 | goto done; | ||
113 | 116 | ||
114 | switch (usb_pipetype(urbp->urb->pipe)) { | 117 | switch (usb_pipetype(urbp->urb->pipe)) { |
115 | case PIPE_ISOCHRONOUS: ptype = "ISO"; break; | 118 | case PIPE_ISOCHRONOUS: ptype = "ISO"; break; |
@@ -128,6 +131,9 @@ static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, | |||
128 | out += sprintf(out, " Unlinked=%d", urbp->urb->unlinked); | 131 | out += sprintf(out, " Unlinked=%d", urbp->urb->unlinked); |
129 | out += sprintf(out, "\n"); | 132 | out += sprintf(out, "\n"); |
130 | 133 | ||
134 | if (out - buf > len) | ||
135 | goto done; | ||
136 | |||
131 | i = nactive = ninactive = 0; | 137 | i = nactive = ninactive = 0; |
132 | list_for_each_entry(td, &urbp->td_list, list) { | 138 | list_for_each_entry(td, &urbp->td_list, list) { |
133 | if (urbp->qh->type != USB_ENDPOINT_XFER_ISOC && | 139 | if (urbp->qh->type != USB_ENDPOINT_XFER_ISOC && |
@@ -135,6 +141,8 @@ static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, | |||
135 | out += sprintf(out, "%*s%d: ", space + 2, "", i); | 141 | out += sprintf(out, "%*s%d: ", space + 2, "", i); |
136 | out += uhci_show_td(uhci, td, out, | 142 | out += uhci_show_td(uhci, td, out, |
137 | len - (out - buf), 0); | 143 | len - (out - buf), 0); |
144 | if (out - buf > len) | ||
145 | goto tail; | ||
138 | } else { | 146 | } else { |
139 | if (td_status(uhci, td) & TD_CTRL_ACTIVE) | 147 | if (td_status(uhci, td) & TD_CTRL_ACTIVE) |
140 | ++nactive; | 148 | ++nactive; |
@@ -143,10 +151,13 @@ static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, | |||
143 | } | 151 | } |
144 | } | 152 | } |
145 | if (nactive + ninactive > 0) | 153 | if (nactive + ninactive > 0) |
146 | out += sprintf(out, "%*s[skipped %d inactive and %d active " | 154 | out += sprintf(out, |
147 | "TDs]\n", | 155 | "%*s[skipped %d inactive and %d active TDs]\n", |
148 | space, "", ninactive, nactive); | 156 | space, "", ninactive, nactive); |
149 | 157 | done: | |
158 | if (out - buf > len) | ||
159 | out += sprintf(out, " ...\n"); | ||
160 | tail: | ||
150 | return out - buf; | 161 | return out - buf; |
151 | } | 162 | } |
152 | 163 | ||
@@ -158,10 +169,6 @@ static int uhci_show_qh(struct uhci_hcd *uhci, | |||
158 | __hc32 element = qh_element(qh); | 169 | __hc32 element = qh_element(qh); |
159 | char *qtype; | 170 | char *qtype; |
160 | 171 | ||
161 | /* Try to make sure there's enough memory */ | ||
162 | if (len < 80 * 7) | ||
163 | return 0; | ||
164 | |||
165 | switch (qh->type) { | 172 | switch (qh->type) { |
166 | case USB_ENDPOINT_XFER_ISOC: qtype = "ISO"; break; | 173 | case USB_ENDPOINT_XFER_ISOC: qtype = "ISO"; break; |
167 | case USB_ENDPOINT_XFER_INT: qtype = "INT"; break; | 174 | case USB_ENDPOINT_XFER_INT: qtype = "INT"; break; |
@@ -175,13 +182,15 @@ static int uhci_show_qh(struct uhci_hcd *uhci, | |||
175 | hc32_to_cpu(uhci, qh->link), | 182 | hc32_to_cpu(uhci, qh->link), |
176 | hc32_to_cpu(uhci, element)); | 183 | hc32_to_cpu(uhci, element)); |
177 | if (qh->type == USB_ENDPOINT_XFER_ISOC) | 184 | if (qh->type == USB_ENDPOINT_XFER_ISOC) |
178 | out += sprintf(out, "%*s period %d phase %d load %d us, " | 185 | out += sprintf(out, |
179 | "frame %x desc [%p]\n", | 186 | "%*s period %d phase %d load %d us, frame %x desc [%p]\n", |
180 | space, "", qh->period, qh->phase, qh->load, | 187 | space, "", qh->period, qh->phase, qh->load, |
181 | qh->iso_frame, qh->iso_packet_desc); | 188 | qh->iso_frame, qh->iso_packet_desc); |
182 | else if (qh->type == USB_ENDPOINT_XFER_INT) | 189 | else if (qh->type == USB_ENDPOINT_XFER_INT) |
183 | out += sprintf(out, "%*s period %d phase %d load %d us\n", | 190 | out += sprintf(out, "%*s period %d phase %d load %d us\n", |
184 | space, "", qh->period, qh->phase, qh->load); | 191 | space, "", qh->period, qh->phase, qh->load); |
192 | if (out - buf > len) | ||
193 | goto done; | ||
185 | 194 | ||
186 | if (element & UHCI_PTR_QH(uhci)) | 195 | if (element & UHCI_PTR_QH(uhci)) |
187 | out += sprintf(out, "%*s Element points to QH (bug?)\n", space, ""); | 196 | out += sprintf(out, "%*s Element points to QH (bug?)\n", space, ""); |
@@ -195,11 +204,17 @@ static int uhci_show_qh(struct uhci_hcd *uhci, | |||
195 | if (!(element & ~(UHCI_PTR_QH(uhci) | UHCI_PTR_DEPTH(uhci)))) | 204 | if (!(element & ~(UHCI_PTR_QH(uhci) | UHCI_PTR_DEPTH(uhci)))) |
196 | out += sprintf(out, "%*s Element is NULL (bug?)\n", space, ""); | 205 | out += sprintf(out, "%*s Element is NULL (bug?)\n", space, ""); |
197 | 206 | ||
207 | if (out - buf > len) | ||
208 | goto done; | ||
209 | |||
198 | if (list_empty(&qh->queue)) { | 210 | if (list_empty(&qh->queue)) { |
199 | out += sprintf(out, "%*s queue is empty\n", space, ""); | 211 | out += sprintf(out, "%*s queue is empty\n", space, ""); |
200 | if (qh == uhci->skel_async_qh) | 212 | if (qh == uhci->skel_async_qh) { |
201 | out += uhci_show_td(uhci, uhci->term_td, out, | 213 | out += uhci_show_td(uhci, uhci->term_td, out, |
202 | len - (out - buf), 0); | 214 | len - (out - buf), 0); |
215 | if (out - buf > len) | ||
216 | goto tail; | ||
217 | } | ||
203 | } else { | 218 | } else { |
204 | struct urb_priv *urbp = list_entry(qh->queue.next, | 219 | struct urb_priv *urbp = list_entry(qh->queue.next, |
205 | struct urb_priv, node); | 220 | struct urb_priv, node); |
@@ -211,9 +226,12 @@ static int uhci_show_qh(struct uhci_hcd *uhci, | |||
211 | space, ""); | 226 | space, ""); |
212 | i = nurbs = 0; | 227 | i = nurbs = 0; |
213 | list_for_each_entry(urbp, &qh->queue, node) { | 228 | list_for_each_entry(urbp, &qh->queue, node) { |
214 | if (++i <= 10) | 229 | if (++i <= 10) { |
215 | out += uhci_show_urbp(uhci, urbp, out, | 230 | out += uhci_show_urbp(uhci, urbp, out, |
216 | len - (out - buf), space + 2); | 231 | len - (out - buf), space + 2); |
232 | if (out - buf > len) | ||
233 | goto tail; | ||
234 | } | ||
217 | else | 235 | else |
218 | ++nurbs; | 236 | ++nurbs; |
219 | } | 237 | } |
@@ -222,24 +240,27 @@ static int uhci_show_qh(struct uhci_hcd *uhci, | |||
222 | space, "", nurbs); | 240 | space, "", nurbs); |
223 | } | 241 | } |
224 | 242 | ||
243 | if (out - buf > len) | ||
244 | goto done; | ||
245 | |||
225 | if (qh->dummy_td) { | 246 | if (qh->dummy_td) { |
226 | out += sprintf(out, "%*s Dummy TD\n", space, ""); | 247 | out += sprintf(out, "%*s Dummy TD\n", space, ""); |
227 | out += uhci_show_td(uhci, qh->dummy_td, out, | 248 | out += uhci_show_td(uhci, qh->dummy_td, out, |
228 | len - (out - buf), 0); | 249 | len - (out - buf), 0); |
250 | if (out - buf > len) | ||
251 | goto tail; | ||
229 | } | 252 | } |
230 | 253 | ||
254 | done: | ||
255 | if (out - buf > len) | ||
256 | out += sprintf(out, " ...\n"); | ||
257 | tail: | ||
231 | return out - buf; | 258 | return out - buf; |
232 | } | 259 | } |
233 | 260 | ||
234 | static int uhci_show_sc(int port, unsigned short status, char *buf, int len) | 261 | static int uhci_show_sc(int port, unsigned short status, char *buf) |
235 | { | 262 | { |
236 | char *out = buf; | 263 | return sprintf(buf, " stat%d = %04x %s%s%s%s%s%s%s%s%s%s\n", |
237 | |||
238 | /* Try to make sure there's enough memory */ | ||
239 | if (len < 160) | ||
240 | return 0; | ||
241 | |||
242 | out += sprintf(out, " stat%d = %04x %s%s%s%s%s%s%s%s%s%s\n", | ||
243 | port, | 264 | port, |
244 | status, | 265 | status, |
245 | (status & USBPORTSC_SUSP) ? " Suspend" : "", | 266 | (status & USBPORTSC_SUSP) ? " Suspend" : "", |
@@ -252,19 +273,12 @@ static int uhci_show_sc(int port, unsigned short status, char *buf, int len) | |||
252 | (status & USBPORTSC_PE) ? " Enabled" : "", | 273 | (status & USBPORTSC_PE) ? " Enabled" : "", |
253 | (status & USBPORTSC_CSC) ? " ConnectChange" : "", | 274 | (status & USBPORTSC_CSC) ? " ConnectChange" : "", |
254 | (status & USBPORTSC_CCS) ? " Connected" : ""); | 275 | (status & USBPORTSC_CCS) ? " Connected" : ""); |
255 | |||
256 | return out - buf; | ||
257 | } | 276 | } |
258 | 277 | ||
259 | static int uhci_show_root_hub_state(struct uhci_hcd *uhci, char *buf, int len) | 278 | static int uhci_show_root_hub_state(struct uhci_hcd *uhci, char *buf) |
260 | { | 279 | { |
261 | char *out = buf; | ||
262 | char *rh_state; | 280 | char *rh_state; |
263 | 281 | ||
264 | /* Try to make sure there's enough memory */ | ||
265 | if (len < 60) | ||
266 | return 0; | ||
267 | |||
268 | switch (uhci->rh_state) { | 282 | switch (uhci->rh_state) { |
269 | case UHCI_RH_RESET: | 283 | case UHCI_RH_RESET: |
270 | rh_state = "reset"; break; | 284 | rh_state = "reset"; break; |
@@ -283,9 +297,8 @@ static int uhci_show_root_hub_state(struct uhci_hcd *uhci, char *buf, int len) | |||
283 | default: | 297 | default: |
284 | rh_state = "?"; break; | 298 | rh_state = "?"; break; |
285 | } | 299 | } |
286 | out += sprintf(out, "Root-hub state: %s FSBR: %d\n", | 300 | return sprintf(buf, "Root-hub state: %s FSBR: %d\n", |
287 | rh_state, uhci->fsbr_is_on); | 301 | rh_state, uhci->fsbr_is_on); |
288 | return out - buf; | ||
289 | } | 302 | } |
290 | 303 | ||
291 | static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len) | 304 | static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len) |
@@ -296,9 +309,6 @@ static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len) | |||
296 | unsigned char sof; | 309 | unsigned char sof; |
297 | unsigned short portsc1, portsc2; | 310 | unsigned short portsc1, portsc2; |
298 | 311 | ||
299 | /* Try to make sure there's enough memory */ | ||
300 | if (len < 80 * 9) | ||
301 | return 0; | ||
302 | 312 | ||
303 | usbcmd = uhci_readw(uhci, 0); | 313 | usbcmd = uhci_readw(uhci, 0); |
304 | usbstat = uhci_readw(uhci, 2); | 314 | usbstat = uhci_readw(uhci, 2); |
@@ -319,6 +329,8 @@ static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len) | |||
319 | (usbcmd & USBCMD_GRESET) ? "GRESET " : "", | 329 | (usbcmd & USBCMD_GRESET) ? "GRESET " : "", |
320 | (usbcmd & USBCMD_HCRESET) ? "HCRESET " : "", | 330 | (usbcmd & USBCMD_HCRESET) ? "HCRESET " : "", |
321 | (usbcmd & USBCMD_RS) ? "RS " : ""); | 331 | (usbcmd & USBCMD_RS) ? "RS " : ""); |
332 | if (out - buf > len) | ||
333 | goto done; | ||
322 | 334 | ||
323 | out += sprintf(out, " usbstat = %04x %s%s%s%s%s%s\n", | 335 | out += sprintf(out, " usbstat = %04x %s%s%s%s%s%s\n", |
324 | usbstat, | 336 | usbstat, |
@@ -328,19 +340,33 @@ static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len) | |||
328 | (usbstat & USBSTS_RD) ? "ResumeDetect " : "", | 340 | (usbstat & USBSTS_RD) ? "ResumeDetect " : "", |
329 | (usbstat & USBSTS_ERROR) ? "USBError " : "", | 341 | (usbstat & USBSTS_ERROR) ? "USBError " : "", |
330 | (usbstat & USBSTS_USBINT) ? "USBINT " : ""); | 342 | (usbstat & USBSTS_USBINT) ? "USBINT " : ""); |
343 | if (out - buf > len) | ||
344 | goto done; | ||
331 | 345 | ||
332 | out += sprintf(out, " usbint = %04x\n", usbint); | 346 | out += sprintf(out, " usbint = %04x\n", usbint); |
333 | out += sprintf(out, " usbfrnum = (%d)%03x\n", (usbfrnum >> 10) & 1, | 347 | out += sprintf(out, " usbfrnum = (%d)%03x\n", (usbfrnum >> 10) & 1, |
334 | 0xfff & (4*(unsigned int)usbfrnum)); | 348 | 0xfff & (4*(unsigned int)usbfrnum)); |
335 | out += sprintf(out, " flbaseadd = %08x\n", flbaseadd); | 349 | out += sprintf(out, " flbaseadd = %08x\n", flbaseadd); |
336 | out += sprintf(out, " sof = %02x\n", sof); | 350 | out += sprintf(out, " sof = %02x\n", sof); |
337 | out += uhci_show_sc(1, portsc1, out, len - (out - buf)); | 351 | if (out - buf > len) |
338 | out += uhci_show_sc(2, portsc2, out, len - (out - buf)); | 352 | goto done; |
339 | out += sprintf(out, "Most recent frame: %x (%d) " | 353 | |
340 | "Last ISO frame: %x (%d)\n", | 354 | out += uhci_show_sc(1, portsc1, out); |
355 | if (out - buf > len) | ||
356 | goto done; | ||
357 | |||
358 | out += uhci_show_sc(2, portsc2, out); | ||
359 | if (out - buf > len) | ||
360 | goto done; | ||
361 | |||
362 | out += sprintf(out, | ||
363 | "Most recent frame: %x (%d) Last ISO frame: %x (%d)\n", | ||
341 | uhci->frame_number, uhci->frame_number & 1023, | 364 | uhci->frame_number, uhci->frame_number & 1023, |
342 | uhci->last_iso_frame, uhci->last_iso_frame & 1023); | 365 | uhci->last_iso_frame, uhci->last_iso_frame & 1023); |
343 | 366 | ||
367 | done: | ||
368 | if (out - buf > len) | ||
369 | out += sprintf(out, " ...\n"); | ||
344 | return out - buf; | 370 | return out - buf; |
345 | } | 371 | } |
346 | 372 | ||
@@ -360,9 +386,13 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) | |||
360 | "int8", "int4", "int2", "async", "term" | 386 | "int8", "int4", "int2", "async", "term" |
361 | }; | 387 | }; |
362 | 388 | ||
363 | out += uhci_show_root_hub_state(uhci, out, len - (out - buf)); | 389 | out += uhci_show_root_hub_state(uhci, out); |
390 | if (out - buf > len) | ||
391 | goto done; | ||
364 | out += sprintf(out, "HC status\n"); | 392 | out += sprintf(out, "HC status\n"); |
365 | out += uhci_show_status(uhci, out, len - (out - buf)); | 393 | out += uhci_show_status(uhci, out, len - (out - buf)); |
394 | if (out - buf > len) | ||
395 | goto tail; | ||
366 | 396 | ||
367 | out += sprintf(out, "Periodic load table\n"); | 397 | out += sprintf(out, "Periodic load table\n"); |
368 | for (i = 0; i < MAX_PHASE; ++i) { | 398 | for (i = 0; i < MAX_PHASE; ++i) { |
@@ -375,7 +405,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) | |||
375 | uhci_to_hcd(uhci)->self.bandwidth_int_reqs, | 405 | uhci_to_hcd(uhci)->self.bandwidth_int_reqs, |
376 | uhci_to_hcd(uhci)->self.bandwidth_isoc_reqs); | 406 | uhci_to_hcd(uhci)->self.bandwidth_isoc_reqs); |
377 | if (debug <= 1) | 407 | if (debug <= 1) |
378 | return out - buf; | 408 | goto tail; |
379 | 409 | ||
380 | out += sprintf(out, "Frame List\n"); | 410 | out += sprintf(out, "Frame List\n"); |
381 | nframes = 10; | 411 | nframes = 10; |
@@ -383,6 +413,8 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) | |||
383 | for (i = 0; i < UHCI_NUMFRAMES; ++i) { | 413 | for (i = 0; i < UHCI_NUMFRAMES; ++i) { |
384 | __hc32 qh_dma; | 414 | __hc32 qh_dma; |
385 | 415 | ||
416 | if (out - buf > len) | ||
417 | goto done; | ||
386 | j = 0; | 418 | j = 0; |
387 | td = uhci->frame_cpu[i]; | 419 | td = uhci->frame_cpu[i]; |
388 | link = uhci->frame[i]; | 420 | link = uhci->frame[i]; |
@@ -401,15 +433,20 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) | |||
401 | td = list_entry(tmp, struct uhci_td, fl_list); | 433 | td = list_entry(tmp, struct uhci_td, fl_list); |
402 | tmp = tmp->next; | 434 | tmp = tmp->next; |
403 | if (link != LINK_TO_TD(uhci, td)) { | 435 | if (link != LINK_TO_TD(uhci, td)) { |
404 | if (nframes > 0) | 436 | if (nframes > 0) { |
405 | out += sprintf(out, " link does " | 437 | out += sprintf(out, |
406 | "not match list entry!\n"); | 438 | " link does not match list entry!\n"); |
407 | else | 439 | if (out - buf > len) |
440 | goto done; | ||
441 | } else | ||
408 | ++nerrs; | 442 | ++nerrs; |
409 | } | 443 | } |
410 | if (nframes > 0) | 444 | if (nframes > 0) { |
411 | out += uhci_show_td(uhci, td, out, | 445 | out += uhci_show_td(uhci, td, out, |
412 | len - (out - buf), 4); | 446 | len - (out - buf), 4); |
447 | if (out - buf > len) | ||
448 | goto tail; | ||
449 | } | ||
413 | link = td->link; | 450 | link = td->link; |
414 | } while (tmp != head); | 451 | } while (tmp != head); |
415 | 452 | ||
@@ -423,9 +460,11 @@ check_link: | |||
423 | i, hc32_to_cpu(uhci, link)); | 460 | i, hc32_to_cpu(uhci, link)); |
424 | j = 1; | 461 | j = 1; |
425 | } | 462 | } |
426 | out += sprintf(out, " link does not match " | 463 | out += sprintf(out, |
427 | "QH (%08x)!\n", | 464 | " link does not match QH (%08x)!\n", |
428 | hc32_to_cpu(uhci, qh_dma)); | 465 | hc32_to_cpu(uhci, qh_dma)); |
466 | if (out - buf > len) | ||
467 | goto done; | ||
429 | } else | 468 | } else |
430 | ++nerrs; | 469 | ++nerrs; |
431 | } | 470 | } |
@@ -436,18 +475,27 @@ check_link: | |||
436 | 475 | ||
437 | out += sprintf(out, "Skeleton QHs\n"); | 476 | out += sprintf(out, "Skeleton QHs\n"); |
438 | 477 | ||
478 | if (out - buf > len) | ||
479 | goto done; | ||
480 | |||
439 | fsbr_link = 0; | 481 | fsbr_link = 0; |
440 | for (i = 0; i < UHCI_NUM_SKELQH; ++i) { | 482 | for (i = 0; i < UHCI_NUM_SKELQH; ++i) { |
441 | int cnt = 0; | 483 | int cnt = 0; |
442 | 484 | ||
443 | qh = uhci->skelqh[i]; | 485 | qh = uhci->skelqh[i]; |
444 | out += sprintf(out, "- skel_%s_qh\n", qh_names[i]); \ | 486 | out += sprintf(out, "- skel_%s_qh\n", qh_names[i]); |
445 | out += uhci_show_qh(uhci, qh, out, len - (out - buf), 4); | 487 | out += uhci_show_qh(uhci, qh, out, len - (out - buf), 4); |
488 | if (out - buf > len) | ||
489 | goto tail; | ||
446 | 490 | ||
447 | /* Last QH is the Terminating QH, it's different */ | 491 | /* Last QH is the Terminating QH, it's different */ |
448 | if (i == SKEL_TERM) { | 492 | if (i == SKEL_TERM) { |
449 | if (qh_element(qh) != LINK_TO_TD(uhci, uhci->term_td)) | 493 | if (qh_element(qh) != LINK_TO_TD(uhci, uhci->term_td)) { |
450 | out += sprintf(out, " skel_term_qh element is not set to term_td!\n"); | 494 | out += sprintf(out, |
495 | " skel_term_qh element is not set to term_td!\n"); | ||
496 | if (out - buf > len) | ||
497 | goto done; | ||
498 | } | ||
451 | link = fsbr_link; | 499 | link = fsbr_link; |
452 | if (!link) | 500 | if (!link) |
453 | link = LINK_TO_QH(uhci, uhci->skel_term_qh); | 501 | link = LINK_TO_QH(uhci, uhci->skel_term_qh); |
@@ -460,9 +508,12 @@ check_link: | |||
460 | while (tmp != head) { | 508 | while (tmp != head) { |
461 | qh = list_entry(tmp, struct uhci_qh, node); | 509 | qh = list_entry(tmp, struct uhci_qh, node); |
462 | tmp = tmp->next; | 510 | tmp = tmp->next; |
463 | if (++cnt <= 10) | 511 | if (++cnt <= 10) { |
464 | out += uhci_show_qh(uhci, qh, out, | 512 | out += uhci_show_qh(uhci, qh, out, |
465 | len - (out - buf), 4); | 513 | len - (out - buf), 4); |
514 | if (out - buf > len) | ||
515 | goto tail; | ||
516 | } | ||
466 | if (!fsbr_link && qh->skel >= SKEL_FSBR) | 517 | if (!fsbr_link && qh->skel >= SKEL_FSBR) |
467 | fsbr_link = LINK_TO_QH(uhci, qh); | 518 | fsbr_link = LINK_TO_QH(uhci, qh); |
468 | } | 519 | } |
@@ -480,9 +531,17 @@ check_link: | |||
480 | link = LINK_TO_QH(uhci, uhci->skel_term_qh); | 531 | link = LINK_TO_QH(uhci, uhci->skel_term_qh); |
481 | check_qh_link: | 532 | check_qh_link: |
482 | if (qh->link != link) | 533 | if (qh->link != link) |
483 | out += sprintf(out, " last QH not linked to next skeleton!\n"); | 534 | out += sprintf(out, |
535 | " last QH not linked to next skeleton!\n"); | ||
536 | |||
537 | if (out - buf > len) | ||
538 | goto done; | ||
484 | } | 539 | } |
485 | 540 | ||
541 | done: | ||
542 | if (out - buf > len) | ||
543 | out += sprintf(out, " ...\n"); | ||
544 | tail: | ||
486 | return out - buf; | 545 | return out - buf; |
487 | } | 546 | } |
488 | 547 | ||
@@ -514,7 +573,8 @@ static int uhci_debug_open(struct inode *inode, struct file *file) | |||
514 | up->size = 0; | 573 | up->size = 0; |
515 | spin_lock_irqsave(&uhci->lock, flags); | 574 | spin_lock_irqsave(&uhci->lock, flags); |
516 | if (uhci->is_initialized) | 575 | if (uhci->is_initialized) |
517 | up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT); | 576 | up->size = uhci_sprint_schedule(uhci, up->data, |
577 | MAX_OUTPUT - EXTRA_SPACE); | ||
518 | spin_unlock_irqrestore(&uhci->lock, flags); | 578 | spin_unlock_irqrestore(&uhci->lock, flags); |
519 | 579 | ||
520 | file->private_data = up; | 580 | file->private_data = up; |
@@ -529,7 +589,9 @@ static loff_t uhci_debug_lseek(struct file *file, loff_t off, int whence) | |||
529 | 589 | ||
530 | up = file->private_data; | 590 | up = file->private_data; |
531 | 591 | ||
532 | /* XXX: atomic 64bit seek access, but that needs to be fixed in the VFS */ | 592 | /* |
593 | * XXX: atomic 64bit seek access, but that needs to be fixed in the VFS | ||
594 | */ | ||
533 | switch (whence) { | 595 | switch (whence) { |
534 | case 0: | 596 | case 0: |
535 | new = off; | 597 | new = off; |