Re: USB hub clear POWER feature -> device still in 'lsusb' ?!

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

 



Hi Greg,

On Wed, May 24, 2017 at 09:19:14AM +0200, Greg KH wrote:
> > * In absence of any sysfs control or other API exposed to userland, I'm
> >   using uhubctl (https://github.com/mvp/uhubctl) to directly clear the
> >   POWER feature on said downstream USB port of the hub.
> > 
> > * The Linux kernel USB stack (tested up to 4.11) does notice this state
> >   change (I can see it doing GET_STATUS as a follow-up), but the USB
> >   device still stays in the USB tree, i.e. it shows up in lsusb despite
> >   being powered off.  This also means that all associated devices like
> >   cdc_acm, cdc_ether etc. still remain seen by applications, despite the
> >   device being gone
> 
> Can you provide the kernel logs for when you do this?  

The kernel log (dmesg) is empty, there is no notification at all about
this.

I looked at it with wireshark + usbmon, and I could see that the kernel
hub driver is doing a GET_STATUS and that seems to return the POWERED
feature to be off, but still indicate the CONNECT and ENABLE feature.
Unfortuantely I don't have the pcap file with me, will have to re-create
the test first.

> The hub should recognise that the device is gone, and disconnect
> everything.  Are you sure the hub is handling this correctly?

I am not sure the hub is handling things correctly.  Its an SMSC
USB2517, full data sheet available at
http://ww1.microchip.com/downloads/en/DeviceDoc/2517.pdf

I've successfully used the USB2517 and its smaller brother USB2514 in a
number of embedded devices I designed for internal connection between
typically some kidn of ARM/Linux USB host and a variety of chips /
modules.  It also seems to be used by a large number of DELL monitors
and other devices.

I guess the issue is that the hub keeps the "connect" feature despite the
"power" feature beinng gone and the the device actually being physically
powered off.

This may be an issue with the hub IC, as USB 2.0 spec 11.24.2.7.1.1
clearly states "This bit is reset to zero when the port is in the
Powered-off state or the Disconnected states".  It doesn't say though
whose responsibility it is to reset it to the zero state ;)

I suspect it might also have to do with the fact that the mPCIe WWAN
modems (we use a large variety of brands and models here) might keep
their pull-up on the D+/D- line active and thus trick the hub into
believing there actually still is something connected here.

Before anyone comes up with the smart suggestion: Why don't you simply
issue the PERST of the mPCIE slot: Because there are many modem models
on this planet which ignore that line, or which simply treat it as a
software GPIO input and thus do not achieve the purpose of actually
power-cycling the modem and thus resetting all state.  I've learned to
distrust any kind of reset line and put high-side power switches or LDOs
with software-controlled enable pin in front of virtually every logical
unit on any of my designs.

> > * Only when the device is turned on again via SET_FEATURE POWER, the
> >   USB device logical structure is remove from the kernel USB stack, and
> >   it subsequently re-enumerates.
> 
> That's "odd" :)

Yes.

> > I know that bypassin the kernel USB hub driver is probably not the
> > cleanest approach, but in absence of any API/sysfs to do so (forgive me
> > if I simply didn't find it), we have to resort to issuing CONTROL
> > requests to the USB hub directly.
> > 
> > As a work-around, I have found that issuing something like
> > 	"echo 1 > /sys/bus/usb/devices/1-4.1/remove"
> > will clear the ENABLE feature on the port and at the same time the
> > kernel code will call usb_remove_device() and hence it disappears from
> > lsusb as well as any associated device nodes re removed.
> > 
> > Hoewver, in this case I have not found any designated way to re-attach
> > the device.  Given that we're talking about embedded devices in
> > industrial applications installed at remote locations, and about a mPCIe
> > physical form factor, re-plugging the device simply won't be an option.
> > 
> > I'm wondering that after decades of a production-grade Linux USB stack,
> > why is there no standard method to re-enable such a port.  Once again,
> > if I'm missing it, please let me know.
> 
> That's because there is no way to reliably do this on USB hubs, there is
> no required support for this in the spec, so people did not implement it
> in their hubs.

What are you referring-to specifically?  We have two distinct issues
here:

a) the fact that you can "remove" the device (disable the "enable"
   feature), but there is no similar interface for re-enabling the
   "enable" feature (which appears to be done implicitly by setting the
   "reset" feature).  I think this should be safe and well within the
   USB spec, shouldn't it?

b) the fact that the device can be powered off and the kernel learning
   about this status change but still happily having the device in its
   data structures.  You can argue which condition keeps the "connect"
   feature, but is there a valid use case for a device without the
   "power" feature still being in the internal lists?  How can it be
   connected without power?  Even a self-powered device is not supposed
   to become active unless it sees VBus, right?

c) the statement that there is no required support for USB power
   switching in hubs?  I have two points about this:

   1) USB 2.0 in 11.11 states clearly "Bus-powered hubs are required to
      have power switches".  Whether that's the case in reality is a
      different question, but at least according to spec it is required.
      Yes, it could be ganged power switching, sure.

   2) Even if there are many devices out there that won't support a
      given feature: There are definitely (also consumer grade) hubs out
      there, that do have per-port power switching.  Should we deprive
      even users of those devices from using a standardized and
      well-specified method to power off and on their devices?

> > But this weird combination between sysfs on the one hand side and
> > directly issuing USB hub control requests via uhubctl on the other side
> > really looks ugly.  Is this really how one is supposed to power-cycle a
> > USB device?  It doesn't seam like such a completely odd requirement,
> > does it?
> 
> It's not an odd requirement, just one that is not implemented at all in
> the standard, nor in most hardware.  Your hub _should_ be reporting that
> the port is now gone, but it doesn't sound like it is, which is probably
> the issue here.  If you try a different hub, does that work properly?

Given that the hub chip is soldered to my circuit board and the
footprint only permits for that given chip, this may be a bit hard ;)

But I can do some mock-up with a different hub and try.

> We can't know if a hub handles this "feature" by probing it, so we can't
> expose it in the kernel through sysfs or anywhere else, as it would be
> just as effective as the userspace tool you are using (i.e. sometimes it
> works, sometimes it doesn't.)  That is why it's a userspace tool.

This addresses only part 'c' above.  Please also note that the
suspend/resume code of hub.c will happily use SET_FEATURE POWER, also
without knowing if it has any effect either.  Isn't that a bit
inconsistent with your statement?

I guess even if we don't have 'c', 'a' and 'b' can still be adressed:

* add a mechanism by which the "enable" feature can be set after it has
  been removed e.g. by means of the "echo > remove".  Not related to
  power switching at all, merely a matter of having orthogonal
  interfaces: If you can remove it, you can add it again.  Non-removable
  USB is pretty frequent these days, think of hub chips built onto
  mainboards, or USB hub + card reader built into the display.  you
  cannot re-plug in one chip into the hub on the circuit board next to
  it.

* as the USB spec states that the "connect" feature should be cleared
  when "power" is cleared, and there apparently are hubs out there who
  think it's not their job to do so:  Should the hub.c kernel driver
  work around that by either clearing it by itself, or by doing a
  usb_remove_device() in that situation?

> sorry, USB sucks :)

Not that much more than a lot of other hardware.

-- 
- Harald Welte <laforge@xxxxxxxxxxxx>           http://laforge.gnumonks.org/
============================================================================
"Privacy in residential applications is a desirable marketing option."
                                                  (ETSI EN 300 175-7 Ch. A6)
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux