Skip to content

Commit e5feb03

Browse files
committed
ipmi: Differentiate between reset and firmware update in maintenance
This allows later changes to have different behaviour during a reset verses a firmware update. Signed-off-by: Corey Minyard <corey@minyard.net> Tested-by: Frederick Lawler <fred@cloudflare.com>
1 parent 121f4a7 commit e5feb03

1 file changed

Lines changed: 30 additions & 12 deletions

File tree

drivers/char/ipmi/ipmi_msghandler.c

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,11 @@ struct ipmi_smi {
541541

542542
/* For handling of maintenance mode. */
543543
int maintenance_mode;
544-
bool maintenance_mode_enable;
544+
545+
#define IPMI_MAINTENANCE_MODE_STATE_OFF 0
546+
#define IPMI_MAINTENANCE_MODE_STATE_FIRMWARE 1
547+
#define IPMI_MAINTENANCE_MODE_STATE_RESET 2
548+
int maintenance_mode_state;
545549
int auto_maintenance_timeout;
546550
spinlock_t maintenance_mode_lock; /* Used in a timer... */
547551

@@ -1530,8 +1534,15 @@ EXPORT_SYMBOL(ipmi_get_maintenance_mode);
15301534
static void maintenance_mode_update(struct ipmi_smi *intf)
15311535
{
15321536
if (intf->handlers->set_maintenance_mode)
1537+
/*
1538+
* Lower level drivers only care about firmware mode
1539+
* as it affects their timing. They don't care about
1540+
* reset, which disables all commands for a while.
1541+
*/
15331542
intf->handlers->set_maintenance_mode(
1534-
intf->send_info, intf->maintenance_mode_enable);
1543+
intf->send_info,
1544+
(intf->maintenance_mode_state ==
1545+
IPMI_MAINTENANCE_MODE_STATE_FIRMWARE));
15351546
}
15361547

15371548
int ipmi_set_maintenance_mode(struct ipmi_user *user, int mode)
@@ -1548,16 +1559,17 @@ int ipmi_set_maintenance_mode(struct ipmi_user *user, int mode)
15481559
if (intf->maintenance_mode != mode) {
15491560
switch (mode) {
15501561
case IPMI_MAINTENANCE_MODE_AUTO:
1551-
intf->maintenance_mode_enable
1552-
= (intf->auto_maintenance_timeout > 0);
1562+
/* Just leave it alone. */
15531563
break;
15541564

15551565
case IPMI_MAINTENANCE_MODE_OFF:
1556-
intf->maintenance_mode_enable = false;
1566+
intf->maintenance_mode_state =
1567+
IPMI_MAINTENANCE_MODE_STATE_OFF;
15571568
break;
15581569

15591570
case IPMI_MAINTENANCE_MODE_ON:
1560-
intf->maintenance_mode_enable = true;
1571+
intf->maintenance_mode_state =
1572+
IPMI_MAINTENANCE_MODE_STATE_FIRMWARE;
15611573
break;
15621574

15631575
default:
@@ -1917,13 +1929,18 @@ static int i_ipmi_req_sysintf(struct ipmi_smi *intf,
19171929

19181930
if (is_maintenance_mode_cmd(msg)) {
19191931
unsigned long flags;
1932+
int newst;
1933+
1934+
if (msg->netfn == IPMI_NETFN_FIRMWARE_REQUEST)
1935+
newst = IPMI_MAINTENANCE_MODE_STATE_FIRMWARE;
1936+
else
1937+
newst = IPMI_MAINTENANCE_MODE_STATE_RESET;
19201938

19211939
spin_lock_irqsave(&intf->maintenance_mode_lock, flags);
1922-
intf->auto_maintenance_timeout
1923-
= maintenance_mode_timeout_ms;
1940+
intf->auto_maintenance_timeout = maintenance_mode_timeout_ms;
19241941
if (!intf->maintenance_mode
1925-
&& !intf->maintenance_mode_enable) {
1926-
intf->maintenance_mode_enable = true;
1942+
&& intf->maintenance_mode_state < newst) {
1943+
intf->maintenance_mode_state = newst;
19271944
maintenance_mode_update(intf);
19281945
}
19291946
spin_unlock_irqrestore(&intf->maintenance_mode_lock,
@@ -5028,7 +5045,8 @@ static bool ipmi_timeout_handler(struct ipmi_smi *intf,
50285045
-= timeout_period;
50295046
if (!intf->maintenance_mode
50305047
&& (intf->auto_maintenance_timeout <= 0)) {
5031-
intf->maintenance_mode_enable = false;
5048+
intf->maintenance_mode_state =
5049+
IPMI_MAINTENANCE_MODE_STATE_OFF;
50325050
maintenance_mode_update(intf);
50335051
}
50345052
}
@@ -5044,7 +5062,7 @@ static bool ipmi_timeout_handler(struct ipmi_smi *intf,
50445062
static void ipmi_request_event(struct ipmi_smi *intf)
50455063
{
50465064
/* No event requests when in maintenance mode. */
5047-
if (intf->maintenance_mode_enable)
5065+
if (intf->maintenance_mode_state)
50485066
return;
50495067

50505068
if (!intf->in_shutdown)

0 commit comments

Comments
 (0)