From: Matthias Kaehlcke <mka@chromium.org>
To: Alan Stern <stern@rowland.harvard.edu>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Rob Herring <robh+dt@kernel.org>,
Frank Rowand <frowand.list@gmail.com>,
linux-usb@vger.kernel.org,
Douglas Anderson <dianders@chromium.org>,
Bastien Nocera <hadess@hadess.net>,
Ravi Chandra Sadineni <ravisadineni@chromium.org>,
Peter Chen <peter.chen@nxp.com>,
Krzysztof Kozlowski <krzk@kernel.org>,
devicetree@vger.kernel.org, Stephen Boyd <swboyd@chromium.org>,
linux-kernel@vger.kernel.org,
"Alexander A. Klimov" <grandmaster@al2klimov.de>,
Masahiro Yamada <masahiroy@kernel.org>
Subject: Re: [PATCH v3 2/2] USB: misc: Add onboard_usb_hub driver
Date: Thu, 24 Sep 2020 08:55:21 -0700 [thread overview]
Message-ID: <20200924155521.GA3165145@google.com> (raw)
In-Reply-To: <20200924152758.GA1337044@rowland.harvard.edu>
Hi Alan,
On Thu, Sep 24, 2020 at 11:27:58AM -0400, Alan Stern wrote:
> On Wed, Sep 23, 2020 at 06:10:12PM -0700, Matthias Kaehlcke wrote:
> > The main issue this driver addresses is that a USB hub needs to be
> > powered before it can be discovered. For discrete onboard hubs (an
> > example for such a hub is the Realtek RTS5411) this is often solved
> > by supplying the hub with an 'always-on' regulator, which is kind
> > of a hack. Some onboard hubs may require further initialization
> > steps, like changing the state of a GPIO or enabling a clock, which
> > requires even more hacks. This driver creates a platform device
> > representing the hub which performs the necessary initialization.
> > Currently it only supports switching on a single regulator, support
> > for multiple regulators or other actions can be added as needed.
> > Different initialization sequences can be supported based on the
> > compatible string.
> >
> > Besides performing the initialization the driver can be configured
> > to power the hub off during system suspend. This can help to extend
> > battery life on battery powered devices which have no requirements
> > to keep the hub powered during suspend. The driver can also be
> > configured to leave the hub powered when a wakeup capable USB device
> > is connected when suspending, and power it off otherwise.
> >
> > Technically the driver consists of two drivers, the platform driver
> > described above and a very thin USB driver that subclasses the
> > generic driver. The purpose of this driver is to provide the platform
> > driver with the USB devices corresponding to the hub(s) (a hub
> > controller may provide multiple 'logical' hubs, e.g. one to support
> > USB 2.0 and another for USB 3.x).
> >
> > Co-developed-by: Ravi Chandra Sadineni <ravisadineni@chromium.org>
> > Signed-off-by: Ravi Chandra Sadineni <ravisadineni@chromium.org>
> > Signed-off-by: Matthias Kaehlcke <mka@chromium.org>
> > ---
>
> > --- a/drivers/usb/misc/Kconfig
> > +++ b/drivers/usb/misc/Kconfig
> > @@ -275,3 +275,19 @@ config USB_CHAOSKEY
> >
> > To compile this driver as a module, choose M here: the
> > module will be called chaoskey.
> > +
> > +config USB_ONBOARD_HUB
> > + tristate "Onboard USB hub support"
> > + depends on OF || COMPILE_TEST
> > + help
> > + Say Y here if you want to support discrete onboard USB hubs that
> > + don't require an additional control bus for initialization (an
>
> ... but does require nontrivial form of initialization, such as
> enabling a power regulator.
ok, I'll add that
> > +static void onboard_hub_remove_usbdev(struct onboard_hub *hub, struct usb_device *udev)
> > +{
> > + struct udev_node *node;
> > +
> > + smp_rmb();
> > + if (hub->going_away) {
> > + /*
> > + * We are most likely being called as a result of unbinding a USB device from
> > + * onboard_hub_remove(). This function also holds the lock and iterates over
> > + * 'udev_list'. Skip deleting the node in this case to avoid a self deadlock,
> > + * keeping the node in the list isn't a problem, since the device is about to go
> > + * away.
> > + */
> > + return;
> > + }
>
> This part has a suspicious look. For one thing, there's no comment
> explaining the purpose of the smp_rmb(). For another, that barrier
> doesn't seem to pair with any other memory barrier in the driver.
IIUC the mutex_lock() in onboard_hub_remove() is an implicit barrier, but
it is indeed not obvious from looking at the code.
> I get that you want to avoid self-deadlock here. But there must be a
> better way. See below.
I wasn't super happy about this either ...
> > +static int onboard_hub_remove(struct platform_device *pdev)
> > +{
> > + struct onboard_hub *hub = dev_get_drvdata(&pdev->dev);
> > + struct udev_node *node;
> > +
> > + hub->going_away = true;
> > +
> > + mutex_lock(&hub->lock);
> > +
> > + /* unbind the USB devices to avoid dangling references to this device */
> > + list_for_each_entry(node, &hub->udev_list, list)
> > + device_release_driver(&node->udev->dev);
> > +
> > + mutex_unlock(&hub->lock);
>
> Alternative approach:
>
> /* unbind the USB devices to avoid dangling references to this device */
> mutex_lock(&hub->lock);
> while (!list_empty(&hub->udev_list)) {
> node = list_first_entry(&hub->udev_list, struct udev_node, list);
> udev = node->udev;
>
> /*
> * Unbinding the driver will call onboard_hub_remove_usbdev(),
> * which acquires hub->lock. We must release the lock first.
> */
> usb_get_device(udev);
> mutex_unlock(&hub->lock);
> device_release_driver(&udev->dev);
> usb_put_device(udev);
> mutex_lock(&hub->lock);
> }
> mutex_unlock(&hub->lock);
>
Thanks, that should work. I also thought about unlocking the mutex before
calling device_release_driver(), but that wouldn't be the right thing when
using list_for_each_entry(_safe). The alternative loop style allows for it.
> > +static int onboard_hub_usbdev_probe(struct usb_device *udev)
> > +{
> > + struct device *dev = &udev->dev;
> > + struct onboard_hub *hub;
> > +
> > + /* ignore supported hubs without device tree node */
> > + if (!dev->of_node)
> > + return -ENODEV;
> > +
> > + hub = _find_onboard_hub(dev);
> > + if (IS_ERR(hub))
> > + return PTR_ERR(dev);
>
> hub, not dev.
ugh, yes
prev parent reply other threads:[~2020-09-24 15:55 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-09-24 1:10 [PATCH v3 1/2] dt-bindings: usb: Add binding for discrete onboard USB hubs Matthias Kaehlcke
2020-09-24 1:10 ` [PATCH v3 2/2] USB: misc: Add onboard_usb_hub driver Matthias Kaehlcke
2020-09-24 15:27 ` Alan Stern
2020-09-24 15:55 ` Matthias Kaehlcke [this message]
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=20200924155521.GA3165145@google.com \
--to=mka@chromium.org \
--cc=devicetree@vger.kernel.org \
--cc=dianders@chromium.org \
--cc=frowand.list@gmail.com \
--cc=grandmaster@al2klimov.de \
--cc=gregkh@linuxfoundation.org \
--cc=hadess@hadess.net \
--cc=krzk@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=masahiroy@kernel.org \
--cc=peter.chen@nxp.com \
--cc=ravisadineni@chromium.org \
--cc=robh+dt@kernel.org \
--cc=stern@rowland.harvard.edu \
--cc=swboyd@chromium.org \
/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.