From 0ff2de8bb163551ec4230a5a6f3c40c1f6adec4f Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Sat, 23 Feb 2019 08:49:48 +0000 Subject: spi: core: allow defining time that cs is deasserted For some SPI devices that support speed_hz > 1MHz the default 10 us delay when cs_change = 1 is typically way to long and may result in poor spi bus utilization. This patch makes it possible to control the delay at micro or nano second resolution on a per spi_transfer basis. It even allows an "as fast as possible" mode with: xfer.cs_change_delay_unit = SPI_DELAY_UNIT_NSECS; xfer.cs_change_delay = 0; The delay code is shared between delay_usecs and cs_change_delay for consistency and reuse, so in the future this change_delay_unit could also apply to delay_usec as well. Note that on slower SOCs/CPU actually reaching ns deasserts on cs is not realistic as the gpio overhead alone (without any delays added ) may already leave cs deasserted for more than 1us - at least on a raspberry pi. But at the very least this way we can keep it as short as possible. Signed-off-by: Martin Sperl Signed-off-by: Mark Brown --- drivers/spi/spi.c | 59 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 10 deletions(-) (limited to 'drivers/spi/spi.c') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 5e75944ad5d1..7e8ffe3fdc00 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1090,6 +1090,52 @@ static int spi_transfer_wait(struct spi_controller *ctlr, return 0; } +static void _spi_transfer_delay_ns(u32 ns) +{ + if (!ns) + return; + if (ns <= 1000) { + ndelay(ns); + } else { + u32 us = DIV_ROUND_UP(ns, 1000); + + if (us <= 10) + udelay(us); + else + usleep_range(us, us + DIV_ROUND_UP(us, 10)); + } +} + +static void _spi_transfer_cs_change_delay(struct spi_message *msg, + struct spi_transfer *xfer) +{ + u32 delay = xfer->cs_change_delay; + u32 unit = xfer->cs_change_delay_unit; + + /* return early on "fast" mode - for everything but USECS */ + if (!delay && unit != SPI_DELAY_UNIT_USECS) + return; + + switch (unit) { + case SPI_DELAY_UNIT_USECS: + /* for compatibility use default of 10us */ + if (!delay) + delay = 10000; + else + delay *= 1000; + break; + case SPI_DELAY_UNIT_NSECS: /* nothing to do here */ + break; + default: + dev_err_once(&msg->spi->dev, + "Use of unsupported delay unit %i, using default of 10us\n", + xfer->cs_change_delay_unit); + delay = 10000; + } + /* now sleep for the requested amount of time */ + _spi_transfer_delay_ns(delay); +} + /* * spi_transfer_one_message - Default implementation of transfer_one_message() * @@ -1148,14 +1194,8 @@ static int spi_transfer_one_message(struct spi_controller *ctlr, if (msg->status != -EINPROGRESS) goto out; - if (xfer->delay_usecs) { - u16 us = xfer->delay_usecs; - - if (us <= 10) - udelay(us); - else - usleep_range(us, us + DIV_ROUND_UP(us, 10)); - } + if (xfer->delay_usecs) + _spi_transfer_delay_ns(xfer->delay_usecs * 1000); if (xfer->cs_change) { if (list_is_last(&xfer->transfer_list, @@ -1163,7 +1203,7 @@ static int spi_transfer_one_message(struct spi_controller *ctlr, keep_cs = true; } else { spi_set_cs(msg->spi, false); - udelay(10); + _spi_transfer_cs_change_delay(msg, xfer); spi_set_cs(msg->spi, true); } } @@ -3757,4 +3797,3 @@ err0: * include needing to have boardinfo data structures be much more public. */ postcore_initcall(spi_init); - -- cgit v1.2.2 From d5864e5bed96db7230da45463d6ae7af5b3b4399 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Sat, 23 Feb 2019 08:49:50 +0000 Subject: spi: core: allow defining time that cs is deasserted as a multiple of SCK Support setting a delay between cs assert and deassert as a multiple of spi clock length. Signed-off-by: Martin Sperl Signed-off-by: Mark Brown --- drivers/spi/spi.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/spi/spi.c') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 7e8ffe3fdc00..cfa3c3decb8a 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1111,6 +1111,7 @@ static void _spi_transfer_cs_change_delay(struct spi_message *msg, { u32 delay = xfer->cs_change_delay; u32 unit = xfer->cs_change_delay_unit; + u32 hz; /* return early on "fast" mode - for everything but USECS */ if (!delay && unit != SPI_DELAY_UNIT_USECS) @@ -1126,6 +1127,13 @@ static void _spi_transfer_cs_change_delay(struct spi_message *msg, break; case SPI_DELAY_UNIT_NSECS: /* nothing to do here */ break; + case SPI_DELAY_UNIT_SCK: + /* if there is no effective speed know, then approximate + * by underestimating with half the requested hz + */ + hz = xfer->effective_speed_hz ?: xfer->speed_hz / 2; + delay *= DIV_ROUND_UP(1000000000, hz); + break; default: dev_err_once(&msg->spi->dev, "Use of unsupported delay unit %i, using default of 10us\n", -- cgit v1.2.2 From 5d7e2b5ed5858fe739d4cb8ad22dcce7bd9dbe7b Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Sat, 23 Feb 2019 08:49:49 +0000 Subject: spi: core: allow reporting the effectivly used speed_hz for a transfer Provide a means for the spi bus driver to report the effectively used spi clock frequency used for each spi_transfer. Signed-off-by: Martin Sperl Signed-off-by: Mark Brown --- drivers/spi/spi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/spi/spi.c') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index cfa3c3decb8a..e9bf0c23da50 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -3126,6 +3126,7 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) */ message->frame_length = 0; list_for_each_entry(xfer, &message->transfers, transfer_list) { + xfer->effective_speed_hz = 0; message->frame_length += xfer->len; if (!xfer->bits_per_word) xfer->bits_per_word = spi->bits_per_word; -- cgit v1.2.2 From aef9752274f4045b0dab577e113da63c96832f77 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 7 Jun 2019 13:48:45 -0500 Subject: spi: Use struct_size() helper One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct spi_replaced_transfers { ... struct spi_transfer inserted_transfers[]; }; Make use of the struct_size() helper instead of an open-coded version in order to avoid any potential type mistakes. So, replace the following form: insert * sizeof(struct spi_transfer) + sizeof(struct spi_replaced_transfers) with: struct_size(rxfer, inserted_transfers, insert) This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- drivers/spi/spi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/spi/spi.c') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 232ed4bb8fca..bced6876de79 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2750,8 +2750,7 @@ struct spi_replaced_transfers *spi_replace_transfers( /* allocate the structure using spi_res */ rxfer = spi_res_alloc(msg->spi, __spi_replace_transfers_release, - insert * sizeof(struct spi_transfer) - + sizeof(struct spi_replaced_transfers) + struct_size(rxfer, inserted_transfers, insert) + extradatasize, gfp); if (!rxfer) -- cgit v1.2.2 From 4c3c59544f33e97cf8557f27e05a9904ead16363 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 30 May 2019 13:16:34 +0200 Subject: spi/acpi: enumerate all SPI slaves in the namespace Currently, the ACPI enumeration that takes place when registering a SPI master only considers immediate child devices in the ACPI namespace, rather than checking the ResourceSource field in the SpiSerialBus() resource descriptor. This is incorrect: SPI slaves could reside anywhere in the ACPI namespace, and so we should enumerate the entire namespace and look for any device that refers to the newly registered SPI master in its resource descriptor. So refactor the existing code and use a lookup structure so that allocating the SPI device structure is deferred until we have identified the device as an actual child of the controller. This approach is loosely based on the way the I2C subsystem handles ACPI enumeration. Note that Apple x86 hardware does not rely on SpiSerialBus() resources in _CRS but uses nested devices below the controller's device node in the ACPI namespace, with a special set of device properties. This means we have to take care to only parse those properties for device nodes that are direct children of the controller node. Cc: Mika Westerberg Cc: linux-spi@vger.kernel.org Cc: broonie@kernel.org Cc: andy.shevchenko@gmail.com Cc: masahisa.kojima@linaro.org Cc: "Rafael J. Wysocki" Cc: Jarkko Nikula Cc: linux-acpi@vger.kernel.org Cc: Lukas Wunner Signed-off-by: Ard Biesheuvel Signed-off-by: Mark Brown --- drivers/spi/spi.c | 103 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 72 insertions(+), 31 deletions(-) (limited to 'drivers/spi/spi.c') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index bced6876de79..498f9b7419a4 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1852,9 +1852,18 @@ static void of_register_spi_devices(struct spi_controller *ctlr) { } #endif #ifdef CONFIG_ACPI -static void acpi_spi_parse_apple_properties(struct spi_device *spi) +struct acpi_spi_lookup { + struct spi_controller *ctlr; + u32 max_speed_hz; + u32 mode; + int irq; + u8 bits_per_word; + u8 chip_select; +}; + +static void acpi_spi_parse_apple_properties(struct acpi_device *dev, + struct acpi_spi_lookup *lookup) { - struct acpi_device *dev = ACPI_COMPANION(&spi->dev); const union acpi_object *obj; if (!x86_apple_machine) @@ -1862,35 +1871,46 @@ static void acpi_spi_parse_apple_properties(struct spi_device *spi) if (!acpi_dev_get_property(dev, "spiSclkPeriod", ACPI_TYPE_BUFFER, &obj) && obj->buffer.length >= 4) - spi->max_speed_hz = NSEC_PER_SEC / *(u32 *)obj->buffer.pointer; + lookup->max_speed_hz = NSEC_PER_SEC / *(u32 *)obj->buffer.pointer; if (!acpi_dev_get_property(dev, "spiWordSize", ACPI_TYPE_BUFFER, &obj) && obj->buffer.length == 8) - spi->bits_per_word = *(u64 *)obj->buffer.pointer; + lookup->bits_per_word = *(u64 *)obj->buffer.pointer; if (!acpi_dev_get_property(dev, "spiBitOrder", ACPI_TYPE_BUFFER, &obj) && obj->buffer.length == 8 && !*(u64 *)obj->buffer.pointer) - spi->mode |= SPI_LSB_FIRST; + lookup->mode |= SPI_LSB_FIRST; if (!acpi_dev_get_property(dev, "spiSPO", ACPI_TYPE_BUFFER, &obj) && obj->buffer.length == 8 && *(u64 *)obj->buffer.pointer) - spi->mode |= SPI_CPOL; + lookup->mode |= SPI_CPOL; if (!acpi_dev_get_property(dev, "spiSPH", ACPI_TYPE_BUFFER, &obj) && obj->buffer.length == 8 && *(u64 *)obj->buffer.pointer) - spi->mode |= SPI_CPHA; + lookup->mode |= SPI_CPHA; } static int acpi_spi_add_resource(struct acpi_resource *ares, void *data) { - struct spi_device *spi = data; - struct spi_controller *ctlr = spi->controller; + struct acpi_spi_lookup *lookup = data; + struct spi_controller *ctlr = lookup->ctlr; if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) { struct acpi_resource_spi_serialbus *sb; + acpi_handle parent_handle; + acpi_status status; sb = &ares->data.spi_serial_bus; if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_SPI) { + + status = acpi_get_handle(NULL, + sb->resource_source.string_ptr, + &parent_handle); + + if (!status || + ACPI_HANDLE(ctlr->dev.parent) != parent_handle) + return -ENODEV; + /* * ACPI DeviceSelection numbering is handled by the * host controller driver in Windows and can vary @@ -1903,25 +1923,25 @@ static int acpi_spi_add_resource(struct acpi_resource *ares, void *data) sb->device_selection); if (cs < 0) return cs; - spi->chip_select = cs; + lookup->chip_select = cs; } else { - spi->chip_select = sb->device_selection; + lookup->chip_select = sb->device_selection; } - spi->max_speed_hz = sb->connection_speed; + lookup->max_speed_hz = sb->connection_speed; if (sb->clock_phase == ACPI_SPI_SECOND_PHASE) - spi->mode |= SPI_CPHA; + lookup->mode |= SPI_CPHA; if (sb->clock_polarity == ACPI_SPI_START_HIGH) - spi->mode |= SPI_CPOL; + lookup->mode |= SPI_CPOL; if (sb->device_polarity == ACPI_SPI_ACTIVE_HIGH) - spi->mode |= SPI_CS_HIGH; + lookup->mode |= SPI_CS_HIGH; } - } else if (spi->irq < 0) { + } else if (lookup->irq < 0) { struct resource r; if (acpi_dev_resource_interrupt(ares, 0, &r)) - spi->irq = r.start; + lookup->irq = r.start; } /* Always tell the ACPI core to skip this resource */ @@ -1931,7 +1951,9 @@ static int acpi_spi_add_resource(struct acpi_resource *ares, void *data) static acpi_status acpi_register_spi_device(struct spi_controller *ctlr, struct acpi_device *adev) { + acpi_handle parent_handle = NULL; struct list_head resource_list; + struct acpi_spi_lookup lookup; struct spi_device *spi; int ret; @@ -1939,28 +1961,44 @@ static acpi_status acpi_register_spi_device(struct spi_controller *ctlr, acpi_device_enumerated(adev)) return AE_OK; - spi = spi_alloc_device(ctlr); - if (!spi) { - dev_err(&ctlr->dev, "failed to allocate SPI device for %s\n", - dev_name(&adev->dev)); - return AE_NO_MEMORY; - } - - ACPI_COMPANION_SET(&spi->dev, adev); - spi->irq = -1; + lookup.ctlr = ctlr; + lookup.mode = 0; + lookup.bits_per_word = 0; + lookup.irq = -1; INIT_LIST_HEAD(&resource_list); ret = acpi_dev_get_resources(adev, &resource_list, - acpi_spi_add_resource, spi); + acpi_spi_add_resource, &lookup); acpi_dev_free_resource_list(&resource_list); - acpi_spi_parse_apple_properties(spi); + if (ret < 0) + /* found SPI in _CRS but it points to another controller */ + return AE_OK; - if (ret < 0 || !spi->max_speed_hz) { - spi_dev_put(spi); + if (!lookup.max_speed_hz && + !ACPI_FAILURE(acpi_get_parent(adev->handle, &parent_handle)) && + ACPI_HANDLE(ctlr->dev.parent) == parent_handle) { + /* Apple does not use _CRS but nested devices for SPI slaves */ + acpi_spi_parse_apple_properties(adev, &lookup); + } + + if (!lookup.max_speed_hz) return AE_OK; + + spi = spi_alloc_device(ctlr); + if (!spi) { + dev_err(&ctlr->dev, "failed to allocate SPI device for %s\n", + dev_name(&adev->dev)); + return AE_NO_MEMORY; } + ACPI_COMPANION_SET(&spi->dev, adev); + spi->max_speed_hz = lookup.max_speed_hz; + spi->mode = lookup.mode; + spi->irq = lookup.irq; + spi->bits_per_word = lookup.bits_per_word; + spi->chip_select = lookup.chip_select; + acpi_set_modalias(adev, acpi_device_hid(adev), spi->modalias, sizeof(spi->modalias)); @@ -1992,6 +2030,8 @@ static acpi_status acpi_spi_add_device(acpi_handle handle, u32 level, return acpi_register_spi_device(ctlr, adev); } +#define SPI_ACPI_ENUMERATE_MAX_DEPTH 32 + static void acpi_register_spi_devices(struct spi_controller *ctlr) { acpi_status status; @@ -2001,7 +2041,8 @@ static void acpi_register_spi_devices(struct spi_controller *ctlr) if (!handle) return; - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + SPI_ACPI_ENUMERATE_MAX_DEPTH, acpi_spi_add_device, NULL, ctlr, NULL); if (ACPI_FAILURE(status)) dev_warn(&ctlr->dev, "failed to enumerate SPI slaves\n"); -- cgit v1.2.2 From ebc37af5e0a134355ea2b62ed4141458bdbd5389 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sat, 15 Jun 2019 20:41:35 +0300 Subject: spi: No need to assign dummy value in spi_unregister_controller() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The device_for_each_child() doesn't require the returned value to be checked. Thus, drop the dummy variable completely and have no warning anymore: drivers/spi/spi.c: In function ‘spi_unregister_controller’: drivers/spi/spi.c:2480:6: warning: variable ‘dummy’ set but not used [-Wunused-but-set-variable] int dummy; ^~~~~ Signed-off-by: Andy Shevchenko Signed-off-by: Mark Brown --- drivers/spi/spi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/spi/spi.c') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 498f9b7419a4..e71881afe475 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2559,7 +2559,6 @@ void spi_unregister_controller(struct spi_controller *ctlr) { struct spi_controller *found; int id = ctlr->bus_num; - int dummy; /* First make sure that this controller was ever added */ mutex_lock(&board_lock); @@ -2573,7 +2572,7 @@ void spi_unregister_controller(struct spi_controller *ctlr) list_del(&ctlr->list); mutex_unlock(&board_lock); - dummy = device_for_each_child(&ctlr->dev, NULL, __unregister); + device_for_each_child(&ctlr->dev, NULL, __unregister); device_unregister(&ctlr->dev); /* free bus id */ mutex_lock(&board_lock); -- cgit v1.2.2 From f56943699463478617b235930252261d5277bd46 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Tue, 18 Jun 2019 19:28:18 +0300 Subject: spi: don't open code list_for_each_entry_safe_reverse() The loop declaration in function spi_res_release() can be simplified by reusing the common list_for_each_entry_safe_reverse() helper macro. Signed-off-by: Vladimir Zapolskiy Signed-off-by: Mark Brown --- drivers/spi/spi.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/spi/spi.c') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index e71881afe475..01a40bcfc352 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2721,12 +2721,9 @@ EXPORT_SYMBOL_GPL(spi_res_add); */ void spi_res_release(struct spi_controller *ctlr, struct spi_message *message) { - struct spi_res *res; - - while (!list_empty(&message->resources)) { - res = list_last_entry(&message->resources, - struct spi_res, entry); + struct spi_res *res, *tmp; + list_for_each_entry_safe_reverse(res, tmp, &message->resources, entry) { if (res->release) res->release(ctlr, message, res->data); -- cgit v1.2.2 From b5e3cf410b486a2415ff09b12f3ef18aba9f53ff Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 19 Jun 2019 11:52:54 +0200 Subject: spi/acpi: fix incorrect ACPI parent check The ACPI device object parsing code for SPI slaves enumerates the entire ACPI namespace to look for devices that refer to the master in question via the 'resource_source' field in the 'SPISerialBus' resource. If that field does not refer to a valid ACPI device or if it refers to the wrong SPI master, we should disregard the device. Current, the valid device check is wrong, since it gets the polarity of 'status' wrong. This could cause issues if the 'resource_source' field is bogus but parent_handle happens to refer to the correct master (which is not entirely imaginary since this code runs in a loop) So test for ACPI_FAILURE() instead, to make the code more self explanatory. Fixes: 4c3c59544f33 ("spi/acpi: enumerate all SPI slaves in the namespace") Reported-by: kbuild test robot Reported-by: Dan Carpenter Cc: Mika Westerberg Cc: andy.shevchenko@gmail.com Cc: masahisa.kojima@linaro.org Cc: "Rafael J. Wysocki" Cc: Jarkko Nikula Cc: linux-acpi@vger.kernel.org Cc: Lukas Wunner Signed-off-by: Ard Biesheuvel Acked-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/spi/spi.c') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 01a40bcfc352..a31e1e291335 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1907,7 +1907,7 @@ static int acpi_spi_add_resource(struct acpi_resource *ares, void *data) sb->resource_source.string_ptr, &parent_handle); - if (!status || + if (ACPI_FAILURE(status) || ACPI_HANDLE(ctlr->dev.parent) != parent_handle) return -ENODEV; -- cgit v1.2.2 From f9481b08220d7dc1ff21e296a330ee8b721b44e4 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Wed, 19 Jun 2019 14:38:28 +0000 Subject: spi: fix ctrl->num_chipselect constraint at91sam9g25ek showed the following error at probe: atmel_spi f0000000.spi: Using dma0chan2 (tx) and dma0chan3 (rx) for DMA transfers atmel_spi: probe of f0000000.spi failed with error -22 Commit 0a919ae49223 ("spi: Don't call spi_get_gpio_descs() before device name is set") moved the calling of spi_get_gpio_descs() after ctrl->dev is set, but didn't move the !ctrl->num_chipselect check. When there are chip selects in the device tree, the spi-atmel driver lets the SPI core discover them when registering the SPI master. The ctrl->num_chipselect is thus expected to be set by spi_get_gpio_descs(). Move the !ctlr->num_chipselect after spi_get_gpio_descs() as it was before the aforementioned commit. While touching this block, get rid of the explicit comparison with 0 and update the commenting style. Fixes: 0a919ae49223 ("spi: Don't call spi_get_gpio_descs() before device name is set") Signed-off-by: Tudor Ambarus Signed-off-by: Mark Brown --- drivers/spi/spi.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/spi/spi.c') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index a31e1e291335..80d2d14f6294 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2375,11 +2375,6 @@ int spi_register_controller(struct spi_controller *ctlr) if (status) return status; - /* even if it's just one always-selected device, there must - * be at least one chipselect - */ - if (ctlr->num_chipselect == 0) - return -EINVAL; if (ctlr->bus_num >= 0) { /* devices with a fixed bus num must check-in with the num */ mutex_lock(&board_lock); @@ -2450,6 +2445,13 @@ int spi_register_controller(struct spi_controller *ctlr) } } + /* + * Even if it's just one always-selected device, there must + * be at least one chipselect. + */ + if (!ctlr->num_chipselect) + return -EINVAL; + status = device_add(&ctlr->dev); if (status < 0) { /* free bus id */ -- cgit v1.2.2 From b28944c6f6d3951f0c8f23f90c83ef741d30bfca Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 20 Jun 2019 14:36:49 +0200 Subject: spi/acpi: avoid spurious matches during slave enumeration In the new SPI ACPI slave enumeration code, we use the value of lookup.max_speed_khz as a flag to decide whether a match occurred. However, doing so only makes sense if we initialize its value to zero beforehand, or otherwise, random junk from the stack will cause spurious matches. So zero initialize the lookup struct fully, and only set the non-zero members explicitly. Fixes: 4c3c59544f33 ("spi/acpi: enumerate all SPI slaves in the namespace") Cc: Mika Westerberg Cc: andy.shevchenko@gmail.com Cc: masahisa.kojima@linaro.org Cc: "Rafael J. Wysocki" Cc: Jarkko Nikula Cc: linux-acpi@vger.kernel.org Cc: Lukas Wunner Signed-off-by: Ard Biesheuvel Tested-by: Jarkko Nikula Acked-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/spi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/spi/spi.c') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 80d2d14f6294..81e4d9f7c0f4 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1953,7 +1953,7 @@ static acpi_status acpi_register_spi_device(struct spi_controller *ctlr, { acpi_handle parent_handle = NULL; struct list_head resource_list; - struct acpi_spi_lookup lookup; + struct acpi_spi_lookup lookup = {}; struct spi_device *spi; int ret; @@ -1962,8 +1962,6 @@ static acpi_status acpi_register_spi_device(struct spi_controller *ctlr, return AE_OK; lookup.ctlr = ctlr; - lookup.mode = 0; - lookup.bits_per_word = 0; lookup.irq = -1; INIT_LIST_HEAD(&resource_list); -- cgit v1.2.2