Skip to content

Commit 67c44e0

Browse files
cminyardgregkh
authored andcommitted
ipmi: Add limits to event and receive message requests
commit c4cca23 upstream. The driver would just fetch events and receive messages until the BMC said it was done. To avoid issues with BMCs that never say they are done, add a limit of 10 fetches at a time. In addition, an si interface has an attn state it can return from the hardware which is supposed to cause a flag fetch to see if the driver needs to fetch events or message or a few other things. If the attn bit gets stuck, it's a similar problem. So allow messages in between flag fetches so the driver itself doesn't get stuck. This is a more general fix than the previous fix for the specific bad BMC, but should fix the more general issue of a BMC that won't stop saying it has data. This has been there from the beginning of the driver. It's not a bug per-se, but it is accounting for bugs in BMCs. Reported-by: Matt Fleming <mfleming@cloudflare.com> Closes: https://lore.kernel.org/lkml/20260415115930.3428942-1-matt@readmodwrite.com/ Fixes: <1da177e4c3f4> ("Linux-2.6.12-rc2") Cc: stable@vger.kernel.org Signed-off-by: Corey Minyard <corey@minyard.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 1f678d1 commit 67c44e0

2 files changed

Lines changed: 64 additions & 13 deletions

File tree

drivers/char/ipmi/ipmi_si_intf.c

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,10 @@ struct smi_info {
162162
OEM2_DATA_AVAIL)
163163
unsigned char msg_flags;
164164

165+
/* When requesting events and messages, don't do it forever. */
166+
unsigned int num_requests_in_a_row;
167+
bool last_was_flag_fetch;
168+
165169
/* Does the BMC have an event buffer? */
166170
bool has_event_buffer;
167171

@@ -394,7 +398,10 @@ static void start_getting_msg_queue(struct smi_info *smi_info)
394398

395399
start_new_msg(smi_info, smi_info->curr_msg->data,
396400
smi_info->curr_msg->data_size);
397-
smi_info->si_state = SI_GETTING_MESSAGES;
401+
if (smi_info->si_state != SI_GETTING_MESSAGES) {
402+
smi_info->num_requests_in_a_row = 0;
403+
smi_info->si_state = SI_GETTING_MESSAGES;
404+
}
398405
}
399406

400407
static void start_getting_events(struct smi_info *smi_info)
@@ -405,7 +412,10 @@ static void start_getting_events(struct smi_info *smi_info)
405412

406413
start_new_msg(smi_info, smi_info->curr_msg->data,
407414
smi_info->curr_msg->data_size);
408-
smi_info->si_state = SI_GETTING_EVENTS;
415+
if (smi_info->si_state != SI_GETTING_EVENTS) {
416+
smi_info->num_requests_in_a_row = 0;
417+
smi_info->si_state = SI_GETTING_EVENTS;
418+
}
409419
}
410420

411421
/*
@@ -579,6 +589,7 @@ static void handle_transaction_done(struct smi_info *smi_info)
579589
smi_info->si_state = SI_NORMAL;
580590
} else {
581591
smi_info->msg_flags = msg[3];
592+
smi_info->last_was_flag_fetch = true;
582593
handle_flags(smi_info);
583594
}
584595
break;
@@ -624,6 +635,11 @@ static void handle_transaction_done(struct smi_info *smi_info)
624635
} else {
625636
smi_inc_stat(smi_info, events);
626637

638+
smi_info->num_requests_in_a_row++;
639+
if (smi_info->num_requests_in_a_row > 10)
640+
/* Stop if we do this too many times. */
641+
smi_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL;
642+
627643
/*
628644
* Do this before we deliver the message
629645
* because delivering the message releases the
@@ -662,6 +678,11 @@ static void handle_transaction_done(struct smi_info *smi_info)
662678
} else {
663679
smi_inc_stat(smi_info, incoming_messages);
664680

681+
smi_info->num_requests_in_a_row++;
682+
if (smi_info->num_requests_in_a_row > 10)
683+
/* Stop if we do this too many times. */
684+
smi_info->msg_flags &= ~RECEIVE_MSG_AVAIL;
685+
665686
/*
666687
* Do this before we deliver the message
667688
* because delivering the message releases the
@@ -789,6 +810,26 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
789810
goto restart;
790811
}
791812

813+
/*
814+
* If we are currently idle, or if the last thing that was
815+
* done was a flag fetch and there is a message pending, try
816+
* to start the next message.
817+
*
818+
* We do the waiting message check to avoid a stuck flag
819+
* completely wedging the driver. Let a message through
820+
* in between flag operations if that happens.
821+
*/
822+
if (si_sm_result == SI_SM_IDLE ||
823+
(si_sm_result == SI_SM_ATTN && smi_info->waiting_msg &&
824+
smi_info->last_was_flag_fetch)) {
825+
smi_info->last_was_flag_fetch = false;
826+
smi_inc_stat(smi_info, idles);
827+
828+
si_sm_result = start_next_msg(smi_info);
829+
if (si_sm_result != SI_SM_IDLE)
830+
goto restart;
831+
}
832+
792833
/*
793834
* We prefer handling attn over new messages. But don't do
794835
* this if there is not yet an upper layer to handle anything.
@@ -822,15 +863,6 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
822863
}
823864
}
824865

825-
/* If we are currently idle, try to start the next message. */
826-
if (si_sm_result == SI_SM_IDLE) {
827-
smi_inc_stat(smi_info, idles);
828-
829-
si_sm_result = start_next_msg(smi_info);
830-
if (si_sm_result != SI_SM_IDLE)
831-
goto restart;
832-
}
833-
834866
if ((si_sm_result == SI_SM_IDLE)
835867
&& (atomic_read(&smi_info->req_events))) {
836868
/*

drivers/char/ipmi/ipmi_ssif.c

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,9 @@ struct ssif_info {
225225
bool has_event_buffer;
226226
bool supports_alert;
227227

228+
/* When requesting events and messages, don't do it forever. */
229+
unsigned int num_requests_in_a_row;
230+
228231
/*
229232
* Used to tell what we should do with alerts. If we are
230233
* waiting on a response, read the data immediately.
@@ -413,7 +416,10 @@ static void start_event_fetch(struct ssif_info *ssif_info, unsigned long *flags)
413416
}
414417

415418
ssif_info->curr_msg = msg;
416-
ssif_info->ssif_state = SSIF_GETTING_EVENTS;
419+
if (ssif_info->ssif_state != SSIF_GETTING_EVENTS) {
420+
ssif_info->num_requests_in_a_row = 0;
421+
ssif_info->ssif_state = SSIF_GETTING_EVENTS;
422+
}
417423
ipmi_ssif_unlock_cond(ssif_info, flags);
418424

419425
msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);
@@ -436,7 +442,10 @@ static void start_recv_msg_fetch(struct ssif_info *ssif_info,
436442
}
437443

438444
ssif_info->curr_msg = msg;
439-
ssif_info->ssif_state = SSIF_GETTING_MESSAGES;
445+
if (ssif_info->ssif_state != SSIF_GETTING_MESSAGES) {
446+
ssif_info->num_requests_in_a_row = 0;
447+
ssif_info->ssif_state = SSIF_GETTING_MESSAGES;
448+
}
440449
ipmi_ssif_unlock_cond(ssif_info, flags);
441450

442451
msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);
@@ -843,6 +852,11 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
843852
ssif_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL;
844853
handle_flags(ssif_info, flags);
845854
} else {
855+
ssif_info->num_requests_in_a_row++;
856+
if (ssif_info->num_requests_in_a_row > 10)
857+
/* Stop if we do this too many times. */
858+
ssif_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL;
859+
846860
handle_flags(ssif_info, flags);
847861
ssif_inc_stat(ssif_info, events);
848862
deliver_recv_msg(ssif_info, msg);
@@ -876,6 +890,11 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
876890
ssif_info->msg_flags &= ~RECEIVE_MSG_AVAIL;
877891
handle_flags(ssif_info, flags);
878892
} else {
893+
ssif_info->num_requests_in_a_row++;
894+
if (ssif_info->num_requests_in_a_row > 10)
895+
/* Stop if we do this too many times. */
896+
ssif_info->msg_flags &= ~RECEIVE_MSG_AVAIL;
897+
879898
ssif_inc_stat(ssif_info, incoming_messages);
880899
handle_flags(ssif_info, flags);
881900
deliver_recv_msg(ssif_info, msg);

0 commit comments

Comments
 (0)