diff options
author | Arnd Bergmann <arnd@arndb.de> | 2014-03-01 02:51:03 -0500 |
---|---|---|
committer | Geert Uytterhoeven <geert@linux-m68k.org> | 2014-03-10 16:15:09 -0400 |
commit | eff9cf8d6e8b048f2f744a1cc382e213a00f3d2c (patch) | |
tree | 00dae389bf92fee740031bc618754eeb3c68f5bd | |
parent | ecc79d4964c4154b8bc2de2a8ffed108f009c405 (diff) |
[SCSI] atari_scsi: Fix sleep_on race
sleep_on is known broken and going away. The atari_scsi driver is one of
two remaining users in the falcon_get_lock() function, which is a rather
crazy piece of code. This does not attempt to fix the driver's locking
scheme in general, but at least prevents falcon_get_lock from going to
sleep when no other thread holds the same lock or tries to get it,
and we no longer schedule with irqs disabled.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
[MSch: fixed completion conditions missed in Arnds' original RFC patch]
Signed-off-by: Michael Schmitz <schmitz@debian.org>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: James E.J. Bottomley <JBottomley@parallels.com>
Cc: linux-scsi@vger.kernel.org
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
-rw-r--r-- | drivers/scsi/atari_scsi.c | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index a3e6c8a3ff0f..296c936cc03c 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c | |||
@@ -90,6 +90,7 @@ | |||
90 | #include <linux/init.h> | 90 | #include <linux/init.h> |
91 | #include <linux/nvram.h> | 91 | #include <linux/nvram.h> |
92 | #include <linux/bitops.h> | 92 | #include <linux/bitops.h> |
93 | #include <linux/wait.h> | ||
93 | 94 | ||
94 | #include <asm/setup.h> | 95 | #include <asm/setup.h> |
95 | #include <asm/atarihw.h> | 96 | #include <asm/atarihw.h> |
@@ -549,8 +550,10 @@ static void falcon_get_lock(void) | |||
549 | 550 | ||
550 | local_irq_save(flags); | 551 | local_irq_save(flags); |
551 | 552 | ||
552 | while (!in_irq() && falcon_got_lock && stdma_others_waiting()) | 553 | wait_event_cmd(falcon_fairness_wait, |
553 | sleep_on(&falcon_fairness_wait); | 554 | in_interrupt() || !falcon_got_lock || !stdma_others_waiting(), |
555 | local_irq_restore(flags), | ||
556 | local_irq_save(flags)); | ||
554 | 557 | ||
555 | while (!falcon_got_lock) { | 558 | while (!falcon_got_lock) { |
556 | if (in_irq()) | 559 | if (in_irq()) |
@@ -562,7 +565,10 @@ static void falcon_get_lock(void) | |||
562 | falcon_trying_lock = 0; | 565 | falcon_trying_lock = 0; |
563 | wake_up(&falcon_try_wait); | 566 | wake_up(&falcon_try_wait); |
564 | } else { | 567 | } else { |
565 | sleep_on(&falcon_try_wait); | 568 | wait_event_cmd(falcon_try_wait, |
569 | falcon_got_lock && !falcon_trying_lock, | ||
570 | local_irq_restore(flags), | ||
571 | local_irq_save(flags)); | ||
566 | } | 572 | } |
567 | } | 573 | } |
568 | 574 | ||