Unverified Commit f8f5a7c9 authored by Mark Brown's avatar Mark Brown
Browse files

spi: Merge fixes

The automated merge for the spidev locking fixes is going wrong and
merging the unlock twice.
parents 7c62a227 35bba23e
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -177,7 +177,10 @@
#define CDNS_XSPI_CMD_FLD_DSEQ_CMD_3(op) ( \
	FIELD_PREP(CDNS_XSPI_CMD_DSEQ_R3_DCNT_H, \
		((op)->data.nbytes >> 16) & 0xffff) | \
	FIELD_PREP(CDNS_XSPI_CMD_DSEQ_R3_NUM_OF_DUMMY, (op)->dummy.nbytes * 8))
	FIELD_PREP(CDNS_XSPI_CMD_DSEQ_R3_NUM_OF_DUMMY, \
		  (op)->dummy.buswidth != 0 ? \
		  (((op)->dummy.nbytes * 8) / (op)->dummy.buswidth) : \
		  0))

#define CDNS_XSPI_CMD_FLD_DSEQ_CMD_4(op, chipsel) ( \
	FIELD_PREP(CDNS_XSPI_CMD_DSEQ_R4_BANK, chipsel) | \
+1 −1
Original line number Diff line number Diff line
@@ -366,7 +366,7 @@ static void dw_spi_irq_setup(struct dw_spi *dws)
	 * will be adjusted at the final stage of the IRQ-based SPI transfer
	 * execution so not to lose the leftover of the incoming data.
	 */
	level = min_t(u16, dws->fifo_len / 2, dws->tx_len);
	level = min_t(unsigned int, dws->fifo_len / 2, dws->tx_len);
	dw_writel(dws, DW_SPI_TXFTLR, level);
	dw_writel(dws, DW_SPI_RXFTLR, level - 1);

+5 −7
Original line number Diff line number Diff line
@@ -1253,6 +1253,11 @@ static int mtk_spi_probe(struct platform_device *pdev)
		dev_notice(dev, "SPI dma_set_mask(%d) failed, ret:%d\n",
			   addr_bits, ret);

	ret = devm_request_irq(dev, irq, mtk_spi_interrupt,
			       IRQF_TRIGGER_NONE, dev_name(dev), master);
	if (ret)
		return dev_err_probe(dev, ret, "failed to register irq\n");

	pm_runtime_enable(dev);

	ret = devm_spi_register_master(dev, master);
@@ -1261,13 +1266,6 @@ static int mtk_spi_probe(struct platform_device *pdev)
		return dev_err_probe(dev, ret, "failed to register master\n");
	}

	ret = devm_request_irq(dev, irq, mtk_spi_interrupt,
			       IRQF_TRIGGER_NONE, dev_name(dev), master);
	if (ret) {
		pm_runtime_disable(dev);
		return dev_err_probe(dev, ret, "failed to register irq\n");
	}

	return 0;
}

+34 −23
Original line number Diff line number Diff line
@@ -68,7 +68,7 @@ static_assert(N_SPI_MINORS > 0 && N_SPI_MINORS <= 256);

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

@@ -89,24 +89,35 @@ 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);

	mutex_unlock(&spidev->spi_lock);
	return status;
}

@@ -294,7 +305,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;

@@ -359,12 +370,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;
@@ -508,6 +519,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;
}

@@ -529,12 +541,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);
@@ -561,6 +573,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;
}

@@ -601,7 +614,6 @@ static int spidev_open(struct inode *inode, struct file *filp)
	if (!spidev->tx_buffer) {
		spidev->tx_buffer = kmalloc(bufsiz, GFP_KERNEL);
		if (!spidev->tx_buffer) {
			dev_dbg(&spidev->spi->dev, "open/ENOMEM\n");
			status = -ENOMEM;
			goto err_find_dev;
		}
@@ -610,7 +622,6 @@ static int spidev_open(struct inode *inode, struct file *filp)
	if (!spidev->rx_buffer) {
		spidev->rx_buffer = kmalloc(bufsiz, GFP_KERNEL);
		if (!spidev->rx_buffer) {
			dev_dbg(&spidev->spi->dev, "open/ENOMEM\n");
			status = -ENOMEM;
			goto err_alloc_rx_buf;
		}
@@ -640,10 +651,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--;
@@ -780,7 +791,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);
@@ -825,9 +836,9 @@ static void 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);