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.

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.

Reported-by: Matt Fleming <[email protected]>
Closes: 
https://lore.kernel.org/lkml/[email protected]/
Fixes: <1da177e4c3f4> ("Linux-2.6.12-rc2")
Cc: [email protected]
Signed-off-by: Corey Minyard <[email protected]>
---
 drivers/char/ipmi/ipmi_si_intf.c | 15 +++++++++++++++
 drivers/char/ipmi/ipmi_ssif.c    | 15 +++++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 08c208cc64c5..a705aae29867 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -168,6 +168,9 @@ struct smi_info {
                             OEM2_DATA_AVAIL)
        unsigned char       msg_flags;
 
+       /* When requesting events and messages, don't do it forever. */
+       unsigned int        num_requests_in_a_row;
+
        /* Does the BMC have an event buffer? */
        bool                has_event_buffer;
 
@@ -410,6 +413,7 @@ static void start_getting_msg_queue(struct smi_info 
*smi_info)
 
        start_new_msg(smi_info, smi_info->curr_msg->data,
                      smi_info->curr_msg->data_size);
+       smi_info->num_requests_in_a_row = 0;
        smi_info->si_state = SI_GETTING_MESSAGES;
 }
 
@@ -421,6 +425,7 @@ static void start_getting_events(struct smi_info *smi_info)
 
        start_new_msg(smi_info, smi_info->curr_msg->data,
                      smi_info->curr_msg->data_size);
+       smi_info->num_requests_in_a_row = 0;
        smi_info->si_state = SI_GETTING_EVENTS;
 }
 
@@ -646,6 +651,11 @@ static void handle_transaction_done(struct smi_info 
*smi_info)
                } else {
                        smi_inc_stat(smi_info, events);
 
+                       smi_info->num_requests_in_a_row++;
+                       if (smi_info->num_requests_in_a_row > 10)
+                               /* Stop if we do this too many times. */
+                               smi_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL;
+
                        /*
                         * Do this before we deliver the message
                         * because delivering the message releases the
@@ -684,6 +694,11 @@ static void handle_transaction_done(struct smi_info 
*smi_info)
                } else {
                        smi_inc_stat(smi_info, incoming_messages);
 
+                       smi_info->num_requests_in_a_row++;
+                       if (smi_info->num_requests_in_a_row > 10)
+                               /* Stop if we do this too many times. */
+                               smi_info->msg_flags &= ~RECEIVE_MSG_AVAIL;
+
                        /*
                         * Do this before we deliver the message
                         * because delivering the message releases the
diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c
index b49500a1bd36..547447f304ba 100644
--- a/drivers/char/ipmi/ipmi_ssif.c
+++ b/drivers/char/ipmi/ipmi_ssif.c
@@ -225,6 +225,9 @@ struct ssif_info {
        bool                has_event_buffer;
        bool                supports_alert;
 
+       /* When requesting events and messages, don't do it forever. */
+       unsigned int        num_requests_in_a_row;
+
        /*
         * Used to tell what we should do with alerts.  If we are
         * waiting on a response, read the data immediately.
@@ -413,6 +416,7 @@ static void start_event_fetch(struct ssif_info *ssif_info, 
unsigned long *flags)
        }
 
        ssif_info->curr_msg = msg;
+       ssif_info->num_requests_in_a_row = 0;
        ssif_info->ssif_state = SSIF_GETTING_EVENTS;
        ipmi_ssif_unlock_cond(ssif_info, flags);
 
@@ -436,6 +440,7 @@ static void start_recv_msg_fetch(struct ssif_info 
*ssif_info,
        }
 
        ssif_info->curr_msg = msg;
+       ssif_info->num_requests_in_a_row = 0;
        ssif_info->ssif_state = SSIF_GETTING_MESSAGES;
        ipmi_ssif_unlock_cond(ssif_info, flags);
 
@@ -843,6 +848,11 @@ static void msg_done_handler(struct ssif_info *ssif_info, 
int result,
                        ssif_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL;
                        handle_flags(ssif_info, flags);
                } else {
+                       ssif_info->num_requests_in_a_row++;
+                       if (ssif_info->num_requests_in_a_row > 10)
+                               /* Stop if we do this too many times. */
+                               ssif_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL;
+
                        handle_flags(ssif_info, flags);
                        ssif_inc_stat(ssif_info, events);
                        deliver_recv_msg(ssif_info, msg);
@@ -876,6 +886,11 @@ static void msg_done_handler(struct ssif_info *ssif_info, 
int result,
                        ssif_info->msg_flags &= ~RECEIVE_MSG_AVAIL;
                        handle_flags(ssif_info, flags);
                } else {
+                       ssif_info->num_requests_in_a_row++;
+                       if (ssif_info->num_requests_in_a_row > 10)
+                               /* Stop if we do this too many times. */
+                               ssif_info->msg_flags &= ~RECEIVE_MSG_AVAIL;
+
                        ssif_inc_stat(ssif_info, incoming_messages);
                        handle_flags(ssif_info, flags);
                        deliver_recv_msg(ssif_info, msg);
-- 
2.43.0



_______________________________________________
Openipmi-developer mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openipmi-developer

Reply via email to