NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: kern/48237: NetBSD 6.1 failed to detect USB 1.x full-speed device (umodem)



Hi again,

I've added the patch and the USB modems comes up again.

Thanks for the patch.
It should go into the the 6.x tree as soon as possible ....



Neverless, during reboot I've still "some" incomplete USB-transactions.
I'm not 100% shure what excatly is gooing on, but it must be related to the forced shutdown of my "getty-Version" on the com-line by init. The process tries to open /dev/ttyU0 and waits for carrier when it is killed by a signal.
This will also happen if I kill the process by hand.

remark:
I've a patch for umodem/ucom in the kernel to catch RI (and reset it after some time) in order to raise DCD to allow ucom-driver to finish the pending open(). This patch is present in all of my kernels because without it umodem (and my hardware) cannot be used for dialin/dialout lines. On real serial lines, I can patch the cable, but this impossible for USB-modems that does not support raising DCD on incoming calls. I'm not shure if I ever reported this (in 2.0.2 or later), because after some discution at that time, it looks like it would never come into any release. I cannot find it in the Gnats-DB at the moment and also not in my mail archive.
If you think I should start an other try for this topic, let me know.



The not terminating transfer seems to be a bulk-transfer this time after one other communication step. Here my debug-printout during system shutdown, just before syncing the disks.


uhci_idone: ii=0xc1f51a40
uhci_idone: ii=0xc1f51a40, xfer=0xc1f519c4, pipe=0xc1725a9c ready
 ---- loop start ....
 ---- status 0x18000007 act-len 0 token 0xe0022d
 ---- status 0x190007ff act-len 0 token 0xffe80269
 ---- adding len -> act-len 0
uhci_idone: actlen=0, status=0x0
uhci_idone: ii=0xc1f51b20
uhci_idone: ii=0xc1f51b20, xfer=0xc1f51aa4, pipe=0xc172586c ready
 ---- loop start ....
 ---- status 0x18000007 act-len 0 token 0xe0032d
 ---- status 0x190007ff act-len 0 token 0xffe80369
 ---- adding len -> act-len 0
uhci_idone: actlen=0, status=0x0
uhci_idone: ii=0xc1f51f80
uhci_idone: ii=0xc1f51f80, xfer=0xc1f51f04, pipe=0xc172516c ready
 ---- loop start ....
 ---- status 0x38000005 act-len 0 token 0x7e30269
 ---- adding len -> act-len 6
 ---- ACTIVE TD found ....
uhci_idone: actlen=6, status=0x0
uhci_idone: ii=0xc1f51ea0
uhci_idone: ii=0xc1f51ea0, xfer=0xc1f51e24, pipe=0xc172524c ready
 ---- loop start ....
 ---- status 0x38000005 act-len 0 token 0x7e30369
 ---- adding len -> act-len 6
 ---- ACTIVE TD found ....
uhci_idone: actlen=6, status=0x0
uhci_device_bulk_abort:
uhci_device_bulk_abort:
uhci_check_intr: aborted xfer=0xc1f51e24
uhci_check_intr: aborted xfer=0xc1f51f04
uhci_check_intr: aborted xfer=0xc1f51e24


remark: there are two modems active on the systems, one pending bulk transfer for each ...


I haven't tested "real" data till now. Next step on my side is to integrate the patch in our NetBSD-installation-base and reinstall the system to get all manualy added debug-stuff eliminated.

best regards

W. Stukenbrock


Nick Hudson wrote:

On 09/25/13 10:01, Wolfgang Stukenbrock wrote:

Hi,

hi,

My base version is the 1.212 for uhci.c from the release tree.


Did you mean 1.242 which is the netbsd-6 version?

http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/dev/usb/uhci.c?only_with_tag=netbsd-6

Here's a diff against this version of uhci.c which will fix your problem, I think.

Nick


------------------------------------------------------------------------

Index: sys/dev/usb/uhci.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/uhci.c,v
retrieving revision 1.242
diff -u -p -r1.242 uhci.c
--- sys/dev/usb/uhci.c  23 Dec 2011 00:51:46 -0000      1.242
+++ sys/dev/usb/uhci.c  25 Sep 2013 09:09:56 -0000
@@ -1102,6 +1102,7 @@ void
 uhci_remove_hs_ctrl(uhci_softc_t *sc, uhci_soft_qh_t *sqh)
 {
        uhci_soft_qh_t *pqh;
+       uint32_t elink;
SPLUSBCHECK; @@ -1125,7 +1126,10 @@ uhci_remove_hs_ctrl(uhci_softc_t *sc, uh
        usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_elink),
            sizeof(sqh->qh.qh_elink),
            BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
-       if (!(sqh->qh.qh_elink & htole32(UHCI_PTR_T))) {
+       elink = le32toh(sqh->qh.qh_elink);
+       usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_elink),
+           sizeof(sqh->qh.qh_elink), BUS_DMASYNC_PREREAD);
+       if (!(elink & UHCI_PTR_T)) {
                sqh->qh.qh_elink = htole32(UHCI_PTR_T);
                usb_syncmem(&sqh->dma,
                    sqh->offs + offsetof(uhci_qh_t, qh_elink),
@@ -1175,6 +1179,7 @@ void
 uhci_remove_ls_ctrl(uhci_softc_t *sc, uhci_soft_qh_t *sqh)
 {
        uhci_soft_qh_t *pqh;
+       uint32_t elink;
SPLUSBCHECK; @@ -1183,7 +1188,10 @@ uhci_remove_ls_ctrl(uhci_softc_t *sc, uh
        usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_elink),
            sizeof(sqh->qh.qh_elink),
            BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
-       if (!(sqh->qh.qh_elink & htole32(UHCI_PTR_T))) {
+       elink = le32toh(sqh->qh.qh_elink);
+       usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_elink),
+           sizeof(sqh->qh.qh_elink), BUS_DMASYNC_PREREAD);
+       if (!(elink & UHCI_PTR_T)) {
                sqh->qh.qh_elink = htole32(UHCI_PTR_T);
                usb_syncmem(&sqh->dma,
                    sqh->offs + offsetof(uhci_qh_t, qh_elink),
@@ -1421,54 +1429,89 @@ uhci_check_intr(uhci_softc_t *sc, uhci_i
                return;
        }
 #endif
+       usb_syncmem(&lstd->dma,
+           lstd->offs + offsetof(uhci_td_t, td_status),
+           sizeof(lstd->td.td_status),
+           BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
+       status = le32toh(lstd->td.td_status);
+       usb_syncmem(&lstd->dma,
+           lstd->offs + offsetof(uhci_td_t, td_status),
+           sizeof(lstd->td.td_status),
+           BUS_DMASYNC_PREREAD);
+
+       /* If the last TD is not marked active we can complete */
+       if (!(status & UHCI_TD_ACTIVE)) {
+ done:
+               DPRINTFN(12, ("uhci_check_intr: ii=%p done\n", ii));
+               callout_stop(&ii->xfer->timeout_handle);
+               uhci_idone(ii);
+               return;
+       }
+
        /*
         * If the last TD is still active we need to check whether there
         * is an error somewhere in the middle, or whether there was a
         * short packet (SPD and not ACTIVE).
         */
-       usb_syncmem(&lstd->dma,
-           lstd->offs + offsetof(uhci_td_t, td_status),
-           sizeof(lstd->td.td_status),
-           BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
-       if (le32toh(lstd->td.td_status) & UHCI_TD_ACTIVE) {
-               DPRINTFN(12, ("uhci_check_intr: active ii=%p\n", ii));
-               for (std = ii->stdstart; std != lstd; std = std->link.std) {
-                       usb_syncmem(&std->dma,
-                           std->offs + offsetof(uhci_td_t, td_status),
-                           sizeof(std->td.td_status),
-                           BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
-                       status = le32toh(std->td.td_status);
-                       usb_syncmem(&std->dma,
-                           std->offs + offsetof(uhci_td_t, td_status),
-                           sizeof(std->td.td_status), BUS_DMASYNC_PREREAD);
-                       /* If there's an active TD the xfer isn't done. */
-                       if (status & UHCI_TD_ACTIVE)
-                               break;
-                       /* Any kind of error makes the xfer done. */
-                       if (status & UHCI_TD_STALLED)
-                               goto done;
-                       /* We want short packets, and it is short: it's done */
-                       usb_syncmem(&std->dma,
-                           std->offs + offsetof(uhci_td_t, td_token),
-                           sizeof(std->td.td_token),
-                           BUS_DMASYNC_POSTWRITE);
-                       if ((status & UHCI_TD_SPD) &&
-                             UHCI_TD_GET_ACTLEN(status) <
-                             UHCI_TD_GET_MAXLEN(le32toh(std->td.td_token)))
-                               goto done;
-               }
-               DPRINTFN(12, ("uhci_check_intr: ii=%p std=%p still active\n",
-                             ii, ii->stdstart));
-               usb_syncmem(&lstd->dma,
-                   lstd->offs + offsetof(uhci_td_t, td_status),
-                   sizeof(lstd->td.td_status),
-                   BUS_DMASYNC_PREREAD);
-               return;
+       DPRINTFN(12, ("uhci_check_intr: active ii=%p\n", ii));
+       for (std = ii->stdstart; std != lstd; std = std->link.std) {
+               usb_syncmem(&std->dma,
+                   std->offs + offsetof(uhci_td_t, td_status),
+                   sizeof(std->td.td_status),
+                   BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
+               status = le32toh(std->td.td_status);
+               usb_syncmem(&std->dma,
+                   std->offs + offsetof(uhci_td_t, td_status),
+                   sizeof(std->td.td_status), BUS_DMASYNC_PREREAD);
+
+               /* If there's an active TD the xfer isn't done. */
+               if (status & UHCI_TD_ACTIVE) {
+                       DPRINTFN(12, ("%s: ii=%p std=%p still active\n",
+                           __func__, ii, std));
+                       return;
+               }
+
+               /* Any kind of error makes the xfer done. */
+               if (status & UHCI_TD_STALLED)
+                       goto done;
+
+               /*
+                * If the data phase of a control transfer is short, we need
+                * to complete the status stage
+                */
+               usbd_xfer_handle xfer = ii->xfer;
+               usb_endpoint_descriptor_t *ed = xfer->pipe->endpoint->edesc;
+               uint8_t xfertype = UE_GET_XFERTYPE(ed->bmAttributes);
+
+               if ((status & UHCI_TD_SPD) && xfertype == UE_CONTROL) {
+                       struct uhci_pipe *upipe =
+                           (struct uhci_pipe *)xfer->pipe;
+                       uhci_soft_qh_t *sqh = upipe->u.ctl.sqh;
+                       uhci_soft_td_t *stat = upipe->u.ctl.stat;
+
+                       DPRINTFN(12, ("%s: ii=%p std=%p control status"
+                           "phase needs completion\n", __func__, ii,
+                           ii->stdstart));
+
+                       sqh->qh.qh_elink =
+                           htole32(stat->physaddr | UHCI_PTR_TD);
+                       usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
+                           BUS_DMASYNC_PREWRITE);
+                       break;
+               }
+
+               /* We want short packets, and it is short: it's done */
+               usb_syncmem(&std->dma,
+                   std->offs + offsetof(uhci_td_t, td_token),
+                   sizeof(std->td.td_token),
+                   BUS_DMASYNC_POSTWRITE);
+
+               if ((status & UHCI_TD_SPD) &&
+                       UHCI_TD_GET_ACTLEN(status) <
+                       UHCI_TD_GET_MAXLEN(le32toh(std->td.td_token))) {
+                       goto done;
+               }
        }
- done:
-       DPRINTFN(12, ("uhci_check_intr: ii=%p done\n", ii));
-       callout_stop(&ii->xfer->timeout_handle);
-       uhci_idone(ii);
 }
/* Called at splusb() */
@@ -2420,7 +2463,7 @@ uhci_device_request(usbd_xfer_handle xfe
                        return (err);
                next = data;
                dataend->link.std = stat;
-               dataend->td.td_link = htole32(stat->physaddr | UHCI_PTR_VF | 
UHCI_PTR_TD);
+               dataend->td.td_link = htole32(stat->physaddr | UHCI_PTR_TD);
                usb_syncmem(&dataend->dma,
                    dataend->offs + offsetof(uhci_td_t, td_link),
                    sizeof(dataend->td.td_link),
@@ -2434,7 +2477,7 @@ uhci_device_request(usbd_xfer_handle xfe
        usb_syncmem(&upipe->u.ctl.reqdma, 0, sizeof *req, BUS_DMASYNC_PREWRITE);
setup->link.std = next;
-       setup->td.td_link = htole32(next->physaddr | UHCI_PTR_VF | UHCI_PTR_TD);
+       setup->td.td_link = htole32(next->physaddr | UHCI_PTR_TD);
        setup->td.td_status = htole32(UHCI_TD_SET_ERRCNT(3) | ls |
                UHCI_TD_ACTIVE);
        setup->td.td_token = htole32(UHCI_TD_SETUP(sizeof *req, endpt, addr));




--


Dr. Nagler & Company GmbH
Hauptstraße 9
92253 Schnaittenbach

Tel. +49 9622/71 97-42
Fax +49 9622/71 97-50

Wolfgang.Stukenbrock%nagler-company.com@localhost
http://www.nagler-company.com


Hauptsitz: Schnaittenbach
Handelregister: Amberg HRB
Gerichtsstand: Amberg
Steuernummer: 201/118/51825
USt.-ID-Nummer: DE 273143997
Geschäftsführer: Dr. Martin Nagler, Prof. Dr. Dr. Karl-Kuno Kunze




Home | Main Index | Thread Index | Old Index