firewire: improve refcounting of fw_card
authorJay Fenlason <fenlason@redhat.com>
Sat, 29 Nov 2008 16:44:57 +0000 (17:44 +0100)
committerStefan Richter <stefanr@s5r6.in-berlin.de>
Sun, 4 Jan 2009 22:50:37 +0000 (23:50 +0100)
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)
drivers/firewire/fw-card.c
drivers/firewire/fw-device.c
drivers/firewire/fw-topology.c
drivers/firewire/fw-transaction.h

index c776079..799f944 100644 (file)
@@ -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);
 }
index 31b6c74..c173be3 100644 (file)
@@ -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)
index 5e20471..7687dca 100644 (file)
@@ -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);
 
index 839466f..0497a18 100644 (file)
@@ -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