mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-07 21:53:44 +00:00
spi: Fixes for v6.2
There's several things in this pull request: - Fixes for long standing issues with accesses to spidev->spi during teardown in the spidev userspace driver. - Rename the newly added spi-cs-setup-ns DT property to be more in line with our other delay properties before it becomes ABI. - A few driver specific fixes. -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAmO+xWEACgkQJNaLcl1U h9C3OAf/Zuyjft9vo0U6nxLLFEpEHCFVkhUZ+oO82iIeHPi7pfWq+9dNGut1s28H mCP8EobJ0eU2VFcOAwvW4MVPnYw2wC1uLKzBvZOzfE9jEPM/TvpfCaKWM9Rwzfir o172dWTNnGGxKYcyC9JHfcLW/1au9XPwYWjGcX1T3I7c4vQyVTwxPV6fC6x9gVe2 5eQTxntIfS9uu2tGYzUAVhklJWLIB3pjU/NUMAqFt3wsKVFl217MquMt3RHnr44M bJSOqi0GsNuGg9gsSV4epgT8wY9oW3Ch7PoBs+VyfwHY2byZdYLTCUBXaZOcwUDT 89CxuJ7OqVorQJsRcdfzFumdZjXtUA== =jcZ7 -----END PGP SIGNATURE----- Merge tag 'spi-fix-v6.2-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi Pull spi fixes from Mark Brown: - Fixes for long standing issues with accesses to spidev->spi during teardown in the spidev userspace driver. - Rename the newly added spi-cs-setup-ns DT property to be more in line with our other delay properties before it becomes ABI. - A few driver specific fixes. * tag 'spi-fix-v6.2-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: spi: spidev: remove debug messages that access spidev->spi without locking spi: spidev: fix a race condition when accessing spidev->spi spi: Rename spi-cs-setup-ns property to spi-cs-setup-delay-ns spi: dt-bindings: Rename spi-cs-setup-ns to spi-cs-setup-delay-ns spi: cadence: Fix busy cycles calculation spi: mediatek: Enable irq before the spi registration
This commit is contained in:
commit
c757fc92a3
@ -44,9 +44,9 @@ properties:
|
||||
description:
|
||||
Maximum SPI clocking speed of the device in Hz.
|
||||
|
||||
spi-cs-setup-ns:
|
||||
spi-cs-setup-delay-ns:
|
||||
description:
|
||||
Delay in nanosecods to be introduced by the controller after CS is
|
||||
Delay in nanoseconds to be introduced by the controller after CS is
|
||||
asserted.
|
||||
|
||||
spi-rx-bus-width:
|
||||
|
@ -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) | \
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -2310,7 +2310,7 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
|
||||
if (!of_property_read_u32(nc, "spi-max-frequency", &value))
|
||||
spi->max_speed_hz = value;
|
||||
|
||||
if (!of_property_read_u16(nc, "spi-cs-setup-ns", &cs_setup)) {
|
||||
if (!of_property_read_u16(nc, "spi-cs-setup-delay-ns", &cs_setup)) {
|
||||
spi->cs_setup.value = cs_setup;
|
||||
spi->cs_setup.unit = SPI_DELAY_UNIT_NSECS;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
@ -95,9 +95,8 @@ spidev_sync(struct spidev_data *spidev, struct spi_message *message)
|
||||
int 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;
|
||||
@ -107,6 +106,7 @@ spidev_sync(struct spidev_data *spidev, struct spi_message *message)
|
||||
if (status == 0)
|
||||
status = message->actual_length;
|
||||
|
||||
mutex_unlock(&spidev->spi_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -359,12 +359,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 +508,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 +530,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 +562,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 +603,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 +611,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 +640,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--;
|
||||
@ -776,7 +776,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);
|
||||
@ -821,9 +821,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);
|
||||
|
Loading…
Reference in New Issue
Block a user