mirror of
https://github.com/torvalds/linux.git
synced 2026-06-03 20:14:06 +02:00
spi: Fixes for v7.0
There are two core fixes here. One is from Johan dealing with an issue introduced by a devm_ API usage update causing things to be freed earlier than they had earlier when we fail to register a device, another from Danilo avoids unlocked acccess to data by converting to use a driver core API. We also have a few relatively minor driver specific fixes. -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAmnG0MUACgkQJNaLcl1U h9BsrAf9H6Wj8EU/xkrHXl+trqY46+Fniloxp9Ar2aezYZXotnFL25JmAxyk5oYK HMHV677Xo+rcp9z77yr3vGyYFhiccioGm4t5kblIZxfwvxcuWj2r2d2KGF0jCBna qr3IfEowlgFW6BDfL72tZbuLrjkfmIAA2IMXOlZdHGz/QswNnOjPbbDRsyKn19xF a/CgVRyyAdAJxlv+p8/o7GbAMqJGStZ/w6Thk0GbLHASQE8Po1pTARGh7UbrJLVS hGEOM828PG8dctDbtE5Cg1mUm4rKIvtDlcZNLArSwPGfLcWei9AK++wfDck/ANho eRu8Zyr7yew00w+HLEssvyiSgS0HrA== =/ogD -----END PGP SIGNATURE----- Merge tag 'spi-fix-v7.0-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi Pull spi fixes from Mark Brown: "There are two core fixes here. One is from Johan dealing with an issue introduced by a devm_ API usage update causing things to be freed earlier than they had earlier when we fail to register a device, another from Danilo avoids unlocked acccess to data by converting to use a driver core API. We also have a few relatively minor driver specific fixes" * tag 'spi-fix-v7.0-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: spi: spi-fsl-lpspi: fix teardown order issue (UAF) spi: fix use-after-free on managed registration failure spi: use generic driver_override infrastructure spi: meson-spicc: Fix double-put in remove path spi: sn-f-ospi: Use devm_mutex_init() to simplify code spi: sn-f-ospi: Fix resource leak in f_ospi_probe()
This commit is contained in:
commit
335c9017e3
|
|
@ -1009,7 +1009,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
|
|||
enable_irq(irq);
|
||||
}
|
||||
|
||||
ret = devm_spi_register_controller(&pdev->dev, controller);
|
||||
ret = spi_register_controller(controller);
|
||||
if (ret < 0) {
|
||||
dev_err_probe(&pdev->dev, ret, "spi_register_controller error\n");
|
||||
goto free_dma;
|
||||
|
|
@ -1035,6 +1035,7 @@ static void fsl_lpspi_remove(struct platform_device *pdev)
|
|||
struct fsl_lpspi_data *fsl_lpspi =
|
||||
spi_controller_get_devdata(controller);
|
||||
|
||||
spi_unregister_controller(controller);
|
||||
fsl_lpspi_dma_exit(controller);
|
||||
|
||||
pm_runtime_dont_use_autosuspend(fsl_lpspi->dev);
|
||||
|
|
|
|||
|
|
@ -1101,8 +1101,6 @@ static void meson_spicc_remove(struct platform_device *pdev)
|
|||
|
||||
/* Disable SPI */
|
||||
writel(0, spicc->base + SPICC_CONREG);
|
||||
|
||||
spi_controller_put(spicc->host);
|
||||
}
|
||||
|
||||
static const struct meson_spicc_data meson_spicc_gx_data = {
|
||||
|
|
|
|||
|
|
@ -612,7 +612,7 @@ static int f_ospi_probe(struct platform_device *pdev)
|
|||
u32 num_cs = OSPI_NUM_CS;
|
||||
int ret;
|
||||
|
||||
ctlr = spi_alloc_host(dev, sizeof(*ospi));
|
||||
ctlr = devm_spi_alloc_host(dev, sizeof(*ospi));
|
||||
if (!ctlr)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -635,43 +635,22 @@ static int f_ospi_probe(struct platform_device *pdev)
|
|||
platform_set_drvdata(pdev, ospi);
|
||||
|
||||
ospi->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(ospi->base)) {
|
||||
ret = PTR_ERR(ospi->base);
|
||||
goto err_put_ctlr;
|
||||
}
|
||||
if (IS_ERR(ospi->base))
|
||||
return PTR_ERR(ospi->base);
|
||||
|
||||
ospi->clk = devm_clk_get_enabled(dev, NULL);
|
||||
if (IS_ERR(ospi->clk)) {
|
||||
ret = PTR_ERR(ospi->clk);
|
||||
goto err_put_ctlr;
|
||||
}
|
||||
if (IS_ERR(ospi->clk))
|
||||
return PTR_ERR(ospi->clk);
|
||||
|
||||
mutex_init(&ospi->mlock);
|
||||
ret = devm_mutex_init(dev, &ospi->mlock);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = f_ospi_init(ospi);
|
||||
if (ret)
|
||||
goto err_destroy_mutex;
|
||||
return ret;
|
||||
|
||||
ret = devm_spi_register_controller(dev, ctlr);
|
||||
if (ret)
|
||||
goto err_destroy_mutex;
|
||||
|
||||
return 0;
|
||||
|
||||
err_destroy_mutex:
|
||||
mutex_destroy(&ospi->mlock);
|
||||
|
||||
err_put_ctlr:
|
||||
spi_controller_put(ctlr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void f_ospi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct f_ospi *ospi = platform_get_drvdata(pdev);
|
||||
|
||||
mutex_destroy(&ospi->mlock);
|
||||
return devm_spi_register_controller(dev, ctlr);
|
||||
}
|
||||
|
||||
static const struct of_device_id f_ospi_dt_ids[] = {
|
||||
|
|
@ -686,7 +665,6 @@ static struct platform_driver f_ospi_driver = {
|
|||
.of_match_table = f_ospi_dt_ids,
|
||||
},
|
||||
.probe = f_ospi_probe,
|
||||
.remove = f_ospi_remove,
|
||||
};
|
||||
module_platform_driver(f_ospi_driver);
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ static void spidev_release(struct device *dev)
|
|||
struct spi_device *spi = to_spi_device(dev);
|
||||
|
||||
spi_controller_put(spi->controller);
|
||||
kfree(spi->driver_override);
|
||||
free_percpu(spi->pcpu_statistics);
|
||||
kfree(spi);
|
||||
}
|
||||
|
|
@ -73,10 +72,9 @@ static ssize_t driver_override_store(struct device *dev,
|
|||
struct device_attribute *a,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(dev);
|
||||
int ret;
|
||||
|
||||
ret = driver_set_override(dev, &spi->driver_override, buf, count);
|
||||
ret = __device_set_driver_override(dev, buf, count);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -86,13 +84,8 @@ static ssize_t driver_override_store(struct device *dev,
|
|||
static ssize_t driver_override_show(struct device *dev,
|
||||
struct device_attribute *a, char *buf)
|
||||
{
|
||||
const struct spi_device *spi = to_spi_device(dev);
|
||||
ssize_t len;
|
||||
|
||||
device_lock(dev);
|
||||
len = sysfs_emit(buf, "%s\n", spi->driver_override ? : "");
|
||||
device_unlock(dev);
|
||||
return len;
|
||||
guard(spinlock)(&dev->driver_override.lock);
|
||||
return sysfs_emit(buf, "%s\n", dev->driver_override.name ?: "");
|
||||
}
|
||||
static DEVICE_ATTR_RW(driver_override);
|
||||
|
||||
|
|
@ -376,10 +369,12 @@ static int spi_match_device(struct device *dev, const struct device_driver *drv)
|
|||
{
|
||||
const struct spi_device *spi = to_spi_device(dev);
|
||||
const struct spi_driver *sdrv = to_spi_driver(drv);
|
||||
int ret;
|
||||
|
||||
/* Check override first, and if set, only use the named driver */
|
||||
if (spi->driver_override)
|
||||
return strcmp(spi->driver_override, drv->name) == 0;
|
||||
ret = device_match_driver_override(dev, drv);
|
||||
if (ret >= 0)
|
||||
return ret;
|
||||
|
||||
/* Attempt an OF style match */
|
||||
if (of_driver_match_device(dev, drv))
|
||||
|
|
@ -3539,8 +3534,19 @@ int devm_spi_register_controller(struct device *dev,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
return devm_add_action_or_reset(dev, devm_spi_unregister_controller, ctlr);
|
||||
/*
|
||||
* Prevent controller from being freed by spi_unregister_controller()
|
||||
* if devm_add_action_or_reset() fails for a non-devres allocated
|
||||
* controller.
|
||||
*/
|
||||
spi_controller_get(ctlr);
|
||||
|
||||
ret = devm_add_action_or_reset(dev, devm_spi_unregister_controller, ctlr);
|
||||
|
||||
if (ret == 0 || ctlr->devm_allocated)
|
||||
spi_controller_put(ctlr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_spi_register_controller);
|
||||
|
||||
|
|
|
|||
|
|
@ -159,10 +159,6 @@ extern void spi_transfer_cs_change_delay_exec(struct spi_message *msg,
|
|||
* @modalias: Name of the driver to use with this device, or an alias
|
||||
* for that name. This appears in the sysfs "modalias" attribute
|
||||
* for driver coldplugging, and in uevents used for hotplugging
|
||||
* @driver_override: If the name of a driver is written to this attribute, then
|
||||
* the device will bind to the named driver and only the named driver.
|
||||
* Do not set directly, because core frees it; use driver_set_override() to
|
||||
* set or clear it.
|
||||
* @pcpu_statistics: statistics for the spi_device
|
||||
* @word_delay: delay to be inserted between consecutive
|
||||
* words of a transfer
|
||||
|
|
@ -224,7 +220,6 @@ struct spi_device {
|
|||
void *controller_state;
|
||||
void *controller_data;
|
||||
char modalias[SPI_NAME_SIZE];
|
||||
const char *driver_override;
|
||||
|
||||
/* The statistics */
|
||||
struct spi_statistics __percpu *pcpu_statistics;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user