ipmi_si: Switch hotmod to use a platform device
[linux-2.6-block.git] / drivers / char / ipmi / ipmi_si_intf.c
index dc8603d343209d384d18695ae406faf7e24cc1a7..c8af06dfa24456804b389dd91e79ba5387d20b56 100644 (file)
@@ -1060,10 +1060,13 @@ static void request_events(void *send_info)
        atomic_set(&smi_info->req_events, 1);
 }
 
-static void set_need_watch(void *send_info, bool enable)
+static void set_need_watch(void *send_info, unsigned int watch_mask)
 {
        struct smi_info *smi_info = send_info;
        unsigned long flags;
+       int enable;
+
+       enable = !!watch_mask;
 
        atomic_set(&smi_info->need_watch, enable);
        spin_lock_irqsave(&smi_info->si_lock, flags);
@@ -1642,7 +1645,7 @@ static ssize_t ipmi_params_show(struct device *dev,
        return snprintf(buf, 200,
                        "%s,%s,0x%lx,rsp=%d,rsi=%d,rsh=%d,irq=%d,ipmb=%d\n",
                        si_to_str[smi_info->io.si_type],
-                       addr_space_to_str[smi_info->io.addr_type],
+                       addr_space_to_str[smi_info->io.addr_space],
                        smi_info->io.addr_data,
                        smi_info->io.regspacing,
                        smi_info->io.regsize,
@@ -1840,7 +1843,7 @@ static struct smi_info *find_dup_si(struct smi_info *info)
        struct smi_info *e;
 
        list_for_each_entry(e, &smi_infos, link) {
-               if (e->io.addr_type != info->io.addr_type)
+               if (e->io.addr_space != info->io.addr_space)
                        continue;
                if (e->io.addr_data == info->io.addr_data) {
                        /*
@@ -1862,10 +1865,22 @@ int ipmi_si_add_smi(struct si_sm_io *io)
        int rv = 0;
        struct smi_info *new_smi, *dup;
 
+       /*
+        * If the user gave us a hard-coded device at the same
+        * address, they presumably want us to use it and not what is
+        * in the firmware.
+        */
+       if (io->addr_source != SI_HARDCODED && io->addr_source != SI_HOTMOD &&
+           ipmi_si_hardcode_match(io->addr_space, io->addr_data)) {
+               dev_info(io->dev,
+                        "Hard-coded device at this address already exists");
+               return -ENODEV;
+       }
+
        if (!io->io_setup) {
-               if (io->addr_type == IPMI_IO_ADDR_SPACE) {
+               if (io->addr_space == IPMI_IO_ADDR_SPACE) {
                        io->io_setup = ipmi_si_port_setup;
-               } else if (io->addr_type == IPMI_MEM_ADDR_SPACE) {
+               } else if (io->addr_space == IPMI_MEM_ADDR_SPACE) {
                        io->io_setup = ipmi_si_mem_setup;
                } else {
                        return -EINVAL;
@@ -1927,7 +1942,7 @@ static int try_smi_init(struct smi_info *new_smi)
        pr_info("Trying %s-specified %s state machine at %s address 0x%lx, slave address 0x%x, irq %d\n",
                ipmi_addr_src_to_str(new_smi->io.addr_source),
                si_to_str[new_smi->io.si_type],
-               addr_space_to_str[new_smi->io.addr_type],
+               addr_space_to_str[new_smi->io.addr_space],
                new_smi->io.addr_data,
                new_smi->io.slave_addr, new_smi->io.irq);
 
@@ -2085,11 +2100,16 @@ static int try_smi_init(struct smi_info *new_smi)
        WARN_ON(new_smi->io.dev->init_name != NULL);
 
  out_err:
+       if (rv && new_smi->io.io_cleanup) {
+               new_smi->io.io_cleanup(&new_smi->io);
+               new_smi->io.io_cleanup = NULL;
+       }
+
        kfree(init_name);
        return rv;
 }
 
-static int init_ipmi_si(void)
+static int __init init_ipmi_si(void)
 {
        struct smi_info *e;
        enum ipmi_addr_src type = SI_INVALID;
@@ -2097,11 +2117,9 @@ static int init_ipmi_si(void)
        if (initialized)
                return 0;
 
-       pr_info("IPMI System Interface driver\n");
+       ipmi_hardcode_init();
 
-       /* If the user gave us a device, they presumably want us to use it */
-       if (!ipmi_si_hardcode_find_bmc())
-               goto do_scan;
+       pr_info("IPMI System Interface driver\n");
 
        ipmi_si_platform_init();
 
@@ -2113,7 +2131,6 @@ static int init_ipmi_si(void)
           with multiple BMCs we assume that there will be several instances
           of a given type so if we succeed in registering a type then also
           try to register everything else of the same type */
-do_scan:
        mutex_lock(&smi_infos_lock);
        list_for_each_entry(e, &smi_infos, link) {
                /* Try to register a device if it has an IRQ and we either
@@ -2272,7 +2289,7 @@ void ipmi_si_remove_by_data(int addr_space, enum si_type si_type,
 
        mutex_lock(&smi_infos_lock);
        list_for_each_entry_safe(e, tmp_e, &smi_infos, link) {
-               if (e->io.addr_type != addr_space)
+               if (e->io.addr_space != addr_space)
                        continue;
                if (e->io.si_type != si_type)
                        continue;
@@ -2299,6 +2316,8 @@ static void cleanup_ipmi_si(void)
        list_for_each_entry_safe(e, tmp_e, &smi_infos, link)
                cleanup_one_si(e);
        mutex_unlock(&smi_infos_lock);
+
+       ipmi_si_hardcode_exit();
 }
 module_exit(cleanup_ipmi_si);