linux-spi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>
To: Mark Brown <broonie@kernel.org>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-spi@vger.kernel.org, Lukas Wunner <lukas@wunner.de>,
	Mika Westerberg <mika.westerberg@linux.intel.com>,
	Jarkko Nikula <jarkko.nikula@intel.com>
Subject: Deadlock in spi_add_device() -- device core problem
Date: Thu, 7 Oct 2021 18:05:24 +0200	[thread overview]
Message-ID: <20211007160524.qhjtcwtto2ftsmhe@pengutronix.de> (raw)

[-- Attachment #1: Type: text/plain, Size: 3894 bytes --]

Hello,

On an ARM board with an spi-mux I observe a deadlock during boot. This
happens because spi_add_device() (in drivers/spi/spi.c) for the spi-mux
device calls device_add() while holding &spi_add_lock. The spi-mux
driver's probe routine than creates another controller and for the
devices on that bus spi_add_device() is called again, trying to grab
&spi_add_lock again.

The easy workaround would be to replace &spi_add_lock with a
per-controller lock, but I have the expectation that it should be
possible to not hold a lock while calling device_add().

The difficulty (and the reason that this lock exists) is that it should
be prevented that more than one device is added for a any chipselect.
My first guess was, this check isn't necessary, because the devices are
called $busname.$chipselect and a second device on the same bus with the
same chipselect would fail when device_add() tries to create the
duplicate name. However for devices instanciated by ACPI the naming is
different (see spi_dev_set_name(), and commit b6fb8d3a1f15). Also there
is a comment "We need to make sure there's no other device with this
chipselect **BEFORE** we call setup(), else we'll trash its
configuration." A problem there might be that spi_setup() might toggle
the chipselect line (which is a problem if the chipselect polarity
isn't the same for the two devices, or the earlier device is currently
busy). Anything else?

There is also a check:

	if (IS_ENABLED(CONFIG_SPI_DYNAMIC) &&
	    !device_is_registered(&ctlr->dev)) {
		return -NODEV;
	}

which catches the race that the controller (which is also the device's
parent) is about to go while we try to add a new device to it. Is this a
real problem? (The spi_unregister_controller() function unregisters all
children which might race with adding a new child without locking. This
check was implemented by Lukas Wunner (on Cc:) in commit ddf75be47ca7.)
Doesn't all children of a given device are unregistered automatically by
the device core somehow when said device is unregistered? (I checked,
but didn't find anything.)

Does this all sound about right? Greg, do you have a recommendation how
to properly fix this problem?

Best regards
Uwe

PS: For now the workaround is to have the spi-mux driver as a module.
This way device_add() for the spi-mux device doesn't bind the driver and
the function returns (but triggers a module load which then can bind the
spi-mux device and create the new controller without a locking issue).

For the record, the relevant device-tree snippet looks as follows:

/ {
	...
        spimux: mux-controller {
                compatible = "gpio-mux";
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_spimux>;
                #mux-control-cells = <0>;
                mux-gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>;
        };
};

&ecspi2 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_ecspi2>;
        status = "okay";
        #address-cells = <1>;
        #size-cells = <0>;

        spi@0 {
                compatible = "spi-mux";
                reg = <0>;
                #address-cells = <1>;
                #size-cells = <0>;
                spi-max-frequency = <100000000>;
                mux-controls = <&spimux>;

                adc@0 {
                        compatible = "ti,ads7953";
                        reg = <0>;
                        spi-max-frequency = <10000000>;
                };

                adc@1 {
                        compatible = "ti,ads7953";
                        reg = <1>;
                        spi-max-frequency = <10000000>;
                };
        };
};


-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | https://www.pengutronix.de/ |

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

             reply	other threads:[~2021-10-07 16:05 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-07 16:05 Uwe Kleine-König [this message]
2021-10-07 16:19 ` Deadlock in spi_add_device() -- device core problem Greg Kroah-Hartman
2021-10-07 16:52   ` Uwe Kleine-König
2021-10-08 13:31     ` Mark Brown
2021-10-12 19:30       ` Uwe Kleine-König
2021-10-13  6:52         ` Greg Kroah-Hartman
2021-10-13  7:33           ` Uwe Kleine-König
2021-10-07 17:23 ` Lukas Wunner

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=20211007160524.qhjtcwtto2ftsmhe@pengutronix.de \
    --to=u.kleine-koenig@pengutronix.de \
    --cc=broonie@kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=jarkko.nikula@intel.com \
    --cc=linux-spi@vger.kernel.org \
    --cc=lukas@wunner.de \
    --cc=mika.westerberg@linux.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).