If the SPI bus number is provided by a DT alias, idr_alloc() is called twice, leading to:
WARNING: CPU: 1 PID: 1 at drivers/spi/spi.c:2179 spi_register_controller+0x11c/0x5d8 couldn't get idr
Fix this by moving the handling of fixed SPI bus numbers up, before the DT handling code fills in ctlr->bus_num.
Fixes: 1a4327fbf4554d5b ("spi: fix IDR collision on systems with both fixed and dynamic SPI bus numbers") Signed-off-by: Geert Uytterhoeven geert+renesas@glider.be --- Seen on e.g. r8a7791/koelsch, breaking both RSPI and MSIOF. --- drivers/spi/spi.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index a00d006d4c3a1c5a..9da0bc5a036cfff6 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2143,8 +2143,17 @@ int spi_register_controller(struct spi_controller *ctlr) */ if (ctlr->num_chipselect == 0) return -EINVAL; - /* allocate dynamic bus number using Linux idr */ - if ((ctlr->bus_num < 0) && ctlr->dev.of_node) { + if (ctlr->bus_num >= 0) { + /* devices with a fixed bus num must check-in with the num */ + mutex_lock(&board_lock); + id = idr_alloc(&spi_master_idr, ctlr, ctlr->bus_num, + ctlr->bus_num + 1, GFP_KERNEL); + mutex_unlock(&board_lock); + if (WARN(id < 0, "couldn't get idr")) + return id == -ENOSPC ? -EBUSY : id; + ctlr->bus_num = id; + } else if (ctlr->dev.of_node) { + /* allocate dynamic bus number using Linux idr */ id = of_alias_get_id(ctlr->dev.of_node, "spi"); if (id >= 0) { ctlr->bus_num = id; @@ -2170,15 +2179,6 @@ int spi_register_controller(struct spi_controller *ctlr) if (WARN(id < 0, "couldn't get idr")) return id; ctlr->bus_num = id; - } else { - /* devices with a fixed bus num must check-in with the num */ - mutex_lock(&board_lock); - id = idr_alloc(&spi_master_idr, ctlr, ctlr->bus_num, - ctlr->bus_num + 1, GFP_KERNEL); - mutex_unlock(&board_lock); - if (WARN(id < 0, "couldn't get idr")) - return id == -ENOSPC ? -EBUSY : id; - ctlr->bus_num = id; } INIT_LIST_HEAD(&ctlr->queue); spin_lock_init(&ctlr->queue_lock);
On Tue, Aug 21, 2018 at 11:53:03AM +0200, Geert Uytterhoeven wrote:
If the SPI bus number is provided by a DT alias, idr_alloc() is called twice, leading to:
WARNING: CPU: 1 PID: 1 at drivers/spi/spi.c:2179 spi_register_controller+0x11c/0x5d8 couldn't get idr
Fix this by moving the handling of fixed SPI bus numbers up, before the DT handling code fills in ctlr->bus_num.
Fixes: 1a4327fbf4554d5b ("spi: fix IDR collision on systems with both fixed and dynamic SPI bus numbers") Signed-off-by: Geert Uytterhoeven geert+renesas@glider.be
Seen on e.g. r8a7791/koelsch, breaking both RSPI and MSIOF.
drivers/spi/spi.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
<formletter>
This is not the correct way to submit patches for inclusion in the stable kernel tree. Please read: https://www.kernel.org/doc/html/latest/process/stable-kernel-rules.html for how to do this properly.
</formletter>
Hi Greg,
On Tue, Aug 21, 2018 at 3:40 PM Greg KH greg@kroah.com wrote:
On Tue, Aug 21, 2018 at 11:53:03AM +0200, Geert Uytterhoeven wrote:
If the SPI bus number is provided by a DT alias, idr_alloc() is called twice, leading to:
WARNING: CPU: 1 PID: 1 at drivers/spi/spi.c:2179 spi_register_controller+0x11c/0x5d8 couldn't get idr
Fix this by moving the handling of fixed SPI bus numbers up, before the DT handling code fills in ctlr->bus_num.
Fixes: 1a4327fbf4554d5b ("spi: fix IDR collision on systems with both fixed and dynamic SPI bus numbers") Signed-off-by: Geert Uytterhoeven geert+renesas@glider.be
Seen on e.g. r8a7791/koelsch, breaking both RSPI and MSIOF.
drivers/spi/spi.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
<formletter>
This is not the correct way to submit patches for inclusion in the stable kernel tree. Please read: https://www.kernel.org/doc/html/latest/process/stable-kernel-rules.html for how to do this properly.
</formletter>
I know.
I only CCed stable because the acceptance email for the original patch was CCed to stable, and I wanted to prevent that one from being backported early.
Gr{oetje,eeting}s,
Geert
Hi Geert
Thank you for keeping me informed.
I have to point at the following threat: a dynamically allocated ID may 'squat' a bus ID that intended for a device with statically allocated ID. This scenario is possible since module loading order is uncertain. This threat seems to be inevitable...
-- Best regards, Kirill.
On 08/21/2018 12:53 PM, Geert Uytterhoeven wrote:
If the SPI bus number is provided by a DT alias, idr_alloc() is called twice, leading to:
WARNING: CPU: 1 PID: 1 at drivers/spi/spi.c:2179 spi_register_controller+0x11c/0x5d8 couldn't get idr
Fix this by moving the handling of fixed SPI bus numbers up, before the DT handling code fills in ctlr->bus_num.
Fixes: 1a4327fbf4554d5b ("spi: fix IDR collision on systems with both fixed and dynamic SPI bus numbers") Signed-off-by: Geert Uytterhoeven geert+renesas@glider.be
Seen on e.g. r8a7791/koelsch, breaking both RSPI and MSIOF.
drivers/spi/spi.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index a00d006d4c3a1c5a..9da0bc5a036cfff6 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2143,8 +2143,17 @@ int spi_register_controller(struct spi_controller *ctlr) */ if (ctlr->num_chipselect == 0) return -EINVAL;
- /* allocate dynamic bus number using Linux idr */
- if ((ctlr->bus_num < 0) && ctlr->dev.of_node) {
- if (ctlr->bus_num >= 0) {
/* devices with a fixed bus num must check-in with the num */
mutex_lock(&board_lock);
id = idr_alloc(&spi_master_idr, ctlr, ctlr->bus_num,
ctlr->bus_num + 1, GFP_KERNEL);
mutex_unlock(&board_lock);
if (WARN(id < 0, "couldn't get idr"))
return id == -ENOSPC ? -EBUSY : id;
ctlr->bus_num = id;
- } else if (ctlr->dev.of_node) {
id = of_alias_get_id(ctlr->dev.of_node, "spi"); if (id >= 0) { ctlr->bus_num = id;/* allocate dynamic bus number using Linux idr */
@@ -2170,15 +2179,6 @@ int spi_register_controller(struct spi_controller *ctlr) if (WARN(id < 0, "couldn't get idr")) return id; ctlr->bus_num = id;
- } else {
/* devices with a fixed bus num must check-in with the num */
mutex_lock(&board_lock);
id = idr_alloc(&spi_master_idr, ctlr, ctlr->bus_num,
ctlr->bus_num + 1, GFP_KERNEL);
mutex_unlock(&board_lock);
if (WARN(id < 0, "couldn't get idr"))
return id == -ENOSPC ? -EBUSY : id;
} INIT_LIST_HEAD(&ctlr->queue); spin_lock_init(&ctlr->queue_lock);ctlr->bus_num = id;
On Wed, Aug 22, 2018 at 08:51:40PM +0300, Kirill Kapranov wrote:
Please don't top post, reply in line with needed context. This allows readers to readily follow the flow of conversation and understand what you are talking about and also helps ensure that everything in the discussion is being addressed.
I have to point at the following threat: a dynamically allocated ID may 'squat' a bus ID that intended for a device with statically allocated ID. This scenario is possible since module loading order is uncertain. This threat seems to be inevitable...
For DT systems the dynamically allocated IDs start at the maximum positive ID and work down so in practice it is vanishingly unlikely that there will be a collision as idiomatic static DT IDs would be low integers.
Hi Geert,
On Tue, Aug 21, 2018 at 6:53 AM, Geert Uytterhoeven geert+renesas@glider.be wrote:
If the SPI bus number is provided by a DT alias, idr_alloc() is called twice, leading to:
WARNING: CPU: 1 PID: 1 at drivers/spi/spi.c:2179 spi_register_controller+0x11c/0x5d8 couldn't get idr
Fix this by moving the handling of fixed SPI bus numbers up, before the DT handling code fills in ctlr->bus_num.
Fixes: 1a4327fbf4554d5b ("spi: fix IDR collision on systems with both fixed and dynamic SPI bus numbers") Signed-off-by: Geert Uytterhoeven geert+renesas@glider.be
This fixes SPI on imx51-babbage, thanks.
Tested-by: Fabio Estevam fabio.estevam@nxp.com
The patch
spi: Fix double IDR allocation with DT aliases
has been applied to the spi tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 04b2d03a75652bda989de1595048f0501dc0c0a0 Mon Sep 17 00:00:00 2001
From: Geert Uytterhoeven geert+renesas@glider.be Date: Tue, 21 Aug 2018 11:53:03 +0200 Subject: [PATCH] spi: Fix double IDR allocation with DT aliases
If the SPI bus number is provided by a DT alias, idr_alloc() is called twice, leading to:
WARNING: CPU: 1 PID: 1 at drivers/spi/spi.c:2179 spi_register_controller+0x11c/0x5d8 couldn't get idr
Fix this by moving the handling of fixed SPI bus numbers up, before the DT handling code fills in ctlr->bus_num.
Fixes: 1a4327fbf4554d5b ("spi: fix IDR collision on systems with both fixed and dynamic SPI bus numbers") Signed-off-by: Geert Uytterhoeven geert+renesas@glider.be Tested-by: Fabio Estevam fabio.estevam@nxp.com Signed-off-by: Mark Brown broonie@kernel.org --- drivers/spi/spi.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index a00d006d4c3a..9da0bc5a036c 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2143,8 +2143,17 @@ int spi_register_controller(struct spi_controller *ctlr) */ if (ctlr->num_chipselect == 0) return -EINVAL; - /* allocate dynamic bus number using Linux idr */ - if ((ctlr->bus_num < 0) && ctlr->dev.of_node) { + if (ctlr->bus_num >= 0) { + /* devices with a fixed bus num must check-in with the num */ + mutex_lock(&board_lock); + id = idr_alloc(&spi_master_idr, ctlr, ctlr->bus_num, + ctlr->bus_num + 1, GFP_KERNEL); + mutex_unlock(&board_lock); + if (WARN(id < 0, "couldn't get idr")) + return id == -ENOSPC ? -EBUSY : id; + ctlr->bus_num = id; + } else if (ctlr->dev.of_node) { + /* allocate dynamic bus number using Linux idr */ id = of_alias_get_id(ctlr->dev.of_node, "spi"); if (id >= 0) { ctlr->bus_num = id; @@ -2170,15 +2179,6 @@ int spi_register_controller(struct spi_controller *ctlr) if (WARN(id < 0, "couldn't get idr")) return id; ctlr->bus_num = id; - } else { - /* devices with a fixed bus num must check-in with the num */ - mutex_lock(&board_lock); - id = idr_alloc(&spi_master_idr, ctlr, ctlr->bus_num, - ctlr->bus_num + 1, GFP_KERNEL); - mutex_unlock(&board_lock); - if (WARN(id < 0, "couldn't get idr")) - return id == -ENOSPC ? -EBUSY : id; - ctlr->bus_num = id; } INIT_LIST_HEAD(&ctlr->queue); spin_lock_init(&ctlr->queue_lock);
linux-stable-mirror@lists.linaro.org