Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

+30 -12
+30 -12
drivers/char/ipmi/ipmi_msghandler.c
··· 541 541 542 542 /* For handling of maintenance mode. */ 543 543 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; 545 549 int auto_maintenance_timeout; 546 550 spinlock_t maintenance_mode_lock; /* Used in a timer... */ 547 551 ··· 1534 1530 static void maintenance_mode_update(struct ipmi_smi *intf) 1535 1531 { 1536 1532 if (intf->handlers->set_maintenance_mode) 1533 + /* 1534 + * Lower level drivers only care about firmware mode 1535 + * as it affects their timing. They don't care about 1536 + * reset, which disables all commands for a while. 1537 + */ 1537 1538 intf->handlers->set_maintenance_mode( 1538 - intf->send_info, intf->maintenance_mode_enable); 1539 + intf->send_info, 1540 + (intf->maintenance_mode_state == 1541 + IPMI_MAINTENANCE_MODE_STATE_FIRMWARE)); 1539 1542 } 1540 1543 1541 1544 int ipmi_set_maintenance_mode(struct ipmi_user *user, int mode) ··· 1559 1548 if (intf->maintenance_mode != mode) { 1560 1549 switch (mode) { 1561 1550 case IPMI_MAINTENANCE_MODE_AUTO: 1562 - intf->maintenance_mode_enable 1563 - = (intf->auto_maintenance_timeout > 0); 1551 + /* Just leave it alone. */ 1564 1552 break; 1565 1553 1566 1554 case IPMI_MAINTENANCE_MODE_OFF: 1567 - intf->maintenance_mode_enable = false; 1555 + intf->maintenance_mode_state = 1556 + IPMI_MAINTENANCE_MODE_STATE_OFF; 1568 1557 break; 1569 1558 1570 1559 case IPMI_MAINTENANCE_MODE_ON: 1571 - intf->maintenance_mode_enable = true; 1560 + intf->maintenance_mode_state = 1561 + IPMI_MAINTENANCE_MODE_STATE_FIRMWARE; 1572 1562 break; 1573 1563 1574 1564 default: ··· 1929 1917 1930 1918 if (is_maintenance_mode_cmd(msg)) { 1931 1919 unsigned long flags; 1920 + int newst; 1921 + 1922 + if (msg->netfn == IPMI_NETFN_FIRMWARE_REQUEST) 1923 + newst = IPMI_MAINTENANCE_MODE_STATE_FIRMWARE; 1924 + else 1925 + newst = IPMI_MAINTENANCE_MODE_STATE_RESET; 1932 1926 1933 1927 spin_lock_irqsave(&intf->maintenance_mode_lock, flags); 1934 - intf->auto_maintenance_timeout 1935 - = maintenance_mode_timeout_ms; 1928 + intf->auto_maintenance_timeout = maintenance_mode_timeout_ms; 1936 1929 if (!intf->maintenance_mode 1937 - && !intf->maintenance_mode_enable) { 1938 - intf->maintenance_mode_enable = true; 1930 + && intf->maintenance_mode_state < newst) { 1931 + intf->maintenance_mode_state = newst; 1939 1932 maintenance_mode_update(intf); 1940 1933 } 1941 1934 spin_unlock_irqrestore(&intf->maintenance_mode_lock, ··· 5045 5028 -= timeout_period; 5046 5029 if (!intf->maintenance_mode 5047 5030 && (intf->auto_maintenance_timeout <= 0)) { 5048 - intf->maintenance_mode_enable = false; 5031 + intf->maintenance_mode_state = 5032 + IPMI_MAINTENANCE_MODE_STATE_OFF; 5049 5033 maintenance_mode_update(intf); 5050 5034 } 5051 5035 } ··· 5062 5044 static void ipmi_request_event(struct ipmi_smi *intf) 5063 5045 { 5064 5046 /* No event requests when in maintenance mode. */ 5065 - if (intf->maintenance_mode_enable) 5047 + if (intf->maintenance_mode_state) 5066 5048 return; 5067 5049 5068 5050 if (!intf->in_shutdown)