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 this case both send a command and get a currupted response.

This patch adds check to void registering the same device twice.

Signed-off-by: Kamlakant Patel <kamlaka...@marvell.com>
---
 drivers/char/ipmi/ipmi_ssif.c | 39 +++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c
index ca9528c4f183..97830d31c5d3 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,34 @@ 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)
 
+static int ssif_is_registered(struct i2c_client *client)
+{
+       struct ssif_addr_info *info;
+       int rv = 0;
+
+       mutex_lock(&ssif_infos_mutex);
+       list_for_each_entry(info, &ssif_clients, link) {
+               if ((info->binfo.addr == client->addr) &&
+                  (!strcmp(info->adapter_name, client->adapter->name))) {
+                       rv = -EEXIST;
+                       goto exit;
+               }
+       }
+
+       info = kzalloc(sizeof(*info), GFP_KERNEL);
+       if (!info){
+               rv = -ENOMEM;
+               goto exit;
+       }
+
+       info->adapter_name = client->adapter->name;
+       info->binfo.addr = client->addr;
+       list_add_tail(&info->link, &ssif_clients);
+exit:
+       mutex_unlock(&ssif_infos_mutex);
+       return rv;
+}
+
 static int ssif_probe(struct i2c_client *client, const struct i2c_device_id 
*id)
 {
        unsigned char     msg[3];
@@ -1534,6 +1563,10 @@ 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;
 
+       /* Check if the client is already registered. */
+       if (ssif_is_registered(client))
+               return 0;
+
        resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL);
        if (!resp)
                return -ENOMEM;
@@ -1844,6 +1877,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);
 }
 
-- 
2.17.1



_______________________________________________
Openipmi-developer mailing list
Openipmi-developer@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openipmi-developer

Reply via email to