summaryrefslogtreecommitdiff
path: root/drivers/spi
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2023-02-06 14:50:53 +0000
committerMark Brown <broonie@kernel.org>2023-02-06 14:50:53 +0000
commitf8f5a7c902776c18598963b359046ddf0728be84 (patch)
treeca9349fd3eb7da70ef103954532e865d10368e42 /drivers/spi
parent7c62a2279b9e88f2cbfa3b92dc49c8b7806c56f8 (diff)
parent35bba23e6732a593722c96cbe03ced627f0d8831 (diff)
spi: Merge fixes
The automated merge for the spidev locking fixes is going wrong and merging the unlock twice.
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi-cadence-xspi.c5
-rw-r--r--drivers/spi/spi-dw-core.c2
-rw-r--r--drivers/spi/spi-mt65xx.c12
-rw-r--r--drivers/spi/spidev.c57
4 files changed, 44 insertions, 32 deletions
diff --git a/drivers/spi/spi-cadence-xspi.c b/drivers/spi/spi-cadence-xspi.c
index 520b4cc69cdc..91db3c973167 100644
--- a/drivers/spi/spi-cadence-xspi.c
+++ b/drivers/spi/spi-cadence-xspi.c
@@ -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) | \
diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
index 99edddf9958b..c3bfb6c84cab 100644
--- a/drivers/spi/spi-dw-core.c
+++ b/drivers/spi/spi-dw-core.c
@@ -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);
diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
index 6de8360e5c2a..9eab6c20dbc5 100644
--- a/drivers/spi/spi-mt65xx.c
+++ b/drivers/spi/spi-mt65xx.c
@@ -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;
}
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index 898167f3b5af..f836567c631b 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -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;
@@ -90,23 +90,34 @@ 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);