Unverified Commit 0351cd89 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!11184 【OLK 5.10】spi: spidev some bugfix

Merge Pull Request from: @huwentao0417 
 
|commitID|commit message|冲突|
|---|---|---|
|1f4d2dd4|spi: pidev: fix a race condition when accessing spidev->spi|NA|
|eede42c9|spi: spidev: fix a recursive locking error|NA|
 
 
Link:https://gitee.com/openeuler/kernel/pulls/11184

 

Signed-off-by: default avatarYang Yingliang <yangyingliang@huawei.com>
parents 3e3bb79c da742a54
Loading
Loading
Loading
Loading
+33 −21
Original line number Diff line number Diff line
@@ -67,7 +67,7 @@ static DECLARE_BITMAP(minors, N_SPI_MINORS);

struct spidev_data {
	dev_t			devt;
	spinlock_t		spi_lock;
	struct mutex		spi_lock;
	struct spi_device	*spi;
	struct list_head	device_entry;

@@ -88,23 +88,33 @@ MODULE_PARM_DESC(bufsiz, "data bytes in biggest supported SPI message");

/*-------------------------------------------------------------------------*/

static ssize_t
spidev_sync_unlocked(struct spi_device *spi, struct spi_message *message)
{
	ssize_t status;

	status = spi_sync(spi, message);
	if (status == 0)
		status = message->actual_length;

	return status;
}

static ssize_t
spidev_sync(struct spidev_data *spidev, struct spi_message *message)
{
	int status;
	ssize_t status;
	struct spi_device *spi;

	spin_lock_irq(&spidev->spi_lock);
	mutex_lock(&spidev->spi_lock);
	spi = spidev->spi;
	spin_unlock_irq(&spidev->spi_lock);

	if (spi == NULL)
		status = -ESHUTDOWN;
	else
		status = spi_sync(spi, message);
		status = spidev_sync_unlocked(spi, message);

	if (status == 0)
		status = message->actual_length;
	mutex_unlock(&spidev->spi_lock);

	return status;
}
@@ -293,7 +303,7 @@ static int spidev_message(struct spidev_data *spidev,
		spi_message_add_tail(k_tmp, &msg);
	}

	status = spidev_sync(spidev, &msg);
	status = spidev_sync_unlocked(spidev->spi, &msg);
	if (status < 0)
		goto done;

@@ -358,12 +368,12 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
	 * we issue this ioctl.
	 */
	spidev = filp->private_data;
	spin_lock_irq(&spidev->spi_lock);
	mutex_lock(&spidev->spi_lock);
	spi = spi_dev_get(spidev->spi);
	spin_unlock_irq(&spidev->spi_lock);

	if (spi == NULL)
	if (spi == NULL) {
		mutex_unlock(&spidev->spi_lock);
		return -ESHUTDOWN;
	}

	/* use the buffer lock here for triple duty:
	 *  - prevent I/O (from us) so calling spi_setup() is safe;
@@ -500,6 +510,7 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)

	mutex_unlock(&spidev->buf_lock);
	spi_dev_put(spi);
	mutex_unlock(&spidev->spi_lock);
	return retval;
}

@@ -521,12 +532,12 @@ spidev_compat_ioc_message(struct file *filp, unsigned int cmd,
	 * we issue this ioctl.
	 */
	spidev = filp->private_data;
	spin_lock_irq(&spidev->spi_lock);
	mutex_lock(&spidev->spi_lock);
	spi = spi_dev_get(spidev->spi);
	spin_unlock_irq(&spidev->spi_lock);

	if (spi == NULL)
	if (spi == NULL) {
		mutex_unlock(&spidev->spi_lock);
		return -ESHUTDOWN;
	}

	/* SPI_IOC_MESSAGE needs the buffer locked "normally" */
	mutex_lock(&spidev->buf_lock);
@@ -553,6 +564,7 @@ spidev_compat_ioc_message(struct file *filp, unsigned int cmd,
done:
	mutex_unlock(&spidev->buf_lock);
	spi_dev_put(spi);
	mutex_unlock(&spidev->spi_lock);
	return retval;
}

@@ -629,10 +641,10 @@ static int spidev_release(struct inode *inode, struct file *filp)
	spidev = filp->private_data;
	filp->private_data = NULL;

	spin_lock_irq(&spidev->spi_lock);
	mutex_lock(&spidev->spi_lock);
	/* ... after we unbound from the underlying device? */
	dofree = (spidev->spi == NULL);
	spin_unlock_irq(&spidev->spi_lock);
	mutex_unlock(&spidev->spi_lock);

	/* last close? */
	spidev->users--;
@@ -759,7 +771,7 @@ static int spidev_probe(struct spi_device *spi)

	/* Initialize the driver data */
	spidev->spi = spi;
	spin_lock_init(&spidev->spi_lock);
	mutex_init(&spidev->spi_lock);
	mutex_init(&spidev->buf_lock);

	INIT_LIST_HEAD(&spidev->device_entry);
@@ -804,9 +816,9 @@ static int spidev_remove(struct spi_device *spi)
	/* prevent new opens */
	mutex_lock(&device_list_lock);
	/* make sure ops on existing fds can abort cleanly */
	spin_lock_irq(&spidev->spi_lock);
	mutex_lock(&spidev->spi_lock);
	spidev->spi = NULL;
	spin_unlock_irq(&spidev->spi_lock);
	mutex_unlock(&spidev->spi_lock);

	list_del(&spidev->device_entry);
	device_destroy(spidev_class, spidev->devt);