diff options
author | Tejun Heo <tj@kernel.org> | 2014-03-07 10:24:48 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2014-03-07 10:24:48 -0500 |
commit | 75ddb38f0901d12831264cd74224598e4d8f528b (patch) | |
tree | 0881a11d77acbbb44b402975cdf6a8316a4f0136 | |
parent | 4a8bb7f54860a3241b177bdeb06bb880151a23dc (diff) |
floppy: don't use PREPARE_[DELAYED_]WORK
PREPARE_[DELAYED_]WORK() are being phased out. They have few users
and a nasty surprise in terms of reentrancy guarantee as workqueue
considers work items to be different if they don't have the same work
function.
floppy has been multiplexing floppy_work and fd_timer with multiple
work functions. Introduce floppy_work_workfn() and fd_timer_workfn()
which invoke floppy_work_fn and fd_timer_fn respectively and always
use the two functions as the work functions and update the users to
set floppy_work_fn and fd_timer_fn instead of overriding work
functions using PREPARE_[DELAYED_]WORK().
It would probably be best to route this with other related updates
through the workqueue tree.
Lightly tested using qemu.
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r-- | drivers/block/floppy.c | 42 |
1 files changed, 28 insertions, 14 deletions
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 2023043ce7c0..8f5565bf34cd 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c | |||
@@ -961,17 +961,31 @@ static void empty(void) | |||
961 | { | 961 | { |
962 | } | 962 | } |
963 | 963 | ||
964 | static DECLARE_WORK(floppy_work, NULL); | 964 | static void (*floppy_work_fn)(void); |
965 | |||
966 | static void floppy_work_workfn(struct work_struct *work) | ||
967 | { | ||
968 | floppy_work_fn(); | ||
969 | } | ||
970 | |||
971 | static DECLARE_WORK(floppy_work, floppy_work_workfn); | ||
965 | 972 | ||
966 | static void schedule_bh(void (*handler)(void)) | 973 | static void schedule_bh(void (*handler)(void)) |
967 | { | 974 | { |
968 | WARN_ON(work_pending(&floppy_work)); | 975 | WARN_ON(work_pending(&floppy_work)); |
969 | 976 | ||
970 | PREPARE_WORK(&floppy_work, (work_func_t)handler); | 977 | floppy_work_fn = handler; |
971 | queue_work(floppy_wq, &floppy_work); | 978 | queue_work(floppy_wq, &floppy_work); |
972 | } | 979 | } |
973 | 980 | ||
974 | static DECLARE_DELAYED_WORK(fd_timer, NULL); | 981 | static void (*fd_timer_fn)(void) = NULL; |
982 | |||
983 | static void fd_timer_workfn(struct work_struct *work) | ||
984 | { | ||
985 | fd_timer_fn(); | ||
986 | } | ||
987 | |||
988 | static DECLARE_DELAYED_WORK(fd_timer, fd_timer_workfn); | ||
975 | 989 | ||
976 | static void cancel_activity(void) | 990 | static void cancel_activity(void) |
977 | { | 991 | { |
@@ -982,7 +996,7 @@ static void cancel_activity(void) | |||
982 | 996 | ||
983 | /* this function makes sure that the disk stays in the drive during the | 997 | /* this function makes sure that the disk stays in the drive during the |
984 | * transfer */ | 998 | * transfer */ |
985 | static void fd_watchdog(struct work_struct *arg) | 999 | static void fd_watchdog(void) |
986 | { | 1000 | { |
987 | debug_dcl(DP->flags, "calling disk change from watchdog\n"); | 1001 | debug_dcl(DP->flags, "calling disk change from watchdog\n"); |
988 | 1002 | ||
@@ -993,7 +1007,7 @@ static void fd_watchdog(struct work_struct *arg) | |||
993 | reset_fdc(); | 1007 | reset_fdc(); |
994 | } else { | 1008 | } else { |
995 | cancel_delayed_work(&fd_timer); | 1009 | cancel_delayed_work(&fd_timer); |
996 | PREPARE_DELAYED_WORK(&fd_timer, fd_watchdog); | 1010 | fd_timer_fn = fd_watchdog; |
997 | queue_delayed_work(floppy_wq, &fd_timer, HZ / 10); | 1011 | queue_delayed_work(floppy_wq, &fd_timer, HZ / 10); |
998 | } | 1012 | } |
999 | } | 1013 | } |
@@ -1005,7 +1019,8 @@ static void main_command_interrupt(void) | |||
1005 | } | 1019 | } |
1006 | 1020 | ||
1007 | /* waits for a delay (spinup or select) to pass */ | 1021 | /* waits for a delay (spinup or select) to pass */ |
1008 | static int fd_wait_for_completion(unsigned long expires, work_func_t function) | 1022 | static int fd_wait_for_completion(unsigned long expires, |
1023 | void (*function)(void)) | ||
1009 | { | 1024 | { |
1010 | if (FDCS->reset) { | 1025 | if (FDCS->reset) { |
1011 | reset_fdc(); /* do the reset during sleep to win time | 1026 | reset_fdc(); /* do the reset during sleep to win time |
@@ -1016,7 +1031,7 @@ static int fd_wait_for_completion(unsigned long expires, work_func_t function) | |||
1016 | 1031 | ||
1017 | if (time_before(jiffies, expires)) { | 1032 | if (time_before(jiffies, expires)) { |
1018 | cancel_delayed_work(&fd_timer); | 1033 | cancel_delayed_work(&fd_timer); |
1019 | PREPARE_DELAYED_WORK(&fd_timer, function); | 1034 | fd_timer_fn = function; |
1020 | queue_delayed_work(floppy_wq, &fd_timer, expires - jiffies); | 1035 | queue_delayed_work(floppy_wq, &fd_timer, expires - jiffies); |
1021 | return 1; | 1036 | return 1; |
1022 | } | 1037 | } |
@@ -1334,8 +1349,7 @@ static int fdc_dtr(void) | |||
1334 | * Pause 5 msec to avoid trouble. (Needs to be 2 jiffies) | 1349 | * Pause 5 msec to avoid trouble. (Needs to be 2 jiffies) |
1335 | */ | 1350 | */ |
1336 | FDCS->dtr = raw_cmd->rate & 3; | 1351 | FDCS->dtr = raw_cmd->rate & 3; |
1337 | return fd_wait_for_completion(jiffies + 2UL * HZ / 100, | 1352 | return fd_wait_for_completion(jiffies + 2UL * HZ / 100, floppy_ready); |
1338 | (work_func_t)floppy_ready); | ||
1339 | } /* fdc_dtr */ | 1353 | } /* fdc_dtr */ |
1340 | 1354 | ||
1341 | static void tell_sector(void) | 1355 | static void tell_sector(void) |
@@ -1440,7 +1454,7 @@ static void setup_rw_floppy(void) | |||
1440 | int flags; | 1454 | int flags; |
1441 | int dflags; | 1455 | int dflags; |
1442 | unsigned long ready_date; | 1456 | unsigned long ready_date; |
1443 | work_func_t function; | 1457 | void (*function)(void); |
1444 | 1458 | ||
1445 | flags = raw_cmd->flags; | 1459 | flags = raw_cmd->flags; |
1446 | if (flags & (FD_RAW_READ | FD_RAW_WRITE)) | 1460 | if (flags & (FD_RAW_READ | FD_RAW_WRITE)) |
@@ -1454,9 +1468,9 @@ static void setup_rw_floppy(void) | |||
1454 | */ | 1468 | */ |
1455 | if (time_after(ready_date, jiffies + DP->select_delay)) { | 1469 | if (time_after(ready_date, jiffies + DP->select_delay)) { |
1456 | ready_date -= DP->select_delay; | 1470 | ready_date -= DP->select_delay; |
1457 | function = (work_func_t)floppy_start; | 1471 | function = floppy_start; |
1458 | } else | 1472 | } else |
1459 | function = (work_func_t)setup_rw_floppy; | 1473 | function = setup_rw_floppy; |
1460 | 1474 | ||
1461 | /* wait until the floppy is spinning fast enough */ | 1475 | /* wait until the floppy is spinning fast enough */ |
1462 | if (fd_wait_for_completion(ready_date, function)) | 1476 | if (fd_wait_for_completion(ready_date, function)) |
@@ -1486,7 +1500,7 @@ static void setup_rw_floppy(void) | |||
1486 | inr = result(); | 1500 | inr = result(); |
1487 | cont->interrupt(); | 1501 | cont->interrupt(); |
1488 | } else if (flags & FD_RAW_NEED_DISK) | 1502 | } else if (flags & FD_RAW_NEED_DISK) |
1489 | fd_watchdog(NULL); | 1503 | fd_watchdog(); |
1490 | } | 1504 | } |
1491 | 1505 | ||
1492 | static int blind_seek; | 1506 | static int blind_seek; |
@@ -1863,7 +1877,7 @@ static int start_motor(void (*function)(void)) | |||
1863 | 1877 | ||
1864 | /* wait_for_completion also schedules reset if needed. */ | 1878 | /* wait_for_completion also schedules reset if needed. */ |
1865 | return fd_wait_for_completion(DRS->select_date + DP->select_delay, | 1879 | return fd_wait_for_completion(DRS->select_date + DP->select_delay, |
1866 | (work_func_t)function); | 1880 | function); |
1867 | } | 1881 | } |
1868 | 1882 | ||
1869 | static void floppy_ready(void) | 1883 | static void floppy_ready(void) |