On Fri, 4 Mar 2016, l00229106 wrote:
> Some super speed device, insert the u3 port, sometimes link is in the
> Compliance Mode State(0x340), and then satisfy hub_port_warm_reset_required
> conditions, the software will perform a warm reset, u3 PORTSC becomes
> 0x2a1203. In hub_port_reset function, it will clear
> USB_PORT_FEAT_C_CONNECTION by usb_clear_port_feature. Finally, the u3
> PORTSC become 0x1203 and super speed device can not be recognized.
>
> The patch can solve it. When the software warm reset, it judge Whether
> the u3 endpoint in the enabled and connected state. if they are, we set
> connect_change = 1. We verify the patch and can correctly identify super
> speed devices.
>
> Signed-off-by: l00229106 <[email protected]>
> ---
> drivers/usb/core/hub.c | 12 +++++++++++-
> 1 file changed, 11 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
> index 350dcd9..039c4e9 100644
> --- a/drivers/usb/core/hub.c
> +++ b/drivers/usb/core/hub.c
> @@ -5037,8 +5037,18 @@ static void port_event(struct usb_hub *hub, int port1)
> usb_reset_device(udev);
> usb_unlock_device(udev);
> usb_lock_port(port_dev);
> - connect_change = 0;
> }
> +
> + ret = hub_port_status(hub, i,
> + &portstatus, &portchange);
> + if (ret < 0)
> + return;
> +
> + if ((portstatus & USB_PORT_STAT_CONNECTION) && !udev &&
> + portstatus & USB_PORT_STAT_ENABLE)
> + connect_change = 1;
You should only test for USB_PORT_STAT_CONNECTION. It doesn't matter
whether USB_PORT_STAT_ENABLE is set; either way, there has been a
connect-status change.
> + else
> + connect_change = 0;
> }
>
> if (connect_change)
Aside from the compiler errors found by the kbuild robot, this patch
was added in the wrong place. It should come here instead:
if (hub_port_warm_reset_required(hub, port1, portstatus)) {
dev_dbg(&port_dev->dev, "do warm reset\n");
if (!udev || !(portstatus & USB_PORT_STAT_CONNECTION)
|| udev->state == USB_STATE_NOTATTACHED) {
if (hub_port_reset(hub, port1, NULL,
HUB_BH_RESET_TIME, true) < 0)
hub_port_disable(hub, port1, 1);
+ else {
+ ...
+ }
} else {
because the new code gets executed only when udev is NULL.
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