spi: spidev: Don't mangle max_speed_hz in underlying spi device
Currently spidev allows callers to set the default speed by overriding the
max_speed_hz in the underlying device. This achieves the immediate goal but
is not what devices expect and can easily lead to userspace trying to set
unsupported speeds and succeeding, apart from anything else drivers can't
set a limit on the speed using max_speed_hz as they'd expect and any other
devices on the bus will be affected.
Instead store the default speed in the spidev struct and fill this in on
each transfer.
Signed-off-by: Mark Brown <broonie@kernel.org>
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index e50039f..6941e04 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -87,6 +87,7 @@
unsigned users;
u8 *tx_buffer;
u8 *rx_buffer;
+ u32 speed_hz;
};
static LIST_HEAD(device_list);
@@ -138,6 +139,7 @@
struct spi_transfer t = {
.tx_buf = spidev->tx_buffer,
.len = len,
+ .speed_hz = spidev->speed_hz,
};
struct spi_message m;
@@ -152,6 +154,7 @@
struct spi_transfer t = {
.rx_buf = spidev->rx_buffer,
.len = len,
+ .speed_hz = spidev->speed_hz,
};
struct spi_message m;
@@ -274,6 +277,8 @@
k_tmp->bits_per_word = u_tmp->bits_per_word;
k_tmp->delay_usecs = u_tmp->delay_usecs;
k_tmp->speed_hz = u_tmp->speed_hz;
+ if (!k_tmp->speed_hz)
+ k_tmp->speed_hz = spidev->speed_hz;
#ifdef VERBOSE
dev_dbg(&spidev->spi->dev,
" xfer len %zd %s%s%s%dbits %u usec %uHz\n",
@@ -377,7 +382,7 @@
retval = __put_user(spi->bits_per_word, (__u8 __user *)arg);
break;
case SPI_IOC_RD_MAX_SPEED_HZ:
- retval = __put_user(spi->max_speed_hz, (__u32 __user *)arg);
+ retval = __put_user(spidev->speed_hz, (__u32 __user *)arg);
break;
/* write requests */
@@ -441,10 +446,11 @@
spi->max_speed_hz = tmp;
retval = spi_setup(spi);
- if (retval < 0)
- spi->max_speed_hz = save;
+ if (retval >= 0)
+ spidev->speed_hz = tmp;
else
dev_dbg(&spi->dev, "%d Hz (max)\n", tmp);
+ spi->max_speed_hz = save;
}
break;
@@ -570,6 +576,8 @@
kfree(spidev->rx_buffer);
spidev->rx_buffer = NULL;
+ spidev->speed_hz = spidev->spi->max_speed_hz;
+
/* ... after we unbound from the underlying device? */
spin_lock_irq(&spidev->spi_lock);
dofree = (spidev->spi == NULL);
@@ -650,6 +658,8 @@
}
mutex_unlock(&device_list_lock);
+ spidev->speed_hz = spi->max_speed_hz;
+
if (status == 0)
spi_set_drvdata(spi, spidev);
else