Commit bdb57b7b authored by Corey Minyard's avatar Corey Minyard
Browse files

ipmi_si: Remove hotmod devices on removal and exit



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: default avatarCorey Minyard <cminyard@mvista.com>
parent 1a84df2d
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -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,
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);
+31 −1
Original line number Diff line number Diff line
@@ -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);
	}
}
+9 −3
Original line number Diff line number Diff line
@@ -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,
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);