diff mbox series

ipmi: Prefer ACPI system interfaces over SMBIOS ones

Message ID 1510256927-8033-1-git-send-email-minyard@acm.org
State New
Headers show
Series ipmi: Prefer ACPI system interfaces over SMBIOS ones | expand

Commit Message

Corey Minyard Nov. 9, 2017, 7:48 p.m. UTC
From: Corey Minyard <cminyard@mvista.com>


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>

---

Andrew,

I looked a bit more and found that I already had this queued for the
next kernel release, it fixes your issue and another issue, too.
If this works for you, I'll request this for stable.

-corey

 drivers/char/ipmi/ipmi_si_intf.c | 33 +++++++++++++++++++++++----------
 1 file changed, 23 insertions(+), 10 deletions(-)

-- 
2.7.4

Comments

Banman, Andrew Nov. 9, 2017, 9:50 p.m. UTC | #1
Corey,

This patch worked on my system. Thank you!

Tested-by: Andrew Banman <abanman@hpe.com>


# insmod ipmi_si.ko; dmesg -c
[  225.793934] ipmi_si IPI0001:00: ipmi_si: probing via ACPI
[  225.799982] ipmi_si IPI0001:00: [io  0x0ce4-0x0ce6] regsize 1 spacing 1 irq 6
[  225.807953] ipmi_si: Adding ACPI-specified bt state machine
[  225.814202] IPMI System Interface driver.
[  225.818895] ipmi_si: probing via SMBIOS
[  225.823183] ipmi_si: SMBIOS: mem 0xce4 regsize 1 spacing 1 irq 6
[  225.829894] ipmi_si: Adding SMBIOS-specified bt state machine
[  225.836318] ipmi_si: probing via SPMI
[  225.840411] ipmi_si: SPMI: io 0xce4 regsize 1 spacing 1 irq 6
[  225.846832] (NULL device *): SPMI-specified bt state machine: duplicate
[  225.854220] ipmi_si: Trying ACPI-specified bt state machine at i/o address 
0xce4, slave address 0x0, irq 6
[  225.870711] ipmi_si IPI0001:00: Using irq 6
[  225.875530] ipmi_si IPI0001:00: Found new BMC (man_id: 0x000000, prod_id: 
0x0101, dev_id: 0x20)
[  225.876266] IPMI BT: req2rsp=2 secs retries=1
[  225.890166] ipmi_si IPI0001:00: IPMI bt interface initialized
# rmmod ipmi_si.ko; dmesg -c
#

Andrew

On 11/9/17 1:48 PM, minyard@acm.org wrote:
> From: Corey Minyard <cminyard@mvista.com>

> 

> 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>

> ---

> 

> Andrew,

> 

> I looked a bit more and found that I already had this queued for the

> next kernel release, it fixes your issue and another issue, too.

> If this works for you, I'll request this for stable.

> 

> -corey

> 

>   drivers/char/ipmi/ipmi_si_intf.c | 33 +++++++++++++++++++++++----------

>   1 file changed, 23 insertions(+), 10 deletions(-)

> 

> diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c

> index 39c55f4..f8e28ba 100644

> --- a/drivers/char/ipmi/ipmi_si_intf.c

> +++ b/drivers/char/ipmi/ipmi_si_intf.c

> @@ -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);

>
diff mbox series

Patch

diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 39c55f4..f8e28ba 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -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);