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