Blob Blame History Raw
From c0734bd594d43a28afcbe476bbf0d35a5bbffa4c Mon Sep 17 00:00:00 2001
From: Corey Minyard <cminyard@mvista.com>
Date: Thu, 31 Aug 2017 17:09:03 -0500
Subject: [PATCH] ipmi: Retry BMC registration on a failure
Git-commit: c0734bd594d43a28afcbe476bbf0d35a5bbffa4c
Patch-mainline: v4.15-rc1
References: FATE#326156

If the BMC fails to register, just set up to retry periodically.

Signed-off-by: Corey Minyard <cminyard@mvista.com>
Acked-by: Takashi Iwai <tiwai@suse.de>

---
 drivers/char/ipmi/ipmi_msghandler.c | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 1da0b3cca6aa..c6ee1de8d76b 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -47,6 +47,7 @@
 #include <linux/rcupdate.h>
 #include <linux/interrupt.h>
 #include <linux/moduleparam.h>
+#include <linux/workqueue.h>
 
 #define PFX "IPMI message handler: "
 
@@ -430,6 +431,7 @@ struct ipmi_smi {
 	struct list_head bmc_link;
 	char *my_dev_name;
 	bool in_bmc_register;  /* Handle recursive situations.  Yuck. */
+	struct work_struct bmc_reg_work;
 
 	/*
 	 * This is the lower-layer's sender routine.  Note that you
@@ -2275,7 +2277,8 @@ static int __bmc_get_device_id(ipmi_smi_t intf, struct bmc_device *bmc,
 		intf->bmc->id = id;
 		intf->bmc->dyn_guid_set = guid_set;
 		memcpy(intf->bmc->guid, guid, 16);
-		rv = __ipmi_bmc_register(intf, &id, guid_set, guid, intf_num);
+		if (__ipmi_bmc_register(intf, &id, guid_set, guid, intf_num))
+			need_waiter(intf); /* Retry later on an error. */
 
 		if (!intf_set) {
 			/*
@@ -3276,6 +3279,16 @@ void ipmi_poll_interface(ipmi_user_t user)
 }
 EXPORT_SYMBOL(ipmi_poll_interface);
 
+static void redo_bmc_reg(struct work_struct *work)
+{
+	ipmi_smi_t intf = container_of(work, struct ipmi_smi, bmc_reg_work);
+
+	if (!intf->in_shutdown)
+		bmc_get_device_id(intf, NULL, NULL, NULL, NULL);
+
+	kref_put(&intf->refcount, intf_free);
+}
+
 int ipmi_register_smi(const struct ipmi_smi_handlers *handlers,
 		      void		       *send_info,
 		      struct device            *si_dev,
@@ -3315,6 +3328,7 @@ int ipmi_register_smi(const struct ipmi_smi_handlers *handlers,
 	mutex_init(&intf->bmc_reg_mutex);
 	intf->intf_num = -1; /* Mark it invalid for now. */
 	kref_init(&intf->refcount);
+	INIT_WORK(&intf->bmc_reg_work, redo_bmc_reg);
 	intf->si_dev = si_dev;
 	for (j = 0; j < IPMI_MAX_CHANNELS; j++) {
 		intf->channels[j].address = IPMI_BMC_SLAVE_ADDR;
@@ -4641,6 +4655,14 @@ static unsigned int ipmi_timeout_handler(ipmi_smi_t intf,
 	int                  i;
 	unsigned int         waiting_msgs = 0;
 
+	if (!intf->bmc_registered) {
+		kref_get(&intf->refcount);
+		if (!schedule_work(&intf->bmc_reg_work)) {
+			kref_put(&intf->refcount, intf_free);
+			waiting_msgs++;
+		}
+	}
+
 	/*
 	 * Go through the seq table and find any messages that
 	 * have timed out, putting them in the timeouts
-- 
2.19.2