1a0285236SJedrzej Jagielski // SPDX-License-Identifier: GPL-2.0 2a0285236SJedrzej Jagielski /* Copyright (c) 2025, Intel Corporation. */ 3a0285236SJedrzej Jagielski 4a0285236SJedrzej Jagielski #include "ixgbe.h" 5a0285236SJedrzej Jagielski #include "devlink.h" 6a0f45672SJedrzej Jagielski #include "ixgbe_fw_update.h" 7a0285236SJedrzej Jagielski 8f6b588afSJedrzej Jagielski struct ixgbe_info_ctx { 9f6b588afSJedrzej Jagielski char buf[128]; 106eae2aebSJedrzej Jagielski struct ixgbe_orom_info pending_orom; 116eae2aebSJedrzej Jagielski struct ixgbe_nvm_info pending_nvm; 126eae2aebSJedrzej Jagielski struct ixgbe_netlist_info pending_netlist; 136eae2aebSJedrzej Jagielski struct ixgbe_hw_dev_caps dev_caps; 146eae2aebSJedrzej Jagielski }; 156eae2aebSJedrzej Jagielski 166eae2aebSJedrzej Jagielski enum ixgbe_devlink_version_type { 176eae2aebSJedrzej Jagielski IXGBE_DL_VERSION_RUNNING, 186eae2aebSJedrzej Jagielski IXGBE_DL_VERSION_STORED 19f6b588afSJedrzej Jagielski }; 20f6b588afSJedrzej Jagielski 21f6b588afSJedrzej Jagielski static void ixgbe_info_get_dsn(struct ixgbe_adapter *adapter, 22f6b588afSJedrzej Jagielski struct ixgbe_info_ctx *ctx) 23f6b588afSJedrzej Jagielski { 24f6b588afSJedrzej Jagielski u8 dsn[8]; 25f6b588afSJedrzej Jagielski 26f6b588afSJedrzej Jagielski /* Copy the DSN into an array in Big Endian format */ 27f6b588afSJedrzej Jagielski put_unaligned_be64(pci_get_dsn(adapter->pdev), dsn); 28f6b588afSJedrzej Jagielski 29f6b588afSJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "%8phD", dsn); 30f6b588afSJedrzej Jagielski } 31f6b588afSJedrzej Jagielski 328210ff73SJedrzej Jagielski static void ixgbe_info_orom_ver(struct ixgbe_adapter *adapter, 336eae2aebSJedrzej Jagielski struct ixgbe_info_ctx *ctx, 346eae2aebSJedrzej Jagielski enum ixgbe_devlink_version_type type) 35f6b588afSJedrzej Jagielski { 36f6b588afSJedrzej Jagielski struct ixgbe_hw *hw = &adapter->hw; 37f6b588afSJedrzej Jagielski struct ixgbe_nvm_version nvm_ver; 38f6b588afSJedrzej Jagielski 39f6b588afSJedrzej Jagielski ctx->buf[0] = '\0'; 40f6b588afSJedrzej Jagielski 418210ff73SJedrzej Jagielski if (hw->mac.type == ixgbe_mac_e610) { 428210ff73SJedrzej Jagielski struct ixgbe_orom_info *orom = &adapter->hw.flash.orom; 438210ff73SJedrzej Jagielski 446eae2aebSJedrzej Jagielski if (type == IXGBE_DL_VERSION_STORED && 456eae2aebSJedrzej Jagielski ctx->dev_caps.common_cap.nvm_update_pending_orom) 466eae2aebSJedrzej Jagielski orom = &ctx->pending_orom; 476eae2aebSJedrzej Jagielski 488210ff73SJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", 498210ff73SJedrzej Jagielski orom->major, orom->build, orom->patch); 508210ff73SJedrzej Jagielski return; 518210ff73SJedrzej Jagielski } 528210ff73SJedrzej Jagielski 53f6b588afSJedrzej Jagielski ixgbe_get_oem_prod_version(hw, &nvm_ver); 54f6b588afSJedrzej Jagielski if (nvm_ver.oem_valid) { 55f6b588afSJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x", 56f6b588afSJedrzej Jagielski nvm_ver.oem_major, nvm_ver.oem_minor, 57f6b588afSJedrzej Jagielski nvm_ver.oem_release); 58f6b588afSJedrzej Jagielski 59f6b588afSJedrzej Jagielski return; 60f6b588afSJedrzej Jagielski } 61f6b588afSJedrzej Jagielski 62f6b588afSJedrzej Jagielski ixgbe_get_orom_version(hw, &nvm_ver); 63f6b588afSJedrzej Jagielski if (nvm_ver.or_valid) 64f6b588afSJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "%d.%d.%d", 65f6b588afSJedrzej Jagielski nvm_ver.or_major, nvm_ver.or_build, nvm_ver.or_patch); 66f6b588afSJedrzej Jagielski } 67f6b588afSJedrzej Jagielski 68f6b588afSJedrzej Jagielski static void ixgbe_info_eetrack(struct ixgbe_adapter *adapter, 696eae2aebSJedrzej Jagielski struct ixgbe_info_ctx *ctx, 706eae2aebSJedrzej Jagielski enum ixgbe_devlink_version_type type) 71f6b588afSJedrzej Jagielski { 72f6b588afSJedrzej Jagielski struct ixgbe_hw *hw = &adapter->hw; 73f6b588afSJedrzej Jagielski struct ixgbe_nvm_version nvm_ver; 74f6b588afSJedrzej Jagielski 758210ff73SJedrzej Jagielski if (hw->mac.type == ixgbe_mac_e610) { 766eae2aebSJedrzej Jagielski u32 eetrack = hw->flash.nvm.eetrack; 776eae2aebSJedrzej Jagielski 786eae2aebSJedrzej Jagielski if (type == IXGBE_DL_VERSION_STORED && 796eae2aebSJedrzej Jagielski ctx->dev_caps.common_cap.nvm_update_pending_nvm) 806eae2aebSJedrzej Jagielski eetrack = ctx->pending_nvm.eetrack; 816eae2aebSJedrzej Jagielski 826eae2aebSJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", eetrack); 838210ff73SJedrzej Jagielski return; 848210ff73SJedrzej Jagielski } 858210ff73SJedrzej Jagielski 86f6b588afSJedrzej Jagielski ixgbe_get_oem_prod_version(hw, &nvm_ver); 87f6b588afSJedrzej Jagielski 88f6b588afSJedrzej Jagielski /* No ETRACK version for OEM */ 89f6b588afSJedrzej Jagielski if (nvm_ver.oem_valid) { 90f6b588afSJedrzej Jagielski ctx->buf[0] = '\0'; 91f6b588afSJedrzej Jagielski return; 92f6b588afSJedrzej Jagielski } 93f6b588afSJedrzej Jagielski 94f6b588afSJedrzej Jagielski ixgbe_get_etk_id(hw, &nvm_ver); 95f6b588afSJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm_ver.etk_id); 96f6b588afSJedrzej Jagielski } 97f6b588afSJedrzej Jagielski 988210ff73SJedrzej Jagielski static void ixgbe_info_fw_api(struct ixgbe_adapter *adapter, 998210ff73SJedrzej Jagielski struct ixgbe_info_ctx *ctx) 1008210ff73SJedrzej Jagielski { 1018210ff73SJedrzej Jagielski struct ixgbe_hw *hw = &adapter->hw; 1028210ff73SJedrzej Jagielski 1038210ff73SJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", 1048210ff73SJedrzej Jagielski hw->api_maj_ver, hw->api_min_ver, hw->api_patch); 1058210ff73SJedrzej Jagielski } 1068210ff73SJedrzej Jagielski 1078210ff73SJedrzej Jagielski static void ixgbe_info_fw_build(struct ixgbe_adapter *adapter, 1088210ff73SJedrzej Jagielski struct ixgbe_info_ctx *ctx) 1098210ff73SJedrzej Jagielski { 1108210ff73SJedrzej Jagielski struct ixgbe_hw *hw = &adapter->hw; 1118210ff73SJedrzej Jagielski 1128210ff73SJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", hw->fw_build); 1138210ff73SJedrzej Jagielski } 1148210ff73SJedrzej Jagielski 1158210ff73SJedrzej Jagielski static void ixgbe_info_fw_srev(struct ixgbe_adapter *adapter, 1166eae2aebSJedrzej Jagielski struct ixgbe_info_ctx *ctx, 1176eae2aebSJedrzej Jagielski enum ixgbe_devlink_version_type type) 1188210ff73SJedrzej Jagielski { 1198210ff73SJedrzej Jagielski struct ixgbe_nvm_info *nvm = &adapter->hw.flash.nvm; 1208210ff73SJedrzej Jagielski 1216eae2aebSJedrzej Jagielski if (type == IXGBE_DL_VERSION_STORED && 1226eae2aebSJedrzej Jagielski ctx->dev_caps.common_cap.nvm_update_pending_nvm) 1236eae2aebSJedrzej Jagielski nvm = &ctx->pending_nvm; 1246eae2aebSJedrzej Jagielski 1258210ff73SJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "%u", nvm->srev); 1268210ff73SJedrzej Jagielski } 1278210ff73SJedrzej Jagielski 1288210ff73SJedrzej Jagielski static void ixgbe_info_orom_srev(struct ixgbe_adapter *adapter, 1296eae2aebSJedrzej Jagielski struct ixgbe_info_ctx *ctx, 1306eae2aebSJedrzej Jagielski enum ixgbe_devlink_version_type type) 1318210ff73SJedrzej Jagielski { 1328210ff73SJedrzej Jagielski struct ixgbe_orom_info *orom = &adapter->hw.flash.orom; 1338210ff73SJedrzej Jagielski 1346eae2aebSJedrzej Jagielski if (type == IXGBE_DL_VERSION_STORED && 1356eae2aebSJedrzej Jagielski ctx->dev_caps.common_cap.nvm_update_pending_orom) 1366eae2aebSJedrzej Jagielski orom = &ctx->pending_orom; 1376eae2aebSJedrzej Jagielski 1388210ff73SJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "%u", orom->srev); 1398210ff73SJedrzej Jagielski } 1408210ff73SJedrzej Jagielski 1418210ff73SJedrzej Jagielski static void ixgbe_info_nvm_ver(struct ixgbe_adapter *adapter, 1426eae2aebSJedrzej Jagielski struct ixgbe_info_ctx *ctx, 1436eae2aebSJedrzej Jagielski enum ixgbe_devlink_version_type type) 1448210ff73SJedrzej Jagielski { 1458210ff73SJedrzej Jagielski struct ixgbe_nvm_info *nvm = &adapter->hw.flash.nvm; 1468210ff73SJedrzej Jagielski 1476eae2aebSJedrzej Jagielski if (type == IXGBE_DL_VERSION_STORED && 1486eae2aebSJedrzej Jagielski ctx->dev_caps.common_cap.nvm_update_pending_nvm) 1496eae2aebSJedrzej Jagielski nvm = &ctx->pending_nvm; 1506eae2aebSJedrzej Jagielski 1518210ff73SJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", nvm->major, nvm->minor); 1528210ff73SJedrzej Jagielski } 1538210ff73SJedrzej Jagielski 1548210ff73SJedrzej Jagielski static void ixgbe_info_netlist_ver(struct ixgbe_adapter *adapter, 1556eae2aebSJedrzej Jagielski struct ixgbe_info_ctx *ctx, 1566eae2aebSJedrzej Jagielski enum ixgbe_devlink_version_type type) 1578210ff73SJedrzej Jagielski { 1588210ff73SJedrzej Jagielski struct ixgbe_netlist_info *netlist = &adapter->hw.flash.netlist; 1598210ff73SJedrzej Jagielski 1606eae2aebSJedrzej Jagielski if (type == IXGBE_DL_VERSION_STORED && 1616eae2aebSJedrzej Jagielski ctx->dev_caps.common_cap.nvm_update_pending_netlist) 1626eae2aebSJedrzej Jagielski netlist = &ctx->pending_netlist; 1636eae2aebSJedrzej Jagielski 1648210ff73SJedrzej Jagielski /* The netlist version fields are BCD formatted */ 1658210ff73SJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x", 1668210ff73SJedrzej Jagielski netlist->major, netlist->minor, 1678210ff73SJedrzej Jagielski netlist->type >> 16, netlist->type & 0xFFFF, 1688210ff73SJedrzej Jagielski netlist->rev, netlist->cust_ver); 1698210ff73SJedrzej Jagielski } 1708210ff73SJedrzej Jagielski 1718210ff73SJedrzej Jagielski static void ixgbe_info_netlist_build(struct ixgbe_adapter *adapter, 1726eae2aebSJedrzej Jagielski struct ixgbe_info_ctx *ctx, 1736eae2aebSJedrzej Jagielski enum ixgbe_devlink_version_type type) 1748210ff73SJedrzej Jagielski { 1758210ff73SJedrzej Jagielski struct ixgbe_netlist_info *netlist = &adapter->hw.flash.netlist; 1768210ff73SJedrzej Jagielski 1776eae2aebSJedrzej Jagielski if (type == IXGBE_DL_VERSION_STORED && 1786eae2aebSJedrzej Jagielski ctx->dev_caps.common_cap.nvm_update_pending_netlist) 1796eae2aebSJedrzej Jagielski netlist = &ctx->pending_netlist; 1806eae2aebSJedrzej Jagielski 1818210ff73SJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash); 1828210ff73SJedrzej Jagielski } 1838210ff73SJedrzej Jagielski 1846eae2aebSJedrzej Jagielski static int ixgbe_set_ctx_dev_caps(struct ixgbe_hw *hw, 1856eae2aebSJedrzej Jagielski struct ixgbe_info_ctx *ctx, 1866eae2aebSJedrzej Jagielski struct netlink_ext_ack *extack) 1876eae2aebSJedrzej Jagielski { 1886eae2aebSJedrzej Jagielski bool *pending_orom, *pending_nvm, *pending_netlist; 1896eae2aebSJedrzej Jagielski int err; 1906eae2aebSJedrzej Jagielski 1916eae2aebSJedrzej Jagielski err = ixgbe_discover_dev_caps(hw, &ctx->dev_caps); 1926eae2aebSJedrzej Jagielski if (err) { 1936eae2aebSJedrzej Jagielski NL_SET_ERR_MSG_MOD(extack, 1946eae2aebSJedrzej Jagielski "Unable to discover device capabilities"); 1956eae2aebSJedrzej Jagielski return err; 1966eae2aebSJedrzej Jagielski } 1976eae2aebSJedrzej Jagielski 1986eae2aebSJedrzej Jagielski pending_orom = &ctx->dev_caps.common_cap.nvm_update_pending_orom; 1996eae2aebSJedrzej Jagielski pending_nvm = &ctx->dev_caps.common_cap.nvm_update_pending_nvm; 2006eae2aebSJedrzej Jagielski pending_netlist = &ctx->dev_caps.common_cap.nvm_update_pending_netlist; 2016eae2aebSJedrzej Jagielski 2026eae2aebSJedrzej Jagielski if (*pending_orom) { 2036eae2aebSJedrzej Jagielski err = ixgbe_get_inactive_orom_ver(hw, &ctx->pending_orom); 2046eae2aebSJedrzej Jagielski if (err) 2056eae2aebSJedrzej Jagielski *pending_orom = false; 2066eae2aebSJedrzej Jagielski } 2076eae2aebSJedrzej Jagielski 2086eae2aebSJedrzej Jagielski if (*pending_nvm) { 2096eae2aebSJedrzej Jagielski err = ixgbe_get_inactive_nvm_ver(hw, &ctx->pending_nvm); 2106eae2aebSJedrzej Jagielski if (err) 2116eae2aebSJedrzej Jagielski *pending_nvm = false; 2126eae2aebSJedrzej Jagielski } 2136eae2aebSJedrzej Jagielski 2146eae2aebSJedrzej Jagielski if (*pending_netlist) { 2156eae2aebSJedrzej Jagielski err = ixgbe_get_inactive_netlist_ver(hw, &ctx->pending_netlist); 2166eae2aebSJedrzej Jagielski if (err) 2176eae2aebSJedrzej Jagielski *pending_netlist = false; 2186eae2aebSJedrzej Jagielski } 2196eae2aebSJedrzej Jagielski 2206eae2aebSJedrzej Jagielski return 0; 2216eae2aebSJedrzej Jagielski } 2226eae2aebSJedrzej Jagielski 2238210ff73SJedrzej Jagielski static int ixgbe_devlink_info_get_e610(struct ixgbe_adapter *adapter, 2248210ff73SJedrzej Jagielski struct devlink_info_req *req, 2258210ff73SJedrzej Jagielski struct ixgbe_info_ctx *ctx) 2268210ff73SJedrzej Jagielski { 2278210ff73SJedrzej Jagielski int err; 2288210ff73SJedrzej Jagielski 2298210ff73SJedrzej Jagielski ixgbe_info_fw_api(adapter, ctx); 2308210ff73SJedrzej Jagielski err = devlink_info_version_running_put(req, 2318210ff73SJedrzej Jagielski DEVLINK_INFO_VERSION_GENERIC_FW_MGMT_API, 2328210ff73SJedrzej Jagielski ctx->buf); 2338210ff73SJedrzej Jagielski if (err) 2348210ff73SJedrzej Jagielski return err; 2358210ff73SJedrzej Jagielski 2368210ff73SJedrzej Jagielski ixgbe_info_fw_build(adapter, ctx); 2378210ff73SJedrzej Jagielski err = devlink_info_version_running_put(req, "fw.mgmt.build", ctx->buf); 2388210ff73SJedrzej Jagielski if (err) 2398210ff73SJedrzej Jagielski return err; 2408210ff73SJedrzej Jagielski 2416eae2aebSJedrzej Jagielski ixgbe_info_fw_srev(adapter, ctx, IXGBE_DL_VERSION_RUNNING); 2428210ff73SJedrzej Jagielski err = devlink_info_version_running_put(req, "fw.mgmt.srev", ctx->buf); 2438210ff73SJedrzej Jagielski if (err) 2448210ff73SJedrzej Jagielski return err; 2458210ff73SJedrzej Jagielski 2466eae2aebSJedrzej Jagielski ixgbe_info_orom_srev(adapter, ctx, IXGBE_DL_VERSION_RUNNING); 2478210ff73SJedrzej Jagielski err = devlink_info_version_running_put(req, "fw.undi.srev", ctx->buf); 2488210ff73SJedrzej Jagielski if (err) 2498210ff73SJedrzej Jagielski return err; 2508210ff73SJedrzej Jagielski 2516eae2aebSJedrzej Jagielski ixgbe_info_nvm_ver(adapter, ctx, IXGBE_DL_VERSION_RUNNING); 2528210ff73SJedrzej Jagielski err = devlink_info_version_running_put(req, "fw.psid.api", ctx->buf); 2538210ff73SJedrzej Jagielski if (err) 2548210ff73SJedrzej Jagielski return err; 2558210ff73SJedrzej Jagielski 2566eae2aebSJedrzej Jagielski ixgbe_info_netlist_ver(adapter, ctx, IXGBE_DL_VERSION_RUNNING); 2578210ff73SJedrzej Jagielski err = devlink_info_version_running_put(req, "fw.netlist", ctx->buf); 2588210ff73SJedrzej Jagielski if (err) 2598210ff73SJedrzej Jagielski return err; 2608210ff73SJedrzej Jagielski 2616eae2aebSJedrzej Jagielski ixgbe_info_netlist_build(adapter, ctx, IXGBE_DL_VERSION_RUNNING); 2628210ff73SJedrzej Jagielski return devlink_info_version_running_put(req, "fw.netlist.build", 2638210ff73SJedrzej Jagielski ctx->buf); 2648210ff73SJedrzej Jagielski } 2658210ff73SJedrzej Jagielski 2666eae2aebSJedrzej Jagielski static int 2676eae2aebSJedrzej Jagielski ixgbe_devlink_pending_info_get_e610(struct ixgbe_adapter *adapter, 2686eae2aebSJedrzej Jagielski struct devlink_info_req *req, 2696eae2aebSJedrzej Jagielski struct ixgbe_info_ctx *ctx) 2706eae2aebSJedrzej Jagielski { 2716eae2aebSJedrzej Jagielski int err; 2726eae2aebSJedrzej Jagielski 2736eae2aebSJedrzej Jagielski ixgbe_info_orom_ver(adapter, ctx, IXGBE_DL_VERSION_STORED); 2746eae2aebSJedrzej Jagielski err = devlink_info_version_stored_put(req, 2756eae2aebSJedrzej Jagielski DEVLINK_INFO_VERSION_GENERIC_FW_UNDI, 2766eae2aebSJedrzej Jagielski ctx->buf); 2776eae2aebSJedrzej Jagielski if (err) 2786eae2aebSJedrzej Jagielski return err; 2796eae2aebSJedrzej Jagielski 2806eae2aebSJedrzej Jagielski ixgbe_info_eetrack(adapter, ctx, IXGBE_DL_VERSION_STORED); 2816eae2aebSJedrzej Jagielski err = devlink_info_version_stored_put(req, 2826eae2aebSJedrzej Jagielski DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID, 2836eae2aebSJedrzej Jagielski ctx->buf); 2846eae2aebSJedrzej Jagielski if (err) 2856eae2aebSJedrzej Jagielski return err; 2866eae2aebSJedrzej Jagielski 2876eae2aebSJedrzej Jagielski ixgbe_info_fw_srev(adapter, ctx, IXGBE_DL_VERSION_STORED); 2886eae2aebSJedrzej Jagielski err = devlink_info_version_stored_put(req, "fw.mgmt.srev", ctx->buf); 2896eae2aebSJedrzej Jagielski if (err) 2906eae2aebSJedrzej Jagielski return err; 2916eae2aebSJedrzej Jagielski 2926eae2aebSJedrzej Jagielski ixgbe_info_orom_srev(adapter, ctx, IXGBE_DL_VERSION_STORED); 2936eae2aebSJedrzej Jagielski err = devlink_info_version_stored_put(req, "fw.undi.srev", ctx->buf); 2946eae2aebSJedrzej Jagielski if (err) 2956eae2aebSJedrzej Jagielski return err; 2966eae2aebSJedrzej Jagielski 2976eae2aebSJedrzej Jagielski ixgbe_info_nvm_ver(adapter, ctx, IXGBE_DL_VERSION_STORED); 2986eae2aebSJedrzej Jagielski err = devlink_info_version_stored_put(req, "fw.psid.api", ctx->buf); 2996eae2aebSJedrzej Jagielski if (err) 3006eae2aebSJedrzej Jagielski return err; 3016eae2aebSJedrzej Jagielski 3026eae2aebSJedrzej Jagielski ixgbe_info_netlist_ver(adapter, ctx, IXGBE_DL_VERSION_STORED); 3036eae2aebSJedrzej Jagielski err = devlink_info_version_stored_put(req, "fw.netlist", ctx->buf); 3046eae2aebSJedrzej Jagielski if (err) 3056eae2aebSJedrzej Jagielski return err; 3066eae2aebSJedrzej Jagielski 3076eae2aebSJedrzej Jagielski ixgbe_info_netlist_build(adapter, ctx, IXGBE_DL_VERSION_STORED); 3086eae2aebSJedrzej Jagielski return devlink_info_version_stored_put(req, "fw.netlist.build", 3096eae2aebSJedrzej Jagielski ctx->buf); 3106eae2aebSJedrzej Jagielski } 3116eae2aebSJedrzej Jagielski 312f6b588afSJedrzej Jagielski static int ixgbe_devlink_info_get(struct devlink *devlink, 313f6b588afSJedrzej Jagielski struct devlink_info_req *req, 314f6b588afSJedrzej Jagielski struct netlink_ext_ack *extack) 315f6b588afSJedrzej Jagielski { 316f6b588afSJedrzej Jagielski struct ixgbe_adapter *adapter = devlink_priv(devlink); 317f6b588afSJedrzej Jagielski struct ixgbe_hw *hw = &adapter->hw; 318f6b588afSJedrzej Jagielski struct ixgbe_info_ctx *ctx; 319f6b588afSJedrzej Jagielski int err; 320f6b588afSJedrzej Jagielski 321f6b588afSJedrzej Jagielski ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); 322f6b588afSJedrzej Jagielski if (!ctx) 323f6b588afSJedrzej Jagielski return -ENOMEM; 324f6b588afSJedrzej Jagielski 325c9e563caSJedrzej Jagielski if (hw->mac.type == ixgbe_mac_e610) 326c9e563caSJedrzej Jagielski ixgbe_refresh_fw_version(adapter); 327c9e563caSJedrzej Jagielski 328f6b588afSJedrzej Jagielski ixgbe_info_get_dsn(adapter, ctx); 329f6b588afSJedrzej Jagielski err = devlink_info_serial_number_put(req, ctx->buf); 330f6b588afSJedrzej Jagielski if (err) 331f6b588afSJedrzej Jagielski goto free_ctx; 332f6b588afSJedrzej Jagielski 3334654ec61SJedrzej Jagielski err = hw->eeprom.ops.read_pba_string(hw, ctx->buf, sizeof(ctx->buf)); 334f6b588afSJedrzej Jagielski if (err) 335f6b588afSJedrzej Jagielski goto free_ctx; 336f6b588afSJedrzej Jagielski 337f6b588afSJedrzej Jagielski err = devlink_info_version_fixed_put(req, 338f6b588afSJedrzej Jagielski DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, 339f6b588afSJedrzej Jagielski ctx->buf); 340f6b588afSJedrzej Jagielski if (err) 341f6b588afSJedrzej Jagielski goto free_ctx; 342f6b588afSJedrzej Jagielski 3436eae2aebSJedrzej Jagielski ixgbe_info_orom_ver(adapter, ctx, IXGBE_DL_VERSION_RUNNING); 344f6b588afSJedrzej Jagielski err = devlink_info_version_running_put(req, 345f6b588afSJedrzej Jagielski DEVLINK_INFO_VERSION_GENERIC_FW_UNDI, 346f6b588afSJedrzej Jagielski ctx->buf); 347f6b588afSJedrzej Jagielski if (err) 348f6b588afSJedrzej Jagielski goto free_ctx; 349f6b588afSJedrzej Jagielski 3506eae2aebSJedrzej Jagielski ixgbe_info_eetrack(adapter, ctx, IXGBE_DL_VERSION_RUNNING); 351f6b588afSJedrzej Jagielski err = devlink_info_version_running_put(req, 352f6b588afSJedrzej Jagielski DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID, 353f6b588afSJedrzej Jagielski ctx->buf); 3548210ff73SJedrzej Jagielski if (err || hw->mac.type != ixgbe_mac_e610) 3558210ff73SJedrzej Jagielski goto free_ctx; 3568210ff73SJedrzej Jagielski 3576eae2aebSJedrzej Jagielski err = ixgbe_set_ctx_dev_caps(hw, ctx, extack); 3586eae2aebSJedrzej Jagielski if (err) 3596eae2aebSJedrzej Jagielski goto free_ctx; 3606eae2aebSJedrzej Jagielski 3618210ff73SJedrzej Jagielski err = ixgbe_devlink_info_get_e610(adapter, req, ctx); 3626eae2aebSJedrzej Jagielski if (err) 3636eae2aebSJedrzej Jagielski goto free_ctx; 3646eae2aebSJedrzej Jagielski 3656eae2aebSJedrzej Jagielski err = ixgbe_devlink_pending_info_get_e610(adapter, req, ctx); 366f6b588afSJedrzej Jagielski free_ctx: 367f6b588afSJedrzej Jagielski kfree(ctx); 368f6b588afSJedrzej Jagielski return err; 369f6b588afSJedrzej Jagielski } 370f6b588afSJedrzej Jagielski 371c9e563caSJedrzej Jagielski /** 372c9e563caSJedrzej Jagielski * ixgbe_devlink_reload_empr_start - Start EMP reset to activate new firmware 373c9e563caSJedrzej Jagielski * @devlink: pointer to the devlink instance to reload 374c9e563caSJedrzej Jagielski * @netns_change: if true, the network namespace is changing 375c9e563caSJedrzej Jagielski * @action: the action to perform. Must be DEVLINK_RELOAD_ACTION_FW_ACTIVATE 376c9e563caSJedrzej Jagielski * @limit: limits on what reload should do, such as not resetting 377c9e563caSJedrzej Jagielski * @extack: netlink extended ACK structure 378c9e563caSJedrzej Jagielski * 379c9e563caSJedrzej Jagielski * Allow user to activate new Embedded Management Processor firmware by 380c9e563caSJedrzej Jagielski * issuing device specific EMP reset. Called in response to 381c9e563caSJedrzej Jagielski * a DEVLINK_CMD_RELOAD with the DEVLINK_RELOAD_ACTION_FW_ACTIVATE. 382c9e563caSJedrzej Jagielski * 383c9e563caSJedrzej Jagielski * Note that teardown and rebuild of the driver state happens automatically as 384c9e563caSJedrzej Jagielski * part of an interrupt and watchdog task. This is because all physical 385c9e563caSJedrzej Jagielski * functions on the device must be able to reset when an EMP reset occurs from 386c9e563caSJedrzej Jagielski * any source. 387c9e563caSJedrzej Jagielski * 388c9e563caSJedrzej Jagielski * Return: the exit code of the operation. 389c9e563caSJedrzej Jagielski */ 390c9e563caSJedrzej Jagielski static int ixgbe_devlink_reload_empr_start(struct devlink *devlink, 391c9e563caSJedrzej Jagielski bool netns_change, 392c9e563caSJedrzej Jagielski enum devlink_reload_action action, 393c9e563caSJedrzej Jagielski enum devlink_reload_limit limit, 394c9e563caSJedrzej Jagielski struct netlink_ext_ack *extack) 395c9e563caSJedrzej Jagielski { 396c9e563caSJedrzej Jagielski struct ixgbe_adapter *adapter = devlink_priv(devlink); 397c9e563caSJedrzej Jagielski struct ixgbe_hw *hw = &adapter->hw; 398c9e563caSJedrzej Jagielski u8 pending; 399c9e563caSJedrzej Jagielski int err; 400c9e563caSJedrzej Jagielski 401c9e563caSJedrzej Jagielski if (hw->mac.type != ixgbe_mac_e610) 402c9e563caSJedrzej Jagielski return -EOPNOTSUPP; 403c9e563caSJedrzej Jagielski 404c9e563caSJedrzej Jagielski err = ixgbe_get_pending_updates(adapter, &pending, extack); 405c9e563caSJedrzej Jagielski if (err) 406c9e563caSJedrzej Jagielski return err; 407c9e563caSJedrzej Jagielski 408c9e563caSJedrzej Jagielski /* Pending is a bitmask of which flash banks have a pending update, 409c9e563caSJedrzej Jagielski * including the main NVM bank, the Option ROM bank, and the netlist 410c9e563caSJedrzej Jagielski * bank. If any of these bits are set, then there is a pending update 411c9e563caSJedrzej Jagielski * waiting to be activated. 412c9e563caSJedrzej Jagielski */ 413c9e563caSJedrzej Jagielski if (!pending) { 414c9e563caSJedrzej Jagielski NL_SET_ERR_MSG_MOD(extack, "No pending firmware update"); 415c9e563caSJedrzej Jagielski return -ECANCELED; 416c9e563caSJedrzej Jagielski } 417c9e563caSJedrzej Jagielski 418c9e563caSJedrzej Jagielski if (adapter->fw_emp_reset_disabled) { 419c9e563caSJedrzej Jagielski NL_SET_ERR_MSG_MOD(extack, 420c9e563caSJedrzej Jagielski "EMP reset is not available. To activate firmware, a reboot or power cycle is needed"); 421c9e563caSJedrzej Jagielski return -ECANCELED; 422c9e563caSJedrzej Jagielski } 423c9e563caSJedrzej Jagielski 424c9e563caSJedrzej Jagielski err = ixgbe_aci_nvm_update_empr(hw); 425c9e563caSJedrzej Jagielski if (err) 426c9e563caSJedrzej Jagielski NL_SET_ERR_MSG_MOD(extack, 427c9e563caSJedrzej Jagielski "Failed to trigger EMP device reset to reload firmware"); 428c9e563caSJedrzej Jagielski 429c9e563caSJedrzej Jagielski return err; 430c9e563caSJedrzej Jagielski } 431c9e563caSJedrzej Jagielski 432c9e563caSJedrzej Jagielski /*Wait for 10 sec with 0.5 sec tic. EMPR takes no less than half of a sec */ 433c9e563caSJedrzej Jagielski #define IXGBE_DEVLINK_RELOAD_TIMEOUT_SEC 20 434c9e563caSJedrzej Jagielski 435c9e563caSJedrzej Jagielski /** 436c9e563caSJedrzej Jagielski * ixgbe_devlink_reload_empr_finish - finishes EMP reset 437c9e563caSJedrzej Jagielski * @devlink: pointer to the devlink instance 438c9e563caSJedrzej Jagielski * @action: the action to perform. 439c9e563caSJedrzej Jagielski * @limit: limits on what reload should do 440c9e563caSJedrzej Jagielski * @actions_performed: actions performed 441c9e563caSJedrzej Jagielski * @extack: netlink extended ACK structure 442c9e563caSJedrzej Jagielski * 443c9e563caSJedrzej Jagielski * Wait for new NVM to be loaded during EMP reset. 444c9e563caSJedrzej Jagielski * 445c9e563caSJedrzej Jagielski * Return: -ETIME when timer is exceeded, 0 on success. 446c9e563caSJedrzej Jagielski */ 447c9e563caSJedrzej Jagielski static int ixgbe_devlink_reload_empr_finish(struct devlink *devlink, 448c9e563caSJedrzej Jagielski enum devlink_reload_action action, 449c9e563caSJedrzej Jagielski enum devlink_reload_limit limit, 450c9e563caSJedrzej Jagielski u32 *actions_performed, 451c9e563caSJedrzej Jagielski struct netlink_ext_ack *extack) 452c9e563caSJedrzej Jagielski { 453c9e563caSJedrzej Jagielski struct ixgbe_adapter *adapter = devlink_priv(devlink); 454c9e563caSJedrzej Jagielski struct ixgbe_hw *hw = &adapter->hw; 455c9e563caSJedrzej Jagielski int i = 0; 456c9e563caSJedrzej Jagielski u32 fwsm; 457c9e563caSJedrzej Jagielski 458c9e563caSJedrzej Jagielski do { 459c9e563caSJedrzej Jagielski /* Just right away after triggering EMP reset the FWSM register 460c9e563caSJedrzej Jagielski * may be not cleared yet, so begin the loop with the delay 461c9e563caSJedrzej Jagielski * in order to not check the not updated register. 462c9e563caSJedrzej Jagielski */ 463c9e563caSJedrzej Jagielski mdelay(500); 464c9e563caSJedrzej Jagielski 465c9e563caSJedrzej Jagielski fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM(hw)); 466c9e563caSJedrzej Jagielski 467c9e563caSJedrzej Jagielski if (i++ >= IXGBE_DEVLINK_RELOAD_TIMEOUT_SEC) 468c9e563caSJedrzej Jagielski return -ETIME; 469c9e563caSJedrzej Jagielski 470c9e563caSJedrzej Jagielski } while (!(fwsm & IXGBE_FWSM_FW_VAL_BIT)); 471c9e563caSJedrzej Jagielski 472c9e563caSJedrzej Jagielski *actions_performed = BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE); 473c9e563caSJedrzej Jagielski 474*b5aae90bSJedrzej Jagielski adapter->flags2 &= ~IXGBE_FLAG2_API_MISMATCH; 475*b5aae90bSJedrzej Jagielski 476c9e563caSJedrzej Jagielski return 0; 477c9e563caSJedrzej Jagielski } 478c9e563caSJedrzej Jagielski 479a0285236SJedrzej Jagielski static const struct devlink_ops ixgbe_devlink_ops = { 480f6b588afSJedrzej Jagielski .info_get = ixgbe_devlink_info_get, 481a0f45672SJedrzej Jagielski .supported_flash_update_params = 482a0f45672SJedrzej Jagielski DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK, 483a0f45672SJedrzej Jagielski .flash_update = ixgbe_flash_pldm_image, 484c9e563caSJedrzej Jagielski .reload_actions = BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE), 485c9e563caSJedrzej Jagielski .reload_down = ixgbe_devlink_reload_empr_start, 486c9e563caSJedrzej Jagielski .reload_up = ixgbe_devlink_reload_empr_finish, 487a0285236SJedrzej Jagielski }; 488a0285236SJedrzej Jagielski 489a0285236SJedrzej Jagielski /** 490a0285236SJedrzej Jagielski * ixgbe_allocate_devlink - Allocate devlink instance 491a0285236SJedrzej Jagielski * @dev: device to allocate devlink for 492a0285236SJedrzej Jagielski * 493a0285236SJedrzej Jagielski * Allocate a devlink instance for this physical function. 494a0285236SJedrzej Jagielski * 495a0285236SJedrzej Jagielski * Return: pointer to the device adapter structure on success, 496a0285236SJedrzej Jagielski * ERR_PTR(-ENOMEM) when allocation failed. 497a0285236SJedrzej Jagielski */ 498a0285236SJedrzej Jagielski struct ixgbe_adapter *ixgbe_allocate_devlink(struct device *dev) 499a0285236SJedrzej Jagielski { 500a0285236SJedrzej Jagielski struct ixgbe_adapter *adapter; 501a0285236SJedrzej Jagielski struct devlink *devlink; 502a0285236SJedrzej Jagielski 503a0285236SJedrzej Jagielski devlink = devlink_alloc(&ixgbe_devlink_ops, sizeof(*adapter), dev); 504a0285236SJedrzej Jagielski if (!devlink) 505a0285236SJedrzej Jagielski return ERR_PTR(-ENOMEM); 506a0285236SJedrzej Jagielski 507a0285236SJedrzej Jagielski adapter = devlink_priv(devlink); 508a0285236SJedrzej Jagielski adapter->devlink = devlink; 509a0285236SJedrzej Jagielski 510a0285236SJedrzej Jagielski return adapter; 511a0285236SJedrzej Jagielski } 512a0285236SJedrzej Jagielski 513a0285236SJedrzej Jagielski /** 514a0285236SJedrzej Jagielski * ixgbe_devlink_set_switch_id - Set unique switch ID based on PCI DSN 515a0285236SJedrzej Jagielski * @adapter: pointer to the device adapter structure 516a0285236SJedrzej Jagielski * @ppid: struct with switch id information 517a0285236SJedrzej Jagielski */ 518a0285236SJedrzej Jagielski static void ixgbe_devlink_set_switch_id(struct ixgbe_adapter *adapter, 519a0285236SJedrzej Jagielski struct netdev_phys_item_id *ppid) 520a0285236SJedrzej Jagielski { 521a0285236SJedrzej Jagielski u64 id = pci_get_dsn(adapter->pdev); 522a0285236SJedrzej Jagielski 523a0285236SJedrzej Jagielski ppid->id_len = sizeof(id); 524a0285236SJedrzej Jagielski put_unaligned_be64(id, &ppid->id); 525a0285236SJedrzej Jagielski } 526a0285236SJedrzej Jagielski 527a0285236SJedrzej Jagielski /** 528a0285236SJedrzej Jagielski * ixgbe_devlink_register_port - Register devlink port 529a0285236SJedrzej Jagielski * @adapter: pointer to the device adapter structure 530a0285236SJedrzej Jagielski * 531a0285236SJedrzej Jagielski * Create and register a devlink_port for this physical function. 532a0285236SJedrzej Jagielski * 533a0285236SJedrzej Jagielski * Return: 0 on success, error code on failure. 534a0285236SJedrzej Jagielski */ 535a0285236SJedrzej Jagielski int ixgbe_devlink_register_port(struct ixgbe_adapter *adapter) 536a0285236SJedrzej Jagielski { 537a0285236SJedrzej Jagielski struct devlink_port *devlink_port = &adapter->devlink_port; 538a0285236SJedrzej Jagielski struct devlink *devlink = adapter->devlink; 539a0285236SJedrzej Jagielski struct device *dev = &adapter->pdev->dev; 540a0285236SJedrzej Jagielski struct devlink_port_attrs attrs = {}; 541a0285236SJedrzej Jagielski int err; 542a0285236SJedrzej Jagielski 543a0285236SJedrzej Jagielski attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; 544a0285236SJedrzej Jagielski attrs.phys.port_number = adapter->hw.bus.func; 545a0285236SJedrzej Jagielski ixgbe_devlink_set_switch_id(adapter, &attrs.switch_id); 546a0285236SJedrzej Jagielski 547a0285236SJedrzej Jagielski devlink_port_attrs_set(devlink_port, &attrs); 548a0285236SJedrzej Jagielski 549a0285236SJedrzej Jagielski err = devl_port_register(devlink, devlink_port, 0); 550a0285236SJedrzej Jagielski if (err) { 551a0285236SJedrzej Jagielski dev_err(dev, 552a0285236SJedrzej Jagielski "devlink port registration failed, err %d\n", err); 553a0285236SJedrzej Jagielski } 554a0285236SJedrzej Jagielski 555a0285236SJedrzej Jagielski return err; 556a0285236SJedrzej Jagielski } 557