On Wed, Jun 01, 2005 at 08:20:07AM -0700, David Brownell wrote: > On Tuesday 31 May 2005 5:12 pm, Adam Kropelin wrote: > > ... > > > > Problem > > After some period of time (minutes to hours), the BackUPS CS 650 and > > BackUPS BR 800 models cease to respond to control transfers. Based on > > HID debug I can see that a control transfer is sent by apcupsd but a > > response never comes back. hid-core.c complains "timeout waiting for > > ctrl or out queue to clear". After that, no further control transfers go > > thru, instead the timeout error repeats. Interrupt transfers continue to > > be processed every 6 seconds as expected. (See dmesg log snippet below). > > Eventually, the timeout error is joined by a "control queue full" error > > as well. > > The HID core has its own control queueing scheme. That was needed > back on 2.4 kernels where the HCDs couldn't be relied on to handle > such queueing, but someone should rip that out for 2.6 kernels. > For synchronous calls the HCD queue can be used directly; and for > async ones, urb->urb_list.
Poking thru hid-core.c I did see a number of things that look buggy in the queuing logic. For example, this bit in the control pipe completion handler... switch (urb->status) { case 0: /* success */ if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN) hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, regs); case -ESHUTDOWN: /* unplug */ case -EILSEQ: /* unplug timectrl on uhci */ unplug = 1; case -ECONNRESET: /* unlink */ case -ENOENT: case -EPIPE: /* report not available */ break; default: /* error */ warn("ctrl urb status %d received", urb->status); } if (unplug) hid->ctrltail = hid->ctrlhead; else hid->ctrltail = (hid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1); if (hid->ctrlhead != hid->ctrltail) { if (hid_submit_ctrl(hid)) { ... ...which appears to reset the queue on successful transfers rather than continuing on with subsequent URBs. Alas, fixing that doesn't eliminate the lockups Martin and Christian are experiencing, which makes sense because apcupsd should never have more than one outstanding control transfer anyway. > For UPS devices, with relatively huge numbers of reports, this > queue mechanism causes HID devices to allocate huge amounts of > runtime space ... pages per device, not bytes, just so that the > hid_init_reports() routine won't block hid_probe() for several > seconds while a low speed UPS initializes everything. I had a good laugh when I fired up *BSD and let their primitive uhid driver bind to the UPS. It created 75 device nodes, one for each report. UPSes tend to stretch the limits of most generic HID layers, it seems. > But you're using "hiddev", and it looked to me as if for some > quirky devices hid_submit_report() needs to return a "no, I could > not ask for that report" error ... which it isn't. That looks > unlikely in your case (no quirks obviously listed for APC). The problem seems to be random in terms of which report transfer is in progress when the lockup strikes. APC definitely has some firmware bugs where reports return fewer bytes than the report descriptor claims they will, and that problem gave me fits on *BSD, but that doesn't seem to be the issue here. > It just looks fishy to see what's fundamentally a synchronous > control request get morhped into an async one to use the HID > layer's queueing logic, rather than staying synchronous and > using the HCD's more-completely-tested queueing logic ... and > then it gets errors from that HID queueing, indicative of that > queue not getting properly cleaned out after faults. I've been considering dumping hiddev entirely and writing a driver based on libusb or possibly libhid, if it's mature enough. That puts HID parsing in userspace (where it ought to be, darn it) and gets the whole kernel HID layer out of the picture. This would be one more argument in favor of that approach. --Adam ------------------------------------------------------- This SF.Net email is sponsored by Yahoo. Introducing Yahoo! Search Developer Network - Create apps using Yahoo! Search APIs Find out how you can build Yahoo! directly into your own Applications - visit http://developer.yahoo.net/?fr=offad-ysdn-ostg-q22005 _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel