diff options
-rw-r--r-- | drivers/char/ipmi/ipmi_si_intf.c | 140 |
1 files changed, 66 insertions, 74 deletions
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 657034febdaf..286c042a0c66 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -120,6 +120,27 @@ static struct device_driver ipmi_driver = | |||
120 | .bus = &platform_bus_type | 120 | .bus = &platform_bus_type |
121 | }; | 121 | }; |
122 | 122 | ||
123 | |||
124 | /* | ||
125 | * Indexes into stats[] in smi_info below. | ||
126 | */ | ||
127 | |||
128 | #define SI_STAT_short_timeouts 0 | ||
129 | #define SI_STAT_long_timeouts 1 | ||
130 | #define SI_STAT_timeout_restarts 2 | ||
131 | #define SI_STAT_idles 3 | ||
132 | #define SI_STAT_interrupts 4 | ||
133 | #define SI_STAT_attentions 5 | ||
134 | #define SI_STAT_flag_fetches 6 | ||
135 | #define SI_STAT_hosed_count 7 | ||
136 | #define SI_STAT_complete_transactions 8 | ||
137 | #define SI_STAT_events 9 | ||
138 | #define SI_STAT_watchdog_pretimeouts 10 | ||
139 | #define SI_STAT_incoming_messages 11 | ||
140 | |||
141 | /* If you add a stat, you must update this value. */ | ||
142 | #define SI_NUM_STATS 12 | ||
143 | |||
123 | struct smi_info | 144 | struct smi_info |
124 | { | 145 | { |
125 | int intf_num; | 146 | int intf_num; |
@@ -216,25 +237,18 @@ struct smi_info | |||
216 | unsigned char slave_addr; | 237 | unsigned char slave_addr; |
217 | 238 | ||
218 | /* Counters and things for the proc filesystem. */ | 239 | /* Counters and things for the proc filesystem. */ |
219 | spinlock_t count_lock; | 240 | atomic_t stats[SI_NUM_STATS]; |
220 | unsigned long short_timeouts; | ||
221 | unsigned long long_timeouts; | ||
222 | unsigned long timeout_restarts; | ||
223 | unsigned long idles; | ||
224 | unsigned long interrupts; | ||
225 | unsigned long attentions; | ||
226 | unsigned long flag_fetches; | ||
227 | unsigned long hosed_count; | ||
228 | unsigned long complete_transactions; | ||
229 | unsigned long events; | ||
230 | unsigned long watchdog_pretimeouts; | ||
231 | unsigned long incoming_messages; | ||
232 | 241 | ||
233 | struct task_struct *thread; | 242 | struct task_struct *thread; |
234 | 243 | ||
235 | struct list_head link; | 244 | struct list_head link; |
236 | }; | 245 | }; |
237 | 246 | ||
247 | #define smi_inc_stat(smi, stat) \ | ||
248 | atomic_inc(&(smi)->stats[SI_STAT_ ## stat]) | ||
249 | #define smi_get_stat(smi, stat) \ | ||
250 | ((unsigned int) atomic_read(&(smi)->stats[SI_STAT_ ## stat])) | ||
251 | |||
238 | #define SI_MAX_PARMS 4 | 252 | #define SI_MAX_PARMS 4 |
239 | 253 | ||
240 | static int force_kipmid[SI_MAX_PARMS]; | 254 | static int force_kipmid[SI_MAX_PARMS]; |
@@ -398,9 +412,7 @@ static void handle_flags(struct smi_info *smi_info) | |||
398 | retry: | 412 | retry: |
399 | if (smi_info->msg_flags & WDT_PRE_TIMEOUT_INT) { | 413 | if (smi_info->msg_flags & WDT_PRE_TIMEOUT_INT) { |
400 | /* Watchdog pre-timeout */ | 414 | /* Watchdog pre-timeout */ |
401 | spin_lock(&smi_info->count_lock); | 415 | smi_inc_stat(smi_info, watchdog_pretimeouts); |
402 | smi_info->watchdog_pretimeouts++; | ||
403 | spin_unlock(&smi_info->count_lock); | ||
404 | 416 | ||
405 | start_clear_flags(smi_info); | 417 | start_clear_flags(smi_info); |
406 | smi_info->msg_flags &= ~WDT_PRE_TIMEOUT_INT; | 418 | smi_info->msg_flags &= ~WDT_PRE_TIMEOUT_INT; |
@@ -545,9 +557,7 @@ static void handle_transaction_done(struct smi_info *smi_info) | |||
545 | smi_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL; | 557 | smi_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL; |
546 | handle_flags(smi_info); | 558 | handle_flags(smi_info); |
547 | } else { | 559 | } else { |
548 | spin_lock(&smi_info->count_lock); | 560 | smi_inc_stat(smi_info, events); |
549 | smi_info->events++; | ||
550 | spin_unlock(&smi_info->count_lock); | ||
551 | 561 | ||
552 | /* Do this before we deliver the message | 562 | /* Do this before we deliver the message |
553 | because delivering the message releases the | 563 | because delivering the message releases the |
@@ -581,9 +591,7 @@ static void handle_transaction_done(struct smi_info *smi_info) | |||
581 | smi_info->msg_flags &= ~RECEIVE_MSG_AVAIL; | 591 | smi_info->msg_flags &= ~RECEIVE_MSG_AVAIL; |
582 | handle_flags(smi_info); | 592 | handle_flags(smi_info); |
583 | } else { | 593 | } else { |
584 | spin_lock(&smi_info->count_lock); | 594 | smi_inc_stat(smi_info, incoming_messages); |
585 | smi_info->incoming_messages++; | ||
586 | spin_unlock(&smi_info->count_lock); | ||
587 | 595 | ||
588 | /* Do this before we deliver the message | 596 | /* Do this before we deliver the message |
589 | because delivering the message releases the | 597 | because delivering the message releases the |
@@ -700,18 +708,14 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info, | |||
700 | 708 | ||
701 | if (si_sm_result == SI_SM_TRANSACTION_COMPLETE) | 709 | if (si_sm_result == SI_SM_TRANSACTION_COMPLETE) |
702 | { | 710 | { |
703 | spin_lock(&smi_info->count_lock); | 711 | smi_inc_stat(smi_info, complete_transactions); |
704 | smi_info->complete_transactions++; | ||
705 | spin_unlock(&smi_info->count_lock); | ||
706 | 712 | ||
707 | handle_transaction_done(smi_info); | 713 | handle_transaction_done(smi_info); |
708 | si_sm_result = smi_info->handlers->event(smi_info->si_sm, 0); | 714 | si_sm_result = smi_info->handlers->event(smi_info->si_sm, 0); |
709 | } | 715 | } |
710 | else if (si_sm_result == SI_SM_HOSED) | 716 | else if (si_sm_result == SI_SM_HOSED) |
711 | { | 717 | { |
712 | spin_lock(&smi_info->count_lock); | 718 | smi_inc_stat(smi_info, hosed_count); |
713 | smi_info->hosed_count++; | ||
714 | spin_unlock(&smi_info->count_lock); | ||
715 | 719 | ||
716 | /* Do the before return_hosed_msg, because that | 720 | /* Do the before return_hosed_msg, because that |
717 | releases the lock. */ | 721 | releases the lock. */ |
@@ -733,9 +737,7 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info, | |||
733 | { | 737 | { |
734 | unsigned char msg[2]; | 738 | unsigned char msg[2]; |
735 | 739 | ||
736 | spin_lock(&smi_info->count_lock); | 740 | smi_inc_stat(smi_info, attentions); |
737 | smi_info->attentions++; | ||
738 | spin_unlock(&smi_info->count_lock); | ||
739 | 741 | ||
740 | /* Got a attn, send down a get message flags to see | 742 | /* Got a attn, send down a get message flags to see |
741 | what's causing it. It would be better to handle | 743 | what's causing it. It would be better to handle |
@@ -753,9 +755,7 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info, | |||
753 | 755 | ||
754 | /* If we are currently idle, try to start the next message. */ | 756 | /* If we are currently idle, try to start the next message. */ |
755 | if (si_sm_result == SI_SM_IDLE) { | 757 | if (si_sm_result == SI_SM_IDLE) { |
756 | spin_lock(&smi_info->count_lock); | 758 | smi_inc_stat(smi_info, idles); |
757 | smi_info->idles++; | ||
758 | spin_unlock(&smi_info->count_lock); | ||
759 | 759 | ||
760 | si_sm_result = start_next_msg(smi_info); | 760 | si_sm_result = start_next_msg(smi_info); |
761 | if (si_sm_result != SI_SM_IDLE) | 761 | if (si_sm_result != SI_SM_IDLE) |
@@ -945,23 +945,17 @@ static void smi_timeout(unsigned long data) | |||
945 | if ((smi_info->irq) && (!smi_info->interrupt_disabled)) { | 945 | if ((smi_info->irq) && (!smi_info->interrupt_disabled)) { |
946 | /* Running with interrupts, only do long timeouts. */ | 946 | /* Running with interrupts, only do long timeouts. */ |
947 | smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; | 947 | smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; |
948 | spin_lock_irqsave(&smi_info->count_lock, flags); | 948 | smi_inc_stat(smi_info, long_timeouts); |
949 | smi_info->long_timeouts++; | ||
950 | spin_unlock_irqrestore(&smi_info->count_lock, flags); | ||
951 | goto do_add_timer; | 949 | goto do_add_timer; |
952 | } | 950 | } |
953 | 951 | ||
954 | /* If the state machine asks for a short delay, then shorten | 952 | /* If the state machine asks for a short delay, then shorten |
955 | the timer timeout. */ | 953 | the timer timeout. */ |
956 | if (smi_result == SI_SM_CALL_WITH_DELAY) { | 954 | if (smi_result == SI_SM_CALL_WITH_DELAY) { |
957 | spin_lock_irqsave(&smi_info->count_lock, flags); | 955 | smi_inc_stat(smi_info, short_timeouts); |
958 | smi_info->short_timeouts++; | ||
959 | spin_unlock_irqrestore(&smi_info->count_lock, flags); | ||
960 | smi_info->si_timer.expires = jiffies + 1; | 956 | smi_info->si_timer.expires = jiffies + 1; |
961 | } else { | 957 | } else { |
962 | spin_lock_irqsave(&smi_info->count_lock, flags); | 958 | smi_inc_stat(smi_info, long_timeouts); |
963 | smi_info->long_timeouts++; | ||
964 | spin_unlock_irqrestore(&smi_info->count_lock, flags); | ||
965 | smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; | 959 | smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; |
966 | } | 960 | } |
967 | 961 | ||
@@ -979,9 +973,7 @@ static irqreturn_t si_irq_handler(int irq, void *data) | |||
979 | 973 | ||
980 | spin_lock_irqsave(&(smi_info->si_lock), flags); | 974 | spin_lock_irqsave(&(smi_info->si_lock), flags); |
981 | 975 | ||
982 | spin_lock(&smi_info->count_lock); | 976 | smi_inc_stat(smi_info, interrupts); |
983 | smi_info->interrupts++; | ||
984 | spin_unlock(&smi_info->count_lock); | ||
985 | 977 | ||
986 | #ifdef DEBUG_TIMING | 978 | #ifdef DEBUG_TIMING |
987 | do_gettimeofday(&t); | 979 | do_gettimeofday(&t); |
@@ -1765,9 +1757,7 @@ static u32 ipmi_acpi_gpe(void *context) | |||
1765 | 1757 | ||
1766 | spin_lock_irqsave(&(smi_info->si_lock), flags); | 1758 | spin_lock_irqsave(&(smi_info->si_lock), flags); |
1767 | 1759 | ||
1768 | spin_lock(&smi_info->count_lock); | 1760 | smi_inc_stat(smi_info, interrupts); |
1769 | smi_info->interrupts++; | ||
1770 | spin_unlock(&smi_info->count_lock); | ||
1771 | 1761 | ||
1772 | #ifdef DEBUG_TIMING | 1762 | #ifdef DEBUG_TIMING |
1773 | do_gettimeofday(&t); | 1763 | do_gettimeofday(&t); |
@@ -2405,30 +2395,30 @@ static int stat_file_read_proc(char *page, char **start, off_t off, | |||
2405 | 2395 | ||
2406 | out += sprintf(out, "interrupts_enabled: %d\n", | 2396 | out += sprintf(out, "interrupts_enabled: %d\n", |
2407 | smi->irq && !smi->interrupt_disabled); | 2397 | smi->irq && !smi->interrupt_disabled); |
2408 | out += sprintf(out, "short_timeouts: %ld\n", | 2398 | out += sprintf(out, "short_timeouts: %u\n", |
2409 | smi->short_timeouts); | 2399 | smi_get_stat(smi, short_timeouts)); |
2410 | out += sprintf(out, "long_timeouts: %ld\n", | 2400 | out += sprintf(out, "long_timeouts: %u\n", |
2411 | smi->long_timeouts); | 2401 | smi_get_stat(smi, long_timeouts)); |
2412 | out += sprintf(out, "timeout_restarts: %ld\n", | 2402 | out += sprintf(out, "timeout_restarts: %u\n", |
2413 | smi->timeout_restarts); | 2403 | smi_get_stat(smi, timeout_restarts)); |
2414 | out += sprintf(out, "idles: %ld\n", | 2404 | out += sprintf(out, "idles: %u\n", |
2415 | smi->idles); | 2405 | smi_get_stat(smi, idles)); |
2416 | out += sprintf(out, "interrupts: %ld\n", | 2406 | out += sprintf(out, "interrupts: %u\n", |
2417 | smi->interrupts); | 2407 | smi_get_stat(smi, interrupts)); |
2418 | out += sprintf(out, "attentions: %ld\n", | 2408 | out += sprintf(out, "attentions: %u\n", |
2419 | smi->attentions); | 2409 | smi_get_stat(smi, attentions)); |
2420 | out += sprintf(out, "flag_fetches: %ld\n", | 2410 | out += sprintf(out, "flag_fetches: %u\n", |
2421 | smi->flag_fetches); | 2411 | smi_get_stat(smi, flag_fetches)); |
2422 | out += sprintf(out, "hosed_count: %ld\n", | 2412 | out += sprintf(out, "hosed_count: %u\n", |
2423 | smi->hosed_count); | 2413 | smi_get_stat(smi, hosed_count)); |
2424 | out += sprintf(out, "complete_transactions: %ld\n", | 2414 | out += sprintf(out, "complete_transactions: %u\n", |
2425 | smi->complete_transactions); | 2415 | smi_get_stat(smi, complete_transactions)); |
2426 | out += sprintf(out, "events: %ld\n", | 2416 | out += sprintf(out, "events: %u\n", |
2427 | smi->events); | 2417 | smi_get_stat(smi, events)); |
2428 | out += sprintf(out, "watchdog_pretimeouts: %ld\n", | 2418 | out += sprintf(out, "watchdog_pretimeouts: %u\n", |
2429 | smi->watchdog_pretimeouts); | 2419 | smi_get_stat(smi, watchdog_pretimeouts)); |
2430 | out += sprintf(out, "incoming_messages: %ld\n", | 2420 | out += sprintf(out, "incoming_messages: %u\n", |
2431 | smi->incoming_messages); | 2421 | smi_get_stat(smi, incoming_messages)); |
2432 | 2422 | ||
2433 | return out - page; | 2423 | return out - page; |
2434 | } | 2424 | } |
@@ -2676,6 +2666,7 @@ static int is_new_interface(struct smi_info *info) | |||
2676 | static int try_smi_init(struct smi_info *new_smi) | 2666 | static int try_smi_init(struct smi_info *new_smi) |
2677 | { | 2667 | { |
2678 | int rv; | 2668 | int rv; |
2669 | int i; | ||
2679 | 2670 | ||
2680 | if (new_smi->addr_source) { | 2671 | if (new_smi->addr_source) { |
2681 | printk(KERN_INFO "ipmi_si: Trying %s-specified %s state" | 2672 | printk(KERN_INFO "ipmi_si: Trying %s-specified %s state" |
@@ -2738,7 +2729,6 @@ static int try_smi_init(struct smi_info *new_smi) | |||
2738 | 2729 | ||
2739 | spin_lock_init(&(new_smi->si_lock)); | 2730 | spin_lock_init(&(new_smi->si_lock)); |
2740 | spin_lock_init(&(new_smi->msg_lock)); | 2731 | spin_lock_init(&(new_smi->msg_lock)); |
2741 | spin_lock_init(&(new_smi->count_lock)); | ||
2742 | 2732 | ||
2743 | /* Do low-level detection first. */ | 2733 | /* Do low-level detection first. */ |
2744 | if (new_smi->handlers->detect(new_smi->si_sm)) { | 2734 | if (new_smi->handlers->detect(new_smi->si_sm)) { |
@@ -2767,6 +2757,8 @@ static int try_smi_init(struct smi_info *new_smi) | |||
2767 | new_smi->curr_msg = NULL; | 2757 | new_smi->curr_msg = NULL; |
2768 | atomic_set(&new_smi->req_events, 0); | 2758 | atomic_set(&new_smi->req_events, 0); |
2769 | new_smi->run_to_completion = 0; | 2759 | new_smi->run_to_completion = 0; |
2760 | for (i = 0; i < SI_NUM_STATS; i++) | ||
2761 | atomic_set(&new_smi->stats[i], 0); | ||
2770 | 2762 | ||
2771 | new_smi->interrupt_disabled = 0; | 2763 | new_smi->interrupt_disabled = 0; |
2772 | atomic_set(&new_smi->stop_operation, 0); | 2764 | atomic_set(&new_smi->stop_operation, 0); |