.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /**************************************************************************** |
---|
2 | 3 | * Driver for Solarflare network controllers and boards |
---|
3 | 4 | * Copyright 2008-2013 Solarflare Communications Inc. |
---|
4 | | - * |
---|
5 | | - * This program is free software; you can redistribute it and/or modify it |
---|
6 | | - * under the terms of the GNU General Public License version 2 as published |
---|
7 | | - * by the Free Software Foundation, incorporated herein by reference. |
---|
8 | 5 | */ |
---|
9 | 6 | |
---|
10 | 7 | #include <linux/delay.h> |
---|
.. | .. |
---|
166 | 163 | /* Serialise with efx_mcdi_ev_cpl() and efx_mcdi_ev_death() */ |
---|
167 | 164 | spin_lock_bh(&mcdi->iface_lock); |
---|
168 | 165 | ++mcdi->seqno; |
---|
| 166 | + seqno = mcdi->seqno & SEQ_MASK; |
---|
169 | 167 | spin_unlock_bh(&mcdi->iface_lock); |
---|
170 | 168 | |
---|
171 | | - seqno = mcdi->seqno & SEQ_MASK; |
---|
172 | 169 | xflags = 0; |
---|
173 | 170 | if (mcdi->mode == MCDI_MODE_EVENTS) |
---|
174 | 171 | xflags |= MCDI_HEADER_XFLAGS_EVREQ; |
---|
.. | .. |
---|
215 | 212 | * progress on a NIC at any one time. So no need for locking. |
---|
216 | 213 | */ |
---|
217 | 214 | for (i = 0; i < hdr_len / 4 && bytes < PAGE_SIZE; i++) |
---|
218 | | - bytes += snprintf(buf + bytes, PAGE_SIZE - bytes, |
---|
219 | | - " %08x", le32_to_cpu(hdr[i].u32[0])); |
---|
| 215 | + bytes += scnprintf(buf + bytes, PAGE_SIZE - bytes, |
---|
| 216 | + " %08x", |
---|
| 217 | + le32_to_cpu(hdr[i].u32[0])); |
---|
220 | 218 | |
---|
221 | 219 | for (i = 0; i < inlen / 4 && bytes < PAGE_SIZE; i++) |
---|
222 | | - bytes += snprintf(buf + bytes, PAGE_SIZE - bytes, |
---|
223 | | - " %08x", le32_to_cpu(inbuf[i].u32[0])); |
---|
| 220 | + bytes += scnprintf(buf + bytes, PAGE_SIZE - bytes, |
---|
| 221 | + " %08x", |
---|
| 222 | + le32_to_cpu(inbuf[i].u32[0])); |
---|
224 | 223 | |
---|
225 | 224 | netif_info(efx, hw, efx->net_dev, "MCDI RPC REQ:%s\n", buf); |
---|
226 | 225 | } |
---|
.. | .. |
---|
305 | 304 | */ |
---|
306 | 305 | for (i = 0; i < hdr_len && bytes < PAGE_SIZE; i++) { |
---|
307 | 306 | efx->type->mcdi_read_response(efx, &hdr, (i * 4), 4); |
---|
308 | | - bytes += snprintf(buf + bytes, PAGE_SIZE - bytes, |
---|
309 | | - " %08x", le32_to_cpu(hdr.u32[0])); |
---|
| 307 | + bytes += scnprintf(buf + bytes, PAGE_SIZE - bytes, |
---|
| 308 | + " %08x", le32_to_cpu(hdr.u32[0])); |
---|
310 | 309 | } |
---|
311 | 310 | |
---|
312 | 311 | for (i = 0; i < data_len && bytes < PAGE_SIZE; i++) { |
---|
313 | 312 | efx->type->mcdi_read_response(efx, &hdr, |
---|
314 | 313 | mcdi->resp_hdr_len + (i * 4), 4); |
---|
315 | | - bytes += snprintf(buf + bytes, PAGE_SIZE - bytes, |
---|
316 | | - " %08x", le32_to_cpu(hdr.u32[0])); |
---|
| 314 | + bytes += scnprintf(buf + bytes, PAGE_SIZE - bytes, |
---|
| 315 | + " %08x", le32_to_cpu(hdr.u32[0])); |
---|
317 | 316 | } |
---|
318 | 317 | |
---|
319 | 318 | netif_info(efx, hw, efx->net_dev, "MCDI RPC RESP:%s\n", buf); |
---|
.. | .. |
---|
1300 | 1299 | efx_schedule_reset(efx, RESET_TYPE_MCDI_TIMEOUT); |
---|
1301 | 1300 | } |
---|
1302 | 1301 | |
---|
| 1302 | +static void efx_handle_drain_event(struct efx_nic *efx) |
---|
| 1303 | +{ |
---|
| 1304 | + if (atomic_dec_and_test(&efx->active_queues)) |
---|
| 1305 | + wake_up(&efx->flush_wq); |
---|
| 1306 | + |
---|
| 1307 | + WARN_ON(atomic_read(&efx->active_queues) < 0); |
---|
| 1308 | +} |
---|
| 1309 | + |
---|
1303 | 1310 | /* Called from efx_farch_ev_process and efx_ef10_ev_process for MCDI events */ |
---|
1304 | 1311 | void efx_mcdi_process_event(struct efx_channel *channel, |
---|
1305 | 1312 | efx_qword_t *event) |
---|
.. | .. |
---|
1330 | 1337 | efx_mcdi_process_link_change(efx, event); |
---|
1331 | 1338 | break; |
---|
1332 | 1339 | case MCDI_EVENT_CODE_SENSOREVT: |
---|
1333 | | - efx_mcdi_sensor_event(efx, event); |
---|
| 1340 | + efx_sensor_event(efx, event); |
---|
1334 | 1341 | break; |
---|
1335 | 1342 | case MCDI_EVENT_CODE_SCHEDERR: |
---|
1336 | 1343 | netif_dbg(efx, hw, efx->net_dev, |
---|
.. | .. |
---|
1372 | 1379 | BUILD_BUG_ON(MCDI_EVENT_TX_FLUSH_TO_DRIVER_LBN != |
---|
1373 | 1380 | MCDI_EVENT_RX_FLUSH_TO_DRIVER_LBN); |
---|
1374 | 1381 | if (!MCDI_EVENT_FIELD(*event, TX_FLUSH_TO_DRIVER)) |
---|
1375 | | - efx_ef10_handle_drain_event(efx); |
---|
| 1382 | + efx_handle_drain_event(efx); |
---|
1376 | 1383 | break; |
---|
1377 | 1384 | case MCDI_EVENT_CODE_TX_ERR: |
---|
1378 | 1385 | case MCDI_EVENT_CODE_RX_ERR: |
---|
.. | .. |
---|
1420 | 1427 | } |
---|
1421 | 1428 | |
---|
1422 | 1429 | ver_words = (__le16 *)MCDI_PTR(outbuf, GET_VERSION_OUT_VERSION); |
---|
1423 | | - offset = snprintf(buf, len, "%u.%u.%u.%u", |
---|
1424 | | - le16_to_cpu(ver_words[0]), le16_to_cpu(ver_words[1]), |
---|
1425 | | - le16_to_cpu(ver_words[2]), le16_to_cpu(ver_words[3])); |
---|
| 1430 | + offset = scnprintf(buf, len, "%u.%u.%u.%u", |
---|
| 1431 | + le16_to_cpu(ver_words[0]), |
---|
| 1432 | + le16_to_cpu(ver_words[1]), |
---|
| 1433 | + le16_to_cpu(ver_words[2]), |
---|
| 1434 | + le16_to_cpu(ver_words[3])); |
---|
1426 | 1435 | |
---|
1427 | | - /* EF10 may have multiple datapath firmware variants within a |
---|
1428 | | - * single version. Report which variants are running. |
---|
| 1436 | + if (efx->type->print_additional_fwver) |
---|
| 1437 | + offset += efx->type->print_additional_fwver(efx, buf + offset, |
---|
| 1438 | + len - offset); |
---|
| 1439 | + |
---|
| 1440 | + /* It's theoretically possible for the string to exceed 31 |
---|
| 1441 | + * characters, though in practice the first three version |
---|
| 1442 | + * components are short enough that this doesn't happen. |
---|
1429 | 1443 | */ |
---|
1430 | | - if (efx_nic_rev(efx) >= EFX_REV_HUNT_A0) { |
---|
1431 | | - struct efx_ef10_nic_data *nic_data = efx->nic_data; |
---|
1432 | | - |
---|
1433 | | - offset += snprintf(buf + offset, len - offset, " rx%x tx%x", |
---|
1434 | | - nic_data->rx_dpcpu_fw_id, |
---|
1435 | | - nic_data->tx_dpcpu_fw_id); |
---|
1436 | | - |
---|
1437 | | - /* It's theoretically possible for the string to exceed 31 |
---|
1438 | | - * characters, though in practice the first three version |
---|
1439 | | - * components are short enough that this doesn't happen. |
---|
1440 | | - */ |
---|
1441 | | - if (WARN_ON(offset >= len)) |
---|
1442 | | - buf[0] = 0; |
---|
1443 | | - } |
---|
| 1444 | + if (WARN_ON(offset >= len)) |
---|
| 1445 | + buf[0] = 0; |
---|
1444 | 1446 | |
---|
1445 | 1447 | return; |
---|
1446 | 1448 | |
---|
.. | .. |
---|
1619 | 1621 | return rc; |
---|
1620 | 1622 | } |
---|
1621 | 1623 | |
---|
| 1624 | +/* This function finds types using the new NVRAM_PARTITIONS mcdi. */ |
---|
| 1625 | +static int efx_new_mcdi_nvram_types(struct efx_nic *efx, u32 *number, |
---|
| 1626 | + u32 *nvram_types) |
---|
| 1627 | +{ |
---|
| 1628 | + efx_dword_t *outbuf = kzalloc(MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX_MCDI2, |
---|
| 1629 | + GFP_KERNEL); |
---|
| 1630 | + size_t outlen; |
---|
| 1631 | + int rc; |
---|
| 1632 | + |
---|
| 1633 | + if (!outbuf) |
---|
| 1634 | + return -ENOMEM; |
---|
| 1635 | + |
---|
| 1636 | + BUILD_BUG_ON(MC_CMD_NVRAM_PARTITIONS_IN_LEN != 0); |
---|
| 1637 | + |
---|
| 1638 | + rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_PARTITIONS, NULL, 0, |
---|
| 1639 | + outbuf, MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX_MCDI2, &outlen); |
---|
| 1640 | + if (rc) |
---|
| 1641 | + goto fail; |
---|
| 1642 | + |
---|
| 1643 | + *number = MCDI_DWORD(outbuf, NVRAM_PARTITIONS_OUT_NUM_PARTITIONS); |
---|
| 1644 | + |
---|
| 1645 | + memcpy(nvram_types, MCDI_PTR(outbuf, NVRAM_PARTITIONS_OUT_TYPE_ID), |
---|
| 1646 | + *number * sizeof(u32)); |
---|
| 1647 | + |
---|
| 1648 | +fail: |
---|
| 1649 | + kfree(outbuf); |
---|
| 1650 | + return rc; |
---|
| 1651 | +} |
---|
| 1652 | + |
---|
1622 | 1653 | int efx_mcdi_nvram_info(struct efx_nic *efx, unsigned int type, |
---|
1623 | 1654 | size_t *size_out, size_t *erase_size_out, |
---|
1624 | 1655 | bool *protected_out) |
---|
.. | .. |
---|
1670 | 1701 | default: |
---|
1671 | 1702 | return -EIO; |
---|
1672 | 1703 | } |
---|
| 1704 | +} |
---|
| 1705 | + |
---|
| 1706 | +/* This function tests nvram partitions using the new mcdi partition lookup scheme */ |
---|
| 1707 | +int efx_new_mcdi_nvram_test_all(struct efx_nic *efx) |
---|
| 1708 | +{ |
---|
| 1709 | + u32 *nvram_types = kzalloc(MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX_MCDI2, |
---|
| 1710 | + GFP_KERNEL); |
---|
| 1711 | + unsigned int number; |
---|
| 1712 | + int rc, i; |
---|
| 1713 | + |
---|
| 1714 | + if (!nvram_types) |
---|
| 1715 | + return -ENOMEM; |
---|
| 1716 | + |
---|
| 1717 | + rc = efx_new_mcdi_nvram_types(efx, &number, nvram_types); |
---|
| 1718 | + if (rc) |
---|
| 1719 | + goto fail; |
---|
| 1720 | + |
---|
| 1721 | + /* Require at least one check */ |
---|
| 1722 | + rc = -EAGAIN; |
---|
| 1723 | + |
---|
| 1724 | + for (i = 0; i < number; i++) { |
---|
| 1725 | + if (nvram_types[i] == NVRAM_PARTITION_TYPE_PARTITION_MAP || |
---|
| 1726 | + nvram_types[i] == NVRAM_PARTITION_TYPE_DYNAMIC_CONFIG) |
---|
| 1727 | + continue; |
---|
| 1728 | + |
---|
| 1729 | + rc = efx_mcdi_nvram_test(efx, nvram_types[i]); |
---|
| 1730 | + if (rc) |
---|
| 1731 | + goto fail; |
---|
| 1732 | + } |
---|
| 1733 | + |
---|
| 1734 | +fail: |
---|
| 1735 | + kfree(nvram_types); |
---|
| 1736 | + return rc; |
---|
1673 | 1737 | } |
---|
1674 | 1738 | |
---|
1675 | 1739 | int efx_mcdi_nvram_test_all(struct efx_nic *efx) |
---|
.. | .. |
---|
1804 | 1868 | return efx_mcdi_exit_assertion(efx); |
---|
1805 | 1869 | } |
---|
1806 | 1870 | |
---|
1807 | | -void efx_mcdi_set_id_led(struct efx_nic *efx, enum efx_led_mode mode) |
---|
| 1871 | +int efx_mcdi_set_id_led(struct efx_nic *efx, enum efx_led_mode mode) |
---|
1808 | 1872 | { |
---|
1809 | 1873 | MCDI_DECLARE_BUF(inbuf, MC_CMD_SET_ID_LED_IN_LEN); |
---|
1810 | | - int rc; |
---|
1811 | 1874 | |
---|
1812 | 1875 | BUILD_BUG_ON(EFX_LED_OFF != MC_CMD_LED_OFF); |
---|
1813 | 1876 | BUILD_BUG_ON(EFX_LED_ON != MC_CMD_LED_ON); |
---|
.. | .. |
---|
1817 | 1880 | |
---|
1818 | 1881 | MCDI_SET_DWORD(inbuf, SET_ID_LED_IN_STATE, mode); |
---|
1819 | 1882 | |
---|
1820 | | - rc = efx_mcdi_rpc(efx, MC_CMD_SET_ID_LED, inbuf, sizeof(inbuf), |
---|
1821 | | - NULL, 0, NULL); |
---|
| 1883 | + return efx_mcdi_rpc(efx, MC_CMD_SET_ID_LED, inbuf, sizeof(inbuf), NULL, 0, NULL); |
---|
1822 | 1884 | } |
---|
1823 | 1885 | |
---|
1824 | 1886 | static int efx_mcdi_reset_func(struct efx_nic *efx) |
---|
.. | .. |
---|
2074 | 2136 | |
---|
2075 | 2137 | static int efx_mcdi_nvram_update_start(struct efx_nic *efx, unsigned int type) |
---|
2076 | 2138 | { |
---|
2077 | | - MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_UPDATE_START_IN_LEN); |
---|
| 2139 | + MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN); |
---|
2078 | 2140 | int rc; |
---|
2079 | 2141 | |
---|
2080 | 2142 | MCDI_SET_DWORD(inbuf, NVRAM_UPDATE_START_IN_TYPE, type); |
---|
| 2143 | + MCDI_POPULATE_DWORD_1(inbuf, NVRAM_UPDATE_START_V2_IN_FLAGS, |
---|
| 2144 | + NVRAM_UPDATE_START_V2_IN_FLAG_REPORT_VERIFY_RESULT, |
---|
| 2145 | + 1); |
---|
2081 | 2146 | |
---|
2082 | 2147 | BUILD_BUG_ON(MC_CMD_NVRAM_UPDATE_START_OUT_LEN != 0); |
---|
2083 | 2148 | |
---|
2084 | 2149 | rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_UPDATE_START, inbuf, sizeof(inbuf), |
---|
2085 | 2150 | NULL, 0, NULL); |
---|
| 2151 | + |
---|
2086 | 2152 | return rc; |
---|
2087 | 2153 | } |
---|
2088 | 2154 | |
---|
2089 | 2155 | static int efx_mcdi_nvram_read(struct efx_nic *efx, unsigned int type, |
---|
2090 | 2156 | loff_t offset, u8 *buffer, size_t length) |
---|
2091 | 2157 | { |
---|
2092 | | - MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_READ_IN_LEN); |
---|
| 2158 | + MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_READ_IN_V2_LEN); |
---|
2093 | 2159 | MCDI_DECLARE_BUF(outbuf, |
---|
2094 | 2160 | MC_CMD_NVRAM_READ_OUT_LEN(EFX_MCDI_NVRAM_LEN_MAX)); |
---|
2095 | 2161 | size_t outlen; |
---|
.. | .. |
---|
2098 | 2164 | MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_TYPE, type); |
---|
2099 | 2165 | MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_OFFSET, offset); |
---|
2100 | 2166 | MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_LENGTH, length); |
---|
| 2167 | + MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_V2_MODE, |
---|
| 2168 | + MC_CMD_NVRAM_READ_IN_V2_DEFAULT); |
---|
2101 | 2169 | |
---|
2102 | 2170 | rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_READ, inbuf, sizeof(inbuf), |
---|
2103 | 2171 | outbuf, sizeof(outbuf), &outlen); |
---|
.. | .. |
---|
2147 | 2215 | |
---|
2148 | 2216 | static int efx_mcdi_nvram_update_finish(struct efx_nic *efx, unsigned int type) |
---|
2149 | 2217 | { |
---|
2150 | | - MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN); |
---|
2151 | | - int rc; |
---|
| 2218 | + MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN); |
---|
| 2219 | + MCDI_DECLARE_BUF(outbuf, MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN); |
---|
| 2220 | + size_t outlen; |
---|
| 2221 | + int rc, rc2; |
---|
2152 | 2222 | |
---|
2153 | 2223 | MCDI_SET_DWORD(inbuf, NVRAM_UPDATE_FINISH_IN_TYPE, type); |
---|
2154 | | - |
---|
2155 | | - BUILD_BUG_ON(MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN != 0); |
---|
| 2224 | + /* Always set this flag. Old firmware ignores it */ |
---|
| 2225 | + MCDI_POPULATE_DWORD_1(inbuf, NVRAM_UPDATE_FINISH_V2_IN_FLAGS, |
---|
| 2226 | + NVRAM_UPDATE_FINISH_V2_IN_FLAG_REPORT_VERIFY_RESULT, |
---|
| 2227 | + 1); |
---|
2156 | 2228 | |
---|
2157 | 2229 | rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_UPDATE_FINISH, inbuf, sizeof(inbuf), |
---|
2158 | | - NULL, 0, NULL); |
---|
| 2230 | + outbuf, sizeof(outbuf), &outlen); |
---|
| 2231 | + if (!rc && outlen >= MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN) { |
---|
| 2232 | + rc2 = MCDI_DWORD(outbuf, NVRAM_UPDATE_FINISH_V2_OUT_RESULT_CODE); |
---|
| 2233 | + if (rc2 != MC_CMD_NVRAM_VERIFY_RC_SUCCESS) |
---|
| 2234 | + netif_err(efx, drv, efx->net_dev, |
---|
| 2235 | + "NVRAM update failed verification with code 0x%x\n", |
---|
| 2236 | + rc2); |
---|
| 2237 | + switch (rc2) { |
---|
| 2238 | + case MC_CMD_NVRAM_VERIFY_RC_SUCCESS: |
---|
| 2239 | + break; |
---|
| 2240 | + case MC_CMD_NVRAM_VERIFY_RC_CMS_CHECK_FAILED: |
---|
| 2241 | + case MC_CMD_NVRAM_VERIFY_RC_MESSAGE_DIGEST_CHECK_FAILED: |
---|
| 2242 | + case MC_CMD_NVRAM_VERIFY_RC_SIGNATURE_CHECK_FAILED: |
---|
| 2243 | + case MC_CMD_NVRAM_VERIFY_RC_TRUSTED_APPROVERS_CHECK_FAILED: |
---|
| 2244 | + case MC_CMD_NVRAM_VERIFY_RC_SIGNATURE_CHAIN_CHECK_FAILED: |
---|
| 2245 | + rc = -EIO; |
---|
| 2246 | + break; |
---|
| 2247 | + case MC_CMD_NVRAM_VERIFY_RC_INVALID_CMS_FORMAT: |
---|
| 2248 | + case MC_CMD_NVRAM_VERIFY_RC_BAD_MESSAGE_DIGEST: |
---|
| 2249 | + rc = -EINVAL; |
---|
| 2250 | + break; |
---|
| 2251 | + case MC_CMD_NVRAM_VERIFY_RC_NO_VALID_SIGNATURES: |
---|
| 2252 | + case MC_CMD_NVRAM_VERIFY_RC_NO_TRUSTED_APPROVERS: |
---|
| 2253 | + case MC_CMD_NVRAM_VERIFY_RC_NO_SIGNATURE_MATCH: |
---|
| 2254 | + rc = -EPERM; |
---|
| 2255 | + break; |
---|
| 2256 | + default: |
---|
| 2257 | + netif_err(efx, drv, efx->net_dev, |
---|
| 2258 | + "Unknown response to NVRAM_UPDATE_FINISH\n"); |
---|
| 2259 | + rc = -EIO; |
---|
| 2260 | + } |
---|
| 2261 | + } |
---|
| 2262 | + |
---|
2159 | 2263 | return rc; |
---|
2160 | 2264 | } |
---|
2161 | 2265 | |
---|