diff options
Diffstat (limited to 'drivers/firewire/fw-card.c')
-rw-r--r-- | drivers/firewire/fw-card.c | 33 |
1 files changed, 23 insertions, 10 deletions
diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c index 418c18f07e9..6bd91a15d5e 100644 --- a/drivers/firewire/fw-card.c +++ b/drivers/firewire/fw-card.c @@ -75,7 +75,7 @@ generate_config_rom(struct fw_card *card, size_t *config_rom_length) * controller, block reads to the config rom accesses the host * memory, but quadlet read access the hardware bus info block * registers. That's just crack, but it means we should make - * sure the contents of bus info block in host memory mathces + * sure the contents of bus info block in host memory matches * the version stored in the OHCI registers. */ @@ -189,6 +189,17 @@ static const char gap_count_table[] = { 63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40 }; +void +fw_schedule_bm_work(struct fw_card *card, unsigned long delay) +{ + int scheduled; + + fw_card_get(card); + scheduled = schedule_delayed_work(&card->work, delay); + if (!scheduled) + fw_card_put(card); +} + static void fw_card_bm_work(struct work_struct *work) { @@ -198,6 +209,8 @@ fw_card_bm_work(struct work_struct *work) unsigned long flags; int root_id, new_root_id, irm_id, gap_count, generation, grace, rcode; bool do_reset = false; + bool root_device_is_running; + bool root_device_is_cmc; __be32 lock_data[2]; spin_lock_irqsave(&card->lock, flags); @@ -206,15 +219,16 @@ fw_card_bm_work(struct work_struct *work) if (local_node == NULL) { spin_unlock_irqrestore(&card->lock, flags); - return; + goto out_put_card; } fw_node_get(local_node); fw_node_get(root_node); generation = card->generation; root_device = root_node->data; - if (root_device) - fw_device_get(root_device); + root_device_is_running = root_device && + atomic_read(&root_device->state) == FW_DEVICE_RUNNING; + root_device_is_cmc = root_device && root_device->cmc; root_id = root_node->node_id; grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 10)); @@ -280,7 +294,7 @@ fw_card_bm_work(struct work_struct *work) * this task 100ms from now. */ spin_unlock_irqrestore(&card->lock, flags); - schedule_delayed_work(&card->work, DIV_ROUND_UP(HZ, 10)); + fw_schedule_bm_work(card, DIV_ROUND_UP(HZ, 10)); goto out; } @@ -297,14 +311,14 @@ fw_card_bm_work(struct work_struct *work) * config rom. In either case, pick another root. */ new_root_id = local_node->node_id; - } else if (atomic_read(&root_device->state) != FW_DEVICE_RUNNING) { + } else if (!root_device_is_running) { /* * If we haven't probed this device yet, bail out now * and let's try again once that's done. */ spin_unlock_irqrestore(&card->lock, flags); goto out; - } else if (root_device->cmc) { + } else if (root_device_is_cmc) { /* * FIXME: I suppose we should set the cmstr bit in the * STATE_CLEAR register of this node, as described in @@ -351,10 +365,10 @@ fw_card_bm_work(struct work_struct *work) fw_core_initiate_bus_reset(card, 1); } out: - if (root_device) - fw_device_put(root_device); fw_node_put(root_node); fw_node_put(local_node); + out_put_card: + fw_card_put(card); } static void @@ -510,7 +524,6 @@ fw_core_remove_card(struct fw_card *card) fw_card_put(card); wait_for_completion(&card->done); - cancel_delayed_work_sync(&card->work); WARN_ON(!list_empty(&card->transaction_list)); del_timer_sync(&card->flush_timer); } |