diff options
| -rw-r--r-- | drivers/char/ipmi/ipmi_msghandler.c | 953 | ||||
| -rw-r--r-- | include/linux/ipmi.h | 5 |
2 files changed, 499 insertions, 459 deletions
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 32fa82c78c7..320d7f035bf 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
| @@ -38,13 +38,13 @@ | |||
| 38 | #include <linux/sched.h> | 38 | #include <linux/sched.h> |
| 39 | #include <linux/poll.h> | 39 | #include <linux/poll.h> |
| 40 | #include <linux/spinlock.h> | 40 | #include <linux/spinlock.h> |
| 41 | #include <linux/rwsem.h> | ||
| 42 | #include <linux/slab.h> | 41 | #include <linux/slab.h> |
| 43 | #include <linux/ipmi.h> | 42 | #include <linux/ipmi.h> |
| 44 | #include <linux/ipmi_smi.h> | 43 | #include <linux/ipmi_smi.h> |
| 45 | #include <linux/notifier.h> | 44 | #include <linux/notifier.h> |
| 46 | #include <linux/init.h> | 45 | #include <linux/init.h> |
| 47 | #include <linux/proc_fs.h> | 46 | #include <linux/proc_fs.h> |
| 47 | #include <linux/rcupdate.h> | ||
| 48 | 48 | ||
| 49 | #define PFX "IPMI message handler: " | 49 | #define PFX "IPMI message handler: " |
| 50 | 50 | ||
| @@ -65,10 +65,19 @@ struct proc_dir_entry *proc_ipmi_root = NULL; | |||
| 65 | the max message timer. This is in milliseconds. */ | 65 | the max message timer. This is in milliseconds. */ |
| 66 | #define MAX_MSG_TIMEOUT 60000 | 66 | #define MAX_MSG_TIMEOUT 60000 |
| 67 | 67 | ||
| 68 | |||
| 69 | /* | ||
| 70 | * The main "user" data structure. | ||
| 71 | */ | ||
| 68 | struct ipmi_user | 72 | struct ipmi_user |
| 69 | { | 73 | { |
| 70 | struct list_head link; | 74 | struct list_head link; |
| 71 | 75 | ||
| 76 | /* Set to "0" when the user is destroyed. */ | ||
| 77 | int valid; | ||
| 78 | |||
| 79 | struct kref refcount; | ||
| 80 | |||
| 72 | /* The upper layer that handles receive messages. */ | 81 | /* The upper layer that handles receive messages. */ |
| 73 | struct ipmi_user_hndl *handler; | 82 | struct ipmi_user_hndl *handler; |
| 74 | void *handler_data; | 83 | void *handler_data; |
| @@ -87,6 +96,15 @@ struct cmd_rcvr | |||
| 87 | ipmi_user_t user; | 96 | ipmi_user_t user; |
| 88 | unsigned char netfn; | 97 | unsigned char netfn; |
| 89 | unsigned char cmd; | 98 | unsigned char cmd; |
| 99 | |||
| 100 | /* | ||
| 101 | * This is used to form a linked lised during mass deletion. | ||
| 102 | * Since this is in an RCU list, we cannot use the link above | ||
| 103 | * or change any data until the RCU period completes. So we | ||
| 104 | * use this next variable during mass deletion so we can have | ||
| 105 | * a list and don't have to wait and restart the search on | ||
| 106 | * every individual deletion of a command. */ | ||
| 107 | struct cmd_rcvr *next; | ||
| 90 | }; | 108 | }; |
| 91 | 109 | ||
| 92 | struct seq_table | 110 | struct seq_table |
| @@ -150,13 +168,11 @@ struct ipmi_smi | |||
| 150 | /* What interface number are we? */ | 168 | /* What interface number are we? */ |
| 151 | int intf_num; | 169 | int intf_num; |
| 152 | 170 | ||
| 153 | /* The list of upper layers that are using me. We read-lock | 171 | struct kref refcount; |
| 154 | this when delivering messages to the upper layer to keep | 172 | |
| 155 | the user from going away while we are processing the | 173 | /* The list of upper layers that are using me. seq_lock |
| 156 | message. This means that you cannot add or delete a user | 174 | * protects this. */ |
| 157 | from the receive callback. */ | 175 | struct list_head users; |
| 158 | rwlock_t users_lock; | ||
| 159 | struct list_head users; | ||
| 160 | 176 | ||
| 161 | /* Used for wake ups at startup. */ | 177 | /* Used for wake ups at startup. */ |
| 162 | wait_queue_head_t waitq; | 178 | wait_queue_head_t waitq; |
| @@ -193,7 +209,7 @@ struct ipmi_smi | |||
| 193 | 209 | ||
| 194 | /* The list of command receivers that are registered for commands | 210 | /* The list of command receivers that are registered for commands |
| 195 | on this interface. */ | 211 | on this interface. */ |
| 196 | rwlock_t cmd_rcvr_lock; | 212 | spinlock_t cmd_rcvrs_lock; |
| 197 | struct list_head cmd_rcvrs; | 213 | struct list_head cmd_rcvrs; |
| 198 | 214 | ||
| 199 | /* Events that were queues because no one was there to receive | 215 | /* Events that were queues because no one was there to receive |
| @@ -296,16 +312,17 @@ struct ipmi_smi | |||
| 296 | unsigned int events; | 312 | unsigned int events; |
| 297 | }; | 313 | }; |
| 298 | 314 | ||
| 315 | /* Used to mark an interface entry that cannot be used but is not a | ||
| 316 | * free entry, either, primarily used at creation and deletion time so | ||
| 317 | * a slot doesn't get reused too quickly. */ | ||
| 318 | #define IPMI_INVALID_INTERFACE_ENTRY ((ipmi_smi_t) ((long) 1)) | ||
| 319 | #define IPMI_INVALID_INTERFACE(i) (((i) == NULL) \ | ||
| 320 | || (i == IPMI_INVALID_INTERFACE_ENTRY)) | ||
| 321 | |||
| 299 | #define MAX_IPMI_INTERFACES 4 | 322 | #define MAX_IPMI_INTERFACES 4 |
| 300 | static ipmi_smi_t ipmi_interfaces[MAX_IPMI_INTERFACES]; | 323 | static ipmi_smi_t ipmi_interfaces[MAX_IPMI_INTERFACES]; |
| 301 | 324 | ||
| 302 | /* Used to keep interfaces from going away while operations are | 325 | /* Directly protects the ipmi_interfaces data structure. */ |
| 303 | operating on interfaces. Grab read if you are not modifying the | ||
| 304 | interfaces, write if you are. */ | ||
| 305 | static DECLARE_RWSEM(interfaces_sem); | ||
| 306 | |||
| 307 | /* Directly protects the ipmi_interfaces data structure. This is | ||
| 308 | claimed in the timer interrupt. */ | ||
| 309 | static DEFINE_SPINLOCK(interfaces_lock); | 326 | static DEFINE_SPINLOCK(interfaces_lock); |
| 310 | 327 | ||
| 311 | /* List of watchers that want to know when smi's are added and | 328 | /* List of watchers that want to know when smi's are added and |
| @@ -313,20 +330,73 @@ static DEFINE_SPINLOCK(interfaces_lock); | |||
| 313 | static struct list_head smi_watchers = LIST_HEAD_INIT(smi_watchers); | 330 | static struct list_head smi_watchers = LIST_HEAD_INIT(smi_watchers); |
| 314 | static DECLARE_RWSEM(smi_watchers_sem); | 331 | static DECLARE_RWSEM(smi_watchers_sem); |
| 315 | 332 | ||
| 333 | |||
| 334 | static void free_recv_msg_list(struct list_head *q) | ||
| 335 | { | ||
| 336 | struct ipmi_recv_msg *msg, *msg2; | ||
| 337 | |||
| 338 | list_for_each_entry_safe(msg, msg2, q, link) { | ||
| 339 | list_del(&msg->link); | ||
| 340 | ipmi_free_recv_msg(msg); | ||
| 341 | } | ||
| 342 | } | ||
| 343 | |||
| 344 | static void clean_up_interface_data(ipmi_smi_t intf) | ||
| 345 | { | ||
| 346 | int i; | ||
| 347 | struct cmd_rcvr *rcvr, *rcvr2; | ||
| 348 | unsigned long flags; | ||
| 349 | struct list_head list; | ||
| 350 | |||
| 351 | free_recv_msg_list(&intf->waiting_msgs); | ||
| 352 | free_recv_msg_list(&intf->waiting_events); | ||
| 353 | |||
| 354 | /* Wholesale remove all the entries from the list in the | ||
| 355 | * interface and wait for RCU to know that none are in use. */ | ||
| 356 | spin_lock_irqsave(&intf->cmd_rcvrs_lock, flags); | ||
| 357 | list_add_rcu(&list, &intf->cmd_rcvrs); | ||
| 358 | list_del_rcu(&intf->cmd_rcvrs); | ||
| 359 | spin_unlock_irqrestore(&intf->cmd_rcvrs_lock, flags); | ||
| 360 | synchronize_rcu(); | ||
| 361 | |||
| 362 | list_for_each_entry_safe(rcvr, rcvr2, &list, link) | ||
| 363 | kfree(rcvr); | ||
| 364 | |||
| 365 | for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) { | ||
| 366 | if ((intf->seq_table[i].inuse) | ||
| 367 | && (intf->seq_table[i].recv_msg)) | ||
| 368 | { | ||
| 369 | ipmi_free_recv_msg(intf->seq_table[i].recv_msg); | ||
| 370 | } | ||
| 371 | } | ||
| 372 | } | ||
| 373 | |||
| 374 | static void intf_free(struct kref *ref) | ||
| 375 | { | ||
| 376 | ipmi_smi_t intf = container_of(ref, struct ipmi_smi, refcount); | ||
| 377 | |||
| 378 | clean_up_interface_data(intf); | ||
| 379 | kfree(intf); | ||
| 380 | } | ||
| 381 | |||
| 316 | int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher) | 382 | int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher) |
| 317 | { | 383 | { |
| 318 | int i; | 384 | int i; |
| 385 | unsigned long flags; | ||
| 319 | 386 | ||
| 320 | down_read(&interfaces_sem); | ||
| 321 | down_write(&smi_watchers_sem); | 387 | down_write(&smi_watchers_sem); |
| 322 | list_add(&(watcher->link), &smi_watchers); | 388 | list_add(&(watcher->link), &smi_watchers); |
| 389 | up_write(&smi_watchers_sem); | ||
| 390 | spin_lock_irqsave(&interfaces_lock, flags); | ||
| 323 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { | 391 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { |
| 324 | if (ipmi_interfaces[i] != NULL) { | 392 | ipmi_smi_t intf = ipmi_interfaces[i]; |
| 325 | watcher->new_smi(i); | 393 | if (IPMI_INVALID_INTERFACE(intf)) |
| 326 | } | 394 | continue; |
| 395 | spin_unlock_irqrestore(&interfaces_lock, flags); | ||
| 396 | watcher->new_smi(i); | ||
| 397 | spin_lock_irqsave(&interfaces_lock, flags); | ||
| 327 | } | 398 | } |
| 328 | up_write(&smi_watchers_sem); | 399 | spin_unlock_irqrestore(&interfaces_lock, flags); |
| 329 | up_read(&interfaces_sem); | ||
| 330 | return 0; | 400 | return 0; |
| 331 | } | 401 | } |
| 332 | 402 | ||
| @@ -471,8 +541,8 @@ static void deliver_response(struct ipmi_recv_msg *msg) | |||
| 471 | } | 541 | } |
| 472 | ipmi_free_recv_msg(msg); | 542 | ipmi_free_recv_msg(msg); |
| 473 | } else { | 543 | } else { |
| 474 | msg->user->handler->ipmi_recv_hndl(msg, | 544 | ipmi_user_t user = msg->user; |
| 475 | msg->user->handler_data); | 545 | user->handler->ipmi_recv_hndl(msg, user->handler_data); |
| 476 | } | 546 | } |
| 477 | } | 547 | } |
| 478 | 548 | ||
| @@ -662,15 +732,18 @@ int ipmi_create_user(unsigned int if_num, | |||
| 662 | if (! new_user) | 732 | if (! new_user) |
| 663 | return -ENOMEM; | 733 | return -ENOMEM; |
| 664 | 734 | ||
| 665 | down_read(&interfaces_sem); | 735 | spin_lock_irqsave(&interfaces_lock, flags); |
| 666 | if ((if_num >= MAX_IPMI_INTERFACES) || ipmi_interfaces[if_num] == NULL) | 736 | intf = ipmi_interfaces[if_num]; |
| 667 | { | 737 | if ((if_num >= MAX_IPMI_INTERFACES) || IPMI_INVALID_INTERFACE(intf)) { |
| 668 | rv = -EINVAL; | 738 | spin_unlock_irqrestore(&interfaces_lock, flags); |
| 669 | goto out_unlock; | 739 | return -EINVAL; |
| 670 | } | 740 | } |
| 671 | 741 | ||
| 672 | intf = ipmi_interfaces[if_num]; | 742 | /* Note that each existing user holds a refcount to the interface. */ |
| 743 | kref_get(&intf->refcount); | ||
| 744 | spin_unlock_irqrestore(&interfaces_lock, flags); | ||
| 673 | 745 | ||
| 746 | kref_init(&new_user->refcount); | ||
| 674 | new_user->handler = handler; | 747 | new_user->handler = handler; |
| 675 | new_user->handler_data = handler_data; | 748 | new_user->handler_data = handler_data; |
| 676 | new_user->intf = intf; | 749 | new_user->intf = intf; |
| @@ -678,98 +751,92 @@ int ipmi_create_user(unsigned int if_num, | |||
| 678 | 751 | ||
| 679 | if (!try_module_get(intf->handlers->owner)) { | 752 | if (!try_module_get(intf->handlers->owner)) { |
| 680 | rv = -ENODEV; | 753 | rv = -ENODEV; |
| 681 | goto out_unlock; | 754 | goto out_err; |
| 682 | } | 755 | } |
| 683 | 756 | ||
| 684 | if (intf->handlers->inc_usecount) { | 757 | if (intf->handlers->inc_usecount) { |
| 685 | rv = intf->handlers->inc_usecount(intf->send_info); | 758 | rv = intf->handlers->inc_usecount(intf->send_info); |
| 686 | if (rv) { | 759 | if (rv) { |
| 687 | module_put(intf->handlers->owner); | 760 | module_put(intf->handlers->owner); |
| 688 | goto out_unlock; | 761 | goto out_err; |
| 689 | } | 762 | } |
| 690 | } | 763 | } |
| 691 | 764 | ||
| 692 | write_lock_irqsave(&intf->users_lock, flags); | 765 | new_user->valid = 1; |
| 693 | list_add_tail(&new_user->link, &intf->users); | 766 | spin_lock_irqsave(&intf->seq_lock, flags); |
| 694 | write_unlock_irqrestore(&intf->users_lock, flags); | 767 | list_add_rcu(&new_user->link, &intf->users); |
| 695 | 768 | spin_unlock_irqrestore(&intf->seq_lock, flags); | |
| 696 | out_unlock: | 769 | *user = new_user; |
| 697 | if (rv) { | 770 | return 0; |
| 698 | kfree(new_user); | ||
| 699 | } else { | ||
| 700 | *user = new_user; | ||
| 701 | } | ||
| 702 | 771 | ||
| 703 | up_read(&interfaces_sem); | 772 | out_err: |
| 773 | kfree(new_user); | ||
| 774 | kref_put(&intf->refcount, intf_free); | ||
| 704 | return rv; | 775 | return rv; |
| 705 | } | 776 | } |
| 706 | 777 | ||
| 707 | static int ipmi_destroy_user_nolock(ipmi_user_t user) | 778 | static void free_user(struct kref *ref) |
| 779 | { | ||
| 780 | ipmi_user_t user = container_of(ref, struct ipmi_user, refcount); | ||
| 781 | kfree(user); | ||
| 782 | } | ||
| 783 | |||
| 784 | int ipmi_destroy_user(ipmi_user_t user) | ||
| 708 | { | 785 | { |
| 709 | int rv = -ENODEV; | 786 | int rv = -ENODEV; |
| 710 | ipmi_user_t t_user; | 787 | ipmi_smi_t intf = user->intf; |
| 711 | struct cmd_rcvr *rcvr, *rcvr2; | ||
| 712 | int i; | 788 | int i; |
| 713 | unsigned long flags; | 789 | unsigned long flags; |
| 790 | struct cmd_rcvr *rcvr; | ||
| 791 | struct list_head *entry1, *entry2; | ||
| 792 | struct cmd_rcvr *rcvrs = NULL; | ||
| 714 | 793 | ||
| 715 | /* Find the user and delete them from the list. */ | 794 | user->valid = 1; |
| 716 | list_for_each_entry(t_user, &(user->intf->users), link) { | ||
| 717 | if (t_user == user) { | ||
| 718 | list_del(&t_user->link); | ||
| 719 | rv = 0; | ||
| 720 | break; | ||
| 721 | } | ||
| 722 | } | ||
| 723 | 795 | ||
| 724 | if (rv) { | 796 | /* Remove the user from the interface's sequence table. */ |
| 725 | goto out_unlock; | 797 | spin_lock_irqsave(&intf->seq_lock, flags); |
| 726 | } | 798 | list_del_rcu(&user->link); |
| 727 | 799 | ||
| 728 | /* Remove the user from the interfaces sequence table. */ | ||
| 729 | spin_lock_irqsave(&(user->intf->seq_lock), flags); | ||
| 730 | for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) { | 800 | for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) { |
| 731 | if (user->intf->seq_table[i].inuse | 801 | if (intf->seq_table[i].inuse |
| 732 | && (user->intf->seq_table[i].recv_msg->user == user)) | 802 | && (intf->seq_table[i].recv_msg->user == user)) |
| 733 | { | 803 | { |
| 734 | user->intf->seq_table[i].inuse = 0; | 804 | intf->seq_table[i].inuse = 0; |
| 735 | } | 805 | } |
| 736 | } | 806 | } |
| 737 | spin_unlock_irqrestore(&(user->intf->seq_lock), flags); | 807 | spin_unlock_irqrestore(&intf->seq_lock, flags); |
| 738 | 808 | ||
| 739 | /* Remove the user from the command receiver's table. */ | 809 | /* |
| 740 | write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags); | 810 | * Remove the user from the command receiver's table. First |
| 741 | list_for_each_entry_safe(rcvr, rcvr2, &(user->intf->cmd_rcvrs), link) { | 811 | * we build a list of everything (not using the standard link, |
| 812 | * since other things may be using it till we do | ||
| 813 | * synchronize_rcu()) then free everything in that list. | ||
| 814 | */ | ||
| 815 | spin_lock_irqsave(&intf->cmd_rcvrs_lock, flags); | ||
| 816 | list_for_each_safe_rcu(entry1, entry2, &intf->cmd_rcvrs) { | ||
| 817 | rcvr = list_entry(entry1, struct cmd_rcvr, link); | ||
| 742 | if (rcvr->user == user) { | 818 | if (rcvr->user == user) { |
| 743 | list_del(&rcvr->link); | 819 | list_del_rcu(&rcvr->link); |
| 744 | kfree(rcvr); | 820 | rcvr->next = rcvrs; |
| 821 | rcvrs = rcvr; | ||
| 745 | } | 822 | } |
| 746 | } | 823 | } |
| 747 | write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags); | 824 | spin_unlock_irqrestore(&intf->cmd_rcvrs_lock, flags); |
| 825 | synchronize_rcu(); | ||
| 826 | while (rcvrs) { | ||
| 827 | rcvr = rcvrs; | ||
| 828 | rcvrs = rcvr->next; | ||
| 829 | kfree(rcvr); | ||
| 830 | } | ||
| 748 | 831 | ||
| 749 | kfree(user); | 832 | module_put(intf->handlers->owner); |
| 833 | if (intf->handlers->dec_usecount) | ||
| 834 | intf->handlers->dec_usecount(intf->send_info); | ||
| 750 | 835 | ||
| 751 | out_unlock: | 836 | kref_put(&intf->refcount, intf_free); |
| 752 | 837 | ||
| 753 | return rv; | 838 | kref_put(&user->refcount, free_user); |
| 754 | } | ||
| 755 | |||
| 756 | int ipmi_destroy_user(ipmi_user_t user) | ||
| 757 | { | ||
| 758 | int rv; | ||
| 759 | ipmi_smi_t intf = user->intf; | ||
| 760 | unsigned long flags; | ||
| 761 | 839 | ||
| 762 | down_read(&interfaces_sem); | ||
| 763 | write_lock_irqsave(&intf->users_lock, flags); | ||
| 764 | rv = ipmi_destroy_user_nolock(user); | ||
| 765 | if (!rv) { | ||
| 766 | module_put(intf->handlers->owner); | ||
| 767 | if (intf->handlers->dec_usecount) | ||
| 768 | intf->handlers->dec_usecount(intf->send_info); | ||
| 769 | } | ||
| 770 | |||
| 771 | write_unlock_irqrestore(&intf->users_lock, flags); | ||
| 772 | up_read(&interfaces_sem); | ||
| 773 | return rv; | 840 | return rv; |
| 774 | } | 841 | } |
| 775 | 842 | ||
| @@ -823,62 +890,78 @@ int ipmi_get_my_LUN(ipmi_user_t user, | |||
| 823 | 890 | ||
| 824 | int ipmi_set_gets_events(ipmi_user_t user, int val) | 891 | int ipmi_set_gets_events(ipmi_user_t user, int val) |
| 825 | { | 892 | { |
| 826 | unsigned long flags; | 893 | unsigned long flags; |
| 827 | struct ipmi_recv_msg *msg, *msg2; | 894 | ipmi_smi_t intf = user->intf; |
| 895 | struct ipmi_recv_msg *msg, *msg2; | ||
| 896 | struct list_head msgs; | ||
| 828 | 897 | ||
| 829 | read_lock(&(user->intf->users_lock)); | 898 | INIT_LIST_HEAD(&msgs); |
| 830 | spin_lock_irqsave(&(user->intf->events_lock), flags); | 899 | |
| 900 | spin_lock_irqsave(&intf->events_lock, flags); | ||
| 831 | user->gets_events = val; | 901 | user->gets_events = val; |
| 832 | 902 | ||
| 833 | if (val) { | 903 | if (val) { |
| 834 | /* Deliver any queued events. */ | 904 | /* Deliver any queued events. */ |
| 835 | list_for_each_entry_safe(msg, msg2, &(user->intf->waiting_events), link) { | 905 | list_for_each_entry_safe(msg, msg2, &intf->waiting_events, link) { |
| 836 | list_del(&msg->link); | 906 | list_del(&msg->link); |
| 837 | msg->user = user; | 907 | list_add_tail(&msg->link, &msgs); |
| 838 | deliver_response(msg); | ||
| 839 | } | 908 | } |
| 840 | } | 909 | } |
| 841 | 910 | ||
| 842 | spin_unlock_irqrestore(&(user->intf->events_lock), flags); | 911 | /* Hold the events lock while doing this to preserve order. */ |
| 843 | read_unlock(&(user->intf->users_lock)); | 912 | list_for_each_entry_safe(msg, msg2, &msgs, link) { |
| 913 | msg->user = user; | ||
| 914 | kref_get(&user->refcount); | ||
| 915 | deliver_response(msg); | ||
| 916 | } | ||
| 917 | |||
| 918 | spin_unlock_irqrestore(&intf->events_lock, flags); | ||
| 844 | 919 | ||
| 845 | return 0; | 920 | return 0; |
| 846 | } | 921 | } |
| 847 | 922 | ||
| 923 | static struct cmd_rcvr *find_cmd_rcvr(ipmi_smi_t intf, | ||
| 924 | unsigned char netfn, | ||
| 925 | unsigned char cmd) | ||
| 926 | { | ||
| 927 | struct cmd_rcvr *rcvr; | ||
| 928 | |||
| 929 | list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) { | ||
| 930 | if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) | ||
| 931 | return rcvr; | ||
| 932 | } | ||
| 933 | return NULL; | ||
| 934 | } | ||
| 935 | |||
| 848 | int ipmi_register_for_cmd(ipmi_user_t user, | 936 | int ipmi_register_for_cmd(ipmi_user_t user, |
| 849 | unsigned char netfn, | 937 | unsigned char netfn, |
| 850 | unsigned char cmd) | 938 | unsigned char cmd) |
| 851 | { | 939 | { |
| 852 | struct cmd_rcvr *cmp; | 940 | ipmi_smi_t intf = user->intf; |
| 853 | unsigned long flags; | 941 | struct cmd_rcvr *rcvr; |
| 854 | struct cmd_rcvr *rcvr; | 942 | struct cmd_rcvr *entry; |
| 855 | int rv = 0; | 943 | int rv = 0; |
| 856 | 944 | ||
| 857 | 945 | ||
| 858 | rcvr = kmalloc(sizeof(*rcvr), GFP_KERNEL); | 946 | rcvr = kmalloc(sizeof(*rcvr), GFP_KERNEL); |
| 859 | if (! rcvr) | 947 | if (! rcvr) |
| 860 | return -ENOMEM; | 948 | return -ENOMEM; |
| 949 | rcvr->cmd = cmd; | ||
| 950 | rcvr->netfn = netfn; | ||
| 951 | rcvr->user = user; | ||
| 861 | 952 | ||
| 862 | read_lock(&(user->intf->users_lock)); | 953 | spin_lock_irq(&intf->cmd_rcvrs_lock); |
| 863 | write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags); | ||
| 864 | /* Make sure the command/netfn is not already registered. */ | 954 | /* Make sure the command/netfn is not already registered. */ |
| 865 | list_for_each_entry(cmp, &(user->intf->cmd_rcvrs), link) { | 955 | entry = find_cmd_rcvr(intf, netfn, cmd); |
| 866 | if ((cmp->netfn == netfn) && (cmp->cmd == cmd)) { | 956 | if (entry) { |
| 867 | rv = -EBUSY; | 957 | rv = -EBUSY; |
| 868 | break; | 958 | goto out_unlock; |
| 869 | } | ||
| 870 | } | ||
| 871 | |||
| 872 | if (! rv) { | ||
| 873 | rcvr->cmd = cmd; | ||
| 874 | rcvr->netfn = netfn; | ||
| 875 | rcvr->user = user; | ||
| 876 | list_add_tail(&(rcvr->link), &(user->intf->cmd_rcvrs)); | ||
| 877 | } | 959 | } |
| 878 | 960 | ||
| 879 | write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags); | 961 | list_add_rcu(&rcvr->link, &intf->cmd_rcvrs); |
| 880 | read_unlock(&(user->intf->users_lock)); | ||
| 881 | 962 | ||
| 963 | out_unlock: | ||
| 964 | spin_unlock_irq(&intf->cmd_rcvrs_lock); | ||
| 882 | if (rv) | 965 | if (rv) |
| 883 | kfree(rcvr); | 966 | kfree(rcvr); |
| 884 | 967 | ||
| @@ -889,31 +972,28 @@ int ipmi_unregister_for_cmd(ipmi_user_t user, | |||
| 889 | unsigned char netfn, | 972 | unsigned char netfn, |
| 890 | unsigned char cmd) | 973 | unsigned char cmd) |
| 891 | { | 974 | { |
| 892 | unsigned long flags; | 975 | ipmi_smi_t intf = user->intf; |
| 893 | struct cmd_rcvr *rcvr; | 976 | struct cmd_rcvr *rcvr; |
| 894 | int rv = -ENOENT; | ||
| 895 | 977 | ||
| 896 | read_lock(&(user->intf->users_lock)); | 978 | spin_lock_irq(&intf->cmd_rcvrs_lock); |
| 897 | write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags); | ||
| 898 | /* Make sure the command/netfn is not already registered. */ | 979 | /* Make sure the command/netfn is not already registered. */ |
| 899 | list_for_each_entry(rcvr, &(user->intf->cmd_rcvrs), link) { | 980 | rcvr = find_cmd_rcvr(intf, netfn, cmd); |
| 900 | if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) { | 981 | if ((rcvr) && (rcvr->user == user)) { |
| 901 | rv = 0; | 982 | list_del_rcu(&rcvr->link); |
| 902 | list_del(&rcvr->link); | 983 | spin_unlock_irq(&intf->cmd_rcvrs_lock); |
| 903 | kfree(rcvr); | 984 | synchronize_rcu(); |
| 904 | break; | 985 | kfree(rcvr); |
| 905 | } | 986 | return 0; |
| 987 | } else { | ||
| 988 | spin_unlock_irq(&intf->cmd_rcvrs_lock); | ||
| 989 | return -ENOENT; | ||
| 906 | } | 990 | } |
| 907 | write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags); | ||
| 908 | read_unlock(&(user->intf->users_lock)); | ||
| 909 | |||
| 910 | return rv; | ||
| 911 | } | 991 | } |
| 912 | 992 | ||
| 913 | void ipmi_user_set_run_to_completion(ipmi_user_t user, int val) | 993 | void ipmi_user_set_run_to_completion(ipmi_user_t user, int val) |
| 914 | { | 994 | { |
| 915 | user->intf->handlers->set_run_to_completion(user->intf->send_info, | 995 | ipmi_smi_t intf = user->intf; |
| 916 | val); | 996 | intf->handlers->set_run_to_completion(intf->send_info, val); |
| 917 | } | 997 | } |
| 918 | 998 | ||
| 919 | static unsigned char | 999 | static unsigned char |
| @@ -1010,19 +1090,19 @@ static inline void format_lan_msg(struct ipmi_smi_msg *smi_msg, | |||
| 1010 | supplied in certain circumstances (mainly at panic time). If | 1090 | supplied in certain circumstances (mainly at panic time). If |
| 1011 | messages are supplied, they will be freed, even if an error | 1091 | messages are supplied, they will be freed, even if an error |
| 1012 | occurs. */ | 1092 | occurs. */ |
| 1013 | static inline int i_ipmi_request(ipmi_user_t user, | 1093 | static int i_ipmi_request(ipmi_user_t user, |
| 1014 | ipmi_smi_t intf, | 1094 | ipmi_smi_t intf, |
| 1015 | struct ipmi_addr *addr, | 1095 | struct ipmi_addr *addr, |
| 1016 | long msgid, | 1096 | long msgid, |
| 1017 | struct kernel_ipmi_msg *msg, | 1097 | struct kernel_ipmi_msg *msg, |
| 1018 | void *user_msg_data, | 1098 | void *user_msg_data, |
| 1019 | void *supplied_smi, | 1099 | void *supplied_smi, |
| 1020 | struct ipmi_recv_msg *supplied_recv, | 1100 | struct ipmi_recv_msg *supplied_recv, |
| 1021 | int priority, | 1101 | int priority, |
| 1022 | unsigned char source_address, | 1102 | unsigned char source_address, |
| 1023 | unsigned char source_lun, | 1103 | unsigned char source_lun, |
| 1024 | int retries, | 1104 | int retries, |
| 1025 | unsigned int retry_time_ms) | 1105 | unsigned int retry_time_ms) |
| 1026 | { | 1106 | { |
| 1027 | int rv = 0; | 1107 | int rv = 0; |
| 1028 | struct ipmi_smi_msg *smi_msg; | 1108 | struct ipmi_smi_msg *smi_msg; |
| @@ -1051,6 +1131,8 @@ static inline int i_ipmi_request(ipmi_user_t user, | |||
| 1051 | } | 1131 | } |
| 1052 | 1132 | ||
| 1053 | recv_msg->user = user; | 1133 | recv_msg->user = user; |
| 1134 | if (user) | ||
| 1135 | kref_get(&user->refcount); | ||
| 1054 | recv_msg->msgid = msgid; | 1136 | recv_msg->msgid = msgid; |
| 1055 | /* Store the message to send in the receive message so timeout | 1137 | /* Store the message to send in the receive message so timeout |
| 1056 | responses can get the proper response data. */ | 1138 | responses can get the proper response data. */ |
| @@ -1725,11 +1807,11 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
| 1725 | unsigned char version_major, | 1807 | unsigned char version_major, |
| 1726 | unsigned char version_minor, | 1808 | unsigned char version_minor, |
| 1727 | unsigned char slave_addr, | 1809 | unsigned char slave_addr, |
| 1728 | ipmi_smi_t *intf) | 1810 | ipmi_smi_t *new_intf) |
| 1729 | { | 1811 | { |
| 1730 | int i, j; | 1812 | int i, j; |
| 1731 | int rv; | 1813 | int rv; |
| 1732 | ipmi_smi_t new_intf; | 1814 | ipmi_smi_t intf; |
| 1733 | unsigned long flags; | 1815 | unsigned long flags; |
| 1734 | 1816 | ||
| 1735 | 1817 | ||
| @@ -1745,189 +1827,142 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
| 1745 | return -ENODEV; | 1827 | return -ENODEV; |
| 1746 | } | 1828 | } |
| 1747 | 1829 | ||
| 1748 | new_intf = kmalloc(sizeof(*new_intf), GFP_KERNEL); | 1830 | intf = kmalloc(sizeof(*intf), GFP_KERNEL); |
| 1749 | if (!new_intf) | 1831 | if (!intf) |
| 1750 | return -ENOMEM; | 1832 | return -ENOMEM; |
| 1751 | memset(new_intf, 0, sizeof(*new_intf)); | 1833 | memset(intf, 0, sizeof(*intf)); |
| 1752 | 1834 | intf->intf_num = -1; | |
| 1753 | new_intf->proc_dir = NULL; | 1835 | kref_init(&intf->refcount); |
| 1836 | intf->version_major = version_major; | ||
| 1837 | intf->version_minor = version_minor; | ||
| 1838 | for (j = 0; j < IPMI_MAX_CHANNELS; j++) { | ||
| 1839 | intf->channels[j].address = IPMI_BMC_SLAVE_ADDR; | ||
| 1840 | intf->channels[j].lun = 2; | ||
| 1841 | } | ||
| 1842 | if (slave_addr != 0) | ||
| 1843 | intf->channels[0].address = slave_addr; | ||
| 1844 | INIT_LIST_HEAD(&intf->users); | ||
| 1845 | intf->handlers = handlers; | ||
| 1846 | intf->send_info = send_info; | ||
| 1847 | spin_lock_init(&intf->seq_lock); | ||
| 1848 | for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) { | ||
| 1849 | intf->seq_table[j].inuse = 0; | ||
| 1850 | intf->seq_table[j].seqid = 0; | ||
| 1851 | } | ||
| 1852 | intf->curr_seq = 0; | ||
| 1853 | #ifdef CONFIG_PROC_FS | ||
| 1854 | spin_lock_init(&intf->proc_entry_lock); | ||
| 1855 | #endif | ||
| 1856 | spin_lock_init(&intf->waiting_msgs_lock); | ||
| 1857 | INIT_LIST_HEAD(&intf->waiting_msgs); | ||
| 1858 | spin_lock_init(&intf->events_lock); | ||
| 1859 | INIT_LIST_HEAD(&intf->waiting_events); | ||
| 1860 | intf->waiting_events_count = 0; | ||
| 1861 | spin_lock_init(&intf->cmd_rcvrs_lock); | ||
| 1862 | INIT_LIST_HEAD(&intf->cmd_rcvrs); | ||
| 1863 | init_waitqueue_head(&intf->waitq); | ||
| 1864 | |||
| 1865 | spin_lock_init(&intf->counter_lock); | ||
| 1866 | intf->proc_dir = NULL; | ||
| 1754 | 1867 | ||
| 1755 | rv = -ENOMEM; | 1868 | rv = -ENOMEM; |
| 1756 | 1869 | spin_lock_irqsave(&interfaces_lock, flags); | |
| 1757 | down_write(&interfaces_sem); | ||
| 1758 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { | 1870 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { |
| 1759 | if (ipmi_interfaces[i] == NULL) { | 1871 | if (ipmi_interfaces[i] == NULL) { |
| 1760 | new_intf->intf_num = i; | 1872 | intf->intf_num = i; |
| 1761 | new_intf->version_major = version_major; | 1873 | /* Reserve the entry till we are done. */ |
| 1762 | new_intf->version_minor = version_minor; | 1874 | ipmi_interfaces[i] = IPMI_INVALID_INTERFACE_ENTRY; |
| 1763 | for (j = 0; j < IPMI_MAX_CHANNELS; j++) { | ||
| 1764 | new_intf->channels[j].address | ||
| 1765 | = IPMI_BMC_SLAVE_ADDR; | ||
| 1766 | new_intf->channels[j].lun = 2; | ||
| 1767 | } | ||
| 1768 | if (slave_addr != 0) | ||
| 1769 | new_intf->channels[0].address = slave_addr; | ||
| 1770 | rwlock_init(&(new_intf->users_lock)); | ||
| 1771 | INIT_LIST_HEAD(&(new_intf->users)); | ||
| 1772 | new_intf->handlers = handlers; | ||
| 1773 | new_intf->send_info = send_info; | ||
| 1774 | spin_lock_init(&(new_intf->seq_lock)); | ||
| 1775 | for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) { | ||
| 1776 | new_intf->seq_table[j].inuse = 0; | ||
| 1777 | new_intf->seq_table[j].seqid = 0; | ||
| 1778 | } | ||
| 1779 | new_intf->curr_seq = 0; | ||
| 1780 | #ifdef CONFIG_PROC_FS | ||
| 1781 | spin_lock_init(&(new_intf->proc_entry_lock)); | ||
| 1782 | #endif | ||
| 1783 | spin_lock_init(&(new_intf->waiting_msgs_lock)); | ||
| 1784 | INIT_LIST_HEAD(&(new_intf->waiting_msgs)); | ||
| 1785 | spin_lock_init(&(new_intf->events_lock)); | ||
| 1786 | INIT_LIST_HEAD(&(new_intf->waiting_events)); | ||
| 1787 | new_intf->waiting_events_count = 0; | ||
| 1788 | rwlock_init(&(new_intf->cmd_rcvr_lock)); | ||
| 1789 | init_waitqueue_head(&new_intf->waitq); | ||
| 1790 | INIT_LIST_HEAD(&(new_intf->cmd_rcvrs)); | ||
| 1791 | |||
| 1792 | spin_lock_init(&(new_intf->counter_lock)); | ||
| 1793 | |||
| 1794 | spin_lock_irqsave(&interfaces_lock, flags); | ||
| 1795 | ipmi_interfaces[i] = new_intf; | ||
| 1796 | spin_unlock_irqrestore(&interfaces_lock, flags); | ||
| 1797 | |||
| 1798 | rv = 0; | 1875 | rv = 0; |
| 1799 | *intf = new_intf; | ||
| 1800 | break; | 1876 | break; |
| 1801 | } | 1877 | } |
| 1802 | } | 1878 | } |
| 1879 | spin_unlock_irqrestore(&interfaces_lock, flags); | ||
| 1880 | if (rv) | ||
| 1881 | goto out; | ||
| 1803 | 1882 | ||
| 1804 | downgrade_write(&interfaces_sem); | 1883 | /* FIXME - this is an ugly kludge, this sets the intf for the |
| 1805 | 1884 | caller before sending any messages with it. */ | |
| 1806 | if (rv == 0) | 1885 | *new_intf = intf; |
| 1807 | rv = add_proc_entries(*intf, i); | ||
| 1808 | |||
| 1809 | if (rv == 0) { | ||
| 1810 | if ((version_major > 1) | ||
| 1811 | || ((version_major == 1) && (version_minor >= 5))) | ||
| 1812 | { | ||
| 1813 | /* Start scanning the channels to see what is | ||
| 1814 | available. */ | ||
| 1815 | (*intf)->null_user_handler = channel_handler; | ||
| 1816 | (*intf)->curr_channel = 0; | ||
| 1817 | rv = send_channel_info_cmd(*intf, 0); | ||
| 1818 | if (rv) | ||
| 1819 | goto out; | ||
| 1820 | 1886 | ||
| 1821 | /* Wait for the channel info to be read. */ | 1887 | if ((version_major > 1) |
| 1822 | up_read(&interfaces_sem); | 1888 | || ((version_major == 1) && (version_minor >= 5))) |
| 1823 | wait_event((*intf)->waitq, | 1889 | { |
| 1824 | ((*intf)->curr_channel>=IPMI_MAX_CHANNELS)); | 1890 | /* Start scanning the channels to see what is |
| 1825 | down_read(&interfaces_sem); | 1891 | available. */ |
| 1892 | intf->null_user_handler = channel_handler; | ||
| 1893 | intf->curr_channel = 0; | ||
| 1894 | rv = send_channel_info_cmd(intf, 0); | ||
| 1895 | if (rv) | ||
| 1896 | goto out; | ||
| 1826 | 1897 | ||
| 1827 | if (ipmi_interfaces[i] != new_intf) | 1898 | /* Wait for the channel info to be read. */ |
| 1828 | /* Well, it went away. Just return. */ | 1899 | wait_event(intf->waitq, |
| 1829 | goto out; | 1900 | intf->curr_channel >= IPMI_MAX_CHANNELS); |
| 1830 | } else { | 1901 | } else { |
| 1831 | /* Assume a single IPMB channel at zero. */ | 1902 | /* Assume a single IPMB channel at zero. */ |
| 1832 | (*intf)->channels[0].medium = IPMI_CHANNEL_MEDIUM_IPMB; | 1903 | intf->channels[0].medium = IPMI_CHANNEL_MEDIUM_IPMB; |
| 1833 | (*intf)->channels[0].protocol | 1904 | intf->channels[0].protocol = IPMI_CHANNEL_PROTOCOL_IPMB; |
| 1834 | = IPMI_CHANNEL_PROTOCOL_IPMB; | ||
| 1835 | } | ||
| 1836 | |||
| 1837 | /* Call all the watcher interfaces to tell | ||
| 1838 | them that a new interface is available. */ | ||
| 1839 | call_smi_watchers(i); | ||
| 1840 | } | 1905 | } |
| 1841 | 1906 | ||
| 1842 | out: | 1907 | if (rv == 0) |
| 1843 | up_read(&interfaces_sem); | 1908 | rv = add_proc_entries(intf, i); |
| 1844 | 1909 | ||
| 1910 | out: | ||
| 1845 | if (rv) { | 1911 | if (rv) { |
| 1846 | if (new_intf->proc_dir) | 1912 | if (intf->proc_dir) |
| 1847 | remove_proc_entries(new_intf); | 1913 | remove_proc_entries(intf); |
| 1848 | kfree(new_intf); | 1914 | kref_put(&intf->refcount, intf_free); |
| 1915 | if (i < MAX_IPMI_INTERFACES) { | ||
| 1916 | spin_lock_irqsave(&interfaces_lock, flags); | ||
| 1917 | ipmi_interfaces[i] = NULL; | ||
| 1918 | spin_unlock_irqrestore(&interfaces_lock, flags); | ||
| 1919 | } | ||
| 1920 | } else { | ||
| 1921 | spin_lock_irqsave(&interfaces_lock, flags); | ||
| 1922 | ipmi_interfaces[i] = intf; | ||
| 1923 | spin_unlock_irqrestore(&interfaces_lock, flags); | ||
| 1924 | call_smi_watchers(i); | ||
| 1849 | } | 1925 | } |
| 1850 | 1926 | ||
| 1851 | return rv; | 1927 | return rv; |
| 1852 | } | 1928 | } |
| 1853 | 1929 | ||
| 1854 | static void free_recv_msg_list(struct list_head *q) | ||
| 1855 | { | ||
| 1856 | struct ipmi_recv_msg *msg, *msg2; | ||
| 1857 | |||
| 1858 | list_for_each_entry_safe(msg, msg2, q, link) { | ||
| 1859 | list_del(&msg->link); | ||
| 1860 | ipmi_free_recv_msg(msg); | ||
| 1861 | } | ||
| 1862 | } | ||
| 1863 | |||
| 1864 | static void free_cmd_rcvr_list(struct list_head *q) | ||
| 1865 | { | ||
| 1866 | struct cmd_rcvr *rcvr, *rcvr2; | ||
| 1867 | |||
| 1868 | list_for_each_entry_safe(rcvr, rcvr2, q, link) { | ||
| 1869 | list_del(&rcvr->link); | ||
| 1870 | kfree(rcvr); | ||
| 1871 | } | ||
| 1872 | } | ||
| 1873 | |||
| 1874 | static void clean_up_interface_data(ipmi_smi_t intf) | ||
| 1875 | { | ||
| 1876 | int i; | ||
| 1877 | |||
| 1878 | free_recv_msg_list(&(intf->waiting_msgs)); | ||
| 1879 | free_recv_msg_list(&(intf->waiting_events)); | ||
| 1880 | free_cmd_rcvr_list(&(intf->cmd_rcvrs)); | ||
| 1881 | |||
| 1882 | for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) { | ||
| 1883 | if ((intf->seq_table[i].inuse) | ||
| 1884 | && (intf->seq_table[i].recv_msg)) | ||
| 1885 | { | ||
| 1886 | ipmi_free_recv_msg(intf->seq_table[i].recv_msg); | ||
| 1887 | } | ||
| 1888 | } | ||
| 1889 | } | ||
| 1890 | |||
| 1891 | int ipmi_unregister_smi(ipmi_smi_t intf) | 1930 | int ipmi_unregister_smi(ipmi_smi_t intf) |
| 1892 | { | 1931 | { |
| 1893 | int rv = -ENODEV; | ||
| 1894 | int i; | 1932 | int i; |
| 1895 | struct ipmi_smi_watcher *w; | 1933 | struct ipmi_smi_watcher *w; |
| 1896 | unsigned long flags; | 1934 | unsigned long flags; |
| 1897 | 1935 | ||
| 1898 | down_write(&interfaces_sem); | 1936 | spin_lock_irqsave(&interfaces_lock, flags); |
| 1899 | if (list_empty(&(intf->users))) | 1937 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { |
| 1900 | { | 1938 | if (ipmi_interfaces[i] == intf) { |
| 1901 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { | 1939 | /* Set the interface number reserved until we |
| 1902 | if (ipmi_interfaces[i] == intf) { | 1940 | * are done. */ |
| 1903 | remove_proc_entries(intf); | 1941 | ipmi_interfaces[i] = IPMI_INVALID_INTERFACE_ENTRY; |
| 1904 | spin_lock_irqsave(&interfaces_lock, flags); | 1942 | intf->intf_num = -1; |
| 1905 | ipmi_interfaces[i] = NULL; | 1943 | break; |
| 1906 | clean_up_interface_data(intf); | ||
| 1907 | spin_unlock_irqrestore(&interfaces_lock,flags); | ||
| 1908 | kfree(intf); | ||
| 1909 | rv = 0; | ||
| 1910 | goto out_call_watcher; | ||
| 1911 | } | ||
| 1912 | } | 1944 | } |
| 1913 | } else { | ||
| 1914 | rv = -EBUSY; | ||
| 1915 | } | 1945 | } |
| 1916 | up_write(&interfaces_sem); | 1946 | spin_unlock_irqrestore(&interfaces_lock,flags); |
| 1917 | 1947 | ||
| 1918 | return rv; | 1948 | if (i == MAX_IPMI_INTERFACES) |
| 1949 | return -ENODEV; | ||
| 1919 | 1950 | ||
| 1920 | out_call_watcher: | 1951 | remove_proc_entries(intf); |
| 1921 | downgrade_write(&interfaces_sem); | ||
| 1922 | 1952 | ||
| 1923 | /* Call all the watcher interfaces to tell them that | 1953 | /* Call all the watcher interfaces to tell them that |
| 1924 | an interface is gone. */ | 1954 | an interface is gone. */ |
| 1925 | down_read(&smi_watchers_sem); | 1955 | down_read(&smi_watchers_sem); |
| 1926 | list_for_each_entry(w, &smi_watchers, link) { | 1956 | list_for_each_entry(w, &smi_watchers, link) |
| 1927 | w->smi_gone(i); | 1957 | w->smi_gone(i); |
| 1928 | } | ||
| 1929 | up_read(&smi_watchers_sem); | 1958 | up_read(&smi_watchers_sem); |
| 1930 | up_read(&interfaces_sem); | 1959 | |
| 1960 | /* Allow the entry to be reused now. */ | ||
| 1961 | spin_lock_irqsave(&interfaces_lock, flags); | ||
| 1962 | ipmi_interfaces[i] = NULL; | ||
| 1963 | spin_unlock_irqrestore(&interfaces_lock,flags); | ||
| 1964 | |||
| 1965 | kref_put(&intf->refcount, intf_free); | ||
| 1931 | return 0; | 1966 | return 0; |
| 1932 | } | 1967 | } |
| 1933 | 1968 | ||
| @@ -1998,14 +2033,14 @@ static int handle_ipmb_get_msg_rsp(ipmi_smi_t intf, | |||
| 1998 | static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, | 2033 | static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, |
| 1999 | struct ipmi_smi_msg *msg) | 2034 | struct ipmi_smi_msg *msg) |
| 2000 | { | 2035 | { |
| 2001 | struct cmd_rcvr *rcvr; | 2036 | struct cmd_rcvr *rcvr; |
| 2002 | int rv = 0; | 2037 | int rv = 0; |
| 2003 | unsigned char netfn; | 2038 | unsigned char netfn; |
| 2004 | unsigned char cmd; | 2039 | unsigned char cmd; |
| 2005 | ipmi_user_t user = NULL; | 2040 | ipmi_user_t user = NULL; |
| 2006 | struct ipmi_ipmb_addr *ipmb_addr; | 2041 | struct ipmi_ipmb_addr *ipmb_addr; |
| 2007 | struct ipmi_recv_msg *recv_msg; | 2042 | struct ipmi_recv_msg *recv_msg; |
| 2008 | unsigned long flags; | 2043 | unsigned long flags; |
| 2009 | 2044 | ||
| 2010 | if (msg->rsp_size < 10) { | 2045 | if (msg->rsp_size < 10) { |
| 2011 | /* Message not big enough, just ignore it. */ | 2046 | /* Message not big enough, just ignore it. */ |
| @@ -2023,16 +2058,14 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, | |||
| 2023 | netfn = msg->rsp[4] >> 2; | 2058 | netfn = msg->rsp[4] >> 2; |
| 2024 | cmd = msg->rsp[8]; | 2059 | cmd = msg->rsp[8]; |
| 2025 | 2060 | ||
| 2026 | read_lock(&(intf->cmd_rcvr_lock)); | 2061 | spin_lock_irqsave(&intf->cmd_rcvrs_lock, flags); |
| 2027 | 2062 | rcvr = find_cmd_rcvr(intf, netfn, cmd); | |
| 2028 | /* Find the command/netfn. */ | 2063 | if (rcvr) { |
| 2029 | list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) { | 2064 | user = rcvr->user; |
| 2030 | if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) { | 2065 | kref_get(&user->refcount); |
| 2031 | user = rcvr->user; | 2066 | } else |
| 2032 | break; | 2067 | user = NULL; |
| 2033 | } | 2068 | spin_unlock_irqrestore(&intf->cmd_rcvrs_lock, flags); |
| 2034 | } | ||
| 2035 | read_unlock(&(intf->cmd_rcvr_lock)); | ||
| 2036 | 2069 | ||
| 2037 | if (user == NULL) { | 2070 | if (user == NULL) { |
| 2038 | /* We didn't find a user, deliver an error response. */ | 2071 | /* We didn't find a user, deliver an error response. */ |
| @@ -2079,6 +2112,7 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, | |||
| 2079 | message, so requeue it for handling | 2112 | message, so requeue it for handling |
| 2080 | later. */ | 2113 | later. */ |
| 2081 | rv = 1; | 2114 | rv = 1; |
| 2115 | kref_put(&user->refcount, free_user); | ||
| 2082 | } else { | 2116 | } else { |
| 2083 | /* Extract the source address from the data. */ | 2117 | /* Extract the source address from the data. */ |
| 2084 | ipmb_addr = (struct ipmi_ipmb_addr *) &recv_msg->addr; | 2118 | ipmb_addr = (struct ipmi_ipmb_addr *) &recv_msg->addr; |
| @@ -2179,14 +2213,14 @@ static int handle_lan_get_msg_rsp(ipmi_smi_t intf, | |||
| 2179 | static int handle_lan_get_msg_cmd(ipmi_smi_t intf, | 2213 | static int handle_lan_get_msg_cmd(ipmi_smi_t intf, |
| 2180 | struct ipmi_smi_msg *msg) | 2214 | struct ipmi_smi_msg *msg) |
| 2181 | { | 2215 | { |
| 2182 | struct cmd_rcvr *rcvr; | 2216 | struct cmd_rcvr *rcvr; |
| 2183 | int rv = 0; | 2217 | int rv = 0; |
| 2184 | unsigned char netfn; | 2218 | unsigned char netfn; |
| 2185 | unsigned char cmd; | 2219 | unsigned char cmd; |
| 2186 | ipmi_user_t user = NULL; | 2220 | ipmi_user_t user = NULL; |
| 2187 | struct ipmi_lan_addr *lan_addr; | 2221 | struct ipmi_lan_addr *lan_addr; |
| 2188 | struct ipmi_recv_msg *recv_msg; | 2222 | struct ipmi_recv_msg *recv_msg; |
| 2189 | unsigned long flags; | 2223 | unsigned long flags; |
| 2190 | 2224 | ||
| 2191 | if (msg->rsp_size < 12) { | 2225 | if (msg->rsp_size < 12) { |
| 2192 | /* Message not big enough, just ignore it. */ | 2226 | /* Message not big enough, just ignore it. */ |
| @@ -2204,19 +2238,17 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf, | |||
| 2204 | netfn = msg->rsp[6] >> 2; | 2238 | netfn = msg->rsp[6] >> 2; |
| 2205 | cmd = msg->rsp[10]; | 2239 | cmd = msg->rsp[10]; |
| 2206 | 2240 | ||
| 2207 | read_lock(&(intf->cmd_rcvr_lock)); | 2241 | spin_lock_irqsave(&intf->cmd_rcvrs_lock, flags); |
| 2208 | 2242 | rcvr = find_cmd_rcvr(intf, netfn, cmd); | |
| 2209 | /* Find the command/netfn. */ | 2243 | if (rcvr) { |
| 2210 | list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) { | 2244 | user = rcvr->user; |
| 2211 | if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) { | 2245 | kref_get(&user->refcount); |
| 2212 | user = rcvr->user; | 2246 | } else |
| 2213 | break; | 2247 | user = NULL; |
| 2214 | } | 2248 | spin_unlock_irqrestore(&intf->cmd_rcvrs_lock, flags); |
| 2215 | } | ||
| 2216 | read_unlock(&(intf->cmd_rcvr_lock)); | ||
| 2217 | 2249 | ||
| 2218 | if (user == NULL) { | 2250 | if (user == NULL) { |
| 2219 | /* We didn't find a user, deliver an error response. */ | 2251 | /* We didn't find a user, just give up. */ |
| 2220 | spin_lock_irqsave(&intf->counter_lock, flags); | 2252 | spin_lock_irqsave(&intf->counter_lock, flags); |
| 2221 | intf->unhandled_commands++; | 2253 | intf->unhandled_commands++; |
| 2222 | spin_unlock_irqrestore(&intf->counter_lock, flags); | 2254 | spin_unlock_irqrestore(&intf->counter_lock, flags); |
| @@ -2235,6 +2267,7 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf, | |||
| 2235 | message, so requeue it for handling | 2267 | message, so requeue it for handling |
| 2236 | later. */ | 2268 | later. */ |
| 2237 | rv = 1; | 2269 | rv = 1; |
| 2270 | kref_put(&user->refcount, free_user); | ||
| 2238 | } else { | 2271 | } else { |
| 2239 | /* Extract the source address from the data. */ | 2272 | /* Extract the source address from the data. */ |
| 2240 | lan_addr = (struct ipmi_lan_addr *) &recv_msg->addr; | 2273 | lan_addr = (struct ipmi_lan_addr *) &recv_msg->addr; |
| @@ -2286,8 +2319,6 @@ static void copy_event_into_recv_msg(struct ipmi_recv_msg *recv_msg, | |||
| 2286 | recv_msg->msg.data_len = msg->rsp_size - 3; | 2319 | recv_msg->msg.data_len = msg->rsp_size - 3; |
| 2287 | } | 2320 | } |
| 2288 | 2321 | ||
| 2289 | /* This will be called with the intf->users_lock read-locked, so no need | ||
| 2290 | to do that here. */ | ||
| 2291 | static int handle_read_event_rsp(ipmi_smi_t intf, | 2322 | static int handle_read_event_rsp(ipmi_smi_t intf, |
| 2292 | struct ipmi_smi_msg *msg) | 2323 | struct ipmi_smi_msg *msg) |
| 2293 | { | 2324 | { |
| @@ -2313,7 +2344,7 @@ static int handle_read_event_rsp(ipmi_smi_t intf, | |||
| 2313 | 2344 | ||
| 2314 | INIT_LIST_HEAD(&msgs); | 2345 | INIT_LIST_HEAD(&msgs); |
| 2315 | 2346 | ||
| 2316 | spin_lock_irqsave(&(intf->events_lock), flags); | 2347 | spin_lock_irqsave(&intf->events_lock, flags); |
| 2317 | 2348 | ||
| 2318 | spin_lock(&intf->counter_lock); | 2349 | spin_lock(&intf->counter_lock); |
| 2319 | intf->events++; | 2350 | intf->events++; |
| @@ -2321,12 +2352,14 @@ static int handle_read_event_rsp(ipmi_smi_t intf, | |||
| 2321 | 2352 | ||
| 2322 | /* Allocate and fill in one message for every user that is getting | 2353 | /* Allocate and fill in one message for every user that is getting |
| 2323 | events. */ | 2354 | events. */ |
| 2324 | list_for_each_entry(user, &(intf->users), link) { | 2355 | rcu_read_lock(); |
| 2356 | list_for_each_entry_rcu(user, &intf->users, link) { | ||
| 2325 | if (! user->gets_events) | 2357 | if (! user->gets_events) |
| 2326 | continue; | 2358 | continue; |
| 2327 | 2359 | ||
| 2328 | recv_msg = ipmi_alloc_recv_msg(); | 2360 | recv_msg = ipmi_alloc_recv_msg(); |
| 2329 | if (! recv_msg) { | 2361 | if (! recv_msg) { |
| 2362 | rcu_read_unlock(); | ||
| 2330 | list_for_each_entry_safe(recv_msg, recv_msg2, &msgs, link) { | 2363 | list_for_each_entry_safe(recv_msg, recv_msg2, &msgs, link) { |
| 2331 | list_del(&recv_msg->link); | 2364 | list_del(&recv_msg->link); |
| 2332 | ipmi_free_recv_msg(recv_msg); | 2365 | ipmi_free_recv_msg(recv_msg); |
| @@ -2342,8 +2375,10 @@ static int handle_read_event_rsp(ipmi_smi_t intf, | |||
| 2342 | 2375 | ||
| 2343 | copy_event_into_recv_msg(recv_msg, msg); | 2376 | copy_event_into_recv_msg(recv_msg, msg); |
| 2344 | recv_msg->user = user; | 2377 | recv_msg->user = user; |
| 2378 | kref_get(&user->refcount); | ||
| 2345 | list_add_tail(&(recv_msg->link), &msgs); | 2379 | list_add_tail(&(recv_msg->link), &msgs); |
| 2346 | } | 2380 | } |
| 2381 | rcu_read_unlock(); | ||
| 2347 | 2382 | ||
| 2348 | if (deliver_count) { | 2383 | if (deliver_count) { |
| 2349 | /* Now deliver all the messages. */ | 2384 | /* Now deliver all the messages. */ |
| @@ -2382,9 +2417,8 @@ static int handle_bmc_rsp(ipmi_smi_t intf, | |||
| 2382 | struct ipmi_smi_msg *msg) | 2417 | struct ipmi_smi_msg *msg) |
| 2383 | { | 2418 | { |
| 2384 | struct ipmi_recv_msg *recv_msg; | 2419 | struct ipmi_recv_msg *recv_msg; |
| 2385 | int found = 0; | ||
| 2386 | struct ipmi_user *user; | ||
| 2387 | unsigned long flags; | 2420 | unsigned long flags; |
| 2421 | struct ipmi_user *user; | ||
| 2388 | 2422 | ||
| 2389 | recv_msg = (struct ipmi_recv_msg *) msg->user_data; | 2423 | recv_msg = (struct ipmi_recv_msg *) msg->user_data; |
| 2390 | if (recv_msg == NULL) | 2424 | if (recv_msg == NULL) |
| @@ -2396,16 +2430,9 @@ static int handle_bmc_rsp(ipmi_smi_t intf, | |||
| 2396 | return 0; | 2430 | return 0; |
| 2397 | } | 2431 | } |
| 2398 | 2432 | ||
| 2433 | user = recv_msg->user; | ||
| 2399 | /* Make sure the user still exists. */ | 2434 | /* Make sure the user still exists. */ |
| 2400 | list_for_each_entry(user, &(intf->users), link) { | 2435 | if (user && !user->valid) { |
| 2401 | if (user == recv_msg->user) { | ||
| 2402 | /* Found it, so we can deliver it */ | ||
| 2403 | found = 1; | ||
| 2404 | break; | ||
| 2405 | } | ||
| 2406 | } | ||
| 2407 | |||
| 2408 | if ((! found) && recv_msg->user) { | ||
| 2409 | /* The user for the message went away, so give up. */ | 2436 | /* The user for the message went away, so give up. */ |
| 2410 | spin_lock_irqsave(&intf->counter_lock, flags); | 2437 | spin_lock_irqsave(&intf->counter_lock, flags); |
| 2411 | intf->unhandled_local_responses++; | 2438 | intf->unhandled_local_responses++; |
| @@ -2486,7 +2513,7 @@ static int handle_new_recv_msg(ipmi_smi_t intf, | |||
| 2486 | { | 2513 | { |
| 2487 | /* It's a response to a response we sent. For this we | 2514 | /* It's a response to a response we sent. For this we |
| 2488 | deliver a send message response to the user. */ | 2515 | deliver a send message response to the user. */ |
| 2489 | struct ipmi_recv_msg *recv_msg = msg->user_data; | 2516 | struct ipmi_recv_msg *recv_msg = msg->user_data; |
| 2490 | 2517 | ||
| 2491 | requeue = 0; | 2518 | requeue = 0; |
| 2492 | if (msg->rsp_size < 2) | 2519 | if (msg->rsp_size < 2) |
| @@ -2498,13 +2525,18 @@ static int handle_new_recv_msg(ipmi_smi_t intf, | |||
| 2498 | /* Invalid channel number */ | 2525 | /* Invalid channel number */ |
| 2499 | goto out; | 2526 | goto out; |
| 2500 | 2527 | ||
| 2501 | if (recv_msg) { | 2528 | if (!recv_msg) |
| 2502 | recv_msg->recv_type = IPMI_RESPONSE_RESPONSE_TYPE; | 2529 | goto out; |
| 2503 | recv_msg->msg.data = recv_msg->msg_data; | 2530 | |
| 2504 | recv_msg->msg.data_len = 1; | 2531 | /* Make sure the user still exists. */ |
| 2505 | recv_msg->msg_data[0] = msg->rsp[2]; | 2532 | if (!recv_msg->user || !recv_msg->user->valid) |
| 2506 | deliver_response(recv_msg); | 2533 | goto out; |
| 2507 | } | 2534 | |
| 2535 | recv_msg->recv_type = IPMI_RESPONSE_RESPONSE_TYPE; | ||
| 2536 | recv_msg->msg.data = recv_msg->msg_data; | ||
| 2537 | recv_msg->msg.data_len = 1; | ||
| 2538 | recv_msg->msg_data[0] = msg->rsp[2]; | ||
| 2539 | deliver_response(recv_msg); | ||
| 2508 | } else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2)) | 2540 | } else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2)) |
| 2509 | && (msg->rsp[1] == IPMI_GET_MSG_CMD)) | 2541 | && (msg->rsp[1] == IPMI_GET_MSG_CMD)) |
| 2510 | { | 2542 | { |
| @@ -2570,14 +2602,11 @@ void ipmi_smi_msg_received(ipmi_smi_t intf, | |||
| 2570 | int rv; | 2602 | int rv; |
| 2571 | 2603 | ||
| 2572 | 2604 | ||
| 2573 | /* Lock the user lock so the user can't go away while we are | ||
| 2574 | working on it. */ | ||
| 2575 | read_lock(&(intf->users_lock)); | ||
| 2576 | |||
| 2577 | if ((msg->data_size >= 2) | 2605 | if ((msg->data_size >= 2) |
| 2578 | && (msg->data[0] == (IPMI_NETFN_APP_REQUEST << 2)) | 2606 | && (msg->data[0] == (IPMI_NETFN_APP_REQUEST << 2)) |
| 2579 | && (msg->data[1] == IPMI_SEND_MSG_CMD) | 2607 | && (msg->data[1] == IPMI_SEND_MSG_CMD) |
| 2580 | && (msg->user_data == NULL)) { | 2608 | && (msg->user_data == NULL)) |
| 2609 | { | ||
| 2581 | /* This is the local response to a command send, start | 2610 | /* This is the local response to a command send, start |
| 2582 | the timer for these. The user_data will not be | 2611 | the timer for these. The user_data will not be |
| 2583 | NULL if this is a response send, and we will let | 2612 | NULL if this is a response send, and we will let |
| @@ -2612,46 +2641,46 @@ void ipmi_smi_msg_received(ipmi_smi_t intf, | |||
| 2612 | } | 2641 | } |
| 2613 | 2642 | ||
| 2614 | ipmi_free_smi_msg(msg); | 2643 | ipmi_free_smi_msg(msg); |
| 2615 | goto out_unlock; | 2644 | goto out; |
| 2616 | } | 2645 | } |
| 2617 | 2646 | ||
| 2618 | /* To preserve message order, if the list is not empty, we | 2647 | /* To preserve message order, if the list is not empty, we |
| 2619 | tack this message onto the end of the list. */ | 2648 | tack this message onto the end of the list. */ |
| 2620 | spin_lock_irqsave(&(intf->waiting_msgs_lock), flags); | 2649 | spin_lock_irqsave(&intf->waiting_msgs_lock, flags); |
| 2621 | if (!list_empty(&(intf->waiting_msgs))) { | 2650 | if (!list_empty(&intf->waiting_msgs)) { |
| 2622 | list_add_tail(&(msg->link), &(intf->waiting_msgs)); | 2651 | list_add_tail(&msg->link, &intf->waiting_msgs); |
| 2623 | spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags); | 2652 | spin_unlock(&intf->waiting_msgs_lock); |
| 2624 | goto out_unlock; | 2653 | goto out; |
| 2625 | } | 2654 | } |
| 2626 | spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags); | 2655 | spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags); |
| 2627 | 2656 | ||
| 2628 | rv = handle_new_recv_msg(intf, msg); | 2657 | rv = handle_new_recv_msg(intf, msg); |
| 2629 | if (rv > 0) { | 2658 | if (rv > 0) { |
| 2630 | /* Could not handle the message now, just add it to a | 2659 | /* Could not handle the message now, just add it to a |
| 2631 | list to handle later. */ | 2660 | list to handle later. */ |
| 2632 | spin_lock_irqsave(&(intf->waiting_msgs_lock), flags); | 2661 | spin_lock(&intf->waiting_msgs_lock); |
| 2633 | list_add_tail(&(msg->link), &(intf->waiting_msgs)); | 2662 | list_add_tail(&msg->link, &intf->waiting_msgs); |
| 2634 | spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags); | 2663 | spin_unlock(&intf->waiting_msgs_lock); |
| 2635 | } else if (rv == 0) { | 2664 | } else if (rv == 0) { |
| 2636 | ipmi_free_smi_msg(msg); | 2665 | ipmi_free_smi_msg(msg); |
| 2637 | } | 2666 | } |
| 2638 | 2667 | ||
| 2639 | out_unlock: | 2668 | out: |
| 2640 | read_unlock(&(intf->users_lock)); | 2669 | return; |
| 2641 | } | 2670 | } |
| 2642 | 2671 | ||
| 2643 | void ipmi_smi_watchdog_pretimeout(ipmi_smi_t intf) | 2672 | void ipmi_smi_watchdog_pretimeout(ipmi_smi_t intf) |
| 2644 | { | 2673 | { |
| 2645 | ipmi_user_t user; | 2674 | ipmi_user_t user; |
| 2646 | 2675 | ||
| 2647 | read_lock(&(intf->users_lock)); | 2676 | rcu_read_lock(); |
| 2648 | list_for_each_entry(user, &(intf->users), link) { | 2677 | list_for_each_entry_rcu(user, &intf->users, link) { |
| 2649 | if (! user->handler->ipmi_watchdog_pretimeout) | 2678 | if (! user->handler->ipmi_watchdog_pretimeout) |
| 2650 | continue; | 2679 | continue; |
| 2651 | 2680 | ||
| 2652 | user->handler->ipmi_watchdog_pretimeout(user->handler_data); | 2681 | user->handler->ipmi_watchdog_pretimeout(user->handler_data); |
| 2653 | } | 2682 | } |
| 2654 | read_unlock(&(intf->users_lock)); | 2683 | rcu_read_unlock(); |
| 2655 | } | 2684 | } |
| 2656 | 2685 | ||
| 2657 | static void | 2686 | static void |
| @@ -2691,8 +2720,65 @@ smi_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg, | |||
| 2691 | return smi_msg; | 2720 | return smi_msg; |
| 2692 | } | 2721 | } |
| 2693 | 2722 | ||
| 2694 | static void | 2723 | static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, |
| 2695 | ipmi_timeout_handler(long timeout_period) | 2724 | struct list_head *timeouts, long timeout_period, |
| 2725 | int slot, unsigned long *flags) | ||
| 2726 | { | ||
| 2727 | struct ipmi_recv_msg *msg; | ||
| 2728 | |||
| 2729 | if (!ent->inuse) | ||
| 2730 | return; | ||
| 2731 | |||
| 2732 | ent->timeout -= timeout_period; | ||
| 2733 | if (ent->timeout > 0) | ||
| 2734 | return; | ||
| 2735 | |||
| 2736 | if (ent->retries_left == 0) { | ||
| 2737 | /* The message has used all its retries. */ | ||
| 2738 | ent->inuse = 0; | ||
| 2739 | msg = ent->recv_msg; | ||
| 2740 | list_add_tail(&msg->link, timeouts); | ||
| 2741 | spin_lock(&intf->counter_lock); | ||
| 2742 | if (ent->broadcast) | ||
| 2743 | intf->timed_out_ipmb_broadcasts++; | ||
| 2744 | else if (ent->recv_msg->addr.addr_type == IPMI_LAN_ADDR_TYPE) | ||
| 2745 | intf->timed_out_lan_commands++; | ||
| 2746 | else | ||
| 2747 | intf->timed_out_ipmb_commands++; | ||
| 2748 | spin_unlock(&intf->counter_lock); | ||
| 2749 | } else { | ||
| 2750 | struct ipmi_smi_msg *smi_msg; | ||
| 2751 | /* More retries, send again. */ | ||
| 2752 | |||
| 2753 | /* Start with the max timer, set to normal | ||
| 2754 | timer after the message is sent. */ | ||
| 2755 | ent->timeout = MAX_MSG_TIMEOUT; | ||
| 2756 | ent->retries_left--; | ||
| 2757 | spin_lock(&intf->counter_lock); | ||
| 2758 | if (ent->recv_msg->addr.addr_type == IPMI_LAN_ADDR_TYPE) | ||
| 2759 | intf->retransmitted_lan_commands++; | ||
| 2760 | else | ||
| 2761 | intf->retransmitted_ipmb_commands++; | ||
| 2762 | spin_unlock(&intf->counter_lock); | ||
| 2763 | |||
| 2764 | smi_msg = smi_from_recv_msg(intf, ent->recv_msg, slot, | ||
| 2765 | ent->seqid); | ||
| 2766 | if (! smi_msg) | ||
| 2767 | return; | ||
| 2768 | |||
| 2769 | spin_unlock_irqrestore(&intf->seq_lock, *flags); | ||
| 2770 | /* Send the new message. We send with a zero | ||
| 2771 | * priority. It timed out, I doubt time is | ||
| 2772 | * that critical now, and high priority | ||
| 2773 | * messages are really only for messages to the | ||
| 2774 | * local MC, which don't get resent. */ | ||
| 2775 | intf->handlers->sender(intf->send_info, | ||
| 2776 | smi_msg, 0); | ||
| 2777 | spin_lock_irqsave(&intf->seq_lock, *flags); | ||
| 2778 | } | ||
| 2779 | } | ||
| 2780 | |||
| 2781 | static void ipmi_timeout_handler(long timeout_period) | ||
| 2696 | { | 2782 | { |
| 2697 | ipmi_smi_t intf; | 2783 | ipmi_smi_t intf; |
| 2698 | struct list_head timeouts; | 2784 | struct list_head timeouts; |
| @@ -2706,14 +2792,14 @@ ipmi_timeout_handler(long timeout_period) | |||
| 2706 | spin_lock(&interfaces_lock); | 2792 | spin_lock(&interfaces_lock); |
| 2707 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { | 2793 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { |
| 2708 | intf = ipmi_interfaces[i]; | 2794 | intf = ipmi_interfaces[i]; |
| 2709 | if (intf == NULL) | 2795 | if (IPMI_INVALID_INTERFACE(intf)) |
| 2710 | continue; | 2796 | continue; |
| 2711 | 2797 | kref_get(&intf->refcount); | |
| 2712 | read_lock(&(intf->users_lock)); | 2798 | spin_unlock(&interfaces_lock); |
| 2713 | 2799 | ||
| 2714 | /* See if any waiting messages need to be processed. */ | 2800 | /* See if any waiting messages need to be processed. */ |
| 2715 | spin_lock_irqsave(&(intf->waiting_msgs_lock), flags); | 2801 | spin_lock_irqsave(&intf->waiting_msgs_lock, flags); |
| 2716 | list_for_each_entry_safe(smi_msg, smi_msg2, &(intf->waiting_msgs), link) { | 2802 | list_for_each_entry_safe(smi_msg, smi_msg2, &intf->waiting_msgs, link) { |
| 2717 | if (! handle_new_recv_msg(intf, smi_msg)) { | 2803 | if (! handle_new_recv_msg(intf, smi_msg)) { |
| 2718 | list_del(&smi_msg->link); | 2804 | list_del(&smi_msg->link); |
| 2719 | ipmi_free_smi_msg(smi_msg); | 2805 | ipmi_free_smi_msg(smi_msg); |
| @@ -2723,73 +2809,23 @@ ipmi_timeout_handler(long timeout_period) | |||
| 2723 | break; | 2809 | break; |
| 2724 | } | 2810 | } |
| 2725 | } | 2811 | } |
| 2726 | spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags); | 2812 | spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags); |
| 2727 | 2813 | ||
| 2728 | /* Go through the seq table and find any messages that | 2814 | /* Go through the seq table and find any messages that |
| 2729 | have timed out, putting them in the timeouts | 2815 | have timed out, putting them in the timeouts |
| 2730 | list. */ | 2816 | list. */ |
| 2731 | spin_lock_irqsave(&(intf->seq_lock), flags); | 2817 | spin_lock_irqsave(&intf->seq_lock, flags); |
| 2732 | for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) { | 2818 | for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) |
| 2733 | struct seq_table *ent = &(intf->seq_table[j]); | 2819 | check_msg_timeout(intf, &(intf->seq_table[j]), |
| 2734 | if (!ent->inuse) | 2820 | &timeouts, timeout_period, j, |
| 2735 | continue; | 2821 | &flags); |
| 2736 | 2822 | spin_unlock_irqrestore(&intf->seq_lock, flags); | |
| 2737 | ent->timeout -= timeout_period; | 2823 | |
| 2738 | if (ent->timeout > 0) | 2824 | list_for_each_entry_safe(msg, msg2, &timeouts, link) |
| 2739 | continue; | ||
| 2740 | |||
| 2741 | if (ent->retries_left == 0) { | ||
| 2742 | /* The message has used all its retries. */ | ||
| 2743 | ent->inuse = 0; | ||
| 2744 | msg = ent->recv_msg; | ||
| 2745 | list_add_tail(&(msg->link), &timeouts); | ||
| 2746 | spin_lock(&intf->counter_lock); | ||
| 2747 | if (ent->broadcast) | ||
| 2748 | intf->timed_out_ipmb_broadcasts++; | ||
| 2749 | else if (ent->recv_msg->addr.addr_type | ||
| 2750 | == IPMI_LAN_ADDR_TYPE) | ||
| 2751 | intf->timed_out_lan_commands++; | ||
| 2752 | else | ||
| 2753 | intf->timed_out_ipmb_commands++; | ||
| 2754 | spin_unlock(&intf->counter_lock); | ||
| 2755 | } else { | ||
| 2756 | struct ipmi_smi_msg *smi_msg; | ||
| 2757 | /* More retries, send again. */ | ||
| 2758 | |||
| 2759 | /* Start with the max timer, set to normal | ||
| 2760 | timer after the message is sent. */ | ||
| 2761 | ent->timeout = MAX_MSG_TIMEOUT; | ||
| 2762 | ent->retries_left--; | ||
| 2763 | spin_lock(&intf->counter_lock); | ||
| 2764 | if (ent->recv_msg->addr.addr_type | ||
| 2765 | == IPMI_LAN_ADDR_TYPE) | ||
| 2766 | intf->retransmitted_lan_commands++; | ||
| 2767 | else | ||
| 2768 | intf->retransmitted_ipmb_commands++; | ||
| 2769 | spin_unlock(&intf->counter_lock); | ||
| 2770 | smi_msg = smi_from_recv_msg(intf, | ||
| 2771 | ent->recv_msg, j, ent->seqid); | ||
| 2772 | if (! smi_msg) | ||
| 2773 | continue; | ||
| 2774 | |||
| 2775 | spin_unlock_irqrestore(&(intf->seq_lock),flags); | ||
| 2776 | /* Send the new message. We send with a zero | ||
| 2777 | * priority. It timed out, I doubt time is | ||
| 2778 | * that critical now, and high priority | ||
| 2779 | * messages are really only for messages to the | ||
| 2780 | * local MC, which don't get resent. */ | ||
| 2781 | intf->handlers->sender(intf->send_info, | ||
| 2782 | smi_msg, 0); | ||
| 2783 | spin_lock_irqsave(&(intf->seq_lock), flags); | ||
| 2784 | } | ||
| 2785 | } | ||
| 2786 | spin_unlock_irqrestore(&(intf->seq_lock), flags); | ||
| 2787 | |||
| 2788 | list_for_each_entry_safe(msg, msg2, &timeouts, link) { | ||
| 2789 | handle_msg_timeout(msg); | 2825 | handle_msg_timeout(msg); |
| 2790 | } | ||
| 2791 | 2826 | ||
| 2792 | read_unlock(&(intf->users_lock)); | 2827 | kref_put(&intf->refcount, intf_free); |
| 2828 | spin_lock(&interfaces_lock); | ||
| 2793 | } | 2829 | } |
| 2794 | spin_unlock(&interfaces_lock); | 2830 | spin_unlock(&interfaces_lock); |
| 2795 | } | 2831 | } |
| @@ -2802,7 +2838,7 @@ static void ipmi_request_event(void) | |||
| 2802 | spin_lock(&interfaces_lock); | 2838 | spin_lock(&interfaces_lock); |
| 2803 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { | 2839 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { |
| 2804 | intf = ipmi_interfaces[i]; | 2840 | intf = ipmi_interfaces[i]; |
| 2805 | if (intf == NULL) | 2841 | if (IPMI_INVALID_INTERFACE(intf)) |
| 2806 | continue; | 2842 | continue; |
| 2807 | 2843 | ||
| 2808 | intf->handlers->request_events(intf->send_info); | 2844 | intf->handlers->request_events(intf->send_info); |
| @@ -2884,6 +2920,13 @@ struct ipmi_recv_msg *ipmi_alloc_recv_msg(void) | |||
| 2884 | return rv; | 2920 | return rv; |
| 2885 | } | 2921 | } |
| 2886 | 2922 | ||
| 2923 | void ipmi_free_recv_msg(struct ipmi_recv_msg *msg) | ||
| 2924 | { | ||
| 2925 | if (msg->user) | ||
| 2926 | kref_put(&msg->user->refcount, free_user); | ||
| 2927 | msg->done(msg); | ||
| 2928 | } | ||
| 2929 | |||
| 2887 | #ifdef CONFIG_IPMI_PANIC_EVENT | 2930 | #ifdef CONFIG_IPMI_PANIC_EVENT |
| 2888 | 2931 | ||
| 2889 | static void dummy_smi_done_handler(struct ipmi_smi_msg *msg) | 2932 | static void dummy_smi_done_handler(struct ipmi_smi_msg *msg) |
| @@ -2964,7 +3007,7 @@ static void send_panic_events(char *str) | |||
| 2964 | /* For every registered interface, send the event. */ | 3007 | /* For every registered interface, send the event. */ |
| 2965 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { | 3008 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { |
| 2966 | intf = ipmi_interfaces[i]; | 3009 | intf = ipmi_interfaces[i]; |
| 2967 | if (intf == NULL) | 3010 | if (IPMI_INVALID_INTERFACE(intf)) |
| 2968 | continue; | 3011 | continue; |
| 2969 | 3012 | ||
| 2970 | /* Send the event announcing the panic. */ | 3013 | /* Send the event announcing the panic. */ |
| @@ -2995,7 +3038,7 @@ static void send_panic_events(char *str) | |||
| 2995 | int j; | 3038 | int j; |
| 2996 | 3039 | ||
| 2997 | intf = ipmi_interfaces[i]; | 3040 | intf = ipmi_interfaces[i]; |
| 2998 | if (intf == NULL) | 3041 | if (IPMI_INVALID_INTERFACE(intf)) |
| 2999 | continue; | 3042 | continue; |
| 3000 | 3043 | ||
| 3001 | /* First job here is to figure out where to send the | 3044 | /* First job here is to figure out where to send the |
| @@ -3131,7 +3174,7 @@ static int panic_event(struct notifier_block *this, | |||
| 3131 | /* For every registered interface, set it to run to completion. */ | 3174 | /* For every registered interface, set it to run to completion. */ |
| 3132 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { | 3175 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { |
| 3133 | intf = ipmi_interfaces[i]; | 3176 | intf = ipmi_interfaces[i]; |
| 3134 | if (intf == NULL) | 3177 | if (IPMI_INVALID_INTERFACE(intf)) |
| 3135 | continue; | 3178 | continue; |
| 3136 | 3179 | ||
| 3137 | intf->handlers->set_run_to_completion(intf->send_info, 1); | 3180 | intf->handlers->set_run_to_completion(intf->send_info, 1); |
| @@ -3160,9 +3203,8 @@ static int ipmi_init_msghandler(void) | |||
| 3160 | printk(KERN_INFO "ipmi message handler version " | 3203 | printk(KERN_INFO "ipmi message handler version " |
| 3161 | IPMI_DRIVER_VERSION "\n"); | 3204 | IPMI_DRIVER_VERSION "\n"); |
| 3162 | 3205 | ||
| 3163 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { | 3206 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) |
| 3164 | ipmi_interfaces[i] = NULL; | 3207 | ipmi_interfaces[i] = NULL; |
| 3165 | } | ||
| 3166 | 3208 | ||
| 3167 | #ifdef CONFIG_PROC_FS | 3209 | #ifdef CONFIG_PROC_FS |
| 3168 | proc_ipmi_root = proc_mkdir("ipmi", NULL); | 3210 | proc_ipmi_root = proc_mkdir("ipmi", NULL); |
| @@ -3258,3 +3300,4 @@ EXPORT_SYMBOL(ipmi_get_my_LUN); | |||
| 3258 | EXPORT_SYMBOL(ipmi_smi_add_proc_entry); | 3300 | EXPORT_SYMBOL(ipmi_smi_add_proc_entry); |
| 3259 | EXPORT_SYMBOL(proc_ipmi_root); | 3301 | EXPORT_SYMBOL(proc_ipmi_root); |
| 3260 | EXPORT_SYMBOL(ipmi_user_set_run_to_completion); | 3302 | EXPORT_SYMBOL(ipmi_user_set_run_to_completion); |
| 3303 | EXPORT_SYMBOL(ipmi_free_recv_msg); | ||
diff --git a/include/linux/ipmi.h b/include/linux/ipmi.h index 938d55b813a..d6276e60b3b 100644 --- a/include/linux/ipmi.h +++ b/include/linux/ipmi.h | |||
| @@ -256,10 +256,7 @@ struct ipmi_recv_msg | |||
| 256 | }; | 256 | }; |
| 257 | 257 | ||
| 258 | /* Allocate and free the receive message. */ | 258 | /* Allocate and free the receive message. */ |
| 259 | static inline void ipmi_free_recv_msg(struct ipmi_recv_msg *msg) | 259 | void ipmi_free_recv_msg(struct ipmi_recv_msg *msg); |
| 260 | { | ||
| 261 | msg->done(msg); | ||
| 262 | } | ||
| 263 | 260 | ||
| 264 | struct ipmi_user_hndl | 261 | struct ipmi_user_hndl |
| 265 | { | 262 | { |
