Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'for-linus-4.0-1' of git://git.code.sf.net/p/openipmi/linux-ipmi

Pull late ipmi fixes from Corey Minyard:
"Some annoying issues in the IPMI driver that would be good to have
fixed before 4.0 is released.

These got reported or discovered late, but they will avoid some
situations that would cause lots of log spam and in one case a
deadlock"

* tag 'for-linus-4.0-1' of git://git.code.sf.net/p/openipmi/linux-ipmi:
ipmi_ssif: Use interruptible completion for waiting in the thread
ipmi/powernv: Fix minor locking bug
ipmi: Handle BMCs that don't allow clearing the rcv irq bit

+108 -10
+1
drivers/char/ipmi/ipmi_powernv.c
··· 125 125 spin_lock_irqsave(&smi->msg_lock, flags); 126 126 127 127 if (!smi->cur_msg) { 128 + spin_unlock_irqrestore(&smi->msg_lock, flags); 128 129 pr_warn("no current message?\n"); 129 130 return 0; 130 131 }
+102 -7
drivers/char/ipmi/ipmi_si_intf.c
··· 263 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 271 * Did we get an attention that we did not handle? 267 272 */ 268 273 bool got_attn; ··· 466 461 * allocate messages, we just leave them in the BMC and run the system 467 462 * polled until we can allocate some memory. Once we have some 468 463 * memory, we will re-enable the interrupt. 464 + * 465 + * Note that we cannot just use disable_irq(), since the interrupt may 466 + * be shared. 469 467 */ 470 468 static inline bool disable_si_irq(struct smi_info *smi_info) 471 469 { ··· 557 549 558 550 if (smi_info->supports_event_msg_buff) 559 551 enables |= IPMI_BMC_EVT_MSG_BUFF; 560 - else 561 - enables &= ~IPMI_BMC_EVT_MSG_BUFF; 562 552 563 - if (smi_info->irq && !smi_info->interrupt_disabled) 553 + if ((smi_info->irq && !smi_info->interrupt_disabled) || 554 + smi_info->cannot_clear_recv_irq_bit) 564 555 enables |= IPMI_BMC_RCV_MSG_INTR; 565 - else 566 - enables &= ~IPMI_BMC_RCV_MSG_INTR; 567 556 568 557 if (smi_info->supports_event_msg_buff && 569 558 smi_info->irq && !smi_info->interrupt_disabled) 570 559 571 560 enables |= IPMI_BMC_EVT_MSG_INTR; 572 - else 573 - enables &= ~IPMI_BMC_EVT_MSG_INTR; 574 561 575 562 *irq_on = enables & (IPMI_BMC_EVT_MSG_INTR | IPMI_BMC_RCV_MSG_INTR); 576 563 ··· 2903 2900 return rv; 2904 2901 } 2905 2902 2903 + /* 2904 + * Some BMCs do not support clearing the receive irq bit in the global 2905 + * enables (even if they don't support interrupts on the BMC). Check 2906 + * for this and handle it properly. 2907 + */ 2908 + static void check_clr_rcv_irq(struct smi_info *smi_info) 2909 + { 2910 + unsigned char msg[3]; 2911 + unsigned char *resp; 2912 + unsigned long resp_len; 2913 + int rv; 2914 + 2915 + resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL); 2916 + if (!resp) { 2917 + printk(KERN_WARNING PFX "Out of memory allocating response for" 2918 + " global enables command, cannot check recv irq bit" 2919 + " handling.\n"); 2920 + return; 2921 + } 2922 + 2923 + msg[0] = IPMI_NETFN_APP_REQUEST << 2; 2924 + msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD; 2925 + smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2); 2926 + 2927 + rv = wait_for_msg_done(smi_info); 2928 + if (rv) { 2929 + printk(KERN_WARNING PFX "Error getting response from get" 2930 + " global enables command, cannot check recv irq bit" 2931 + " handling.\n"); 2932 + goto out; 2933 + } 2934 + 2935 + resp_len = smi_info->handlers->get_result(smi_info->si_sm, 2936 + resp, IPMI_MAX_MSG_LENGTH); 2937 + 2938 + if (resp_len < 4 || 2939 + resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 || 2940 + resp[1] != IPMI_GET_BMC_GLOBAL_ENABLES_CMD || 2941 + resp[2] != 0) { 2942 + printk(KERN_WARNING PFX "Invalid return from get global" 2943 + " enables command, cannot check recv irq bit" 2944 + " handling.\n"); 2945 + rv = -EINVAL; 2946 + goto out; 2947 + } 2948 + 2949 + if ((resp[3] & IPMI_BMC_RCV_MSG_INTR) == 0) 2950 + /* Already clear, should work ok. */ 2951 + goto out; 2952 + 2953 + msg[0] = IPMI_NETFN_APP_REQUEST << 2; 2954 + msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD; 2955 + msg[2] = resp[3] & ~IPMI_BMC_RCV_MSG_INTR; 2956 + smi_info->handlers->start_transaction(smi_info->si_sm, msg, 3); 2957 + 2958 + rv = wait_for_msg_done(smi_info); 2959 + if (rv) { 2960 + printk(KERN_WARNING PFX "Error getting response from set" 2961 + " global enables command, cannot check recv irq bit" 2962 + " handling.\n"); 2963 + goto out; 2964 + } 2965 + 2966 + resp_len = smi_info->handlers->get_result(smi_info->si_sm, 2967 + resp, IPMI_MAX_MSG_LENGTH); 2968 + 2969 + if (resp_len < 3 || 2970 + resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 || 2971 + resp[1] != IPMI_SET_BMC_GLOBAL_ENABLES_CMD) { 2972 + printk(KERN_WARNING PFX "Invalid return from get global" 2973 + " enables command, cannot check recv irq bit" 2974 + " handling.\n"); 2975 + rv = -EINVAL; 2976 + goto out; 2977 + } 2978 + 2979 + if (resp[2] != 0) { 2980 + /* 2981 + * An error when setting the event buffer bit means 2982 + * clearing the bit is not supported. 2983 + */ 2984 + printk(KERN_WARNING PFX "The BMC does not support clearing" 2985 + " the recv irq bit, compensating, but the BMC needs to" 2986 + " be fixed.\n"); 2987 + smi_info->cannot_clear_recv_irq_bit = true; 2988 + } 2989 + out: 2990 + kfree(resp); 2991 + } 2992 + 2906 2993 static int try_enable_event_buffer(struct smi_info *smi_info) 2907 2994 { 2908 2995 unsigned char msg[3]; ··· 3487 3394 " at this location\n"); 3488 3395 goto out_err; 3489 3396 } 3397 + 3398 + check_clr_rcv_irq(new_smi); 3490 3399 3491 3400 setup_oem_data_handler(new_smi); 3492 3401 setup_xaction_handlers(new_smi);
+5 -3
drivers/char/ipmi/ipmi_ssif.c
··· 468 468 int result; 469 469 470 470 /* Wait for something to do */ 471 - wait_for_completion(&ssif_info->wake_thread); 472 - init_completion(&ssif_info->wake_thread); 473 - 471 + result = wait_for_completion_interruptible( 472 + &ssif_info->wake_thread); 474 473 if (ssif_info->stopping) 475 474 break; 475 + if (result == -ERESTARTSYS) 476 + continue; 477 + init_completion(&ssif_info->wake_thread); 476 478 477 479 if (ssif_info->i2c_read_write == I2C_SMBUS_WRITE) { 478 480 result = i2c_smbus_write_block_data(