Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

spi: keep track of number of chipselects in spi_device

There are several places where we need to iterate over a device's
chipselect. To be able to do it efficiently, store the number of
chipselects in spi_device, like we do for controllers.

Since we now use a device supplied value, add a check to make sure it
isn't more than we can support.

Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
Link: https://patch.msgid.link/20250915183725.219473-3-jonas.gorski@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Jonas Gorski and committed by
Mark Brown
099f9421 188f6323

+24 -9
+21 -8
drivers/spi/spi.c
··· 586 586 spi->dev.bus = &spi_bus_type; 587 587 spi->dev.release = spidev_release; 588 588 spi->mode = ctlr->buswidth_override_bits; 589 + spi->num_chipselect = 1; 589 590 590 591 device_initialize(&spi->dev); 591 592 return spi; ··· 636 635 u8 idx_new; 637 636 638 637 cs = spi_get_chipselect(spi, idx); 639 - for (idx_new = new_idx; idx_new < SPI_CS_CNT_MAX; idx_new++) { 638 + for (idx_new = new_idx; idx_new < new_spi->num_chipselect; idx_new++) { 640 639 cs_new = spi_get_chipselect(new_spi, idx_new); 641 640 if (is_valid_cs(cs) && is_valid_cs(cs_new) && cs == cs_new) { 642 641 dev_err(dev, "chipselect %u already in use\n", cs_new); ··· 653 652 int status, idx; 654 653 655 654 if (spi->controller == new_spi->controller) { 656 - for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) { 655 + for (idx = 0; idx < spi->num_chipselect; idx++) { 657 656 status = spi_dev_check_cs(dev, spi, idx, new_spi, 0); 658 657 if (status) 659 658 return status; ··· 675 674 int status, idx; 676 675 u8 cs; 677 676 678 - for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) { 677 + if (spi->num_chipselect > SPI_CS_CNT_MAX) { 678 + dev_err(dev, "num_cs %d > max %d\n", spi->num_chipselect, 679 + SPI_CS_CNT_MAX); 680 + return -EOVERFLOW; 681 + } 682 + 683 + for (idx = 0; idx < spi->num_chipselect; idx++) { 679 684 /* Chipselects are numbered 0..max; validate. */ 680 685 cs = spi_get_chipselect(spi, idx); 681 686 if (is_valid_cs(cs) && cs >= ctlr->num_chipselect) { ··· 696 689 * For example, spi->chip_select[0] != spi->chip_select[1] and so on. 697 690 */ 698 691 if (!spi_controller_is_target(ctlr)) { 699 - for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) { 692 + for (idx = 0; idx < spi->num_chipselect; idx++) { 700 693 status = spi_dev_check_cs(dev, spi, idx, spi, idx + 1); 701 694 if (status) 702 695 return status; ··· 724 717 if (ctlr->cs_gpiods) { 725 718 u8 cs; 726 719 727 - for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) { 720 + for (idx = 0; idx < spi->num_chipselect; idx++) { 728 721 cs = spi_get_chipselect(spi, idx); 729 722 if (is_valid_cs(cs)) 730 723 spi_set_csgpiod(spi, idx, ctlr->cs_gpiods[cs]); ··· 1031 1024 1032 1025 /*-------------------------------------------------------------------------*/ 1033 1026 #define spi_for_each_valid_cs(spi, idx) \ 1034 - for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) \ 1027 + for (idx = 0; idx < spi->num_chipselect; idx++) \ 1035 1028 if (!(spi->cs_index_mask & BIT(idx))) {} else 1036 1029 1037 1030 static inline bool spi_is_last_cs(struct spi_device *spi) ··· 1087 1080 trace_spi_set_cs(spi, activate); 1088 1081 1089 1082 spi->controller->last_cs_index_mask = spi->cs_index_mask; 1090 - for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) 1091 - spi->controller->last_cs[idx] = enable ? spi_get_chipselect(spi, 0) : SPI_INVALID_CS; 1083 + for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) { 1084 + if (enable && idx < spi->num_chipselect) 1085 + spi->controller->last_cs[idx] = spi_get_chipselect(spi, 0); 1086 + else 1087 + spi->controller->last_cs[idx] = SPI_INVALID_CS; 1088 + } 1092 1089 1093 1090 spi->controller->last_cs_mode_high = spi->mode & SPI_CS_HIGH; 1094 1091 if (spi->controller->last_cs_mode_high) ··· 2463 2452 dev_err(&ctlr->dev, "SPI controller doesn't support multi CS\n"); 2464 2453 return -EINVAL; 2465 2454 } 2455 + 2456 + spi->num_chipselect = rc; 2466 2457 for (idx = 0; idx < rc; idx++) 2467 2458 spi_set_chipselect(spi, idx, cs[idx]); 2468 2459
+3 -1
include/linux/spi/spi.h
··· 170 170 * two delays will be added up. 171 171 * @chip_select: Array of physical chipselect, spi->chipselect[i] gives 172 172 * the corresponding physical CS for logical CS i. 173 + * @num_chipselect: Number of physical chipselects used. 173 174 * @cs_index_mask: Bit mask of the active chipselect(s) in the chipselect array 174 175 * @cs_gpiod: Array of GPIO descriptors of the corresponding chipselect lines 175 176 * (optional, NULL when not using a GPIO line) ··· 230 229 struct spi_delay cs_inactive; 231 230 232 231 u8 chip_select[SPI_CS_CNT_MAX]; 232 + u8 num_chipselect; 233 233 234 234 /* 235 235 * Bit mask of the chipselect(s) that the driver need to use from ··· 317 315 { 318 316 u8 idx; 319 317 320 - for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) { 318 + for (idx = 0; idx < spi->num_chipselect; idx++) { 321 319 if (spi_get_csgpiod(spi, idx)) 322 320 return true; 323 321 }