From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.4 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 322C6C4709C for ; Thu, 3 Jun 2021 17:07:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 15F42613FE for ; Thu, 3 Jun 2021 17:07:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230329AbhFCRJZ (ORCPT ); Thu, 3 Jun 2021 13:09:25 -0400 Received: from mail.kernel.org ([198.145.29.99]:40212 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230247AbhFCRJX (ORCPT ); Thu, 3 Jun 2021 13:09:23 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 0D294613F1; Thu, 3 Jun 2021 17:07:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1622740058; bh=M/5NejGzPjHEsCiI1zU6wysLuJGHBUueDoeg9EZU1Eg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PRZNJz0vDq6lVPOkSUWQvtxaZedIGznIVzUbbUd10f6ao5m2TsmjPxd6a+4cXU4BY 4Cb+dXhXnPMWOAqg+GtsBMR7kpsALzmHLtgoC6Cr1gtrSRzLGdAkvLmwtsHMZlGpMd pRtEXJJE5VV8cJj1T4xn4MAaiMy9wxyaZ+zxnB69eMod9Vi6gmAJmdhEfDt8h1puBg DJO9/uVUuJrLkWxAuRXAlly2XS/Tw3hq4fLMyhMKF/To85l7+8N0GgvkCYG1RJLKc7 n+izGNYJS3RsuKMG80YE2/n4GnC2ZJtcoFj4FkL+T76rFHQFcybTA9+Kx6IP8UjHFg o8H41RlodVZDg== From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Saravana Kannan , Mark Brown , Sasha Levin , linux-spi@vger.kernel.org Subject: [PATCH AUTOSEL 5.12 03/43] spi: Fix spi device unregister flow Date: Thu, 3 Jun 2021 13:06:53 -0400 Message-Id: <20210603170734.3168284-3-sashal@kernel.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210603170734.3168284-1-sashal@kernel.org> References: <20210603170734.3168284-1-sashal@kernel.org> MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Saravana Kannan [ Upstream commit c7299fea67696db5bd09d924d1f1080d894f92ef ] When an SPI device is unregistered, the spi->controller->cleanup() is called in the device's release callback. That's wrong for a couple of reasons: 1. spi_dev_put() can be called before spi_add_device() is called. And it's spi_add_device() that calls spi_setup(). This will cause clean() to get called without the spi device ever being setup. 2. There's no guarantee that the controller's driver would be present by the time the spi device's release function gets called. 3. It also causes "sleeping in atomic context" stack dump[1] when device link deletion code does a put_device() on the spi device. Fix these issues by simply moving the cleanup from the device release callback to the actual spi_unregister_device() function. [1] - https://lore.kernel.org/lkml/CAHp75Vc=FCGcUyS0v6fnxme2YJ+qD+Y-hQDQLa2JhWNON9VmsQ@mail.gmail.com/ Signed-off-by: Saravana Kannan Link: https://lore.kernel.org/r/20210426235638.1285530-1-saravanak@google.com Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- drivers/spi/spi.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 8da4fe475b84..4278d9a63636 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -47,10 +47,6 @@ static void spidev_release(struct device *dev) { struct spi_device *spi = to_spi_device(dev); - /* spi controllers may cleanup for released devices */ - if (spi->controller->cleanup) - spi->controller->cleanup(spi); - spi_controller_put(spi->controller); kfree(spi->driver_override); kfree(spi); @@ -558,6 +554,12 @@ static int spi_dev_check(struct device *dev, void *data) return 0; } +static void spi_cleanup(struct spi_device *spi) +{ + if (spi->controller->cleanup) + spi->controller->cleanup(spi); +} + /** * spi_add_device - Add spi_device allocated with spi_alloc_device * @spi: spi_device to register @@ -622,11 +624,13 @@ int spi_add_device(struct spi_device *spi) /* Device may be bound to an active driver when this returns */ status = device_add(&spi->dev); - if (status < 0) + if (status < 0) { dev_err(dev, "can't add %s, status %d\n", dev_name(&spi->dev), status); - else + spi_cleanup(spi); + } else { dev_dbg(dev, "registered child %s\n", dev_name(&spi->dev)); + } done: mutex_unlock(&spi_add_lock); @@ -713,6 +717,8 @@ void spi_unregister_device(struct spi_device *spi) if (!spi) return; + spi_cleanup(spi); + if (spi->dev.of_node) { of_node_clear_flag(spi->dev.of_node, OF_POPULATED); of_node_put(spi->dev.of_node); -- 2.30.2