aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorMatthew Garrett <mjg@redhat.com>2010-05-26 17:43:46 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-27 12:12:49 -0400
commit2407d77a1a013b88ee3b817f2b934e420e5376f5 (patch)
treebb7eeb2621dccc01964612e664de17d612a7aa11 /drivers/char
parent5fedc4a282f0c6f5be5e4bebc8840f6022153bb3 (diff)
ipmi: split device discovery and registration
The ipmi spec indicates that we should only make use of one si per bmc, so separate device discovery and registration to make that possible. [thenzl@redhat.com: fix mutex use] Signed-off-by: Matthew Garrett <mjg@redhat.com> Signed-off-by: Corey Minyard <cminyard@mvista.com> Signed-off-by: Tomas Henzl <thenzl@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c130
1 files changed, 84 insertions, 46 deletions
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 93ab75887fbf..3f2a4900fe18 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -308,6 +308,7 @@ static int num_max_busy_us;
308 308
309static int unload_when_empty = 1; 309static int unload_when_empty = 1;
310 310
311static int add_smi(struct smi_info *smi);
311static int try_smi_init(struct smi_info *smi); 312static int try_smi_init(struct smi_info *smi);
312static void cleanup_one_si(struct smi_info *to_clean); 313static void cleanup_one_si(struct smi_info *to_clean);
313 314
@@ -1785,7 +1786,9 @@ static int hotmod_handler(const char *val, struct kernel_param *kp)
1785 info->irq_setup = std_irq_setup; 1786 info->irq_setup = std_irq_setup;
1786 info->slave_addr = ipmb; 1787 info->slave_addr = ipmb;
1787 1788
1788 try_smi_init(info); 1789 if (!add_smi(info))
1790 if (try_smi_init(info))
1791 cleanup_one_si(info);
1789 } else { 1792 } else {
1790 /* remove */ 1793 /* remove */
1791 struct smi_info *e, *tmp_e; 1794 struct smi_info *e, *tmp_e;
@@ -1871,7 +1874,9 @@ static __devinit void hardcode_find_bmc(void)
1871 info->irq_setup = std_irq_setup; 1874 info->irq_setup = std_irq_setup;
1872 info->slave_addr = slave_addrs[i]; 1875 info->slave_addr = slave_addrs[i];
1873 1876
1874 try_smi_init(info); 1877 if (!add_smi(info))
1878 if (try_smi_init(info))
1879 cleanup_one_si(info);
1875 } 1880 }
1876} 1881}
1877 1882
@@ -2069,7 +2074,7 @@ static __devinit int try_init_spmi(struct SPMITable *spmi)
2069 } 2074 }
2070 info->io.addr_data = spmi->addr.address; 2075 info->io.addr_data = spmi->addr.address;
2071 2076
2072 try_smi_init(info); 2077 add_smi(info);
2073 2078
2074 return 0; 2079 return 0;
2075} 2080}
@@ -2167,7 +2172,7 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev,
2167 info->dev = &acpi_dev->dev; 2172 info->dev = &acpi_dev->dev;
2168 pnp_set_drvdata(dev, info); 2173 pnp_set_drvdata(dev, info);
2169 2174
2170 return try_smi_init(info); 2175 return add_smi(info);
2171 2176
2172err_free: 2177err_free:
2173 kfree(info); 2178 kfree(info);
@@ -2326,7 +2331,7 @@ static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data)
2326 if (info->irq) 2331 if (info->irq)
2327 info->irq_setup = std_irq_setup; 2332 info->irq_setup = std_irq_setup;
2328 2333
2329 try_smi_init(info); 2334 add_smi(info);
2330} 2335}
2331 2336
2332static void __devinit dmi_find_bmc(void) 2337static void __devinit dmi_find_bmc(void)
@@ -2429,7 +2434,7 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev,
2429 info->dev = &pdev->dev; 2434 info->dev = &pdev->dev;
2430 pci_set_drvdata(pdev, info); 2435 pci_set_drvdata(pdev, info);
2431 2436
2432 return try_smi_init(info); 2437 return add_smi(info);
2433} 2438}
2434 2439
2435static void __devexit ipmi_pci_remove(struct pci_dev *pdev) 2440static void __devexit ipmi_pci_remove(struct pci_dev *pdev)
@@ -2542,7 +2547,7 @@ static int __devinit ipmi_of_probe(struct of_device *dev,
2542 2547
2543 dev_set_drvdata(&dev->dev, info); 2548 dev_set_drvdata(&dev->dev, info);
2544 2549
2545 return try_smi_init(info); 2550 return add_smi(info);
2546} 2551}
2547 2552
2548static int __devexit ipmi_of_remove(struct of_device *dev) 2553static int __devexit ipmi_of_remove(struct of_device *dev)
@@ -2971,14 +2976,16 @@ static __devinit void default_find_bmc(void)
2971 info->io.regsize = DEFAULT_REGSPACING; 2976 info->io.regsize = DEFAULT_REGSPACING;
2972 info->io.regshift = 0; 2977 info->io.regshift = 0;
2973 2978
2974 if (try_smi_init(info) == 0) { 2979 if (add_smi(info) == 0) {
2975 /* Found one... */ 2980 if ((try_smi_init(info)) == 0) {
2976 printk(KERN_INFO "ipmi_si: Found default %s state" 2981 /* Found one... */
2977 " machine at %s address 0x%lx\n", 2982 printk(KERN_INFO "ipmi_si: Found default %s"
2978 si_to_str[info->si_type], 2983 " state machine at %s address 0x%lx\n",
2979 addr_space_to_str[info->io.addr_type], 2984 si_to_str[info->si_type],
2980 info->io.addr_data); 2985 addr_space_to_str[info->io.addr_type],
2981 return; 2986 info->io.addr_data);
2987 } else
2988 cleanup_one_si(info);
2982 } 2989 }
2983 } 2990 }
2984} 2991}
@@ -2997,32 +3004,48 @@ static int is_new_interface(struct smi_info *info)
2997 return 1; 3004 return 1;
2998} 3005}
2999 3006
3000static int try_smi_init(struct smi_info *new_smi) 3007static int add_smi(struct smi_info *new_smi)
3001{ 3008{
3002 int rv; 3009 int rv = 0;
3003 int i;
3004
3005 printk(KERN_INFO "ipmi_si: Trying %s-specified %s state"
3006 " machine at %s address 0x%lx, slave address 0x%x,"
3007 " irq %d\n",
3008 ipmi_addr_src_to_str[new_smi->addr_source],
3009 si_to_str[new_smi->si_type],
3010 addr_space_to_str[new_smi->io.addr_type],
3011 new_smi->io.addr_data,
3012 new_smi->slave_addr, new_smi->irq);
3013 3010
3011 printk(KERN_INFO "ipmi_si: Adding %s-specified %s state machine",
3012 ipmi_addr_src_to_str[new_smi->addr_source],
3013 si_to_str[new_smi->si_type]);
3014 mutex_lock(&smi_infos_lock); 3014 mutex_lock(&smi_infos_lock);
3015 if (!is_new_interface(new_smi)) { 3015 if (!is_new_interface(new_smi)) {
3016 printk(KERN_WARNING "ipmi_si: duplicate interface\n"); 3016 printk(KERN_CONT ": duplicate interface\n");
3017 rv = -EBUSY; 3017 rv = -EBUSY;
3018 goto out_err; 3018 goto out_err;
3019 } 3019 }
3020 3020
3021 printk(KERN_CONT "\n");
3022
3021 /* So we know not to free it unless we have allocated one. */ 3023 /* So we know not to free it unless we have allocated one. */
3022 new_smi->intf = NULL; 3024 new_smi->intf = NULL;
3023 new_smi->si_sm = NULL; 3025 new_smi->si_sm = NULL;
3024 new_smi->handlers = NULL; 3026 new_smi->handlers = NULL;
3025 3027
3028 list_add_tail(&new_smi->link, &smi_infos);
3029
3030out_err:
3031 mutex_unlock(&smi_infos_lock);
3032 return rv;
3033}
3034
3035static int try_smi_init(struct smi_info *new_smi)
3036{
3037 int rv = 0;
3038 int i;
3039
3040 printk(KERN_INFO "ipmi_si: Trying %s-specified %s state"
3041 " machine at %s address 0x%lx, slave address 0x%x,"
3042 " irq %d\n",
3043 ipmi_addr_src_to_str[new_smi->addr_source],
3044 si_to_str[new_smi->si_type],
3045 addr_space_to_str[new_smi->io.addr_type],
3046 new_smi->io.addr_data,
3047 new_smi->slave_addr, new_smi->irq);
3048
3026 switch (new_smi->si_type) { 3049 switch (new_smi->si_type) {
3027 case SI_KCS: 3050 case SI_KCS:
3028 new_smi->handlers = &kcs_smi_handlers; 3051 new_smi->handlers = &kcs_smi_handlers;
@@ -3183,10 +3206,6 @@ static int try_smi_init(struct smi_info *new_smi)
3183 goto out_err_stop_timer; 3206 goto out_err_stop_timer;
3184 } 3207 }
3185 3208
3186 list_add_tail(&new_smi->link, &smi_infos);
3187
3188 mutex_unlock(&smi_infos_lock);
3189
3190 printk(KERN_INFO "IPMI %s interface initialized\n", 3209 printk(KERN_INFO "IPMI %s interface initialized\n",
3191 si_to_str[new_smi->si_type]); 3210 si_to_str[new_smi->si_type]);
3192 3211
@@ -3197,11 +3216,17 @@ static int try_smi_init(struct smi_info *new_smi)
3197 wait_for_timer_and_thread(new_smi); 3216 wait_for_timer_and_thread(new_smi);
3198 3217
3199 out_err: 3218 out_err:
3200 if (new_smi->intf) 3219 new_smi->interrupt_disabled = 1;
3220
3221 if (new_smi->intf) {
3201 ipmi_unregister_smi(new_smi->intf); 3222 ipmi_unregister_smi(new_smi->intf);
3223 new_smi->intf = NULL;
3224 }
3202 3225
3203 if (new_smi->irq_cleanup) 3226 if (new_smi->irq_cleanup) {
3204 new_smi->irq_cleanup(new_smi); 3227 new_smi->irq_cleanup(new_smi);
3228 new_smi->irq_cleanup = NULL;
3229 }
3205 3230
3206 /* 3231 /*
3207 * Wait until we know that we are out of any interrupt 3232 * Wait until we know that we are out of any interrupt
@@ -3214,18 +3239,21 @@ static int try_smi_init(struct smi_info *new_smi)
3214 if (new_smi->handlers) 3239 if (new_smi->handlers)
3215 new_smi->handlers->cleanup(new_smi->si_sm); 3240 new_smi->handlers->cleanup(new_smi->si_sm);
3216 kfree(new_smi->si_sm); 3241 kfree(new_smi->si_sm);
3242 new_smi->si_sm = NULL;
3217 } 3243 }
3218 if (new_smi->addr_source_cleanup) 3244 if (new_smi->addr_source_cleanup) {
3219 new_smi->addr_source_cleanup(new_smi); 3245 new_smi->addr_source_cleanup(new_smi);
3220 if (new_smi->io_cleanup) 3246 new_smi->addr_source_cleanup = NULL;
3247 }
3248 if (new_smi->io_cleanup) {
3221 new_smi->io_cleanup(new_smi); 3249 new_smi->io_cleanup(new_smi);
3250 new_smi->io_cleanup = NULL;
3251 }
3222 3252
3223 if (new_smi->dev_registered) 3253 if (new_smi->dev_registered) {
3224 platform_device_unregister(new_smi->pdev); 3254 platform_device_unregister(new_smi->pdev);
3225 3255 new_smi->dev_registered = 0;
3226 kfree(new_smi); 3256 }
3227
3228 mutex_unlock(&smi_infos_lock);
3229 3257
3230 return rv; 3258 return rv;
3231} 3259}
@@ -3235,6 +3263,7 @@ static __devinit int init_ipmi_si(void)
3235 int i; 3263 int i;
3236 char *str; 3264 char *str;
3237 int rv; 3265 int rv;
3266 struct smi_info *e;
3238 3267
3239 if (initialized) 3268 if (initialized)
3240 return 0; 3269 return 0;
@@ -3292,15 +3321,21 @@ static __devinit int init_ipmi_si(void)
3292 of_register_platform_driver(&ipmi_of_platform_driver); 3321 of_register_platform_driver(&ipmi_of_platform_driver);
3293#endif 3322#endif
3294 3323
3324 mutex_lock(&smi_infos_lock);
3325 list_for_each_entry(e, &smi_infos, link) {
3326 if (!e->si_sm)
3327 try_smi_init(e);
3328 }
3329 mutex_unlock(&smi_infos_lock);
3330
3295 if (si_trydefaults) { 3331 if (si_trydefaults) {
3296 mutex_lock(&smi_infos_lock); 3332 mutex_lock(&smi_infos_lock);
3297 if (list_empty(&smi_infos)) { 3333 if (list_empty(&smi_infos)) {
3298 /* No BMC was found, try defaults. */ 3334 /* No BMC was found, try defaults. */
3299 mutex_unlock(&smi_infos_lock); 3335 mutex_unlock(&smi_infos_lock);
3300 default_find_bmc(); 3336 default_find_bmc();
3301 } else { 3337 } else
3302 mutex_unlock(&smi_infos_lock); 3338 mutex_unlock(&smi_infos_lock);
3303 }
3304 } 3339 }
3305 3340
3306 mutex_lock(&smi_infos_lock); 3341 mutex_lock(&smi_infos_lock);
@@ -3326,7 +3361,7 @@ module_init(init_ipmi_si);
3326 3361
3327static void cleanup_one_si(struct smi_info *to_clean) 3362static void cleanup_one_si(struct smi_info *to_clean)
3328{ 3363{
3329 int rv; 3364 int rv = 0;
3330 unsigned long flags; 3365 unsigned long flags;
3331 3366
3332 if (!to_clean) 3367 if (!to_clean)
@@ -3370,14 +3405,17 @@ static void cleanup_one_si(struct smi_info *to_clean)
3370 schedule_timeout_uninterruptible(1); 3405 schedule_timeout_uninterruptible(1);
3371 } 3406 }
3372 3407
3373 rv = ipmi_unregister_smi(to_clean->intf); 3408 if (to_clean->intf)
3409 rv = ipmi_unregister_smi(to_clean->intf);
3410
3374 if (rv) { 3411 if (rv) {
3375 printk(KERN_ERR 3412 printk(KERN_ERR
3376 "ipmi_si: Unable to unregister device: errno=%d\n", 3413 "ipmi_si: Unable to unregister device: errno=%d\n",
3377 rv); 3414 rv);
3378 } 3415 }
3379 3416
3380 to_clean->handlers->cleanup(to_clean->si_sm); 3417 if (to_clean->handlers)
3418 to_clean->handlers->cleanup(to_clean->si_sm);
3381 3419
3382 kfree(to_clean->si_sm); 3420 kfree(to_clean->si_sm);
3383 3421