ipmi: Prefer ACPI system interfaces over SMBIOS ones
authorCorey Minyard <cminyard@mvista.com>
Fri, 8 Sep 2017 19:05:58 +0000 (14:05 -0500)
committerCorey Minyard <cminyard@mvista.com>
Wed, 27 Sep 2017 21:03:45 +0000 (16:03 -0500)
The recent changes to add SMBIOS (DMI) IPMI interfaces as platform
devices caused DMI to be selected before ACPI, causing ACPI type
of operations to not work.

Signed-off-by: Corey Minyard <cminyard@mvista.com>
drivers/char/ipmi/ipmi_si_intf.c

index 39c55f4052b8f34d3d106b09c78078c522cc72c7..f8e28bad6d56b5fa140c06aff7b8774ea77f8680 100644 (file)
@@ -3425,7 +3425,7 @@ static inline void wait_for_timer_and_thread(struct smi_info *smi_info)
                del_timer_sync(&smi_info->si_timer);
 }
 
-static int is_new_interface(struct smi_info *info)
+static struct smi_info *find_dup_si(struct smi_info *info)
 {
        struct smi_info *e;
 
@@ -3440,24 +3440,36 @@ static int is_new_interface(struct smi_info *info)
                         */
                        if (info->slave_addr && !e->slave_addr)
                                e->slave_addr = info->slave_addr;
-                       return 0;
+                       return e;
                }
        }
 
-       return 1;
+       return NULL;
 }
 
 static int add_smi(struct smi_info *new_smi)
 {
        int rv = 0;
+       struct smi_info *dup;
 
        mutex_lock(&smi_infos_lock);
-       if (!is_new_interface(new_smi)) {
-               pr_info(PFX "%s-specified %s state machine: duplicate\n",
-                       ipmi_addr_src_to_str(new_smi->addr_source),
-                       si_to_str[new_smi->si_type]);
-               rv = -EBUSY;
-               goto out_err;
+       dup = find_dup_si(new_smi);
+       if (dup) {
+               if (new_smi->addr_source == SI_ACPI &&
+                   dup->addr_source == SI_SMBIOS) {
+                       /* We prefer ACPI over SMBIOS. */
+                       dev_info(dup->dev,
+                                "Removing SMBIOS-specified %s state machine in favor of ACPI\n",
+                                si_to_str[new_smi->si_type]);
+                       cleanup_one_si(dup);
+               } else {
+                       dev_info(new_smi->dev,
+                                "%s-specified %s state machine: duplicate\n",
+                                ipmi_addr_src_to_str(new_smi->addr_source),
+                                si_to_str[new_smi->si_type]);
+                       rv = -EBUSY;
+                       goto out_err;
+               }
        }
 
        pr_info(PFX "Adding %s-specified %s state machine\n",
@@ -3866,7 +3878,8 @@ static void cleanup_one_si(struct smi_info *to_clean)
                poll(to_clean);
                schedule_timeout_uninterruptible(1);
        }
-       disable_si_irq(to_clean, false);
+       if (to_clean->handlers)
+               disable_si_irq(to_clean, false);
        while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) {
                poll(to_clean);
                schedule_timeout_uninterruptible(1);