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: Jay Fenlason <fenlason@redhat.com> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> (patch update)
This commit is contained in:
parent
2cc489c213
commit
0fa1986f3a
|
@ -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)
|
||||||
|
|
||||||
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)
|
||||||
* 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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
* 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)
|
||||||
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,
|
||||||
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)
|
||||||
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
|
||||||
|
|
Loading…
Reference in New Issue