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.

ipmi: Allow an SMI sender to return an error

Getting ready for handling when a BMC is non-responsive or broken, allow
the sender operation to fail in an SMI. If it was a user-generated
message it will return the error.

The powernv code was already doing this internally, but the way it was
written could result in deep stack descent if there were a lot of
messages queued. Have its send return an error in this case.

Signed-off-by: Corey Minyard <corey@minyard.net>

+35 -24
+2 -2
drivers/char/ipmi/ipmi_ipmb.c
··· 404 404 ipmi_ipmb_stop_thread(iidev); 405 405 } 406 406 407 - static void ipmi_ipmb_sender(void *send_info, 408 - struct ipmi_smi_msg *msg) 407 + static int ipmi_ipmb_sender(void *send_info, struct ipmi_smi_msg *msg) 409 408 { 410 409 struct ipmi_ipmb_dev *iidev = send_info; 411 410 unsigned long flags; ··· 416 417 spin_unlock_irqrestore(&iidev->lock, flags); 417 418 418 419 up(&iidev->wake_thread); 420 + return IPMI_CC_NO_ERROR; 419 421 } 420 422 421 423 static void ipmi_ipmb_request_events(void *send_info)
+13 -3
drivers/char/ipmi/ipmi_msghandler.c
··· 4803 4803 int run_to_completion = READ_ONCE(intf->run_to_completion); 4804 4804 struct ipmi_smi_msg *newmsg = NULL; 4805 4805 struct ipmi_recv_msg *msg, *msg2; 4806 + int cc; 4806 4807 4807 4808 /* 4808 4809 * Start the next message if available. ··· 4812 4811 * because the lower layer is allowed to hold locks while calling 4813 4812 * message delivery. 4814 4813 */ 4815 - 4814 + restart: 4816 4815 if (!run_to_completion) 4817 4816 spin_lock_irqsave(&intf->xmit_msgs_lock, flags); 4818 4817 if (intf->curr_msg == NULL && !intf->in_shutdown) { ··· 4833 4832 if (!run_to_completion) 4834 4833 spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags); 4835 4834 4836 - if (newmsg) 4837 - intf->handlers->sender(intf->send_info, newmsg); 4835 + if (newmsg) { 4836 + cc = intf->handlers->sender(intf->send_info, newmsg); 4837 + if (cc) { 4838 + if (newmsg->user_data) 4839 + deliver_err_response(intf, 4840 + newmsg->user_data, cc); 4841 + else 4842 + ipmi_free_smi_msg(newmsg); 4843 + goto restart; 4844 + } 4845 + } 4838 4846 4839 4847 handle_new_recv_msgs(intf); 4840 4848
+9 -8
drivers/char/ipmi/ipmi_powernv.c
··· 51 51 ipmi_smi_msg_received(smi->intf, msg); 52 52 } 53 53 54 - static void ipmi_powernv_send(void *send_info, struct ipmi_smi_msg *msg) 54 + static int ipmi_powernv_send(void *send_info, struct ipmi_smi_msg *msg) 55 55 { 56 56 struct ipmi_smi_powernv *smi = send_info; 57 57 struct opal_ipmi_msg *opal_msg; ··· 93 93 smi->interface_id, opal_msg, size); 94 94 rc = opal_ipmi_send(smi->interface_id, opal_msg, size); 95 95 pr_devel("%s: -> %d\n", __func__, rc); 96 - 97 - if (!rc) { 98 - smi->cur_msg = msg; 99 - spin_unlock_irqrestore(&smi->msg_lock, flags); 100 - return; 96 + if (rc) { 97 + comp = IPMI_ERR_UNSPECIFIED; 98 + goto err_unlock; 101 99 } 102 100 103 - comp = IPMI_ERR_UNSPECIFIED; 101 + smi->cur_msg = msg; 102 + spin_unlock_irqrestore(&smi->msg_lock, flags); 103 + return IPMI_CC_NO_ERROR; 104 + 104 105 err_unlock: 105 106 spin_unlock_irqrestore(&smi->msg_lock, flags); 106 107 err: 107 - send_error_reply(smi, msg, comp); 108 + return comp; 108 109 } 109 110 110 111 static int ipmi_powernv_recv(struct ipmi_smi_powernv *smi)
+3 -5
drivers/char/ipmi/ipmi_si_intf.c
··· 809 809 * this if there is not yet an upper layer to handle anything. 810 810 */ 811 811 if (si_sm_result == SI_SM_ATTN || smi_info->got_attn) { 812 - unsigned char msg[2]; 813 - 814 812 if (smi_info->si_state != SI_NORMAL) { 815 813 /* 816 814 * We got an ATTN, but we are doing something else. ··· 905 907 } 906 908 } 907 909 908 - static void sender(void *send_info, 909 - struct ipmi_smi_msg *msg) 910 + static int sender(void *send_info, struct ipmi_smi_msg *msg) 910 911 { 911 912 struct smi_info *smi_info = send_info; 912 913 unsigned long flags; ··· 918 921 * layer will call flush_messages to clear it out. 919 922 */ 920 923 smi_info->waiting_msg = msg; 921 - return; 924 + return IPMI_CC_NO_ERROR; 922 925 } 923 926 924 927 spin_lock_irqsave(&smi_info->si_lock, flags); ··· 933 936 smi_info->waiting_msg = msg; 934 937 check_start_timer_thread(smi_info); 935 938 spin_unlock_irqrestore(&smi_info->si_lock, flags); 939 + return IPMI_CC_NO_ERROR; 936 940 } 937 941 938 942 static void set_run_to_completion(void *send_info, bool i_run_to_completion)
+2 -2
drivers/char/ipmi/ipmi_ssif.c
··· 1068 1068 } 1069 1069 } 1070 1070 1071 - static void sender(void *send_info, 1072 - struct ipmi_smi_msg *msg) 1071 + static int sender(void *send_info, struct ipmi_smi_msg *msg) 1073 1072 { 1074 1073 struct ssif_info *ssif_info = send_info; 1075 1074 unsigned long oflags, *flags; ··· 1088 1089 msg->data[0], msg->data[1], 1089 1090 (long long)t.tv_sec, (long)t.tv_nsec / NSEC_PER_USEC); 1090 1091 } 1092 + return IPMI_CC_NO_ERROR; 1091 1093 } 1092 1094 1093 1095 static int get_smi_info(void *send_info, struct ipmi_smi_info *data)
+6 -4
include/linux/ipmi_smi.h
··· 109 109 110 110 enum ipmi_smi_msg_type type; 111 111 112 - long msgid; 113 - void *user_data; 112 + long msgid; 113 + void *user_data; 114 114 115 115 int data_size; 116 116 unsigned char data[IPMI_MAX_MSG_LENGTH]; ··· 168 168 * are held when this is run. Message are delivered one at 169 169 * a time by the message handler, a new message will not be 170 170 * delivered until the previous message is returned. 171 + * 172 + * This can return an error if the SMI is not in a state where it 173 + * can send a message. 171 174 */ 172 - void (*sender)(void *send_info, 173 - struct ipmi_smi_msg *msg); 175 + int (*sender)(void *send_info, struct ipmi_smi_msg *msg); 174 176 175 177 /* 176 178 * Called by the upper layer to request that we try to get