diff options
author | Tejun Heo <tj@kernel.org> | 2014-03-07 10:19:57 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2014-03-07 10:19:57 -0500 |
commit | 70044d71d31d6973665ced5be04ef39ac1c09a48 (patch) | |
tree | f74d931f9df397f6ffcb257158215780bed6ab87 /drivers/firewire/sbp2.c | |
parent | 5bdfff96c69a4d5ab9c49e60abf9e070ecd2acbb (diff) |
firewire: 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.
firewire core-device and sbp2 have been been multiplexing work items
with multiple work functions. Introduce fw_device_workfn() and
sbp2_lu_workfn() which invoke fw_device->workfn and
sbp2_logical_unit->workfn respectively and always use the two
functions as the work functions and update the users to set the
->workfn fields instead of overriding work functions using
PREPARE_DELAYED_WORK().
This fixes a variety of possible regressions since a2c1c57be8d9
"workqueue: consider work function when searching for busy work items"
due to which fw_workqueue lost its required non-reentrancy property.
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Cc: linux1394-devel@lists.sourceforge.net
Cc: stable@vger.kernel.org # v3.9+
Cc: stable@vger.kernel.org # v3.8.2+
Cc: stable@vger.kernel.org # v3.4.60+
Cc: stable@vger.kernel.org # v3.2.40+
Diffstat (limited to 'drivers/firewire/sbp2.c')
-rw-r--r-- | drivers/firewire/sbp2.c | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c index 281029daf98c..7aef911fdc71 100644 --- a/drivers/firewire/sbp2.c +++ b/drivers/firewire/sbp2.c | |||
@@ -146,6 +146,7 @@ struct sbp2_logical_unit { | |||
146 | */ | 146 | */ |
147 | int generation; | 147 | int generation; |
148 | int retries; | 148 | int retries; |
149 | work_func_t workfn; | ||
149 | struct delayed_work work; | 150 | struct delayed_work work; |
150 | bool has_sdev; | 151 | bool has_sdev; |
151 | bool blocked; | 152 | bool blocked; |
@@ -864,7 +865,7 @@ static void sbp2_login(struct work_struct *work) | |||
864 | /* set appropriate retry limit(s) in BUSY_TIMEOUT register */ | 865 | /* set appropriate retry limit(s) in BUSY_TIMEOUT register */ |
865 | sbp2_set_busy_timeout(lu); | 866 | sbp2_set_busy_timeout(lu); |
866 | 867 | ||
867 | PREPARE_DELAYED_WORK(&lu->work, sbp2_reconnect); | 868 | lu->workfn = sbp2_reconnect; |
868 | sbp2_agent_reset(lu); | 869 | sbp2_agent_reset(lu); |
869 | 870 | ||
870 | /* This was a re-login. */ | 871 | /* This was a re-login. */ |
@@ -918,7 +919,7 @@ static void sbp2_login(struct work_struct *work) | |||
918 | * If a bus reset happened, sbp2_update will have requeued | 919 | * If a bus reset happened, sbp2_update will have requeued |
919 | * lu->work already. Reset the work from reconnect to login. | 920 | * lu->work already. Reset the work from reconnect to login. |
920 | */ | 921 | */ |
921 | PREPARE_DELAYED_WORK(&lu->work, sbp2_login); | 922 | lu->workfn = sbp2_login; |
922 | } | 923 | } |
923 | 924 | ||
924 | static void sbp2_reconnect(struct work_struct *work) | 925 | static void sbp2_reconnect(struct work_struct *work) |
@@ -952,7 +953,7 @@ static void sbp2_reconnect(struct work_struct *work) | |||
952 | lu->retries++ >= 5) { | 953 | lu->retries++ >= 5) { |
953 | dev_err(tgt_dev(tgt), "failed to reconnect\n"); | 954 | dev_err(tgt_dev(tgt), "failed to reconnect\n"); |
954 | lu->retries = 0; | 955 | lu->retries = 0; |
955 | PREPARE_DELAYED_WORK(&lu->work, sbp2_login); | 956 | lu->workfn = sbp2_login; |
956 | } | 957 | } |
957 | sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5)); | 958 | sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5)); |
958 | 959 | ||
@@ -972,6 +973,13 @@ static void sbp2_reconnect(struct work_struct *work) | |||
972 | sbp2_conditionally_unblock(lu); | 973 | sbp2_conditionally_unblock(lu); |
973 | } | 974 | } |
974 | 975 | ||
976 | static void sbp2_lu_workfn(struct work_struct *work) | ||
977 | { | ||
978 | struct sbp2_logical_unit *lu = container_of(to_delayed_work(work), | ||
979 | struct sbp2_logical_unit, work); | ||
980 | lu->workfn(work); | ||
981 | } | ||
982 | |||
975 | static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry) | 983 | static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry) |
976 | { | 984 | { |
977 | struct sbp2_logical_unit *lu; | 985 | struct sbp2_logical_unit *lu; |
@@ -998,7 +1006,8 @@ static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry) | |||
998 | lu->blocked = false; | 1006 | lu->blocked = false; |
999 | ++tgt->dont_block; | 1007 | ++tgt->dont_block; |
1000 | INIT_LIST_HEAD(&lu->orb_list); | 1008 | INIT_LIST_HEAD(&lu->orb_list); |
1001 | INIT_DELAYED_WORK(&lu->work, sbp2_login); | 1009 | lu->workfn = sbp2_login; |
1010 | INIT_DELAYED_WORK(&lu->work, sbp2_lu_workfn); | ||
1002 | 1011 | ||
1003 | list_add_tail(&lu->link, &tgt->lu_list); | 1012 | list_add_tail(&lu->link, &tgt->lu_list); |
1004 | return 0; | 1013 | return 0; |