On Fri, Oct 03, 2014 at 07:58:11PM +0200, Mark Kettenis wrote:
> > Date: Thu, 2 Oct 2014 12:20:14 +0200
> > From: Martin Pieuchot <[email protected]>
> > 
> > Our USB stack contains a hack needed for ehci(4) and ohci(4) that
> > breaks xhci(4).   The diff below moves this hack in these drivers,
> > and makes it possible to have a working xhci(4) in GENERIC.
> > 
> > I'd like this diff to be tested on as much machines as possible, because
> > the code path it touches is very sensible.  This also matters if you are
> > using uhci(4)!
> > 
> > Please test and report back.
> 
> Works fine for me on my old i386 Mac mini with usb keyboard and mouse
> and two usb disks.  Diff makes sense to me as well.

Works ok for me on x230.

> 
> ok kettenis@
> 
> > Index: ehci.c
> > ===================================================================
> > RCS file: /cvs/src/sys/dev/usb/ehci.c,v
> > retrieving revision 1.168
> > diff -u -p -r1.168 ehci.c
> > --- ehci.c  1 Sep 2014 08:13:02 -0000       1.168
> > +++ ehci.c  2 Oct 2014 09:30:28 -0000
> > @@ -99,6 +99,7 @@ struct ehci_pipe {
> >  u_int8_t           ehci_reverse_bits(u_int8_t, int);
> >  
> >  usbd_status        ehci_open(struct usbd_pipe *);
> > +int                ehci_setaddr(struct usbd_device *, int);
> >  void               ehci_poll(struct usbd_bus *);
> >  void               ehci_softintr(void *);
> >  int                ehci_intr1(struct ehci_softc *);
> > @@ -215,7 +216,7 @@ void            ehci_dump_exfer(struct ehci_xfer *
> >  
> >  struct usbd_bus_methods ehci_bus_methods = {
> >     .open_pipe = ehci_open,
> > -   .dev_setaddr = usbd_set_address,
> > +   .dev_setaddr = ehci_setaddr,
> >     .soft_intr = ehci_softintr,
> >     .do_poll = ehci_poll,
> >     .allocx = ehci_allocx,
> > @@ -603,6 +604,40 @@ ehci_pcd(struct ehci_softc *sc, struct u
> >     xfer->status = USBD_NORMAL_COMPLETION;
> >  
> >     usb_transfer_complete(xfer);
> > +}
> > +
> > +/*
> > + * Work around the half configured control (default) pipe when setting
> > + * the address of a device.
> > + *
> > + * Because a single QH is setup per endpoint in ehci_open(), and the
> > + * control pipe is configured before we could have set the address
> > + * of the device or read the wMaxPacketSize of the endpoint, we have
> > + * to re-open the pipe twice here.
> > + */
> > +int
> > +ehci_setaddr(struct usbd_device *dev, int addr)
> > +{
> > +   /* Root Hub */
> > +   if (dev->depth == 0)
> > +           return (0);
> > +
> > +   /* Re-establish the default pipe with the new max packet size. */
> > +   ehci_close_pipe(dev->default_pipe);
> > +   if (ehci_open(dev->default_pipe))
> > +           return (EINVAL);
> > +
> > +   if (usbd_set_address(dev, addr))
> > +           return (1);
> > +
> > +   dev->address = addr;
> > +
> > +   /* Re-establish the default pipe with the new address. */
> > +   ehci_close_pipe(dev->default_pipe);
> > +   if (ehci_open(dev->default_pipe))
> > +           return (EINVAL);
> > +
> > +   return (0);
> >  }
> >  
> >  void
> > Index: ohci.c
> > ===================================================================
> > RCS file: /cvs/src/sys/dev/usb/ohci.c,v
> > retrieving revision 1.139
> > diff -u -p -r1.139 ohci.c
> > --- ohci.c  10 Aug 2014 11:18:57 -0000      1.139
> > +++ ohci.c  2 Oct 2014 09:33:03 -0000
> > @@ -88,6 +88,7 @@ usbd_status       ohci_alloc_std_chain(struct 
> >                 struct ohci_soft_td **);
> >  
> >  usbd_status        ohci_open(struct usbd_pipe *);
> > +int                ohci_setaddr(struct usbd_device *, int);
> >  void               ohci_poll(struct usbd_bus *);
> >  void               ohci_softintr(void *);
> >  void               ohci_waitintr(struct ohci_softc *, struct usbd_xfer *);
> > @@ -232,7 +233,7 @@ struct ohci_pipe {
> >  
> >  struct usbd_bus_methods ohci_bus_methods = {
> >     .open_pipe = ohci_open,
> > -   .dev_setaddr = usbd_set_address,
> > +   .dev_setaddr = ohci_setaddr,
> >     .soft_intr = ohci_softintr,
> >     .do_poll = ohci_poll,
> >     .allocx = ohci_allocx,
> > @@ -2003,6 +2004,40 @@ ohci_open(struct usbd_pipe *pipe)
> >   bad0:
> >     return (USBD_NOMEM);
> >  
> > +}
> > +
> > +/*
> > + * Work around the half configured control (default) pipe when setting
> > + * the address of a device.
> > + *
> > + * Because a single ED is setup per endpoint in ohci_open(), and the
> > + * control pipe is configured before we could have set the address
> > + * of the device or read the wMaxPacketSize of the endpoint, we have
> > + * to re-open the pipe twice here.
> > + */
> > +int
> > +ohci_setaddr(struct usbd_device *dev, int addr)
> > +{
> > +   /* Root Hub */
> > +   if (dev->depth == 0)
> > +           return (0);
> > +
> > +   /* Re-establish the default pipe with the new max packet size. */
> > +   ohci_device_ctrl_close(dev->default_pipe);
> > +   if (ohci_open(dev->default_pipe))
> > +           return (EINVAL);
> > +
> > +   if (usbd_set_address(dev, addr))
> > +           return (1);
> > +
> > +   dev->address = addr;
> > +
> > +   /* Re-establish the default pipe with the new address. */
> > +   ohci_device_ctrl_close(dev->default_pipe);
> > +   if (ohci_open(dev->default_pipe))
> > +           return (EINVAL);
> > +
> > +   return (0);
> >  }
> >  
> >  /*
> > Index: usb_subr.c
> > ===================================================================
> > RCS file: /cvs/src/sys/dev/usb/usb_subr.c,v
> > retrieving revision 1.109
> > diff -u -p -r1.109 usb_subr.c
> > --- usb_subr.c      1 Oct 2014 08:29:01 -0000       1.109
> > +++ usb_subr.c      2 Oct 2014 09:24:18 -0000
> > @@ -901,8 +901,8 @@ usbd_probe_and_attach(struct device *par
> >                              "error=%s\n", parent->dv_xname, port,
> >                              addr, usbd_errstr(err)));
> >  #else
> > -                   printf("%s: port %d, set config at addr %d failed\n",
> > -                       parent->dv_xname, port, addr);
> > +                   printf("%s: port %d, set config %d at addr %d failed\n",
> > +                       parent->dv_xname, port, confi, addr);
> >  #endif
> >  
> >                     goto fail;
> > @@ -1160,23 +1160,6 @@ usbd_new_device(struct device *parent, s
> >  
> >     USETW(dev->def_ep_desc.wMaxPacketSize, dd->bMaxPacketSize);
> >  
> > -   /* Re-establish the default pipe with the new max packet size. */
> > -   usbd_close_pipe(dev->default_pipe);
> > -   err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL,
> > -       &dev->default_pipe);
> > -   if (err) {
> > -           usb_free_device(dev);
> > -           up->device = NULL;
> > -           return (err);
> > -   }
> > -
> > -   err = usbd_reload_device_desc(dev);
> > -   if (err) {
> > -           usb_free_device(dev);
> > -           up->device = NULL;
> > -           return (err);
> > -   }
> > -
> >     /* Set the address if the HC didn't do it already. */
> >     if (bus->methods->dev_setaddr != NULL &&
> >         bus->methods->dev_setaddr(dev, addr)) {
> > @@ -1192,10 +1175,7 @@ usbd_new_device(struct device *parent, s
> >     dev->address = addr;
> >     bus->devices[addr] = dev;
> >  
> > -   /* Re-establish the default pipe with the new address. */
> > -   usbd_close_pipe(dev->default_pipe);
> > -   err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL,
> > -       &dev->default_pipe);
> > +   err = usbd_reload_device_desc(dev);
> >     if (err) {
> >             usb_free_device(dev);
> >             up->device = NULL;
> > 
> > 
> 

Reply via email to