aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire/fw-card.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2008-03-08 11:49:24 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2008-03-08 11:49:24 -0500
commit9446389ef612096704fdf18fa79bab423d4110f0 (patch)
tree3e4fda7270be58ae176d20d318e61fb115b325b5 /drivers/firewire/fw-card.c
parentcdd0972945dbcb8ea24db365d9b0e100af2a27bb (diff)
parent84c6f6046c5a2189160a8f0dca8b90427bf690ea (diff)
Merge commit 'origin' into devel
Diffstat (limited to 'drivers/firewire/fw-card.c')
-rw-r--r--drivers/firewire/fw-card.c61
1 files changed, 43 insertions, 18 deletions
diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c
index 3e9719948a8e..a03462750b95 100644
--- a/drivers/firewire/fw-card.c
+++ b/drivers/firewire/fw-card.c
@@ -18,6 +18,7 @@
18 18
19#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/errno.h> 20#include <linux/errno.h>
21#include <linux/delay.h>
21#include <linux/device.h> 22#include <linux/device.h>
22#include <linux/mutex.h> 23#include <linux/mutex.h>
23#include <linux/crc-itu-t.h> 24#include <linux/crc-itu-t.h>
@@ -214,17 +215,29 @@ static void
214fw_card_bm_work(struct work_struct *work) 215fw_card_bm_work(struct work_struct *work)
215{ 216{
216 struct fw_card *card = container_of(work, struct fw_card, work.work); 217 struct fw_card *card = container_of(work, struct fw_card, work.work);
217 struct fw_device *root; 218 struct fw_device *root_device;
219 struct fw_node *root_node, *local_node;
218 struct bm_data bmd; 220 struct bm_data bmd;
219 unsigned long flags; 221 unsigned long flags;
220 int root_id, new_root_id, irm_id, gap_count, generation, grace; 222 int root_id, new_root_id, irm_id, gap_count, generation, grace;
221 int do_reset = 0; 223 int do_reset = 0;
222 224
223 spin_lock_irqsave(&card->lock, flags); 225 spin_lock_irqsave(&card->lock, flags);
226 local_node = card->local_node;
227 root_node = card->root_node;
228
229 if (local_node == NULL) {
230 spin_unlock_irqrestore(&card->lock, flags);
231 return;
232 }
233 fw_node_get(local_node);
234 fw_node_get(root_node);
224 235
225 generation = card->generation; 236 generation = card->generation;
226 root = card->root_node->data; 237 root_device = root_node->data;
227 root_id = card->root_node->node_id; 238 if (root_device)
239 fw_device_get(root_device);
240 root_id = root_node->node_id;
228 grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 10)); 241 grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 10));
229 242
230 if (card->bm_generation + 1 == generation || 243 if (card->bm_generation + 1 == generation ||
@@ -243,14 +256,14 @@ fw_card_bm_work(struct work_struct *work)
243 256
244 irm_id = card->irm_node->node_id; 257 irm_id = card->irm_node->node_id;
245 if (!card->irm_node->link_on) { 258 if (!card->irm_node->link_on) {
246 new_root_id = card->local_node->node_id; 259 new_root_id = local_node->node_id;
247 fw_notify("IRM has link off, making local node (%02x) root.\n", 260 fw_notify("IRM has link off, making local node (%02x) root.\n",
248 new_root_id); 261 new_root_id);
249 goto pick_me; 262 goto pick_me;
250 } 263 }
251 264
252 bmd.lock.arg = cpu_to_be32(0x3f); 265 bmd.lock.arg = cpu_to_be32(0x3f);
253 bmd.lock.data = cpu_to_be32(card->local_node->node_id); 266 bmd.lock.data = cpu_to_be32(local_node->node_id);
254 267
255 spin_unlock_irqrestore(&card->lock, flags); 268 spin_unlock_irqrestore(&card->lock, flags);
256 269
@@ -267,12 +280,12 @@ fw_card_bm_work(struct work_struct *work)
267 * Another bus reset happened. Just return, 280 * Another bus reset happened. Just return,
268 * the BM work has been rescheduled. 281 * the BM work has been rescheduled.
269 */ 282 */
270 return; 283 goto out;
271 } 284 }
272 285
273 if (bmd.rcode == RCODE_COMPLETE && bmd.old != 0x3f) 286 if (bmd.rcode == RCODE_COMPLETE && bmd.old != 0x3f)
274 /* Somebody else is BM, let them do the work. */ 287 /* Somebody else is BM, let them do the work. */
275 return; 288 goto out;
276 289
277 spin_lock_irqsave(&card->lock, flags); 290 spin_lock_irqsave(&card->lock, flags);
278 if (bmd.rcode != RCODE_COMPLETE) { 291 if (bmd.rcode != RCODE_COMPLETE) {
@@ -282,7 +295,7 @@ fw_card_bm_work(struct work_struct *work)
282 * do a bus reset and pick the local node as 295 * do a bus reset and pick the local node as
283 * root, and thus, IRM. 296 * root, and thus, IRM.
284 */ 297 */
285 new_root_id = card->local_node->node_id; 298 new_root_id = local_node->node_id;
286 fw_notify("BM lock failed, making local node (%02x) root.\n", 299 fw_notify("BM lock failed, making local node (%02x) root.\n",
287 new_root_id); 300 new_root_id);
288 goto pick_me; 301 goto pick_me;
@@ -295,7 +308,7 @@ fw_card_bm_work(struct work_struct *work)
295 */ 308 */
296 spin_unlock_irqrestore(&card->lock, flags); 309 spin_unlock_irqrestore(&card->lock, flags);
297 schedule_delayed_work(&card->work, DIV_ROUND_UP(HZ, 10)); 310 schedule_delayed_work(&card->work, DIV_ROUND_UP(HZ, 10));
298 return; 311 goto out;
299 } 312 }
300 313
301 /* 314 /*
@@ -305,20 +318,20 @@ fw_card_bm_work(struct work_struct *work)
305 */ 318 */
306 card->bm_generation = generation; 319 card->bm_generation = generation;
307 320
308 if (root == NULL) { 321 if (root_device == NULL) {
309 /* 322 /*
310 * Either link_on is false, or we failed to read the 323 * Either link_on is false, or we failed to read the
311 * config rom. In either case, pick another root. 324 * config rom. In either case, pick another root.
312 */ 325 */
313 new_root_id = card->local_node->node_id; 326 new_root_id = local_node->node_id;
314 } else if (atomic_read(&root->state) != FW_DEVICE_RUNNING) { 327 } else if (atomic_read(&root_device->state) != FW_DEVICE_RUNNING) {
315 /* 328 /*
316 * If we haven't probed this device yet, bail out now 329 * If we haven't probed this device yet, bail out now
317 * and let's try again once that's done. 330 * and let's try again once that's done.
318 */ 331 */
319 spin_unlock_irqrestore(&card->lock, flags); 332 spin_unlock_irqrestore(&card->lock, flags);
320 return; 333 goto out;
321 } else if (root->config_rom[2] & BIB_CMC) { 334 } else if (root_device->config_rom[2] & BIB_CMC) {
322 /* 335 /*
323 * FIXME: I suppose we should set the cmstr bit in the 336 * FIXME: I suppose we should set the cmstr bit in the
324 * STATE_CLEAR register of this node, as described in 337 * STATE_CLEAR register of this node, as described in
@@ -332,7 +345,7 @@ fw_card_bm_work(struct work_struct *work)
332 * successfully read the config rom, but it's not 345 * successfully read the config rom, but it's not
333 * cycle master capable. 346 * cycle master capable.
334 */ 347 */
335 new_root_id = card->local_node->node_id; 348 new_root_id = local_node->node_id;
336 } 349 }
337 350
338 pick_me: 351 pick_me:
@@ -341,8 +354,8 @@ fw_card_bm_work(struct work_struct *work)
341 * the typically much larger 1394b beta repeater delays though. 354 * the typically much larger 1394b beta repeater delays though.
342 */ 355 */
343 if (!card->beta_repeaters_present && 356 if (!card->beta_repeaters_present &&
344 card->root_node->max_hops < ARRAY_SIZE(gap_count_table)) 357 root_node->max_hops < ARRAY_SIZE(gap_count_table))
345 gap_count = gap_count_table[card->root_node->max_hops]; 358 gap_count = gap_count_table[root_node->max_hops];
346 else 359 else
347 gap_count = 63; 360 gap_count = 63;
348 361
@@ -364,6 +377,11 @@ fw_card_bm_work(struct work_struct *work)
364 fw_send_phy_config(card, new_root_id, generation, gap_count); 377 fw_send_phy_config(card, new_root_id, generation, gap_count);
365 fw_core_initiate_bus_reset(card, 1); 378 fw_core_initiate_bus_reset(card, 1);
366 } 379 }
380 out:
381 if (root_device)
382 fw_device_put(root_device);
383 fw_node_put(root_node);
384 fw_node_put(local_node);
367} 385}
368 386
369static void 387static void
@@ -381,6 +399,7 @@ fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver,
381 static atomic_t index = ATOMIC_INIT(-1); 399 static atomic_t index = ATOMIC_INIT(-1);
382 400
383 kref_init(&card->kref); 401 kref_init(&card->kref);
402 atomic_set(&card->device_count, 0);
384 card->index = atomic_inc_return(&index); 403 card->index = atomic_inc_return(&index);
385 card->driver = driver; 404 card->driver = driver;
386 card->device = device; 405 card->device = device;
@@ -511,8 +530,14 @@ fw_core_remove_card(struct fw_card *card)
511 card->driver = &dummy_driver; 530 card->driver = &dummy_driver;
512 531
513 fw_destroy_nodes(card); 532 fw_destroy_nodes(card);
514 flush_scheduled_work(); 533 /*
534 * Wait for all device workqueue jobs to finish. Otherwise the
535 * firewire-core module could be unloaded before the jobs ran.
536 */
537 while (atomic_read(&card->device_count) > 0)
538 msleep(100);
515 539
540 cancel_delayed_work_sync(&card->work);
516 fw_flush_transactions(card); 541 fw_flush_transactions(card);
517 del_timer_sync(&card->flush_timer); 542 del_timer_sync(&card->flush_timer);
518 543