@@ -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);
15301534static 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
15371548int 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,
50445062static 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