aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire/fw-card.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firewire/fw-card.c')
-rw-r--r--drivers/firewire/fw-card.c56
1 files changed, 14 insertions, 42 deletions
diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c
index bbd73a406e53..418c18f07e9d 100644
--- a/drivers/firewire/fw-card.c
+++ b/drivers/firewire/fw-card.c
@@ -189,39 +189,16 @@ static const char gap_count_table[] = {
189 63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40 189 63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40
190}; 190};
191 191
192struct bm_data {
193 struct fw_transaction t;
194 struct {
195 __be32 arg;
196 __be32 data;
197 } lock;
198 u32 old;
199 int rcode;
200 struct completion done;
201};
202
203static void
204complete_bm_lock(struct fw_card *card, int rcode,
205 void *payload, size_t length, void *data)
206{
207 struct bm_data *bmd = data;
208
209 if (rcode == RCODE_COMPLETE)
210 bmd->old = be32_to_cpu(*(__be32 *) payload);
211 bmd->rcode = rcode;
212 complete(&bmd->done);
213}
214
215static void 192static void
216fw_card_bm_work(struct work_struct *work) 193fw_card_bm_work(struct work_struct *work)
217{ 194{
218 struct fw_card *card = container_of(work, struct fw_card, work.work); 195 struct fw_card *card = container_of(work, struct fw_card, work.work);
219 struct fw_device *root_device; 196 struct fw_device *root_device;
220 struct fw_node *root_node, *local_node; 197 struct fw_node *root_node, *local_node;
221 struct bm_data bmd;
222 unsigned long flags; 198 unsigned long flags;
223 int root_id, new_root_id, irm_id, gap_count, generation, grace; 199 int root_id, new_root_id, irm_id, gap_count, generation, grace, rcode;
224 bool do_reset = false; 200 bool do_reset = false;
201 __be32 lock_data[2];
225 202
226 spin_lock_irqsave(&card->lock, flags); 203 spin_lock_irqsave(&card->lock, flags);
227 local_node = card->local_node; 204 local_node = card->local_node;
@@ -263,33 +240,28 @@ fw_card_bm_work(struct work_struct *work)
263 goto pick_me; 240 goto pick_me;
264 } 241 }
265 242
266 bmd.lock.arg = cpu_to_be32(0x3f); 243 lock_data[0] = cpu_to_be32(0x3f);
267 bmd.lock.data = cpu_to_be32(local_node->node_id); 244 lock_data[1] = cpu_to_be32(local_node->node_id);
268 245
269 spin_unlock_irqrestore(&card->lock, flags); 246 spin_unlock_irqrestore(&card->lock, flags);
270 247
271 init_completion(&bmd.done); 248 rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,
272 fw_send_request(card, &bmd.t, TCODE_LOCK_COMPARE_SWAP, 249 irm_id, generation, SCODE_100,
273 irm_id, generation, 250 CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID,
274 SCODE_100, CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID, 251 lock_data, sizeof(lock_data));
275 &bmd.lock, sizeof(bmd.lock),
276 complete_bm_lock, &bmd);
277 wait_for_completion(&bmd.done);
278 252
279 if (bmd.rcode == RCODE_GENERATION) { 253 if (rcode == RCODE_GENERATION)
280 /* 254 /* Another bus reset, BM work has been rescheduled. */
281 * Another bus reset happened. Just return,
282 * the BM work has been rescheduled.
283 */
284 goto out; 255 goto out;
285 }
286 256
287 if (bmd.rcode == RCODE_COMPLETE && bmd.old != 0x3f) 257 if (rcode == RCODE_COMPLETE &&
258 lock_data[0] != cpu_to_be32(0x3f))
288 /* Somebody else is BM, let them do the work. */ 259 /* Somebody else is BM, let them do the work. */
289 goto out; 260 goto out;
290 261
291 spin_lock_irqsave(&card->lock, flags); 262 spin_lock_irqsave(&card->lock, flags);
292 if (bmd.rcode != RCODE_COMPLETE) { 263
264 if (rcode != RCODE_COMPLETE) {
293 /* 265 /*
294 * The lock request failed, maybe the IRM 266 * The lock request failed, maybe the IRM
295 * isn't really IRM capable after all. Let's 267 * isn't really IRM capable after all. Let's