Re: How usb port_dev suspend

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

 



Questions like these should always be CC'ed to the linux-usb mailing 
list.

On Wed, 10 Jan 2018 liuhongweichina@xxxxxxxxxxx wrote:

> Good Morning Mr. Stern
> 
> i am a learner of linux kernel of usb. nowadays, i am running linux on a zhaoxin xhci,�
> which is the same as via xhci but different in vendor id.
> this xhci have a high speed root hub and a super speed root, both of them have 5 ports.
> 
> 1.
> what i am confused is that. for example, i use pr_info to print the dev.power.usage_count of port_dev.
> when i plug a high speed udisk to hs port in the 1st time, usage_count is 1.
> when i plug out and plug in again, usage_count is a 2. i think the right value may be 1.
> when i plug out and plug in again, usage_count is a 3.......
> when i plug a ss udisk to ss port for the 1st time, before plug usage_count is 1.....
> when i plug in usage_count is 2. after another plug out and plug in usage_count is 3.�

This doesn't happen on my system.  The usage count is the same each 
time the device is plugged in.  (I'm using an EHCI host controller, not 
xHCI, but that shouldn't make any difference.)

> i find that in usb_disconnect():
> if (udev->parent) {
> port1 = udev->portnum;
> hub = usb_hub_to_struct_hub(udev->parent);
> port_dev = hub->ports[port1 - 1];
> 
> sysfs_remove_link(&udev->dev.kobj, "port");
> sysfs_remove_link(&port_dev->dev.kobj, "device");
> 
> /*
> �* As usb_port_runtime_resume() de-references udev, make
> �* sure no resumes occur during removal
> �* change test_and_set_bit to clear
> �*/
> if (!test_and_set_bit(port1, hub->child_usage_bits))
> pm_runtime_get_sync(&port_dev->dev);
> }
> this situation is that a usb device been detached, so should it be as follows?:
> if (!test_and_clear_bit(port1, hub->child_usage_bits))
> pm_runtime_put(&port_dev->dev);

Code like that is already present in usb_disconnect(), near the end of
the function.  You should search the entire source file for all places
where "child_usage_bits" is used.

> when i change the code as above, i find when i plug in a udisk, usage_count increase,�
> when i plug out the udisk, usage_count decrease.

Something else must be wrong, but I can't tell what.

> 2.
> there is another problems for my zhaoxin xhci.
> for each ss port, hub driver will find a hs port peer for it according to port->location.
> i print out the port->location of each ports, they are:
> ssport1->location=0x80000000,� � hsport1->location=0x80000000
> ssport2->location=0x80000003,� � hsport2->location=0x80000003
> 
> ssport3->location=0x80000003,� � hsport3->location=0x80000003
> 
> ssport4->location=0x80000001,� � hsport4->location=0x80000001
> 
> ssport5->location=0x80000002,� � hsport5->location=0x80000002
> 
> ssport2, ssport3, hsport2 and hsport3 have the same location.
> so in match_location(), hsport2 will be assigned to ssport2 and ssport3 for peer port.
> is the value of port_dev->location read from acpi table?

Yes, it is.  See usb_acpi_find_companion() in usb-acpi.c.

>  if so, this case is the zhaoxin xhci problem.
> i manually change ssport3->location and hsport3->location to 0x80000004(may be stupid but i have no choice :(
> after that, the peers will be assigned correctly.
> 
> 3.
> but when i watch usage_count value that i print out.
> i see when i 1st plug a hs udisk, usage_count change from 0 to 1.
> when i plug a ss udisk the 1st time, usage_count change from 1 to 2, should it be from 0 to 1?
> so in link_peers(), i find that:
> pm_runtime_get_sync(&hs_port->dev);
> 
> left->peer = right;
> right->peer = left;
> 
> /*
> �* The SuperSpeed reference is dropped when the HiSpeed port in
> �* this relationship suspends, i.e. when it is safe to allow a
> �* SuperSpeed connection to drop since there is no risk of a
> �* device degrading to its powered-off HiSpeed connection.
> �*
> �* Also, drop the HiSpeed ref taken above.
> �*/
> pm_runtime_get_sync(&ss_port->dev);
> pm_runtime_put(&hs_port->dev);
> i think this code means, ssport's usage_count will be decreased in hsport's runtime suspend function.
> so in usb_port_runtime_susspend(), i print some log, find it will return in:
> if (dev_pm_qos_flags(&port_dev->dev, PM_QOS_FLAG_NO_POWER_OFF)
> == PM_QOS_FLAGS_ALL)
> return -EAGAIN;
> and will not suspend ss port, as it returns a -EAGAIN will hs port suspend again? or not.
> so i delete return -EAGAIN and let the code goes continue.
> (may you tell me the use of PM_QOS_FLAGS_ALL? :)

dev_pm_qos_flags() tests whether the flag bits you ask it about are
set.  PM_QOS_FLAGS_ALL means that all the bits in the mask are set.  
In this case the only bit in the mask is PM_QOS_FLAG_NO_POWER_OFF, so
if that flag bit is set then the return value will be PM_QOS_FLAGS_ALL.

The user can set or clear that flag bit by writing to the
pm_qos_no_power_off file in the port device's power/ directory in /sys.  
However, this file will not be created unless the hub is capable of
power switching; see the pm_qos function calls in
usb_hub_create_port_device().

> i seams works, when boot i can see the usage_count of ss port is 0, and this ss port suspend.
> 
> 4.
> ss port can suspend, but in usb_port_runtime_suspend(), i see it will clear the port power bit of PORTSC register.
> and pls will go to disabled state, next time plug a device, xhci will do nothing.
> so should port_dev need autosuspend? i turn off auto suspend when in port_dev initialization.
> it works, at least util now.

You don't have to edit the source code to turn off autosuspend.  You
can turn it off by writing "on" to the control file in the port
device's power/ directory under /sys.

However, if the port isn't capable of detecting a new device that gets
plugged in while the power is off, maybe you should just leave the port
at full power all the time.

Alan Stern

--
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