Merge tag 'drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
[linux-2.6-block.git] / drivers / firewire / core-device.c
index 68109e9bb04e4395bdbeadc02e0edfa9229074a8..4d460ef871610d6309a47561bf0c531344e2b7cd 100644 (file)
@@ -481,6 +481,7 @@ static int read_rom(struct fw_device *device,
  * generation changes under us, read_config_rom will fail and get retried.
  * It's better to start all over in this case because the node from which we
  * are reading the ROM may have changed the ROM during the reset.
+ * Returns either a result code or a negative error code.
  */
 static int read_config_rom(struct fw_device *device, int generation)
 {
@@ -488,7 +489,7 @@ static int read_config_rom(struct fw_device *device, int generation)
        const u32 *old_rom, *new_rom;
        u32 *rom, *stack;
        u32 sp, key;
-       int i, end, length, ret = -1;
+       int i, end, length, ret;
 
        rom = kmalloc(sizeof(*rom) * MAX_CONFIG_ROM_SIZE +
                      sizeof(*stack) * MAX_CONFIG_ROM_SIZE, GFP_KERNEL);
@@ -502,18 +503,21 @@ static int read_config_rom(struct fw_device *device, int generation)
 
        /* First read the bus info block. */
        for (i = 0; i < 5; i++) {
-               if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
+               ret = read_rom(device, generation, i, &rom[i]);
+               if (ret != RCODE_COMPLETE)
                        goto out;
                /*
-                * As per IEEE1212 7.2, during power-up, devices can
+                * As per IEEE1212 7.2, during initialization, devices can
                 * reply with a 0 for the first quadlet of the config
                 * rom to indicate that they are booting (for example,
                 * if the firmware is on the disk of a external
                 * harddisk).  In that case we just fail, and the
                 * retry mechanism will try again later.
                 */
-               if (i == 0 && rom[i] == 0)
+               if (i == 0 && rom[i] == 0) {
+                       ret = RCODE_BUSY;
                        goto out;
+               }
        }
 
        device->max_speed = device->node->max_speed;
@@ -563,11 +567,14 @@ static int read_config_rom(struct fw_device *device, int generation)
                 */
                key = stack[--sp];
                i = key & 0xffffff;
-               if (WARN_ON(i >= MAX_CONFIG_ROM_SIZE))
+               if (WARN_ON(i >= MAX_CONFIG_ROM_SIZE)) {
+                       ret = -ENXIO;
                        goto out;
+               }
 
                /* Read header quadlet for the block to get the length. */
-               if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
+               ret = read_rom(device, generation, i, &rom[i]);
+               if (ret != RCODE_COMPLETE)
                        goto out;
                end = i + (rom[i] >> 16) + 1;
                if (end > MAX_CONFIG_ROM_SIZE) {
@@ -590,8 +597,8 @@ static int read_config_rom(struct fw_device *device, int generation)
                 * it references another block, and push it in that case.
                 */
                for (; i < end; i++) {
-                       if (read_rom(device, generation, i, &rom[i]) !=
-                           RCODE_COMPLETE)
+                       ret = read_rom(device, generation, i, &rom[i]);
+                       if (ret != RCODE_COMPLETE)
                                goto out;
 
                        if ((key >> 30) != 3 || (rom[i] >> 30) < 2)
@@ -619,8 +626,10 @@ static int read_config_rom(struct fw_device *device, int generation)
 
        old_rom = device->config_rom;
        new_rom = kmemdup(rom, length * 4, GFP_KERNEL);
-       if (new_rom == NULL)
+       if (new_rom == NULL) {
+               ret = -ENOMEM;
                goto out;
+       }
 
        down_write(&fw_device_rwsem);
        device->config_rom = new_rom;
@@ -628,7 +637,7 @@ static int read_config_rom(struct fw_device *device, int generation)
        up_write(&fw_device_rwsem);
 
        kfree(old_rom);
-       ret = 0;
+       ret = RCODE_COMPLETE;
        device->max_rec = rom[2] >> 12 & 0xf;
        device->cmc     = rom[2] >> 30 & 1;
        device->irmc    = rom[2] >> 31 & 1;
@@ -967,15 +976,17 @@ static void fw_device_init(struct work_struct *work)
         * device.
         */
 
-       if (read_config_rom(device, device->generation) < 0) {
+       ret = read_config_rom(device, device->generation);
+       if (ret != RCODE_COMPLETE) {
                if (device->config_rom_retries < MAX_RETRIES &&
                    atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
                        device->config_rom_retries++;
                        fw_schedule_device_work(device, RETRY_DELAY);
                } else {
                        if (device->node->link_on)
-                               fw_notice(card, "giving up on Config ROM for node id %x\n",
-                                         device->node_id);
+                               fw_notice(card, "giving up on node %x: reading config rom failed: %s\n",
+                                         device->node_id,
+                                         fw_rcode_string(ret));
                        if (device->node == card->root_node)
                                fw_schedule_bm_work(card, 0);
                        fw_device_release(&device->device);
@@ -1069,31 +1080,30 @@ static void fw_device_init(struct work_struct *work)
        put_device(&device->device);    /* our reference */
 }
 
-enum {
-       REREAD_BIB_ERROR,
-       REREAD_BIB_GONE,
-       REREAD_BIB_UNCHANGED,
-       REREAD_BIB_CHANGED,
-};
-
 /* Reread and compare bus info block and header of root directory */
-static int reread_config_rom(struct fw_device *device, int generation)
+static int reread_config_rom(struct fw_device *device, int generation,
+                            bool *changed)
 {
        u32 q;
-       int i;
+       int i, rcode;
 
        for (i = 0; i < 6; i++) {
-               if (read_rom(device, generation, i, &q) != RCODE_COMPLETE)
-                       return REREAD_BIB_ERROR;
+               rcode = read_rom(device, generation, i, &q);
+               if (rcode != RCODE_COMPLETE)
+                       return rcode;
 
                if (i == 0 && q == 0)
-                       return REREAD_BIB_GONE;
+                       /* inaccessible (see read_config_rom); retry later */
+                       return RCODE_BUSY;
 
-               if (q != device->config_rom[i])
-                       return REREAD_BIB_CHANGED;
+               if (q != device->config_rom[i]) {
+                       *changed = true;
+                       return RCODE_COMPLETE;
+               }
        }
 
-       return REREAD_BIB_UNCHANGED;
+       *changed = false;
+       return RCODE_COMPLETE;
 }
 
 static void fw_device_refresh(struct work_struct *work)
@@ -1101,23 +1111,14 @@ static void fw_device_refresh(struct work_struct *work)
        struct fw_device *device =
                container_of(work, struct fw_device, work.work);
        struct fw_card *card = device->card;
-       int node_id = device->node_id;
-
-       switch (reread_config_rom(device, device->generation)) {
-       case REREAD_BIB_ERROR:
-               if (device->config_rom_retries < MAX_RETRIES / 2 &&
-                   atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
-                       device->config_rom_retries++;
-                       fw_schedule_device_work(device, RETRY_DELAY / 2);
-
-                       return;
-               }
-               goto give_up;
+       int ret, node_id = device->node_id;
+       bool changed;
 
-       case REREAD_BIB_GONE:
-               goto gone;
+       ret = reread_config_rom(device, device->generation, &changed);
+       if (ret != RCODE_COMPLETE)
+               goto failed_config_rom;
 
-       case REREAD_BIB_UNCHANGED:
+       if (!changed) {
                if (atomic_cmpxchg(&device->state,
                                   FW_DEVICE_INITIALIZING,
                                   FW_DEVICE_RUNNING) == FW_DEVICE_GONE)
@@ -1126,9 +1127,6 @@ static void fw_device_refresh(struct work_struct *work)
                fw_device_update(work);
                device->config_rom_retries = 0;
                goto out;
-
-       case REREAD_BIB_CHANGED:
-               break;
        }
 
        /*
@@ -1137,16 +1135,9 @@ static void fw_device_refresh(struct work_struct *work)
         */
        device_for_each_child(&device->device, NULL, shutdown_unit);
 
-       if (read_config_rom(device, device->generation) < 0) {
-               if (device->config_rom_retries < MAX_RETRIES &&
-                   atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
-                       device->config_rom_retries++;
-                       fw_schedule_device_work(device, RETRY_DELAY);
-
-                       return;
-               }
-               goto give_up;
-       }
+       ret = read_config_rom(device, device->generation);
+       if (ret != RCODE_COMPLETE)
+               goto failed_config_rom;
 
        fw_device_cdev_update(device);
        create_units(device);
@@ -1163,9 +1154,16 @@ static void fw_device_refresh(struct work_struct *work)
        device->config_rom_retries = 0;
        goto out;
 
- give_up:
-       fw_notice(card, "giving up on refresh of device %s\n",
-                 dev_name(&device->device));
+ failed_config_rom:
+       if (device->config_rom_retries < MAX_RETRIES &&
+           atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
+               device->config_rom_retries++;
+               fw_schedule_device_work(device, RETRY_DELAY);
+               return;
+       }
+
+       fw_notice(card, "giving up on refresh of device %s: %s\n",
+                 dev_name(&device->device), fw_rcode_string(ret));
  gone:
        atomic_set(&device->state, FW_DEVICE_GONE);
        PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);