]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/3.10.34/firewire-don-t-use-prepare_delayed_work.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 3.10.34 / firewire-don-t-use-prepare_delayed_work.patch
CommitLineData
1f2cf677
GKH
1From 70044d71d31d6973665ced5be04ef39ac1c09a48 Mon Sep 17 00:00:00 2001
2From: Tejun Heo <tj@kernel.org>
3Date: Fri, 7 Mar 2014 10:19:57 -0500
4Subject: firewire: don't use PREPARE_DELAYED_WORK
5
6From: Tejun Heo <tj@kernel.org>
7
8commit 70044d71d31d6973665ced5be04ef39ac1c09a48 upstream.
9
10PREPARE_[DELAYED_]WORK() are being phased out. They have few users
11and a nasty surprise in terms of reentrancy guarantee as workqueue
12considers work items to be different if they don't have the same work
13function.
14
15firewire core-device and sbp2 have been been multiplexing work items
16with multiple work functions. Introduce fw_device_workfn() and
17sbp2_lu_workfn() which invoke fw_device->workfn and
18sbp2_logical_unit->workfn respectively and always use the two
19functions as the work functions and update the users to set the
20->workfn fields instead of overriding work functions using
21PREPARE_DELAYED_WORK().
22
23This fixes a variety of possible regressions since a2c1c57be8d9
24"workqueue: consider work function when searching for busy work items"
25due to which fw_workqueue lost its required non-reentrancy property.
26
27Signed-off-by: Tejun Heo <tj@kernel.org>
28Acked-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
29Cc: linux1394-devel@lists.sourceforge.net
30Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
31
32---
33 drivers/firewire/core-device.c | 22 +++++++++++++++-------
34 drivers/firewire/sbp2.c | 17 +++++++++++++----
35 include/linux/firewire.h | 1 +
36 3 files changed, 29 insertions(+), 11 deletions(-)
37
38--- a/drivers/firewire/core-device.c
39+++ b/drivers/firewire/core-device.c
40@@ -895,7 +895,7 @@ static int lookup_existing_device(struct
41 old->config_rom_retries = 0;
42 fw_notice(card, "rediscovered device %s\n", dev_name(dev));
43
44- PREPARE_DELAYED_WORK(&old->work, fw_device_update);
45+ old->workfn = fw_device_update;
46 fw_schedule_device_work(old, 0);
47
48 if (current_node == card->root_node)
49@@ -1054,7 +1054,7 @@ static void fw_device_init(struct work_s
50 if (atomic_cmpxchg(&device->state,
51 FW_DEVICE_INITIALIZING,
52 FW_DEVICE_RUNNING) == FW_DEVICE_GONE) {
53- PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
54+ device->workfn = fw_device_shutdown;
55 fw_schedule_device_work(device, SHUTDOWN_DELAY);
56 } else {
57 fw_notice(card, "created device %s: GUID %08x%08x, S%d00\n",
58@@ -1175,13 +1175,20 @@ static void fw_device_refresh(struct wor
59 dev_name(&device->device), fw_rcode_string(ret));
60 gone:
61 atomic_set(&device->state, FW_DEVICE_GONE);
62- PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
63+ device->workfn = fw_device_shutdown;
64 fw_schedule_device_work(device, SHUTDOWN_DELAY);
65 out:
66 if (node_id == card->root_node->node_id)
67 fw_schedule_bm_work(card, 0);
68 }
69
70+static void fw_device_workfn(struct work_struct *work)
71+{
72+ struct fw_device *device = container_of(to_delayed_work(work),
73+ struct fw_device, work);
74+ device->workfn(work);
75+}
76+
77 void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
78 {
79 struct fw_device *device;
80@@ -1231,7 +1238,8 @@ void fw_node_event(struct fw_card *card,
81 * power-up after getting plugged in. We schedule the
82 * first config rom scan half a second after bus reset.
83 */
84- INIT_DELAYED_WORK(&device->work, fw_device_init);
85+ device->workfn = fw_device_init;
86+ INIT_DELAYED_WORK(&device->work, fw_device_workfn);
87 fw_schedule_device_work(device, INITIAL_DELAY);
88 break;
89
90@@ -1247,7 +1255,7 @@ void fw_node_event(struct fw_card *card,
91 if (atomic_cmpxchg(&device->state,
92 FW_DEVICE_RUNNING,
93 FW_DEVICE_INITIALIZING) == FW_DEVICE_RUNNING) {
94- PREPARE_DELAYED_WORK(&device->work, fw_device_refresh);
95+ device->workfn = fw_device_refresh;
96 fw_schedule_device_work(device,
97 device->is_local ? 0 : INITIAL_DELAY);
98 }
99@@ -1262,7 +1270,7 @@ void fw_node_event(struct fw_card *card,
100 smp_wmb(); /* update node_id before generation */
101 device->generation = card->generation;
102 if (atomic_read(&device->state) == FW_DEVICE_RUNNING) {
103- PREPARE_DELAYED_WORK(&device->work, fw_device_update);
104+ device->workfn = fw_device_update;
105 fw_schedule_device_work(device, 0);
106 }
107 break;
108@@ -1287,7 +1295,7 @@ void fw_node_event(struct fw_card *card,
109 device = node->data;
110 if (atomic_xchg(&device->state,
111 FW_DEVICE_GONE) == FW_DEVICE_RUNNING) {
112- PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
113+ device->workfn = fw_device_shutdown;
114 fw_schedule_device_work(device,
115 list_empty(&card->link) ? 0 : SHUTDOWN_DELAY);
116 }
117--- a/drivers/firewire/sbp2.c
118+++ b/drivers/firewire/sbp2.c
119@@ -146,6 +146,7 @@ struct sbp2_logical_unit {
120 */
121 int generation;
122 int retries;
123+ work_func_t workfn;
124 struct delayed_work work;
125 bool has_sdev;
126 bool blocked;
127@@ -864,7 +865,7 @@ static void sbp2_login(struct work_struc
128 /* set appropriate retry limit(s) in BUSY_TIMEOUT register */
129 sbp2_set_busy_timeout(lu);
130
131- PREPARE_DELAYED_WORK(&lu->work, sbp2_reconnect);
132+ lu->workfn = sbp2_reconnect;
133 sbp2_agent_reset(lu);
134
135 /* This was a re-login. */
136@@ -918,7 +919,7 @@ static void sbp2_login(struct work_struc
137 * If a bus reset happened, sbp2_update will have requeued
138 * lu->work already. Reset the work from reconnect to login.
139 */
140- PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
141+ lu->workfn = sbp2_login;
142 }
143
144 static void sbp2_reconnect(struct work_struct *work)
145@@ -952,7 +953,7 @@ static void sbp2_reconnect(struct work_s
146 lu->retries++ >= 5) {
147 dev_err(tgt_dev(tgt), "failed to reconnect\n");
148 lu->retries = 0;
149- PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
150+ lu->workfn = sbp2_login;
151 }
152 sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
153
154@@ -972,6 +973,13 @@ static void sbp2_reconnect(struct work_s
155 sbp2_conditionally_unblock(lu);
156 }
157
158+static void sbp2_lu_workfn(struct work_struct *work)
159+{
160+ struct sbp2_logical_unit *lu = container_of(to_delayed_work(work),
161+ struct sbp2_logical_unit, work);
162+ lu->workfn(work);
163+}
164+
165 static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry)
166 {
167 struct sbp2_logical_unit *lu;
168@@ -998,7 +1006,8 @@ static int sbp2_add_logical_unit(struct
169 lu->blocked = false;
170 ++tgt->dont_block;
171 INIT_LIST_HEAD(&lu->orb_list);
172- INIT_DELAYED_WORK(&lu->work, sbp2_login);
173+ lu->workfn = sbp2_login;
174+ INIT_DELAYED_WORK(&lu->work, sbp2_lu_workfn);
175
176 list_add_tail(&lu->link, &tgt->lu_list);
177 return 0;
178--- a/include/linux/firewire.h
179+++ b/include/linux/firewire.h
180@@ -200,6 +200,7 @@ struct fw_device {
181 unsigned irmc:1;
182 unsigned bc_implemented:2;
183
184+ work_func_t workfn;
185 struct delayed_work work;
186 struct fw_attribute_group attribute_group;
187 };