Skip to content

Commit 9cf93a8

Browse files
committed
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>
1 parent abe4918 commit 9cf93a8

6 files changed

Lines changed: 35 additions & 24 deletions

File tree

drivers/char/ipmi/ipmi_ipmb.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -404,8 +404,7 @@ static void ipmi_ipmb_shutdown(void *send_info)
404404
ipmi_ipmb_stop_thread(iidev);
405405
}
406406

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)
409408
{
410409
struct ipmi_ipmb_dev *iidev = send_info;
411410
unsigned long flags;
@@ -417,6 +416,7 @@ static void ipmi_ipmb_sender(void *send_info,
417416
spin_unlock_irqrestore(&iidev->lock, flags);
418417

419418
up(&iidev->wake_thread);
419+
return IPMI_CC_NO_ERROR;
420420
}
421421

422422
static void ipmi_ipmb_request_events(void *send_info)

drivers/char/ipmi/ipmi_msghandler.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4803,6 +4803,7 @@ static void smi_work(struct work_struct *t)
48034803
int run_to_completion = READ_ONCE(intf->run_to_completion);
48044804
struct ipmi_smi_msg *newmsg = NULL;
48054805
struct ipmi_recv_msg *msg, *msg2;
4806+
int cc;
48064807

48074808
/*
48084809
* Start the next message if available.
@@ -4811,7 +4812,7 @@ static void smi_work(struct work_struct *t)
48114812
* because the lower layer is allowed to hold locks while calling
48124813
* message delivery.
48134814
*/
4814-
4815+
restart:
48154816
if (!run_to_completion)
48164817
spin_lock_irqsave(&intf->xmit_msgs_lock, flags);
48174818
if (intf->curr_msg == NULL && !intf->in_shutdown) {
@@ -4832,8 +4833,17 @@ static void smi_work(struct work_struct *t)
48324833
if (!run_to_completion)
48334834
spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags);
48344835

4835-
if (newmsg)
4836-
intf->handlers->sender(intf->send_info, newmsg);
4836+
if (newmsg) {
4837+
cc = intf->handlers->sender(intf->send_info, newmsg);
4838+
if (cc) {
4839+
if (newmsg->user_data)
4840+
deliver_err_response(intf,
4841+
newmsg->user_data, cc);
4842+
else
4843+
ipmi_free_smi_msg(newmsg);
4844+
goto restart;
4845+
}
4846+
}
48374847

48384848
handle_new_recv_msgs(intf);
48394849

drivers/char/ipmi/ipmi_powernv.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ static void send_error_reply(struct ipmi_smi_powernv *smi,
5151
ipmi_smi_msg_received(smi->intf, msg);
5252
}
5353

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)
5555
{
5656
struct ipmi_smi_powernv *smi = send_info;
5757
struct opal_ipmi_msg *opal_msg;
@@ -93,18 +93,19 @@ static void ipmi_powernv_send(void *send_info, struct ipmi_smi_msg *msg)
9393
smi->interface_id, opal_msg, size);
9494
rc = opal_ipmi_send(smi->interface_id, opal_msg, size);
9595
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;
10199
}
102100

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+
104105
err_unlock:
105106
spin_unlock_irqrestore(&smi->msg_lock, flags);
106107
err:
107-
send_error_reply(smi, msg, comp);
108+
return comp;
108109
}
109110

110111
static int ipmi_powernv_recv(struct ipmi_smi_powernv *smi)

drivers/char/ipmi/ipmi_si_intf.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -809,8 +809,6 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
809809
* this if there is not yet an upper layer to handle anything.
810810
*/
811811
if (si_sm_result == SI_SM_ATTN || smi_info->got_attn) {
812-
unsigned char msg[2];
813-
814812
if (smi_info->si_state != SI_NORMAL) {
815813
/*
816814
* We got an ATTN, but we are doing something else.
@@ -907,8 +905,7 @@ static void flush_messages(void *send_info)
907905
}
908906
}
909907

910-
static void sender(void *send_info,
911-
struct ipmi_smi_msg *msg)
908+
static int sender(void *send_info, struct ipmi_smi_msg *msg)
912909
{
913910
struct smi_info *smi_info = send_info;
914911
unsigned long flags;
@@ -921,7 +918,7 @@ static void sender(void *send_info,
921918
* layer will call flush_messages to clear it out.
922919
*/
923920
smi_info->waiting_msg = msg;
924-
return;
921+
return IPMI_CC_NO_ERROR;
925922
}
926923

927924
spin_lock_irqsave(&smi_info->si_lock, flags);
@@ -936,6 +933,7 @@ static void sender(void *send_info,
936933
smi_info->waiting_msg = msg;
937934
check_start_timer_thread(smi_info);
938935
spin_unlock_irqrestore(&smi_info->si_lock, flags);
936+
return IPMI_CC_NO_ERROR;
939937
}
940938

941939
static void set_run_to_completion(void *send_info, bool i_run_to_completion)

drivers/char/ipmi/ipmi_ssif.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1068,8 +1068,7 @@ static void start_next_msg(struct ssif_info *ssif_info, unsigned long *flags)
10681068
}
10691069
}
10701070

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)
10731072
{
10741073
struct ssif_info *ssif_info = send_info;
10751074
unsigned long oflags, *flags;
@@ -1089,6 +1088,7 @@ static void sender(void *send_info,
10891088
msg->data[0], msg->data[1],
10901089
(long long)t.tv_sec, (long)t.tv_nsec / NSEC_PER_USEC);
10911090
}
1091+
return IPMI_CC_NO_ERROR;
10921092
}
10931093

10941094
static int get_smi_info(void *send_info, struct ipmi_smi_info *data)

include/linux/ipmi_smi.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ struct ipmi_smi_msg {
109109

110110
enum ipmi_smi_msg_type type;
111111

112-
long msgid;
113-
void *user_data;
112+
long msgid;
113+
void *user_data;
114114

115115
int data_size;
116116
unsigned char data[IPMI_MAX_MSG_LENGTH];
@@ -168,9 +168,11 @@ struct ipmi_smi_handlers {
168168
* are held when this is run. Message are delivered one at
169169
* a time by the message handler, a new message will not be
170170
* 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.
171174
*/
172-
void (*sender)(void *send_info,
173-
struct ipmi_smi_msg *msg);
175+
int (*sender)(void *send_info, struct ipmi_smi_msg *msg);
174176

175177
/*
176178
* Called by the upper layer to request that we try to get

0 commit comments

Comments
 (0)