Skip to content

Commit e3f7320

Browse files
legoatercminyard
authored andcommitted
ipmi: add SET_SENSOR_READING command
SET_SENSOR_READING is a complex IPMI command (see IPMI spec 35.17) which enables the host software to set the reading value and the event status of sensors supporting it. Below is a proposal for all the operations (reading, assert, deassert, event data) with the following limitations : - No event are generated for threshold-based sensors. - The case in which the BMC needs to generate its own events is not supported. Signed-off-by: Cédric Le Goater <[email protected]> Reviewed-by: Corey Minyard <[email protected]> Message-Id: <[email protected]> [Moved the break statement for case SENSOR_GEN_EVENT_DATA above the closing brace to keep the indention consistent.] Signed-off-by: Corey Minyard <[email protected]>
1 parent 789101b commit e3f7320

File tree

1 file changed

+223
-0
lines changed

1 file changed

+223
-0
lines changed

hw/ipmi/ipmi_bmc_sim.c

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
#define IPMI_CMD_GET_SENSOR_READING 0x2d
5050
#define IPMI_CMD_SET_SENSOR_TYPE 0x2e
5151
#define IPMI_CMD_GET_SENSOR_TYPE 0x2f
52+
#define IPMI_CMD_SET_SENSOR_READING 0x30
5253

5354
/* #define IPMI_NETFN_APP 0x06 In ipmi.h */
5455

@@ -1747,6 +1748,227 @@ static void get_sensor_type(IPMIBmcSim *ibs,
17471748
rsp_buffer_push(rsp, sens->evt_reading_type_code);
17481749
}
17491750

1751+
/*
1752+
* bytes parameter
1753+
* 1 sensor number
1754+
* 2 operation (see below for bits meaning)
1755+
* 3 sensor reading
1756+
* 4:5 assertion states (optional)
1757+
* 6:7 deassertion states (optional)
1758+
* 8:10 event data 1,2,3 (optional)
1759+
*/
1760+
static void set_sensor_reading(IPMIBmcSim *ibs,
1761+
uint8_t *cmd, unsigned int cmd_len,
1762+
RspBuffer *rsp)
1763+
{
1764+
IPMISensor *sens;
1765+
uint8_t evd1 = 0;
1766+
uint8_t evd2 = 0;
1767+
uint8_t evd3 = 0;
1768+
uint8_t new_reading = 0;
1769+
uint16_t new_assert_states = 0;
1770+
uint16_t new_deassert_states = 0;
1771+
bool change_reading = false;
1772+
bool change_assert = false;
1773+
bool change_deassert = false;
1774+
enum {
1775+
SENSOR_GEN_EVENT_NONE,
1776+
SENSOR_GEN_EVENT_DATA,
1777+
SENSOR_GEN_EVENT_BMC,
1778+
} do_gen_event = SENSOR_GEN_EVENT_NONE;
1779+
1780+
if ((cmd[2] >= MAX_SENSORS) ||
1781+
!IPMI_SENSOR_GET_PRESENT(ibs->sensors + cmd[2])) {
1782+
rsp_buffer_set_error(rsp, IPMI_CC_REQ_ENTRY_NOT_PRESENT);
1783+
return;
1784+
}
1785+
1786+
sens = ibs->sensors + cmd[2];
1787+
1788+
/* [1:0] Sensor Reading operation */
1789+
switch ((cmd[3]) & 0x3) {
1790+
case 0: /* Do not change */
1791+
break;
1792+
case 1: /* write given value to sensor reading byte */
1793+
new_reading = cmd[4];
1794+
if (sens->reading != new_reading) {
1795+
change_reading = true;
1796+
}
1797+
break;
1798+
case 2:
1799+
case 3:
1800+
rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1801+
return;
1802+
}
1803+
1804+
/* [3:2] Deassertion bits operation */
1805+
switch ((cmd[3] >> 2) & 0x3) {
1806+
case 0: /* Do not change */
1807+
break;
1808+
case 1: /* write given value */
1809+
if (cmd_len > 7) {
1810+
new_deassert_states = cmd[7];
1811+
change_deassert = true;
1812+
}
1813+
if (cmd_len > 8) {
1814+
new_deassert_states |= (cmd[8] << 8);
1815+
}
1816+
break;
1817+
1818+
case 2: /* mask on */
1819+
if (cmd_len > 7) {
1820+
new_deassert_states = (sens->deassert_states | cmd[7]);
1821+
change_deassert = true;
1822+
}
1823+
if (cmd_len > 8) {
1824+
new_deassert_states |= (sens->deassert_states | (cmd[8] << 8));
1825+
}
1826+
break;
1827+
1828+
case 3: /* mask off */
1829+
if (cmd_len > 7) {
1830+
new_deassert_states = (sens->deassert_states & cmd[7]);
1831+
change_deassert = true;
1832+
}
1833+
if (cmd_len > 8) {
1834+
new_deassert_states |= (sens->deassert_states & (cmd[8] << 8));
1835+
}
1836+
break;
1837+
}
1838+
1839+
if (change_deassert && (new_deassert_states == sens->deassert_states)) {
1840+
change_deassert = false;
1841+
}
1842+
1843+
/* [5:4] Assertion bits operation */
1844+
switch ((cmd[3] >> 4) & 0x3) {
1845+
case 0: /* Do not change */
1846+
break;
1847+
case 1: /* write given value */
1848+
if (cmd_len > 5) {
1849+
new_assert_states = cmd[5];
1850+
change_assert = true;
1851+
}
1852+
if (cmd_len > 6) {
1853+
new_assert_states |= (cmd[6] << 8);
1854+
}
1855+
break;
1856+
1857+
case 2: /* mask on */
1858+
if (cmd_len > 5) {
1859+
new_assert_states = (sens->assert_states | cmd[5]);
1860+
change_assert = true;
1861+
}
1862+
if (cmd_len > 6) {
1863+
new_assert_states |= (sens->assert_states | (cmd[6] << 8));
1864+
}
1865+
break;
1866+
1867+
case 3: /* mask off */
1868+
if (cmd_len > 5) {
1869+
new_assert_states = (sens->assert_states & cmd[5]);
1870+
change_assert = true;
1871+
}
1872+
if (cmd_len > 6) {
1873+
new_assert_states |= (sens->assert_states & (cmd[6] << 8));
1874+
}
1875+
break;
1876+
}
1877+
1878+
if (change_assert && (new_assert_states == sens->assert_states)) {
1879+
change_assert = false;
1880+
}
1881+
1882+
if (cmd_len > 9) {
1883+
evd1 = cmd[9];
1884+
}
1885+
if (cmd_len > 10) {
1886+
evd2 = cmd[10];
1887+
}
1888+
if (cmd_len > 11) {
1889+
evd3 = cmd[11];
1890+
}
1891+
1892+
/* [7:6] Event Data Bytes operation */
1893+
switch ((cmd[3] >> 6) & 0x3) {
1894+
case 0: /*
1895+
* Don’t use Event Data bytes from this command. BMC will
1896+
* generate it's own Event Data bytes based on its sensor
1897+
* implementation.
1898+
*/
1899+
evd1 = evd2 = evd3 = 0x0;
1900+
do_gen_event = SENSOR_GEN_EVENT_BMC;
1901+
break;
1902+
case 1: /*
1903+
* Write given values to event data bytes including bits
1904+
* [3:0] Event Data 1.
1905+
*/
1906+
do_gen_event = SENSOR_GEN_EVENT_DATA;
1907+
break;
1908+
case 2: /*
1909+
* Write given values to event data bytes excluding bits
1910+
* [3:0] Event Data 1.
1911+
*/
1912+
evd1 &= 0xf0;
1913+
do_gen_event = SENSOR_GEN_EVENT_DATA;
1914+
break;
1915+
case 3:
1916+
rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1917+
return;
1918+
}
1919+
1920+
/*
1921+
* Event Data Bytes operation and parameter are inconsistent. The
1922+
* Specs are not clear on that topic but generating an error seems
1923+
* correct.
1924+
*/
1925+
if (do_gen_event == SENSOR_GEN_EVENT_DATA && cmd_len < 10) {
1926+
rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
1927+
return;
1928+
}
1929+
1930+
/* commit values */
1931+
if (change_reading) {
1932+
sens->reading = new_reading;
1933+
}
1934+
1935+
if (change_assert) {
1936+
sens->assert_states = new_assert_states;
1937+
}
1938+
1939+
if (change_deassert) {
1940+
sens->deassert_states = new_deassert_states;
1941+
}
1942+
1943+
/* TODO: handle threshold sensor */
1944+
if (!IPMI_SENSOR_IS_DISCRETE(sens)) {
1945+
return;
1946+
}
1947+
1948+
switch (do_gen_event) {
1949+
case SENSOR_GEN_EVENT_DATA: {
1950+
unsigned int bit = evd1 & 0xf;
1951+
uint16_t mask = (1 << bit);
1952+
1953+
if (sens->assert_states & mask & sens->assert_enable) {
1954+
gen_event(ibs, cmd[2], 0, evd1, evd2, evd3);
1955+
}
1956+
1957+
if (sens->deassert_states & mask & sens->deassert_enable) {
1958+
gen_event(ibs, cmd[2], 1, evd1, evd2, evd3);
1959+
}
1960+
break;
1961+
}
1962+
case SENSOR_GEN_EVENT_BMC:
1963+
/*
1964+
* TODO: generate event and event data bytes depending on the
1965+
* sensor
1966+
*/
1967+
break;
1968+
case SENSOR_GEN_EVENT_NONE:
1969+
break;
1970+
}
1971+
}
17501972

17511973
static const IPMICmdHandler chassis_cmds[] = {
17521974
[IPMI_CMD_GET_CHASSIS_CAPABILITIES] = { chassis_capabilities },
@@ -1768,6 +1990,7 @@ static const IPMICmdHandler sensor_event_cmds[] = {
17681990
[IPMI_CMD_GET_SENSOR_READING] = { get_sensor_reading, 3 },
17691991
[IPMI_CMD_SET_SENSOR_TYPE] = { set_sensor_type, 5 },
17701992
[IPMI_CMD_GET_SENSOR_TYPE] = { get_sensor_type, 3 },
1993+
[IPMI_CMD_SET_SENSOR_READING] = { set_sensor_reading, 5 },
17711994
};
17721995
static const IPMINetfn sensor_event_netfn = {
17731996
.cmd_nums = ARRAY_SIZE(sensor_event_cmds),

0 commit comments

Comments
 (0)