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: Nick Hudson <skrll%netbsd.org@localhost>
To: Wolfgang Stukenbrock <wolfgang.stukenbrock%nagler-company.com@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 10:15:22 +0100

 This is a multi-part message in MIME format.
 --------------030401000304070401080704
 Content-Type: text/plain; charset=ISO-8859-1; format=flowed
 Content-Transfer-Encoding: 7bit
 
 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
 
 --------------030401000304070401080704
 Content-Type: text/plain; charset=us-ascii;
  name="uhci.c.diff"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: attachment;
  filename="uhci.c.diff"
 
 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));
 
 
 --------------030401000304070401080704--
 


Home | Main Index | Thread Index | Old Index