Commit 9cf93a8f authored by Corey Minyard's avatar Corey Minyard
Browse files

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: default avatarCorey Minyard <corey@minyard.net>
parent abe4918a
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -404,8 +404,7 @@ static void ipmi_ipmb_shutdown(void *send_info)
	ipmi_ipmb_stop_thread(iidev);
}

static void ipmi_ipmb_sender(void *send_info,
			     struct ipmi_smi_msg *msg)
static int ipmi_ipmb_sender(void *send_info, struct ipmi_smi_msg *msg)
{
	struct ipmi_ipmb_dev *iidev = send_info;
	unsigned long flags;
@@ -417,6 +416,7 @@ static void ipmi_ipmb_sender(void *send_info,
	spin_unlock_irqrestore(&iidev->lock, flags);

	up(&iidev->wake_thread);
	return IPMI_CC_NO_ERROR;
}

static void ipmi_ipmb_request_events(void *send_info)
+13 −3
Original line number Diff line number Diff line
@@ -4803,6 +4803,7 @@ static void smi_work(struct work_struct *t)
	int run_to_completion = READ_ONCE(intf->run_to_completion);
	struct ipmi_smi_msg *newmsg = NULL;
	struct ipmi_recv_msg *msg, *msg2;
	int cc;

	/*
	 * 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
	 * message delivery.
	 */

restart:
	if (!run_to_completion)
		spin_lock_irqsave(&intf->xmit_msgs_lock, flags);
	if (intf->curr_msg == NULL && !intf->in_shutdown) {
@@ -4832,8 +4833,17 @@ static void smi_work(struct work_struct *t)
	if (!run_to_completion)
		spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags);

	if (newmsg)
		intf->handlers->sender(intf->send_info, newmsg);
	if (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);

+9 −8
Original line number Diff line number Diff line
@@ -51,7 +51,7 @@ static void send_error_reply(struct ipmi_smi_powernv *smi,
	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 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);
	rc = opal_ipmi_send(smi->interface_id, opal_msg, size);
	pr_devel("%s:  -> %d\n", __func__, rc);
	if (rc) {
		comp = IPMI_ERR_UNSPECIFIED;
		goto err_unlock;
	}

	if (!rc) {
	smi->cur_msg = msg;
	spin_unlock_irqrestore(&smi->msg_lock, flags);
		return;
	}
	return IPMI_CC_NO_ERROR;

	comp = IPMI_ERR_UNSPECIFIED;
err_unlock:
	spin_unlock_irqrestore(&smi->msg_lock, flags);
err:
	send_error_reply(smi, msg, comp);
	return comp;
}

static int ipmi_powernv_recv(struct ipmi_smi_powernv *smi)
+3 −5
Original line number Diff line number Diff line
@@ -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.
	 */
	if (si_sm_result == SI_SM_ATTN || smi_info->got_attn) {
		unsigned char msg[2];

		if (smi_info->si_state != SI_NORMAL) {
			/*
			 * 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,
		   struct ipmi_smi_msg *msg)
static int sender(void *send_info, struct ipmi_smi_msg *msg)
{
	struct smi_info   *smi_info = send_info;
	unsigned long     flags;
@@ -921,7 +918,7 @@ static void sender(void *send_info,
		 * layer will call flush_messages to clear it out.
		 */
		smi_info->waiting_msg = msg;
		return;
		return IPMI_CC_NO_ERROR;
	}

	spin_lock_irqsave(&smi_info->si_lock, flags);
@@ -936,6 +933,7 @@ static void sender(void *send_info,
	smi_info->waiting_msg = msg;
	check_start_timer_thread(smi_info);
	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)
+2 −2
Original line number Diff line number Diff line
@@ -1068,8 +1068,7 @@ static void start_next_msg(struct ssif_info *ssif_info, unsigned long *flags)
	}
}

static void sender(void                *send_info,
		   struct ipmi_smi_msg *msg)
static int sender(void *send_info, struct ipmi_smi_msg *msg)
{
	struct ssif_info *ssif_info = send_info;
	unsigned long oflags, *flags;
@@ -1089,6 +1088,7 @@ static void sender(void *send_info,
			msg->data[0], msg->data[1],
			(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)
Loading