diff options
Diffstat (limited to 'drivers/char/ipmi/ipmi_msghandler.c')
-rw-r--r-- | drivers/char/ipmi/ipmi_msghandler.c | 724 |
1 files changed, 488 insertions, 236 deletions
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index c47add8e47df..5703ee28e1cc 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -48,7 +48,7 @@ | |||
48 | 48 | ||
49 | #define PFX "IPMI message handler: " | 49 | #define PFX "IPMI message handler: " |
50 | 50 | ||
51 | #define IPMI_DRIVER_VERSION "39.0" | 51 | #define IPMI_DRIVER_VERSION "39.1" |
52 | 52 | ||
53 | static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void); | 53 | static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void); |
54 | static int ipmi_init_msghandler(void); | 54 | static int ipmi_init_msghandler(void); |
@@ -59,6 +59,9 @@ static int initialized = 0; | |||
59 | static struct proc_dir_entry *proc_ipmi_root = NULL; | 59 | static struct proc_dir_entry *proc_ipmi_root = NULL; |
60 | #endif /* CONFIG_PROC_FS */ | 60 | #endif /* CONFIG_PROC_FS */ |
61 | 61 | ||
62 | /* Remain in auto-maintenance mode for this amount of time (in ms). */ | ||
63 | #define IPMI_MAINTENANCE_MODE_TIMEOUT 30000 | ||
64 | |||
62 | #define MAX_EVENTS_IN_QUEUE 25 | 65 | #define MAX_EVENTS_IN_QUEUE 25 |
63 | 66 | ||
64 | /* Don't let a message sit in a queue forever, always time it with at lest | 67 | /* Don't let a message sit in a queue forever, always time it with at lest |
@@ -193,17 +196,28 @@ struct ipmi_smi | |||
193 | 196 | ||
194 | struct kref refcount; | 197 | struct kref refcount; |
195 | 198 | ||
199 | /* Used for a list of interfaces. */ | ||
200 | struct list_head link; | ||
201 | |||
196 | /* The list of upper layers that are using me. seq_lock | 202 | /* The list of upper layers that are using me. seq_lock |
197 | * protects this. */ | 203 | * protects this. */ |
198 | struct list_head users; | 204 | struct list_head users; |
199 | 205 | ||
206 | /* Information to supply to users. */ | ||
207 | unsigned char ipmi_version_major; | ||
208 | unsigned char ipmi_version_minor; | ||
209 | |||
200 | /* Used for wake ups at startup. */ | 210 | /* Used for wake ups at startup. */ |
201 | wait_queue_head_t waitq; | 211 | wait_queue_head_t waitq; |
202 | 212 | ||
203 | struct bmc_device *bmc; | 213 | struct bmc_device *bmc; |
204 | char *my_dev_name; | 214 | char *my_dev_name; |
215 | char *sysfs_name; | ||
205 | 216 | ||
206 | /* This is the lower-layer's sender routine. */ | 217 | /* This is the lower-layer's sender routine. Note that you |
218 | * must either be holding the ipmi_interfaces_mutex or be in | ||
219 | * an umpreemptible region to use this. You must fetch the | ||
220 | * value into a local variable and make sure it is not NULL. */ | ||
207 | struct ipmi_smi_handlers *handlers; | 221 | struct ipmi_smi_handlers *handlers; |
208 | void *send_info; | 222 | void *send_info; |
209 | 223 | ||
@@ -242,6 +256,7 @@ struct ipmi_smi | |||
242 | spinlock_t events_lock; /* For dealing with event stuff. */ | 256 | spinlock_t events_lock; /* For dealing with event stuff. */ |
243 | struct list_head waiting_events; | 257 | struct list_head waiting_events; |
244 | unsigned int waiting_events_count; /* How many events in queue? */ | 258 | unsigned int waiting_events_count; /* How many events in queue? */ |
259 | int delivering_events; | ||
245 | 260 | ||
246 | /* The event receiver for my BMC, only really used at panic | 261 | /* The event receiver for my BMC, only really used at panic |
247 | shutdown as a place to store this. */ | 262 | shutdown as a place to store this. */ |
@@ -250,6 +265,12 @@ struct ipmi_smi | |||
250 | unsigned char local_sel_device; | 265 | unsigned char local_sel_device; |
251 | unsigned char local_event_generator; | 266 | unsigned char local_event_generator; |
252 | 267 | ||
268 | /* For handling of maintenance mode. */ | ||
269 | int maintenance_mode; | ||
270 | int maintenance_mode_enable; | ||
271 | int auto_maintenance_timeout; | ||
272 | spinlock_t maintenance_mode_lock; /* Used in a timer... */ | ||
273 | |||
253 | /* A cheap hack, if this is non-null and a message to an | 274 | /* A cheap hack, if this is non-null and a message to an |
254 | interface comes in with a NULL user, call this routine with | 275 | interface comes in with a NULL user, call this routine with |
255 | it. Note that the message will still be freed by the | 276 | it. Note that the message will still be freed by the |
@@ -338,13 +359,6 @@ struct ipmi_smi | |||
338 | }; | 359 | }; |
339 | #define to_si_intf_from_dev(device) container_of(device, struct ipmi_smi, dev) | 360 | #define to_si_intf_from_dev(device) container_of(device, struct ipmi_smi, dev) |
340 | 361 | ||
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 | /** | 362 | /** |
349 | * The driver model view of the IPMI messaging driver. | 363 | * The driver model view of the IPMI messaging driver. |
350 | */ | 364 | */ |
@@ -354,16 +368,13 @@ static struct device_driver ipmidriver = { | |||
354 | }; | 368 | }; |
355 | static DEFINE_MUTEX(ipmidriver_mutex); | 369 | static DEFINE_MUTEX(ipmidriver_mutex); |
356 | 370 | ||
357 | #define MAX_IPMI_INTERFACES 4 | 371 | static struct list_head ipmi_interfaces = LIST_HEAD_INIT(ipmi_interfaces); |
358 | static ipmi_smi_t ipmi_interfaces[MAX_IPMI_INTERFACES]; | 372 | static DEFINE_MUTEX(ipmi_interfaces_mutex); |
359 | |||
360 | /* Directly protects the ipmi_interfaces data structure. */ | ||
361 | static DEFINE_SPINLOCK(interfaces_lock); | ||
362 | 373 | ||
363 | /* List of watchers that want to know when smi's are added and | 374 | /* List of watchers that want to know when smi's are added and |
364 | deleted. */ | 375 | deleted. */ |
365 | static struct list_head smi_watchers = LIST_HEAD_INIT(smi_watchers); | 376 | static struct list_head smi_watchers = LIST_HEAD_INIT(smi_watchers); |
366 | static DECLARE_RWSEM(smi_watchers_sem); | 377 | static DEFINE_MUTEX(smi_watchers_mutex); |
367 | 378 | ||
368 | 379 | ||
369 | static void free_recv_msg_list(struct list_head *q) | 380 | static void free_recv_msg_list(struct list_head *q) |
@@ -423,48 +434,84 @@ static void intf_free(struct kref *ref) | |||
423 | kfree(intf); | 434 | kfree(intf); |
424 | } | 435 | } |
425 | 436 | ||
437 | struct watcher_entry { | ||
438 | int intf_num; | ||
439 | ipmi_smi_t intf; | ||
440 | struct list_head link; | ||
441 | }; | ||
442 | |||
426 | int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher) | 443 | int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher) |
427 | { | 444 | { |
428 | int i; | 445 | ipmi_smi_t intf; |
429 | unsigned long flags; | 446 | struct list_head to_deliver = LIST_HEAD_INIT(to_deliver); |
447 | struct watcher_entry *e, *e2; | ||
448 | |||
449 | mutex_lock(&smi_watchers_mutex); | ||
450 | |||
451 | mutex_lock(&ipmi_interfaces_mutex); | ||
430 | 452 | ||
431 | down_write(&smi_watchers_sem); | 453 | /* Build a list of things to deliver. */ |
432 | list_add(&(watcher->link), &smi_watchers); | 454 | list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { |
433 | up_write(&smi_watchers_sem); | 455 | if (intf->intf_num == -1) |
434 | spin_lock_irqsave(&interfaces_lock, flags); | ||
435 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { | ||
436 | ipmi_smi_t intf = ipmi_interfaces[i]; | ||
437 | if (IPMI_INVALID_INTERFACE(intf)) | ||
438 | continue; | 456 | continue; |
439 | spin_unlock_irqrestore(&interfaces_lock, flags); | 457 | e = kmalloc(sizeof(*e), GFP_KERNEL); |
440 | watcher->new_smi(i, intf->si_dev); | 458 | if (!e) |
441 | spin_lock_irqsave(&interfaces_lock, flags); | 459 | goto out_err; |
460 | kref_get(&intf->refcount); | ||
461 | e->intf = intf; | ||
462 | e->intf_num = intf->intf_num; | ||
463 | list_add_tail(&e->link, &to_deliver); | ||
442 | } | 464 | } |
443 | spin_unlock_irqrestore(&interfaces_lock, flags); | 465 | |
466 | /* We will succeed, so add it to the list. */ | ||
467 | list_add(&watcher->link, &smi_watchers); | ||
468 | |||
469 | mutex_unlock(&ipmi_interfaces_mutex); | ||
470 | |||
471 | list_for_each_entry_safe(e, e2, &to_deliver, link) { | ||
472 | list_del(&e->link); | ||
473 | watcher->new_smi(e->intf_num, e->intf->si_dev); | ||
474 | kref_put(&e->intf->refcount, intf_free); | ||
475 | kfree(e); | ||
476 | } | ||
477 | |||
478 | mutex_unlock(&smi_watchers_mutex); | ||
479 | |||
444 | return 0; | 480 | return 0; |
481 | |||
482 | out_err: | ||
483 | mutex_unlock(&ipmi_interfaces_mutex); | ||
484 | mutex_unlock(&smi_watchers_mutex); | ||
485 | list_for_each_entry_safe(e, e2, &to_deliver, link) { | ||
486 | list_del(&e->link); | ||
487 | kref_put(&e->intf->refcount, intf_free); | ||
488 | kfree(e); | ||
489 | } | ||
490 | return -ENOMEM; | ||
445 | } | 491 | } |
446 | 492 | ||
447 | int ipmi_smi_watcher_unregister(struct ipmi_smi_watcher *watcher) | 493 | int ipmi_smi_watcher_unregister(struct ipmi_smi_watcher *watcher) |
448 | { | 494 | { |
449 | down_write(&smi_watchers_sem); | 495 | mutex_lock(&smi_watchers_mutex); |
450 | list_del(&(watcher->link)); | 496 | list_del(&(watcher->link)); |
451 | up_write(&smi_watchers_sem); | 497 | mutex_unlock(&smi_watchers_mutex); |
452 | return 0; | 498 | return 0; |
453 | } | 499 | } |
454 | 500 | ||
501 | /* | ||
502 | * Must be called with smi_watchers_mutex held. | ||
503 | */ | ||
455 | static void | 504 | static void |
456 | call_smi_watchers(int i, struct device *dev) | 505 | call_smi_watchers(int i, struct device *dev) |
457 | { | 506 | { |
458 | struct ipmi_smi_watcher *w; | 507 | struct ipmi_smi_watcher *w; |
459 | 508 | ||
460 | down_read(&smi_watchers_sem); | ||
461 | list_for_each_entry(w, &smi_watchers, link) { | 509 | list_for_each_entry(w, &smi_watchers, link) { |
462 | if (try_module_get(w->owner)) { | 510 | if (try_module_get(w->owner)) { |
463 | w->new_smi(i, dev); | 511 | w->new_smi(i, dev); |
464 | module_put(w->owner); | 512 | module_put(w->owner); |
465 | } | 513 | } |
466 | } | 514 | } |
467 | up_read(&smi_watchers_sem); | ||
468 | } | 515 | } |
469 | 516 | ||
470 | static int | 517 | static int |
@@ -590,6 +637,17 @@ static void deliver_response(struct ipmi_recv_msg *msg) | |||
590 | } | 637 | } |
591 | } | 638 | } |
592 | 639 | ||
640 | static void | ||
641 | deliver_err_response(struct ipmi_recv_msg *msg, int err) | ||
642 | { | ||
643 | msg->recv_type = IPMI_RESPONSE_RECV_TYPE; | ||
644 | msg->msg_data[0] = err; | ||
645 | msg->msg.netfn |= 1; /* Convert to a response. */ | ||
646 | msg->msg.data_len = 1; | ||
647 | msg->msg.data = msg->msg_data; | ||
648 | deliver_response(msg); | ||
649 | } | ||
650 | |||
593 | /* Find the next sequence number not being used and add the given | 651 | /* Find the next sequence number not being used and add the given |
594 | message with the given timeout to the sequence table. This must be | 652 | message with the given timeout to the sequence table. This must be |
595 | called with the interface's seq_lock held. */ | 653 | called with the interface's seq_lock held. */ |
@@ -727,14 +785,8 @@ static int intf_err_seq(ipmi_smi_t intf, | |||
727 | } | 785 | } |
728 | spin_unlock_irqrestore(&(intf->seq_lock), flags); | 786 | spin_unlock_irqrestore(&(intf->seq_lock), flags); |
729 | 787 | ||
730 | if (msg) { | 788 | if (msg) |
731 | msg->recv_type = IPMI_RESPONSE_RECV_TYPE; | 789 | deliver_err_response(msg, err); |
732 | msg->msg_data[0] = err; | ||
733 | msg->msg.netfn |= 1; /* Convert to a response. */ | ||
734 | msg->msg.data_len = 1; | ||
735 | msg->msg.data = msg->msg_data; | ||
736 | deliver_response(msg); | ||
737 | } | ||
738 | 790 | ||
739 | return rv; | 791 | return rv; |
740 | } | 792 | } |
@@ -776,17 +828,18 @@ int ipmi_create_user(unsigned int if_num, | |||
776 | if (!new_user) | 828 | if (!new_user) |
777 | return -ENOMEM; | 829 | return -ENOMEM; |
778 | 830 | ||
779 | spin_lock_irqsave(&interfaces_lock, flags); | 831 | mutex_lock(&ipmi_interfaces_mutex); |
780 | intf = ipmi_interfaces[if_num]; | 832 | list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { |
781 | if ((if_num >= MAX_IPMI_INTERFACES) || IPMI_INVALID_INTERFACE(intf)) { | 833 | if (intf->intf_num == if_num) |
782 | spin_unlock_irqrestore(&interfaces_lock, flags); | 834 | goto found; |
783 | rv = -EINVAL; | ||
784 | goto out_kfree; | ||
785 | } | 835 | } |
836 | /* Not found, return an error */ | ||
837 | rv = -EINVAL; | ||
838 | goto out_kfree; | ||
786 | 839 | ||
840 | found: | ||
787 | /* Note that each existing user holds a refcount to the interface. */ | 841 | /* Note that each existing user holds a refcount to the interface. */ |
788 | kref_get(&intf->refcount); | 842 | kref_get(&intf->refcount); |
789 | spin_unlock_irqrestore(&interfaces_lock, flags); | ||
790 | 843 | ||
791 | kref_init(&new_user->refcount); | 844 | kref_init(&new_user->refcount); |
792 | new_user->handler = handler; | 845 | new_user->handler = handler; |
@@ -807,6 +860,10 @@ int ipmi_create_user(unsigned int if_num, | |||
807 | } | 860 | } |
808 | } | 861 | } |
809 | 862 | ||
863 | /* Hold the lock so intf->handlers is guaranteed to be good | ||
864 | * until now */ | ||
865 | mutex_unlock(&ipmi_interfaces_mutex); | ||
866 | |||
810 | new_user->valid = 1; | 867 | new_user->valid = 1; |
811 | spin_lock_irqsave(&intf->seq_lock, flags); | 868 | spin_lock_irqsave(&intf->seq_lock, flags); |
812 | list_add_rcu(&new_user->link, &intf->users); | 869 | list_add_rcu(&new_user->link, &intf->users); |
@@ -817,6 +874,7 @@ int ipmi_create_user(unsigned int if_num, | |||
817 | out_kref: | 874 | out_kref: |
818 | kref_put(&intf->refcount, intf_free); | 875 | kref_put(&intf->refcount, intf_free); |
819 | out_kfree: | 876 | out_kfree: |
877 | mutex_unlock(&ipmi_interfaces_mutex); | ||
820 | kfree(new_user); | 878 | kfree(new_user); |
821 | return rv; | 879 | return rv; |
822 | } | 880 | } |
@@ -846,6 +904,7 @@ int ipmi_destroy_user(ipmi_user_t user) | |||
846 | && (intf->seq_table[i].recv_msg->user == user)) | 904 | && (intf->seq_table[i].recv_msg->user == user)) |
847 | { | 905 | { |
848 | intf->seq_table[i].inuse = 0; | 906 | intf->seq_table[i].inuse = 0; |
907 | ipmi_free_recv_msg(intf->seq_table[i].recv_msg); | ||
849 | } | 908 | } |
850 | } | 909 | } |
851 | spin_unlock_irqrestore(&intf->seq_lock, flags); | 910 | spin_unlock_irqrestore(&intf->seq_lock, flags); |
@@ -872,9 +931,13 @@ int ipmi_destroy_user(ipmi_user_t user) | |||
872 | kfree(rcvr); | 931 | kfree(rcvr); |
873 | } | 932 | } |
874 | 933 | ||
875 | module_put(intf->handlers->owner); | 934 | mutex_lock(&ipmi_interfaces_mutex); |
876 | if (intf->handlers->dec_usecount) | 935 | if (intf->handlers) { |
877 | intf->handlers->dec_usecount(intf->send_info); | 936 | module_put(intf->handlers->owner); |
937 | if (intf->handlers->dec_usecount) | ||
938 | intf->handlers->dec_usecount(intf->send_info); | ||
939 | } | ||
940 | mutex_unlock(&ipmi_interfaces_mutex); | ||
878 | 941 | ||
879 | kref_put(&intf->refcount, intf_free); | 942 | kref_put(&intf->refcount, intf_free); |
880 | 943 | ||
@@ -887,8 +950,8 @@ void ipmi_get_version(ipmi_user_t user, | |||
887 | unsigned char *major, | 950 | unsigned char *major, |
888 | unsigned char *minor) | 951 | unsigned char *minor) |
889 | { | 952 | { |
890 | *major = ipmi_version_major(&user->intf->bmc->id); | 953 | *major = user->intf->ipmi_version_major; |
891 | *minor = ipmi_version_minor(&user->intf->bmc->id); | 954 | *minor = user->intf->ipmi_version_minor; |
892 | } | 955 | } |
893 | 956 | ||
894 | int ipmi_set_my_address(ipmi_user_t user, | 957 | int ipmi_set_my_address(ipmi_user_t user, |
@@ -931,6 +994,65 @@ int ipmi_get_my_LUN(ipmi_user_t user, | |||
931 | return 0; | 994 | return 0; |
932 | } | 995 | } |
933 | 996 | ||
997 | int ipmi_get_maintenance_mode(ipmi_user_t user) | ||
998 | { | ||
999 | int mode; | ||
1000 | unsigned long flags; | ||
1001 | |||
1002 | spin_lock_irqsave(&user->intf->maintenance_mode_lock, flags); | ||
1003 | mode = user->intf->maintenance_mode; | ||
1004 | spin_unlock_irqrestore(&user->intf->maintenance_mode_lock, flags); | ||
1005 | |||
1006 | return mode; | ||
1007 | } | ||
1008 | EXPORT_SYMBOL(ipmi_get_maintenance_mode); | ||
1009 | |||
1010 | static void maintenance_mode_update(ipmi_smi_t intf) | ||
1011 | { | ||
1012 | if (intf->handlers->set_maintenance_mode) | ||
1013 | intf->handlers->set_maintenance_mode( | ||
1014 | intf->send_info, intf->maintenance_mode_enable); | ||
1015 | } | ||
1016 | |||
1017 | int ipmi_set_maintenance_mode(ipmi_user_t user, int mode) | ||
1018 | { | ||
1019 | int rv = 0; | ||
1020 | unsigned long flags; | ||
1021 | ipmi_smi_t intf = user->intf; | ||
1022 | |||
1023 | spin_lock_irqsave(&intf->maintenance_mode_lock, flags); | ||
1024 | if (intf->maintenance_mode != mode) { | ||
1025 | switch (mode) { | ||
1026 | case IPMI_MAINTENANCE_MODE_AUTO: | ||
1027 | intf->maintenance_mode = mode; | ||
1028 | intf->maintenance_mode_enable | ||
1029 | = (intf->auto_maintenance_timeout > 0); | ||
1030 | break; | ||
1031 | |||
1032 | case IPMI_MAINTENANCE_MODE_OFF: | ||
1033 | intf->maintenance_mode = mode; | ||
1034 | intf->maintenance_mode_enable = 0; | ||
1035 | break; | ||
1036 | |||
1037 | case IPMI_MAINTENANCE_MODE_ON: | ||
1038 | intf->maintenance_mode = mode; | ||
1039 | intf->maintenance_mode_enable = 1; | ||
1040 | break; | ||
1041 | |||
1042 | default: | ||
1043 | rv = -EINVAL; | ||
1044 | goto out_unlock; | ||
1045 | } | ||
1046 | |||
1047 | maintenance_mode_update(intf); | ||
1048 | } | ||
1049 | out_unlock: | ||
1050 | spin_unlock_irqrestore(&intf->maintenance_mode_lock, flags); | ||
1051 | |||
1052 | return rv; | ||
1053 | } | ||
1054 | EXPORT_SYMBOL(ipmi_set_maintenance_mode); | ||
1055 | |||
934 | int ipmi_set_gets_events(ipmi_user_t user, int val) | 1056 | int ipmi_set_gets_events(ipmi_user_t user, int val) |
935 | { | 1057 | { |
936 | unsigned long flags; | 1058 | unsigned long flags; |
@@ -943,20 +1065,33 @@ int ipmi_set_gets_events(ipmi_user_t user, int val) | |||
943 | spin_lock_irqsave(&intf->events_lock, flags); | 1065 | spin_lock_irqsave(&intf->events_lock, flags); |
944 | user->gets_events = val; | 1066 | user->gets_events = val; |
945 | 1067 | ||
946 | if (val) { | 1068 | if (intf->delivering_events) |
947 | /* Deliver any queued events. */ | 1069 | /* |
1070 | * Another thread is delivering events for this, so | ||
1071 | * let it handle any new events. | ||
1072 | */ | ||
1073 | goto out; | ||
1074 | |||
1075 | /* Deliver any queued events. */ | ||
1076 | while (user->gets_events && !list_empty(&intf->waiting_events)) { | ||
948 | list_for_each_entry_safe(msg, msg2, &intf->waiting_events, link) | 1077 | list_for_each_entry_safe(msg, msg2, &intf->waiting_events, link) |
949 | list_move_tail(&msg->link, &msgs); | 1078 | list_move_tail(&msg->link, &msgs); |
950 | intf->waiting_events_count = 0; | 1079 | intf->waiting_events_count = 0; |
951 | } | ||
952 | 1080 | ||
953 | /* Hold the events lock while doing this to preserve order. */ | 1081 | intf->delivering_events = 1; |
954 | list_for_each_entry_safe(msg, msg2, &msgs, link) { | 1082 | spin_unlock_irqrestore(&intf->events_lock, flags); |
955 | msg->user = user; | 1083 | |
956 | kref_get(&user->refcount); | 1084 | list_for_each_entry_safe(msg, msg2, &msgs, link) { |
957 | deliver_response(msg); | 1085 | msg->user = user; |
1086 | kref_get(&user->refcount); | ||
1087 | deliver_response(msg); | ||
1088 | } | ||
1089 | |||
1090 | spin_lock_irqsave(&intf->events_lock, flags); | ||
1091 | intf->delivering_events = 0; | ||
958 | } | 1092 | } |
959 | 1093 | ||
1094 | out: | ||
960 | spin_unlock_irqrestore(&intf->events_lock, flags); | 1095 | spin_unlock_irqrestore(&intf->events_lock, flags); |
961 | 1096 | ||
962 | return 0; | 1097 | return 0; |
@@ -1067,7 +1202,8 @@ int ipmi_unregister_for_cmd(ipmi_user_t user, | |||
1067 | void ipmi_user_set_run_to_completion(ipmi_user_t user, int val) | 1202 | void ipmi_user_set_run_to_completion(ipmi_user_t user, int val) |
1068 | { | 1203 | { |
1069 | ipmi_smi_t intf = user->intf; | 1204 | ipmi_smi_t intf = user->intf; |
1070 | intf->handlers->set_run_to_completion(intf->send_info, val); | 1205 | if (intf->handlers) |
1206 | intf->handlers->set_run_to_completion(intf->send_info, val); | ||
1071 | } | 1207 | } |
1072 | 1208 | ||
1073 | static unsigned char | 1209 | static unsigned char |
@@ -1178,10 +1314,11 @@ static int i_ipmi_request(ipmi_user_t user, | |||
1178 | int retries, | 1314 | int retries, |
1179 | unsigned int retry_time_ms) | 1315 | unsigned int retry_time_ms) |
1180 | { | 1316 | { |
1181 | int rv = 0; | 1317 | int rv = 0; |
1182 | struct ipmi_smi_msg *smi_msg; | 1318 | struct ipmi_smi_msg *smi_msg; |
1183 | struct ipmi_recv_msg *recv_msg; | 1319 | struct ipmi_recv_msg *recv_msg; |
1184 | unsigned long flags; | 1320 | unsigned long flags; |
1321 | struct ipmi_smi_handlers *handlers; | ||
1185 | 1322 | ||
1186 | 1323 | ||
1187 | if (supplied_recv) { | 1324 | if (supplied_recv) { |
@@ -1204,6 +1341,13 @@ static int i_ipmi_request(ipmi_user_t user, | |||
1204 | } | 1341 | } |
1205 | } | 1342 | } |
1206 | 1343 | ||
1344 | rcu_read_lock(); | ||
1345 | handlers = intf->handlers; | ||
1346 | if (!handlers) { | ||
1347 | rv = -ENODEV; | ||
1348 | goto out_err; | ||
1349 | } | ||
1350 | |||
1207 | recv_msg->user = user; | 1351 | recv_msg->user = user; |
1208 | if (user) | 1352 | if (user) |
1209 | kref_get(&user->refcount); | 1353 | kref_get(&user->refcount); |
@@ -1246,6 +1390,24 @@ static int i_ipmi_request(ipmi_user_t user, | |||
1246 | goto out_err; | 1390 | goto out_err; |
1247 | } | 1391 | } |
1248 | 1392 | ||
1393 | if (((msg->netfn == IPMI_NETFN_APP_REQUEST) | ||
1394 | && ((msg->cmd == IPMI_COLD_RESET_CMD) | ||
1395 | || (msg->cmd == IPMI_WARM_RESET_CMD))) | ||
1396 | || (msg->netfn == IPMI_NETFN_FIRMWARE_REQUEST)) | ||
1397 | { | ||
1398 | spin_lock_irqsave(&intf->maintenance_mode_lock, flags); | ||
1399 | intf->auto_maintenance_timeout | ||
1400 | = IPMI_MAINTENANCE_MODE_TIMEOUT; | ||
1401 | if (!intf->maintenance_mode | ||
1402 | && !intf->maintenance_mode_enable) | ||
1403 | { | ||
1404 | intf->maintenance_mode_enable = 1; | ||
1405 | maintenance_mode_update(intf); | ||
1406 | } | ||
1407 | spin_unlock_irqrestore(&intf->maintenance_mode_lock, | ||
1408 | flags); | ||
1409 | } | ||
1410 | |||
1249 | if ((msg->data_len + 2) > IPMI_MAX_MSG_LENGTH) { | 1411 | if ((msg->data_len + 2) > IPMI_MAX_MSG_LENGTH) { |
1250 | spin_lock_irqsave(&intf->counter_lock, flags); | 1412 | spin_lock_irqsave(&intf->counter_lock, flags); |
1251 | intf->sent_invalid_commands++; | 1413 | intf->sent_invalid_commands++; |
@@ -1520,11 +1682,14 @@ static int i_ipmi_request(ipmi_user_t user, | |||
1520 | printk("\n"); | 1682 | printk("\n"); |
1521 | } | 1683 | } |
1522 | #endif | 1684 | #endif |
1523 | intf->handlers->sender(intf->send_info, smi_msg, priority); | 1685 | |
1686 | handlers->sender(intf->send_info, smi_msg, priority); | ||
1687 | rcu_read_unlock(); | ||
1524 | 1688 | ||
1525 | return 0; | 1689 | return 0; |
1526 | 1690 | ||
1527 | out_err: | 1691 | out_err: |
1692 | rcu_read_unlock(); | ||
1528 | ipmi_free_smi_msg(smi_msg); | 1693 | ipmi_free_smi_msg(smi_msg); |
1529 | ipmi_free_recv_msg(recv_msg); | 1694 | ipmi_free_recv_msg(recv_msg); |
1530 | return rv; | 1695 | return rv; |
@@ -1604,6 +1769,7 @@ int ipmi_request_supply_msgs(ipmi_user_t user, | |||
1604 | -1, 0); | 1769 | -1, 0); |
1605 | } | 1770 | } |
1606 | 1771 | ||
1772 | #ifdef CONFIG_PROC_FS | ||
1607 | static int ipmb_file_read_proc(char *page, char **start, off_t off, | 1773 | static int ipmb_file_read_proc(char *page, char **start, off_t off, |
1608 | int count, int *eof, void *data) | 1774 | int count, int *eof, void *data) |
1609 | { | 1775 | { |
@@ -1692,6 +1858,7 @@ static int stat_file_read_proc(char *page, char **start, off_t off, | |||
1692 | 1858 | ||
1693 | return (out - ((char *) page)); | 1859 | return (out - ((char *) page)); |
1694 | } | 1860 | } |
1861 | #endif /* CONFIG_PROC_FS */ | ||
1695 | 1862 | ||
1696 | int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name, | 1863 | int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name, |
1697 | read_proc_t *read_proc, write_proc_t *write_proc, | 1864 | read_proc_t *read_proc, write_proc_t *write_proc, |
@@ -1817,13 +1984,12 @@ static int __find_bmc_prod_dev_id(struct device *dev, void *data) | |||
1817 | struct bmc_device *bmc = dev_get_drvdata(dev); | 1984 | struct bmc_device *bmc = dev_get_drvdata(dev); |
1818 | 1985 | ||
1819 | return (bmc->id.product_id == id->product_id | 1986 | return (bmc->id.product_id == id->product_id |
1820 | && bmc->id.product_id == id->product_id | ||
1821 | && bmc->id.device_id == id->device_id); | 1987 | && bmc->id.device_id == id->device_id); |
1822 | } | 1988 | } |
1823 | 1989 | ||
1824 | static struct bmc_device *ipmi_find_bmc_prod_dev_id( | 1990 | static struct bmc_device *ipmi_find_bmc_prod_dev_id( |
1825 | struct device_driver *drv, | 1991 | struct device_driver *drv, |
1826 | unsigned char product_id, unsigned char device_id) | 1992 | unsigned int product_id, unsigned char device_id) |
1827 | { | 1993 | { |
1828 | struct prod_dev_id id = { | 1994 | struct prod_dev_id id = { |
1829 | .product_id = product_id, | 1995 | .product_id = product_id, |
@@ -1940,6 +2106,9 @@ static ssize_t guid_show(struct device *dev, struct device_attribute *attr, | |||
1940 | 2106 | ||
1941 | static void remove_files(struct bmc_device *bmc) | 2107 | static void remove_files(struct bmc_device *bmc) |
1942 | { | 2108 | { |
2109 | if (!bmc->dev) | ||
2110 | return; | ||
2111 | |||
1943 | device_remove_file(&bmc->dev->dev, | 2112 | device_remove_file(&bmc->dev->dev, |
1944 | &bmc->device_id_attr); | 2113 | &bmc->device_id_attr); |
1945 | device_remove_file(&bmc->dev->dev, | 2114 | device_remove_file(&bmc->dev->dev, |
@@ -1973,7 +2142,8 @@ cleanup_bmc_device(struct kref *ref) | |||
1973 | bmc = container_of(ref, struct bmc_device, refcount); | 2142 | bmc = container_of(ref, struct bmc_device, refcount); |
1974 | 2143 | ||
1975 | remove_files(bmc); | 2144 | remove_files(bmc); |
1976 | platform_device_unregister(bmc->dev); | 2145 | if (bmc->dev) |
2146 | platform_device_unregister(bmc->dev); | ||
1977 | kfree(bmc); | 2147 | kfree(bmc); |
1978 | } | 2148 | } |
1979 | 2149 | ||
@@ -1981,7 +2151,11 @@ static void ipmi_bmc_unregister(ipmi_smi_t intf) | |||
1981 | { | 2151 | { |
1982 | struct bmc_device *bmc = intf->bmc; | 2152 | struct bmc_device *bmc = intf->bmc; |
1983 | 2153 | ||
1984 | sysfs_remove_link(&intf->si_dev->kobj, "bmc"); | 2154 | if (intf->sysfs_name) { |
2155 | sysfs_remove_link(&intf->si_dev->kobj, intf->sysfs_name); | ||
2156 | kfree(intf->sysfs_name); | ||
2157 | intf->sysfs_name = NULL; | ||
2158 | } | ||
1985 | if (intf->my_dev_name) { | 2159 | if (intf->my_dev_name) { |
1986 | sysfs_remove_link(&bmc->dev->dev.kobj, intf->my_dev_name); | 2160 | sysfs_remove_link(&bmc->dev->dev.kobj, intf->my_dev_name); |
1987 | kfree(intf->my_dev_name); | 2161 | kfree(intf->my_dev_name); |
@@ -1990,6 +2164,7 @@ static void ipmi_bmc_unregister(ipmi_smi_t intf) | |||
1990 | 2164 | ||
1991 | mutex_lock(&ipmidriver_mutex); | 2165 | mutex_lock(&ipmidriver_mutex); |
1992 | kref_put(&bmc->refcount, cleanup_bmc_device); | 2166 | kref_put(&bmc->refcount, cleanup_bmc_device); |
2167 | intf->bmc = NULL; | ||
1993 | mutex_unlock(&ipmidriver_mutex); | 2168 | mutex_unlock(&ipmidriver_mutex); |
1994 | } | 2169 | } |
1995 | 2170 | ||
@@ -1997,6 +2172,56 @@ static int create_files(struct bmc_device *bmc) | |||
1997 | { | 2172 | { |
1998 | int err; | 2173 | int err; |
1999 | 2174 | ||
2175 | bmc->device_id_attr.attr.name = "device_id"; | ||
2176 | bmc->device_id_attr.attr.owner = THIS_MODULE; | ||
2177 | bmc->device_id_attr.attr.mode = S_IRUGO; | ||
2178 | bmc->device_id_attr.show = device_id_show; | ||
2179 | |||
2180 | bmc->provides_dev_sdrs_attr.attr.name = "provides_device_sdrs"; | ||
2181 | bmc->provides_dev_sdrs_attr.attr.owner = THIS_MODULE; | ||
2182 | bmc->provides_dev_sdrs_attr.attr.mode = S_IRUGO; | ||
2183 | bmc->provides_dev_sdrs_attr.show = provides_dev_sdrs_show; | ||
2184 | |||
2185 | bmc->revision_attr.attr.name = "revision"; | ||
2186 | bmc->revision_attr.attr.owner = THIS_MODULE; | ||
2187 | bmc->revision_attr.attr.mode = S_IRUGO; | ||
2188 | bmc->revision_attr.show = revision_show; | ||
2189 | |||
2190 | bmc->firmware_rev_attr.attr.name = "firmware_revision"; | ||
2191 | bmc->firmware_rev_attr.attr.owner = THIS_MODULE; | ||
2192 | bmc->firmware_rev_attr.attr.mode = S_IRUGO; | ||
2193 | bmc->firmware_rev_attr.show = firmware_rev_show; | ||
2194 | |||
2195 | bmc->version_attr.attr.name = "ipmi_version"; | ||
2196 | bmc->version_attr.attr.owner = THIS_MODULE; | ||
2197 | bmc->version_attr.attr.mode = S_IRUGO; | ||
2198 | bmc->version_attr.show = ipmi_version_show; | ||
2199 | |||
2200 | bmc->add_dev_support_attr.attr.name = "additional_device_support"; | ||
2201 | bmc->add_dev_support_attr.attr.owner = THIS_MODULE; | ||
2202 | bmc->add_dev_support_attr.attr.mode = S_IRUGO; | ||
2203 | bmc->add_dev_support_attr.show = add_dev_support_show; | ||
2204 | |||
2205 | bmc->manufacturer_id_attr.attr.name = "manufacturer_id"; | ||
2206 | bmc->manufacturer_id_attr.attr.owner = THIS_MODULE; | ||
2207 | bmc->manufacturer_id_attr.attr.mode = S_IRUGO; | ||
2208 | bmc->manufacturer_id_attr.show = manufacturer_id_show; | ||
2209 | |||
2210 | bmc->product_id_attr.attr.name = "product_id"; | ||
2211 | bmc->product_id_attr.attr.owner = THIS_MODULE; | ||
2212 | bmc->product_id_attr.attr.mode = S_IRUGO; | ||
2213 | bmc->product_id_attr.show = product_id_show; | ||
2214 | |||
2215 | bmc->guid_attr.attr.name = "guid"; | ||
2216 | bmc->guid_attr.attr.owner = THIS_MODULE; | ||
2217 | bmc->guid_attr.attr.mode = S_IRUGO; | ||
2218 | bmc->guid_attr.show = guid_show; | ||
2219 | |||
2220 | bmc->aux_firmware_rev_attr.attr.name = "aux_firmware_revision"; | ||
2221 | bmc->aux_firmware_rev_attr.attr.owner = THIS_MODULE; | ||
2222 | bmc->aux_firmware_rev_attr.attr.mode = S_IRUGO; | ||
2223 | bmc->aux_firmware_rev_attr.show = aux_firmware_rev_show; | ||
2224 | |||
2000 | err = device_create_file(&bmc->dev->dev, | 2225 | err = device_create_file(&bmc->dev->dev, |
2001 | &bmc->device_id_attr); | 2226 | &bmc->device_id_attr); |
2002 | if (err) goto out; | 2227 | if (err) goto out; |
@@ -2066,7 +2291,8 @@ out: | |||
2066 | return err; | 2291 | return err; |
2067 | } | 2292 | } |
2068 | 2293 | ||
2069 | static int ipmi_bmc_register(ipmi_smi_t intf) | 2294 | static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum, |
2295 | const char *sysfs_name) | ||
2070 | { | 2296 | { |
2071 | int rv; | 2297 | int rv; |
2072 | struct bmc_device *bmc = intf->bmc; | 2298 | struct bmc_device *bmc = intf->bmc; |
@@ -2106,9 +2332,39 @@ static int ipmi_bmc_register(ipmi_smi_t intf) | |||
2106 | bmc->id.product_id, | 2332 | bmc->id.product_id, |
2107 | bmc->id.device_id); | 2333 | bmc->id.device_id); |
2108 | } else { | 2334 | } else { |
2109 | bmc->dev = platform_device_alloc("ipmi_bmc", | 2335 | char name[14]; |
2110 | bmc->id.device_id); | 2336 | unsigned char orig_dev_id = bmc->id.device_id; |
2337 | int warn_printed = 0; | ||
2338 | |||
2339 | snprintf(name, sizeof(name), | ||
2340 | "ipmi_bmc.%4.4x", bmc->id.product_id); | ||
2341 | |||
2342 | while (ipmi_find_bmc_prod_dev_id(&ipmidriver, | ||
2343 | bmc->id.product_id, | ||
2344 | bmc->id.device_id)) | ||
2345 | { | ||
2346 | if (!warn_printed) { | ||
2347 | printk(KERN_WARNING PFX | ||
2348 | "This machine has two different BMCs" | ||
2349 | " with the same product id and device" | ||
2350 | " id. This is an error in the" | ||
2351 | " firmware, but incrementing the" | ||
2352 | " device id to work around the problem." | ||
2353 | " Prod ID = 0x%x, Dev ID = 0x%x\n", | ||
2354 | bmc->id.product_id, bmc->id.device_id); | ||
2355 | warn_printed = 1; | ||
2356 | } | ||
2357 | bmc->id.device_id++; /* Wraps at 255 */ | ||
2358 | if (bmc->id.device_id == orig_dev_id) { | ||
2359 | printk(KERN_ERR PFX | ||
2360 | "Out of device ids!\n"); | ||
2361 | break; | ||
2362 | } | ||
2363 | } | ||
2364 | |||
2365 | bmc->dev = platform_device_alloc(name, bmc->id.device_id); | ||
2111 | if (!bmc->dev) { | 2366 | if (!bmc->dev) { |
2367 | mutex_unlock(&ipmidriver_mutex); | ||
2112 | printk(KERN_ERR | 2368 | printk(KERN_ERR |
2113 | "ipmi_msghandler:" | 2369 | "ipmi_msghandler:" |
2114 | " Unable to allocate platform device\n"); | 2370 | " Unable to allocate platform device\n"); |
@@ -2121,6 +2377,8 @@ static int ipmi_bmc_register(ipmi_smi_t intf) | |||
2121 | rv = platform_device_add(bmc->dev); | 2377 | rv = platform_device_add(bmc->dev); |
2122 | mutex_unlock(&ipmidriver_mutex); | 2378 | mutex_unlock(&ipmidriver_mutex); |
2123 | if (rv) { | 2379 | if (rv) { |
2380 | platform_device_put(bmc->dev); | ||
2381 | bmc->dev = NULL; | ||
2124 | printk(KERN_ERR | 2382 | printk(KERN_ERR |
2125 | "ipmi_msghandler:" | 2383 | "ipmi_msghandler:" |
2126 | " Unable to register bmc device: %d\n", | 2384 | " Unable to register bmc device: %d\n", |
@@ -2130,57 +2388,6 @@ static int ipmi_bmc_register(ipmi_smi_t intf) | |||
2130 | return rv; | 2388 | return rv; |
2131 | } | 2389 | } |
2132 | 2390 | ||
2133 | bmc->device_id_attr.attr.name = "device_id"; | ||
2134 | bmc->device_id_attr.attr.owner = THIS_MODULE; | ||
2135 | bmc->device_id_attr.attr.mode = S_IRUGO; | ||
2136 | bmc->device_id_attr.show = device_id_show; | ||
2137 | |||
2138 | bmc->provides_dev_sdrs_attr.attr.name = "provides_device_sdrs"; | ||
2139 | bmc->provides_dev_sdrs_attr.attr.owner = THIS_MODULE; | ||
2140 | bmc->provides_dev_sdrs_attr.attr.mode = S_IRUGO; | ||
2141 | bmc->provides_dev_sdrs_attr.show = provides_dev_sdrs_show; | ||
2142 | |||
2143 | bmc->revision_attr.attr.name = "revision"; | ||
2144 | bmc->revision_attr.attr.owner = THIS_MODULE; | ||
2145 | bmc->revision_attr.attr.mode = S_IRUGO; | ||
2146 | bmc->revision_attr.show = revision_show; | ||
2147 | |||
2148 | bmc->firmware_rev_attr.attr.name = "firmware_revision"; | ||
2149 | bmc->firmware_rev_attr.attr.owner = THIS_MODULE; | ||
2150 | bmc->firmware_rev_attr.attr.mode = S_IRUGO; | ||
2151 | bmc->firmware_rev_attr.show = firmware_rev_show; | ||
2152 | |||
2153 | bmc->version_attr.attr.name = "ipmi_version"; | ||
2154 | bmc->version_attr.attr.owner = THIS_MODULE; | ||
2155 | bmc->version_attr.attr.mode = S_IRUGO; | ||
2156 | bmc->version_attr.show = ipmi_version_show; | ||
2157 | |||
2158 | bmc->add_dev_support_attr.attr.name | ||
2159 | = "additional_device_support"; | ||
2160 | bmc->add_dev_support_attr.attr.owner = THIS_MODULE; | ||
2161 | bmc->add_dev_support_attr.attr.mode = S_IRUGO; | ||
2162 | bmc->add_dev_support_attr.show = add_dev_support_show; | ||
2163 | |||
2164 | bmc->manufacturer_id_attr.attr.name = "manufacturer_id"; | ||
2165 | bmc->manufacturer_id_attr.attr.owner = THIS_MODULE; | ||
2166 | bmc->manufacturer_id_attr.attr.mode = S_IRUGO; | ||
2167 | bmc->manufacturer_id_attr.show = manufacturer_id_show; | ||
2168 | |||
2169 | bmc->product_id_attr.attr.name = "product_id"; | ||
2170 | bmc->product_id_attr.attr.owner = THIS_MODULE; | ||
2171 | bmc->product_id_attr.attr.mode = S_IRUGO; | ||
2172 | bmc->product_id_attr.show = product_id_show; | ||
2173 | |||
2174 | bmc->guid_attr.attr.name = "guid"; | ||
2175 | bmc->guid_attr.attr.owner = THIS_MODULE; | ||
2176 | bmc->guid_attr.attr.mode = S_IRUGO; | ||
2177 | bmc->guid_attr.show = guid_show; | ||
2178 | |||
2179 | bmc->aux_firmware_rev_attr.attr.name = "aux_firmware_revision"; | ||
2180 | bmc->aux_firmware_rev_attr.attr.owner = THIS_MODULE; | ||
2181 | bmc->aux_firmware_rev_attr.attr.mode = S_IRUGO; | ||
2182 | bmc->aux_firmware_rev_attr.show = aux_firmware_rev_show; | ||
2183 | |||
2184 | rv = create_files(bmc); | 2391 | rv = create_files(bmc); |
2185 | if (rv) { | 2392 | if (rv) { |
2186 | mutex_lock(&ipmidriver_mutex); | 2393 | mutex_lock(&ipmidriver_mutex); |
@@ -2202,29 +2409,44 @@ static int ipmi_bmc_register(ipmi_smi_t intf) | |||
2202 | * create symlink from system interface device to bmc device | 2409 | * create symlink from system interface device to bmc device |
2203 | * and back. | 2410 | * and back. |
2204 | */ | 2411 | */ |
2412 | intf->sysfs_name = kstrdup(sysfs_name, GFP_KERNEL); | ||
2413 | if (!intf->sysfs_name) { | ||
2414 | rv = -ENOMEM; | ||
2415 | printk(KERN_ERR | ||
2416 | "ipmi_msghandler: allocate link to BMC: %d\n", | ||
2417 | rv); | ||
2418 | goto out_err; | ||
2419 | } | ||
2420 | |||
2205 | rv = sysfs_create_link(&intf->si_dev->kobj, | 2421 | rv = sysfs_create_link(&intf->si_dev->kobj, |
2206 | &bmc->dev->dev.kobj, "bmc"); | 2422 | &bmc->dev->dev.kobj, intf->sysfs_name); |
2207 | if (rv) { | 2423 | if (rv) { |
2424 | kfree(intf->sysfs_name); | ||
2425 | intf->sysfs_name = NULL; | ||
2208 | printk(KERN_ERR | 2426 | printk(KERN_ERR |
2209 | "ipmi_msghandler: Unable to create bmc symlink: %d\n", | 2427 | "ipmi_msghandler: Unable to create bmc symlink: %d\n", |
2210 | rv); | 2428 | rv); |
2211 | goto out_err; | 2429 | goto out_err; |
2212 | } | 2430 | } |
2213 | 2431 | ||
2214 | size = snprintf(dummy, 0, "ipmi%d", intf->intf_num); | 2432 | size = snprintf(dummy, 0, "ipmi%d", ifnum); |
2215 | intf->my_dev_name = kmalloc(size+1, GFP_KERNEL); | 2433 | intf->my_dev_name = kmalloc(size+1, GFP_KERNEL); |
2216 | if (!intf->my_dev_name) { | 2434 | if (!intf->my_dev_name) { |
2435 | kfree(intf->sysfs_name); | ||
2436 | intf->sysfs_name = NULL; | ||
2217 | rv = -ENOMEM; | 2437 | rv = -ENOMEM; |
2218 | printk(KERN_ERR | 2438 | printk(KERN_ERR |
2219 | "ipmi_msghandler: allocate link from BMC: %d\n", | 2439 | "ipmi_msghandler: allocate link from BMC: %d\n", |
2220 | rv); | 2440 | rv); |
2221 | goto out_err; | 2441 | goto out_err; |
2222 | } | 2442 | } |
2223 | snprintf(intf->my_dev_name, size+1, "ipmi%d", intf->intf_num); | 2443 | snprintf(intf->my_dev_name, size+1, "ipmi%d", ifnum); |
2224 | 2444 | ||
2225 | rv = sysfs_create_link(&bmc->dev->dev.kobj, &intf->si_dev->kobj, | 2445 | rv = sysfs_create_link(&bmc->dev->dev.kobj, &intf->si_dev->kobj, |
2226 | intf->my_dev_name); | 2446 | intf->my_dev_name); |
2227 | if (rv) { | 2447 | if (rv) { |
2448 | kfree(intf->sysfs_name); | ||
2449 | intf->sysfs_name = NULL; | ||
2228 | kfree(intf->my_dev_name); | 2450 | kfree(intf->my_dev_name); |
2229 | intf->my_dev_name = NULL; | 2451 | intf->my_dev_name = NULL; |
2230 | printk(KERN_ERR | 2452 | printk(KERN_ERR |
@@ -2409,17 +2631,14 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
2409 | void *send_info, | 2631 | void *send_info, |
2410 | struct ipmi_device_id *device_id, | 2632 | struct ipmi_device_id *device_id, |
2411 | struct device *si_dev, | 2633 | struct device *si_dev, |
2634 | const char *sysfs_name, | ||
2412 | unsigned char slave_addr) | 2635 | unsigned char slave_addr) |
2413 | { | 2636 | { |
2414 | int i, j; | 2637 | int i, j; |
2415 | int rv; | 2638 | int rv; |
2416 | ipmi_smi_t intf; | 2639 | ipmi_smi_t intf; |
2417 | unsigned long flags; | 2640 | ipmi_smi_t tintf; |
2418 | int version_major; | 2641 | struct list_head *link; |
2419 | int version_minor; | ||
2420 | |||
2421 | version_major = ipmi_version_major(device_id); | ||
2422 | version_minor = ipmi_version_minor(device_id); | ||
2423 | 2642 | ||
2424 | /* Make sure the driver is actually initialized, this handles | 2643 | /* Make sure the driver is actually initialized, this handles |
2425 | problems with initialization order. */ | 2644 | problems with initialization order. */ |
@@ -2437,12 +2656,16 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
2437 | if (!intf) | 2656 | if (!intf) |
2438 | return -ENOMEM; | 2657 | return -ENOMEM; |
2439 | memset(intf, 0, sizeof(*intf)); | 2658 | memset(intf, 0, sizeof(*intf)); |
2659 | |||
2660 | intf->ipmi_version_major = ipmi_version_major(device_id); | ||
2661 | intf->ipmi_version_minor = ipmi_version_minor(device_id); | ||
2662 | |||
2440 | intf->bmc = kzalloc(sizeof(*intf->bmc), GFP_KERNEL); | 2663 | intf->bmc = kzalloc(sizeof(*intf->bmc), GFP_KERNEL); |
2441 | if (!intf->bmc) { | 2664 | if (!intf->bmc) { |
2442 | kfree(intf); | 2665 | kfree(intf); |
2443 | return -ENOMEM; | 2666 | return -ENOMEM; |
2444 | } | 2667 | } |
2445 | intf->intf_num = -1; | 2668 | intf->intf_num = -1; /* Mark it invalid for now. */ |
2446 | kref_init(&intf->refcount); | 2669 | kref_init(&intf->refcount); |
2447 | intf->bmc->id = *device_id; | 2670 | intf->bmc->id = *device_id; |
2448 | intf->si_dev = si_dev; | 2671 | intf->si_dev = si_dev; |
@@ -2470,26 +2693,30 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
2470 | INIT_LIST_HEAD(&intf->waiting_events); | 2693 | INIT_LIST_HEAD(&intf->waiting_events); |
2471 | intf->waiting_events_count = 0; | 2694 | intf->waiting_events_count = 0; |
2472 | mutex_init(&intf->cmd_rcvrs_mutex); | 2695 | mutex_init(&intf->cmd_rcvrs_mutex); |
2696 | spin_lock_init(&intf->maintenance_mode_lock); | ||
2473 | INIT_LIST_HEAD(&intf->cmd_rcvrs); | 2697 | INIT_LIST_HEAD(&intf->cmd_rcvrs); |
2474 | init_waitqueue_head(&intf->waitq); | 2698 | init_waitqueue_head(&intf->waitq); |
2475 | 2699 | ||
2476 | spin_lock_init(&intf->counter_lock); | 2700 | spin_lock_init(&intf->counter_lock); |
2477 | intf->proc_dir = NULL; | 2701 | intf->proc_dir = NULL; |
2478 | 2702 | ||
2479 | rv = -ENOMEM; | 2703 | mutex_lock(&smi_watchers_mutex); |
2480 | spin_lock_irqsave(&interfaces_lock, flags); | 2704 | mutex_lock(&ipmi_interfaces_mutex); |
2481 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { | 2705 | /* Look for a hole in the numbers. */ |
2482 | if (ipmi_interfaces[i] == NULL) { | 2706 | i = 0; |
2483 | intf->intf_num = i; | 2707 | link = &ipmi_interfaces; |
2484 | /* Reserve the entry till we are done. */ | 2708 | list_for_each_entry_rcu(tintf, &ipmi_interfaces, link) { |
2485 | ipmi_interfaces[i] = IPMI_INVALID_INTERFACE_ENTRY; | 2709 | if (tintf->intf_num != i) { |
2486 | rv = 0; | 2710 | link = &tintf->link; |
2487 | break; | 2711 | break; |
2488 | } | 2712 | } |
2713 | i++; | ||
2489 | } | 2714 | } |
2490 | spin_unlock_irqrestore(&interfaces_lock, flags); | 2715 | /* Add the new interface in numeric order. */ |
2491 | if (rv) | 2716 | if (i == 0) |
2492 | goto out; | 2717 | list_add_rcu(&intf->link, &ipmi_interfaces); |
2718 | else | ||
2719 | list_add_tail_rcu(&intf->link, link); | ||
2493 | 2720 | ||
2494 | rv = handlers->start_processing(send_info, intf); | 2721 | rv = handlers->start_processing(send_info, intf); |
2495 | if (rv) | 2722 | if (rv) |
@@ -2497,8 +2724,9 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
2497 | 2724 | ||
2498 | get_guid(intf); | 2725 | get_guid(intf); |
2499 | 2726 | ||
2500 | if ((version_major > 1) | 2727 | if ((intf->ipmi_version_major > 1) |
2501 | || ((version_major == 1) && (version_minor >= 5))) | 2728 | || ((intf->ipmi_version_major == 1) |
2729 | && (intf->ipmi_version_minor >= 5))) | ||
2502 | { | 2730 | { |
2503 | /* Start scanning the channels to see what is | 2731 | /* Start scanning the channels to see what is |
2504 | available. */ | 2732 | available. */ |
@@ -2521,64 +2749,67 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
2521 | if (rv == 0) | 2749 | if (rv == 0) |
2522 | rv = add_proc_entries(intf, i); | 2750 | rv = add_proc_entries(intf, i); |
2523 | 2751 | ||
2524 | rv = ipmi_bmc_register(intf); | 2752 | rv = ipmi_bmc_register(intf, i, sysfs_name); |
2525 | 2753 | ||
2526 | out: | 2754 | out: |
2527 | if (rv) { | 2755 | if (rv) { |
2528 | if (intf->proc_dir) | 2756 | if (intf->proc_dir) |
2529 | remove_proc_entries(intf); | 2757 | remove_proc_entries(intf); |
2758 | intf->handlers = NULL; | ||
2759 | list_del_rcu(&intf->link); | ||
2760 | mutex_unlock(&ipmi_interfaces_mutex); | ||
2761 | mutex_unlock(&smi_watchers_mutex); | ||
2762 | synchronize_rcu(); | ||
2530 | kref_put(&intf->refcount, intf_free); | 2763 | kref_put(&intf->refcount, intf_free); |
2531 | if (i < MAX_IPMI_INTERFACES) { | ||
2532 | spin_lock_irqsave(&interfaces_lock, flags); | ||
2533 | ipmi_interfaces[i] = NULL; | ||
2534 | spin_unlock_irqrestore(&interfaces_lock, flags); | ||
2535 | } | ||
2536 | } else { | 2764 | } else { |
2537 | spin_lock_irqsave(&interfaces_lock, flags); | 2765 | /* After this point the interface is legal to use. */ |
2538 | ipmi_interfaces[i] = intf; | 2766 | intf->intf_num = i; |
2539 | spin_unlock_irqrestore(&interfaces_lock, flags); | 2767 | mutex_unlock(&ipmi_interfaces_mutex); |
2540 | call_smi_watchers(i, intf->si_dev); | 2768 | call_smi_watchers(i, intf->si_dev); |
2769 | mutex_unlock(&smi_watchers_mutex); | ||
2541 | } | 2770 | } |
2542 | 2771 | ||
2543 | return rv; | 2772 | return rv; |
2544 | } | 2773 | } |
2545 | 2774 | ||
2775 | static void cleanup_smi_msgs(ipmi_smi_t intf) | ||
2776 | { | ||
2777 | int i; | ||
2778 | struct seq_table *ent; | ||
2779 | |||
2780 | /* No need for locks, the interface is down. */ | ||
2781 | for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) { | ||
2782 | ent = &(intf->seq_table[i]); | ||
2783 | if (!ent->inuse) | ||
2784 | continue; | ||
2785 | deliver_err_response(ent->recv_msg, IPMI_ERR_UNSPECIFIED); | ||
2786 | } | ||
2787 | } | ||
2788 | |||
2546 | int ipmi_unregister_smi(ipmi_smi_t intf) | 2789 | int ipmi_unregister_smi(ipmi_smi_t intf) |
2547 | { | 2790 | { |
2548 | int i; | ||
2549 | struct ipmi_smi_watcher *w; | 2791 | struct ipmi_smi_watcher *w; |
2550 | unsigned long flags; | 2792 | int intf_num = intf->intf_num; |
2551 | 2793 | ||
2552 | ipmi_bmc_unregister(intf); | 2794 | ipmi_bmc_unregister(intf); |
2553 | 2795 | ||
2554 | spin_lock_irqsave(&interfaces_lock, flags); | 2796 | mutex_lock(&smi_watchers_mutex); |
2555 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { | 2797 | mutex_lock(&ipmi_interfaces_mutex); |
2556 | if (ipmi_interfaces[i] == intf) { | 2798 | intf->intf_num = -1; |
2557 | /* Set the interface number reserved until we | 2799 | intf->handlers = NULL; |
2558 | * are done. */ | 2800 | list_del_rcu(&intf->link); |
2559 | ipmi_interfaces[i] = IPMI_INVALID_INTERFACE_ENTRY; | 2801 | mutex_unlock(&ipmi_interfaces_mutex); |
2560 | intf->intf_num = -1; | 2802 | synchronize_rcu(); |
2561 | break; | ||
2562 | } | ||
2563 | } | ||
2564 | spin_unlock_irqrestore(&interfaces_lock,flags); | ||
2565 | 2803 | ||
2566 | if (i == MAX_IPMI_INTERFACES) | 2804 | cleanup_smi_msgs(intf); |
2567 | return -ENODEV; | ||
2568 | 2805 | ||
2569 | remove_proc_entries(intf); | 2806 | remove_proc_entries(intf); |
2570 | 2807 | ||
2571 | /* Call all the watcher interfaces to tell them that | 2808 | /* Call all the watcher interfaces to tell them that |
2572 | an interface is gone. */ | 2809 | an interface is gone. */ |
2573 | down_read(&smi_watchers_sem); | ||
2574 | list_for_each_entry(w, &smi_watchers, link) | 2810 | list_for_each_entry(w, &smi_watchers, link) |
2575 | w->smi_gone(i); | 2811 | w->smi_gone(intf_num); |
2576 | up_read(&smi_watchers_sem); | 2812 | mutex_unlock(&smi_watchers_mutex); |
2577 | |||
2578 | /* Allow the entry to be reused now. */ | ||
2579 | spin_lock_irqsave(&interfaces_lock, flags); | ||
2580 | ipmi_interfaces[i] = NULL; | ||
2581 | spin_unlock_irqrestore(&interfaces_lock,flags); | ||
2582 | 2813 | ||
2583 | kref_put(&intf->refcount, intf_free); | 2814 | kref_put(&intf->refcount, intf_free); |
2584 | return 0; | 2815 | return 0; |
@@ -2660,6 +2891,7 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, | |||
2660 | struct ipmi_ipmb_addr *ipmb_addr; | 2891 | struct ipmi_ipmb_addr *ipmb_addr; |
2661 | struct ipmi_recv_msg *recv_msg; | 2892 | struct ipmi_recv_msg *recv_msg; |
2662 | unsigned long flags; | 2893 | unsigned long flags; |
2894 | struct ipmi_smi_handlers *handlers; | ||
2663 | 2895 | ||
2664 | if (msg->rsp_size < 10) { | 2896 | if (msg->rsp_size < 10) { |
2665 | /* Message not big enough, just ignore it. */ | 2897 | /* Message not big enough, just ignore it. */ |
@@ -2716,10 +2948,16 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, | |||
2716 | printk("\n"); | 2948 | printk("\n"); |
2717 | } | 2949 | } |
2718 | #endif | 2950 | #endif |
2719 | intf->handlers->sender(intf->send_info, msg, 0); | 2951 | rcu_read_lock(); |
2720 | 2952 | handlers = intf->handlers; | |
2721 | rv = -1; /* We used the message, so return the value that | 2953 | if (handlers) { |
2722 | causes it to not be freed or queued. */ | 2954 | handlers->sender(intf->send_info, msg, 0); |
2955 | /* We used the message, so return the value | ||
2956 | that causes it to not be freed or | ||
2957 | queued. */ | ||
2958 | rv = -1; | ||
2959 | } | ||
2960 | rcu_read_unlock(); | ||
2723 | } else { | 2961 | } else { |
2724 | /* Deliver the message to the user. */ | 2962 | /* Deliver the message to the user. */ |
2725 | spin_lock_irqsave(&intf->counter_lock, flags); | 2963 | spin_lock_irqsave(&intf->counter_lock, flags); |
@@ -3309,16 +3547,6 @@ void ipmi_smi_watchdog_pretimeout(ipmi_smi_t intf) | |||
3309 | rcu_read_unlock(); | 3547 | rcu_read_unlock(); |
3310 | } | 3548 | } |
3311 | 3549 | ||
3312 | static void | ||
3313 | handle_msg_timeout(struct ipmi_recv_msg *msg) | ||
3314 | { | ||
3315 | msg->recv_type = IPMI_RESPONSE_RECV_TYPE; | ||
3316 | msg->msg_data[0] = IPMI_TIMEOUT_COMPLETION_CODE; | ||
3317 | msg->msg.netfn |= 1; /* Convert to a response. */ | ||
3318 | msg->msg.data_len = 1; | ||
3319 | msg->msg.data = msg->msg_data; | ||
3320 | deliver_response(msg); | ||
3321 | } | ||
3322 | 3550 | ||
3323 | static struct ipmi_smi_msg * | 3551 | static struct ipmi_smi_msg * |
3324 | smi_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg, | 3552 | smi_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg, |
@@ -3350,7 +3578,11 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, | |||
3350 | struct list_head *timeouts, long timeout_period, | 3578 | struct list_head *timeouts, long timeout_period, |
3351 | int slot, unsigned long *flags) | 3579 | int slot, unsigned long *flags) |
3352 | { | 3580 | { |
3353 | struct ipmi_recv_msg *msg; | 3581 | struct ipmi_recv_msg *msg; |
3582 | struct ipmi_smi_handlers *handlers; | ||
3583 | |||
3584 | if (intf->intf_num == -1) | ||
3585 | return; | ||
3354 | 3586 | ||
3355 | if (!ent->inuse) | 3587 | if (!ent->inuse) |
3356 | return; | 3588 | return; |
@@ -3393,13 +3625,19 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, | |||
3393 | return; | 3625 | return; |
3394 | 3626 | ||
3395 | spin_unlock_irqrestore(&intf->seq_lock, *flags); | 3627 | spin_unlock_irqrestore(&intf->seq_lock, *flags); |
3628 | |||
3396 | /* Send the new message. We send with a zero | 3629 | /* Send the new message. We send with a zero |
3397 | * priority. It timed out, I doubt time is | 3630 | * priority. It timed out, I doubt time is |
3398 | * that critical now, and high priority | 3631 | * that critical now, and high priority |
3399 | * messages are really only for messages to the | 3632 | * messages are really only for messages to the |
3400 | * local MC, which don't get resent. */ | 3633 | * local MC, which don't get resent. */ |
3401 | intf->handlers->sender(intf->send_info, | 3634 | handlers = intf->handlers; |
3402 | smi_msg, 0); | 3635 | if (handlers) |
3636 | intf->handlers->sender(intf->send_info, | ||
3637 | smi_msg, 0); | ||
3638 | else | ||
3639 | ipmi_free_smi_msg(smi_msg); | ||
3640 | |||
3403 | spin_lock_irqsave(&intf->seq_lock, *flags); | 3641 | spin_lock_irqsave(&intf->seq_lock, *flags); |
3404 | } | 3642 | } |
3405 | } | 3643 | } |
@@ -3411,18 +3649,12 @@ static void ipmi_timeout_handler(long timeout_period) | |||
3411 | struct ipmi_recv_msg *msg, *msg2; | 3649 | struct ipmi_recv_msg *msg, *msg2; |
3412 | struct ipmi_smi_msg *smi_msg, *smi_msg2; | 3650 | struct ipmi_smi_msg *smi_msg, *smi_msg2; |
3413 | unsigned long flags; | 3651 | unsigned long flags; |
3414 | int i, j; | 3652 | int i; |
3415 | 3653 | ||
3416 | INIT_LIST_HEAD(&timeouts); | 3654 | INIT_LIST_HEAD(&timeouts); |
3417 | 3655 | ||
3418 | spin_lock(&interfaces_lock); | 3656 | rcu_read_lock(); |
3419 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { | 3657 | list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { |
3420 | intf = ipmi_interfaces[i]; | ||
3421 | if (IPMI_INVALID_INTERFACE(intf)) | ||
3422 | continue; | ||
3423 | kref_get(&intf->refcount); | ||
3424 | spin_unlock(&interfaces_lock); | ||
3425 | |||
3426 | /* See if any waiting messages need to be processed. */ | 3658 | /* See if any waiting messages need to be processed. */ |
3427 | spin_lock_irqsave(&intf->waiting_msgs_lock, flags); | 3659 | spin_lock_irqsave(&intf->waiting_msgs_lock, flags); |
3428 | list_for_each_entry_safe(smi_msg, smi_msg2, | 3660 | list_for_each_entry_safe(smi_msg, smi_msg2, |
@@ -3442,35 +3674,60 @@ static void ipmi_timeout_handler(long timeout_period) | |||
3442 | have timed out, putting them in the timeouts | 3674 | have timed out, putting them in the timeouts |
3443 | list. */ | 3675 | list. */ |
3444 | spin_lock_irqsave(&intf->seq_lock, flags); | 3676 | spin_lock_irqsave(&intf->seq_lock, flags); |
3445 | for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) | 3677 | for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) |
3446 | check_msg_timeout(intf, &(intf->seq_table[j]), | 3678 | check_msg_timeout(intf, &(intf->seq_table[i]), |
3447 | &timeouts, timeout_period, j, | 3679 | &timeouts, timeout_period, i, |
3448 | &flags); | 3680 | &flags); |
3449 | spin_unlock_irqrestore(&intf->seq_lock, flags); | 3681 | spin_unlock_irqrestore(&intf->seq_lock, flags); |
3450 | 3682 | ||
3451 | list_for_each_entry_safe(msg, msg2, &timeouts, link) | 3683 | list_for_each_entry_safe(msg, msg2, &timeouts, link) |
3452 | handle_msg_timeout(msg); | 3684 | deliver_err_response(msg, IPMI_TIMEOUT_COMPLETION_CODE); |
3453 | 3685 | ||
3454 | kref_put(&intf->refcount, intf_free); | 3686 | /* |
3455 | spin_lock(&interfaces_lock); | 3687 | * Maintenance mode handling. Check the timeout |
3688 | * optimistically before we claim the lock. It may | ||
3689 | * mean a timeout gets missed occasionally, but that | ||
3690 | * only means the timeout gets extended by one period | ||
3691 | * in that case. No big deal, and it avoids the lock | ||
3692 | * most of the time. | ||
3693 | */ | ||
3694 | if (intf->auto_maintenance_timeout > 0) { | ||
3695 | spin_lock_irqsave(&intf->maintenance_mode_lock, flags); | ||
3696 | if (intf->auto_maintenance_timeout > 0) { | ||
3697 | intf->auto_maintenance_timeout | ||
3698 | -= timeout_period; | ||
3699 | if (!intf->maintenance_mode | ||
3700 | && (intf->auto_maintenance_timeout <= 0)) | ||
3701 | { | ||
3702 | intf->maintenance_mode_enable = 0; | ||
3703 | maintenance_mode_update(intf); | ||
3704 | } | ||
3705 | } | ||
3706 | spin_unlock_irqrestore(&intf->maintenance_mode_lock, | ||
3707 | flags); | ||
3708 | } | ||
3456 | } | 3709 | } |
3457 | spin_unlock(&interfaces_lock); | 3710 | rcu_read_unlock(); |
3458 | } | 3711 | } |
3459 | 3712 | ||
3460 | static void ipmi_request_event(void) | 3713 | static void ipmi_request_event(void) |
3461 | { | 3714 | { |
3462 | ipmi_smi_t intf; | 3715 | ipmi_smi_t intf; |
3463 | int i; | 3716 | struct ipmi_smi_handlers *handlers; |
3464 | 3717 | ||
3465 | spin_lock(&interfaces_lock); | 3718 | rcu_read_lock(); |
3466 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { | 3719 | /* Called from the timer, no need to check if handlers is |
3467 | intf = ipmi_interfaces[i]; | 3720 | * valid. */ |
3468 | if (IPMI_INVALID_INTERFACE(intf)) | 3721 | list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { |
3722 | /* No event requests when in maintenance mode. */ | ||
3723 | if (intf->maintenance_mode_enable) | ||
3469 | continue; | 3724 | continue; |
3470 | 3725 | ||
3471 | intf->handlers->request_events(intf->send_info); | 3726 | handlers = intf->handlers; |
3727 | if (handlers) | ||
3728 | handlers->request_events(intf->send_info); | ||
3472 | } | 3729 | } |
3473 | spin_unlock(&interfaces_lock); | 3730 | rcu_read_unlock(); |
3474 | } | 3731 | } |
3475 | 3732 | ||
3476 | static struct timer_list ipmi_timer; | 3733 | static struct timer_list ipmi_timer; |
@@ -3599,7 +3856,6 @@ static void send_panic_events(char *str) | |||
3599 | struct kernel_ipmi_msg msg; | 3856 | struct kernel_ipmi_msg msg; |
3600 | ipmi_smi_t intf; | 3857 | ipmi_smi_t intf; |
3601 | unsigned char data[16]; | 3858 | unsigned char data[16]; |
3602 | int i; | ||
3603 | struct ipmi_system_interface_addr *si; | 3859 | struct ipmi_system_interface_addr *si; |
3604 | struct ipmi_addr addr; | 3860 | struct ipmi_addr addr; |
3605 | struct ipmi_smi_msg smi_msg; | 3861 | struct ipmi_smi_msg smi_msg; |
@@ -3633,9 +3889,9 @@ static void send_panic_events(char *str) | |||
3633 | recv_msg.done = dummy_recv_done_handler; | 3889 | recv_msg.done = dummy_recv_done_handler; |
3634 | 3890 | ||
3635 | /* For every registered interface, send the event. */ | 3891 | /* For every registered interface, send the event. */ |
3636 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { | 3892 | list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { |
3637 | intf = ipmi_interfaces[i]; | 3893 | if (!intf->handlers) |
3638 | if (IPMI_INVALID_INTERFACE(intf)) | 3894 | /* Interface is not ready. */ |
3639 | continue; | 3895 | continue; |
3640 | 3896 | ||
3641 | /* Send the event announcing the panic. */ | 3897 | /* Send the event announcing the panic. */ |
@@ -3660,13 +3916,14 @@ static void send_panic_events(char *str) | |||
3660 | if (!str) | 3916 | if (!str) |
3661 | return; | 3917 | return; |
3662 | 3918 | ||
3663 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { | 3919 | /* For every registered interface, send the event. */ |
3920 | list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { | ||
3664 | char *p = str; | 3921 | char *p = str; |
3665 | struct ipmi_ipmb_addr *ipmb; | 3922 | struct ipmi_ipmb_addr *ipmb; |
3666 | int j; | 3923 | int j; |
3667 | 3924 | ||
3668 | intf = ipmi_interfaces[i]; | 3925 | if (intf->intf_num == -1) |
3669 | if (IPMI_INVALID_INTERFACE(intf)) | 3926 | /* Interface was not ready yet. */ |
3670 | continue; | 3927 | continue; |
3671 | 3928 | ||
3672 | /* First job here is to figure out where to send the | 3929 | /* First job here is to figure out where to send the |
@@ -3792,7 +4049,6 @@ static int panic_event(struct notifier_block *this, | |||
3792 | unsigned long event, | 4049 | unsigned long event, |
3793 | void *ptr) | 4050 | void *ptr) |
3794 | { | 4051 | { |
3795 | int i; | ||
3796 | ipmi_smi_t intf; | 4052 | ipmi_smi_t intf; |
3797 | 4053 | ||
3798 | if (has_panicked) | 4054 | if (has_panicked) |
@@ -3800,9 +4056,9 @@ static int panic_event(struct notifier_block *this, | |||
3800 | has_panicked = 1; | 4056 | has_panicked = 1; |
3801 | 4057 | ||
3802 | /* For every registered interface, set it to run to completion. */ | 4058 | /* For every registered interface, set it to run to completion. */ |
3803 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { | 4059 | list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { |
3804 | intf = ipmi_interfaces[i]; | 4060 | if (!intf->handlers) |
3805 | if (IPMI_INVALID_INTERFACE(intf)) | 4061 | /* Interface is not ready. */ |
3806 | continue; | 4062 | continue; |
3807 | 4063 | ||
3808 | intf->handlers->set_run_to_completion(intf->send_info, 1); | 4064 | intf->handlers->set_run_to_completion(intf->send_info, 1); |
@@ -3823,7 +4079,6 @@ static struct notifier_block panic_block = { | |||
3823 | 4079 | ||
3824 | static int ipmi_init_msghandler(void) | 4080 | static int ipmi_init_msghandler(void) |
3825 | { | 4081 | { |
3826 | int i; | ||
3827 | int rv; | 4082 | int rv; |
3828 | 4083 | ||
3829 | if (initialized) | 4084 | if (initialized) |
@@ -3838,9 +4093,6 @@ static int ipmi_init_msghandler(void) | |||
3838 | printk(KERN_INFO "ipmi message handler version " | 4093 | printk(KERN_INFO "ipmi message handler version " |
3839 | IPMI_DRIVER_VERSION "\n"); | 4094 | IPMI_DRIVER_VERSION "\n"); |
3840 | 4095 | ||
3841 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) | ||
3842 | ipmi_interfaces[i] = NULL; | ||
3843 | |||
3844 | #ifdef CONFIG_PROC_FS | 4096 | #ifdef CONFIG_PROC_FS |
3845 | proc_ipmi_root = proc_mkdir("ipmi", NULL); | 4097 | proc_ipmi_root = proc_mkdir("ipmi", NULL); |
3846 | if (!proc_ipmi_root) { | 4098 | if (!proc_ipmi_root) { |