All of lore.kernel.org
 help / color / mirror / Atom feed
From: Nikolay Yakimov <root@livid.pp.ru>
To: "Gopal, Saranya" <saranya.gopal@intel.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	"linux-usb@vger.kernel.org" <linux-usb@vger.kernel.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH] USB: Fix configuration selection issues introduced in v4.20.0
Date: Wed, 16 Jan 2019 22:13:24 +0300	[thread overview]
Message-ID: <CA+A=rXGckxCsEPAG_DczMgLwS2+K3SXFUnHnXQrOOr+9WOWj9w@mail.gmail.com> (raw)
In-Reply-To: <C672AA6DAAC36042A98BAD0B0B25BDA94CB280EC@BGSMSX104.gar.corp.intel.com>

On Wed, 16 Jan 2019 at 07:24, Gopal, Saranya <saranya.gopal@intel.com> wrote:
>
> Hi Yakimov,
>
> As per UAC3 configuration, the first configuration will always be backward-compatible.
> So, there cannot be any UAC3-compatible device which has first configuration as UAC3.

Thanks for the clarification. I would argue though that not all
devices might adhere to the specification, so it's still probably a
good idea to check all configurations "just in case". I will not press
this point though.

> And secondly, the commit ff2a8c532c14 does not break the pre-existing logic.
> I also thought so much about moving the code above Ethernet check while preparing ff2a8c532c14.
> But, then, it doesn't break the existing logic and so decided against moving it.

It does seem to change the logic for RNDIS devices with multiple
configurations when RNDIS kernel module is enabled.

Consider an RNDIS device with multiple configurations (num_configs > 1)

Before f13912d3f014a, the following sequence would be executed:

1. i == 0.

if (i == 0 && num_configs > 1 && desc &&
        (is_rndis(desc) || is_activesync(desc))) {
    best = c;
}
else ...

The condition is true, so this branch is executed. The first
configuration is selected. Since it's the last condition (all the
remaining code in the loop body is in the else branch), the loop will
continue onto the next iteration.

2. i == 1.

if (i == 0 && num_configs > 1 && desc &&
        (is_rndis(desc) || is_activesync(desc))) {
    ...
}
else if (udev->descriptor.bDeviceClass !=
                    USB_CLASS_VENDOR_SPEC &&
            (desc && desc->bInterfaceClass !=
                    USB_CLASS_VENDOR_SPEC)) {
    best = c;
    break;
} else ...

If the second configuration is not vendor-specific, the first "else
if" branch would be executed, and the second configuration is
selected. The loop is exited on break.

After ff2a8c532c14, the following sequence would be executed:

1. i == 0.

if (i == 0 && num_configs > 1 && desc &&
        (is_rndis(desc) || is_activesync(desc))) {
    best = c;
}

The condition is true, so this branch is executed. The first
configuration is selected, but the loop body continues execution.

2. Still i == 0.

if (i == 0 && num_configs > 1 && desc && is_audio(desc)) {
    ...
}

A redundant check is preformed to check if the device is an audio
device. We already know it isn't.

3. Still i == 0.

if (i > 0 && desc && is_audio(desc)) {
    ...
}
else ...

A redundant check is preformed to check if (i > 0). We already know it isn't.

4. Still i == 0.

else if (udev->descriptor.bDeviceClass !=
                    USB_CLASS_VENDOR_SPEC &&
            (desc && desc->bInterfaceClass !=
                    USB_CLASS_VENDOR_SPEC)) {
    best = c;
    break;
}
else ...

The first "else if" condition is checked. Unless bDeviceClass is
USB_CLASS_VENDOR_SPEC (correct me if I'm wrong, but in most cases I
think it wouldn't be), that condition evaluates as true. The
configuration is selected (redundantly), and the loop is exited on
break.

The result is this:
Before f13912d3f014a, if an RNDIS device has non-vendor-specific
configurations after the first one, that one would be selected.
After ff2a8c532c14, the first configuration would always be selected
for RNDIS devices. Besides, there are several redundant checks in this
case, which is, if nothing else, confusing.

Hopefully I've explained my point clearly enough.

>
> Thanks,
> Saranya

WARNING: multiple messages have this Message-ID (diff)
From: Nikolay Yakimov <root@livid.pp.ru>
To: "Gopal, Saranya" <saranya.gopal@intel.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	"linux-usb@vger.kernel.org" <linux-usb@vger.kernel.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: USB: Fix configuration selection issues introduced in v4.20.0
Date: Wed, 16 Jan 2019 22:13:24 +0300	[thread overview]
Message-ID: <CA+A=rXGckxCsEPAG_DczMgLwS2+K3SXFUnHnXQrOOr+9WOWj9w@mail.gmail.com> (raw)

On Wed, 16 Jan 2019 at 07:24, Gopal, Saranya <saranya.gopal@intel.com> wrote:
>
> Hi Yakimov,
>
> As per UAC3 configuration, the first configuration will always be backward-compatible.
> So, there cannot be any UAC3-compatible device which has first configuration as UAC3.

Thanks for the clarification. I would argue though that not all
devices might adhere to the specification, so it's still probably a
good idea to check all configurations "just in case". I will not press
this point though.

> And secondly, the commit ff2a8c532c14 does not break the pre-existing logic.
> I also thought so much about moving the code above Ethernet check while preparing ff2a8c532c14.
> But, then, it doesn't break the existing logic and so decided against moving it.

It does seem to change the logic for RNDIS devices with multiple
configurations when RNDIS kernel module is enabled.

Consider an RNDIS device with multiple configurations (num_configs > 1)

Before f13912d3f014a, the following sequence would be executed:

1. i == 0.

if (i == 0 && num_configs > 1 && desc &&
        (is_rndis(desc) || is_activesync(desc))) {
    best = c;
}
else ...

The condition is true, so this branch is executed. The first
configuration is selected. Since it's the last condition (all the
remaining code in the loop body is in the else branch), the loop will
continue onto the next iteration.

2. i == 1.

if (i == 0 && num_configs > 1 && desc &&
        (is_rndis(desc) || is_activesync(desc))) {
    ...
}
else if (udev->descriptor.bDeviceClass !=
                    USB_CLASS_VENDOR_SPEC &&
            (desc && desc->bInterfaceClass !=
                    USB_CLASS_VENDOR_SPEC)) {
    best = c;
    break;
} else ...

If the second configuration is not vendor-specific, the first "else
if" branch would be executed, and the second configuration is
selected. The loop is exited on break.

After ff2a8c532c14, the following sequence would be executed:

1. i == 0.

if (i == 0 && num_configs > 1 && desc &&
        (is_rndis(desc) || is_activesync(desc))) {
    best = c;
}

The condition is true, so this branch is executed. The first
configuration is selected, but the loop body continues execution.

2. Still i == 0.

if (i == 0 && num_configs > 1 && desc && is_audio(desc)) {
    ...
}

A redundant check is preformed to check if the device is an audio
device. We already know it isn't.

3. Still i == 0.

if (i > 0 && desc && is_audio(desc)) {
    ...
}
else ...

A redundant check is preformed to check if (i > 0). We already know it isn't.

4. Still i == 0.

else if (udev->descriptor.bDeviceClass !=
                    USB_CLASS_VENDOR_SPEC &&
            (desc && desc->bInterfaceClass !=
                    USB_CLASS_VENDOR_SPEC)) {
    best = c;
    break;
}
else ...

The first "else if" condition is checked. Unless bDeviceClass is
USB_CLASS_VENDOR_SPEC (correct me if I'm wrong, but in most cases I
think it wouldn't be), that condition evaluates as true. The
configuration is selected (redundantly), and the loop is exited on
break.

The result is this:
Before f13912d3f014a, if an RNDIS device has non-vendor-specific
configurations after the first one, that one would be selected.
After ff2a8c532c14, the first configuration would always be selected
for RNDIS devices. Besides, there are several redundant checks in this
case, which is, if nothing else, confusing.

Hopefully I've explained my point clearly enough.

>
> Thanks,
> Saranya

  reply	other threads:[~2019-01-16 19:13 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-01-15 16:13 [PATCH] USB: Fix configuration selection issues introduced in v4.20.0 Nikolay Yakimov
2019-01-15 16:13 ` Nikolay Yakimov
2019-01-15 16:40 ` [PATCH] " Greg Kroah-Hartman
2019-01-15 16:40   ` Greg Kroah-Hartman
2019-01-15 18:12   ` [PATCH] " Nikolay Yakimov
2019-01-15 18:12     ` Nikolay Yakimov
2019-01-16  4:24 ` [PATCH] " Gopal, Saranya
2019-01-16  4:24   ` saranya.gopal
2019-01-16 19:13   ` Nikolay Yakimov [this message]
2019-01-16 19:13     ` Nikolay Yakimov
2019-01-17  3:53     ` [PATCH] " Gopal, Saranya
2019-01-17  3:53       ` saranya.gopal
2019-02-06 12:01       ` [PATCH] " Nikolay Yakimov
2019-02-06 12:01         ` Nikolay Yakimov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CA+A=rXGckxCsEPAG_DczMgLwS2+K3SXFUnHnXQrOOr+9WOWj9w@mail.gmail.com' \
    --to=root@livid.pp.ru \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=saranya.gopal@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.