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)



The following reply was made to PR kern/48237; it has been noted by GNATS.

From: Wolfgang Stukenbrock <wolfgang.stukenbrock%nagler-company.com@localhost>
To: Nick Hudson <skrll%netbsd.org@localhost>
Cc: gnats-bugs%netbsd.org@localhost, kern-bug-people%netbsd.org@localhost, 
gnats-admin%netbsd.org@localhost,
        netbsd-bugs%netbsd.org@localhost
Subject: Re: kern/48237: NetBSD 6.1 failed to detect USB 1.x full-speed device 
(umodem)
Date: Wed, 25 Sep 2013 14:53:08 +0200

 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