On 25.11.2013 12:16, Mark Brown wrote:
> You can't do this safely, setup() may be called while another transfer
> is active so reprogramming the hardware during setup() may disrupt an
> ongoing transfer. Remember, setup() can be triggered by client drivers
> calling spi_setup().
>
We are not reprogramming the HW there.
We just filling in the "template" value for the register used the next
time the control-register needs to get configured for a transfer.
If you look exactly you will find that
bcm2835_spi_start_transfer makes use of:
bs->cs_device_flags[spi->chip_select]
and bcm2835_spi_transfer_one uses the:
bs->cs_device_flags_idle
to fill in the "flags" and then writes to the control-register.
So if there would be a race between spi_setup and the functions above,
then the worsted case situation is that:
bs->cs_device_flags[spi->chip_select] and/or bs->cs_device_flags_idle
still contains the "old" flags.
But if this is a race, then it exists regardless of if there is a
spinlock protecting access of those variables or not, because then
it is a race between spi_transfer and spi_setup which is totally outside
of the driver.
If this is not safe enough, then we can wrap this structure in a spinlock.
To elaborate on the race: the way the problem presents itself the issue
is that if there is already a SPI message that is getting processed for
a device while there is a device with reverse polarity that has not been
set up yet, then both devices would assume they are being "addressed".
So until spi_setup is called for the device with reverse polarity, both
devices would be (potentially) changing the MISO line concurrently.
See also the comment in spi_add_device:
/* Drivers may modify this initial i/o setup, but will
* normally rely on the device being setup. Devices
* using SPI_CS_HIGH can't coexist well otherwise...
*/
status = spi_setup(spi);
and this call in spi_add_device is "protected" by the spi_add_lock mutex.
Any subsequent calls to spi_setup by a device driver should not
impact SPI_CS_HIGH so we do not change anything in these fields
at a later time anyway.
Martin
P.s: Maybe I miss something else?
Maybe that a device may change spi->mode while the driver is working?
If so then such an action would require a full bus-lock to avoid running
into a race with other device-drivers. Then the driver could reconfigure
the polarity settings on the device itself and then it can change
spi->mode and can call spi_setup and then finally release the bus lock.
Following the argument above we open up another can of worms:
As spi_async will fail on bus_lock there are drivers (as far as I have
seen) that would stop working if they were confronted with a short-term
bus_lock situation assuming the device itself went away.
And that in itself would be a rare race-condition that would only show
under certain circumstances.
So maybe instead of "failing" spi_async for this locked-bus case, we
should queue the messages in a separate queue in such a situation
instead to avoid the "error-handling" bugs in the drivers and schedule
those messages when releasing the bus-lock?
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html