Unverified Commit 6b7a9710 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!9314 spi: Fix deadlock when adding SPI controllers on SPI buses

Merge Pull Request from: @ci-robot 
 
PR sync from: Zeng Heng <zengheng4@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/EOKL6R5JT5CVLCLZGM3OIVTRO5TTL3WM/ 
Mark Brown (1):
  spi: Fix deadlock when adding SPI controllers on SPI buses

Zeng Heng (1):
  spi: fix kabi breakage in struct spi_controller


--
2.25.1
 
https://gitee.com/src-openeuler/kernel/issues/I9RBZI 
 
Link:https://gitee.com/openeuler/kernel/pulls/9314

 

Reviewed-by: default avatarWeilong Chen <chenweilong@huawei.com>
Reviewed-by: default avatarWei Li <liwei391@huawei.com>
Reviewed-by: default avatarLiu YongQiang <liuyongqiang13@huawei.com>
Signed-off-by: default avatarZhang Changzhong <zhangchangzhong@huawei.com>
parents a691480d 53bc3e1f
Loading
Loading
Loading
Loading
+27 −16
Original line number Diff line number Diff line
@@ -433,12 +433,6 @@ static LIST_HEAD(spi_controller_list);
 */
static DEFINE_MUTEX(board_lock);

/*
 * Prevents addition of devices with same chip select and
 * addition of devices below an unregistering controller.
 */
static DEFINE_MUTEX(spi_add_lock);

/**
 * spi_alloc_device - Allocate a new SPI device
 * @ctlr: Controller to which device is connected
@@ -535,7 +529,7 @@ int spi_add_device(struct spi_device *spi)
	 * chipselect **BEFORE** we call setup(), else we'll trash
	 * its configuration.  Lock against concurrent add() calls.
	 */
	mutex_lock(&spi_add_lock);
	mutex_lock(ctlr->dev.add_lock);

	status = bus_for_each_dev(&spi_bus_type, NULL, spi, spi_dev_check);
	if (status) {
@@ -574,7 +568,7 @@ int spi_add_device(struct spi_device *spi)
		dev_dbg(dev, "registered child %s\n", dev_name(&spi->dev));

done:
	mutex_unlock(&spi_add_lock);
	mutex_unlock(ctlr->dev.add_lock);
	return status;
}
EXPORT_SYMBOL_GPL(spi_add_device);
@@ -2158,6 +2152,10 @@ int spi_register_controller(struct spi_controller *ctlr)
			return status;
	}

	ctlr->dev.add_lock = kmalloc(sizeof(struct mutex), GFP_KERNEL);
	if (!ctlr->dev.add_lock)
		return -ENOMEM;

	/* even if it's just one always-selected device, there must
	 * be at least one chipselect
	 */
@@ -2169,8 +2167,10 @@ int spi_register_controller(struct spi_controller *ctlr)
		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;
		if (WARN(id < 0, "couldn't get idr")) {
			status = (id == -ENOSPC) ? -EBUSY : id;
			goto done;
		}
		ctlr->bus_num = id;
	} else if (ctlr->dev.of_node) {
		/* allocate dynamic bus number using Linux idr */
@@ -2181,8 +2181,10 @@ int spi_register_controller(struct spi_controller *ctlr)
			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;
			if (WARN(id < 0, "couldn't get idr")) {
				status = (id == -ENOSPC) ? -EBUSY : id;
				goto done;
			}
		}
	}
	if (ctlr->bus_num < 0) {
@@ -2196,8 +2198,11 @@ int spi_register_controller(struct spi_controller *ctlr)
		id = idr_alloc(&spi_master_idr, ctlr, first_dynamic,
			       0, GFP_KERNEL);
		mutex_unlock(&board_lock);
		if (WARN(id < 0, "couldn't get idr"))
			return id;
		if (WARN(id < 0, "couldn't get idr")) {
			status = id;
			goto done;
		}

		ctlr->bus_num = id;
	}
	INIT_LIST_HEAD(&ctlr->queue);
@@ -2205,6 +2210,7 @@ int spi_register_controller(struct spi_controller *ctlr)
	spin_lock_init(&ctlr->bus_lock_spinlock);
	mutex_init(&ctlr->bus_lock_mutex);
	mutex_init(&ctlr->io_mutex);
	mutex_init(ctlr->dev.add_lock);
	ctlr->bus_lock_flag = 0;
	init_completion(&ctlr->xfer_completion);
	if (!ctlr->max_dma_len)
@@ -2256,7 +2262,10 @@ int spi_register_controller(struct spi_controller *ctlr)
	/* Register devices from the device tree and ACPI */
	of_register_spi_devices(ctlr);
	acpi_register_spi_devices(ctlr);
	return status;

done:
	kfree(ctlr->dev.add_lock);
	return status;
}
EXPORT_SYMBOL_GPL(spi_register_controller);
@@ -2326,7 +2335,7 @@ void spi_unregister_controller(struct spi_controller *ctlr)

	/* Prevent addition of new devices, unregister existing ones */
	if (IS_ENABLED(CONFIG_SPI_DYNAMIC))
		mutex_lock(&spi_add_lock);
		mutex_lock(ctlr->dev.add_lock);

	device_for_each_child(&ctlr->dev, NULL, __unregister);

@@ -2350,7 +2359,9 @@ void spi_unregister_controller(struct spi_controller *ctlr)
	mutex_unlock(&board_lock);

	if (IS_ENABLED(CONFIG_SPI_DYNAMIC))
		mutex_unlock(&spi_add_lock);
		mutex_unlock(ctlr->dev.add_lock);

	kfree(ctlr->dev.add_lock);
}
EXPORT_SYMBOL_GPL(spi_unregister_controller);

+12 −0
Original line number Diff line number Diff line
@@ -1078,7 +1078,19 @@ struct device {
#else
	KABI_RESERVE(1)
#endif
#ifdef CONFIG_SPI_MASTER
#ifndef __GENKSYMS__
	/*
	 * Reserved for struct spi_controller.
	 * Used to avoid adding the same CS twice.
	 */
	struct mutex *add_lock;
#else
	KABI_RESERVE(2)
#endif
#else
	KABI_RESERVE(2)
#endif
	KABI_RESERVE(3)
	KABI_RESERVE(4)
	KABI_RESERVE(5)