ipmi_si: Remove hotmod devices on removal and exit
authorCorey Minyard <cminyard@mvista.com>
Thu, 21 Feb 2019 23:21:50 +0000 (17:21 -0600)
committerCorey Minyard <cminyard@mvista.com>
Fri, 22 Feb 2019 13:12:41 +0000 (07:12 -0600)
When a hotmod-added device is removed or when the module is removed,
remove the platform devices that was created for it.

Signed-off-by: Corey Minyard <cminyard@mvista.com>
drivers/char/ipmi/ipmi_si.h
drivers/char/ipmi/ipmi_si_hotmod.c
drivers/char/ipmi/ipmi_si_intf.c

index 49b211b..2ae9ebd 100644 (file)
@@ -21,10 +21,11 @@ void ipmi_irq_start_cleanup(struct si_sm_io *io);
 int ipmi_std_irq_setup(struct si_sm_io *io);
 void ipmi_irq_finish_setup(struct si_sm_io *io);
 int ipmi_si_remove_by_dev(struct device *dev);
-void ipmi_si_remove_by_data(int addr_space, enum si_type si_type,
-                           unsigned long addr);
+struct device *ipmi_si_remove_by_data(int addr_space, enum si_type si_type,
+                                     unsigned long addr);
 void ipmi_hardcode_init(void);
 void ipmi_si_hardcode_exit(void);
+void ipmi_si_hotmod_exit(void);
 int ipmi_si_hardcode_match(int addr_space, unsigned long addr);
 void ipmi_si_platform_init(void);
 void ipmi_si_platform_shutdown(void);
index f0728be..230b10e 100644 (file)
@@ -219,7 +219,18 @@ static int hotmod_handler(const char *val, const struct kernel_param *kp)
                                          atomic_inc_return(&hotmod_nr),
                                          &h);
                } else {
-                       ipmi_si_remove_by_data(h.space, h.type, h.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;
@@ -227,3 +238,22 @@ out:
        kfree(str);
        return rv;
 }
+
+static int pdev_match_name(struct device *dev, void *data)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+
+       return strcmp(pdev->name, "hotmod-ipmi-si") == 0;
+}
+
+void ipmi_si_hotmod_exit(void)
+{
+       struct device *dev;
+
+       while ((dev = bus_find_device(&platform_bus_type, NULL, NULL,
+                                     pdev_match_name))) {
+               struct platform_device *pdev = to_platform_device(dev);
+
+               platform_device_unregister(pdev);
+       }
+}
index c8af06d..9b3a272 100644 (file)
@@ -2281,11 +2281,12 @@ int ipmi_si_remove_by_dev(struct device *dev)
        return rv;
 }
 
-void ipmi_si_remove_by_data(int addr_space, enum si_type si_type,
-                           unsigned long addr)
+struct device *ipmi_si_remove_by_data(int addr_space, enum si_type si_type,
+                                     unsigned long addr)
 {
        /* remove */
        struct smi_info *e, *tmp_e;
+       struct device *dev = NULL;
 
        mutex_lock(&smi_infos_lock);
        list_for_each_entry_safe(e, tmp_e, &smi_infos, link) {
@@ -2293,10 +2294,14 @@ void ipmi_si_remove_by_data(int addr_space, enum si_type si_type,
                        continue;
                if (e->io.si_type != si_type)
                        continue;
-               if (e->io.addr_data == addr)
+               if (e->io.addr_data == addr) {
+                       dev = get_device(e->io.dev);
                        cleanup_one_si(e);
+               }
        }
        mutex_unlock(&smi_infos_lock);
+
+       return dev;
 }
 
 static void cleanup_ipmi_si(void)
@@ -2318,6 +2323,7 @@ static void cleanup_ipmi_si(void)
        mutex_unlock(&smi_infos_lock);
 
        ipmi_si_hardcode_exit();
+       ipmi_si_hotmod_exit();
 }
 module_exit(cleanup_ipmi_si);