Message ID | 1410705908-20847-2-git-send-email-jepler@unpythonic.net (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Sun, Sep 14, 2014 at 09:45:05AM -0500, Jeff Epler wrote: > one source of excess latency in hm2_spi / hal_spidev is latency due > to async transfers. Make the __spi_sync primitive actually synchronous, > rather than building on an asynchronous primitive. > --- Please submit patches using the process that is documented in Documentation/SubmittingPatches, in particular it is *essential* that you sign off your patches and you need CC maintainers otherwise it's likely your patch will be missed. > + if(!master->cur_msg) > + return; > + Please also follow the kernel coding style. > > - status = spi_async_locked(spi, message); > + if(master->prepare_transfer_hardware) > + status = master->prepare_transfer_hardware(master); > + if(status >= 0) > + status = master->transfer_one_message(master, message); > + if(status >= 0 && master->unprepare_transfer_hardware) > + status = master->unprepare_transfer_hardware(master); > > if (!bus_locked) > mutex_unlock(&master->bus_lock_mutex); > > - if (status == 0) { > - wait_for_completion(&done); > - status = message->status; > - } There's many problems with this - the most critical are that it is broken for multithreaded use, it's not even trying to do locking so both other callers and the thread will break, and it's not waiting for the transfer to complete. It would be good to do as much as we can inline but doing so needs much more work than this and needs to consider other aspects of performance - your patch will also make performance worse in many situations. My talk at ELC this year covers a lot of this, the slides should be googleable.
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 19ee901..55404b5 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -664,10 +664,18 @@ void spi_finalize_current_message(struct spi_master *master) struct spi_message *mesg; unsigned long flags; + if(!master->cur_msg) + return; + spin_lock_irqsave(&master->queue_lock, flags); mesg = master->cur_msg; master->cur_msg = NULL; + if(!mesg) { + spin_unlock_irqrestore(&master->queue_lock, flags); + return; + } + queue_kthread_work(&master->kworker, &master->pump_messages); spin_unlock_irqrestore(&master->queue_lock, flags); @@ -1490,24 +1498,26 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message, int bus_locked) { DECLARE_COMPLETION_ONSTACK(done); - int status; + int status = 0; struct spi_master *master = spi->master; message->complete = spi_complete; message->context = &done; + message->spi = spi; if (!bus_locked) mutex_lock(&master->bus_lock_mutex); - status = spi_async_locked(spi, message); + if(master->prepare_transfer_hardware) + status = master->prepare_transfer_hardware(master); + if(status >= 0) + status = master->transfer_one_message(master, message); + if(status >= 0 && master->unprepare_transfer_hardware) + status = master->unprepare_transfer_hardware(master); if (!bus_locked) mutex_unlock(&master->bus_lock_mutex); - if (status == 0) { - wait_for_completion(&done); - status = message->status; - } message->context = NULL; return status; }