On Thu, 24 Oct 2013, Dan Williams wrote:
> >> Details:
> >> 1/ Port power policy needs 'connector' awareness.
> >>
> >> It is a recipe for unintended device disconnects to turn off a
> >> port while leaving its peer active.
> >
> > "It is a recipe" -- what is "it"? Do you mean that under the current
> > implementation, an unintended device disconnect turns off a port while
> > leaving the port's peer turned on? Or do you mean that this series of
> > patches creates a mechanism for doing this?
>
> The current implementation is unaware of cases where it is turning off
> a USB3 port that has a related USB2 port. These patches create
> mechanisms to turn off both ports in concert.
Why is that necessary?
Consider an external hub. The USB-3 spec says that the hub is allowed
to remove power from a port only if both the SuperSpeed and USB-2
port-power features are set to 0. Assuming xhci-hcd is made to do the
same for root-hub ports, what's wrong with the kernel treating related
ports independently?
> > What is a port's "peer"?
>
> See patch 2 [1]. For example ACPI enumerates when a USB2 port is
> peered (colocated in the same physical plug) with a USB3 for the XHCI
> controller.
Sarah has mentioned that some systems may do weird things like hook the
USB-3 wires in a port directly to a controller while routing the USB-2
wires through an integrated hub (a "tier mismatch"). Can the ACPI data
represent this sort of thing?
Even more relevant: How is the power for such ports controlled? By the
controller or by the integrated hub?
> > Note that most USB-3 devices are not allowed to connect to the both
> > USB-3 and USB-2 buses at the same time. Hubs are exceptions; they are
> > required to do so (and consequently each USB-3 hub appears to the
> > system as two separate and unrelated hubs; one that is USB-3 and one
> > that is USB-2).
>
> I special case hubs in the code as devices that are allowed to be
> connected to both ports in a connector simultaneously. There will be
> no peer power management in that case. Are there other devices that
> are expected to dual connect?
According to the USB-3 spec, it is not allowed.
> >> A 'connector' is
> >> distinct from 'companion' ports which share the same data lines
> >> across multiple hcds.
> >
> > Why treat "companion" ports differently?
> >
>
> Companion-ports share 1 physical connection among controllers,
> 'connectors' co-locate multiple physical connections in one plug.
Yes, I realize that. It doesn't answer the question, though. In both
cases we have two usb_port structures representing a single physical
plug. This suggests they should be treated the same way.
> >> The existing implementation makes attempts to mitigate the damage of
> >> khubd running in the middle of a port power control event, but
> >> makes no guarantees.
> >
> > Sure it does. What damage are you talking about?
>
> Unless I missed it I did not see what prevents the port from being
> powered down mid khubd run?
It looks like hub_port_connect_change() needs to do a
pm_runtime_get_sync on the port... That's an easy fix, though.
> We have the busy_bits check but what does
> that synchronize against?
It prevents khubd from trying to manage a port when another thread is
doing something to it (a reset, for example).
> We also used to have this usb_port_runtime_resume:
>
> static int usb_port_runtime_resume(struct device *dev)
> {...
> usb_autopm_get_interface(intf);
> ...}
What do you mean, "used to"? That code is there right now!
> Which arranges for hub_activate() to run on a known powered down port.
I'm not sure what you mean by "on a ... port". hub_activate doesn't
run on any ports; it affects the entire hub.
> We would subsequently notice the connection gone and disconnect the
> device. I could reliably reproduce this after just a few power
> toggles... fixed now.
Fixed what? Calling usb_disconnect when the connection is gone is the
right thing to do.
> Now the policy is explicit that khubd only touches ports that have a
> power policy set to 'on', or are otherwise runtime active. No more
> pm_suspend_ignore_children() for the hub device. This makes hub.c a
> bit less complicated and the stats seem to agree:
>
> drivers/usb/core/hub.c | 252
> +++++++++++++-----------------------------------
> drivers/usb/core/hub.h | 29 +++---
> 2 files changed, 85 insertions(+), 196 deletions(-)
Okay, so you are changing what it means for a port to be in runtime
suspend. In the current code, it means the port is powered down. If I
understand all this, your intention is to leave a port in runtime
suspend essentially whenever the attached device is suspended (or there
is no attached device). Then you have to decide whether or not to
power-down the port while suspending it.
> >> We need to support both suspending hubs with
> >> live ports (to receive wakeup events) and fully powering down the
> >> port when userspace policy allows.
> >
> > Don't we support this already?
> >
>
> The code tries to, yes. The usb_port_runtime_resume() issue above is
> one bug I hit.
What's the bug?
> When patch 6 [2] moved the port into its more natural place in the
> device model hierarchy the code needed to support two 'suspended'
> states for the port. Suspended with power on (to support remote
> wakeup), and suspended with power off. Patch 5 [3] gives more detail.
I couldn't understand the tables in the patch 5 description. There are
columns labelled "power", "state", and "count", but they don't say
whether this means power before or after the event in the left column,
or what is being counted.
> Quick summary is:
> portX/power/pm_qos_no_power_off: regardless of connect_type never power down
Okay. We do this already.
> portX/connect_type: when 'hotplug', prevent port power off (unless
> peer port is connected to a non-hub device, then power down until the
> peer port disconnects),
All right, this policy explains why you need to keep track of related
ports. This should have been mentioned at the very start of your 00/15
description -- it appears to be the main reason for doing all this
work.
> when 'hardwired' honor pm_qos_no_power_off and
> child device runtime state. Hmm, also should block power-down when
> the child is configured for remote-wakeup, will add.
This is what we do now, right?
> portX/power/pm_qos_no_notify_flags: when set don't try to keep
> connector peer power policies synchronized. See patch 4 [4]
I didn't understand the description of that patch either, but it seems
to contain some confusion about the power provided to a port and its
peer. The power is either on to both or off to both, because there is
only one Vbus pin in the physical plug.
> portX/<child-usb-device>/power/control: when set to auto the port
> runtime state is implicitly controlled by the child driver
What does this mean? Are you saying that if
portX/<child-usb-device>/power/control is set to "on" then the port's
runtime state _isn't_ implicitly controlled by the child driver?
Alan Stern
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html