spi: Fix race condition in stop_queue()
There's a race condition in stop_queue() in some drivers - if drv_data->queue is empty, but drv_data->busy is still set (or opposite situation) stop_queue will return -EBUSY. So fix loop condition to check that both drv_data->queue is empty and drv_data->busy is not set. This patch affects following drivers: pxa2xx_spi spi_bfin5xx amba-pl022 dw_spi Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com> Acked-by: Eric Miao <eric.y.miao@gmail.com> Acked-by: Mike Frysinger <vapier@gentoo.org> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
This commit is contained in:
Родитель
454abcc57f
Коммит
850a28ecd8
|
@ -1555,7 +1555,7 @@ static int stop_queue(struct pl022 *pl022)
|
|||
* A wait_queue on the pl022->busy could be used, but then the common
|
||||
* execution path (pump_messages) would be required to call wake_up or
|
||||
* friends on every SPI message. Do this instead */
|
||||
while (!list_empty(&pl022->queue) && pl022->busy && limit--) {
|
||||
while ((!list_empty(&pl022->queue) || pl022->busy) && limit--) {
|
||||
spin_unlock_irqrestore(&pl022->queue_lock, flags);
|
||||
msleep(10);
|
||||
spin_lock_irqsave(&pl022->queue_lock, flags);
|
||||
|
|
|
@ -821,7 +821,7 @@ static int stop_queue(struct dw_spi *dws)
|
|||
|
||||
spin_lock_irqsave(&dws->lock, flags);
|
||||
dws->run = QUEUE_STOPPED;
|
||||
while (!list_empty(&dws->queue) && dws->busy && limit--) {
|
||||
while ((!list_empty(&dws->queue) || dws->busy) && limit--) {
|
||||
spin_unlock_irqrestore(&dws->lock, flags);
|
||||
msleep(10);
|
||||
spin_lock_irqsave(&dws->lock, flags);
|
||||
|
|
|
@ -1493,7 +1493,7 @@ static int stop_queue(struct driver_data *drv_data)
|
|||
* execution path (pump_messages) would be required to call wake_up or
|
||||
* friends on every SPI message. Do this instead */
|
||||
drv_data->run = QUEUE_STOPPED;
|
||||
while (!list_empty(&drv_data->queue) && drv_data->busy && limit--) {
|
||||
while ((!list_empty(&drv_data->queue) || drv_data->busy) && limit--) {
|
||||
spin_unlock_irqrestore(&drv_data->lock, flags);
|
||||
msleep(10);
|
||||
spin_lock_irqsave(&drv_data->lock, flags);
|
||||
|
|
|
@ -1284,7 +1284,7 @@ static inline int bfin_spi_stop_queue(struct bfin_spi_master_data *drv_data)
|
|||
* friends on every SPI message. Do this instead
|
||||
*/
|
||||
drv_data->running = false;
|
||||
while (!list_empty(&drv_data->queue) && drv_data->busy && limit--) {
|
||||
while ((!list_empty(&drv_data->queue) || drv_data->busy) && limit--) {
|
||||
spin_unlock_irqrestore(&drv_data->lock, flags);
|
||||
msleep(10);
|
||||
spin_lock_irqsave(&drv_data->lock, flags);
|
||||
|
|
Загрузка…
Ссылка в новой задаче