ibft: Fix finding IBFT ACPI table on UEFI
[linux-2.6.git] / drivers / firmware / iscsi_ibft.c
index 6148a1c..2cce44a 100644 (file)
@@ -87,8 +87,8 @@
 #define IBFT_ISCSI_VERSION "0.5.0"
 #define IBFT_ISCSI_DATE "2010-Feb-25"
 
-MODULE_AUTHOR("Peter Jones <pjones@redhat.com> and \
-Konrad Rzeszutek <ketuzsezr@darnok.org>");
+MODULE_AUTHOR("Peter Jones <pjones@redhat.com> and "
+             "Konrad Rzeszutek <ketuzsezr@darnok.org>");
 MODULE_DESCRIPTION("sysfs interface to BIOS iBFT information");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(IBFT_ISCSI_VERSION);
@@ -566,6 +566,11 @@ static mode_t __init ibft_check_initiator_for(void *data, int type)
        return rc;
 }
 
+static void ibft_kobj_release(void *data)
+{
+       kfree(data);
+}
+
 /*
  * Helper function for ibft_register_kobjects.
  */
@@ -595,7 +600,8 @@ static int __init ibft_create_kobject(struct acpi_table_ibft *header,
                boot_kobj = iscsi_boot_create_initiator(boot_kset, hdr->index,
                                                ibft_kobj,
                                                ibft_attr_show_initiator,
-                                               ibft_check_initiator_for);
+                                               ibft_check_initiator_for,
+                                               ibft_kobj_release);
                if (!boot_kobj) {
                        rc = -ENOMEM;
                        goto free_ibft_obj;
@@ -610,7 +616,8 @@ static int __init ibft_create_kobject(struct acpi_table_ibft *header,
                boot_kobj = iscsi_boot_create_ethernet(boot_kset, hdr->index,
                                                       ibft_kobj,
                                                       ibft_attr_show_nic,
-                                                      ibft_check_nic_for);
+                                                      ibft_check_nic_for,
+                                                      ibft_kobj_release);
                if (!boot_kobj) {
                        rc = -ENOMEM;
                        goto free_ibft_obj;
@@ -625,7 +632,8 @@ static int __init ibft_create_kobject(struct acpi_table_ibft *header,
                boot_kobj = iscsi_boot_create_target(boot_kset, hdr->index,
                                                     ibft_kobj,
                                                     ibft_attr_show_target,
-                                                    ibft_check_tgt_for);
+                                                    ibft_check_tgt_for,
+                                                    ibft_kobj_release);
                if (!boot_kobj) {
                        rc = -ENOMEM;
                        goto free_ibft_obj;
@@ -738,6 +746,37 @@ static void __exit ibft_exit(void)
        ibft_cleanup();
 }
 
+#ifdef CONFIG_ACPI
+static const struct {
+       char *sign;
+} ibft_signs[] = {
+       /*
+        * One spec says "IBFT", the other says "iBFT". We have to check
+        * for both.
+        */
+       { ACPI_SIG_IBFT },
+       { "iBFT" },
+};
+
+static void __init acpi_find_ibft_region(void)
+{
+       int i;
+       struct acpi_table_header *table = NULL;
+
+       if (acpi_disabled)
+               return;
+
+       for (i = 0; i < ARRAY_SIZE(ibft_signs) && !ibft_addr; i++) {
+               acpi_get_table(ibft_signs[i].sign, 0, &table);
+               ibft_addr = (struct acpi_table_ibft *)table;
+       }
+}
+#else
+static void __init acpi_find_ibft_region(void)
+{
+}
+#endif
+
 /*
  * ibft_init() - creates sysfs tree entries for the iBFT data.
  */
@@ -745,9 +784,16 @@ static int __init ibft_init(void)
 {
        int rc = 0;
 
+       /*
+          As on UEFI systems the setup_arch()/find_ibft_region()
+          is called before ACPI tables are parsed and it only does
+          legacy finding.
+       */
+       if (!ibft_addr)
+               acpi_find_ibft_region();
+
        if (ibft_addr) {
-               printk(KERN_INFO "iBFT detected at 0x%llx.\n",
-                      (u64)isa_virt_to_bus(ibft_addr));
+               pr_info("iBFT detected.\n");
 
                rc = ibft_check_device();
                if (rc)