On 21/06/15(Sun) 19:54, Martin Pieuchot wrote:
> On 21/06/15(Sun) 12:25, Adam Wolk wrote:
> > Hi misc@,
> > 
> > I'm running -current amd64 snapshot from 19th Jun, this laptop
> > went through 9 snapshots so far.
> > 
> > During all upgrades the built-in camera in the laptop was
> > always detected and displayed as configured. I had no need
> > to use it so didn't test if it actually works.
> > [...] 
> > Running video(1) results in the following line appearing in dmesg:
> > uvideo0: could not open VS pipe: INVAL
> > 
> > This was consistent behaviour for the past 2 snapshots and I believe
> > that it always behaved this way but I didn't test older ones. I doubt
> > this is a regression of any kind.
> 
> It is not a regression.  The problem is that your camera is attached
> to an xHCI controller and the xhci(4) driver still lack support for
> Isochronous transfer.  
> 
> > The interesting bit happened yesterday. I wanted to leave the laptop
> > on overnight but didn't want it to drain power so enabled apmd, set apm
> > -C and hit zzz.
> > 
> > Before going off I decided to test if it's possible to even wake up
> > from that state. So hit space, the laptop started waking up and I
> > noticed the webcam led blinking once shortly. Decided to test video(1)
> > again and behold, a webcam window appeared with my half asleep face on
> > it.
> > 
> > Does anyone have an idea what might be different when waking up from
> > zzz compared to the regular initialization that the system does during
> > boot?
> 
> If you carefully look at your dmesg you'll see that:
> 
> - uvideo0 at uhub0 port 6 configuration 1 interface 0 "J58E8R30X Lenovo 
> EasyCamera" rev 2.00/0.06 addr 4
> + uvideo0 at uhub2 port 6 configuration 1 interface 0 "J58E8R30X Lenovo 
> EasyCamera" rev 2.00/0.06 addr 4
> 
> Here uhub2 is the rate match hub below your ehci(4) whereas uhub0 is the
> root hub of xhci(4).  In other words after resuming your machine your
> camera appears to be on a different bus...
> 
> Alternatively you can run usbdevs(8) before and after suspending an see
> the difference.  Now I don't know why/how this happens.

After looking at Linux' sources it seems that some BIOSes that do not
support xHCI route your USB ports back to an EHCI controller during
suspend/resume.

Could you test the diff below and let me know if your uvideo(4) stays on
the same bus after resuming?

Index: xhci_pci.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/xhci_pci.c,v
retrieving revision 1.5
diff -u -p -r1.5 xhci_pci.c
--- xhci_pci.c  30 Oct 2014 18:25:08 -0000      1.5
+++ xhci_pci.c  21 Jun 2015 18:10:57 -0000
@@ -61,17 +61,19 @@ struct xhci_pci_softc {
        struct xhci_softc       sc;
        pci_chipset_tag_t       sc_pc;
        pcitag_t                sc_tag;
+       pcireg_t                sc_id;
        void                    *sc_ih;         /* interrupt vectoring */
 };
 
 int    xhci_pci_match(struct device *, void *, void *);
 void   xhci_pci_attach(struct device *, struct device *, void *);
 int    xhci_pci_detach(struct device *, int);
+int    xhci_pci_activate(struct device *, int);
 void   xhci_pci_takecontroller(struct xhci_pci_softc *, int);
 
 struct cfattach xhci_pci_ca = {
        sizeof(struct xhci_pci_softc), xhci_pci_match, xhci_pci_attach,
-       xhci_pci_detach, xhci_activate
+       xhci_pci_detach, xhci_pci_activate
 };
 
 int
@@ -92,10 +94,10 @@ xhci_pci_port_route(struct xhci_pci_soft
 {
        pcireg_t val;
 
-       /* 
+       /*
         * Check USB3 Port Routing Mask register that indicates the ports
         * can be changed from OS, and turn on by USB3 Port SS Enable register.
-        */ 
+        */
        val = pci_conf_read(psc->sc_pc, psc->sc_tag, PCI_XHCI_INTEL_USB3PRM);
        DPRINTF(("%s: USB3PRM / USB3.0 configurable ports: 0x%08x\n",
            psc->sc.sc_bus.bdev.dv_xname, val));
@@ -106,7 +108,7 @@ xhci_pci_port_route(struct xhci_pci_soft
            psc->sc.sc_bus.bdev.dv_xname, val));
 
        /*
-        * Check USB2 Port Routing Mask register that indicates the USB2.0 
+        * Check USB2 Port Routing Mask register that indicates the USB2.0
         * ports to be controlled by xHCI HC, and switch them to xHCI HC.
         */
        val = pci_conf_read(psc->sc_pc, psc->sc_tag, PCI_XHCI_INTEL_XUSB2PRM);
@@ -142,6 +144,7 @@ xhci_pci_attach(struct device *parent, s
 
        psc->sc_pc = pa->pa_pc;
        psc->sc_tag = pa->pa_tag;
+       psc->sc_id = pa->pa_id;
        psc->sc.sc_bus.dmatag = pa->pa_dmat;
 
        /* Handle quirks */
@@ -189,16 +192,8 @@ xhci_pci_attach(struct device *parent, s
                goto disestablish_ret;
        }
 
-       switch (PCI_VENDOR(pa->pa_id)) {
-       case PCI_VENDOR_INTEL:
-               switch (PCI_PRODUCT(pa->pa_id)) {
-               case PCI_PRODUCT_INTEL_8SERIES_XHCI:
-               case PCI_PRODUCT_INTEL_8SERIES_LP_XHCI:
-               case PCI_PRODUCT_INTEL_7SERIES_XHCI:
-                       xhci_pci_port_route(psc);
-                       break;
-               }
-       }
+       if (PCI_VENDOR(psc->sc_id) == PCI_VENDOR_INTEL)
+               xhci_pci_port_route(psc);
 
        /* Attach usb device. */
        config_found(self, &psc->sc.sc_bus, usbctlprint);
@@ -233,6 +228,24 @@ xhci_pci_detach(struct device *self, int
        }
        return (0);
 }
+
+int
+xhci_pci_activate(struct device *self, int act)
+{
+       struct xhci_pci_softc *psc = (struct xhci_pci_softc *)self;
+
+       switch (act) {
+       case DVACT_RESUME:
+               if (PCI_VENDOR(psc->sc_id) == PCI_VENDOR_INTEL)
+                       xhci_pci_port_route(psc);
+               break;
+       default:
+               break;
+       }
+
+       return (xhci_activate(self, act));
+}
+
 
 void
 xhci_pci_takecontroller(struct xhci_pci_softc *psc, int silent)

Reply via email to