mirror of
https://github.com/torvalds/linux.git
synced 2026-06-02 19:43:40 +02:00
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>
This commit is contained in:
parent
abe4918a94
commit
9cf93a8fa9
|
|
@ -404,8 +404,7 @@ static void ipmi_ipmb_shutdown(void *send_info)
|
||||||
ipmi_ipmb_stop_thread(iidev);
|
ipmi_ipmb_stop_thread(iidev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ipmi_ipmb_sender(void *send_info,
|
static int ipmi_ipmb_sender(void *send_info, struct ipmi_smi_msg *msg)
|
||||||
struct ipmi_smi_msg *msg)
|
|
||||||
{
|
{
|
||||||
struct ipmi_ipmb_dev *iidev = send_info;
|
struct ipmi_ipmb_dev *iidev = send_info;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
@ -417,6 +416,7 @@ static void ipmi_ipmb_sender(void *send_info,
|
||||||
spin_unlock_irqrestore(&iidev->lock, flags);
|
spin_unlock_irqrestore(&iidev->lock, flags);
|
||||||
|
|
||||||
up(&iidev->wake_thread);
|
up(&iidev->wake_thread);
|
||||||
|
return IPMI_CC_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ipmi_ipmb_request_events(void *send_info)
|
static void ipmi_ipmb_request_events(void *send_info)
|
||||||
|
|
|
||||||
|
|
@ -4803,6 +4803,7 @@ static void smi_work(struct work_struct *t)
|
||||||
int run_to_completion = READ_ONCE(intf->run_to_completion);
|
int run_to_completion = READ_ONCE(intf->run_to_completion);
|
||||||
struct ipmi_smi_msg *newmsg = NULL;
|
struct ipmi_smi_msg *newmsg = NULL;
|
||||||
struct ipmi_recv_msg *msg, *msg2;
|
struct ipmi_recv_msg *msg, *msg2;
|
||||||
|
int cc;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Start the next message if available.
|
* Start the next message if available.
|
||||||
|
|
@ -4811,7 +4812,7 @@ static void smi_work(struct work_struct *t)
|
||||||
* because the lower layer is allowed to hold locks while calling
|
* because the lower layer is allowed to hold locks while calling
|
||||||
* message delivery.
|
* message delivery.
|
||||||
*/
|
*/
|
||||||
|
restart:
|
||||||
if (!run_to_completion)
|
if (!run_to_completion)
|
||||||
spin_lock_irqsave(&intf->xmit_msgs_lock, flags);
|
spin_lock_irqsave(&intf->xmit_msgs_lock, flags);
|
||||||
if (intf->curr_msg == NULL && !intf->in_shutdown) {
|
if (intf->curr_msg == NULL && !intf->in_shutdown) {
|
||||||
|
|
@ -4832,8 +4833,17 @@ static void smi_work(struct work_struct *t)
|
||||||
if (!run_to_completion)
|
if (!run_to_completion)
|
||||||
spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags);
|
spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags);
|
||||||
|
|
||||||
if (newmsg)
|
if (newmsg) {
|
||||||
intf->handlers->sender(intf->send_info, newmsg);
|
cc = intf->handlers->sender(intf->send_info, newmsg);
|
||||||
|
if (cc) {
|
||||||
|
if (newmsg->user_data)
|
||||||
|
deliver_err_response(intf,
|
||||||
|
newmsg->user_data, cc);
|
||||||
|
else
|
||||||
|
ipmi_free_smi_msg(newmsg);
|
||||||
|
goto restart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
handle_new_recv_msgs(intf);
|
handle_new_recv_msgs(intf);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ static void send_error_reply(struct ipmi_smi_powernv *smi,
|
||||||
ipmi_smi_msg_received(smi->intf, msg);
|
ipmi_smi_msg_received(smi->intf, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ipmi_powernv_send(void *send_info, struct ipmi_smi_msg *msg)
|
static int ipmi_powernv_send(void *send_info, struct ipmi_smi_msg *msg)
|
||||||
{
|
{
|
||||||
struct ipmi_smi_powernv *smi = send_info;
|
struct ipmi_smi_powernv *smi = send_info;
|
||||||
struct opal_ipmi_msg *opal_msg;
|
struct opal_ipmi_msg *opal_msg;
|
||||||
|
|
@ -93,18 +93,19 @@ static void ipmi_powernv_send(void *send_info, struct ipmi_smi_msg *msg)
|
||||||
smi->interface_id, opal_msg, size);
|
smi->interface_id, opal_msg, size);
|
||||||
rc = opal_ipmi_send(smi->interface_id, opal_msg, size);
|
rc = opal_ipmi_send(smi->interface_id, opal_msg, size);
|
||||||
pr_devel("%s: -> %d\n", __func__, rc);
|
pr_devel("%s: -> %d\n", __func__, rc);
|
||||||
|
if (rc) {
|
||||||
if (!rc) {
|
comp = IPMI_ERR_UNSPECIFIED;
|
||||||
smi->cur_msg = msg;
|
goto err_unlock;
|
||||||
spin_unlock_irqrestore(&smi->msg_lock, flags);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
comp = IPMI_ERR_UNSPECIFIED;
|
smi->cur_msg = msg;
|
||||||
|
spin_unlock_irqrestore(&smi->msg_lock, flags);
|
||||||
|
return IPMI_CC_NO_ERROR;
|
||||||
|
|
||||||
err_unlock:
|
err_unlock:
|
||||||
spin_unlock_irqrestore(&smi->msg_lock, flags);
|
spin_unlock_irqrestore(&smi->msg_lock, flags);
|
||||||
err:
|
err:
|
||||||
send_error_reply(smi, msg, comp);
|
return comp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ipmi_powernv_recv(struct ipmi_smi_powernv *smi)
|
static int ipmi_powernv_recv(struct ipmi_smi_powernv *smi)
|
||||||
|
|
|
||||||
|
|
@ -809,8 +809,6 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
|
||||||
* this if there is not yet an upper layer to handle anything.
|
* this if there is not yet an upper layer to handle anything.
|
||||||
*/
|
*/
|
||||||
if (si_sm_result == SI_SM_ATTN || smi_info->got_attn) {
|
if (si_sm_result == SI_SM_ATTN || smi_info->got_attn) {
|
||||||
unsigned char msg[2];
|
|
||||||
|
|
||||||
if (smi_info->si_state != SI_NORMAL) {
|
if (smi_info->si_state != SI_NORMAL) {
|
||||||
/*
|
/*
|
||||||
* We got an ATTN, but we are doing something else.
|
* We got an ATTN, but we are doing something else.
|
||||||
|
|
@ -907,8 +905,7 @@ static void flush_messages(void *send_info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sender(void *send_info,
|
static int sender(void *send_info, struct ipmi_smi_msg *msg)
|
||||||
struct ipmi_smi_msg *msg)
|
|
||||||
{
|
{
|
||||||
struct smi_info *smi_info = send_info;
|
struct smi_info *smi_info = send_info;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
@ -921,7 +918,7 @@ static void sender(void *send_info,
|
||||||
* layer will call flush_messages to clear it out.
|
* layer will call flush_messages to clear it out.
|
||||||
*/
|
*/
|
||||||
smi_info->waiting_msg = msg;
|
smi_info->waiting_msg = msg;
|
||||||
return;
|
return IPMI_CC_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&smi_info->si_lock, flags);
|
spin_lock_irqsave(&smi_info->si_lock, flags);
|
||||||
|
|
@ -936,6 +933,7 @@ static void sender(void *send_info,
|
||||||
smi_info->waiting_msg = msg;
|
smi_info->waiting_msg = msg;
|
||||||
check_start_timer_thread(smi_info);
|
check_start_timer_thread(smi_info);
|
||||||
spin_unlock_irqrestore(&smi_info->si_lock, flags);
|
spin_unlock_irqrestore(&smi_info->si_lock, flags);
|
||||||
|
return IPMI_CC_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_run_to_completion(void *send_info, bool i_run_to_completion)
|
static void set_run_to_completion(void *send_info, bool i_run_to_completion)
|
||||||
|
|
|
||||||
|
|
@ -1068,8 +1068,7 @@ static void start_next_msg(struct ssif_info *ssif_info, unsigned long *flags)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sender(void *send_info,
|
static int sender(void *send_info, struct ipmi_smi_msg *msg)
|
||||||
struct ipmi_smi_msg *msg)
|
|
||||||
{
|
{
|
||||||
struct ssif_info *ssif_info = send_info;
|
struct ssif_info *ssif_info = send_info;
|
||||||
unsigned long oflags, *flags;
|
unsigned long oflags, *flags;
|
||||||
|
|
@ -1089,6 +1088,7 @@ static void sender(void *send_info,
|
||||||
msg->data[0], msg->data[1],
|
msg->data[0], msg->data[1],
|
||||||
(long long)t.tv_sec, (long)t.tv_nsec / NSEC_PER_USEC);
|
(long long)t.tv_sec, (long)t.tv_nsec / NSEC_PER_USEC);
|
||||||
}
|
}
|
||||||
|
return IPMI_CC_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_smi_info(void *send_info, struct ipmi_smi_info *data)
|
static int get_smi_info(void *send_info, struct ipmi_smi_info *data)
|
||||||
|
|
|
||||||
|
|
@ -168,9 +168,11 @@ struct ipmi_smi_handlers {
|
||||||
* are held when this is run. Message are delivered one at
|
* are held when this is run. Message are delivered one at
|
||||||
* a time by the message handler, a new message will not be
|
* a time by the message handler, a new message will not be
|
||||||
* delivered until the previous message is returned.
|
* delivered until the previous message is returned.
|
||||||
|
*
|
||||||
|
* This can return an error if the SMI is not in a state where it
|
||||||
|
* can send a message.
|
||||||
*/
|
*/
|
||||||
void (*sender)(void *send_info,
|
int (*sender)(void *send_info, struct ipmi_smi_msg *msg);
|
||||||
struct ipmi_smi_msg *msg);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called by the upper layer to request that we try to get
|
* Called by the upper layer to request that we try to get
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user