10545cc86SMichal Swiatkowski // SPDX-License-Identifier: GPL-2.0 20545cc86SMichal Swiatkowski /* Copyright (c) 2020, Intel Corporation. */ 30545cc86SMichal Swiatkowski 40545cc86SMichal Swiatkowski #include <linux/vmalloc.h> 50545cc86SMichal Swiatkowski 60545cc86SMichal Swiatkowski #include "ice.h" 70545cc86SMichal Swiatkowski #include "ice_lib.h" 80545cc86SMichal Swiatkowski #include "devlink.h" 90545cc86SMichal Swiatkowski #include "ice_eswitch.h" 100545cc86SMichal Swiatkowski #include "ice_fw_update.h" 110545cc86SMichal Swiatkowski #include "ice_dcb_lib.h" 120545cc86SMichal Swiatkowski 130545cc86SMichal Swiatkowski /* context for devlink info version reporting */ 140545cc86SMichal Swiatkowski struct ice_info_ctx { 150545cc86SMichal Swiatkowski char buf[128]; 160545cc86SMichal Swiatkowski struct ice_orom_info pending_orom; 170545cc86SMichal Swiatkowski struct ice_nvm_info pending_nvm; 180545cc86SMichal Swiatkowski struct ice_netlist_info pending_netlist; 190545cc86SMichal Swiatkowski struct ice_hw_dev_caps dev_caps; 200545cc86SMichal Swiatkowski }; 210545cc86SMichal Swiatkowski 220545cc86SMichal Swiatkowski /* The following functions are used to format specific strings for various 230545cc86SMichal Swiatkowski * devlink info versions. The ctx parameter is used to provide the storage 240545cc86SMichal Swiatkowski * buffer, as well as any ancillary information calculated when the info 250545cc86SMichal Swiatkowski * request was made. 260545cc86SMichal Swiatkowski * 270545cc86SMichal Swiatkowski * If a version does not exist, for example when attempting to get the 280545cc86SMichal Swiatkowski * inactive version of flash when there is no pending update, the function 290545cc86SMichal Swiatkowski * should leave the buffer in the ctx structure empty. 300545cc86SMichal Swiatkowski */ 310545cc86SMichal Swiatkowski 320545cc86SMichal Swiatkowski static void ice_info_get_dsn(struct ice_pf *pf, struct ice_info_ctx *ctx) 330545cc86SMichal Swiatkowski { 340545cc86SMichal Swiatkowski u8 dsn[8]; 350545cc86SMichal Swiatkowski 360545cc86SMichal Swiatkowski /* Copy the DSN into an array in Big Endian format */ 370545cc86SMichal Swiatkowski put_unaligned_be64(pci_get_dsn(pf->pdev), dsn); 380545cc86SMichal Swiatkowski 390545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%8phD", dsn); 400545cc86SMichal Swiatkowski } 410545cc86SMichal Swiatkowski 420545cc86SMichal Swiatkowski static void ice_info_pba(struct ice_pf *pf, struct ice_info_ctx *ctx) 430545cc86SMichal Swiatkowski { 440545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 450545cc86SMichal Swiatkowski int status; 460545cc86SMichal Swiatkowski 470545cc86SMichal Swiatkowski status = ice_read_pba_string(hw, (u8 *)ctx->buf, sizeof(ctx->buf)); 480545cc86SMichal Swiatkowski if (status) 490545cc86SMichal Swiatkowski /* We failed to locate the PBA, so just skip this entry */ 500545cc86SMichal Swiatkowski dev_dbg(ice_pf_to_dev(pf), "Failed to read Product Board Assembly string, status %d\n", 510545cc86SMichal Swiatkowski status); 520545cc86SMichal Swiatkowski } 530545cc86SMichal Swiatkowski 540545cc86SMichal Swiatkowski static void ice_info_fw_mgmt(struct ice_pf *pf, struct ice_info_ctx *ctx) 550545cc86SMichal Swiatkowski { 560545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 570545cc86SMichal Swiatkowski 580545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", 590545cc86SMichal Swiatkowski hw->fw_maj_ver, hw->fw_min_ver, hw->fw_patch); 600545cc86SMichal Swiatkowski } 610545cc86SMichal Swiatkowski 620545cc86SMichal Swiatkowski static void ice_info_fw_api(struct ice_pf *pf, struct ice_info_ctx *ctx) 630545cc86SMichal Swiatkowski { 640545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 650545cc86SMichal Swiatkowski 660545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", hw->api_maj_ver, 670545cc86SMichal Swiatkowski hw->api_min_ver, hw->api_patch); 680545cc86SMichal Swiatkowski } 690545cc86SMichal Swiatkowski 700545cc86SMichal Swiatkowski static void ice_info_fw_build(struct ice_pf *pf, struct ice_info_ctx *ctx) 710545cc86SMichal Swiatkowski { 720545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 730545cc86SMichal Swiatkowski 740545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", hw->fw_build); 750545cc86SMichal Swiatkowski } 760545cc86SMichal Swiatkowski 770545cc86SMichal Swiatkowski static void ice_info_orom_ver(struct ice_pf *pf, struct ice_info_ctx *ctx) 780545cc86SMichal Swiatkowski { 790545cc86SMichal Swiatkowski struct ice_orom_info *orom = &pf->hw.flash.orom; 800545cc86SMichal Swiatkowski 810545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", 820545cc86SMichal Swiatkowski orom->major, orom->build, orom->patch); 830545cc86SMichal Swiatkowski } 840545cc86SMichal Swiatkowski 850545cc86SMichal Swiatkowski static void 860545cc86SMichal Swiatkowski ice_info_pending_orom_ver(struct ice_pf __always_unused *pf, 870545cc86SMichal Swiatkowski struct ice_info_ctx *ctx) 880545cc86SMichal Swiatkowski { 890545cc86SMichal Swiatkowski struct ice_orom_info *orom = &ctx->pending_orom; 900545cc86SMichal Swiatkowski 910545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_orom) 920545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", 930545cc86SMichal Swiatkowski orom->major, orom->build, orom->patch); 940545cc86SMichal Swiatkowski } 950545cc86SMichal Swiatkowski 960545cc86SMichal Swiatkowski static void ice_info_nvm_ver(struct ice_pf *pf, struct ice_info_ctx *ctx) 970545cc86SMichal Swiatkowski { 980545cc86SMichal Swiatkowski struct ice_nvm_info *nvm = &pf->hw.flash.nvm; 990545cc86SMichal Swiatkowski 1000545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", nvm->major, nvm->minor); 1010545cc86SMichal Swiatkowski } 1020545cc86SMichal Swiatkowski 1030545cc86SMichal Swiatkowski static void 1040545cc86SMichal Swiatkowski ice_info_pending_nvm_ver(struct ice_pf __always_unused *pf, 1050545cc86SMichal Swiatkowski struct ice_info_ctx *ctx) 1060545cc86SMichal Swiatkowski { 1070545cc86SMichal Swiatkowski struct ice_nvm_info *nvm = &ctx->pending_nvm; 1080545cc86SMichal Swiatkowski 1090545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_nvm) 1100545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", 1110545cc86SMichal Swiatkowski nvm->major, nvm->minor); 1120545cc86SMichal Swiatkowski } 1130545cc86SMichal Swiatkowski 1140545cc86SMichal Swiatkowski static void ice_info_eetrack(struct ice_pf *pf, struct ice_info_ctx *ctx) 1150545cc86SMichal Swiatkowski { 1160545cc86SMichal Swiatkowski struct ice_nvm_info *nvm = &pf->hw.flash.nvm; 1170545cc86SMichal Swiatkowski 1180545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm->eetrack); 1190545cc86SMichal Swiatkowski } 1200545cc86SMichal Swiatkowski 1210545cc86SMichal Swiatkowski static void 1220545cc86SMichal Swiatkowski ice_info_pending_eetrack(struct ice_pf *pf, struct ice_info_ctx *ctx) 1230545cc86SMichal Swiatkowski { 1240545cc86SMichal Swiatkowski struct ice_nvm_info *nvm = &ctx->pending_nvm; 1250545cc86SMichal Swiatkowski 1260545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_nvm) 1270545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm->eetrack); 1280545cc86SMichal Swiatkowski } 1290545cc86SMichal Swiatkowski 1300545cc86SMichal Swiatkowski static void ice_info_ddp_pkg_name(struct ice_pf *pf, struct ice_info_ctx *ctx) 1310545cc86SMichal Swiatkowski { 1320545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 1330545cc86SMichal Swiatkowski 1340545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%s", hw->active_pkg_name); 1350545cc86SMichal Swiatkowski } 1360545cc86SMichal Swiatkowski 1370545cc86SMichal Swiatkowski static void 1380545cc86SMichal Swiatkowski ice_info_ddp_pkg_version(struct ice_pf *pf, struct ice_info_ctx *ctx) 1390545cc86SMichal Swiatkowski { 1400545cc86SMichal Swiatkowski struct ice_pkg_ver *pkg = &pf->hw.active_pkg_ver; 1410545cc86SMichal Swiatkowski 1420545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u.%u", 1430545cc86SMichal Swiatkowski pkg->major, pkg->minor, pkg->update, pkg->draft); 1440545cc86SMichal Swiatkowski } 1450545cc86SMichal Swiatkowski 1460545cc86SMichal Swiatkowski static void 1470545cc86SMichal Swiatkowski ice_info_ddp_pkg_bundle_id(struct ice_pf *pf, struct ice_info_ctx *ctx) 1480545cc86SMichal Swiatkowski { 1490545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", pf->hw.active_track_id); 1500545cc86SMichal Swiatkowski } 1510545cc86SMichal Swiatkowski 1520545cc86SMichal Swiatkowski static void ice_info_netlist_ver(struct ice_pf *pf, struct ice_info_ctx *ctx) 1530545cc86SMichal Swiatkowski { 1540545cc86SMichal Swiatkowski struct ice_netlist_info *netlist = &pf->hw.flash.netlist; 1550545cc86SMichal Swiatkowski 1560545cc86SMichal Swiatkowski /* The netlist version fields are BCD formatted */ 1570545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x", 1580545cc86SMichal Swiatkowski netlist->major, netlist->minor, 1590545cc86SMichal Swiatkowski netlist->type >> 16, netlist->type & 0xFFFF, 1600545cc86SMichal Swiatkowski netlist->rev, netlist->cust_ver); 1610545cc86SMichal Swiatkowski } 1620545cc86SMichal Swiatkowski 1630545cc86SMichal Swiatkowski static void ice_info_netlist_build(struct ice_pf *pf, struct ice_info_ctx *ctx) 1640545cc86SMichal Swiatkowski { 1650545cc86SMichal Swiatkowski struct ice_netlist_info *netlist = &pf->hw.flash.netlist; 1660545cc86SMichal Swiatkowski 1670545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash); 1680545cc86SMichal Swiatkowski } 1690545cc86SMichal Swiatkowski 1700545cc86SMichal Swiatkowski static void 1710545cc86SMichal Swiatkowski ice_info_pending_netlist_ver(struct ice_pf __always_unused *pf, 1720545cc86SMichal Swiatkowski struct ice_info_ctx *ctx) 1730545cc86SMichal Swiatkowski { 1740545cc86SMichal Swiatkowski struct ice_netlist_info *netlist = &ctx->pending_netlist; 1750545cc86SMichal Swiatkowski 1760545cc86SMichal Swiatkowski /* The netlist version fields are BCD formatted */ 1770545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_netlist) 1780545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x", 1790545cc86SMichal Swiatkowski netlist->major, netlist->minor, 1800545cc86SMichal Swiatkowski netlist->type >> 16, netlist->type & 0xFFFF, 1810545cc86SMichal Swiatkowski netlist->rev, netlist->cust_ver); 1820545cc86SMichal Swiatkowski } 1830545cc86SMichal Swiatkowski 1840545cc86SMichal Swiatkowski static void 1850545cc86SMichal Swiatkowski ice_info_pending_netlist_build(struct ice_pf __always_unused *pf, 1860545cc86SMichal Swiatkowski struct ice_info_ctx *ctx) 1870545cc86SMichal Swiatkowski { 1880545cc86SMichal Swiatkowski struct ice_netlist_info *netlist = &ctx->pending_netlist; 1890545cc86SMichal Swiatkowski 1900545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_netlist) 1910545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash); 1920545cc86SMichal Swiatkowski } 1930545cc86SMichal Swiatkowski 1940545cc86SMichal Swiatkowski static void ice_info_cgu_fw_build(struct ice_pf *pf, struct ice_info_ctx *ctx) 1950545cc86SMichal Swiatkowski { 1960545cc86SMichal Swiatkowski u32 id, cfg_ver, fw_ver; 1970545cc86SMichal Swiatkowski 1980545cc86SMichal Swiatkowski if (!ice_is_feature_supported(pf, ICE_F_CGU)) 1990545cc86SMichal Swiatkowski return; 2000545cc86SMichal Swiatkowski if (ice_aq_get_cgu_info(&pf->hw, &id, &cfg_ver, &fw_ver)) 2010545cc86SMichal Swiatkowski return; 2020545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", id, cfg_ver, fw_ver); 2030545cc86SMichal Swiatkowski } 2040545cc86SMichal Swiatkowski 2050545cc86SMichal Swiatkowski static void ice_info_cgu_id(struct ice_pf *pf, struct ice_info_ctx *ctx) 2060545cc86SMichal Swiatkowski { 2070545cc86SMichal Swiatkowski if (!ice_is_feature_supported(pf, ICE_F_CGU)) 2080545cc86SMichal Swiatkowski return; 2090545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%u", pf->hw.cgu_part_number); 2100545cc86SMichal Swiatkowski } 2110545cc86SMichal Swiatkowski 2120545cc86SMichal Swiatkowski #define fixed(key, getter) { ICE_VERSION_FIXED, key, getter, NULL } 2130545cc86SMichal Swiatkowski #define running(key, getter) { ICE_VERSION_RUNNING, key, getter, NULL } 2140545cc86SMichal Swiatkowski #define stored(key, getter, fallback) { ICE_VERSION_STORED, key, getter, fallback } 2150545cc86SMichal Swiatkowski 2160545cc86SMichal Swiatkowski /* The combined() macro inserts both the running entry as well as a stored 2170545cc86SMichal Swiatkowski * entry. The running entry will always report the version from the active 2180545cc86SMichal Swiatkowski * handler. The stored entry will first try the pending handler, and fallback 2190545cc86SMichal Swiatkowski * to the active handler if the pending function does not report a version. 2200545cc86SMichal Swiatkowski * The pending handler should check the status of a pending update for the 2210545cc86SMichal Swiatkowski * relevant flash component. It should only fill in the buffer in the case 2220545cc86SMichal Swiatkowski * where a valid pending version is available. This ensures that the related 2230545cc86SMichal Swiatkowski * stored and running versions remain in sync, and that stored versions are 2240545cc86SMichal Swiatkowski * correctly reported as expected. 2250545cc86SMichal Swiatkowski */ 2260545cc86SMichal Swiatkowski #define combined(key, active, pending) \ 2270545cc86SMichal Swiatkowski running(key, active), \ 2280545cc86SMichal Swiatkowski stored(key, pending, active) 2290545cc86SMichal Swiatkowski 2300545cc86SMichal Swiatkowski enum ice_version_type { 2310545cc86SMichal Swiatkowski ICE_VERSION_FIXED, 2320545cc86SMichal Swiatkowski ICE_VERSION_RUNNING, 2330545cc86SMichal Swiatkowski ICE_VERSION_STORED, 2340545cc86SMichal Swiatkowski }; 2350545cc86SMichal Swiatkowski 2360545cc86SMichal Swiatkowski static const struct ice_devlink_version { 2370545cc86SMichal Swiatkowski enum ice_version_type type; 2380545cc86SMichal Swiatkowski const char *key; 2390545cc86SMichal Swiatkowski void (*getter)(struct ice_pf *pf, struct ice_info_ctx *ctx); 2400545cc86SMichal Swiatkowski void (*fallback)(struct ice_pf *pf, struct ice_info_ctx *ctx); 2410545cc86SMichal Swiatkowski } ice_devlink_versions[] = { 2420545cc86SMichal Swiatkowski fixed(DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, ice_info_pba), 2430545cc86SMichal Swiatkowski running(DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, ice_info_fw_mgmt), 2440545cc86SMichal Swiatkowski running("fw.mgmt.api", ice_info_fw_api), 2450545cc86SMichal Swiatkowski running("fw.mgmt.build", ice_info_fw_build), 2460545cc86SMichal Swiatkowski combined(DEVLINK_INFO_VERSION_GENERIC_FW_UNDI, ice_info_orom_ver, ice_info_pending_orom_ver), 2470545cc86SMichal Swiatkowski combined("fw.psid.api", ice_info_nvm_ver, ice_info_pending_nvm_ver), 2480545cc86SMichal Swiatkowski combined(DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID, ice_info_eetrack, ice_info_pending_eetrack), 2490545cc86SMichal Swiatkowski running("fw.app.name", ice_info_ddp_pkg_name), 2500545cc86SMichal Swiatkowski running(DEVLINK_INFO_VERSION_GENERIC_FW_APP, ice_info_ddp_pkg_version), 2510545cc86SMichal Swiatkowski running("fw.app.bundle_id", ice_info_ddp_pkg_bundle_id), 2520545cc86SMichal Swiatkowski combined("fw.netlist", ice_info_netlist_ver, ice_info_pending_netlist_ver), 2530545cc86SMichal Swiatkowski combined("fw.netlist.build", ice_info_netlist_build, ice_info_pending_netlist_build), 2540545cc86SMichal Swiatkowski fixed("cgu.id", ice_info_cgu_id), 2550545cc86SMichal Swiatkowski running("fw.cgu", ice_info_cgu_fw_build), 2560545cc86SMichal Swiatkowski }; 2570545cc86SMichal Swiatkowski 2580545cc86SMichal Swiatkowski /** 2590545cc86SMichal Swiatkowski * ice_devlink_info_get - .info_get devlink handler 2600545cc86SMichal Swiatkowski * @devlink: devlink instance structure 2610545cc86SMichal Swiatkowski * @req: the devlink info request 2620545cc86SMichal Swiatkowski * @extack: extended netdev ack structure 2630545cc86SMichal Swiatkowski * 2640545cc86SMichal Swiatkowski * Callback for the devlink .info_get operation. Reports information about the 2650545cc86SMichal Swiatkowski * device. 2660545cc86SMichal Swiatkowski * 2670545cc86SMichal Swiatkowski * Return: zero on success or an error code on failure. 2680545cc86SMichal Swiatkowski */ 2690545cc86SMichal Swiatkowski static int ice_devlink_info_get(struct devlink *devlink, 2700545cc86SMichal Swiatkowski struct devlink_info_req *req, 2710545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 2720545cc86SMichal Swiatkowski { 2730545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 2740545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 2750545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 2760545cc86SMichal Swiatkowski struct ice_info_ctx *ctx; 2770545cc86SMichal Swiatkowski size_t i; 2780545cc86SMichal Swiatkowski int err; 2790545cc86SMichal Swiatkowski 2800545cc86SMichal Swiatkowski err = ice_wait_for_reset(pf, 10 * HZ); 2810545cc86SMichal Swiatkowski if (err) { 2820545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Device is busy resetting"); 2830545cc86SMichal Swiatkowski return err; 2840545cc86SMichal Swiatkowski } 2850545cc86SMichal Swiatkowski 2860545cc86SMichal Swiatkowski ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 2870545cc86SMichal Swiatkowski if (!ctx) 2880545cc86SMichal Swiatkowski return -ENOMEM; 2890545cc86SMichal Swiatkowski 2900545cc86SMichal Swiatkowski /* discover capabilities first */ 2910545cc86SMichal Swiatkowski err = ice_discover_dev_caps(hw, &ctx->dev_caps); 2920545cc86SMichal Swiatkowski if (err) { 2930545cc86SMichal Swiatkowski dev_dbg(dev, "Failed to discover device capabilities, status %d aq_err %s\n", 2940545cc86SMichal Swiatkowski err, ice_aq_str(hw->adminq.sq_last_status)); 2950545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unable to discover device capabilities"); 2960545cc86SMichal Swiatkowski goto out_free_ctx; 2970545cc86SMichal Swiatkowski } 2980545cc86SMichal Swiatkowski 2990545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_orom) { 3000545cc86SMichal Swiatkowski err = ice_get_inactive_orom_ver(hw, &ctx->pending_orom); 3010545cc86SMichal Swiatkowski if (err) { 3020545cc86SMichal Swiatkowski dev_dbg(dev, "Unable to read inactive Option ROM version data, status %d aq_err %s\n", 3030545cc86SMichal Swiatkowski err, ice_aq_str(hw->adminq.sq_last_status)); 3040545cc86SMichal Swiatkowski 3050545cc86SMichal Swiatkowski /* disable display of pending Option ROM */ 3060545cc86SMichal Swiatkowski ctx->dev_caps.common_cap.nvm_update_pending_orom = false; 3070545cc86SMichal Swiatkowski } 3080545cc86SMichal Swiatkowski } 3090545cc86SMichal Swiatkowski 3100545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_nvm) { 3110545cc86SMichal Swiatkowski err = ice_get_inactive_nvm_ver(hw, &ctx->pending_nvm); 3120545cc86SMichal Swiatkowski if (err) { 3130545cc86SMichal Swiatkowski dev_dbg(dev, "Unable to read inactive NVM version data, status %d aq_err %s\n", 3140545cc86SMichal Swiatkowski err, ice_aq_str(hw->adminq.sq_last_status)); 3150545cc86SMichal Swiatkowski 3160545cc86SMichal Swiatkowski /* disable display of pending Option ROM */ 3170545cc86SMichal Swiatkowski ctx->dev_caps.common_cap.nvm_update_pending_nvm = false; 3180545cc86SMichal Swiatkowski } 3190545cc86SMichal Swiatkowski } 3200545cc86SMichal Swiatkowski 3210545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_netlist) { 3220545cc86SMichal Swiatkowski err = ice_get_inactive_netlist_ver(hw, &ctx->pending_netlist); 3230545cc86SMichal Swiatkowski if (err) { 3240545cc86SMichal Swiatkowski dev_dbg(dev, "Unable to read inactive Netlist version data, status %d aq_err %s\n", 3250545cc86SMichal Swiatkowski err, ice_aq_str(hw->adminq.sq_last_status)); 3260545cc86SMichal Swiatkowski 3270545cc86SMichal Swiatkowski /* disable display of pending Option ROM */ 3280545cc86SMichal Swiatkowski ctx->dev_caps.common_cap.nvm_update_pending_netlist = false; 3290545cc86SMichal Swiatkowski } 3300545cc86SMichal Swiatkowski } 3310545cc86SMichal Swiatkowski 3320545cc86SMichal Swiatkowski ice_info_get_dsn(pf, ctx); 3330545cc86SMichal Swiatkowski 3340545cc86SMichal Swiatkowski err = devlink_info_serial_number_put(req, ctx->buf); 3350545cc86SMichal Swiatkowski if (err) { 3360545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unable to set serial number"); 3370545cc86SMichal Swiatkowski goto out_free_ctx; 3380545cc86SMichal Swiatkowski } 3390545cc86SMichal Swiatkowski 3400545cc86SMichal Swiatkowski for (i = 0; i < ARRAY_SIZE(ice_devlink_versions); i++) { 3410545cc86SMichal Swiatkowski enum ice_version_type type = ice_devlink_versions[i].type; 3420545cc86SMichal Swiatkowski const char *key = ice_devlink_versions[i].key; 3430545cc86SMichal Swiatkowski 3440545cc86SMichal Swiatkowski memset(ctx->buf, 0, sizeof(ctx->buf)); 3450545cc86SMichal Swiatkowski 3460545cc86SMichal Swiatkowski ice_devlink_versions[i].getter(pf, ctx); 3470545cc86SMichal Swiatkowski 3480545cc86SMichal Swiatkowski /* If the default getter doesn't report a version, use the 3490545cc86SMichal Swiatkowski * fallback function. This is primarily useful in the case of 3500545cc86SMichal Swiatkowski * "stored" versions that want to report the same value as the 3510545cc86SMichal Swiatkowski * running version in the normal case of no pending update. 3520545cc86SMichal Swiatkowski */ 3530545cc86SMichal Swiatkowski if (ctx->buf[0] == '\0' && ice_devlink_versions[i].fallback) 3540545cc86SMichal Swiatkowski ice_devlink_versions[i].fallback(pf, ctx); 3550545cc86SMichal Swiatkowski 3560545cc86SMichal Swiatkowski /* Do not report missing versions */ 3570545cc86SMichal Swiatkowski if (ctx->buf[0] == '\0') 3580545cc86SMichal Swiatkowski continue; 3590545cc86SMichal Swiatkowski 3600545cc86SMichal Swiatkowski switch (type) { 3610545cc86SMichal Swiatkowski case ICE_VERSION_FIXED: 3620545cc86SMichal Swiatkowski err = devlink_info_version_fixed_put(req, key, ctx->buf); 3630545cc86SMichal Swiatkowski if (err) { 3640545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unable to set fixed version"); 3650545cc86SMichal Swiatkowski goto out_free_ctx; 3660545cc86SMichal Swiatkowski } 3670545cc86SMichal Swiatkowski break; 3680545cc86SMichal Swiatkowski case ICE_VERSION_RUNNING: 3690545cc86SMichal Swiatkowski err = devlink_info_version_running_put(req, key, ctx->buf); 3700545cc86SMichal Swiatkowski if (err) { 3710545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unable to set running version"); 3720545cc86SMichal Swiatkowski goto out_free_ctx; 3730545cc86SMichal Swiatkowski } 3740545cc86SMichal Swiatkowski break; 3750545cc86SMichal Swiatkowski case ICE_VERSION_STORED: 3760545cc86SMichal Swiatkowski err = devlink_info_version_stored_put(req, key, ctx->buf); 3770545cc86SMichal Swiatkowski if (err) { 3780545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unable to set stored version"); 3790545cc86SMichal Swiatkowski goto out_free_ctx; 3800545cc86SMichal Swiatkowski } 3810545cc86SMichal Swiatkowski break; 3820545cc86SMichal Swiatkowski } 3830545cc86SMichal Swiatkowski } 3840545cc86SMichal Swiatkowski 3850545cc86SMichal Swiatkowski out_free_ctx: 3860545cc86SMichal Swiatkowski kfree(ctx); 3870545cc86SMichal Swiatkowski return err; 3880545cc86SMichal Swiatkowski } 3890545cc86SMichal Swiatkowski 3900545cc86SMichal Swiatkowski /** 3910545cc86SMichal Swiatkowski * ice_devlink_reload_empr_start - Start EMP reset to activate new firmware 3920545cc86SMichal Swiatkowski * @pf: pointer to the pf instance 3930545cc86SMichal Swiatkowski * @extack: netlink extended ACK structure 3940545cc86SMichal Swiatkowski * 3950545cc86SMichal Swiatkowski * Allow user to activate new Embedded Management Processor firmware by 3960545cc86SMichal Swiatkowski * issuing device specific EMP reset. Called in response to 3970545cc86SMichal Swiatkowski * a DEVLINK_CMD_RELOAD with the DEVLINK_RELOAD_ACTION_FW_ACTIVATE. 3980545cc86SMichal Swiatkowski * 3990545cc86SMichal Swiatkowski * Note that teardown and rebuild of the driver state happens automatically as 4000545cc86SMichal Swiatkowski * part of an interrupt and watchdog task. This is because all physical 4010545cc86SMichal Swiatkowski * functions on the device must be able to reset when an EMP reset occurs from 4020545cc86SMichal Swiatkowski * any source. 4030545cc86SMichal Swiatkowski */ 4040545cc86SMichal Swiatkowski static int 4050545cc86SMichal Swiatkowski ice_devlink_reload_empr_start(struct ice_pf *pf, 4060545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 4070545cc86SMichal Swiatkowski { 4080545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 4090545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 4100545cc86SMichal Swiatkowski u8 pending; 4110545cc86SMichal Swiatkowski int err; 4120545cc86SMichal Swiatkowski 4130545cc86SMichal Swiatkowski err = ice_get_pending_updates(pf, &pending, extack); 4140545cc86SMichal Swiatkowski if (err) 4150545cc86SMichal Swiatkowski return err; 4160545cc86SMichal Swiatkowski 4170545cc86SMichal Swiatkowski /* pending is a bitmask of which flash banks have a pending update, 4180545cc86SMichal Swiatkowski * including the main NVM bank, the Option ROM bank, and the netlist 4190545cc86SMichal Swiatkowski * bank. If any of these bits are set, then there is a pending update 4200545cc86SMichal Swiatkowski * waiting to be activated. 4210545cc86SMichal Swiatkowski */ 4220545cc86SMichal Swiatkowski if (!pending) { 4230545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "No pending firmware update"); 4240545cc86SMichal Swiatkowski return -ECANCELED; 4250545cc86SMichal Swiatkowski } 4260545cc86SMichal Swiatkowski 4270545cc86SMichal Swiatkowski if (pf->fw_emp_reset_disabled) { 4280545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "EMP reset is not available. To activate firmware, a reboot or power cycle is needed"); 4290545cc86SMichal Swiatkowski return -ECANCELED; 4300545cc86SMichal Swiatkowski } 4310545cc86SMichal Swiatkowski 4320545cc86SMichal Swiatkowski dev_dbg(dev, "Issuing device EMP reset to activate firmware\n"); 4330545cc86SMichal Swiatkowski 4340545cc86SMichal Swiatkowski err = ice_aq_nvm_update_empr(hw); 4350545cc86SMichal Swiatkowski if (err) { 4360545cc86SMichal Swiatkowski dev_err(dev, "Failed to trigger EMP device reset to reload firmware, err %d aq_err %s\n", 4370545cc86SMichal Swiatkowski err, ice_aq_str(hw->adminq.sq_last_status)); 4380545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Failed to trigger EMP device reset to reload firmware"); 4390545cc86SMichal Swiatkowski return err; 4400545cc86SMichal Swiatkowski } 4410545cc86SMichal Swiatkowski 4420545cc86SMichal Swiatkowski return 0; 4430545cc86SMichal Swiatkowski } 4440545cc86SMichal Swiatkowski 4450545cc86SMichal Swiatkowski /** 4460545cc86SMichal Swiatkowski * ice_devlink_reinit_down - unload given PF 4470545cc86SMichal Swiatkowski * @pf: pointer to the PF struct 4480545cc86SMichal Swiatkowski */ 4490545cc86SMichal Swiatkowski static void ice_devlink_reinit_down(struct ice_pf *pf) 4500545cc86SMichal Swiatkowski { 4510545cc86SMichal Swiatkowski /* No need to take devl_lock, it's already taken by devlink API */ 4520545cc86SMichal Swiatkowski ice_unload(pf); 4530545cc86SMichal Swiatkowski rtnl_lock(); 4540545cc86SMichal Swiatkowski ice_vsi_decfg(ice_get_main_vsi(pf)); 4550545cc86SMichal Swiatkowski rtnl_unlock(); 4560545cc86SMichal Swiatkowski ice_deinit_dev(pf); 4570545cc86SMichal Swiatkowski } 4580545cc86SMichal Swiatkowski 4590545cc86SMichal Swiatkowski /** 4600545cc86SMichal Swiatkowski * ice_devlink_reload_down - prepare for reload 4610545cc86SMichal Swiatkowski * @devlink: pointer to the devlink instance to reload 4620545cc86SMichal Swiatkowski * @netns_change: if true, the network namespace is changing 4630545cc86SMichal Swiatkowski * @action: the action to perform 4640545cc86SMichal Swiatkowski * @limit: limits on what reload should do, such as not resetting 4650545cc86SMichal Swiatkowski * @extack: netlink extended ACK structure 4660545cc86SMichal Swiatkowski */ 4670545cc86SMichal Swiatkowski static int 4680545cc86SMichal Swiatkowski ice_devlink_reload_down(struct devlink *devlink, bool netns_change, 4690545cc86SMichal Swiatkowski enum devlink_reload_action action, 4700545cc86SMichal Swiatkowski enum devlink_reload_limit limit, 4710545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 4720545cc86SMichal Swiatkowski { 4730545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 4740545cc86SMichal Swiatkowski 4750545cc86SMichal Swiatkowski switch (action) { 4760545cc86SMichal Swiatkowski case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: 4770545cc86SMichal Swiatkowski if (ice_is_eswitch_mode_switchdev(pf)) { 4780545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, 4790545cc86SMichal Swiatkowski "Go to legacy mode before doing reinit"); 4800545cc86SMichal Swiatkowski return -EOPNOTSUPP; 4810545cc86SMichal Swiatkowski } 4820545cc86SMichal Swiatkowski if (ice_is_adq_active(pf)) { 4830545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, 4840545cc86SMichal Swiatkowski "Turn off ADQ before doing reinit"); 4850545cc86SMichal Swiatkowski return -EOPNOTSUPP; 4860545cc86SMichal Swiatkowski } 4870545cc86SMichal Swiatkowski if (ice_has_vfs(pf)) { 4880545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, 4890545cc86SMichal Swiatkowski "Remove all VFs before doing reinit"); 4900545cc86SMichal Swiatkowski return -EOPNOTSUPP; 4910545cc86SMichal Swiatkowski } 4920545cc86SMichal Swiatkowski ice_devlink_reinit_down(pf); 4930545cc86SMichal Swiatkowski return 0; 4940545cc86SMichal Swiatkowski case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: 4950545cc86SMichal Swiatkowski return ice_devlink_reload_empr_start(pf, extack); 4960545cc86SMichal Swiatkowski default: 4970545cc86SMichal Swiatkowski WARN_ON(1); 4980545cc86SMichal Swiatkowski return -EOPNOTSUPP; 4990545cc86SMichal Swiatkowski } 5000545cc86SMichal Swiatkowski } 5010545cc86SMichal Swiatkowski 5020545cc86SMichal Swiatkowski /** 5030545cc86SMichal Swiatkowski * ice_devlink_reload_empr_finish - Wait for EMP reset to finish 5040545cc86SMichal Swiatkowski * @pf: pointer to the pf instance 5050545cc86SMichal Swiatkowski * @extack: netlink extended ACK structure 5060545cc86SMichal Swiatkowski * 5070545cc86SMichal Swiatkowski * Wait for driver to finish rebuilding after EMP reset is completed. This 5080545cc86SMichal Swiatkowski * includes time to wait for both the actual device reset as well as the time 5090545cc86SMichal Swiatkowski * for the driver's rebuild to complete. 5100545cc86SMichal Swiatkowski */ 5110545cc86SMichal Swiatkowski static int 5120545cc86SMichal Swiatkowski ice_devlink_reload_empr_finish(struct ice_pf *pf, 5130545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 5140545cc86SMichal Swiatkowski { 5150545cc86SMichal Swiatkowski int err; 5160545cc86SMichal Swiatkowski 5170545cc86SMichal Swiatkowski err = ice_wait_for_reset(pf, 60 * HZ); 5180545cc86SMichal Swiatkowski if (err) { 5190545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Device still resetting after 1 minute"); 5200545cc86SMichal Swiatkowski return err; 5210545cc86SMichal Swiatkowski } 5220545cc86SMichal Swiatkowski 5230545cc86SMichal Swiatkowski return 0; 5240545cc86SMichal Swiatkowski } 5250545cc86SMichal Swiatkowski 5260545cc86SMichal Swiatkowski /** 5270545cc86SMichal Swiatkowski * ice_tear_down_devlink_rate_tree - removes devlink-rate exported tree 5280545cc86SMichal Swiatkowski * @pf: pf struct 5290545cc86SMichal Swiatkowski * 5300545cc86SMichal Swiatkowski * This function tears down tree exported during VF's creation. 5310545cc86SMichal Swiatkowski */ 5320545cc86SMichal Swiatkowski void ice_tear_down_devlink_rate_tree(struct ice_pf *pf) 5330545cc86SMichal Swiatkowski { 5340545cc86SMichal Swiatkowski struct devlink *devlink; 5350545cc86SMichal Swiatkowski struct ice_vf *vf; 5360545cc86SMichal Swiatkowski unsigned int bkt; 5370545cc86SMichal Swiatkowski 5380545cc86SMichal Swiatkowski devlink = priv_to_devlink(pf); 5390545cc86SMichal Swiatkowski 5400545cc86SMichal Swiatkowski devl_lock(devlink); 5410545cc86SMichal Swiatkowski mutex_lock(&pf->vfs.table_lock); 5420545cc86SMichal Swiatkowski ice_for_each_vf(pf, bkt, vf) { 5430545cc86SMichal Swiatkowski if (vf->devlink_port.devlink_rate) 5440545cc86SMichal Swiatkowski devl_rate_leaf_destroy(&vf->devlink_port); 5450545cc86SMichal Swiatkowski } 5460545cc86SMichal Swiatkowski mutex_unlock(&pf->vfs.table_lock); 5470545cc86SMichal Swiatkowski 5480545cc86SMichal Swiatkowski devl_rate_nodes_destroy(devlink); 5490545cc86SMichal Swiatkowski devl_unlock(devlink); 5500545cc86SMichal Swiatkowski } 5510545cc86SMichal Swiatkowski 5520545cc86SMichal Swiatkowski /** 5530545cc86SMichal Swiatkowski * ice_enable_custom_tx - try to enable custom Tx feature 5540545cc86SMichal Swiatkowski * @pf: pf struct 5550545cc86SMichal Swiatkowski * 5560545cc86SMichal Swiatkowski * This function tries to enable custom Tx feature, 5570545cc86SMichal Swiatkowski * it's not possible to enable it, if DCB or ADQ is active. 5580545cc86SMichal Swiatkowski */ 5590545cc86SMichal Swiatkowski static bool ice_enable_custom_tx(struct ice_pf *pf) 5600545cc86SMichal Swiatkowski { 5610545cc86SMichal Swiatkowski struct ice_port_info *pi = ice_get_main_vsi(pf)->port_info; 5620545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 5630545cc86SMichal Swiatkowski 5640545cc86SMichal Swiatkowski if (pi->is_custom_tx_enabled) 5650545cc86SMichal Swiatkowski /* already enabled, return true */ 5660545cc86SMichal Swiatkowski return true; 5670545cc86SMichal Swiatkowski 5680545cc86SMichal Swiatkowski if (ice_is_adq_active(pf)) { 5690545cc86SMichal Swiatkowski dev_err(dev, "ADQ active, can't modify Tx scheduler tree\n"); 5700545cc86SMichal Swiatkowski return false; 5710545cc86SMichal Swiatkowski } 5720545cc86SMichal Swiatkowski 5730545cc86SMichal Swiatkowski if (ice_is_dcb_active(pf)) { 5740545cc86SMichal Swiatkowski dev_err(dev, "DCB active, can't modify Tx scheduler tree\n"); 5750545cc86SMichal Swiatkowski return false; 5760545cc86SMichal Swiatkowski } 5770545cc86SMichal Swiatkowski 5780545cc86SMichal Swiatkowski pi->is_custom_tx_enabled = true; 5790545cc86SMichal Swiatkowski 5800545cc86SMichal Swiatkowski return true; 5810545cc86SMichal Swiatkowski } 5820545cc86SMichal Swiatkowski 5830545cc86SMichal Swiatkowski /** 5840545cc86SMichal Swiatkowski * ice_traverse_tx_tree - traverse Tx scheduler tree 5850545cc86SMichal Swiatkowski * @devlink: devlink struct 5860545cc86SMichal Swiatkowski * @node: current node, used for recursion 5870545cc86SMichal Swiatkowski * @tc_node: tc_node struct, that is treated as a root 5880545cc86SMichal Swiatkowski * @pf: pf struct 5890545cc86SMichal Swiatkowski * 5900545cc86SMichal Swiatkowski * This function traverses Tx scheduler tree and exports 5910545cc86SMichal Swiatkowski * entire structure to the devlink-rate. 5920545cc86SMichal Swiatkowski */ 5930545cc86SMichal Swiatkowski static void ice_traverse_tx_tree(struct devlink *devlink, struct ice_sched_node *node, 5940545cc86SMichal Swiatkowski struct ice_sched_node *tc_node, struct ice_pf *pf) 5950545cc86SMichal Swiatkowski { 5960545cc86SMichal Swiatkowski struct devlink_rate *rate_node = NULL; 5970545cc86SMichal Swiatkowski struct ice_vf *vf; 5980545cc86SMichal Swiatkowski int i; 5990545cc86SMichal Swiatkowski 6000545cc86SMichal Swiatkowski if (node->rate_node) 6010545cc86SMichal Swiatkowski /* already added, skip to the next */ 6020545cc86SMichal Swiatkowski goto traverse_children; 6030545cc86SMichal Swiatkowski 6040545cc86SMichal Swiatkowski if (node->parent == tc_node) { 6050545cc86SMichal Swiatkowski /* create root node */ 6060545cc86SMichal Swiatkowski rate_node = devl_rate_node_create(devlink, node, node->name, NULL); 6070545cc86SMichal Swiatkowski } else if (node->vsi_handle && 6080545cc86SMichal Swiatkowski pf->vsi[node->vsi_handle]->vf) { 6090545cc86SMichal Swiatkowski vf = pf->vsi[node->vsi_handle]->vf; 6100545cc86SMichal Swiatkowski if (!vf->devlink_port.devlink_rate) 6110545cc86SMichal Swiatkowski /* leaf nodes doesn't have children 6120545cc86SMichal Swiatkowski * so we don't set rate_node 6130545cc86SMichal Swiatkowski */ 6140545cc86SMichal Swiatkowski devl_rate_leaf_create(&vf->devlink_port, node, 6150545cc86SMichal Swiatkowski node->parent->rate_node); 6160545cc86SMichal Swiatkowski } else if (node->info.data.elem_type != ICE_AQC_ELEM_TYPE_LEAF && 6170545cc86SMichal Swiatkowski node->parent->rate_node) { 6180545cc86SMichal Swiatkowski rate_node = devl_rate_node_create(devlink, node, node->name, 6190545cc86SMichal Swiatkowski node->parent->rate_node); 6200545cc86SMichal Swiatkowski } 6210545cc86SMichal Swiatkowski 6220545cc86SMichal Swiatkowski if (rate_node && !IS_ERR(rate_node)) 6230545cc86SMichal Swiatkowski node->rate_node = rate_node; 6240545cc86SMichal Swiatkowski 6250545cc86SMichal Swiatkowski traverse_children: 6260545cc86SMichal Swiatkowski for (i = 0; i < node->num_children; i++) 6270545cc86SMichal Swiatkowski ice_traverse_tx_tree(devlink, node->children[i], tc_node, pf); 6280545cc86SMichal Swiatkowski } 6290545cc86SMichal Swiatkowski 6300545cc86SMichal Swiatkowski /** 6310545cc86SMichal Swiatkowski * ice_devlink_rate_init_tx_topology - export Tx scheduler tree to devlink rate 6320545cc86SMichal Swiatkowski * @devlink: devlink struct 6330545cc86SMichal Swiatkowski * @vsi: main vsi struct 6340545cc86SMichal Swiatkowski * 6350545cc86SMichal Swiatkowski * This function finds a root node, then calls ice_traverse_tx tree, which 6360545cc86SMichal Swiatkowski * traverses the tree and exports it's contents to devlink rate. 6370545cc86SMichal Swiatkowski */ 6380545cc86SMichal Swiatkowski int ice_devlink_rate_init_tx_topology(struct devlink *devlink, struct ice_vsi *vsi) 6390545cc86SMichal Swiatkowski { 6400545cc86SMichal Swiatkowski struct ice_port_info *pi = vsi->port_info; 6410545cc86SMichal Swiatkowski struct ice_sched_node *tc_node; 6420545cc86SMichal Swiatkowski struct ice_pf *pf = vsi->back; 6430545cc86SMichal Swiatkowski int i; 6440545cc86SMichal Swiatkowski 6450545cc86SMichal Swiatkowski tc_node = pi->root->children[0]; 6460545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 6470545cc86SMichal Swiatkowski devl_lock(devlink); 6480545cc86SMichal Swiatkowski for (i = 0; i < tc_node->num_children; i++) 6490545cc86SMichal Swiatkowski ice_traverse_tx_tree(devlink, tc_node->children[i], tc_node, pf); 6500545cc86SMichal Swiatkowski devl_unlock(devlink); 6510545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 6520545cc86SMichal Swiatkowski 6530545cc86SMichal Swiatkowski return 0; 6540545cc86SMichal Swiatkowski } 6550545cc86SMichal Swiatkowski 6560545cc86SMichal Swiatkowski static void ice_clear_rate_nodes(struct ice_sched_node *node) 6570545cc86SMichal Swiatkowski { 6580545cc86SMichal Swiatkowski node->rate_node = NULL; 6590545cc86SMichal Swiatkowski 6600545cc86SMichal Swiatkowski for (int i = 0; i < node->num_children; i++) 6610545cc86SMichal Swiatkowski ice_clear_rate_nodes(node->children[i]); 6620545cc86SMichal Swiatkowski } 6630545cc86SMichal Swiatkowski 6640545cc86SMichal Swiatkowski /** 6650545cc86SMichal Swiatkowski * ice_devlink_rate_clear_tx_topology - clear node->rate_node 6660545cc86SMichal Swiatkowski * @vsi: main vsi struct 6670545cc86SMichal Swiatkowski * 6680545cc86SMichal Swiatkowski * Clear rate_node to cleanup creation of Tx topology. 6690545cc86SMichal Swiatkowski * 6700545cc86SMichal Swiatkowski */ 6710545cc86SMichal Swiatkowski void ice_devlink_rate_clear_tx_topology(struct ice_vsi *vsi) 6720545cc86SMichal Swiatkowski { 6730545cc86SMichal Swiatkowski struct ice_port_info *pi = vsi->port_info; 6740545cc86SMichal Swiatkowski 6750545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 6760545cc86SMichal Swiatkowski ice_clear_rate_nodes(pi->root->children[0]); 6770545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 6780545cc86SMichal Swiatkowski } 6790545cc86SMichal Swiatkowski 6800545cc86SMichal Swiatkowski /** 6810545cc86SMichal Swiatkowski * ice_set_object_tx_share - sets node scheduling parameter 6820545cc86SMichal Swiatkowski * @pi: devlink struct instance 6830545cc86SMichal Swiatkowski * @node: node struct instance 6840545cc86SMichal Swiatkowski * @bw: bandwidth in bytes per second 6850545cc86SMichal Swiatkowski * @extack: extended netdev ack structure 6860545cc86SMichal Swiatkowski * 6870545cc86SMichal Swiatkowski * This function sets ICE_MIN_BW scheduling BW limit. 6880545cc86SMichal Swiatkowski */ 6890545cc86SMichal Swiatkowski static int ice_set_object_tx_share(struct ice_port_info *pi, struct ice_sched_node *node, 6900545cc86SMichal Swiatkowski u64 bw, struct netlink_ext_ack *extack) 6910545cc86SMichal Swiatkowski { 6920545cc86SMichal Swiatkowski int status; 6930545cc86SMichal Swiatkowski 6940545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 6950545cc86SMichal Swiatkowski /* converts bytes per second to kilo bits per second */ 6960545cc86SMichal Swiatkowski node->tx_share = div_u64(bw, 125); 6970545cc86SMichal Swiatkowski status = ice_sched_set_node_bw_lmt(pi, node, ICE_MIN_BW, node->tx_share); 6980545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 6990545cc86SMichal Swiatkowski 7000545cc86SMichal Swiatkowski if (status) 7010545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Can't set scheduling node tx_share"); 7020545cc86SMichal Swiatkowski 7030545cc86SMichal Swiatkowski return status; 7040545cc86SMichal Swiatkowski } 7050545cc86SMichal Swiatkowski 7060545cc86SMichal Swiatkowski /** 7070545cc86SMichal Swiatkowski * ice_set_object_tx_max - sets node scheduling parameter 7080545cc86SMichal Swiatkowski * @pi: devlink struct instance 7090545cc86SMichal Swiatkowski * @node: node struct instance 7100545cc86SMichal Swiatkowski * @bw: bandwidth in bytes per second 7110545cc86SMichal Swiatkowski * @extack: extended netdev ack structure 7120545cc86SMichal Swiatkowski * 7130545cc86SMichal Swiatkowski * This function sets ICE_MAX_BW scheduling BW limit. 7140545cc86SMichal Swiatkowski */ 7150545cc86SMichal Swiatkowski static int ice_set_object_tx_max(struct ice_port_info *pi, struct ice_sched_node *node, 7160545cc86SMichal Swiatkowski u64 bw, struct netlink_ext_ack *extack) 7170545cc86SMichal Swiatkowski { 7180545cc86SMichal Swiatkowski int status; 7190545cc86SMichal Swiatkowski 7200545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 7210545cc86SMichal Swiatkowski /* converts bytes per second value to kilo bits per second */ 7220545cc86SMichal Swiatkowski node->tx_max = div_u64(bw, 125); 7230545cc86SMichal Swiatkowski status = ice_sched_set_node_bw_lmt(pi, node, ICE_MAX_BW, node->tx_max); 7240545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 7250545cc86SMichal Swiatkowski 7260545cc86SMichal Swiatkowski if (status) 7270545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Can't set scheduling node tx_max"); 7280545cc86SMichal Swiatkowski 7290545cc86SMichal Swiatkowski return status; 7300545cc86SMichal Swiatkowski } 7310545cc86SMichal Swiatkowski 7320545cc86SMichal Swiatkowski /** 7330545cc86SMichal Swiatkowski * ice_set_object_tx_priority - sets node scheduling parameter 7340545cc86SMichal Swiatkowski * @pi: devlink struct instance 7350545cc86SMichal Swiatkowski * @node: node struct instance 7360545cc86SMichal Swiatkowski * @priority: value representing priority for strict priority arbitration 7370545cc86SMichal Swiatkowski * @extack: extended netdev ack structure 7380545cc86SMichal Swiatkowski * 7390545cc86SMichal Swiatkowski * This function sets priority of node among siblings. 7400545cc86SMichal Swiatkowski */ 7410545cc86SMichal Swiatkowski static int ice_set_object_tx_priority(struct ice_port_info *pi, struct ice_sched_node *node, 7420545cc86SMichal Swiatkowski u32 priority, struct netlink_ext_ack *extack) 7430545cc86SMichal Swiatkowski { 7440545cc86SMichal Swiatkowski int status; 7450545cc86SMichal Swiatkowski 7460545cc86SMichal Swiatkowski if (priority >= 8) { 7470545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Priority should be less than 8"); 7480545cc86SMichal Swiatkowski return -EINVAL; 7490545cc86SMichal Swiatkowski } 7500545cc86SMichal Swiatkowski 7510545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 7520545cc86SMichal Swiatkowski node->tx_priority = priority; 7530545cc86SMichal Swiatkowski status = ice_sched_set_node_priority(pi, node, node->tx_priority); 7540545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 7550545cc86SMichal Swiatkowski 7560545cc86SMichal Swiatkowski if (status) 7570545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Can't set scheduling node tx_priority"); 7580545cc86SMichal Swiatkowski 7590545cc86SMichal Swiatkowski return status; 7600545cc86SMichal Swiatkowski } 7610545cc86SMichal Swiatkowski 7620545cc86SMichal Swiatkowski /** 7630545cc86SMichal Swiatkowski * ice_set_object_tx_weight - sets node scheduling parameter 7640545cc86SMichal Swiatkowski * @pi: devlink struct instance 7650545cc86SMichal Swiatkowski * @node: node struct instance 7660545cc86SMichal Swiatkowski * @weight: value represeting relative weight for WFQ arbitration 7670545cc86SMichal Swiatkowski * @extack: extended netdev ack structure 7680545cc86SMichal Swiatkowski * 7690545cc86SMichal Swiatkowski * This function sets node weight for WFQ algorithm. 7700545cc86SMichal Swiatkowski */ 7710545cc86SMichal Swiatkowski static int ice_set_object_tx_weight(struct ice_port_info *pi, struct ice_sched_node *node, 7720545cc86SMichal Swiatkowski u32 weight, struct netlink_ext_ack *extack) 7730545cc86SMichal Swiatkowski { 7740545cc86SMichal Swiatkowski int status; 7750545cc86SMichal Swiatkowski 7760545cc86SMichal Swiatkowski if (weight > 200 || weight < 1) { 7770545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Weight must be between 1 and 200"); 7780545cc86SMichal Swiatkowski return -EINVAL; 7790545cc86SMichal Swiatkowski } 7800545cc86SMichal Swiatkowski 7810545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 7820545cc86SMichal Swiatkowski node->tx_weight = weight; 7830545cc86SMichal Swiatkowski status = ice_sched_set_node_weight(pi, node, node->tx_weight); 7840545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 7850545cc86SMichal Swiatkowski 7860545cc86SMichal Swiatkowski if (status) 7870545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Can't set scheduling node tx_weight"); 7880545cc86SMichal Swiatkowski 7890545cc86SMichal Swiatkowski return status; 7900545cc86SMichal Swiatkowski } 7910545cc86SMichal Swiatkowski 7920545cc86SMichal Swiatkowski /** 7930545cc86SMichal Swiatkowski * ice_get_pi_from_dev_rate - get port info from devlink_rate 7940545cc86SMichal Swiatkowski * @rate_node: devlink struct instance 7950545cc86SMichal Swiatkowski * 7960545cc86SMichal Swiatkowski * This function returns corresponding port_info struct of devlink_rate 7970545cc86SMichal Swiatkowski */ 7980545cc86SMichal Swiatkowski static struct ice_port_info *ice_get_pi_from_dev_rate(struct devlink_rate *rate_node) 7990545cc86SMichal Swiatkowski { 8000545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(rate_node->devlink); 8010545cc86SMichal Swiatkowski 8020545cc86SMichal Swiatkowski return ice_get_main_vsi(pf)->port_info; 8030545cc86SMichal Swiatkowski } 8040545cc86SMichal Swiatkowski 8050545cc86SMichal Swiatkowski static int ice_devlink_rate_node_new(struct devlink_rate *rate_node, void **priv, 8060545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 8070545cc86SMichal Swiatkowski { 8080545cc86SMichal Swiatkowski struct ice_sched_node *node; 8090545cc86SMichal Swiatkowski struct ice_port_info *pi; 8100545cc86SMichal Swiatkowski 8110545cc86SMichal Swiatkowski pi = ice_get_pi_from_dev_rate(rate_node); 8120545cc86SMichal Swiatkowski 8130545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink))) 8140545cc86SMichal Swiatkowski return -EBUSY; 8150545cc86SMichal Swiatkowski 8160545cc86SMichal Swiatkowski /* preallocate memory for ice_sched_node */ 8170545cc86SMichal Swiatkowski node = devm_kzalloc(ice_hw_to_dev(pi->hw), sizeof(*node), GFP_KERNEL); 8180545cc86SMichal Swiatkowski *priv = node; 8190545cc86SMichal Swiatkowski 8200545cc86SMichal Swiatkowski return 0; 8210545cc86SMichal Swiatkowski } 8220545cc86SMichal Swiatkowski 8230545cc86SMichal Swiatkowski static int ice_devlink_rate_node_del(struct devlink_rate *rate_node, void *priv, 8240545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 8250545cc86SMichal Swiatkowski { 8260545cc86SMichal Swiatkowski struct ice_sched_node *node, *tc_node; 8270545cc86SMichal Swiatkowski struct ice_port_info *pi; 8280545cc86SMichal Swiatkowski 8290545cc86SMichal Swiatkowski pi = ice_get_pi_from_dev_rate(rate_node); 8300545cc86SMichal Swiatkowski tc_node = pi->root->children[0]; 8310545cc86SMichal Swiatkowski node = priv; 8320545cc86SMichal Swiatkowski 8330545cc86SMichal Swiatkowski if (!rate_node->parent || !node || tc_node == node || !extack) 8340545cc86SMichal Swiatkowski return 0; 8350545cc86SMichal Swiatkowski 8360545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink))) 8370545cc86SMichal Swiatkowski return -EBUSY; 8380545cc86SMichal Swiatkowski 8390545cc86SMichal Swiatkowski /* can't allow to delete a node with children */ 8400545cc86SMichal Swiatkowski if (node->num_children) 8410545cc86SMichal Swiatkowski return -EINVAL; 8420545cc86SMichal Swiatkowski 8430545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 8440545cc86SMichal Swiatkowski ice_free_sched_node(pi, node); 8450545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 8460545cc86SMichal Swiatkowski 8470545cc86SMichal Swiatkowski return 0; 8480545cc86SMichal Swiatkowski } 8490545cc86SMichal Swiatkowski 8500545cc86SMichal Swiatkowski static int ice_devlink_rate_leaf_tx_max_set(struct devlink_rate *rate_leaf, void *priv, 8510545cc86SMichal Swiatkowski u64 tx_max, struct netlink_ext_ack *extack) 8520545cc86SMichal Swiatkowski { 8530545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 8540545cc86SMichal Swiatkowski 8550545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_leaf->devlink))) 8560545cc86SMichal Swiatkowski return -EBUSY; 8570545cc86SMichal Swiatkowski 8580545cc86SMichal Swiatkowski if (!node) 8590545cc86SMichal Swiatkowski return 0; 8600545cc86SMichal Swiatkowski 8610545cc86SMichal Swiatkowski return ice_set_object_tx_max(ice_get_pi_from_dev_rate(rate_leaf), 8620545cc86SMichal Swiatkowski node, tx_max, extack); 8630545cc86SMichal Swiatkowski } 8640545cc86SMichal Swiatkowski 8650545cc86SMichal Swiatkowski static int ice_devlink_rate_leaf_tx_share_set(struct devlink_rate *rate_leaf, void *priv, 8660545cc86SMichal Swiatkowski u64 tx_share, struct netlink_ext_ack *extack) 8670545cc86SMichal Swiatkowski { 8680545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 8690545cc86SMichal Swiatkowski 8700545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_leaf->devlink))) 8710545cc86SMichal Swiatkowski return -EBUSY; 8720545cc86SMichal Swiatkowski 8730545cc86SMichal Swiatkowski if (!node) 8740545cc86SMichal Swiatkowski return 0; 8750545cc86SMichal Swiatkowski 8760545cc86SMichal Swiatkowski return ice_set_object_tx_share(ice_get_pi_from_dev_rate(rate_leaf), node, 8770545cc86SMichal Swiatkowski tx_share, extack); 8780545cc86SMichal Swiatkowski } 8790545cc86SMichal Swiatkowski 8800545cc86SMichal Swiatkowski static int ice_devlink_rate_leaf_tx_priority_set(struct devlink_rate *rate_leaf, void *priv, 8810545cc86SMichal Swiatkowski u32 tx_priority, struct netlink_ext_ack *extack) 8820545cc86SMichal Swiatkowski { 8830545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 8840545cc86SMichal Swiatkowski 8850545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_leaf->devlink))) 8860545cc86SMichal Swiatkowski return -EBUSY; 8870545cc86SMichal Swiatkowski 8880545cc86SMichal Swiatkowski if (!node) 8890545cc86SMichal Swiatkowski return 0; 8900545cc86SMichal Swiatkowski 8910545cc86SMichal Swiatkowski return ice_set_object_tx_priority(ice_get_pi_from_dev_rate(rate_leaf), node, 8920545cc86SMichal Swiatkowski tx_priority, extack); 8930545cc86SMichal Swiatkowski } 8940545cc86SMichal Swiatkowski 8950545cc86SMichal Swiatkowski static int ice_devlink_rate_leaf_tx_weight_set(struct devlink_rate *rate_leaf, void *priv, 8960545cc86SMichal Swiatkowski u32 tx_weight, struct netlink_ext_ack *extack) 8970545cc86SMichal Swiatkowski { 8980545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 8990545cc86SMichal Swiatkowski 9000545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_leaf->devlink))) 9010545cc86SMichal Swiatkowski return -EBUSY; 9020545cc86SMichal Swiatkowski 9030545cc86SMichal Swiatkowski if (!node) 9040545cc86SMichal Swiatkowski return 0; 9050545cc86SMichal Swiatkowski 9060545cc86SMichal Swiatkowski return ice_set_object_tx_weight(ice_get_pi_from_dev_rate(rate_leaf), node, 9070545cc86SMichal Swiatkowski tx_weight, extack); 9080545cc86SMichal Swiatkowski } 9090545cc86SMichal Swiatkowski 9100545cc86SMichal Swiatkowski static int ice_devlink_rate_node_tx_max_set(struct devlink_rate *rate_node, void *priv, 9110545cc86SMichal Swiatkowski u64 tx_max, struct netlink_ext_ack *extack) 9120545cc86SMichal Swiatkowski { 9130545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 9140545cc86SMichal Swiatkowski 9150545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink))) 9160545cc86SMichal Swiatkowski return -EBUSY; 9170545cc86SMichal Swiatkowski 9180545cc86SMichal Swiatkowski if (!node) 9190545cc86SMichal Swiatkowski return 0; 9200545cc86SMichal Swiatkowski 9210545cc86SMichal Swiatkowski return ice_set_object_tx_max(ice_get_pi_from_dev_rate(rate_node), 9220545cc86SMichal Swiatkowski node, tx_max, extack); 9230545cc86SMichal Swiatkowski } 9240545cc86SMichal Swiatkowski 9250545cc86SMichal Swiatkowski static int ice_devlink_rate_node_tx_share_set(struct devlink_rate *rate_node, void *priv, 9260545cc86SMichal Swiatkowski u64 tx_share, struct netlink_ext_ack *extack) 9270545cc86SMichal Swiatkowski { 9280545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 9290545cc86SMichal Swiatkowski 9300545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink))) 9310545cc86SMichal Swiatkowski return -EBUSY; 9320545cc86SMichal Swiatkowski 9330545cc86SMichal Swiatkowski if (!node) 9340545cc86SMichal Swiatkowski return 0; 9350545cc86SMichal Swiatkowski 9360545cc86SMichal Swiatkowski return ice_set_object_tx_share(ice_get_pi_from_dev_rate(rate_node), 9370545cc86SMichal Swiatkowski node, tx_share, extack); 9380545cc86SMichal Swiatkowski } 9390545cc86SMichal Swiatkowski 9400545cc86SMichal Swiatkowski static int ice_devlink_rate_node_tx_priority_set(struct devlink_rate *rate_node, void *priv, 9410545cc86SMichal Swiatkowski u32 tx_priority, struct netlink_ext_ack *extack) 9420545cc86SMichal Swiatkowski { 9430545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 9440545cc86SMichal Swiatkowski 9450545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink))) 9460545cc86SMichal Swiatkowski return -EBUSY; 9470545cc86SMichal Swiatkowski 9480545cc86SMichal Swiatkowski if (!node) 9490545cc86SMichal Swiatkowski return 0; 9500545cc86SMichal Swiatkowski 9510545cc86SMichal Swiatkowski return ice_set_object_tx_priority(ice_get_pi_from_dev_rate(rate_node), 9520545cc86SMichal Swiatkowski node, tx_priority, extack); 9530545cc86SMichal Swiatkowski } 9540545cc86SMichal Swiatkowski 9550545cc86SMichal Swiatkowski static int ice_devlink_rate_node_tx_weight_set(struct devlink_rate *rate_node, void *priv, 9560545cc86SMichal Swiatkowski u32 tx_weight, struct netlink_ext_ack *extack) 9570545cc86SMichal Swiatkowski { 9580545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 9590545cc86SMichal Swiatkowski 9600545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink))) 9610545cc86SMichal Swiatkowski return -EBUSY; 9620545cc86SMichal Swiatkowski 9630545cc86SMichal Swiatkowski if (!node) 9640545cc86SMichal Swiatkowski return 0; 9650545cc86SMichal Swiatkowski 9660545cc86SMichal Swiatkowski return ice_set_object_tx_weight(ice_get_pi_from_dev_rate(rate_node), 9670545cc86SMichal Swiatkowski node, tx_weight, extack); 9680545cc86SMichal Swiatkowski } 9690545cc86SMichal Swiatkowski 9700545cc86SMichal Swiatkowski static int ice_devlink_set_parent(struct devlink_rate *devlink_rate, 9710545cc86SMichal Swiatkowski struct devlink_rate *parent, 9720545cc86SMichal Swiatkowski void *priv, void *parent_priv, 9730545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 9740545cc86SMichal Swiatkowski { 9750545cc86SMichal Swiatkowski struct ice_port_info *pi = ice_get_pi_from_dev_rate(devlink_rate); 9760545cc86SMichal Swiatkowski struct ice_sched_node *tc_node, *node, *parent_node; 9770545cc86SMichal Swiatkowski u16 num_nodes_added; 9780545cc86SMichal Swiatkowski u32 first_node_teid; 9790545cc86SMichal Swiatkowski u32 node_teid; 9800545cc86SMichal Swiatkowski int status; 9810545cc86SMichal Swiatkowski 9820545cc86SMichal Swiatkowski tc_node = pi->root->children[0]; 9830545cc86SMichal Swiatkowski node = priv; 9840545cc86SMichal Swiatkowski 9850545cc86SMichal Swiatkowski if (!extack) 9860545cc86SMichal Swiatkowski return 0; 9870545cc86SMichal Swiatkowski 9880545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(devlink_rate->devlink))) 9890545cc86SMichal Swiatkowski return -EBUSY; 9900545cc86SMichal Swiatkowski 9910545cc86SMichal Swiatkowski if (!parent) { 9920545cc86SMichal Swiatkowski if (!node || tc_node == node || node->num_children) 9930545cc86SMichal Swiatkowski return -EINVAL; 9940545cc86SMichal Swiatkowski 9950545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 9960545cc86SMichal Swiatkowski ice_free_sched_node(pi, node); 9970545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 9980545cc86SMichal Swiatkowski 9990545cc86SMichal Swiatkowski return 0; 10000545cc86SMichal Swiatkowski } 10010545cc86SMichal Swiatkowski 10020545cc86SMichal Swiatkowski parent_node = parent_priv; 10030545cc86SMichal Swiatkowski 10040545cc86SMichal Swiatkowski /* if the node doesn't exist, create it */ 10050545cc86SMichal Swiatkowski if (!node->parent) { 10060545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 10070545cc86SMichal Swiatkowski status = ice_sched_add_elems(pi, tc_node, parent_node, 10080545cc86SMichal Swiatkowski parent_node->tx_sched_layer + 1, 10090545cc86SMichal Swiatkowski 1, &num_nodes_added, &first_node_teid, 10100545cc86SMichal Swiatkowski &node); 10110545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 10120545cc86SMichal Swiatkowski 10130545cc86SMichal Swiatkowski if (status) { 10140545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Can't add a new node"); 10150545cc86SMichal Swiatkowski return status; 10160545cc86SMichal Swiatkowski } 10170545cc86SMichal Swiatkowski 10180545cc86SMichal Swiatkowski if (devlink_rate->tx_share) 10190545cc86SMichal Swiatkowski ice_set_object_tx_share(pi, node, devlink_rate->tx_share, extack); 10200545cc86SMichal Swiatkowski if (devlink_rate->tx_max) 10210545cc86SMichal Swiatkowski ice_set_object_tx_max(pi, node, devlink_rate->tx_max, extack); 10220545cc86SMichal Swiatkowski if (devlink_rate->tx_priority) 10230545cc86SMichal Swiatkowski ice_set_object_tx_priority(pi, node, devlink_rate->tx_priority, extack); 10240545cc86SMichal Swiatkowski if (devlink_rate->tx_weight) 10250545cc86SMichal Swiatkowski ice_set_object_tx_weight(pi, node, devlink_rate->tx_weight, extack); 10260545cc86SMichal Swiatkowski } else { 10270545cc86SMichal Swiatkowski node_teid = le32_to_cpu(node->info.node_teid); 10280545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 10290545cc86SMichal Swiatkowski status = ice_sched_move_nodes(pi, parent_node, 1, &node_teid); 10300545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 10310545cc86SMichal Swiatkowski 10320545cc86SMichal Swiatkowski if (status) 10330545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Can't move existing node to a new parent"); 10340545cc86SMichal Swiatkowski } 10350545cc86SMichal Swiatkowski 10360545cc86SMichal Swiatkowski return status; 10370545cc86SMichal Swiatkowski } 10380545cc86SMichal Swiatkowski 10390545cc86SMichal Swiatkowski /** 10400545cc86SMichal Swiatkowski * ice_devlink_reinit_up - do reinit of the given PF 10410545cc86SMichal Swiatkowski * @pf: pointer to the PF struct 10420545cc86SMichal Swiatkowski */ 10430545cc86SMichal Swiatkowski static int ice_devlink_reinit_up(struct ice_pf *pf) 10440545cc86SMichal Swiatkowski { 10450545cc86SMichal Swiatkowski struct ice_vsi *vsi = ice_get_main_vsi(pf); 10460545cc86SMichal Swiatkowski struct ice_vsi_cfg_params params; 10470545cc86SMichal Swiatkowski int err; 10480545cc86SMichal Swiatkowski 10490545cc86SMichal Swiatkowski err = ice_init_dev(pf); 10500545cc86SMichal Swiatkowski if (err) 10510545cc86SMichal Swiatkowski return err; 10520545cc86SMichal Swiatkowski 10530545cc86SMichal Swiatkowski params = ice_vsi_to_params(vsi); 10540545cc86SMichal Swiatkowski params.flags = ICE_VSI_FLAG_INIT; 10550545cc86SMichal Swiatkowski 10560545cc86SMichal Swiatkowski rtnl_lock(); 10570545cc86SMichal Swiatkowski err = ice_vsi_cfg(vsi, ¶ms); 10580545cc86SMichal Swiatkowski rtnl_unlock(); 10590545cc86SMichal Swiatkowski if (err) 10600545cc86SMichal Swiatkowski goto err_vsi_cfg; 10610545cc86SMichal Swiatkowski 10620545cc86SMichal Swiatkowski /* No need to take devl_lock, it's already taken by devlink API */ 10630545cc86SMichal Swiatkowski err = ice_load(pf); 10640545cc86SMichal Swiatkowski if (err) 10650545cc86SMichal Swiatkowski goto err_load; 10660545cc86SMichal Swiatkowski 10670545cc86SMichal Swiatkowski return 0; 10680545cc86SMichal Swiatkowski 10690545cc86SMichal Swiatkowski err_load: 10700545cc86SMichal Swiatkowski rtnl_lock(); 10710545cc86SMichal Swiatkowski ice_vsi_decfg(vsi); 10720545cc86SMichal Swiatkowski rtnl_unlock(); 10730545cc86SMichal Swiatkowski err_vsi_cfg: 10740545cc86SMichal Swiatkowski ice_deinit_dev(pf); 10750545cc86SMichal Swiatkowski return err; 10760545cc86SMichal Swiatkowski } 10770545cc86SMichal Swiatkowski 10780545cc86SMichal Swiatkowski /** 10790545cc86SMichal Swiatkowski * ice_devlink_reload_up - do reload up after reinit 10800545cc86SMichal Swiatkowski * @devlink: pointer to the devlink instance reloading 10810545cc86SMichal Swiatkowski * @action: the action requested 10820545cc86SMichal Swiatkowski * @limit: limits imposed by userspace, such as not resetting 10830545cc86SMichal Swiatkowski * @actions_performed: on return, indicate what actions actually performed 10840545cc86SMichal Swiatkowski * @extack: netlink extended ACK structure 10850545cc86SMichal Swiatkowski */ 10860545cc86SMichal Swiatkowski static int 10870545cc86SMichal Swiatkowski ice_devlink_reload_up(struct devlink *devlink, 10880545cc86SMichal Swiatkowski enum devlink_reload_action action, 10890545cc86SMichal Swiatkowski enum devlink_reload_limit limit, 10900545cc86SMichal Swiatkowski u32 *actions_performed, 10910545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 10920545cc86SMichal Swiatkowski { 10930545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 10940545cc86SMichal Swiatkowski 10950545cc86SMichal Swiatkowski switch (action) { 10960545cc86SMichal Swiatkowski case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: 10970545cc86SMichal Swiatkowski *actions_performed = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT); 10980545cc86SMichal Swiatkowski return ice_devlink_reinit_up(pf); 10990545cc86SMichal Swiatkowski case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: 11000545cc86SMichal Swiatkowski *actions_performed = BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE); 11010545cc86SMichal Swiatkowski return ice_devlink_reload_empr_finish(pf, extack); 11020545cc86SMichal Swiatkowski default: 11030545cc86SMichal Swiatkowski WARN_ON(1); 11040545cc86SMichal Swiatkowski return -EOPNOTSUPP; 11050545cc86SMichal Swiatkowski } 11060545cc86SMichal Swiatkowski } 11070545cc86SMichal Swiatkowski 11080545cc86SMichal Swiatkowski static const struct devlink_ops ice_devlink_ops = { 11090545cc86SMichal Swiatkowski .supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK, 11100545cc86SMichal Swiatkowski .reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) | 11110545cc86SMichal Swiatkowski BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE), 11120545cc86SMichal Swiatkowski .reload_down = ice_devlink_reload_down, 11130545cc86SMichal Swiatkowski .reload_up = ice_devlink_reload_up, 11140545cc86SMichal Swiatkowski .eswitch_mode_get = ice_eswitch_mode_get, 11150545cc86SMichal Swiatkowski .eswitch_mode_set = ice_eswitch_mode_set, 11160545cc86SMichal Swiatkowski .info_get = ice_devlink_info_get, 11170545cc86SMichal Swiatkowski .flash_update = ice_devlink_flash_update, 11180545cc86SMichal Swiatkowski 11190545cc86SMichal Swiatkowski .rate_node_new = ice_devlink_rate_node_new, 11200545cc86SMichal Swiatkowski .rate_node_del = ice_devlink_rate_node_del, 11210545cc86SMichal Swiatkowski 11220545cc86SMichal Swiatkowski .rate_leaf_tx_max_set = ice_devlink_rate_leaf_tx_max_set, 11230545cc86SMichal Swiatkowski .rate_leaf_tx_share_set = ice_devlink_rate_leaf_tx_share_set, 11240545cc86SMichal Swiatkowski .rate_leaf_tx_priority_set = ice_devlink_rate_leaf_tx_priority_set, 11250545cc86SMichal Swiatkowski .rate_leaf_tx_weight_set = ice_devlink_rate_leaf_tx_weight_set, 11260545cc86SMichal Swiatkowski 11270545cc86SMichal Swiatkowski .rate_node_tx_max_set = ice_devlink_rate_node_tx_max_set, 11280545cc86SMichal Swiatkowski .rate_node_tx_share_set = ice_devlink_rate_node_tx_share_set, 11290545cc86SMichal Swiatkowski .rate_node_tx_priority_set = ice_devlink_rate_node_tx_priority_set, 11300545cc86SMichal Swiatkowski .rate_node_tx_weight_set = ice_devlink_rate_node_tx_weight_set, 11310545cc86SMichal Swiatkowski 11320545cc86SMichal Swiatkowski .rate_leaf_parent_set = ice_devlink_set_parent, 11330545cc86SMichal Swiatkowski .rate_node_parent_set = ice_devlink_set_parent, 11340545cc86SMichal Swiatkowski }; 11350545cc86SMichal Swiatkowski 11360545cc86SMichal Swiatkowski static int 11370545cc86SMichal Swiatkowski ice_devlink_enable_roce_get(struct devlink *devlink, u32 id, 11380545cc86SMichal Swiatkowski struct devlink_param_gset_ctx *ctx) 11390545cc86SMichal Swiatkowski { 11400545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 11410545cc86SMichal Swiatkowski 11420545cc86SMichal Swiatkowski ctx->val.vbool = pf->rdma_mode & IIDC_RDMA_PROTOCOL_ROCEV2 ? true : false; 11430545cc86SMichal Swiatkowski 11440545cc86SMichal Swiatkowski return 0; 11450545cc86SMichal Swiatkowski } 11460545cc86SMichal Swiatkowski 11470545cc86SMichal Swiatkowski static int 11480545cc86SMichal Swiatkowski ice_devlink_enable_roce_set(struct devlink *devlink, u32 id, 11490545cc86SMichal Swiatkowski struct devlink_param_gset_ctx *ctx) 11500545cc86SMichal Swiatkowski { 11510545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 11520545cc86SMichal Swiatkowski bool roce_ena = ctx->val.vbool; 11530545cc86SMichal Swiatkowski int ret; 11540545cc86SMichal Swiatkowski 11550545cc86SMichal Swiatkowski if (!roce_ena) { 11560545cc86SMichal Swiatkowski ice_unplug_aux_dev(pf); 11570545cc86SMichal Swiatkowski pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_ROCEV2; 11580545cc86SMichal Swiatkowski return 0; 11590545cc86SMichal Swiatkowski } 11600545cc86SMichal Swiatkowski 11610545cc86SMichal Swiatkowski pf->rdma_mode |= IIDC_RDMA_PROTOCOL_ROCEV2; 11620545cc86SMichal Swiatkowski ret = ice_plug_aux_dev(pf); 11630545cc86SMichal Swiatkowski if (ret) 11640545cc86SMichal Swiatkowski pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_ROCEV2; 11650545cc86SMichal Swiatkowski 11660545cc86SMichal Swiatkowski return ret; 11670545cc86SMichal Swiatkowski } 11680545cc86SMichal Swiatkowski 11690545cc86SMichal Swiatkowski static int 11700545cc86SMichal Swiatkowski ice_devlink_enable_roce_validate(struct devlink *devlink, u32 id, 11710545cc86SMichal Swiatkowski union devlink_param_value val, 11720545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 11730545cc86SMichal Swiatkowski { 11740545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 11750545cc86SMichal Swiatkowski 11760545cc86SMichal Swiatkowski if (!test_bit(ICE_FLAG_RDMA_ENA, pf->flags)) 11770545cc86SMichal Swiatkowski return -EOPNOTSUPP; 11780545cc86SMichal Swiatkowski 11790545cc86SMichal Swiatkowski if (pf->rdma_mode & IIDC_RDMA_PROTOCOL_IWARP) { 11800545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "iWARP is currently enabled. This device cannot enable iWARP and RoCEv2 simultaneously"); 11810545cc86SMichal Swiatkowski return -EOPNOTSUPP; 11820545cc86SMichal Swiatkowski } 11830545cc86SMichal Swiatkowski 11840545cc86SMichal Swiatkowski return 0; 11850545cc86SMichal Swiatkowski } 11860545cc86SMichal Swiatkowski 11870545cc86SMichal Swiatkowski static int 11880545cc86SMichal Swiatkowski ice_devlink_enable_iw_get(struct devlink *devlink, u32 id, 11890545cc86SMichal Swiatkowski struct devlink_param_gset_ctx *ctx) 11900545cc86SMichal Swiatkowski { 11910545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 11920545cc86SMichal Swiatkowski 11930545cc86SMichal Swiatkowski ctx->val.vbool = pf->rdma_mode & IIDC_RDMA_PROTOCOL_IWARP; 11940545cc86SMichal Swiatkowski 11950545cc86SMichal Swiatkowski return 0; 11960545cc86SMichal Swiatkowski } 11970545cc86SMichal Swiatkowski 11980545cc86SMichal Swiatkowski static int 11990545cc86SMichal Swiatkowski ice_devlink_enable_iw_set(struct devlink *devlink, u32 id, 12000545cc86SMichal Swiatkowski struct devlink_param_gset_ctx *ctx) 12010545cc86SMichal Swiatkowski { 12020545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 12030545cc86SMichal Swiatkowski bool iw_ena = ctx->val.vbool; 12040545cc86SMichal Swiatkowski int ret; 12050545cc86SMichal Swiatkowski 12060545cc86SMichal Swiatkowski if (!iw_ena) { 12070545cc86SMichal Swiatkowski ice_unplug_aux_dev(pf); 12080545cc86SMichal Swiatkowski pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_IWARP; 12090545cc86SMichal Swiatkowski return 0; 12100545cc86SMichal Swiatkowski } 12110545cc86SMichal Swiatkowski 12120545cc86SMichal Swiatkowski pf->rdma_mode |= IIDC_RDMA_PROTOCOL_IWARP; 12130545cc86SMichal Swiatkowski ret = ice_plug_aux_dev(pf); 12140545cc86SMichal Swiatkowski if (ret) 12150545cc86SMichal Swiatkowski pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_IWARP; 12160545cc86SMichal Swiatkowski 12170545cc86SMichal Swiatkowski return ret; 12180545cc86SMichal Swiatkowski } 12190545cc86SMichal Swiatkowski 12200545cc86SMichal Swiatkowski static int 12210545cc86SMichal Swiatkowski ice_devlink_enable_iw_validate(struct devlink *devlink, u32 id, 12220545cc86SMichal Swiatkowski union devlink_param_value val, 12230545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 12240545cc86SMichal Swiatkowski { 12250545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 12260545cc86SMichal Swiatkowski 12270545cc86SMichal Swiatkowski if (!test_bit(ICE_FLAG_RDMA_ENA, pf->flags)) 12280545cc86SMichal Swiatkowski return -EOPNOTSUPP; 12290545cc86SMichal Swiatkowski 12300545cc86SMichal Swiatkowski if (pf->rdma_mode & IIDC_RDMA_PROTOCOL_ROCEV2) { 12310545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "RoCEv2 is currently enabled. This device cannot enable iWARP and RoCEv2 simultaneously"); 12320545cc86SMichal Swiatkowski return -EOPNOTSUPP; 12330545cc86SMichal Swiatkowski } 12340545cc86SMichal Swiatkowski 12350545cc86SMichal Swiatkowski return 0; 12360545cc86SMichal Swiatkowski } 12370545cc86SMichal Swiatkowski 12380545cc86SMichal Swiatkowski static const struct devlink_param ice_devlink_params[] = { 12390545cc86SMichal Swiatkowski DEVLINK_PARAM_GENERIC(ENABLE_ROCE, BIT(DEVLINK_PARAM_CMODE_RUNTIME), 12400545cc86SMichal Swiatkowski ice_devlink_enable_roce_get, 12410545cc86SMichal Swiatkowski ice_devlink_enable_roce_set, 12420545cc86SMichal Swiatkowski ice_devlink_enable_roce_validate), 12430545cc86SMichal Swiatkowski DEVLINK_PARAM_GENERIC(ENABLE_IWARP, BIT(DEVLINK_PARAM_CMODE_RUNTIME), 12440545cc86SMichal Swiatkowski ice_devlink_enable_iw_get, 12450545cc86SMichal Swiatkowski ice_devlink_enable_iw_set, 12460545cc86SMichal Swiatkowski ice_devlink_enable_iw_validate), 12470545cc86SMichal Swiatkowski 12480545cc86SMichal Swiatkowski }; 12490545cc86SMichal Swiatkowski 12500545cc86SMichal Swiatkowski static void ice_devlink_free(void *devlink_ptr) 12510545cc86SMichal Swiatkowski { 12520545cc86SMichal Swiatkowski devlink_free((struct devlink *)devlink_ptr); 12530545cc86SMichal Swiatkowski } 12540545cc86SMichal Swiatkowski 12550545cc86SMichal Swiatkowski /** 12560545cc86SMichal Swiatkowski * ice_allocate_pf - Allocate devlink and return PF structure pointer 12570545cc86SMichal Swiatkowski * @dev: the device to allocate for 12580545cc86SMichal Swiatkowski * 12590545cc86SMichal Swiatkowski * Allocate a devlink instance for this device and return the private area as 12600545cc86SMichal Swiatkowski * the PF structure. The devlink memory is kept track of through devres by 12610545cc86SMichal Swiatkowski * adding an action to remove it when unwinding. 12620545cc86SMichal Swiatkowski */ 12630545cc86SMichal Swiatkowski struct ice_pf *ice_allocate_pf(struct device *dev) 12640545cc86SMichal Swiatkowski { 12650545cc86SMichal Swiatkowski struct devlink *devlink; 12660545cc86SMichal Swiatkowski 12670545cc86SMichal Swiatkowski devlink = devlink_alloc(&ice_devlink_ops, sizeof(struct ice_pf), dev); 12680545cc86SMichal Swiatkowski if (!devlink) 12690545cc86SMichal Swiatkowski return NULL; 12700545cc86SMichal Swiatkowski 12710545cc86SMichal Swiatkowski /* Add an action to teardown the devlink when unwinding the driver */ 12720545cc86SMichal Swiatkowski if (devm_add_action_or_reset(dev, ice_devlink_free, devlink)) 12730545cc86SMichal Swiatkowski return NULL; 12740545cc86SMichal Swiatkowski 12750545cc86SMichal Swiatkowski return devlink_priv(devlink); 12760545cc86SMichal Swiatkowski } 12770545cc86SMichal Swiatkowski 12780545cc86SMichal Swiatkowski /** 12790545cc86SMichal Swiatkowski * ice_devlink_register - Register devlink interface for this PF 12800545cc86SMichal Swiatkowski * @pf: the PF to register the devlink for. 12810545cc86SMichal Swiatkowski * 12820545cc86SMichal Swiatkowski * Register the devlink instance associated with this physical function. 12830545cc86SMichal Swiatkowski * 12840545cc86SMichal Swiatkowski * Return: zero on success or an error code on failure. 12850545cc86SMichal Swiatkowski */ 12860545cc86SMichal Swiatkowski void ice_devlink_register(struct ice_pf *pf) 12870545cc86SMichal Swiatkowski { 12880545cc86SMichal Swiatkowski struct devlink *devlink = priv_to_devlink(pf); 12890545cc86SMichal Swiatkowski 1290*118c6bdeSMichal Swiatkowski devl_register(devlink); 12910545cc86SMichal Swiatkowski } 12920545cc86SMichal Swiatkowski 12930545cc86SMichal Swiatkowski /** 12940545cc86SMichal Swiatkowski * ice_devlink_unregister - Unregister devlink resources for this PF. 12950545cc86SMichal Swiatkowski * @pf: the PF structure to cleanup 12960545cc86SMichal Swiatkowski * 12970545cc86SMichal Swiatkowski * Releases resources used by devlink and cleans up associated memory. 12980545cc86SMichal Swiatkowski */ 12990545cc86SMichal Swiatkowski void ice_devlink_unregister(struct ice_pf *pf) 13000545cc86SMichal Swiatkowski { 1301*118c6bdeSMichal Swiatkowski devl_unregister(priv_to_devlink(pf)); 13020545cc86SMichal Swiatkowski } 13030545cc86SMichal Swiatkowski 13040545cc86SMichal Swiatkowski int ice_devlink_register_params(struct ice_pf *pf) 13050545cc86SMichal Swiatkowski { 13060545cc86SMichal Swiatkowski struct devlink *devlink = priv_to_devlink(pf); 13070545cc86SMichal Swiatkowski 1308*118c6bdeSMichal Swiatkowski return devl_params_register(devlink, ice_devlink_params, 13090545cc86SMichal Swiatkowski ARRAY_SIZE(ice_devlink_params)); 13100545cc86SMichal Swiatkowski } 13110545cc86SMichal Swiatkowski 13120545cc86SMichal Swiatkowski void ice_devlink_unregister_params(struct ice_pf *pf) 13130545cc86SMichal Swiatkowski { 1314*118c6bdeSMichal Swiatkowski devl_params_unregister(priv_to_devlink(pf), ice_devlink_params, 13150545cc86SMichal Swiatkowski ARRAY_SIZE(ice_devlink_params)); 13160545cc86SMichal Swiatkowski } 13170545cc86SMichal Swiatkowski 13180545cc86SMichal Swiatkowski #define ICE_DEVLINK_READ_BLK_SIZE (1024 * 1024) 13190545cc86SMichal Swiatkowski 13200545cc86SMichal Swiatkowski static const struct devlink_region_ops ice_nvm_region_ops; 13210545cc86SMichal Swiatkowski static const struct devlink_region_ops ice_sram_region_ops; 13220545cc86SMichal Swiatkowski 13230545cc86SMichal Swiatkowski /** 13240545cc86SMichal Swiatkowski * ice_devlink_nvm_snapshot - Capture a snapshot of the NVM flash contents 13250545cc86SMichal Swiatkowski * @devlink: the devlink instance 13260545cc86SMichal Swiatkowski * @ops: the devlink region to snapshot 13270545cc86SMichal Swiatkowski * @extack: extended ACK response structure 13280545cc86SMichal Swiatkowski * @data: on exit points to snapshot data buffer 13290545cc86SMichal Swiatkowski * 13300545cc86SMichal Swiatkowski * This function is called in response to a DEVLINK_CMD_REGION_NEW for either 13310545cc86SMichal Swiatkowski * the nvm-flash or shadow-ram region. 13320545cc86SMichal Swiatkowski * 13330545cc86SMichal Swiatkowski * It captures a snapshot of the NVM or Shadow RAM flash contents. This 13340545cc86SMichal Swiatkowski * snapshot can then later be viewed via the DEVLINK_CMD_REGION_READ netlink 13350545cc86SMichal Swiatkowski * interface. 13360545cc86SMichal Swiatkowski * 13370545cc86SMichal Swiatkowski * @returns zero on success, and updates the data pointer. Returns a non-zero 13380545cc86SMichal Swiatkowski * error code on failure. 13390545cc86SMichal Swiatkowski */ 13400545cc86SMichal Swiatkowski static int ice_devlink_nvm_snapshot(struct devlink *devlink, 13410545cc86SMichal Swiatkowski const struct devlink_region_ops *ops, 13420545cc86SMichal Swiatkowski struct netlink_ext_ack *extack, u8 **data) 13430545cc86SMichal Swiatkowski { 13440545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 13450545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 13460545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 13470545cc86SMichal Swiatkowski bool read_shadow_ram; 13480545cc86SMichal Swiatkowski u8 *nvm_data, *tmp, i; 13490545cc86SMichal Swiatkowski u32 nvm_size, left; 13500545cc86SMichal Swiatkowski s8 num_blks; 13510545cc86SMichal Swiatkowski int status; 13520545cc86SMichal Swiatkowski 13530545cc86SMichal Swiatkowski if (ops == &ice_nvm_region_ops) { 13540545cc86SMichal Swiatkowski read_shadow_ram = false; 13550545cc86SMichal Swiatkowski nvm_size = hw->flash.flash_size; 13560545cc86SMichal Swiatkowski } else if (ops == &ice_sram_region_ops) { 13570545cc86SMichal Swiatkowski read_shadow_ram = true; 13580545cc86SMichal Swiatkowski nvm_size = hw->flash.sr_words * 2u; 13590545cc86SMichal Swiatkowski } else { 13600545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unexpected region in snapshot function"); 13610545cc86SMichal Swiatkowski return -EOPNOTSUPP; 13620545cc86SMichal Swiatkowski } 13630545cc86SMichal Swiatkowski 13640545cc86SMichal Swiatkowski nvm_data = vzalloc(nvm_size); 13650545cc86SMichal Swiatkowski if (!nvm_data) 13660545cc86SMichal Swiatkowski return -ENOMEM; 13670545cc86SMichal Swiatkowski 13680545cc86SMichal Swiatkowski num_blks = DIV_ROUND_UP(nvm_size, ICE_DEVLINK_READ_BLK_SIZE); 13690545cc86SMichal Swiatkowski tmp = nvm_data; 13700545cc86SMichal Swiatkowski left = nvm_size; 13710545cc86SMichal Swiatkowski 13720545cc86SMichal Swiatkowski /* Some systems take longer to read the NVM than others which causes the 13730545cc86SMichal Swiatkowski * FW to reclaim the NVM lock before the entire NVM has been read. Fix 13740545cc86SMichal Swiatkowski * this by breaking the reads of the NVM into smaller chunks that will 13750545cc86SMichal Swiatkowski * probably not take as long. This has some overhead since we are 13760545cc86SMichal Swiatkowski * increasing the number of AQ commands, but it should always work 13770545cc86SMichal Swiatkowski */ 13780545cc86SMichal Swiatkowski for (i = 0; i < num_blks; i++) { 13790545cc86SMichal Swiatkowski u32 read_sz = min_t(u32, ICE_DEVLINK_READ_BLK_SIZE, left); 13800545cc86SMichal Swiatkowski 13810545cc86SMichal Swiatkowski status = ice_acquire_nvm(hw, ICE_RES_READ); 13820545cc86SMichal Swiatkowski if (status) { 13830545cc86SMichal Swiatkowski dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n", 13840545cc86SMichal Swiatkowski status, hw->adminq.sq_last_status); 13850545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore"); 13860545cc86SMichal Swiatkowski vfree(nvm_data); 13870545cc86SMichal Swiatkowski return -EIO; 13880545cc86SMichal Swiatkowski } 13890545cc86SMichal Swiatkowski 13900545cc86SMichal Swiatkowski status = ice_read_flat_nvm(hw, i * ICE_DEVLINK_READ_BLK_SIZE, 13910545cc86SMichal Swiatkowski &read_sz, tmp, read_shadow_ram); 13920545cc86SMichal Swiatkowski if (status) { 13930545cc86SMichal Swiatkowski dev_dbg(dev, "ice_read_flat_nvm failed after reading %u bytes, err %d aq_err %d\n", 13940545cc86SMichal Swiatkowski read_sz, status, hw->adminq.sq_last_status); 13950545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Failed to read NVM contents"); 13960545cc86SMichal Swiatkowski ice_release_nvm(hw); 13970545cc86SMichal Swiatkowski vfree(nvm_data); 13980545cc86SMichal Swiatkowski return -EIO; 13990545cc86SMichal Swiatkowski } 14000545cc86SMichal Swiatkowski ice_release_nvm(hw); 14010545cc86SMichal Swiatkowski 14020545cc86SMichal Swiatkowski tmp += read_sz; 14030545cc86SMichal Swiatkowski left -= read_sz; 14040545cc86SMichal Swiatkowski } 14050545cc86SMichal Swiatkowski 14060545cc86SMichal Swiatkowski *data = nvm_data; 14070545cc86SMichal Swiatkowski 14080545cc86SMichal Swiatkowski return 0; 14090545cc86SMichal Swiatkowski } 14100545cc86SMichal Swiatkowski 14110545cc86SMichal Swiatkowski /** 14120545cc86SMichal Swiatkowski * ice_devlink_nvm_read - Read a portion of NVM flash contents 14130545cc86SMichal Swiatkowski * @devlink: the devlink instance 14140545cc86SMichal Swiatkowski * @ops: the devlink region to snapshot 14150545cc86SMichal Swiatkowski * @extack: extended ACK response structure 14160545cc86SMichal Swiatkowski * @offset: the offset to start at 14170545cc86SMichal Swiatkowski * @size: the amount to read 14180545cc86SMichal Swiatkowski * @data: the data buffer to read into 14190545cc86SMichal Swiatkowski * 14200545cc86SMichal Swiatkowski * This function is called in response to DEVLINK_CMD_REGION_READ to directly 14210545cc86SMichal Swiatkowski * read a section of the NVM contents. 14220545cc86SMichal Swiatkowski * 14230545cc86SMichal Swiatkowski * It reads from either the nvm-flash or shadow-ram region contents. 14240545cc86SMichal Swiatkowski * 14250545cc86SMichal Swiatkowski * @returns zero on success, and updates the data pointer. Returns a non-zero 14260545cc86SMichal Swiatkowski * error code on failure. 14270545cc86SMichal Swiatkowski */ 14280545cc86SMichal Swiatkowski static int ice_devlink_nvm_read(struct devlink *devlink, 14290545cc86SMichal Swiatkowski const struct devlink_region_ops *ops, 14300545cc86SMichal Swiatkowski struct netlink_ext_ack *extack, 14310545cc86SMichal Swiatkowski u64 offset, u32 size, u8 *data) 14320545cc86SMichal Swiatkowski { 14330545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 14340545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 14350545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 14360545cc86SMichal Swiatkowski bool read_shadow_ram; 14370545cc86SMichal Swiatkowski u64 nvm_size; 14380545cc86SMichal Swiatkowski int status; 14390545cc86SMichal Swiatkowski 14400545cc86SMichal Swiatkowski if (ops == &ice_nvm_region_ops) { 14410545cc86SMichal Swiatkowski read_shadow_ram = false; 14420545cc86SMichal Swiatkowski nvm_size = hw->flash.flash_size; 14430545cc86SMichal Swiatkowski } else if (ops == &ice_sram_region_ops) { 14440545cc86SMichal Swiatkowski read_shadow_ram = true; 14450545cc86SMichal Swiatkowski nvm_size = hw->flash.sr_words * 2u; 14460545cc86SMichal Swiatkowski } else { 14470545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unexpected region in snapshot function"); 14480545cc86SMichal Swiatkowski return -EOPNOTSUPP; 14490545cc86SMichal Swiatkowski } 14500545cc86SMichal Swiatkowski 14510545cc86SMichal Swiatkowski if (offset + size >= nvm_size) { 14520545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Cannot read beyond the region size"); 14530545cc86SMichal Swiatkowski return -ERANGE; 14540545cc86SMichal Swiatkowski } 14550545cc86SMichal Swiatkowski 14560545cc86SMichal Swiatkowski status = ice_acquire_nvm(hw, ICE_RES_READ); 14570545cc86SMichal Swiatkowski if (status) { 14580545cc86SMichal Swiatkowski dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n", 14590545cc86SMichal Swiatkowski status, hw->adminq.sq_last_status); 14600545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore"); 14610545cc86SMichal Swiatkowski return -EIO; 14620545cc86SMichal Swiatkowski } 14630545cc86SMichal Swiatkowski 14640545cc86SMichal Swiatkowski status = ice_read_flat_nvm(hw, (u32)offset, &size, data, 14650545cc86SMichal Swiatkowski read_shadow_ram); 14660545cc86SMichal Swiatkowski if (status) { 14670545cc86SMichal Swiatkowski dev_dbg(dev, "ice_read_flat_nvm failed after reading %u bytes, err %d aq_err %d\n", 14680545cc86SMichal Swiatkowski size, status, hw->adminq.sq_last_status); 14690545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Failed to read NVM contents"); 14700545cc86SMichal Swiatkowski ice_release_nvm(hw); 14710545cc86SMichal Swiatkowski return -EIO; 14720545cc86SMichal Swiatkowski } 14730545cc86SMichal Swiatkowski ice_release_nvm(hw); 14740545cc86SMichal Swiatkowski 14750545cc86SMichal Swiatkowski return 0; 14760545cc86SMichal Swiatkowski } 14770545cc86SMichal Swiatkowski 14780545cc86SMichal Swiatkowski /** 14790545cc86SMichal Swiatkowski * ice_devlink_devcaps_snapshot - Capture snapshot of device capabilities 14800545cc86SMichal Swiatkowski * @devlink: the devlink instance 14810545cc86SMichal Swiatkowski * @ops: the devlink region being snapshotted 14820545cc86SMichal Swiatkowski * @extack: extended ACK response structure 14830545cc86SMichal Swiatkowski * @data: on exit points to snapshot data buffer 14840545cc86SMichal Swiatkowski * 14850545cc86SMichal Swiatkowski * This function is called in response to the DEVLINK_CMD_REGION_TRIGGER for 14860545cc86SMichal Swiatkowski * the device-caps devlink region. It captures a snapshot of the device 14870545cc86SMichal Swiatkowski * capabilities reported by firmware. 14880545cc86SMichal Swiatkowski * 14890545cc86SMichal Swiatkowski * @returns zero on success, and updates the data pointer. Returns a non-zero 14900545cc86SMichal Swiatkowski * error code on failure. 14910545cc86SMichal Swiatkowski */ 14920545cc86SMichal Swiatkowski static int 14930545cc86SMichal Swiatkowski ice_devlink_devcaps_snapshot(struct devlink *devlink, 14940545cc86SMichal Swiatkowski const struct devlink_region_ops *ops, 14950545cc86SMichal Swiatkowski struct netlink_ext_ack *extack, u8 **data) 14960545cc86SMichal Swiatkowski { 14970545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 14980545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 14990545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 15000545cc86SMichal Swiatkowski void *devcaps; 15010545cc86SMichal Swiatkowski int status; 15020545cc86SMichal Swiatkowski 15030545cc86SMichal Swiatkowski devcaps = vzalloc(ICE_AQ_MAX_BUF_LEN); 15040545cc86SMichal Swiatkowski if (!devcaps) 15050545cc86SMichal Swiatkowski return -ENOMEM; 15060545cc86SMichal Swiatkowski 15070545cc86SMichal Swiatkowski status = ice_aq_list_caps(hw, devcaps, ICE_AQ_MAX_BUF_LEN, NULL, 15080545cc86SMichal Swiatkowski ice_aqc_opc_list_dev_caps, NULL); 15090545cc86SMichal Swiatkowski if (status) { 15100545cc86SMichal Swiatkowski dev_dbg(dev, "ice_aq_list_caps: failed to read device capabilities, err %d aq_err %d\n", 15110545cc86SMichal Swiatkowski status, hw->adminq.sq_last_status); 15120545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Failed to read device capabilities"); 15130545cc86SMichal Swiatkowski vfree(devcaps); 15140545cc86SMichal Swiatkowski return status; 15150545cc86SMichal Swiatkowski } 15160545cc86SMichal Swiatkowski 15170545cc86SMichal Swiatkowski *data = (u8 *)devcaps; 15180545cc86SMichal Swiatkowski 15190545cc86SMichal Swiatkowski return 0; 15200545cc86SMichal Swiatkowski } 15210545cc86SMichal Swiatkowski 15220545cc86SMichal Swiatkowski static const struct devlink_region_ops ice_nvm_region_ops = { 15230545cc86SMichal Swiatkowski .name = "nvm-flash", 15240545cc86SMichal Swiatkowski .destructor = vfree, 15250545cc86SMichal Swiatkowski .snapshot = ice_devlink_nvm_snapshot, 15260545cc86SMichal Swiatkowski .read = ice_devlink_nvm_read, 15270545cc86SMichal Swiatkowski }; 15280545cc86SMichal Swiatkowski 15290545cc86SMichal Swiatkowski static const struct devlink_region_ops ice_sram_region_ops = { 15300545cc86SMichal Swiatkowski .name = "shadow-ram", 15310545cc86SMichal Swiatkowski .destructor = vfree, 15320545cc86SMichal Swiatkowski .snapshot = ice_devlink_nvm_snapshot, 15330545cc86SMichal Swiatkowski .read = ice_devlink_nvm_read, 15340545cc86SMichal Swiatkowski }; 15350545cc86SMichal Swiatkowski 15360545cc86SMichal Swiatkowski static const struct devlink_region_ops ice_devcaps_region_ops = { 15370545cc86SMichal Swiatkowski .name = "device-caps", 15380545cc86SMichal Swiatkowski .destructor = vfree, 15390545cc86SMichal Swiatkowski .snapshot = ice_devlink_devcaps_snapshot, 15400545cc86SMichal Swiatkowski }; 15410545cc86SMichal Swiatkowski 15420545cc86SMichal Swiatkowski /** 15430545cc86SMichal Swiatkowski * ice_devlink_init_regions - Initialize devlink regions 15440545cc86SMichal Swiatkowski * @pf: the PF device structure 15450545cc86SMichal Swiatkowski * 15460545cc86SMichal Swiatkowski * Create devlink regions used to enable access to dump the contents of the 15470545cc86SMichal Swiatkowski * flash memory on the device. 15480545cc86SMichal Swiatkowski */ 15490545cc86SMichal Swiatkowski void ice_devlink_init_regions(struct ice_pf *pf) 15500545cc86SMichal Swiatkowski { 15510545cc86SMichal Swiatkowski struct devlink *devlink = priv_to_devlink(pf); 15520545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 15530545cc86SMichal Swiatkowski u64 nvm_size, sram_size; 15540545cc86SMichal Swiatkowski 15550545cc86SMichal Swiatkowski nvm_size = pf->hw.flash.flash_size; 1556*118c6bdeSMichal Swiatkowski pf->nvm_region = devl_region_create(devlink, &ice_nvm_region_ops, 1, 15570545cc86SMichal Swiatkowski nvm_size); 15580545cc86SMichal Swiatkowski if (IS_ERR(pf->nvm_region)) { 15590545cc86SMichal Swiatkowski dev_err(dev, "failed to create NVM devlink region, err %ld\n", 15600545cc86SMichal Swiatkowski PTR_ERR(pf->nvm_region)); 15610545cc86SMichal Swiatkowski pf->nvm_region = NULL; 15620545cc86SMichal Swiatkowski } 15630545cc86SMichal Swiatkowski 15640545cc86SMichal Swiatkowski sram_size = pf->hw.flash.sr_words * 2u; 1565*118c6bdeSMichal Swiatkowski pf->sram_region = devl_region_create(devlink, &ice_sram_region_ops, 15660545cc86SMichal Swiatkowski 1, sram_size); 15670545cc86SMichal Swiatkowski if (IS_ERR(pf->sram_region)) { 15680545cc86SMichal Swiatkowski dev_err(dev, "failed to create shadow-ram devlink region, err %ld\n", 15690545cc86SMichal Swiatkowski PTR_ERR(pf->sram_region)); 15700545cc86SMichal Swiatkowski pf->sram_region = NULL; 15710545cc86SMichal Swiatkowski } 15720545cc86SMichal Swiatkowski 1573*118c6bdeSMichal Swiatkowski pf->devcaps_region = devl_region_create(devlink, 15740545cc86SMichal Swiatkowski &ice_devcaps_region_ops, 10, 15750545cc86SMichal Swiatkowski ICE_AQ_MAX_BUF_LEN); 15760545cc86SMichal Swiatkowski if (IS_ERR(pf->devcaps_region)) { 15770545cc86SMichal Swiatkowski dev_err(dev, "failed to create device-caps devlink region, err %ld\n", 15780545cc86SMichal Swiatkowski PTR_ERR(pf->devcaps_region)); 15790545cc86SMichal Swiatkowski pf->devcaps_region = NULL; 15800545cc86SMichal Swiatkowski } 15810545cc86SMichal Swiatkowski } 15820545cc86SMichal Swiatkowski 15830545cc86SMichal Swiatkowski /** 15840545cc86SMichal Swiatkowski * ice_devlink_destroy_regions - Destroy devlink regions 15850545cc86SMichal Swiatkowski * @pf: the PF device structure 15860545cc86SMichal Swiatkowski * 15870545cc86SMichal Swiatkowski * Remove previously created regions for this PF. 15880545cc86SMichal Swiatkowski */ 15890545cc86SMichal Swiatkowski void ice_devlink_destroy_regions(struct ice_pf *pf) 15900545cc86SMichal Swiatkowski { 15910545cc86SMichal Swiatkowski if (pf->nvm_region) 1592*118c6bdeSMichal Swiatkowski devl_region_destroy(pf->nvm_region); 15930545cc86SMichal Swiatkowski 15940545cc86SMichal Swiatkowski if (pf->sram_region) 1595*118c6bdeSMichal Swiatkowski devl_region_destroy(pf->sram_region); 15960545cc86SMichal Swiatkowski 15970545cc86SMichal Swiatkowski if (pf->devcaps_region) 1598*118c6bdeSMichal Swiatkowski devl_region_destroy(pf->devcaps_region); 15990545cc86SMichal Swiatkowski } 1600