aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCorey Minyard <cminyard@mvista.com>2015-04-03 13:13:48 -0400
committerCorey Minyard <cminyard@mvista.com>2015-04-10 21:51:42 -0400
commit1e7d6a45f6b10bc48a1453bca3d829e210546571 (patch)
tree86eb47ed9056f0a99117eb991dc9ec00e47dbe6f
parent3259b12ae1c79c146809829412ddc0d11a1b8e26 (diff)
ipmi: Handle BMCs that don't allow clearing the rcv irq bit
Some BMCs don't let you clear the receive irq bit in the global enables. This is kind of silly, but they give an error if you try to clear it. Compensate for this by detecting the situation and working around it. Signed-off-by: Corey Minyard <cminyard@mvista.com> Tested-by: Thomas D <whissi@whissi.de> Reviewed-by: Thomas D <whissi@whissi.de>
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c109
1 files changed, 102 insertions, 7 deletions
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index f6646ed3047e..518585c1ce94 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -263,6 +263,11 @@ struct smi_info {
263 bool supports_event_msg_buff; 263 bool supports_event_msg_buff;
264 264
265 /* 265 /*
266 * Can we clear the global enables receive irq bit?
267 */
268 bool cannot_clear_recv_irq_bit;
269
270 /*
266 * Did we get an attention that we did not handle? 271 * Did we get an attention that we did not handle?
267 */ 272 */
268 bool got_attn; 273 bool got_attn;
@@ -461,6 +466,9 @@ static void smi_mod_timer(struct smi_info *smi_info, unsigned long new_val)
461 * allocate messages, we just leave them in the BMC and run the system 466 * allocate messages, we just leave them in the BMC and run the system
462 * polled until we can allocate some memory. Once we have some 467 * polled until we can allocate some memory. Once we have some
463 * memory, we will re-enable the interrupt. 468 * memory, we will re-enable the interrupt.
469 *
470 * Note that we cannot just use disable_irq(), since the interrupt may
471 * be shared.
464 */ 472 */
465static inline bool disable_si_irq(struct smi_info *smi_info) 473static inline bool disable_si_irq(struct smi_info *smi_info)
466{ 474{
@@ -549,20 +557,15 @@ static u8 current_global_enables(struct smi_info *smi_info, u8 base,
549 557
550 if (smi_info->supports_event_msg_buff) 558 if (smi_info->supports_event_msg_buff)
551 enables |= IPMI_BMC_EVT_MSG_BUFF; 559 enables |= IPMI_BMC_EVT_MSG_BUFF;
552 else
553 enables &= ~IPMI_BMC_EVT_MSG_BUFF;
554 560
555 if (smi_info->irq && !smi_info->interrupt_disabled) 561 if ((smi_info->irq && !smi_info->interrupt_disabled) ||
562 smi_info->cannot_clear_recv_irq_bit)
556 enables |= IPMI_BMC_RCV_MSG_INTR; 563 enables |= IPMI_BMC_RCV_MSG_INTR;
557 else
558 enables &= ~IPMI_BMC_RCV_MSG_INTR;
559 564
560 if (smi_info->supports_event_msg_buff && 565 if (smi_info->supports_event_msg_buff &&
561 smi_info->irq && !smi_info->interrupt_disabled) 566 smi_info->irq && !smi_info->interrupt_disabled)
562 567
563 enables |= IPMI_BMC_EVT_MSG_INTR; 568 enables |= IPMI_BMC_EVT_MSG_INTR;
564 else
565 enables &= ~IPMI_BMC_EVT_MSG_INTR;
566 569
567 *irq_on = enables & (IPMI_BMC_EVT_MSG_INTR | IPMI_BMC_RCV_MSG_INTR); 570 *irq_on = enables & (IPMI_BMC_EVT_MSG_INTR | IPMI_BMC_RCV_MSG_INTR);
568 571
@@ -2900,6 +2903,96 @@ static int try_get_dev_id(struct smi_info *smi_info)
2900 return rv; 2903 return rv;
2901} 2904}
2902 2905
2906/*
2907 * Some BMCs do not support clearing the receive irq bit in the global
2908 * enables (even if they don't support interrupts on the BMC). Check
2909 * for this and handle it properly.
2910 */
2911static void check_clr_rcv_irq(struct smi_info *smi_info)
2912{
2913 unsigned char msg[3];
2914 unsigned char *resp;
2915 unsigned long resp_len;
2916 int rv;
2917
2918 resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL);
2919 if (!resp) {
2920 printk(KERN_WARNING PFX "Out of memory allocating response for"
2921 " global enables command, cannot check recv irq bit"
2922 " handling.\n");
2923 return;
2924 }
2925
2926 msg[0] = IPMI_NETFN_APP_REQUEST << 2;
2927 msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD;
2928 smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2);
2929
2930 rv = wait_for_msg_done(smi_info);
2931 if (rv) {
2932 printk(KERN_WARNING PFX "Error getting response from get"
2933 " global enables command, cannot check recv irq bit"
2934 " handling.\n");
2935 goto out;
2936 }
2937
2938 resp_len = smi_info->handlers->get_result(smi_info->si_sm,
2939 resp, IPMI_MAX_MSG_LENGTH);
2940
2941 if (resp_len < 4 ||
2942 resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 ||
2943 resp[1] != IPMI_GET_BMC_GLOBAL_ENABLES_CMD ||
2944 resp[2] != 0) {
2945 printk(KERN_WARNING PFX "Invalid return from get global"
2946 " enables command, cannot check recv irq bit"
2947 " handling.\n");
2948 rv = -EINVAL;
2949 goto out;
2950 }
2951
2952 if ((resp[3] & IPMI_BMC_RCV_MSG_INTR) == 0)
2953 /* Already clear, should work ok. */
2954 goto out;
2955
2956 msg[0] = IPMI_NETFN_APP_REQUEST << 2;
2957 msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD;
2958 msg[2] = resp[3] & ~IPMI_BMC_RCV_MSG_INTR;
2959 smi_info->handlers->start_transaction(smi_info->si_sm, msg, 3);
2960
2961 rv = wait_for_msg_done(smi_info);
2962 if (rv) {
2963 printk(KERN_WARNING PFX "Error getting response from set"
2964 " global enables command, cannot check recv irq bit"
2965 " handling.\n");
2966 goto out;
2967 }
2968
2969 resp_len = smi_info->handlers->get_result(smi_info->si_sm,
2970 resp, IPMI_MAX_MSG_LENGTH);
2971
2972 if (resp_len < 3 ||
2973 resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 ||
2974 resp[1] != IPMI_SET_BMC_GLOBAL_ENABLES_CMD) {
2975 printk(KERN_WARNING PFX "Invalid return from get global"
2976 " enables command, cannot check recv irq bit"
2977 " handling.\n");
2978 rv = -EINVAL;
2979 goto out;
2980 }
2981
2982 if (resp[2] != 0) {
2983 /*
2984 * An error when setting the event buffer bit means
2985 * clearing the bit is not supported.
2986 */
2987 printk(KERN_WARNING PFX "The BMC does not support clearing"
2988 " the recv irq bit, compensating, but the BMC needs to"
2989 " be fixed.\n");
2990 smi_info->cannot_clear_recv_irq_bit = true;
2991 }
2992 out:
2993 kfree(resp);
2994}
2995
2903static int try_enable_event_buffer(struct smi_info *smi_info) 2996static int try_enable_event_buffer(struct smi_info *smi_info)
2904{ 2997{
2905 unsigned char msg[3]; 2998 unsigned char msg[3];
@@ -3395,6 +3488,8 @@ static int try_smi_init(struct smi_info *new_smi)
3395 goto out_err; 3488 goto out_err;
3396 } 3489 }
3397 3490
3491 check_clr_rcv_irq(new_smi);
3492
3398 setup_oem_data_handler(new_smi); 3493 setup_oem_data_handler(new_smi);
3399 setup_xaction_handlers(new_smi); 3494 setup_xaction_handlers(new_smi);
3400 3495