summaryrefslogtreecommitdiffstats
path: root/drivers/firewire
diff options
context:
space:
mode:
authorJay Fenlason <fenlason@redhat.com>2008-11-29 17:44:57 +0100
committerStefan Richter <stefanr@s5r6.in-berlin.de>2009-01-04 23:50:37 +0100
commit0fa1986f3a6c385b3bca0b6a051c30e548bda30d (patch)
tree5b61ce9579a520f89bc4c000bfe3496e58d4f47a /drivers/firewire
parent2cc489c21338950c2b4097dec48864bdf7b30f1b (diff)
downloadlinux-0fa1986f3a6c385b3bca0b6a051c30e548bda30d.tar.gz
linux-0fa1986f3a6c385b3bca0b6a051c30e548bda30d.tar.bz2
linux-0fa1986f3a6c385b3bca0b6a051c30e548bda30d.zip
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)
Diffstat (limited to 'drivers/firewire')
-rw-r--r--drivers/firewire/fw-card.c18
-rw-r--r--drivers/firewire/fw-device.c6
-rw-r--r--drivers/firewire/fw-topology.c2
-rw-r--r--drivers/firewire/fw-transaction.h2
4 files changed, 21 insertions, 7 deletions
diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c
index c7760794de0d..799f94424c8a 100644
--- a/drivers/firewire/fw-card.c
+++ b/drivers/firewire/fw-card.c
@@ -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)
{
@@ -206,7 +217,7 @@ 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);
@@ -280,7 +291,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;
}
@@ -355,6 +366,8 @@ fw_card_bm_work(struct work_struct *work)
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 +523,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);
}
diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c
index 31b6c74d34df..c173be383725 100644
--- a/drivers/firewire/fw-device.c
+++ b/drivers/firewire/fw-device.c
@@ -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",
device->node_id);
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);
}
return;
@@ -758,7 +758,7 @@ static void fw_device_init(struct work_struct *work)
* pretty harmless.
*/
if (device->node == device->card->root_node)
- schedule_delayed_work(&device->card->work, 0);
+ fw_schedule_bm_work(device->card, 0);
return;
@@ -892,7 +892,7 @@ static void fw_device_refresh(struct work_struct *work)
fw_device_shutdown(work);
out:
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)
diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c
index 5e204713002d..7687dca1a690 100644
--- a/drivers/firewire/fw-topology.c
+++ b/drivers/firewire/fw-topology.c
@@ -530,7 +530,7 @@ fw_core_handle_bus_reset(struct fw_card *card,
smp_wmb();
card->generation = generation;
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);
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h
index 839466f0a795..0497a18dc59e 100644
--- a/drivers/firewire/fw-transaction.h
+++ b/drivers/firewire/fw-transaction.h
@@ -278,6 +278,8 @@ static inline void fw_card_put(struct fw_card *card)
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
* stored in 'header' immediately after the packet info plus an