Hi Corey,

Could you please review this patch and provide your valuable comments?

Thanks,
Kamlakant Patel

On 12/28/18 5:59 PM, Kamlakant Patel wrote:
> We have SSIF interface present in both DMI and ACPI tables, sometimes
> ssif_probe is called simultaneously from i2c interface (from ACPI)
> and while loading ipmi_ssif driver(from DMI table) at kernel boot.
> Both try to register the same SSIF interface simultaneously, where it
> hits a race.
> 
> In cases where ACPI and SMBIOS both are available, we need to prefer ACPI
> over SMBIOS so that ACPI functions work properly if they use IPMI.
> So if we get an ACPI interface and have already registered an SMBIOS interface
> at the same address, we need to remove the SMBIOS one and add the ACPI one.
> 
> Signed-off-by: Kamlakant Patel <[email protected]>
> ---
>   drivers/char/ipmi/ipmi_ssif.c | 52 +++++++++++++++++++++++++++++++++++
>   1 file changed, 52 insertions(+)
> 
> diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c
> index ca9528c4f183..8d60e5cd2e17 100644
> --- a/drivers/char/ipmi/ipmi_ssif.c
> +++ b/drivers/char/ipmi/ipmi_ssif.c
> @@ -1146,6 +1146,7 @@ MODULE_PARM_DESC(trydmi, "Setting this to zero will 
> disable the default scan of
>   
>   static DEFINE_MUTEX(ssif_infos_mutex);
>   static LIST_HEAD(ssif_infos);
> +static LIST_HEAD(ssif_clients);
>   
>   #define IPMI_SSIF_ATTR(name) \
>   static ssize_t ipmi_##name##_show(struct device *dev,                       
> \
> @@ -1523,6 +1524,43 @@ static void test_multipart_messages(struct i2c_client 
> *client,
>   #define GLOBAL_ENABLES_MASK (IPMI_BMC_EVT_MSG_BUFF | IPMI_BMC_RCV_MSG_INTR 
> | \
>                            IPMI_BMC_EVT_MSG_INTR)
>   
> +/*
> + * Prefer ACPI over SMBIOS, if both are available.
> + * So if we get an ACPI interface and have already registered a SMBIOS
> + * interface at the same address, remove the SMBIOS and add the ACPI one.
> + */
> +static int ssif_is_registered(struct i2c_client *client)
> +{
> +     struct ssif_addr_info *info;
> +     int rv = 0;
> +
> +     list_for_each_entry(info, &ssif_clients, link) {
> +             if ((info->binfo.addr == client->addr) &&
> +                (!strcmp(info->adapter_name, client->adapter->name))) {
> +                     if (!ACPI_HANDLE(&info->client->dev)) {
> +                             /* Remove SMBIOS interface */
> +                             ssif_remove(info->client);
> +                             rv = 0;
> +                     } else
> +                             rv = -EEXIST;
> +                     goto exit;
> +             }
> +     }
> +
> +     info = kzalloc(sizeof(*info), GFP_KERNEL);
> +     if (!info){
> +             rv = -ENOMEM;
> +             goto exit;
> +     }
> +
> +     info->client = client;
> +     info->adapter_name = client->adapter->name;
> +     info->binfo.addr = client->addr;
> +     list_add_tail(&info->link, &ssif_clients);
> +exit:
> +     return rv;
> +}
> +
>   static int ssif_probe(struct i2c_client *client, const struct i2c_device_id 
> *id)
>   {
>       unsigned char     msg[3];
> @@ -1534,6 +1572,13 @@ static int ssif_probe(struct i2c_client *client, const 
> struct i2c_device_id *id)
>       u8                slave_addr = 0;
>       struct ssif_addr_info *addr_info = NULL;
>   
> +     mutex_lock(&ssif_infos_mutex);
> +     /* Check if the client is already registered. */
> +     if (ssif_is_registered(client)) {
> +             mutex_unlock(&ssif_infos_mutex);
> +             return 0;
> +     }
> +
>       resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL);
>       if (!resp)
>               return -ENOMEM;
> @@ -1759,6 +1804,7 @@ static int ssif_probe(struct i2c_client *client, const 
> struct i2c_device_id *id)
>               kfree(ssif_info);
>       }
>       kfree(resp);
> +     mutex_unlock(&ssif_infos_mutex);
>       return rv;
>   
>   out_remove_attr:
> @@ -1844,6 +1890,12 @@ static void free_ssif_clients(void)
>               kfree(info->adapter_name);
>               kfree(info);
>       }
> +
> +     list_for_each_entry_safe(info, tmp, &ssif_clients, link) {
> +             list_del(&info->link);
> +             kfree(info);
> +     }
> +
>       mutex_unlock(&ssif_infos_mutex);
>   }
>   
> 



_______________________________________________
Openipmi-developer mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openipmi-developer

Reply via email to