From b22da3d8526a935aa31e086e63f60ff3246cb61c Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Sat, 09 Dec 2023 07:24:11 +0000
Subject: [PATCH] add stmac read mac form eeprom

---
 kernel/drivers/char/ipmi/ipmi_si_hotmod.c |  238 ++++++++++++++++++++++++++++++-----------------------------
 1 files changed, 121 insertions(+), 117 deletions(-)

diff --git a/kernel/drivers/char/ipmi/ipmi_si_hotmod.c b/kernel/drivers/char/ipmi/ipmi_si_hotmod.c
index a98ca42..4fbb4e1 100644
--- a/kernel/drivers/char/ipmi/ipmi_si_hotmod.c
+++ b/kernel/drivers/char/ipmi/ipmi_si_hotmod.c
@@ -5,17 +5,20 @@
  * Handling for dynamically adding/removing IPMI devices through
  * a module parameter (and thus sysfs).
  */
+
+#define pr_fmt(fmt) "ipmi_hotmod: " fmt
+
 #include <linux/moduleparam.h>
 #include <linux/ipmi.h>
+#include <linux/atomic.h>
 #include "ipmi_si.h"
-
-#define PFX "ipmi_hotmod: "
+#include "ipmi_plat_data.h"
 
 static int hotmod_handler(const char *val, const struct kernel_param *kp);
 
 module_param_call(hotmod, hotmod_handler, NULL, NULL, 0200);
 MODULE_PARM_DESC(hotmod, "Add and remove interfaces.  See"
-		 " Documentation/IPMI.txt in the kernel sources for the"
+		 " Documentation/driver-api/ipmi.rst in the kernel sources for the"
 		 " gory details.");
 
 /*
@@ -53,15 +56,15 @@
 	{ NULL }
 };
 
-static int parse_str(const struct hotmod_vals *v, int *val, char *name,
-		     char **curr)
+static int parse_str(const struct hotmod_vals *v, unsigned int *val, char *name,
+		     const char **curr)
 {
 	char *s;
 	int  i;
 
 	s = strchr(*curr, ',');
 	if (!s) {
-		pr_warn(PFX "No hotmod %s given.\n", name);
+		pr_warn("No hotmod %s given\n", name);
 		return -EINVAL;
 	}
 	*s = '\0';
@@ -74,23 +77,23 @@
 		}
 	}
 
-	pr_warn(PFX "Invalid hotmod %s '%s'\n", name, *curr);
+	pr_warn("Invalid hotmod %s '%s'\n", name, *curr);
 	return -EINVAL;
 }
 
 static int check_hotmod_int_op(const char *curr, const char *option,
-			       const char *name, int *val)
+			       const char *name, unsigned int *val)
 {
 	char *n;
 
 	if (strcmp(curr, name) == 0) {
 		if (!option) {
-			pr_warn(PFX "No option given for '%s'\n", curr);
+			pr_warn("No option given for '%s'\n", curr);
 			return -EINVAL;
 		}
 		*val = simple_strtoul(option, &n, 0);
 		if ((*n != '\0') || (*option == '\0')) {
-			pr_warn(PFX "Bad option given for '%s'\n", curr);
+			pr_warn("Bad option given for '%s'\n", curr);
 			return -EINVAL;
 		}
 		return 1;
@@ -98,22 +101,95 @@
 	return 0;
 }
 
+static int parse_hotmod_str(const char *curr, enum hotmod_op *op,
+			    struct ipmi_plat_data *h)
+{
+	char *s, *o;
+	int rv;
+	unsigned int ival;
+
+	h->iftype = IPMI_PLAT_IF_SI;
+	rv = parse_str(hotmod_ops, &ival, "operation", &curr);
+	if (rv)
+		return rv;
+	*op = ival;
+
+	rv = parse_str(hotmod_si, &ival, "interface type", &curr);
+	if (rv)
+		return rv;
+	h->type = ival;
+
+	rv = parse_str(hotmod_as, &ival, "address space", &curr);
+	if (rv)
+		return rv;
+	h->space = ival;
+
+	s = strchr(curr, ',');
+	if (s) {
+		*s = '\0';
+		s++;
+	}
+	rv = kstrtoul(curr, 0, &h->addr);
+	if (rv) {
+		pr_warn("Invalid hotmod address '%s': %d\n", curr, rv);
+		return rv;
+	}
+
+	while (s) {
+		curr = s;
+		s = strchr(curr, ',');
+		if (s) {
+			*s = '\0';
+			s++;
+		}
+		o = strchr(curr, '=');
+		if (o) {
+			*o = '\0';
+			o++;
+		}
+		rv = check_hotmod_int_op(curr, o, "rsp", &h->regspacing);
+		if (rv < 0)
+			return rv;
+		else if (rv)
+			continue;
+		rv = check_hotmod_int_op(curr, o, "rsi", &h->regsize);
+		if (rv < 0)
+			return rv;
+		else if (rv)
+			continue;
+		rv = check_hotmod_int_op(curr, o, "rsh", &h->regshift);
+		if (rv < 0)
+			return rv;
+		else if (rv)
+			continue;
+		rv = check_hotmod_int_op(curr, o, "irq", &h->irq);
+		if (rv < 0)
+			return rv;
+		else if (rv)
+			continue;
+		rv = check_hotmod_int_op(curr, o, "ipmb", &h->slave_addr);
+		if (rv < 0)
+			return rv;
+		else if (rv)
+			continue;
+
+		pr_warn("Invalid hotmod option '%s'\n", curr);
+		return -EINVAL;
+	}
+
+	h->addr_source = SI_HOTMOD;
+	return 0;
+}
+
+static atomic_t hotmod_nr;
+
 static int hotmod_handler(const char *val, const struct kernel_param *kp)
 {
-	char *str = kstrdup(val, GFP_KERNEL);
+	char *str = kstrdup(val, GFP_KERNEL), *curr, *next;
 	int  rv;
-	char *next, *curr, *s, *n, *o;
-	enum hotmod_op op;
-	enum si_type si_type;
-	int  addr_space;
-	unsigned long addr;
-	int regspacing;
-	int regsize;
-	int regshift;
-	int irq;
-	int ipmb;
+	struct ipmi_plat_data h;
+	unsigned int len;
 	int ival;
-	int len;
 
 	if (!str)
 		return -ENOMEM;
@@ -127,11 +203,7 @@
 	}
 
 	for (curr = str; curr; curr = next) {
-		regspacing = 1;
-		regsize = 1;
-		regshift = 0;
-		irq = 0;
-		ipmb = 0; /* Choose the default if not specified */
+		enum hotmod_op op;
 
 		next = strchr(curr, ':');
 		if (next) {
@@ -139,101 +211,28 @@
 			next++;
 		}
 
-		rv = parse_str(hotmod_ops, &ival, "operation", &curr);
+		memset(&h, 0, sizeof(h));
+		rv = parse_hotmod_str(curr, &op, &h);
 		if (rv)
-			break;
-		op = ival;
-
-		rv = parse_str(hotmod_si, &ival, "interface type", &curr);
-		if (rv)
-			break;
-		si_type = ival;
-
-		rv = parse_str(hotmod_as, &addr_space, "address space", &curr);
-		if (rv)
-			break;
-
-		s = strchr(curr, ',');
-		if (s) {
-			*s = '\0';
-			s++;
-		}
-		addr = simple_strtoul(curr, &n, 0);
-		if ((*n != '\0') || (*curr == '\0')) {
-			pr_warn(PFX "Invalid hotmod address '%s'\n", curr);
-			break;
-		}
-
-		while (s) {
-			curr = s;
-			s = strchr(curr, ',');
-			if (s) {
-				*s = '\0';
-				s++;
-			}
-			o = strchr(curr, '=');
-			if (o) {
-				*o = '\0';
-				o++;
-			}
-			rv = check_hotmod_int_op(curr, o, "rsp", &regspacing);
-			if (rv < 0)
-				goto out;
-			else if (rv)
-				continue;
-			rv = check_hotmod_int_op(curr, o, "rsi", &regsize);
-			if (rv < 0)
-				goto out;
-			else if (rv)
-				continue;
-			rv = check_hotmod_int_op(curr, o, "rsh", &regshift);
-			if (rv < 0)
-				goto out;
-			else if (rv)
-				continue;
-			rv = check_hotmod_int_op(curr, o, "irq", &irq);
-			if (rv < 0)
-				goto out;
-			else if (rv)
-				continue;
-			rv = check_hotmod_int_op(curr, o, "ipmb", &ipmb);
-			if (rv < 0)
-				goto out;
-			else if (rv)
-				continue;
-
-			rv = -EINVAL;
-			pr_warn(PFX "Invalid hotmod option '%s'\n", curr);
 			goto out;
-		}
 
 		if (op == HM_ADD) {
-			struct si_sm_io io;
-
-			memset(&io, 0, sizeof(io));
-			io.addr_source = SI_HOTMOD;
-			io.si_type = si_type;
-			io.addr_data = addr;
-			io.addr_type = addr_space;
-
-			io.addr = NULL;
-			io.regspacing = regspacing;
-			if (!io.regspacing)
-				io.regspacing = DEFAULT_REGSPACING;
-			io.regsize = regsize;
-			if (!io.regsize)
-				io.regsize = DEFAULT_REGSIZE;
-			io.regshift = regshift;
-			io.irq = irq;
-			if (io.irq)
-				io.irq_setup = ipmi_std_irq_setup;
-			io.slave_addr = ipmb;
-
-			rv = ipmi_si_add_smi(&io);
-			if (rv)
-				goto out;
+			ipmi_platform_add("hotmod-ipmi-si",
+					  atomic_inc_return(&hotmod_nr),
+					  &h);
 		} else {
-			ipmi_si_remove_by_data(addr_space, si_type, addr);
+			struct device *dev;
+
+			dev = ipmi_si_remove_by_data(h.space, h.type, h.addr);
+			if (dev && dev_is_platform(dev)) {
+				struct platform_device *pdev;
+
+				pdev = to_platform_device(dev);
+				if (strcmp(pdev->name, "hotmod-ipmi-si") == 0)
+					platform_device_unregister(pdev);
+			}
+			if (dev)
+				put_device(dev);
 		}
 	}
 	rv = len;
@@ -241,3 +240,8 @@
 	kfree(str);
 	return rv;
 }
+
+void ipmi_si_hotmod_exit(void)
+{
+	ipmi_remove_platform_device_by_name("hotmod-ipmi-si");
+}

--
Gitblit v1.6.2