aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/ipmi
diff options
context:
space:
mode:
authorCorey Minyard <minyard@acm.org>2006-12-06 23:40:57 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-07 11:39:47 -0500
commitbca0324d09e413ee089f44cc71263ae1fc582b35 (patch)
tree1819be63547bcf4f430bba13f47498350612c454 /drivers/char/ipmi
parentf0b55da0d2701230e973866c9dfbf932d8b884cb (diff)
[PATCH] IPMI: remove interface number limits
Remove the arbitrary limit of number of IPMI interfaces. This has been tested with 8 interfaces. Signed-off-by: Corey Minyard <minyard@acm.org> Cc: Carol Hebert <cah@us.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/char/ipmi')
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c210
1 files changed, 97 insertions, 113 deletions
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index da13df46e984..761ed2699204 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -193,6 +193,9 @@ struct ipmi_smi
193 193
194 struct kref refcount; 194 struct kref refcount;
195 195
196 /* Used for a list of interfaces. */
197 struct list_head link;
198
196 /* The list of upper layers that are using me. seq_lock 199 /* The list of upper layers that are using me. seq_lock
197 * protects this. */ 200 * protects this. */
198 struct list_head users; 201 struct list_head users;
@@ -338,13 +341,6 @@ struct ipmi_smi
338}; 341};
339#define to_si_intf_from_dev(device) container_of(device, struct ipmi_smi, dev) 342#define to_si_intf_from_dev(device) container_of(device, struct ipmi_smi, dev)
340 343
341/* Used to mark an interface entry that cannot be used but is not a
342 * free entry, either, primarily used at creation and deletion time so
343 * a slot doesn't get reused too quickly. */
344#define IPMI_INVALID_INTERFACE_ENTRY ((ipmi_smi_t) ((long) 1))
345#define IPMI_INVALID_INTERFACE(i) (((i) == NULL) \
346 || (i == IPMI_INVALID_INTERFACE_ENTRY))
347
348/** 344/**
349 * The driver model view of the IPMI messaging driver. 345 * The driver model view of the IPMI messaging driver.
350 */ 346 */
@@ -354,11 +350,8 @@ static struct device_driver ipmidriver = {
354}; 350};
355static DEFINE_MUTEX(ipmidriver_mutex); 351static DEFINE_MUTEX(ipmidriver_mutex);
356 352
357#define MAX_IPMI_INTERFACES 4 353static struct list_head ipmi_interfaces = LIST_HEAD_INIT(ipmi_interfaces);
358static ipmi_smi_t ipmi_interfaces[MAX_IPMI_INTERFACES]; 354static DEFINE_MUTEX(ipmi_interfaces_mutex);
359
360/* Directly protects the ipmi_interfaces data structure. */
361static DEFINE_SPINLOCK(interfaces_lock);
362 355
363/* List of watchers that want to know when smi's are added and 356/* List of watchers that want to know when smi's are added and
364 deleted. */ 357 deleted. */
@@ -423,25 +416,50 @@ static void intf_free(struct kref *ref)
423 kfree(intf); 416 kfree(intf);
424} 417}
425 418
419struct watcher_entry {
420 struct list_head link;
421 int intf_num;
422};
423
426int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher) 424int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher)
427{ 425{
428 int i; 426 ipmi_smi_t intf;
429 unsigned long flags; 427 struct list_head to_deliver = LIST_HEAD_INIT(to_deliver);
428 struct watcher_entry *e, *e2;
429
430 mutex_lock(&ipmi_interfaces_mutex);
431
432 list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
433 if (intf->intf_num == -1)
434 continue;
435 e = kmalloc(sizeof(*e), GFP_KERNEL);
436 if (!e)
437 goto out_err;
438 e->intf_num = intf->intf_num;
439 list_add_tail(&e->link, &to_deliver);
440 }
430 441
431 down_write(&smi_watchers_sem); 442 down_write(&smi_watchers_sem);
432 list_add(&(watcher->link), &smi_watchers); 443 list_add(&(watcher->link), &smi_watchers);
433 up_write(&smi_watchers_sem); 444 up_write(&smi_watchers_sem);
434 spin_lock_irqsave(&interfaces_lock, flags); 445
435 for (i = 0; i < MAX_IPMI_INTERFACES; i++) { 446 mutex_unlock(&ipmi_interfaces_mutex);
436 ipmi_smi_t intf = ipmi_interfaces[i]; 447
437 if (IPMI_INVALID_INTERFACE(intf)) 448 list_for_each_entry_safe(e, e2, &to_deliver, link) {
438 continue; 449 list_del(&e->link);
439 spin_unlock_irqrestore(&interfaces_lock, flags); 450 watcher->new_smi(e->intf_num, intf->si_dev);
440 watcher->new_smi(i, intf->si_dev); 451 kfree(e);
441 spin_lock_irqsave(&interfaces_lock, flags);
442 } 452 }
443 spin_unlock_irqrestore(&interfaces_lock, flags); 453
454
444 return 0; 455 return 0;
456
457 out_err:
458 list_for_each_entry_safe(e, e2, &to_deliver, link) {
459 list_del(&e->link);
460 kfree(e);
461 }
462 return -ENOMEM;
445} 463}
446 464
447int ipmi_smi_watcher_unregister(struct ipmi_smi_watcher *watcher) 465int ipmi_smi_watcher_unregister(struct ipmi_smi_watcher *watcher)
@@ -776,17 +794,19 @@ int ipmi_create_user(unsigned int if_num,
776 if (!new_user) 794 if (!new_user)
777 return -ENOMEM; 795 return -ENOMEM;
778 796
779 spin_lock_irqsave(&interfaces_lock, flags); 797 rcu_read_lock();
780 intf = ipmi_interfaces[if_num]; 798 list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
781 if ((if_num >= MAX_IPMI_INTERFACES) || IPMI_INVALID_INTERFACE(intf)) { 799 if (intf->intf_num == if_num)
782 spin_unlock_irqrestore(&interfaces_lock, flags); 800 goto found;
783 rv = -EINVAL;
784 goto out_kfree;
785 } 801 }
802 rcu_read_unlock();
803 rv = -EINVAL;
804 goto out_kfree;
786 805
806 found:
787 /* Note that each existing user holds a refcount to the interface. */ 807 /* Note that each existing user holds a refcount to the interface. */
788 kref_get(&intf->refcount); 808 kref_get(&intf->refcount);
789 spin_unlock_irqrestore(&interfaces_lock, flags); 809 rcu_read_unlock();
790 810
791 kref_init(&new_user->refcount); 811 kref_init(&new_user->refcount);
792 new_user->handler = handler; 812 new_user->handler = handler;
@@ -2449,9 +2469,10 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
2449 int i, j; 2469 int i, j;
2450 int rv; 2470 int rv;
2451 ipmi_smi_t intf; 2471 ipmi_smi_t intf;
2452 unsigned long flags; 2472 ipmi_smi_t tintf;
2453 int version_major; 2473 int version_major;
2454 int version_minor; 2474 int version_minor;
2475 struct list_head *link;
2455 2476
2456 version_major = ipmi_version_major(device_id); 2477 version_major = ipmi_version_major(device_id);
2457 version_minor = ipmi_version_minor(device_id); 2478 version_minor = ipmi_version_minor(device_id);
@@ -2477,7 +2498,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
2477 kfree(intf); 2498 kfree(intf);
2478 return -ENOMEM; 2499 return -ENOMEM;
2479 } 2500 }
2480 intf->intf_num = -1; 2501 intf->intf_num = -1; /* Mark it invalid for now. */
2481 kref_init(&intf->refcount); 2502 kref_init(&intf->refcount);
2482 intf->bmc->id = *device_id; 2503 intf->bmc->id = *device_id;
2483 intf->si_dev = si_dev; 2504 intf->si_dev = si_dev;
@@ -2511,20 +2532,22 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
2511 spin_lock_init(&intf->counter_lock); 2532 spin_lock_init(&intf->counter_lock);
2512 intf->proc_dir = NULL; 2533 intf->proc_dir = NULL;
2513 2534
2514 rv = -ENOMEM; 2535 mutex_lock(&ipmi_interfaces_mutex);
2515 spin_lock_irqsave(&interfaces_lock, flags); 2536 /* Look for a hole in the numbers. */
2516 for (i = 0; i < MAX_IPMI_INTERFACES; i++) { 2537 i = 0;
2517 if (ipmi_interfaces[i] == NULL) { 2538 link = &ipmi_interfaces;
2518 intf->intf_num = i; 2539 list_for_each_entry_rcu(tintf, &ipmi_interfaces, link) {
2519 /* Reserve the entry till we are done. */ 2540 if (tintf->intf_num != i) {
2520 ipmi_interfaces[i] = IPMI_INVALID_INTERFACE_ENTRY; 2541 link = &tintf->link;
2521 rv = 0;
2522 break; 2542 break;
2523 } 2543 }
2544 i++;
2524 } 2545 }
2525 spin_unlock_irqrestore(&interfaces_lock, flags); 2546 /* Add the new interface in numeric order. */
2526 if (rv) 2547 if (i == 0)
2527 goto out; 2548 list_add_rcu(&intf->link, &ipmi_interfaces);
2549 else
2550 list_add_tail_rcu(&intf->link, link);
2528 2551
2529 rv = handlers->start_processing(send_info, intf); 2552 rv = handlers->start_processing(send_info, intf);
2530 if (rv) 2553 if (rv)
@@ -2562,16 +2585,14 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
2562 if (rv) { 2585 if (rv) {
2563 if (intf->proc_dir) 2586 if (intf->proc_dir)
2564 remove_proc_entries(intf); 2587 remove_proc_entries(intf);
2588 list_del_rcu(&intf->link);
2589 mutex_unlock(&ipmi_interfaces_mutex);
2590 synchronize_rcu();
2565 kref_put(&intf->refcount, intf_free); 2591 kref_put(&intf->refcount, intf_free);
2566 if (i < MAX_IPMI_INTERFACES) {
2567 spin_lock_irqsave(&interfaces_lock, flags);
2568 ipmi_interfaces[i] = NULL;
2569 spin_unlock_irqrestore(&interfaces_lock, flags);
2570 }
2571 } else { 2592 } else {
2572 spin_lock_irqsave(&interfaces_lock, flags); 2593 /* After this point the interface is legal to use. */
2573 ipmi_interfaces[i] = intf; 2594 intf->intf_num = i;
2574 spin_unlock_irqrestore(&interfaces_lock, flags); 2595 mutex_unlock(&ipmi_interfaces_mutex);
2575 call_smi_watchers(i, intf->si_dev); 2596 call_smi_watchers(i, intf->si_dev);
2576 } 2597 }
2577 2598
@@ -2580,26 +2601,14 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
2580 2601
2581int ipmi_unregister_smi(ipmi_smi_t intf) 2602int ipmi_unregister_smi(ipmi_smi_t intf)
2582{ 2603{
2583 int i;
2584 struct ipmi_smi_watcher *w; 2604 struct ipmi_smi_watcher *w;
2585 unsigned long flags;
2586 2605
2587 ipmi_bmc_unregister(intf); 2606 ipmi_bmc_unregister(intf);
2588 2607
2589 spin_lock_irqsave(&interfaces_lock, flags); 2608 mutex_lock(&ipmi_interfaces_mutex);
2590 for (i = 0; i < MAX_IPMI_INTERFACES; i++) { 2609 list_del_rcu(&intf->link);
2591 if (ipmi_interfaces[i] == intf) { 2610 mutex_unlock(&ipmi_interfaces_mutex);
2592 /* Set the interface number reserved until we 2611 synchronize_rcu();
2593 * are done. */
2594 ipmi_interfaces[i] = IPMI_INVALID_INTERFACE_ENTRY;
2595 intf->intf_num = -1;
2596 break;
2597 }
2598 }
2599 spin_unlock_irqrestore(&interfaces_lock,flags);
2600
2601 if (i == MAX_IPMI_INTERFACES)
2602 return -ENODEV;
2603 2612
2604 remove_proc_entries(intf); 2613 remove_proc_entries(intf);
2605 2614
@@ -2607,14 +2616,9 @@ int ipmi_unregister_smi(ipmi_smi_t intf)
2607 an interface is gone. */ 2616 an interface is gone. */
2608 down_read(&smi_watchers_sem); 2617 down_read(&smi_watchers_sem);
2609 list_for_each_entry(w, &smi_watchers, link) 2618 list_for_each_entry(w, &smi_watchers, link)
2610 w->smi_gone(i); 2619 w->smi_gone(intf->intf_num);
2611 up_read(&smi_watchers_sem); 2620 up_read(&smi_watchers_sem);
2612 2621
2613 /* Allow the entry to be reused now. */
2614 spin_lock_irqsave(&interfaces_lock, flags);
2615 ipmi_interfaces[i] = NULL;
2616 spin_unlock_irqrestore(&interfaces_lock,flags);
2617
2618 kref_put(&intf->refcount, intf_free); 2622 kref_put(&intf->refcount, intf_free);
2619 return 0; 2623 return 0;
2620} 2624}
@@ -3446,18 +3450,12 @@ static void ipmi_timeout_handler(long timeout_period)
3446 struct ipmi_recv_msg *msg, *msg2; 3450 struct ipmi_recv_msg *msg, *msg2;
3447 struct ipmi_smi_msg *smi_msg, *smi_msg2; 3451 struct ipmi_smi_msg *smi_msg, *smi_msg2;
3448 unsigned long flags; 3452 unsigned long flags;
3449 int i, j; 3453 int i;
3450 3454
3451 INIT_LIST_HEAD(&timeouts); 3455 INIT_LIST_HEAD(&timeouts);
3452 3456
3453 spin_lock(&interfaces_lock); 3457 rcu_read_lock();
3454 for (i = 0; i < MAX_IPMI_INTERFACES; i++) { 3458 list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
3455 intf = ipmi_interfaces[i];
3456 if (IPMI_INVALID_INTERFACE(intf))
3457 continue;
3458 kref_get(&intf->refcount);
3459 spin_unlock(&interfaces_lock);
3460
3461 /* See if any waiting messages need to be processed. */ 3459 /* See if any waiting messages need to be processed. */
3462 spin_lock_irqsave(&intf->waiting_msgs_lock, flags); 3460 spin_lock_irqsave(&intf->waiting_msgs_lock, flags);
3463 list_for_each_entry_safe(smi_msg, smi_msg2, 3461 list_for_each_entry_safe(smi_msg, smi_msg2,
@@ -3477,35 +3475,26 @@ static void ipmi_timeout_handler(long timeout_period)
3477 have timed out, putting them in the timeouts 3475 have timed out, putting them in the timeouts
3478 list. */ 3476 list. */
3479 spin_lock_irqsave(&intf->seq_lock, flags); 3477 spin_lock_irqsave(&intf->seq_lock, flags);
3480 for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) 3478 for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++)
3481 check_msg_timeout(intf, &(intf->seq_table[j]), 3479 check_msg_timeout(intf, &(intf->seq_table[i]),
3482 &timeouts, timeout_period, j, 3480 &timeouts, timeout_period, i,
3483 &flags); 3481 &flags);
3484 spin_unlock_irqrestore(&intf->seq_lock, flags); 3482 spin_unlock_irqrestore(&intf->seq_lock, flags);
3485 3483
3486 list_for_each_entry_safe(msg, msg2, &timeouts, link) 3484 list_for_each_entry_safe(msg, msg2, &timeouts, link)
3487 handle_msg_timeout(msg); 3485 handle_msg_timeout(msg);
3488
3489 kref_put(&intf->refcount, intf_free);
3490 spin_lock(&interfaces_lock);
3491 } 3486 }
3492 spin_unlock(&interfaces_lock); 3487 rcu_read_unlock();
3493} 3488}
3494 3489
3495static void ipmi_request_event(void) 3490static void ipmi_request_event(void)
3496{ 3491{
3497 ipmi_smi_t intf; 3492 ipmi_smi_t intf;
3498 int i;
3499
3500 spin_lock(&interfaces_lock);
3501 for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
3502 intf = ipmi_interfaces[i];
3503 if (IPMI_INVALID_INTERFACE(intf))
3504 continue;
3505 3493
3494 rcu_read_lock();
3495 list_for_each_entry_rcu(intf, &ipmi_interfaces, link)
3506 intf->handlers->request_events(intf->send_info); 3496 intf->handlers->request_events(intf->send_info);
3507 } 3497 rcu_read_unlock();
3508 spin_unlock(&interfaces_lock);
3509} 3498}
3510 3499
3511static struct timer_list ipmi_timer; 3500static struct timer_list ipmi_timer;
@@ -3634,7 +3623,6 @@ static void send_panic_events(char *str)
3634 struct kernel_ipmi_msg msg; 3623 struct kernel_ipmi_msg msg;
3635 ipmi_smi_t intf; 3624 ipmi_smi_t intf;
3636 unsigned char data[16]; 3625 unsigned char data[16];
3637 int i;
3638 struct ipmi_system_interface_addr *si; 3626 struct ipmi_system_interface_addr *si;
3639 struct ipmi_addr addr; 3627 struct ipmi_addr addr;
3640 struct ipmi_smi_msg smi_msg; 3628 struct ipmi_smi_msg smi_msg;
@@ -3668,9 +3656,9 @@ static void send_panic_events(char *str)
3668 recv_msg.done = dummy_recv_done_handler; 3656 recv_msg.done = dummy_recv_done_handler;
3669 3657
3670 /* For every registered interface, send the event. */ 3658 /* For every registered interface, send the event. */
3671 for (i = 0; i < MAX_IPMI_INTERFACES; i++) { 3659 list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
3672 intf = ipmi_interfaces[i]; 3660 if (intf->intf_num == -1)
3673 if (IPMI_INVALID_INTERFACE(intf)) 3661 /* Interface was not ready yet. */
3674 continue; 3662 continue;
3675 3663
3676 /* Send the event announcing the panic. */ 3664 /* Send the event announcing the panic. */
@@ -3695,13 +3683,14 @@ static void send_panic_events(char *str)
3695 if (!str) 3683 if (!str)
3696 return; 3684 return;
3697 3685
3698 for (i = 0; i < MAX_IPMI_INTERFACES; i++) { 3686 /* For every registered interface, send the event. */
3687 list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
3699 char *p = str; 3688 char *p = str;
3700 struct ipmi_ipmb_addr *ipmb; 3689 struct ipmi_ipmb_addr *ipmb;
3701 int j; 3690 int j;
3702 3691
3703 intf = ipmi_interfaces[i]; 3692 if (intf->intf_num == -1)
3704 if (IPMI_INVALID_INTERFACE(intf)) 3693 /* Interface was not ready yet. */
3705 continue; 3694 continue;
3706 3695
3707 /* First job here is to figure out where to send the 3696 /* First job here is to figure out where to send the
@@ -3827,7 +3816,6 @@ static int panic_event(struct notifier_block *this,
3827 unsigned long event, 3816 unsigned long event,
3828 void *ptr) 3817 void *ptr)
3829{ 3818{
3830 int i;
3831 ipmi_smi_t intf; 3819 ipmi_smi_t intf;
3832 3820
3833 if (has_panicked) 3821 if (has_panicked)
@@ -3835,9 +3823,9 @@ static int panic_event(struct notifier_block *this,
3835 has_panicked = 1; 3823 has_panicked = 1;
3836 3824
3837 /* For every registered interface, set it to run to completion. */ 3825 /* For every registered interface, set it to run to completion. */
3838 for (i = 0; i < MAX_IPMI_INTERFACES; i++) { 3826 list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
3839 intf = ipmi_interfaces[i]; 3827 if (intf->intf_num == -1)
3840 if (IPMI_INVALID_INTERFACE(intf)) 3828 /* Interface was not ready yet. */
3841 continue; 3829 continue;
3842 3830
3843 intf->handlers->set_run_to_completion(intf->send_info, 1); 3831 intf->handlers->set_run_to_completion(intf->send_info, 1);
@@ -3858,7 +3846,6 @@ static struct notifier_block panic_block = {
3858 3846
3859static int ipmi_init_msghandler(void) 3847static int ipmi_init_msghandler(void)
3860{ 3848{
3861 int i;
3862 int rv; 3849 int rv;
3863 3850
3864 if (initialized) 3851 if (initialized)
@@ -3873,9 +3860,6 @@ static int ipmi_init_msghandler(void)
3873 printk(KERN_INFO "ipmi message handler version " 3860 printk(KERN_INFO "ipmi message handler version "
3874 IPMI_DRIVER_VERSION "\n"); 3861 IPMI_DRIVER_VERSION "\n");
3875 3862
3876 for (i = 0; i < MAX_IPMI_INTERFACES; i++)
3877 ipmi_interfaces[i] = NULL;
3878
3879#ifdef CONFIG_PROC_FS 3863#ifdef CONFIG_PROC_FS
3880 proc_ipmi_root = proc_mkdir("ipmi", NULL); 3864 proc_ipmi_root = proc_mkdir("ipmi", NULL);
3881 if (!proc_ipmi_root) { 3865 if (!proc_ipmi_root) {