]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/powerpc/platforms/ps3/device-init.c
[POWERPC] PS3: Add repository polling loop to work around timing bug
[linux-2.6-omap-h63xx.git] / arch / powerpc / platforms / ps3 / device-init.c
index 5695e00219e438bb8e69268d29ac7c8d63ed5944..05c7c1c624dcd3079b86e9da0a65a18b160536c7 100644 (file)
@@ -489,6 +489,38 @@ static int ps3_register_repository_device(
        return result;
 }
 
+static void ps3_find_and_add_device(u64 bus_id, u64 dev_id)
+{
+       struct ps3_repository_device repo;
+       int res;
+       unsigned int retries;
+       unsigned long rem;
+
+       /*
+        * On some firmware versions (e.g. 1.90), the device may not show up
+        * in the repository immediately
+        */
+       for (retries = 0; retries < 10; retries++) {
+               res = ps3_repository_find_device_by_id(&repo, bus_id, dev_id);
+               if (!res)
+                       goto found;
+
+               rem = msleep_interruptible(100);
+               if (rem)
+                       break;
+       }
+       pr_warning("%s:%u: device %lu:%lu not found\n", __func__, __LINE__,
+                  bus_id, dev_id);
+       return;
+
+found:
+       if (retries)
+               pr_debug("%s:%u: device %lu:%lu found after %u retries\n",
+                        __func__, __LINE__, bus_id, dev_id, retries);
+
+       ps3_register_repository_device(&repo);
+       return;
+}
 
 #define PS3_NOTIFICATION_DEV_ID                ULONG_MAX
 #define PS3_NOTIFICATION_INTERRUPT_ID  0
@@ -600,7 +632,6 @@ static struct task_struct *probe_task;
 static int ps3_probe_thread(void *data)
 {
        struct ps3_notification_device dev;
-       struct ps3_repository_device repo;
        int res;
        unsigned int irq;
        u64 lpar;
@@ -682,18 +713,7 @@ static int ps3_probe_thread(void *data)
                        continue;
                }
 
-               res = ps3_repository_find_device_by_id(&repo, dev.sbd.bus_id,
-                                                      notify_event->dev_id);
-               if (res) {
-                       pr_warning("%s:%u: device %lu:%lu not found\n",
-                                  __func__, __LINE__, dev.sbd.bus_id,
-                                  notify_event->dev_id);
-                       continue;
-               }
-
-               pr_debug("%s:%u: device %lu:%lu found\n", __func__, __LINE__,
-                        dev.sbd.bus_id, notify_event->dev_id);
-               ps3_register_repository_device(&repo);
+               ps3_find_and_add_device(dev.sbd.bus_id, notify_event->dev_id);
 
        } while (!kthread_should_stop());