]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
[IA64-SGI] Older PROM WAR for device flush code
authorPrarit Bhargava <prarit@sgi.com>
Mon, 16 Jan 2006 20:31:52 +0000 (15:31 -0500)
committerTony Luck <tony.luck@intel.com>
Tue, 17 Jan 2006 18:08:37 +0000 (10:08 -0800)
Work-around to temporarily support older PROMs with new flush device code.

This code allows systems running older PROMs to continue to run on the new
kernel base until a new official PROM is released.

Signed-off-by: Prarit Bhargava <prarit@sgi.com>
Acked-by: Jes Sorensen <jes@sgi.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
arch/ia64/sn/include/xtalk/hubdev.h
arch/ia64/sn/kernel/io_init.c

index 7c88e9a585169cfa89f970178213b59c3b28078f..8182583c762c6a4928857373041cb900779044d0 100644 (file)
@@ -51,6 +51,15 @@ struct sn_flush_device_kernel {
        struct sn_flush_device_common *common;
 };
 
+/* 01/16/06 This struct is the old PROM/kernel struct and needs to be included
+ * for older official PROMs to function on the new kernel base.  This struct
+ * will be removed when the next official PROM release occurs. */
+
+struct sn_flush_device_war {
+       struct sn_flush_device_common common;
+       u32 filler; /* older PROMs expect the default size of a spinlock_t */
+};
+
 /*
  * **widget_p - Used as an array[wid_num][device] of sn_flush_device_kernel.
  */
index 233d55115d33013defe9b266d474c04d3171d2bb..00700f7e68376c72d1be595c70b7fb1b7adca1b9 100644 (file)
@@ -165,8 +165,45 @@ sn_pcidev_info_get(struct pci_dev *dev)
        return NULL;
 }
 
+/* Older PROM flush WAR
+ *
+ * 01/16/06 -- This war will be in place until a new official PROM is released.
+ * Additionally note that the struct sn_flush_device_war also has to be
+ * removed from arch/ia64/sn/include/xtalk/hubdev.h
+ */
+static u8 war_implemented = 0;
+
+static void sn_device_fixup_war(u64 nasid, u64 widget, int device,
+                               struct sn_flush_device_common *common)
+{
+       struct sn_flush_device_war *war_list;
+       struct sn_flush_device_war *dev_entry;
+       struct ia64_sal_retval isrv = {0,0,0,0};
+
+       if (!war_implemented) {
+               printk(KERN_WARNING "PROM version < 4.50 -- implementing old "
+                      "PROM flush WAR\n");
+               war_implemented = 1;
+       }
+
+       war_list = kzalloc(DEV_PER_WIDGET * sizeof(*war_list), GFP_KERNEL);
+       if (!war_list)
+               BUG();
+
+       SAL_CALL_NOLOCK(isrv, SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST,
+                       nasid, widget, __pa(war_list), 0, 0, 0 ,0);
+       if (isrv.status)
+               panic("sn_device_fixup_war failed: %s\n",
+                     ia64_sal_strerror(isrv.status));
+
+       dev_entry = war_list + device;
+       memcpy(common,dev_entry, sizeof(*common));
+
+       kfree(war_list);
+}
+
 /*
- * sn_fixup_ionodes() - This routine initializes the HUB data strcuture for 
+ * sn_fixup_ionodes() - This routine initializes the HUB data strcuture for
  *     each node in the system.
  */
 static void sn_fixup_ionodes(void)
@@ -246,8 +283,19 @@ static void sn_fixup_ionodes(void)
                                                                        widget,
                                                                        device,
                                                      (u64)(dev_entry->common));
-                               if (status)
-                                       BUG();
+                               if (status) {
+                                       if (sn_sal_rev() < 0x0450) {
+                                               /* shortlived WAR for older
+                                                * PROM images
+                                                */
+                                               sn_device_fixup_war(nasid,
+                                                                   widget,
+                                                                   device,
+                                                            dev_entry->common);
+                                       }
+                                       else
+                                               BUG();
+                               }
 
                                spin_lock_init(&dev_entry->sfdl_flush_lock);
                        }