“1da177e4c3f41524e886b7f1b8a0c1fc7321cac2”上不存在“arch/s390/include/asm/scatterlist.h”
提交 0ed6c4de 编写于 作者: S Saravana Kannan 提交者: Wang ShaoBo

spi: Fix spi device unregister flow

stable inclusion
from stable-v5.10.44
commit 01905f3232fdc0737de5c38e9d817f87a06a1a6d
bugzilla: https://bugzilla.openeuler.org/show_bug.cgi?id=347
CVE: NA

-------------------------------------------------

[ Upstream commit c7299fea ]

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: NSaravana Kannan <saravanak@google.com>
Link: https://lore.kernel.org/r/20210426235638.1285530-1-saravanak@google.comSigned-off-by: NMark Brown <broonie@kernel.org>
Signed-off-by: NSasha Levin <sashal@kernel.org>
Signed-off-by: NYu Hua Xiao <xiaoyuhua2332@163.com>
Reviewed-by: Jian Cheng <cj.chengjian(a)huawei.com>
Signed-off-by: NWang ShaoBo <bobo.shaobowang@huawei.com>
上级 f04afefe
......@@ -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);
......@@ -550,6 +546,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
......@@ -614,11 +616,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);
......@@ -705,6 +709,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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册