diff options
author | Tony Camuso <tcamuso@redhat.com> | 2017-04-10 12:22:13 -0400 |
---|---|---|
committer | Corey Minyard <cminyard@mvista.com> | 2017-04-10 13:42:10 -0400 |
commit | 3f724c408a7bcf25609f6a0102b835d5970cadd3 (patch) | |
tree | 018a97b7d1f977fe65204c4780181a0089bb5111 | |
parent | 7ecaff7733b50da8e02d22be6719069892633c53 (diff) |
ipmi_si: use smi_num for init_name
Commit 1abf71e moved the creation of new_smi->dev to earlier in the init
sequence in order to provide infrastructure for log printing.
However, the init_name was created with a hard-coded value of zero. This
presents a problem in systems with more than one interface, producing a
call trace in dmesg.
To correct the problem, simply use smi_num instead of the hard-coded
value of zero.
Tested on a lenovo x3950.
Signed-off-by: Tony Camuso <tcamuso@redhat.com>
There was actually a more general problem, the platform device wasn't
being set correctly, either, and there was a possible (though extremely
unlikely) race on smi_num. Add locks to clean up the race and use the
proper value for the platform device, too.
Tested on qemu in various configurations.
Signed-off-by: Corey Minyard <cminyard@mvista.com>
-rw-r--r-- | drivers/char/ipmi/ipmi_si_intf.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 2a7c425ddfa7..b2b618f066e0 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -1954,7 +1954,9 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) | |||
1954 | kfree(info); | 1954 | kfree(info); |
1955 | goto out; | 1955 | goto out; |
1956 | } | 1956 | } |
1957 | mutex_lock(&smi_infos_lock); | ||
1957 | rv = try_smi_init(info); | 1958 | rv = try_smi_init(info); |
1959 | mutex_unlock(&smi_infos_lock); | ||
1958 | if (rv) { | 1960 | if (rv) { |
1959 | cleanup_one_si(info); | 1961 | cleanup_one_si(info); |
1960 | goto out; | 1962 | goto out; |
@@ -2042,8 +2044,10 @@ static int hardcode_find_bmc(void) | |||
2042 | info->slave_addr = slave_addrs[i]; | 2044 | info->slave_addr = slave_addrs[i]; |
2043 | 2045 | ||
2044 | if (!add_smi(info)) { | 2046 | if (!add_smi(info)) { |
2047 | mutex_lock(&smi_infos_lock); | ||
2045 | if (try_smi_init(info)) | 2048 | if (try_smi_init(info)) |
2046 | cleanup_one_si(info); | 2049 | cleanup_one_si(info); |
2050 | mutex_unlock(&smi_infos_lock); | ||
2047 | ret = 0; | 2051 | ret = 0; |
2048 | } else { | 2052 | } else { |
2049 | kfree(info); | 2053 | kfree(info); |
@@ -3492,6 +3496,11 @@ out_err: | |||
3492 | return rv; | 3496 | return rv; |
3493 | } | 3497 | } |
3494 | 3498 | ||
3499 | /* | ||
3500 | * Try to start up an interface. Must be called with smi_infos_lock | ||
3501 | * held, primarily to keep smi_num consistent, we only one to do these | ||
3502 | * one at a time. | ||
3503 | */ | ||
3495 | static int try_smi_init(struct smi_info *new_smi) | 3504 | static int try_smi_init(struct smi_info *new_smi) |
3496 | { | 3505 | { |
3497 | int rv = 0; | 3506 | int rv = 0; |
@@ -3524,9 +3533,12 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3524 | goto out_err; | 3533 | goto out_err; |
3525 | } | 3534 | } |
3526 | 3535 | ||
3536 | new_smi->intf_num = smi_num; | ||
3537 | |||
3527 | /* Do this early so it's available for logs. */ | 3538 | /* Do this early so it's available for logs. */ |
3528 | if (!new_smi->dev) { | 3539 | if (!new_smi->dev) { |
3529 | init_name = kasprintf(GFP_KERNEL, "ipmi_si.%d", 0); | 3540 | init_name = kasprintf(GFP_KERNEL, "ipmi_si.%d", |
3541 | new_smi->intf_num); | ||
3530 | 3542 | ||
3531 | /* | 3543 | /* |
3532 | * If we don't already have a device from something | 3544 | * If we don't already have a device from something |
@@ -3593,8 +3605,6 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3593 | 3605 | ||
3594 | new_smi->interrupt_disabled = true; | 3606 | new_smi->interrupt_disabled = true; |
3595 | atomic_set(&new_smi->need_watch, 0); | 3607 | atomic_set(&new_smi->need_watch, 0); |
3596 | new_smi->intf_num = smi_num; | ||
3597 | smi_num++; | ||
3598 | 3608 | ||
3599 | rv = try_enable_event_buffer(new_smi); | 3609 | rv = try_enable_event_buffer(new_smi); |
3600 | if (rv == 0) | 3610 | if (rv == 0) |
@@ -3661,6 +3671,9 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3661 | goto out_err_stop_timer; | 3671 | goto out_err_stop_timer; |
3662 | } | 3672 | } |
3663 | 3673 | ||
3674 | /* Don't increment till we know we have succeeded. */ | ||
3675 | smi_num++; | ||
3676 | |||
3664 | dev_info(new_smi->dev, "IPMI %s interface initialized\n", | 3677 | dev_info(new_smi->dev, "IPMI %s interface initialized\n", |
3665 | si_to_str[new_smi->si_type]); | 3678 | si_to_str[new_smi->si_type]); |
3666 | 3679 | ||