Merge branch 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / drivers / firewire / fw-card.c
index bbd73a406e537106a2eeda4ba4a2ba1a543b030d..6bd91a15d5e6a8397f9aa0988c510cb97f11df4b 100644 (file)
@@ -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,27 +189,15 @@ static const char gap_count_table[] = {
        63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40
 };
 
-struct bm_data {
-       struct fw_transaction t;
-       struct {
-               __be32 arg;
-               __be32 data;
-       } lock;
-       u32 old;
-       int rcode;
-       struct completion done;
-};
-
-static void
-complete_bm_lock(struct fw_card *card, int rcode,
-                void *payload, size_t length, void *data)
+void
+fw_schedule_bm_work(struct fw_card *card, unsigned long delay)
 {
-       struct bm_data *bmd = data;
+       int scheduled;
 
-       if (rcode == RCODE_COMPLETE)
-               bmd->old = be32_to_cpu(*(__be32 *) payload);
-       bmd->rcode = rcode;
-       complete(&bmd->done);
+       fw_card_get(card);
+       scheduled = schedule_delayed_work(&card->work, delay);
+       if (!scheduled)
+               fw_card_put(card);
 }
 
 static void
@@ -218,10 +206,12 @@ fw_card_bm_work(struct work_struct *work)
        struct fw_card *card = container_of(work, struct fw_card, work.work);
        struct fw_device *root_device;
        struct fw_node *root_node, *local_node;
-       struct bm_data bmd;
        unsigned long flags;
-       int root_id, new_root_id, irm_id, gap_count, generation, grace;
+       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);
        local_node = card->local_node;
@@ -229,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));
 
@@ -263,33 +254,28 @@ fw_card_bm_work(struct work_struct *work)
                        goto pick_me;
                }
 
-               bmd.lock.arg = cpu_to_be32(0x3f);
-               bmd.lock.data = cpu_to_be32(local_node->node_id);
+               lock_data[0] = cpu_to_be32(0x3f);
+               lock_data[1] = cpu_to_be32(local_node->node_id);
 
                spin_unlock_irqrestore(&card->lock, flags);
 
-               init_completion(&bmd.done);
-               fw_send_request(card, &bmd.t, TCODE_LOCK_COMPARE_SWAP,
-                               irm_id, generation,
-                               SCODE_100, CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID,
-                               &bmd.lock, sizeof(bmd.lock),
-                               complete_bm_lock, &bmd);
-               wait_for_completion(&bmd.done);
+               rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,
+                               irm_id, generation, SCODE_100,
+                               CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID,
+                               lock_data, sizeof(lock_data));
 
-               if (bmd.rcode == RCODE_GENERATION) {
-                       /*
-                        * Another bus reset happened. Just return,
-                        * the BM work has been rescheduled.
-                        */
+               if (rcode == RCODE_GENERATION)
+                       /* Another bus reset, BM work has been rescheduled. */
                        goto out;
-               }
 
-               if (bmd.rcode == RCODE_COMPLETE && bmd.old != 0x3f)
+               if (rcode == RCODE_COMPLETE &&
+                   lock_data[0] != cpu_to_be32(0x3f))
                        /* Somebody else is BM, let them do the work. */
                        goto out;
 
                spin_lock_irqsave(&card->lock, flags);
-               if (bmd.rcode != RCODE_COMPLETE) {
+
+               if (rcode != RCODE_COMPLETE) {
                        /*
                         * The lock request failed, maybe the IRM
                         * isn't really IRM capable after all. Let's
@@ -308,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;
        }
 
@@ -325,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
@@ -379,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
@@ -538,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);
 }