Commit 0fa1986f authored by Jay Fenlason's avatar Jay Fenlason Committed by Stefan Richter

firewire: improve refcounting of fw_card

Take a reference to the card whenever fw_card_bm_work() is scheduled on
that card and release it when the work is done.  This allows us to
remove the cancel_delayed_work_sync() in fw_core_remove_card().
Signed-off-by: default avatarJay Fenlason <fenlason@redhat.com>
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> (patch update)
parent 2cc489c2
...@@ -189,6 +189,17 @@ static const char gap_count_table[] = { ...@@ -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 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 static void
fw_card_bm_work(struct work_struct *work) fw_card_bm_work(struct work_struct *work)
{ {
...@@ -206,7 +217,7 @@ fw_card_bm_work(struct work_struct *work) ...@@ -206,7 +217,7 @@ fw_card_bm_work(struct work_struct *work)
if (local_node == NULL) { if (local_node == NULL) {
spin_unlock_irqrestore(&card->lock, flags); spin_unlock_irqrestore(&card->lock, flags);
return; goto out_put_card;
} }
fw_node_get(local_node); fw_node_get(local_node);
fw_node_get(root_node); fw_node_get(root_node);
...@@ -280,7 +291,7 @@ fw_card_bm_work(struct work_struct *work) ...@@ -280,7 +291,7 @@ fw_card_bm_work(struct work_struct *work)
* this task 100ms from now. * this task 100ms from now.
*/ */
spin_unlock_irqrestore(&card->lock, flags); 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; goto out;
} }
...@@ -355,6 +366,8 @@ fw_card_bm_work(struct work_struct *work) ...@@ -355,6 +366,8 @@ fw_card_bm_work(struct work_struct *work)
fw_device_put(root_device); fw_device_put(root_device);
fw_node_put(root_node); fw_node_put(root_node);
fw_node_put(local_node); fw_node_put(local_node);
out_put_card:
fw_card_put(card);
} }
static void static void
...@@ -510,7 +523,6 @@ fw_core_remove_card(struct fw_card *card) ...@@ -510,7 +523,6 @@ fw_core_remove_card(struct fw_card *card)
fw_card_put(card); fw_card_put(card);
wait_for_completion(&card->done); wait_for_completion(&card->done);
cancel_delayed_work_sync(&card->work);
WARN_ON(!list_empty(&card->transaction_list)); WARN_ON(!list_empty(&card->transaction_list));
del_timer_sync(&card->flush_timer); del_timer_sync(&card->flush_timer);
} }
......
...@@ -689,7 +689,7 @@ static void fw_device_init(struct work_struct *work) ...@@ -689,7 +689,7 @@ static void fw_device_init(struct work_struct *work)
fw_notify("giving up on config rom for node id %x\n", fw_notify("giving up on config rom for node id %x\n",
device->node_id); device->node_id);
if (device->node == device->card->root_node) if (device->node == device->card->root_node)
schedule_delayed_work(&device->card->work, 0); fw_schedule_bm_work(device->card, 0);
fw_device_release(&device->device); fw_device_release(&device->device);
} }
return; return;
...@@ -758,7 +758,7 @@ static void fw_device_init(struct work_struct *work) ...@@ -758,7 +758,7 @@ static void fw_device_init(struct work_struct *work)
* pretty harmless. * pretty harmless.
*/ */
if (device->node == device->card->root_node) if (device->node == device->card->root_node)
schedule_delayed_work(&device->card->work, 0); fw_schedule_bm_work(device->card, 0);
return; return;
...@@ -892,7 +892,7 @@ static void fw_device_refresh(struct work_struct *work) ...@@ -892,7 +892,7 @@ static void fw_device_refresh(struct work_struct *work)
fw_device_shutdown(work); fw_device_shutdown(work);
out: out:
if (node_id == card->root_node->node_id) if (node_id == card->root_node->node_id)
schedule_delayed_work(&card->work, 0); fw_schedule_bm_work(card, 0);
} }
void fw_node_event(struct fw_card *card, struct fw_node *node, int event) void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
......
...@@ -530,7 +530,7 @@ fw_core_handle_bus_reset(struct fw_card *card, ...@@ -530,7 +530,7 @@ fw_core_handle_bus_reset(struct fw_card *card,
smp_wmb(); smp_wmb();
card->generation = generation; card->generation = generation;
card->reset_jiffies = jiffies; card->reset_jiffies = jiffies;
schedule_delayed_work(&card->work, 0); fw_schedule_bm_work(card, 0);
local_node = build_tree(card, self_ids, self_id_count); local_node = build_tree(card, self_ids, self_id_count);
......
...@@ -278,6 +278,8 @@ static inline void fw_card_put(struct fw_card *card) ...@@ -278,6 +278,8 @@ static inline void fw_card_put(struct fw_card *card)
kref_put(&card->kref, fw_card_release); kref_put(&card->kref, fw_card_release);
} }
extern void fw_schedule_bm_work(struct fw_card *card, unsigned long delay);
/* /*
* The iso packet format allows for an immediate header/payload part * The iso packet format allows for an immediate header/payload part
* stored in 'header' immediately after the packet info plus an * stored in 'header' immediately after the packet info plus an
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment