11adf7eadSJacob Keller // SPDX-License-Identifier: GPL-2.0 21adf7eadSJacob Keller /* Copyright (c) 2020, Intel Corporation. */ 31adf7eadSJacob Keller 4b6459415SJakub Kicinski #include <linux/vmalloc.h> 5b6459415SJakub Kicinski 61adf7eadSJacob Keller #include "ice.h" 7ff2e5c70SJacob Keller #include "ice_lib.h" 81adf7eadSJacob Keller #include "ice_devlink.h" 93ea9bd5dSMichal Swiatkowski #include "ice_eswitch.h" 10d69ea414SJacob Keller #include "ice_fw_update.h" 111adf7eadSJacob Keller 12*26d1c571SAnatolii Gerasymenko static int ice_active_port_option = -1; 13*26d1c571SAnatolii Gerasymenko 1474789085SJacob Keller /* context for devlink info version reporting */ 1574789085SJacob Keller struct ice_info_ctx { 1674789085SJacob Keller char buf[128]; 17e67fbcfbSJacob Keller struct ice_orom_info pending_orom; 182c4fe41dSJacob Keller struct ice_nvm_info pending_nvm; 19e120a9abSJacob Keller struct ice_netlist_info pending_netlist; 202c4fe41dSJacob Keller struct ice_hw_dev_caps dev_caps; 2174789085SJacob Keller }; 2274789085SJacob Keller 2374789085SJacob Keller /* The following functions are used to format specific strings for various 2474789085SJacob Keller * devlink info versions. The ctx parameter is used to provide the storage 2574789085SJacob Keller * buffer, as well as any ancillary information calculated when the info 2674789085SJacob Keller * request was made. 2774789085SJacob Keller * 2874789085SJacob Keller * If a version does not exist, for example when attempting to get the 2974789085SJacob Keller * inactive version of flash when there is no pending update, the function 300128cc6eSJacob Keller * should leave the buffer in the ctx structure empty. 3174789085SJacob Keller */ 3274789085SJacob Keller 3374789085SJacob Keller static void ice_info_get_dsn(struct ice_pf *pf, struct ice_info_ctx *ctx) 34ff2e5c70SJacob Keller { 35ff2e5c70SJacob Keller u8 dsn[8]; 36ff2e5c70SJacob Keller 37ff2e5c70SJacob Keller /* Copy the DSN into an array in Big Endian format */ 38ff2e5c70SJacob Keller put_unaligned_be64(pci_get_dsn(pf->pdev), dsn); 39ff2e5c70SJacob Keller 4074789085SJacob Keller snprintf(ctx->buf, sizeof(ctx->buf), "%8phD", dsn); 41ff2e5c70SJacob Keller } 42ff2e5c70SJacob Keller 430128cc6eSJacob Keller static void ice_info_pba(struct ice_pf *pf, struct ice_info_ctx *ctx) 44e961b679SJacob Keller { 45e961b679SJacob Keller struct ice_hw *hw = &pf->hw; 465e24d598STony Nguyen int status; 47e961b679SJacob Keller 4874789085SJacob Keller status = ice_read_pba_string(hw, (u8 *)ctx->buf, sizeof(ctx->buf)); 49e961b679SJacob Keller if (status) 50a8f89fa2SJacob Keller /* We failed to locate the PBA, so just skip this entry */ 515f87ec48STony Nguyen dev_dbg(ice_pf_to_dev(pf), "Failed to read Product Board Assembly string, status %d\n", 525f87ec48STony Nguyen status); 53e961b679SJacob Keller } 54e961b679SJacob Keller 550128cc6eSJacob Keller static void ice_info_fw_mgmt(struct ice_pf *pf, struct ice_info_ctx *ctx) 56ff2e5c70SJacob Keller { 57ff2e5c70SJacob Keller struct ice_hw *hw = &pf->hw; 58ff2e5c70SJacob Keller 590128cc6eSJacob Keller snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", 600128cc6eSJacob Keller hw->fw_maj_ver, hw->fw_min_ver, hw->fw_patch); 61ff2e5c70SJacob Keller } 62ff2e5c70SJacob Keller 630128cc6eSJacob Keller static void ice_info_fw_api(struct ice_pf *pf, struct ice_info_ctx *ctx) 64ff2e5c70SJacob Keller { 65ff2e5c70SJacob Keller struct ice_hw *hw = &pf->hw; 66ff2e5c70SJacob Keller 67b726ddf9SBrett Creeley snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", hw->api_maj_ver, 68b726ddf9SBrett Creeley hw->api_min_ver, hw->api_patch); 69ff2e5c70SJacob Keller } 70ff2e5c70SJacob Keller 710128cc6eSJacob Keller static void ice_info_fw_build(struct ice_pf *pf, struct ice_info_ctx *ctx) 72ff2e5c70SJacob Keller { 73ff2e5c70SJacob Keller struct ice_hw *hw = &pf->hw; 74ff2e5c70SJacob Keller 7574789085SJacob Keller snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", hw->fw_build); 76ff2e5c70SJacob Keller } 77ff2e5c70SJacob Keller 780128cc6eSJacob Keller static void ice_info_orom_ver(struct ice_pf *pf, struct ice_info_ctx *ctx) 79ff2e5c70SJacob Keller { 809af368faSJacob Keller struct ice_orom_info *orom = &pf->hw.flash.orom; 81ff2e5c70SJacob Keller 820128cc6eSJacob Keller snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", 830128cc6eSJacob Keller orom->major, orom->build, orom->patch); 84ff2e5c70SJacob Keller } 85ff2e5c70SJacob Keller 860128cc6eSJacob Keller static void 870128cc6eSJacob Keller ice_info_pending_orom_ver(struct ice_pf __always_unused *pf, 880128cc6eSJacob Keller struct ice_info_ctx *ctx) 89e67fbcfbSJacob Keller { 90e67fbcfbSJacob Keller struct ice_orom_info *orom = &ctx->pending_orom; 91e67fbcfbSJacob Keller 92e67fbcfbSJacob Keller if (ctx->dev_caps.common_cap.nvm_update_pending_orom) 93e67fbcfbSJacob Keller snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", 94e67fbcfbSJacob Keller orom->major, orom->build, orom->patch); 95e67fbcfbSJacob Keller } 96e67fbcfbSJacob Keller 970128cc6eSJacob Keller static void ice_info_nvm_ver(struct ice_pf *pf, struct ice_info_ctx *ctx) 98ff2e5c70SJacob Keller { 999af368faSJacob Keller struct ice_nvm_info *nvm = &pf->hw.flash.nvm; 100ff2e5c70SJacob Keller 10174789085SJacob Keller snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", nvm->major, nvm->minor); 102ff2e5c70SJacob Keller } 103ff2e5c70SJacob Keller 1040128cc6eSJacob Keller static void 1050128cc6eSJacob Keller ice_info_pending_nvm_ver(struct ice_pf __always_unused *pf, 1060128cc6eSJacob Keller struct ice_info_ctx *ctx) 1072c4fe41dSJacob Keller { 1082c4fe41dSJacob Keller struct ice_nvm_info *nvm = &ctx->pending_nvm; 1092c4fe41dSJacob Keller 1102c4fe41dSJacob Keller if (ctx->dev_caps.common_cap.nvm_update_pending_nvm) 1110128cc6eSJacob Keller snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", 1120128cc6eSJacob Keller nvm->major, nvm->minor); 1132c4fe41dSJacob Keller } 1142c4fe41dSJacob Keller 1150128cc6eSJacob Keller static void ice_info_eetrack(struct ice_pf *pf, struct ice_info_ctx *ctx) 116ff2e5c70SJacob Keller { 1179af368faSJacob Keller struct ice_nvm_info *nvm = &pf->hw.flash.nvm; 118ff2e5c70SJacob Keller 11974789085SJacob Keller snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm->eetrack); 120ff2e5c70SJacob Keller } 121ff2e5c70SJacob Keller 1220128cc6eSJacob Keller static void 1230128cc6eSJacob Keller ice_info_pending_eetrack(struct ice_pf *pf, struct ice_info_ctx *ctx) 1242c4fe41dSJacob Keller { 1252c4fe41dSJacob Keller struct ice_nvm_info *nvm = &ctx->pending_nvm; 1262c4fe41dSJacob Keller 1272c4fe41dSJacob Keller if (ctx->dev_caps.common_cap.nvm_update_pending_nvm) 1282c4fe41dSJacob Keller snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm->eetrack); 1292c4fe41dSJacob Keller } 1302c4fe41dSJacob Keller 1310128cc6eSJacob Keller static void ice_info_ddp_pkg_name(struct ice_pf *pf, struct ice_info_ctx *ctx) 132ff2e5c70SJacob Keller { 133ff2e5c70SJacob Keller struct ice_hw *hw = &pf->hw; 134ff2e5c70SJacob Keller 13574789085SJacob Keller snprintf(ctx->buf, sizeof(ctx->buf), "%s", hw->active_pkg_name); 136ff2e5c70SJacob Keller } 137ff2e5c70SJacob Keller 1380128cc6eSJacob Keller static void 1390128cc6eSJacob Keller ice_info_ddp_pkg_version(struct ice_pf *pf, struct ice_info_ctx *ctx) 140ff2e5c70SJacob Keller { 141ff2e5c70SJacob Keller struct ice_pkg_ver *pkg = &pf->hw.active_pkg_ver; 142ff2e5c70SJacob Keller 1430128cc6eSJacob Keller snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u.%u", 1440128cc6eSJacob Keller pkg->major, pkg->minor, pkg->update, pkg->draft); 145ff2e5c70SJacob Keller } 146ff2e5c70SJacob Keller 1470128cc6eSJacob Keller static void 1480128cc6eSJacob Keller ice_info_ddp_pkg_bundle_id(struct ice_pf *pf, struct ice_info_ctx *ctx) 149410d0687SJacob Keller { 15074789085SJacob Keller snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", pf->hw.active_track_id); 151410d0687SJacob Keller } 152410d0687SJacob Keller 1530128cc6eSJacob Keller static void ice_info_netlist_ver(struct ice_pf *pf, struct ice_info_ctx *ctx) 154f45a645fSJacob Keller { 1559af368faSJacob Keller struct ice_netlist_info *netlist = &pf->hw.flash.netlist; 156f45a645fSJacob Keller 157f45a645fSJacob Keller /* The netlist version fields are BCD formatted */ 1580128cc6eSJacob Keller snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x", 1590128cc6eSJacob Keller netlist->major, netlist->minor, 1600128cc6eSJacob Keller netlist->type >> 16, netlist->type & 0xFFFF, 1610128cc6eSJacob Keller netlist->rev, netlist->cust_ver); 162f45a645fSJacob Keller } 163f45a645fSJacob Keller 1640128cc6eSJacob Keller static void ice_info_netlist_build(struct ice_pf *pf, struct ice_info_ctx *ctx) 165f45a645fSJacob Keller { 1669af368faSJacob Keller struct ice_netlist_info *netlist = &pf->hw.flash.netlist; 167f45a645fSJacob Keller 16874789085SJacob Keller snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash); 169f45a645fSJacob Keller } 170f45a645fSJacob Keller 1710128cc6eSJacob Keller static void 1720128cc6eSJacob Keller ice_info_pending_netlist_ver(struct ice_pf __always_unused *pf, 1730128cc6eSJacob Keller struct ice_info_ctx *ctx) 174e120a9abSJacob Keller { 175e120a9abSJacob Keller struct ice_netlist_info *netlist = &ctx->pending_netlist; 176e120a9abSJacob Keller 177e120a9abSJacob Keller /* The netlist version fields are BCD formatted */ 178e120a9abSJacob Keller if (ctx->dev_caps.common_cap.nvm_update_pending_netlist) 179e120a9abSJacob Keller snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x", 180e120a9abSJacob Keller netlist->major, netlist->minor, 1810128cc6eSJacob Keller netlist->type >> 16, netlist->type & 0xFFFF, 1820128cc6eSJacob Keller netlist->rev, netlist->cust_ver); 183e120a9abSJacob Keller } 184e120a9abSJacob Keller 1850128cc6eSJacob Keller static void 1860128cc6eSJacob Keller ice_info_pending_netlist_build(struct ice_pf __always_unused *pf, 1870128cc6eSJacob Keller struct ice_info_ctx *ctx) 188e120a9abSJacob Keller { 189e120a9abSJacob Keller struct ice_netlist_info *netlist = &ctx->pending_netlist; 190e120a9abSJacob Keller 191e120a9abSJacob Keller if (ctx->dev_caps.common_cap.nvm_update_pending_netlist) 192e120a9abSJacob Keller snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash); 193e120a9abSJacob Keller } 194e120a9abSJacob Keller 1952c4fe41dSJacob Keller #define fixed(key, getter) { ICE_VERSION_FIXED, key, getter, NULL } 1962c4fe41dSJacob Keller #define running(key, getter) { ICE_VERSION_RUNNING, key, getter, NULL } 1972c4fe41dSJacob Keller #define stored(key, getter, fallback) { ICE_VERSION_STORED, key, getter, fallback } 1982c4fe41dSJacob Keller 1992c4fe41dSJacob Keller /* The combined() macro inserts both the running entry as well as a stored 2002c4fe41dSJacob Keller * entry. The running entry will always report the version from the active 2012c4fe41dSJacob Keller * handler. The stored entry will first try the pending handler, and fallback 2022c4fe41dSJacob Keller * to the active handler if the pending function does not report a version. 2032c4fe41dSJacob Keller * The pending handler should check the status of a pending update for the 2042c4fe41dSJacob Keller * relevant flash component. It should only fill in the buffer in the case 2052c4fe41dSJacob Keller * where a valid pending version is available. This ensures that the related 2062c4fe41dSJacob Keller * stored and running versions remain in sync, and that stored versions are 2072c4fe41dSJacob Keller * correctly reported as expected. 2082c4fe41dSJacob Keller */ 2092c4fe41dSJacob Keller #define combined(key, active, pending) \ 2102c4fe41dSJacob Keller running(key, active), \ 2112c4fe41dSJacob Keller stored(key, pending, active) 212ff2e5c70SJacob Keller 213ff2e5c70SJacob Keller enum ice_version_type { 214ff2e5c70SJacob Keller ICE_VERSION_FIXED, 215ff2e5c70SJacob Keller ICE_VERSION_RUNNING, 216ff2e5c70SJacob Keller ICE_VERSION_STORED, 217ff2e5c70SJacob Keller }; 218ff2e5c70SJacob Keller 219ff2e5c70SJacob Keller static const struct ice_devlink_version { 220ff2e5c70SJacob Keller enum ice_version_type type; 221ff2e5c70SJacob Keller const char *key; 2220128cc6eSJacob Keller void (*getter)(struct ice_pf *pf, struct ice_info_ctx *ctx); 2230128cc6eSJacob Keller void (*fallback)(struct ice_pf *pf, struct ice_info_ctx *ctx); 224ff2e5c70SJacob Keller } ice_devlink_versions[] = { 225e961b679SJacob Keller fixed(DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, ice_info_pba), 226ff2e5c70SJacob Keller running(DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, ice_info_fw_mgmt), 227ff2e5c70SJacob Keller running("fw.mgmt.api", ice_info_fw_api), 228ff2e5c70SJacob Keller running("fw.mgmt.build", ice_info_fw_build), 229e67fbcfbSJacob Keller combined(DEVLINK_INFO_VERSION_GENERIC_FW_UNDI, ice_info_orom_ver, ice_info_pending_orom_ver), 2302c4fe41dSJacob Keller combined("fw.psid.api", ice_info_nvm_ver, ice_info_pending_nvm_ver), 2312c4fe41dSJacob Keller combined(DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID, ice_info_eetrack, ice_info_pending_eetrack), 232ff2e5c70SJacob Keller running("fw.app.name", ice_info_ddp_pkg_name), 233ff2e5c70SJacob Keller running(DEVLINK_INFO_VERSION_GENERIC_FW_APP, ice_info_ddp_pkg_version), 234410d0687SJacob Keller running("fw.app.bundle_id", ice_info_ddp_pkg_bundle_id), 235e120a9abSJacob Keller combined("fw.netlist", ice_info_netlist_ver, ice_info_pending_netlist_ver), 236e120a9abSJacob Keller combined("fw.netlist.build", ice_info_netlist_build, ice_info_pending_netlist_build), 237ff2e5c70SJacob Keller }; 238ff2e5c70SJacob Keller 239ff2e5c70SJacob Keller /** 240ff2e5c70SJacob Keller * ice_devlink_info_get - .info_get devlink handler 241ff2e5c70SJacob Keller * @devlink: devlink instance structure 242ff2e5c70SJacob Keller * @req: the devlink info request 243ff2e5c70SJacob Keller * @extack: extended netdev ack structure 244ff2e5c70SJacob Keller * 245ff2e5c70SJacob Keller * Callback for the devlink .info_get operation. Reports information about the 246ff2e5c70SJacob Keller * device. 247ff2e5c70SJacob Keller * 248e961b679SJacob Keller * Return: zero on success or an error code on failure. 249ff2e5c70SJacob Keller */ 250ff2e5c70SJacob Keller static int ice_devlink_info_get(struct devlink *devlink, 251ff2e5c70SJacob Keller struct devlink_info_req *req, 252ff2e5c70SJacob Keller struct netlink_ext_ack *extack) 253ff2e5c70SJacob Keller { 254ff2e5c70SJacob Keller struct ice_pf *pf = devlink_priv(devlink); 2552c4fe41dSJacob Keller struct device *dev = ice_pf_to_dev(pf); 2562c4fe41dSJacob Keller struct ice_hw *hw = &pf->hw; 25774789085SJacob Keller struct ice_info_ctx *ctx; 258ff2e5c70SJacob Keller size_t i; 259ff2e5c70SJacob Keller int err; 260ff2e5c70SJacob Keller 2611c08052eSJacob Keller err = ice_wait_for_reset(pf, 10 * HZ); 2621c08052eSJacob Keller if (err) { 2631c08052eSJacob Keller NL_SET_ERR_MSG_MOD(extack, "Device is busy resetting"); 2641c08052eSJacob Keller return err; 2651c08052eSJacob Keller } 2661c08052eSJacob Keller 26774789085SJacob Keller ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 26874789085SJacob Keller if (!ctx) 26974789085SJacob Keller return -ENOMEM; 27074789085SJacob Keller 2712c4fe41dSJacob Keller /* discover capabilities first */ 2722ccc1c1cSTony Nguyen err = ice_discover_dev_caps(hw, &ctx->dev_caps); 2732ccc1c1cSTony Nguyen if (err) { 2745f87ec48STony Nguyen dev_dbg(dev, "Failed to discover device capabilities, status %d aq_err %s\n", 2752ccc1c1cSTony Nguyen err, ice_aq_str(hw->adminq.sq_last_status)); 276d5f84ae9SJacob Keller NL_SET_ERR_MSG_MOD(extack, "Unable to discover device capabilities"); 2772c4fe41dSJacob Keller goto out_free_ctx; 2782c4fe41dSJacob Keller } 2792c4fe41dSJacob Keller 280e67fbcfbSJacob Keller if (ctx->dev_caps.common_cap.nvm_update_pending_orom) { 2812ccc1c1cSTony Nguyen err = ice_get_inactive_orom_ver(hw, &ctx->pending_orom); 2822ccc1c1cSTony Nguyen if (err) { 2835f87ec48STony Nguyen dev_dbg(dev, "Unable to read inactive Option ROM version data, status %d aq_err %s\n", 2842ccc1c1cSTony Nguyen err, ice_aq_str(hw->adminq.sq_last_status)); 285e67fbcfbSJacob Keller 286e67fbcfbSJacob Keller /* disable display of pending Option ROM */ 287e67fbcfbSJacob Keller ctx->dev_caps.common_cap.nvm_update_pending_orom = false; 288e67fbcfbSJacob Keller } 289e67fbcfbSJacob Keller } 290e67fbcfbSJacob Keller 2912c4fe41dSJacob Keller if (ctx->dev_caps.common_cap.nvm_update_pending_nvm) { 2922ccc1c1cSTony Nguyen err = ice_get_inactive_nvm_ver(hw, &ctx->pending_nvm); 2932ccc1c1cSTony Nguyen if (err) { 2945f87ec48STony Nguyen dev_dbg(dev, "Unable to read inactive NVM version data, status %d aq_err %s\n", 2952ccc1c1cSTony Nguyen err, ice_aq_str(hw->adminq.sq_last_status)); 2962c4fe41dSJacob Keller 2972c4fe41dSJacob Keller /* disable display of pending Option ROM */ 2982c4fe41dSJacob Keller ctx->dev_caps.common_cap.nvm_update_pending_nvm = false; 2992c4fe41dSJacob Keller } 3002c4fe41dSJacob Keller } 3012c4fe41dSJacob Keller 302e120a9abSJacob Keller if (ctx->dev_caps.common_cap.nvm_update_pending_netlist) { 3032ccc1c1cSTony Nguyen err = ice_get_inactive_netlist_ver(hw, &ctx->pending_netlist); 3042ccc1c1cSTony Nguyen if (err) { 3055f87ec48STony Nguyen dev_dbg(dev, "Unable to read inactive Netlist version data, status %d aq_err %s\n", 3062ccc1c1cSTony Nguyen err, ice_aq_str(hw->adminq.sq_last_status)); 307e120a9abSJacob Keller 308e120a9abSJacob Keller /* disable display of pending Option ROM */ 309e120a9abSJacob Keller ctx->dev_caps.common_cap.nvm_update_pending_netlist = false; 310e120a9abSJacob Keller } 311e120a9abSJacob Keller } 312e120a9abSJacob Keller 313ff2e5c70SJacob Keller err = devlink_info_driver_name_put(req, KBUILD_MODNAME); 314ff2e5c70SJacob Keller if (err) { 315ff2e5c70SJacob Keller NL_SET_ERR_MSG_MOD(extack, "Unable to set driver name"); 31674789085SJacob Keller goto out_free_ctx; 317ff2e5c70SJacob Keller } 318ff2e5c70SJacob Keller 31974789085SJacob Keller ice_info_get_dsn(pf, ctx); 320ff2e5c70SJacob Keller 32174789085SJacob Keller err = devlink_info_serial_number_put(req, ctx->buf); 322ff2e5c70SJacob Keller if (err) { 323ff2e5c70SJacob Keller NL_SET_ERR_MSG_MOD(extack, "Unable to set serial number"); 32474789085SJacob Keller goto out_free_ctx; 325ff2e5c70SJacob Keller } 326ff2e5c70SJacob Keller 327ff2e5c70SJacob Keller for (i = 0; i < ARRAY_SIZE(ice_devlink_versions); i++) { 328ff2e5c70SJacob Keller enum ice_version_type type = ice_devlink_versions[i].type; 329ff2e5c70SJacob Keller const char *key = ice_devlink_versions[i].key; 330ff2e5c70SJacob Keller 33174789085SJacob Keller memset(ctx->buf, 0, sizeof(ctx->buf)); 33274789085SJacob Keller 3330128cc6eSJacob Keller ice_devlink_versions[i].getter(pf, ctx); 334ff2e5c70SJacob Keller 3352c4fe41dSJacob Keller /* If the default getter doesn't report a version, use the 3362c4fe41dSJacob Keller * fallback function. This is primarily useful in the case of 3372c4fe41dSJacob Keller * "stored" versions that want to report the same value as the 3382c4fe41dSJacob Keller * running version in the normal case of no pending update. 3392c4fe41dSJacob Keller */ 3400128cc6eSJacob Keller if (ctx->buf[0] == '\0' && ice_devlink_versions[i].fallback) 3410128cc6eSJacob Keller ice_devlink_versions[i].fallback(pf, ctx); 3422c4fe41dSJacob Keller 34374789085SJacob Keller /* Do not report missing versions */ 34474789085SJacob Keller if (ctx->buf[0] == '\0') 34574789085SJacob Keller continue; 34674789085SJacob Keller 347ff2e5c70SJacob Keller switch (type) { 348ff2e5c70SJacob Keller case ICE_VERSION_FIXED: 34974789085SJacob Keller err = devlink_info_version_fixed_put(req, key, ctx->buf); 350ff2e5c70SJacob Keller if (err) { 351ff2e5c70SJacob Keller NL_SET_ERR_MSG_MOD(extack, "Unable to set fixed version"); 35274789085SJacob Keller goto out_free_ctx; 353ff2e5c70SJacob Keller } 354ff2e5c70SJacob Keller break; 355ff2e5c70SJacob Keller case ICE_VERSION_RUNNING: 35674789085SJacob Keller err = devlink_info_version_running_put(req, key, ctx->buf); 357ff2e5c70SJacob Keller if (err) { 358ff2e5c70SJacob Keller NL_SET_ERR_MSG_MOD(extack, "Unable to set running version"); 35974789085SJacob Keller goto out_free_ctx; 360ff2e5c70SJacob Keller } 361ff2e5c70SJacob Keller break; 362ff2e5c70SJacob Keller case ICE_VERSION_STORED: 36374789085SJacob Keller err = devlink_info_version_stored_put(req, key, ctx->buf); 364ff2e5c70SJacob Keller if (err) { 365ff2e5c70SJacob Keller NL_SET_ERR_MSG_MOD(extack, "Unable to set stored version"); 36674789085SJacob Keller goto out_free_ctx; 367ff2e5c70SJacob Keller } 368ff2e5c70SJacob Keller break; 369ff2e5c70SJacob Keller } 370ff2e5c70SJacob Keller } 371ff2e5c70SJacob Keller 37274789085SJacob Keller out_free_ctx: 37374789085SJacob Keller kfree(ctx); 37474789085SJacob Keller return err; 375ff2e5c70SJacob Keller } 376ff2e5c70SJacob Keller 377399e27dbSJacob Keller /** 378399e27dbSJacob Keller * ice_devlink_reload_empr_start - Start EMP reset to activate new firmware 379399e27dbSJacob Keller * @devlink: pointer to the devlink instance to reload 380399e27dbSJacob Keller * @netns_change: if true, the network namespace is changing 381399e27dbSJacob Keller * @action: the action to perform. Must be DEVLINK_RELOAD_ACTION_FW_ACTIVATE 382399e27dbSJacob Keller * @limit: limits on what reload should do, such as not resetting 383399e27dbSJacob Keller * @extack: netlink extended ACK structure 384399e27dbSJacob Keller * 385399e27dbSJacob Keller * Allow user to activate new Embedded Management Processor firmware by 386399e27dbSJacob Keller * issuing device specific EMP reset. Called in response to 387399e27dbSJacob Keller * a DEVLINK_CMD_RELOAD with the DEVLINK_RELOAD_ACTION_FW_ACTIVATE. 388399e27dbSJacob Keller * 389399e27dbSJacob Keller * Note that teardown and rebuild of the driver state happens automatically as 390399e27dbSJacob Keller * part of an interrupt and watchdog task. This is because all physical 391399e27dbSJacob Keller * functions on the device must be able to reset when an EMP reset occurs from 392399e27dbSJacob Keller * any source. 393399e27dbSJacob Keller */ 394399e27dbSJacob Keller static int 395399e27dbSJacob Keller ice_devlink_reload_empr_start(struct devlink *devlink, bool netns_change, 396399e27dbSJacob Keller enum devlink_reload_action action, 397399e27dbSJacob Keller enum devlink_reload_limit limit, 398399e27dbSJacob Keller struct netlink_ext_ack *extack) 399399e27dbSJacob Keller { 400399e27dbSJacob Keller struct ice_pf *pf = devlink_priv(devlink); 401399e27dbSJacob Keller struct device *dev = ice_pf_to_dev(pf); 402399e27dbSJacob Keller struct ice_hw *hw = &pf->hw; 403399e27dbSJacob Keller u8 pending; 404399e27dbSJacob Keller int err; 405399e27dbSJacob Keller 406399e27dbSJacob Keller err = ice_get_pending_updates(pf, &pending, extack); 407399e27dbSJacob Keller if (err) 408399e27dbSJacob Keller return err; 409399e27dbSJacob Keller 410399e27dbSJacob Keller /* pending is a bitmask of which flash banks have a pending update, 411399e27dbSJacob Keller * including the main NVM bank, the Option ROM bank, and the netlist 412399e27dbSJacob Keller * bank. If any of these bits are set, then there is a pending update 413399e27dbSJacob Keller * waiting to be activated. 414399e27dbSJacob Keller */ 415399e27dbSJacob Keller if (!pending) { 416399e27dbSJacob Keller NL_SET_ERR_MSG_MOD(extack, "No pending firmware update"); 417399e27dbSJacob Keller return -ECANCELED; 418399e27dbSJacob Keller } 419399e27dbSJacob Keller 420399e27dbSJacob Keller if (pf->fw_emp_reset_disabled) { 421399e27dbSJacob Keller NL_SET_ERR_MSG_MOD(extack, "EMP reset is not available. To activate firmware, a reboot or power cycle is needed"); 422399e27dbSJacob Keller return -ECANCELED; 423399e27dbSJacob Keller } 424399e27dbSJacob Keller 425399e27dbSJacob Keller dev_dbg(dev, "Issuing device EMP reset to activate firmware\n"); 426399e27dbSJacob Keller 427399e27dbSJacob Keller err = ice_aq_nvm_update_empr(hw); 428399e27dbSJacob Keller if (err) { 429399e27dbSJacob Keller dev_err(dev, "Failed to trigger EMP device reset to reload firmware, err %d aq_err %s\n", 430399e27dbSJacob Keller err, ice_aq_str(hw->adminq.sq_last_status)); 431399e27dbSJacob Keller NL_SET_ERR_MSG_MOD(extack, "Failed to trigger EMP device reset to reload firmware"); 432399e27dbSJacob Keller return err; 433399e27dbSJacob Keller } 434399e27dbSJacob Keller 435399e27dbSJacob Keller return 0; 436399e27dbSJacob Keller } 437399e27dbSJacob Keller 438399e27dbSJacob Keller /** 439399e27dbSJacob Keller * ice_devlink_reload_empr_finish - Wait for EMP reset to finish 440399e27dbSJacob Keller * @devlink: pointer to the devlink instance reloading 441399e27dbSJacob Keller * @action: the action requested 442399e27dbSJacob Keller * @limit: limits imposed by userspace, such as not resetting 443399e27dbSJacob Keller * @actions_performed: on return, indicate what actions actually performed 444399e27dbSJacob Keller * @extack: netlink extended ACK structure 445399e27dbSJacob Keller * 446399e27dbSJacob Keller * Wait for driver to finish rebuilding after EMP reset is completed. This 447399e27dbSJacob Keller * includes time to wait for both the actual device reset as well as the time 448399e27dbSJacob Keller * for the driver's rebuild to complete. 449399e27dbSJacob Keller */ 450399e27dbSJacob Keller static int 451399e27dbSJacob Keller ice_devlink_reload_empr_finish(struct devlink *devlink, 452399e27dbSJacob Keller enum devlink_reload_action action, 453399e27dbSJacob Keller enum devlink_reload_limit limit, 454399e27dbSJacob Keller u32 *actions_performed, 455399e27dbSJacob Keller struct netlink_ext_ack *extack) 456399e27dbSJacob Keller { 457399e27dbSJacob Keller struct ice_pf *pf = devlink_priv(devlink); 458399e27dbSJacob Keller int err; 459399e27dbSJacob Keller 460399e27dbSJacob Keller *actions_performed = BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE); 461399e27dbSJacob Keller 462399e27dbSJacob Keller err = ice_wait_for_reset(pf, 60 * HZ); 463399e27dbSJacob Keller if (err) { 464399e27dbSJacob Keller NL_SET_ERR_MSG_MOD(extack, "Device still resetting after 1 minute"); 465399e27dbSJacob Keller return err; 466399e27dbSJacob Keller } 467399e27dbSJacob Keller 468399e27dbSJacob Keller return 0; 469399e27dbSJacob Keller } 470399e27dbSJacob Keller 471*26d1c571SAnatolii Gerasymenko /** 472*26d1c571SAnatolii Gerasymenko * ice_devlink_port_opt_speed_str - convert speed to a string 473*26d1c571SAnatolii Gerasymenko * @speed: speed value 474*26d1c571SAnatolii Gerasymenko */ 475*26d1c571SAnatolii Gerasymenko static const char *ice_devlink_port_opt_speed_str(u8 speed) 476*26d1c571SAnatolii Gerasymenko { 477*26d1c571SAnatolii Gerasymenko switch (speed & ICE_AQC_PORT_OPT_MAX_LANE_M) { 478*26d1c571SAnatolii Gerasymenko case ICE_AQC_PORT_OPT_MAX_LANE_100M: 479*26d1c571SAnatolii Gerasymenko return "0.1"; 480*26d1c571SAnatolii Gerasymenko case ICE_AQC_PORT_OPT_MAX_LANE_1G: 481*26d1c571SAnatolii Gerasymenko return "1"; 482*26d1c571SAnatolii Gerasymenko case ICE_AQC_PORT_OPT_MAX_LANE_2500M: 483*26d1c571SAnatolii Gerasymenko return "2.5"; 484*26d1c571SAnatolii Gerasymenko case ICE_AQC_PORT_OPT_MAX_LANE_5G: 485*26d1c571SAnatolii Gerasymenko return "5"; 486*26d1c571SAnatolii Gerasymenko case ICE_AQC_PORT_OPT_MAX_LANE_10G: 487*26d1c571SAnatolii Gerasymenko return "10"; 488*26d1c571SAnatolii Gerasymenko case ICE_AQC_PORT_OPT_MAX_LANE_25G: 489*26d1c571SAnatolii Gerasymenko return "25"; 490*26d1c571SAnatolii Gerasymenko case ICE_AQC_PORT_OPT_MAX_LANE_50G: 491*26d1c571SAnatolii Gerasymenko return "50"; 492*26d1c571SAnatolii Gerasymenko case ICE_AQC_PORT_OPT_MAX_LANE_100G: 493*26d1c571SAnatolii Gerasymenko return "100"; 494*26d1c571SAnatolii Gerasymenko } 495*26d1c571SAnatolii Gerasymenko 496*26d1c571SAnatolii Gerasymenko return "-"; 497*26d1c571SAnatolii Gerasymenko } 498*26d1c571SAnatolii Gerasymenko 499*26d1c571SAnatolii Gerasymenko #define ICE_PORT_OPT_DESC_LEN 50 500*26d1c571SAnatolii Gerasymenko /** 501*26d1c571SAnatolii Gerasymenko * ice_devlink_port_options_print - Print available port split options 502*26d1c571SAnatolii Gerasymenko * @pf: the PF to print split port options 503*26d1c571SAnatolii Gerasymenko * 504*26d1c571SAnatolii Gerasymenko * Prints a table with available port split options and max port speeds 505*26d1c571SAnatolii Gerasymenko */ 506*26d1c571SAnatolii Gerasymenko static void ice_devlink_port_options_print(struct ice_pf *pf) 507*26d1c571SAnatolii Gerasymenko { 508*26d1c571SAnatolii Gerasymenko u8 i, j, options_count, cnt, speed, pending_idx, active_idx; 509*26d1c571SAnatolii Gerasymenko struct ice_aqc_get_port_options_elem *options, *opt; 510*26d1c571SAnatolii Gerasymenko struct device *dev = ice_pf_to_dev(pf); 511*26d1c571SAnatolii Gerasymenko bool active_valid, pending_valid; 512*26d1c571SAnatolii Gerasymenko char desc[ICE_PORT_OPT_DESC_LEN]; 513*26d1c571SAnatolii Gerasymenko const char *str; 514*26d1c571SAnatolii Gerasymenko int status; 515*26d1c571SAnatolii Gerasymenko 516*26d1c571SAnatolii Gerasymenko options = kcalloc(ICE_AQC_PORT_OPT_MAX * ICE_MAX_PORT_PER_PCI_DEV, 517*26d1c571SAnatolii Gerasymenko sizeof(*options), GFP_KERNEL); 518*26d1c571SAnatolii Gerasymenko if (!options) 519*26d1c571SAnatolii Gerasymenko return; 520*26d1c571SAnatolii Gerasymenko 521*26d1c571SAnatolii Gerasymenko for (i = 0; i < ICE_MAX_PORT_PER_PCI_DEV; i++) { 522*26d1c571SAnatolii Gerasymenko opt = options + i * ICE_AQC_PORT_OPT_MAX; 523*26d1c571SAnatolii Gerasymenko options_count = ICE_AQC_PORT_OPT_MAX; 524*26d1c571SAnatolii Gerasymenko active_valid = 0; 525*26d1c571SAnatolii Gerasymenko 526*26d1c571SAnatolii Gerasymenko status = ice_aq_get_port_options(&pf->hw, opt, &options_count, 527*26d1c571SAnatolii Gerasymenko i, true, &active_idx, 528*26d1c571SAnatolii Gerasymenko &active_valid, &pending_idx, 529*26d1c571SAnatolii Gerasymenko &pending_valid); 530*26d1c571SAnatolii Gerasymenko if (status) { 531*26d1c571SAnatolii Gerasymenko dev_dbg(dev, "Couldn't read port option for port %d, err %d\n", 532*26d1c571SAnatolii Gerasymenko i, status); 533*26d1c571SAnatolii Gerasymenko goto err; 534*26d1c571SAnatolii Gerasymenko } 535*26d1c571SAnatolii Gerasymenko } 536*26d1c571SAnatolii Gerasymenko 537*26d1c571SAnatolii Gerasymenko dev_dbg(dev, "Available port split options and max port speeds (Gbps):\n"); 538*26d1c571SAnatolii Gerasymenko dev_dbg(dev, "Status Split Quad 0 Quad 1\n"); 539*26d1c571SAnatolii Gerasymenko dev_dbg(dev, " count L0 L1 L2 L3 L4 L5 L6 L7\n"); 540*26d1c571SAnatolii Gerasymenko 541*26d1c571SAnatolii Gerasymenko for (i = 0; i < options_count; i++) { 542*26d1c571SAnatolii Gerasymenko cnt = 0; 543*26d1c571SAnatolii Gerasymenko 544*26d1c571SAnatolii Gerasymenko if (i == ice_active_port_option) 545*26d1c571SAnatolii Gerasymenko str = "Active"; 546*26d1c571SAnatolii Gerasymenko else if ((i == pending_idx) && pending_valid) 547*26d1c571SAnatolii Gerasymenko str = "Pending"; 548*26d1c571SAnatolii Gerasymenko else 549*26d1c571SAnatolii Gerasymenko str = ""; 550*26d1c571SAnatolii Gerasymenko 551*26d1c571SAnatolii Gerasymenko cnt += snprintf(&desc[cnt], ICE_PORT_OPT_DESC_LEN - cnt, 552*26d1c571SAnatolii Gerasymenko "%-8s", str); 553*26d1c571SAnatolii Gerasymenko 554*26d1c571SAnatolii Gerasymenko cnt += snprintf(&desc[cnt], ICE_PORT_OPT_DESC_LEN - cnt, 555*26d1c571SAnatolii Gerasymenko "%-6u", options[i].pmd); 556*26d1c571SAnatolii Gerasymenko 557*26d1c571SAnatolii Gerasymenko for (j = 0; j < ICE_MAX_PORT_PER_PCI_DEV; ++j) { 558*26d1c571SAnatolii Gerasymenko speed = options[i + j * ICE_AQC_PORT_OPT_MAX].max_lane_speed; 559*26d1c571SAnatolii Gerasymenko str = ice_devlink_port_opt_speed_str(speed); 560*26d1c571SAnatolii Gerasymenko cnt += snprintf(&desc[cnt], ICE_PORT_OPT_DESC_LEN - cnt, 561*26d1c571SAnatolii Gerasymenko "%3s ", str); 562*26d1c571SAnatolii Gerasymenko } 563*26d1c571SAnatolii Gerasymenko 564*26d1c571SAnatolii Gerasymenko dev_dbg(dev, "%s\n", desc); 565*26d1c571SAnatolii Gerasymenko } 566*26d1c571SAnatolii Gerasymenko 567*26d1c571SAnatolii Gerasymenko err: 568*26d1c571SAnatolii Gerasymenko kfree(options); 569*26d1c571SAnatolii Gerasymenko } 570*26d1c571SAnatolii Gerasymenko 571*26d1c571SAnatolii Gerasymenko /** 572*26d1c571SAnatolii Gerasymenko * ice_devlink_aq_set_port_option - Send set port option admin queue command 573*26d1c571SAnatolii Gerasymenko * @pf: the PF to print split port options 574*26d1c571SAnatolii Gerasymenko * @option_idx: selected port option 575*26d1c571SAnatolii Gerasymenko * @extack: extended netdev ack structure 576*26d1c571SAnatolii Gerasymenko * 577*26d1c571SAnatolii Gerasymenko * Sends set port option admin queue command with selected port option and 578*26d1c571SAnatolii Gerasymenko * calls NVM write activate. 579*26d1c571SAnatolii Gerasymenko */ 580*26d1c571SAnatolii Gerasymenko static int 581*26d1c571SAnatolii Gerasymenko ice_devlink_aq_set_port_option(struct ice_pf *pf, u8 option_idx, 582*26d1c571SAnatolii Gerasymenko struct netlink_ext_ack *extack) 583*26d1c571SAnatolii Gerasymenko { 584*26d1c571SAnatolii Gerasymenko struct device *dev = ice_pf_to_dev(pf); 585*26d1c571SAnatolii Gerasymenko int status; 586*26d1c571SAnatolii Gerasymenko 587*26d1c571SAnatolii Gerasymenko status = ice_aq_set_port_option(&pf->hw, 0, true, option_idx); 588*26d1c571SAnatolii Gerasymenko if (status) { 589*26d1c571SAnatolii Gerasymenko dev_dbg(dev, "ice_aq_set_port_option, err %d aq_err %d\n", 590*26d1c571SAnatolii Gerasymenko status, pf->hw.adminq.sq_last_status); 591*26d1c571SAnatolii Gerasymenko NL_SET_ERR_MSG_MOD(extack, "Port split request failed"); 592*26d1c571SAnatolii Gerasymenko return -EIO; 593*26d1c571SAnatolii Gerasymenko } 594*26d1c571SAnatolii Gerasymenko 595*26d1c571SAnatolii Gerasymenko status = ice_acquire_nvm(&pf->hw, ICE_RES_WRITE); 596*26d1c571SAnatolii Gerasymenko if (status) { 597*26d1c571SAnatolii Gerasymenko dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n", 598*26d1c571SAnatolii Gerasymenko status, pf->hw.adminq.sq_last_status); 599*26d1c571SAnatolii Gerasymenko NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore"); 600*26d1c571SAnatolii Gerasymenko return -EIO; 601*26d1c571SAnatolii Gerasymenko } 602*26d1c571SAnatolii Gerasymenko 603*26d1c571SAnatolii Gerasymenko status = ice_nvm_write_activate(&pf->hw, ICE_AQC_NVM_ACTIV_REQ_EMPR, NULL); 604*26d1c571SAnatolii Gerasymenko if (status) { 605*26d1c571SAnatolii Gerasymenko dev_dbg(dev, "ice_nvm_write_activate failed, err %d aq_err %d\n", 606*26d1c571SAnatolii Gerasymenko status, pf->hw.adminq.sq_last_status); 607*26d1c571SAnatolii Gerasymenko NL_SET_ERR_MSG_MOD(extack, "Port split request failed to save data"); 608*26d1c571SAnatolii Gerasymenko ice_release_nvm(&pf->hw); 609*26d1c571SAnatolii Gerasymenko return -EIO; 610*26d1c571SAnatolii Gerasymenko } 611*26d1c571SAnatolii Gerasymenko 612*26d1c571SAnatolii Gerasymenko ice_release_nvm(&pf->hw); 613*26d1c571SAnatolii Gerasymenko 614*26d1c571SAnatolii Gerasymenko NL_SET_ERR_MSG_MOD(extack, "Reboot required to finish port split"); 615*26d1c571SAnatolii Gerasymenko return 0; 616*26d1c571SAnatolii Gerasymenko } 617*26d1c571SAnatolii Gerasymenko 618*26d1c571SAnatolii Gerasymenko /** 619*26d1c571SAnatolii Gerasymenko * ice_devlink_port_split - .port_split devlink handler 620*26d1c571SAnatolii Gerasymenko * @devlink: devlink instance structure 621*26d1c571SAnatolii Gerasymenko * @port: devlink port structure 622*26d1c571SAnatolii Gerasymenko * @count: number of ports to split to 623*26d1c571SAnatolii Gerasymenko * @extack: extended netdev ack structure 624*26d1c571SAnatolii Gerasymenko * 625*26d1c571SAnatolii Gerasymenko * Callback for the devlink .port_split operation. 626*26d1c571SAnatolii Gerasymenko * 627*26d1c571SAnatolii Gerasymenko * Unfortunately, the devlink expression of available options is limited 628*26d1c571SAnatolii Gerasymenko * to just a number, so search for an FW port option which supports 629*26d1c571SAnatolii Gerasymenko * the specified number. As there could be multiple FW port options with 630*26d1c571SAnatolii Gerasymenko * the same port split count, allow switching between them. When the same 631*26d1c571SAnatolii Gerasymenko * port split count request is issued again, switch to the next FW port 632*26d1c571SAnatolii Gerasymenko * option with the same port split count. 633*26d1c571SAnatolii Gerasymenko * 634*26d1c571SAnatolii Gerasymenko * Return: zero on success or an error code on failure. 635*26d1c571SAnatolii Gerasymenko */ 636*26d1c571SAnatolii Gerasymenko static int 637*26d1c571SAnatolii Gerasymenko ice_devlink_port_split(struct devlink *devlink, struct devlink_port *port, 638*26d1c571SAnatolii Gerasymenko unsigned int count, struct netlink_ext_ack *extack) 639*26d1c571SAnatolii Gerasymenko { 640*26d1c571SAnatolii Gerasymenko struct ice_aqc_get_port_options_elem options[ICE_AQC_PORT_OPT_MAX]; 641*26d1c571SAnatolii Gerasymenko u8 i, j, active_idx, pending_idx, new_option; 642*26d1c571SAnatolii Gerasymenko struct ice_pf *pf = devlink_priv(devlink); 643*26d1c571SAnatolii Gerasymenko u8 option_count = ICE_AQC_PORT_OPT_MAX; 644*26d1c571SAnatolii Gerasymenko struct device *dev = ice_pf_to_dev(pf); 645*26d1c571SAnatolii Gerasymenko bool active_valid, pending_valid; 646*26d1c571SAnatolii Gerasymenko int status; 647*26d1c571SAnatolii Gerasymenko 648*26d1c571SAnatolii Gerasymenko status = ice_aq_get_port_options(&pf->hw, options, &option_count, 649*26d1c571SAnatolii Gerasymenko 0, true, &active_idx, &active_valid, 650*26d1c571SAnatolii Gerasymenko &pending_idx, &pending_valid); 651*26d1c571SAnatolii Gerasymenko if (status) { 652*26d1c571SAnatolii Gerasymenko dev_dbg(dev, "Couldn't read port split options, err = %d\n", 653*26d1c571SAnatolii Gerasymenko status); 654*26d1c571SAnatolii Gerasymenko NL_SET_ERR_MSG_MOD(extack, "Failed to get available port split options"); 655*26d1c571SAnatolii Gerasymenko return -EIO; 656*26d1c571SAnatolii Gerasymenko } 657*26d1c571SAnatolii Gerasymenko 658*26d1c571SAnatolii Gerasymenko new_option = ICE_AQC_PORT_OPT_MAX; 659*26d1c571SAnatolii Gerasymenko active_idx = pending_valid ? pending_idx : active_idx; 660*26d1c571SAnatolii Gerasymenko for (i = 1; i <= option_count; i++) { 661*26d1c571SAnatolii Gerasymenko /* In order to allow switching between FW port options with 662*26d1c571SAnatolii Gerasymenko * the same port split count, search for a new option starting 663*26d1c571SAnatolii Gerasymenko * from the active/pending option (with array wrap around). 664*26d1c571SAnatolii Gerasymenko */ 665*26d1c571SAnatolii Gerasymenko j = (active_idx + i) % option_count; 666*26d1c571SAnatolii Gerasymenko 667*26d1c571SAnatolii Gerasymenko if (count == options[j].pmd) { 668*26d1c571SAnatolii Gerasymenko new_option = j; 669*26d1c571SAnatolii Gerasymenko break; 670*26d1c571SAnatolii Gerasymenko } 671*26d1c571SAnatolii Gerasymenko } 672*26d1c571SAnatolii Gerasymenko 673*26d1c571SAnatolii Gerasymenko if (new_option == active_idx) { 674*26d1c571SAnatolii Gerasymenko dev_dbg(dev, "request to split: count: %u is already set and there are no other options\n", 675*26d1c571SAnatolii Gerasymenko count); 676*26d1c571SAnatolii Gerasymenko NL_SET_ERR_MSG_MOD(extack, "Requested split count is already set"); 677*26d1c571SAnatolii Gerasymenko ice_devlink_port_options_print(pf); 678*26d1c571SAnatolii Gerasymenko return -EINVAL; 679*26d1c571SAnatolii Gerasymenko } 680*26d1c571SAnatolii Gerasymenko 681*26d1c571SAnatolii Gerasymenko if (new_option == ICE_AQC_PORT_OPT_MAX) { 682*26d1c571SAnatolii Gerasymenko dev_dbg(dev, "request to split: count: %u not found\n", count); 683*26d1c571SAnatolii Gerasymenko NL_SET_ERR_MSG_MOD(extack, "Port split requested unsupported port config"); 684*26d1c571SAnatolii Gerasymenko ice_devlink_port_options_print(pf); 685*26d1c571SAnatolii Gerasymenko return -EINVAL; 686*26d1c571SAnatolii Gerasymenko } 687*26d1c571SAnatolii Gerasymenko 688*26d1c571SAnatolii Gerasymenko status = ice_devlink_aq_set_port_option(pf, new_option, extack); 689*26d1c571SAnatolii Gerasymenko if (status) 690*26d1c571SAnatolii Gerasymenko return status; 691*26d1c571SAnatolii Gerasymenko 692*26d1c571SAnatolii Gerasymenko ice_devlink_port_options_print(pf); 693*26d1c571SAnatolii Gerasymenko 694*26d1c571SAnatolii Gerasymenko return 0; 695*26d1c571SAnatolii Gerasymenko } 696*26d1c571SAnatolii Gerasymenko 697*26d1c571SAnatolii Gerasymenko /** 698*26d1c571SAnatolii Gerasymenko * ice_devlink_port_unsplit - .port_unsplit devlink handler 699*26d1c571SAnatolii Gerasymenko * @devlink: devlink instance structure 700*26d1c571SAnatolii Gerasymenko * @port: devlink port structure 701*26d1c571SAnatolii Gerasymenko * @extack: extended netdev ack structure 702*26d1c571SAnatolii Gerasymenko * 703*26d1c571SAnatolii Gerasymenko * Callback for the devlink .port_unsplit operation. 704*26d1c571SAnatolii Gerasymenko * Calls ice_devlink_port_split with split count set to 1. 705*26d1c571SAnatolii Gerasymenko * There could be no FW option available with split count 1. 706*26d1c571SAnatolii Gerasymenko * 707*26d1c571SAnatolii Gerasymenko * Return: zero on success or an error code on failure. 708*26d1c571SAnatolii Gerasymenko */ 709*26d1c571SAnatolii Gerasymenko static int 710*26d1c571SAnatolii Gerasymenko ice_devlink_port_unsplit(struct devlink *devlink, struct devlink_port *port, 711*26d1c571SAnatolii Gerasymenko struct netlink_ext_ack *extack) 712*26d1c571SAnatolii Gerasymenko { 713*26d1c571SAnatolii Gerasymenko return ice_devlink_port_split(devlink, port, 1, extack); 714*26d1c571SAnatolii Gerasymenko } 715*26d1c571SAnatolii Gerasymenko 7161adf7eadSJacob Keller static const struct devlink_ops ice_devlink_ops = { 71750db1bcaSJacob Keller .supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK, 718399e27dbSJacob Keller .reload_actions = BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE), 719399e27dbSJacob Keller /* The ice driver currently does not support driver reinit */ 720399e27dbSJacob Keller .reload_down = ice_devlink_reload_empr_start, 721399e27dbSJacob Keller .reload_up = ice_devlink_reload_empr_finish, 722*26d1c571SAnatolii Gerasymenko .port_split = ice_devlink_port_split, 723*26d1c571SAnatolii Gerasymenko .port_unsplit = ice_devlink_port_unsplit, 7243ea9bd5dSMichal Swiatkowski .eswitch_mode_get = ice_eswitch_mode_get, 7253ea9bd5dSMichal Swiatkowski .eswitch_mode_set = ice_eswitch_mode_set, 726ff2e5c70SJacob Keller .info_get = ice_devlink_info_get, 727d69ea414SJacob Keller .flash_update = ice_devlink_flash_update, 7281adf7eadSJacob Keller }; 7291adf7eadSJacob Keller 730e523af4eSShiraz Saleem static int 731e523af4eSShiraz Saleem ice_devlink_enable_roce_get(struct devlink *devlink, u32 id, 732e523af4eSShiraz Saleem struct devlink_param_gset_ctx *ctx) 733e523af4eSShiraz Saleem { 734e523af4eSShiraz Saleem struct ice_pf *pf = devlink_priv(devlink); 735e523af4eSShiraz Saleem 7367b62483fSShiraz Saleem ctx->val.vbool = pf->rdma_mode & IIDC_RDMA_PROTOCOL_ROCEV2 ? true : false; 737e523af4eSShiraz Saleem 738e523af4eSShiraz Saleem return 0; 739e523af4eSShiraz Saleem } 740e523af4eSShiraz Saleem 741e523af4eSShiraz Saleem static int 742e523af4eSShiraz Saleem ice_devlink_enable_roce_set(struct devlink *devlink, u32 id, 743e523af4eSShiraz Saleem struct devlink_param_gset_ctx *ctx) 744e523af4eSShiraz Saleem { 745e523af4eSShiraz Saleem struct ice_pf *pf = devlink_priv(devlink); 746e523af4eSShiraz Saleem bool roce_ena = ctx->val.vbool; 747e523af4eSShiraz Saleem int ret; 748e523af4eSShiraz Saleem 749e523af4eSShiraz Saleem if (!roce_ena) { 750e523af4eSShiraz Saleem ice_unplug_aux_dev(pf); 751e523af4eSShiraz Saleem pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_ROCEV2; 752e523af4eSShiraz Saleem return 0; 753e523af4eSShiraz Saleem } 754e523af4eSShiraz Saleem 755e523af4eSShiraz Saleem pf->rdma_mode |= IIDC_RDMA_PROTOCOL_ROCEV2; 756e523af4eSShiraz Saleem ret = ice_plug_aux_dev(pf); 757e523af4eSShiraz Saleem if (ret) 758e523af4eSShiraz Saleem pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_ROCEV2; 759e523af4eSShiraz Saleem 760e523af4eSShiraz Saleem return ret; 761e523af4eSShiraz Saleem } 762e523af4eSShiraz Saleem 763e523af4eSShiraz Saleem static int 764e523af4eSShiraz Saleem ice_devlink_enable_roce_validate(struct devlink *devlink, u32 id, 765e523af4eSShiraz Saleem union devlink_param_value val, 766e523af4eSShiraz Saleem struct netlink_ext_ack *extack) 767e523af4eSShiraz Saleem { 768e523af4eSShiraz Saleem struct ice_pf *pf = devlink_priv(devlink); 769e523af4eSShiraz Saleem 770e523af4eSShiraz Saleem if (!test_bit(ICE_FLAG_RDMA_ENA, pf->flags)) 771e523af4eSShiraz Saleem return -EOPNOTSUPP; 772e523af4eSShiraz Saleem 773e523af4eSShiraz Saleem if (pf->rdma_mode & IIDC_RDMA_PROTOCOL_IWARP) { 774e523af4eSShiraz Saleem NL_SET_ERR_MSG_MOD(extack, "iWARP is currently enabled. This device cannot enable iWARP and RoCEv2 simultaneously"); 775e523af4eSShiraz Saleem return -EOPNOTSUPP; 776e523af4eSShiraz Saleem } 777e523af4eSShiraz Saleem 778e523af4eSShiraz Saleem return 0; 779e523af4eSShiraz Saleem } 780e523af4eSShiraz Saleem 781e523af4eSShiraz Saleem static int 782e523af4eSShiraz Saleem ice_devlink_enable_iw_get(struct devlink *devlink, u32 id, 783e523af4eSShiraz Saleem struct devlink_param_gset_ctx *ctx) 784e523af4eSShiraz Saleem { 785e523af4eSShiraz Saleem struct ice_pf *pf = devlink_priv(devlink); 786e523af4eSShiraz Saleem 787e523af4eSShiraz Saleem ctx->val.vbool = pf->rdma_mode & IIDC_RDMA_PROTOCOL_IWARP; 788e523af4eSShiraz Saleem 789e523af4eSShiraz Saleem return 0; 790e523af4eSShiraz Saleem } 791e523af4eSShiraz Saleem 792e523af4eSShiraz Saleem static int 793e523af4eSShiraz Saleem ice_devlink_enable_iw_set(struct devlink *devlink, u32 id, 794e523af4eSShiraz Saleem struct devlink_param_gset_ctx *ctx) 795e523af4eSShiraz Saleem { 796e523af4eSShiraz Saleem struct ice_pf *pf = devlink_priv(devlink); 797e523af4eSShiraz Saleem bool iw_ena = ctx->val.vbool; 798e523af4eSShiraz Saleem int ret; 799e523af4eSShiraz Saleem 800e523af4eSShiraz Saleem if (!iw_ena) { 801e523af4eSShiraz Saleem ice_unplug_aux_dev(pf); 802e523af4eSShiraz Saleem pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_IWARP; 803e523af4eSShiraz Saleem return 0; 804e523af4eSShiraz Saleem } 805e523af4eSShiraz Saleem 806e523af4eSShiraz Saleem pf->rdma_mode |= IIDC_RDMA_PROTOCOL_IWARP; 807e523af4eSShiraz Saleem ret = ice_plug_aux_dev(pf); 808e523af4eSShiraz Saleem if (ret) 809e523af4eSShiraz Saleem pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_IWARP; 810e523af4eSShiraz Saleem 811e523af4eSShiraz Saleem return ret; 812e523af4eSShiraz Saleem } 813e523af4eSShiraz Saleem 814e523af4eSShiraz Saleem static int 815e523af4eSShiraz Saleem ice_devlink_enable_iw_validate(struct devlink *devlink, u32 id, 816e523af4eSShiraz Saleem union devlink_param_value val, 817e523af4eSShiraz Saleem struct netlink_ext_ack *extack) 818e523af4eSShiraz Saleem { 819e523af4eSShiraz Saleem struct ice_pf *pf = devlink_priv(devlink); 820e523af4eSShiraz Saleem 821e523af4eSShiraz Saleem if (!test_bit(ICE_FLAG_RDMA_ENA, pf->flags)) 822e523af4eSShiraz Saleem return -EOPNOTSUPP; 823e523af4eSShiraz Saleem 824e523af4eSShiraz Saleem if (pf->rdma_mode & IIDC_RDMA_PROTOCOL_ROCEV2) { 825e523af4eSShiraz Saleem NL_SET_ERR_MSG_MOD(extack, "RoCEv2 is currently enabled. This device cannot enable iWARP and RoCEv2 simultaneously"); 826e523af4eSShiraz Saleem return -EOPNOTSUPP; 827e523af4eSShiraz Saleem } 828e523af4eSShiraz Saleem 829e523af4eSShiraz Saleem return 0; 830e523af4eSShiraz Saleem } 831e523af4eSShiraz Saleem 832e523af4eSShiraz Saleem static const struct devlink_param ice_devlink_params[] = { 833e523af4eSShiraz Saleem DEVLINK_PARAM_GENERIC(ENABLE_ROCE, BIT(DEVLINK_PARAM_CMODE_RUNTIME), 834e523af4eSShiraz Saleem ice_devlink_enable_roce_get, 835e523af4eSShiraz Saleem ice_devlink_enable_roce_set, 836e523af4eSShiraz Saleem ice_devlink_enable_roce_validate), 837e523af4eSShiraz Saleem DEVLINK_PARAM_GENERIC(ENABLE_IWARP, BIT(DEVLINK_PARAM_CMODE_RUNTIME), 838e523af4eSShiraz Saleem ice_devlink_enable_iw_get, 839e523af4eSShiraz Saleem ice_devlink_enable_iw_set, 840e523af4eSShiraz Saleem ice_devlink_enable_iw_validate), 841e523af4eSShiraz Saleem 842e523af4eSShiraz Saleem }; 843e523af4eSShiraz Saleem 8441adf7eadSJacob Keller static void ice_devlink_free(void *devlink_ptr) 8451adf7eadSJacob Keller { 8461adf7eadSJacob Keller devlink_free((struct devlink *)devlink_ptr); 8471adf7eadSJacob Keller } 8481adf7eadSJacob Keller 8491adf7eadSJacob Keller /** 8501adf7eadSJacob Keller * ice_allocate_pf - Allocate devlink and return PF structure pointer 8511adf7eadSJacob Keller * @dev: the device to allocate for 8521adf7eadSJacob Keller * 8531adf7eadSJacob Keller * Allocate a devlink instance for this device and return the private area as 8541adf7eadSJacob Keller * the PF structure. The devlink memory is kept track of through devres by 8551adf7eadSJacob Keller * adding an action to remove it when unwinding. 8561adf7eadSJacob Keller */ 8571adf7eadSJacob Keller struct ice_pf *ice_allocate_pf(struct device *dev) 8581adf7eadSJacob Keller { 8591adf7eadSJacob Keller struct devlink *devlink; 8601adf7eadSJacob Keller 861919d13a7SLeon Romanovsky devlink = devlink_alloc(&ice_devlink_ops, sizeof(struct ice_pf), dev); 8621adf7eadSJacob Keller if (!devlink) 8631adf7eadSJacob Keller return NULL; 8641adf7eadSJacob Keller 8651adf7eadSJacob Keller /* Add an action to teardown the devlink when unwinding the driver */ 8667c1b694aSCai Huoqing if (devm_add_action_or_reset(dev, ice_devlink_free, devlink)) 8671adf7eadSJacob Keller return NULL; 8681adf7eadSJacob Keller 8691adf7eadSJacob Keller return devlink_priv(devlink); 8701adf7eadSJacob Keller } 8711adf7eadSJacob Keller 8721adf7eadSJacob Keller /** 8731adf7eadSJacob Keller * ice_devlink_register - Register devlink interface for this PF 8741adf7eadSJacob Keller * @pf: the PF to register the devlink for. 8751adf7eadSJacob Keller * 8761adf7eadSJacob Keller * Register the devlink instance associated with this physical function. 8771adf7eadSJacob Keller * 8781adf7eadSJacob Keller * Return: zero on success or an error code on failure. 8791adf7eadSJacob Keller */ 880db4278c5SLeon Romanovsky void ice_devlink_register(struct ice_pf *pf) 8811adf7eadSJacob Keller { 8821adf7eadSJacob Keller struct devlink *devlink = priv_to_devlink(pf); 8831adf7eadSJacob Keller 884399e27dbSJacob Keller devlink_set_features(devlink, DEVLINK_F_RELOAD); 885db4278c5SLeon Romanovsky devlink_register(devlink); 8861adf7eadSJacob Keller } 8871adf7eadSJacob Keller 8881adf7eadSJacob Keller /** 8891adf7eadSJacob Keller * ice_devlink_unregister - Unregister devlink resources for this PF. 8901adf7eadSJacob Keller * @pf: the PF structure to cleanup 8911adf7eadSJacob Keller * 8921adf7eadSJacob Keller * Releases resources used by devlink and cleans up associated memory. 8931adf7eadSJacob Keller */ 8941adf7eadSJacob Keller void ice_devlink_unregister(struct ice_pf *pf) 8951adf7eadSJacob Keller { 8961adf7eadSJacob Keller devlink_unregister(priv_to_devlink(pf)); 8971adf7eadSJacob Keller } 8981adf7eadSJacob Keller 8994b889474SMichal Swiatkowski /** 9004b889474SMichal Swiatkowski * ice_devlink_set_switch_id - Set unique switch id based on pci dsn 9014b889474SMichal Swiatkowski * @pf: the PF to create a devlink port for 9024b889474SMichal Swiatkowski * @ppid: struct with switch id information 9034b889474SMichal Swiatkowski */ 9044b889474SMichal Swiatkowski static void 9054b889474SMichal Swiatkowski ice_devlink_set_switch_id(struct ice_pf *pf, struct netdev_phys_item_id *ppid) 9064b889474SMichal Swiatkowski { 9074b889474SMichal Swiatkowski struct pci_dev *pdev = pf->pdev; 9084b889474SMichal Swiatkowski u64 id; 9094b889474SMichal Swiatkowski 9104b889474SMichal Swiatkowski id = pci_get_dsn(pdev); 9114b889474SMichal Swiatkowski 9124b889474SMichal Swiatkowski ppid->id_len = sizeof(id); 9134b889474SMichal Swiatkowski put_unaligned_be64(id, &ppid->id); 9144b889474SMichal Swiatkowski } 9154b889474SMichal Swiatkowski 916e523af4eSShiraz Saleem int ice_devlink_register_params(struct ice_pf *pf) 917e523af4eSShiraz Saleem { 918e523af4eSShiraz Saleem struct devlink *devlink = priv_to_devlink(pf); 919e523af4eSShiraz Saleem union devlink_param_value value; 920e523af4eSShiraz Saleem int err; 921e523af4eSShiraz Saleem 922e523af4eSShiraz Saleem err = devlink_params_register(devlink, ice_devlink_params, 923e523af4eSShiraz Saleem ARRAY_SIZE(ice_devlink_params)); 924e523af4eSShiraz Saleem if (err) 925e523af4eSShiraz Saleem return err; 926e523af4eSShiraz Saleem 927e523af4eSShiraz Saleem value.vbool = false; 928e523af4eSShiraz Saleem devlink_param_driverinit_value_set(devlink, 929e523af4eSShiraz Saleem DEVLINK_PARAM_GENERIC_ID_ENABLE_IWARP, 930e523af4eSShiraz Saleem value); 931e523af4eSShiraz Saleem 932e523af4eSShiraz Saleem value.vbool = test_bit(ICE_FLAG_RDMA_ENA, pf->flags) ? true : false; 933e523af4eSShiraz Saleem devlink_param_driverinit_value_set(devlink, 934e523af4eSShiraz Saleem DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE, 935e523af4eSShiraz Saleem value); 936e523af4eSShiraz Saleem 937e523af4eSShiraz Saleem return 0; 938e523af4eSShiraz Saleem } 939e523af4eSShiraz Saleem 940e523af4eSShiraz Saleem void ice_devlink_unregister_params(struct ice_pf *pf) 941e523af4eSShiraz Saleem { 942e523af4eSShiraz Saleem devlink_params_unregister(priv_to_devlink(pf), ice_devlink_params, 943e523af4eSShiraz Saleem ARRAY_SIZE(ice_devlink_params)); 944e523af4eSShiraz Saleem } 945e523af4eSShiraz Saleem 9461adf7eadSJacob Keller /** 947*26d1c571SAnatolii Gerasymenko * ice_devlink_set_port_split_options - Set port split options 948*26d1c571SAnatolii Gerasymenko * @pf: the PF to set port split options 949*26d1c571SAnatolii Gerasymenko * @attrs: devlink attributes 950*26d1c571SAnatolii Gerasymenko * 951*26d1c571SAnatolii Gerasymenko * Sets devlink port split options based on available FW port options 952*26d1c571SAnatolii Gerasymenko */ 953*26d1c571SAnatolii Gerasymenko static void 954*26d1c571SAnatolii Gerasymenko ice_devlink_set_port_split_options(struct ice_pf *pf, 955*26d1c571SAnatolii Gerasymenko struct devlink_port_attrs *attrs) 956*26d1c571SAnatolii Gerasymenko { 957*26d1c571SAnatolii Gerasymenko struct ice_aqc_get_port_options_elem options[ICE_AQC_PORT_OPT_MAX]; 958*26d1c571SAnatolii Gerasymenko u8 i, active_idx, pending_idx, option_count = ICE_AQC_PORT_OPT_MAX; 959*26d1c571SAnatolii Gerasymenko bool active_valid, pending_valid; 960*26d1c571SAnatolii Gerasymenko int status; 961*26d1c571SAnatolii Gerasymenko 962*26d1c571SAnatolii Gerasymenko status = ice_aq_get_port_options(&pf->hw, options, &option_count, 963*26d1c571SAnatolii Gerasymenko 0, true, &active_idx, &active_valid, 964*26d1c571SAnatolii Gerasymenko &pending_idx, &pending_valid); 965*26d1c571SAnatolii Gerasymenko if (status) { 966*26d1c571SAnatolii Gerasymenko dev_dbg(ice_pf_to_dev(pf), "Couldn't read port split options, err = %d\n", 967*26d1c571SAnatolii Gerasymenko status); 968*26d1c571SAnatolii Gerasymenko return; 969*26d1c571SAnatolii Gerasymenko } 970*26d1c571SAnatolii Gerasymenko 971*26d1c571SAnatolii Gerasymenko /* find the biggest available port split count */ 972*26d1c571SAnatolii Gerasymenko for (i = 0; i < option_count; i++) 973*26d1c571SAnatolii Gerasymenko attrs->lanes = max_t(int, attrs->lanes, options[i].pmd); 974*26d1c571SAnatolii Gerasymenko 975*26d1c571SAnatolii Gerasymenko attrs->splittable = attrs->lanes ? 1 : 0; 976*26d1c571SAnatolii Gerasymenko ice_active_port_option = active_idx; 977*26d1c571SAnatolii Gerasymenko } 978*26d1c571SAnatolii Gerasymenko 979*26d1c571SAnatolii Gerasymenko /** 9802ae0aa47SWojciech Drewek * ice_devlink_create_pf_port - Create a devlink port for this PF 9812ae0aa47SWojciech Drewek * @pf: the PF to create a devlink port for 9821adf7eadSJacob Keller * 9832ae0aa47SWojciech Drewek * Create and register a devlink_port for this PF. 9841adf7eadSJacob Keller * 9851adf7eadSJacob Keller * Return: zero on success or an error code on failure. 9861adf7eadSJacob Keller */ 9872ae0aa47SWojciech Drewek int ice_devlink_create_pf_port(struct ice_pf *pf) 9881adf7eadSJacob Keller { 98971ad8d55SDanielle Ratson struct devlink_port_attrs attrs = {}; 9902ae0aa47SWojciech Drewek struct devlink_port *devlink_port; 99148d40025SJacob Keller struct devlink *devlink; 9922ae0aa47SWojciech Drewek struct ice_vsi *vsi; 99348d40025SJacob Keller struct device *dev; 9941adf7eadSJacob Keller int err; 9951adf7eadSJacob Keller 99648d40025SJacob Keller dev = ice_pf_to_dev(pf); 9972ae0aa47SWojciech Drewek 9982ae0aa47SWojciech Drewek devlink_port = &pf->devlink_port; 9992ae0aa47SWojciech Drewek 10002ae0aa47SWojciech Drewek vsi = ice_get_main_vsi(pf); 10012ae0aa47SWojciech Drewek if (!vsi) 10022ae0aa47SWojciech Drewek return -EIO; 10031adf7eadSJacob Keller 100471ad8d55SDanielle Ratson attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; 10052ae0aa47SWojciech Drewek attrs.phys.port_number = pf->hw.bus.func; 10064b889474SMichal Swiatkowski 1007*26d1c571SAnatolii Gerasymenko /* As FW supports only port split options for whole device, 1008*26d1c571SAnatolii Gerasymenko * set port split options only for first PF. 1009*26d1c571SAnatolii Gerasymenko */ 1010*26d1c571SAnatolii Gerasymenko if (pf->hw.pf_id == 0) 1011*26d1c571SAnatolii Gerasymenko ice_devlink_set_port_split_options(pf, &attrs); 1012*26d1c571SAnatolii Gerasymenko 10134b889474SMichal Swiatkowski ice_devlink_set_switch_id(pf, &attrs.switch_id); 10144b889474SMichal Swiatkowski 10152ae0aa47SWojciech Drewek devlink_port_attrs_set(devlink_port, &attrs); 10162ae0aa47SWojciech Drewek devlink = priv_to_devlink(pf); 10172ae0aa47SWojciech Drewek 10182ae0aa47SWojciech Drewek err = devlink_port_register(devlink, devlink_port, vsi->idx); 10191adf7eadSJacob Keller if (err) { 10202ae0aa47SWojciech Drewek dev_err(dev, "Failed to create devlink port for PF %d, error %d\n", 10212ae0aa47SWojciech Drewek pf->hw.pf_id, err); 10221adf7eadSJacob Keller return err; 10231adf7eadSJacob Keller } 10241adf7eadSJacob Keller 10251adf7eadSJacob Keller return 0; 10261adf7eadSJacob Keller } 10271adf7eadSJacob Keller 10281adf7eadSJacob Keller /** 10292ae0aa47SWojciech Drewek * ice_devlink_destroy_pf_port - Destroy the devlink_port for this PF 10302ae0aa47SWojciech Drewek * @pf: the PF to cleanup 10311adf7eadSJacob Keller * 10322ae0aa47SWojciech Drewek * Unregisters the devlink_port structure associated with this PF. 10331adf7eadSJacob Keller */ 10342ae0aa47SWojciech Drewek void ice_devlink_destroy_pf_port(struct ice_pf *pf) 10351adf7eadSJacob Keller { 10362ae0aa47SWojciech Drewek struct devlink_port *devlink_port; 103748d40025SJacob Keller 10382ae0aa47SWojciech Drewek devlink_port = &pf->devlink_port; 103948d40025SJacob Keller 10402ae0aa47SWojciech Drewek devlink_port_type_clear(devlink_port); 10412ae0aa47SWojciech Drewek devlink_port_unregister(devlink_port); 10422ae0aa47SWojciech Drewek } 10432ae0aa47SWojciech Drewek 10442ae0aa47SWojciech Drewek /** 10452ae0aa47SWojciech Drewek * ice_devlink_create_vf_port - Create a devlink port for this VF 10462ae0aa47SWojciech Drewek * @vf: the VF to create a port for 10472ae0aa47SWojciech Drewek * 10482ae0aa47SWojciech Drewek * Create and register a devlink_port for this VF. 10492ae0aa47SWojciech Drewek * 10502ae0aa47SWojciech Drewek * Return: zero on success or an error code on failure. 10512ae0aa47SWojciech Drewek */ 10522ae0aa47SWojciech Drewek int ice_devlink_create_vf_port(struct ice_vf *vf) 10532ae0aa47SWojciech Drewek { 10542ae0aa47SWojciech Drewek struct devlink_port_attrs attrs = {}; 10552ae0aa47SWojciech Drewek struct devlink_port *devlink_port; 10562ae0aa47SWojciech Drewek struct devlink *devlink; 10572ae0aa47SWojciech Drewek struct ice_vsi *vsi; 10582ae0aa47SWojciech Drewek struct device *dev; 10592ae0aa47SWojciech Drewek struct ice_pf *pf; 10602ae0aa47SWojciech Drewek int err; 10612ae0aa47SWojciech Drewek 10622ae0aa47SWojciech Drewek pf = vf->pf; 10632ae0aa47SWojciech Drewek dev = ice_pf_to_dev(pf); 10642ae0aa47SWojciech Drewek devlink_port = &vf->devlink_port; 10652ae0aa47SWojciech Drewek 1066baeb705fSJacob Keller vsi = ice_get_vf_vsi(vf); 1067baeb705fSJacob Keller if (!vsi) 1068baeb705fSJacob Keller return -EINVAL; 1069baeb705fSJacob Keller 10702ae0aa47SWojciech Drewek attrs.flavour = DEVLINK_PORT_FLAVOUR_PCI_VF; 10712ae0aa47SWojciech Drewek attrs.pci_vf.pf = pf->hw.bus.func; 10722ae0aa47SWojciech Drewek attrs.pci_vf.vf = vf->vf_id; 10732ae0aa47SWojciech Drewek 10744b889474SMichal Swiatkowski ice_devlink_set_switch_id(pf, &attrs.switch_id); 10754b889474SMichal Swiatkowski 10762ae0aa47SWojciech Drewek devlink_port_attrs_set(devlink_port, &attrs); 10772ae0aa47SWojciech Drewek devlink = priv_to_devlink(pf); 10782ae0aa47SWojciech Drewek 10792ae0aa47SWojciech Drewek err = devlink_port_register(devlink, devlink_port, vsi->idx); 10802ae0aa47SWojciech Drewek if (err) { 10812ae0aa47SWojciech Drewek dev_err(dev, "Failed to create devlink port for VF %d, error %d\n", 10822ae0aa47SWojciech Drewek vf->vf_id, err); 10832ae0aa47SWojciech Drewek return err; 10842ae0aa47SWojciech Drewek } 10852ae0aa47SWojciech Drewek 10862ae0aa47SWojciech Drewek return 0; 10872ae0aa47SWojciech Drewek } 10882ae0aa47SWojciech Drewek 10892ae0aa47SWojciech Drewek /** 10902ae0aa47SWojciech Drewek * ice_devlink_destroy_vf_port - Destroy the devlink_port for this VF 10912ae0aa47SWojciech Drewek * @vf: the VF to cleanup 10922ae0aa47SWojciech Drewek * 10932ae0aa47SWojciech Drewek * Unregisters the devlink_port structure associated with this VF. 10942ae0aa47SWojciech Drewek */ 10952ae0aa47SWojciech Drewek void ice_devlink_destroy_vf_port(struct ice_vf *vf) 10962ae0aa47SWojciech Drewek { 10972ae0aa47SWojciech Drewek struct devlink_port *devlink_port; 10982ae0aa47SWojciech Drewek 10992ae0aa47SWojciech Drewek devlink_port = &vf->devlink_port; 11002ae0aa47SWojciech Drewek 11012ae0aa47SWojciech Drewek devlink_port_type_clear(devlink_port); 11022ae0aa47SWojciech Drewek devlink_port_unregister(devlink_port); 11031adf7eadSJacob Keller } 1104dce730f1SJacob Keller 11057b6f9462SPaul M Stillwell Jr #define ICE_DEVLINK_READ_BLK_SIZE (1024 * 1024) 11067b6f9462SPaul M Stillwell Jr 1107dce730f1SJacob Keller /** 110878ad87daSJacob Keller * ice_devlink_nvm_snapshot - Capture a snapshot of the NVM flash contents 1109dce730f1SJacob Keller * @devlink: the devlink instance 1110d4602a9fSAndrew Lunn * @ops: the devlink region being snapshotted 1111dce730f1SJacob Keller * @extack: extended ACK response structure 1112dce730f1SJacob Keller * @data: on exit points to snapshot data buffer 1113dce730f1SJacob Keller * 1114dce730f1SJacob Keller * This function is called in response to the DEVLINK_CMD_REGION_TRIGGER for 111578ad87daSJacob Keller * the nvm-flash devlink region. It captures a snapshot of the full NVM flash 111678ad87daSJacob Keller * contents, including both banks of flash. This snapshot can later be viewed 111778ad87daSJacob Keller * via the devlink-region interface. 111878ad87daSJacob Keller * 111978ad87daSJacob Keller * It captures the flash using the FLASH_ONLY bit set when reading via 112078ad87daSJacob Keller * firmware, so it does not read the current Shadow RAM contents. For that, 112178ad87daSJacob Keller * use the shadow-ram region. 1122dce730f1SJacob Keller * 1123dce730f1SJacob Keller * @returns zero on success, and updates the data pointer. Returns a non-zero 1124dce730f1SJacob Keller * error code on failure. 1125dce730f1SJacob Keller */ 1126dce730f1SJacob Keller static int ice_devlink_nvm_snapshot(struct devlink *devlink, 1127d4602a9fSAndrew Lunn const struct devlink_region_ops *ops, 1128dce730f1SJacob Keller struct netlink_ext_ack *extack, u8 **data) 1129dce730f1SJacob Keller { 1130dce730f1SJacob Keller struct ice_pf *pf = devlink_priv(devlink); 1131dce730f1SJacob Keller struct device *dev = ice_pf_to_dev(pf); 1132dce730f1SJacob Keller struct ice_hw *hw = &pf->hw; 11337b6f9462SPaul M Stillwell Jr u8 *nvm_data, *tmp, i; 11347b6f9462SPaul M Stillwell Jr u32 nvm_size, left; 11357b6f9462SPaul M Stillwell Jr s8 num_blks; 11365518ac2aSTony Nguyen int status; 1137dce730f1SJacob Keller 11389af368faSJacob Keller nvm_size = hw->flash.flash_size; 1139dce730f1SJacob Keller nvm_data = vzalloc(nvm_size); 1140dce730f1SJacob Keller if (!nvm_data) 1141dce730f1SJacob Keller return -ENOMEM; 1142dce730f1SJacob Keller 11437b6f9462SPaul M Stillwell Jr 11447b6f9462SPaul M Stillwell Jr num_blks = DIV_ROUND_UP(nvm_size, ICE_DEVLINK_READ_BLK_SIZE); 11457b6f9462SPaul M Stillwell Jr tmp = nvm_data; 11467b6f9462SPaul M Stillwell Jr left = nvm_size; 11477b6f9462SPaul M Stillwell Jr 11487b6f9462SPaul M Stillwell Jr /* Some systems take longer to read the NVM than others which causes the 11497b6f9462SPaul M Stillwell Jr * FW to reclaim the NVM lock before the entire NVM has been read. Fix 11507b6f9462SPaul M Stillwell Jr * this by breaking the reads of the NVM into smaller chunks that will 11517b6f9462SPaul M Stillwell Jr * probably not take as long. This has some overhead since we are 11527b6f9462SPaul M Stillwell Jr * increasing the number of AQ commands, but it should always work 11537b6f9462SPaul M Stillwell Jr */ 11547b6f9462SPaul M Stillwell Jr for (i = 0; i < num_blks; i++) { 11557b6f9462SPaul M Stillwell Jr u32 read_sz = min_t(u32, ICE_DEVLINK_READ_BLK_SIZE, left); 11567b6f9462SPaul M Stillwell Jr 1157dce730f1SJacob Keller status = ice_acquire_nvm(hw, ICE_RES_READ); 1158dce730f1SJacob Keller if (status) { 1159dce730f1SJacob Keller dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n", 1160dce730f1SJacob Keller status, hw->adminq.sq_last_status); 1161dce730f1SJacob Keller NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore"); 1162dce730f1SJacob Keller vfree(nvm_data); 11637b6f9462SPaul M Stillwell Jr return -EIO; 1164dce730f1SJacob Keller } 1165dce730f1SJacob Keller 11667b6f9462SPaul M Stillwell Jr status = ice_read_flat_nvm(hw, i * ICE_DEVLINK_READ_BLK_SIZE, 11677b6f9462SPaul M Stillwell Jr &read_sz, tmp, false); 1168dce730f1SJacob Keller if (status) { 1169dce730f1SJacob Keller dev_dbg(dev, "ice_read_flat_nvm failed after reading %u bytes, err %d aq_err %d\n", 11707b6f9462SPaul M Stillwell Jr read_sz, status, hw->adminq.sq_last_status); 1171dce730f1SJacob Keller NL_SET_ERR_MSG_MOD(extack, "Failed to read NVM contents"); 1172dce730f1SJacob Keller ice_release_nvm(hw); 1173dce730f1SJacob Keller vfree(nvm_data); 11747b6f9462SPaul M Stillwell Jr return -EIO; 1175dce730f1SJacob Keller } 1176dce730f1SJacob Keller ice_release_nvm(hw); 1177dce730f1SJacob Keller 11787b6f9462SPaul M Stillwell Jr tmp += read_sz; 11797b6f9462SPaul M Stillwell Jr left -= read_sz; 11807b6f9462SPaul M Stillwell Jr } 11817b6f9462SPaul M Stillwell Jr 1182dce730f1SJacob Keller *data = nvm_data; 1183dce730f1SJacob Keller 1184dce730f1SJacob Keller return 0; 1185dce730f1SJacob Keller } 1186dce730f1SJacob Keller 11878d7aab35SJacob Keller /** 118878ad87daSJacob Keller * ice_devlink_sram_snapshot - Capture a snapshot of the Shadow RAM contents 118978ad87daSJacob Keller * @devlink: the devlink instance 119078ad87daSJacob Keller * @ops: the devlink region being snapshotted 119178ad87daSJacob Keller * @extack: extended ACK response structure 119278ad87daSJacob Keller * @data: on exit points to snapshot data buffer 119378ad87daSJacob Keller * 119478ad87daSJacob Keller * This function is called in response to the DEVLINK_CMD_REGION_TRIGGER for 119578ad87daSJacob Keller * the shadow-ram devlink region. It captures a snapshot of the shadow ram 119678ad87daSJacob Keller * contents. This snapshot can later be viewed via the devlink-region 119778ad87daSJacob Keller * interface. 119878ad87daSJacob Keller * 119978ad87daSJacob Keller * @returns zero on success, and updates the data pointer. Returns a non-zero 120078ad87daSJacob Keller * error code on failure. 120178ad87daSJacob Keller */ 120278ad87daSJacob Keller static int 120378ad87daSJacob Keller ice_devlink_sram_snapshot(struct devlink *devlink, 120478ad87daSJacob Keller const struct devlink_region_ops __always_unused *ops, 120578ad87daSJacob Keller struct netlink_ext_ack *extack, u8 **data) 120678ad87daSJacob Keller { 120778ad87daSJacob Keller struct ice_pf *pf = devlink_priv(devlink); 120878ad87daSJacob Keller struct device *dev = ice_pf_to_dev(pf); 120978ad87daSJacob Keller struct ice_hw *hw = &pf->hw; 121078ad87daSJacob Keller u8 *sram_data; 121178ad87daSJacob Keller u32 sram_size; 121278ad87daSJacob Keller int err; 121378ad87daSJacob Keller 121478ad87daSJacob Keller sram_size = hw->flash.sr_words * 2u; 121578ad87daSJacob Keller sram_data = vzalloc(sram_size); 121678ad87daSJacob Keller if (!sram_data) 121778ad87daSJacob Keller return -ENOMEM; 121878ad87daSJacob Keller 121978ad87daSJacob Keller err = ice_acquire_nvm(hw, ICE_RES_READ); 122078ad87daSJacob Keller if (err) { 122178ad87daSJacob Keller dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n", 122278ad87daSJacob Keller err, hw->adminq.sq_last_status); 122378ad87daSJacob Keller NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore"); 122478ad87daSJacob Keller vfree(sram_data); 122578ad87daSJacob Keller return err; 122678ad87daSJacob Keller } 122778ad87daSJacob Keller 122878ad87daSJacob Keller /* Read from the Shadow RAM, rather than directly from NVM */ 122978ad87daSJacob Keller err = ice_read_flat_nvm(hw, 0, &sram_size, sram_data, true); 123078ad87daSJacob Keller if (err) { 123178ad87daSJacob Keller dev_dbg(dev, "ice_read_flat_nvm failed after reading %u bytes, err %d aq_err %d\n", 123278ad87daSJacob Keller sram_size, err, hw->adminq.sq_last_status); 123378ad87daSJacob Keller NL_SET_ERR_MSG_MOD(extack, 123478ad87daSJacob Keller "Failed to read Shadow RAM contents"); 123578ad87daSJacob Keller ice_release_nvm(hw); 123678ad87daSJacob Keller vfree(sram_data); 123778ad87daSJacob Keller return err; 123878ad87daSJacob Keller } 123978ad87daSJacob Keller 124078ad87daSJacob Keller ice_release_nvm(hw); 124178ad87daSJacob Keller 124278ad87daSJacob Keller *data = sram_data; 124378ad87daSJacob Keller 124478ad87daSJacob Keller return 0; 124578ad87daSJacob Keller } 124678ad87daSJacob Keller 124778ad87daSJacob Keller /** 12488d7aab35SJacob Keller * ice_devlink_devcaps_snapshot - Capture snapshot of device capabilities 12498d7aab35SJacob Keller * @devlink: the devlink instance 1250d4602a9fSAndrew Lunn * @ops: the devlink region being snapshotted 12518d7aab35SJacob Keller * @extack: extended ACK response structure 12528d7aab35SJacob Keller * @data: on exit points to snapshot data buffer 12538d7aab35SJacob Keller * 12548d7aab35SJacob Keller * This function is called in response to the DEVLINK_CMD_REGION_TRIGGER for 12558d7aab35SJacob Keller * the device-caps devlink region. It captures a snapshot of the device 12568d7aab35SJacob Keller * capabilities reported by firmware. 12578d7aab35SJacob Keller * 12588d7aab35SJacob Keller * @returns zero on success, and updates the data pointer. Returns a non-zero 12598d7aab35SJacob Keller * error code on failure. 12608d7aab35SJacob Keller */ 12618d7aab35SJacob Keller static int 12628d7aab35SJacob Keller ice_devlink_devcaps_snapshot(struct devlink *devlink, 1263d4602a9fSAndrew Lunn const struct devlink_region_ops *ops, 12648d7aab35SJacob Keller struct netlink_ext_ack *extack, u8 **data) 12658d7aab35SJacob Keller { 12668d7aab35SJacob Keller struct ice_pf *pf = devlink_priv(devlink); 12678d7aab35SJacob Keller struct device *dev = ice_pf_to_dev(pf); 12688d7aab35SJacob Keller struct ice_hw *hw = &pf->hw; 12698d7aab35SJacob Keller void *devcaps; 12705518ac2aSTony Nguyen int status; 12718d7aab35SJacob Keller 12728d7aab35SJacob Keller devcaps = vzalloc(ICE_AQ_MAX_BUF_LEN); 12738d7aab35SJacob Keller if (!devcaps) 12748d7aab35SJacob Keller return -ENOMEM; 12758d7aab35SJacob Keller 12768d7aab35SJacob Keller status = ice_aq_list_caps(hw, devcaps, ICE_AQ_MAX_BUF_LEN, NULL, 12778d7aab35SJacob Keller ice_aqc_opc_list_dev_caps, NULL); 12788d7aab35SJacob Keller if (status) { 12798d7aab35SJacob Keller dev_dbg(dev, "ice_aq_list_caps: failed to read device capabilities, err %d aq_err %d\n", 12808d7aab35SJacob Keller status, hw->adminq.sq_last_status); 12818d7aab35SJacob Keller NL_SET_ERR_MSG_MOD(extack, "Failed to read device capabilities"); 12828d7aab35SJacob Keller vfree(devcaps); 1283c1484691STony Nguyen return status; 12848d7aab35SJacob Keller } 12858d7aab35SJacob Keller 12868d7aab35SJacob Keller *data = (u8 *)devcaps; 12878d7aab35SJacob Keller 12888d7aab35SJacob Keller return 0; 12898d7aab35SJacob Keller } 12908d7aab35SJacob Keller 1291dce730f1SJacob Keller static const struct devlink_region_ops ice_nvm_region_ops = { 1292dce730f1SJacob Keller .name = "nvm-flash", 1293dce730f1SJacob Keller .destructor = vfree, 1294dce730f1SJacob Keller .snapshot = ice_devlink_nvm_snapshot, 1295dce730f1SJacob Keller }; 1296dce730f1SJacob Keller 129778ad87daSJacob Keller static const struct devlink_region_ops ice_sram_region_ops = { 129878ad87daSJacob Keller .name = "shadow-ram", 129978ad87daSJacob Keller .destructor = vfree, 130078ad87daSJacob Keller .snapshot = ice_devlink_sram_snapshot, 130178ad87daSJacob Keller }; 130278ad87daSJacob Keller 13038d7aab35SJacob Keller static const struct devlink_region_ops ice_devcaps_region_ops = { 13048d7aab35SJacob Keller .name = "device-caps", 13058d7aab35SJacob Keller .destructor = vfree, 13068d7aab35SJacob Keller .snapshot = ice_devlink_devcaps_snapshot, 13078d7aab35SJacob Keller }; 13088d7aab35SJacob Keller 1309dce730f1SJacob Keller /** 1310dce730f1SJacob Keller * ice_devlink_init_regions - Initialize devlink regions 1311dce730f1SJacob Keller * @pf: the PF device structure 1312dce730f1SJacob Keller * 1313dce730f1SJacob Keller * Create devlink regions used to enable access to dump the contents of the 1314dce730f1SJacob Keller * flash memory on the device. 1315dce730f1SJacob Keller */ 1316dce730f1SJacob Keller void ice_devlink_init_regions(struct ice_pf *pf) 1317dce730f1SJacob Keller { 1318dce730f1SJacob Keller struct devlink *devlink = priv_to_devlink(pf); 1319dce730f1SJacob Keller struct device *dev = ice_pf_to_dev(pf); 132078ad87daSJacob Keller u64 nvm_size, sram_size; 1321dce730f1SJacob Keller 13229af368faSJacob Keller nvm_size = pf->hw.flash.flash_size; 1323dce730f1SJacob Keller pf->nvm_region = devlink_region_create(devlink, &ice_nvm_region_ops, 1, 1324dce730f1SJacob Keller nvm_size); 1325dce730f1SJacob Keller if (IS_ERR(pf->nvm_region)) { 1326dce730f1SJacob Keller dev_err(dev, "failed to create NVM devlink region, err %ld\n", 1327dce730f1SJacob Keller PTR_ERR(pf->nvm_region)); 1328dce730f1SJacob Keller pf->nvm_region = NULL; 1329dce730f1SJacob Keller } 13308d7aab35SJacob Keller 133178ad87daSJacob Keller sram_size = pf->hw.flash.sr_words * 2u; 133278ad87daSJacob Keller pf->sram_region = devlink_region_create(devlink, &ice_sram_region_ops, 133378ad87daSJacob Keller 1, sram_size); 133478ad87daSJacob Keller if (IS_ERR(pf->sram_region)) { 133578ad87daSJacob Keller dev_err(dev, "failed to create shadow-ram devlink region, err %ld\n", 133678ad87daSJacob Keller PTR_ERR(pf->sram_region)); 133778ad87daSJacob Keller pf->sram_region = NULL; 133878ad87daSJacob Keller } 133978ad87daSJacob Keller 13408d7aab35SJacob Keller pf->devcaps_region = devlink_region_create(devlink, 13418d7aab35SJacob Keller &ice_devcaps_region_ops, 10, 13428d7aab35SJacob Keller ICE_AQ_MAX_BUF_LEN); 13438d7aab35SJacob Keller if (IS_ERR(pf->devcaps_region)) { 13448d7aab35SJacob Keller dev_err(dev, "failed to create device-caps devlink region, err %ld\n", 13458d7aab35SJacob Keller PTR_ERR(pf->devcaps_region)); 13468d7aab35SJacob Keller pf->devcaps_region = NULL; 13478d7aab35SJacob Keller } 1348dce730f1SJacob Keller } 1349dce730f1SJacob Keller 1350dce730f1SJacob Keller /** 1351dce730f1SJacob Keller * ice_devlink_destroy_regions - Destroy devlink regions 1352dce730f1SJacob Keller * @pf: the PF device structure 1353dce730f1SJacob Keller * 1354dce730f1SJacob Keller * Remove previously created regions for this PF. 1355dce730f1SJacob Keller */ 1356dce730f1SJacob Keller void ice_devlink_destroy_regions(struct ice_pf *pf) 1357dce730f1SJacob Keller { 1358dce730f1SJacob Keller if (pf->nvm_region) 1359dce730f1SJacob Keller devlink_region_destroy(pf->nvm_region); 136078ad87daSJacob Keller 136178ad87daSJacob Keller if (pf->sram_region) 136278ad87daSJacob Keller devlink_region_destroy(pf->sram_region); 136378ad87daSJacob Keller 13648d7aab35SJacob Keller if (pf->devcaps_region) 13658d7aab35SJacob Keller devlink_region_destroy(pf->devcaps_region); 1366dce730f1SJacob Keller } 1367