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: allow ancillary devices to share parent's chip selects

When registering an ancillary SPI device, the current code flags a chip
select conflict with the parent device. This happens because the
ancillary device intentionally uses one of the parent's chip selects,
but __spi_add_device() checks against all existing devices including
the parent.

Allow this by passing the parent device pointer to __spi_add_device()
and skipping the conflict check when the existing device is the parent.

Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
Reviewed-by: David Lechner <dlechner@baylibre.com>
Link: https://patch.msgid.link/bcb1eb34fc5e86fd5dbb4472ad1d3ea3cf3e9779.1770393792.git.antoniu.miclaus@analog.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Antoniu Miclaus and committed by
Mark Brown
ffef4123 6de23f81

+23 -6
+23 -6
drivers/spi/spi.c
··· 641 641 return 0; 642 642 } 643 643 644 + struct spi_dev_check_info { 645 + struct spi_device *new_spi; 646 + struct spi_device *parent; /* set for ancillary devices */ 647 + }; 648 + 644 649 static int spi_dev_check(struct device *dev, void *data) 645 650 { 646 651 struct spi_device *spi = to_spi_device(dev); 647 - struct spi_device *new_spi = data; 652 + struct spi_dev_check_info *info = data; 653 + struct spi_device *new_spi = info->new_spi; 648 654 int status, idx; 655 + 656 + /* 657 + * When registering an ancillary device, skip checking against the 658 + * parent device since the ancillary is intentionally using one of 659 + * the parent's chip selects. 660 + */ 661 + if (info->parent && spi == info->parent) 662 + return 0; 649 663 650 664 if (spi->controller == new_spi->controller) { 651 665 for (idx = 0; idx < spi->num_chipselect; idx++) { ··· 677 663 spi->controller->cleanup(spi); 678 664 } 679 665 680 - static int __spi_add_device(struct spi_device *spi) 666 + static int __spi_add_device(struct spi_device *spi, struct spi_device *parent) 681 667 { 682 668 struct spi_controller *ctlr = spi->controller; 683 669 struct device *dev = ctlr->dev.parent; 670 + struct spi_dev_check_info check_info; 684 671 int status, idx; 685 672 u8 cs; 686 673 ··· 725 710 * chipselect **BEFORE** we call setup(), else we'll trash 726 711 * its configuration. 727 712 */ 728 - status = bus_for_each_dev(&spi_bus_type, NULL, spi, spi_dev_check); 713 + check_info.new_spi = spi; 714 + check_info.parent = parent; 715 + status = bus_for_each_dev(&spi_bus_type, NULL, &check_info, spi_dev_check); 729 716 if (status) 730 717 return status; 731 718 ··· 789 772 spi_dev_set_name(spi); 790 773 791 774 mutex_lock(&ctlr->add_lock); 792 - status = __spi_add_device(spi); 775 + status = __spi_add_device(spi, NULL); 793 776 mutex_unlock(&ctlr->add_lock); 794 777 return status; 795 778 } ··· 2732 2715 2733 2716 WARN_ON(!mutex_is_locked(&ctlr->add_lock)); 2734 2717 2735 - /* Register the new device */ 2736 - rc = __spi_add_device(ancillary); 2718 + /* Register the new device, passing the parent to skip CS conflict check */ 2719 + rc = __spi_add_device(ancillary, spi); 2737 2720 if (rc) { 2738 2721 dev_err(&spi->dev, "failed to register ancillary device\n"); 2739 2722 goto err_out;