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" 9*eda69d65SPiotr Raczynski #include "devlink_port.h" 100545cc86SMichal Swiatkowski #include "ice_eswitch.h" 110545cc86SMichal Swiatkowski #include "ice_fw_update.h" 120545cc86SMichal Swiatkowski #include "ice_dcb_lib.h" 130545cc86SMichal Swiatkowski 140545cc86SMichal Swiatkowski /* context for devlink info version reporting */ 150545cc86SMichal Swiatkowski struct ice_info_ctx { 160545cc86SMichal Swiatkowski char buf[128]; 170545cc86SMichal Swiatkowski struct ice_orom_info pending_orom; 180545cc86SMichal Swiatkowski struct ice_nvm_info pending_nvm; 190545cc86SMichal Swiatkowski struct ice_netlist_info pending_netlist; 200545cc86SMichal Swiatkowski struct ice_hw_dev_caps dev_caps; 210545cc86SMichal Swiatkowski }; 220545cc86SMichal Swiatkowski 230545cc86SMichal Swiatkowski /* The following functions are used to format specific strings for various 240545cc86SMichal Swiatkowski * devlink info versions. The ctx parameter is used to provide the storage 250545cc86SMichal Swiatkowski * buffer, as well as any ancillary information calculated when the info 260545cc86SMichal Swiatkowski * request was made. 270545cc86SMichal Swiatkowski * 280545cc86SMichal Swiatkowski * If a version does not exist, for example when attempting to get the 290545cc86SMichal Swiatkowski * inactive version of flash when there is no pending update, the function 300545cc86SMichal Swiatkowski * should leave the buffer in the ctx structure empty. 310545cc86SMichal Swiatkowski */ 320545cc86SMichal Swiatkowski 330545cc86SMichal Swiatkowski static void ice_info_get_dsn(struct ice_pf *pf, struct ice_info_ctx *ctx) 340545cc86SMichal Swiatkowski { 350545cc86SMichal Swiatkowski u8 dsn[8]; 360545cc86SMichal Swiatkowski 370545cc86SMichal Swiatkowski /* Copy the DSN into an array in Big Endian format */ 380545cc86SMichal Swiatkowski put_unaligned_be64(pci_get_dsn(pf->pdev), dsn); 390545cc86SMichal Swiatkowski 400545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%8phD", dsn); 410545cc86SMichal Swiatkowski } 420545cc86SMichal Swiatkowski 430545cc86SMichal Swiatkowski static void ice_info_pba(struct ice_pf *pf, struct ice_info_ctx *ctx) 440545cc86SMichal Swiatkowski { 450545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 460545cc86SMichal Swiatkowski int status; 470545cc86SMichal Swiatkowski 480545cc86SMichal Swiatkowski status = ice_read_pba_string(hw, (u8 *)ctx->buf, sizeof(ctx->buf)); 490545cc86SMichal Swiatkowski if (status) 500545cc86SMichal Swiatkowski /* We failed to locate the PBA, so just skip this entry */ 510545cc86SMichal Swiatkowski dev_dbg(ice_pf_to_dev(pf), "Failed to read Product Board Assembly string, status %d\n", 520545cc86SMichal Swiatkowski status); 530545cc86SMichal Swiatkowski } 540545cc86SMichal Swiatkowski 550545cc86SMichal Swiatkowski static void ice_info_fw_mgmt(struct ice_pf *pf, struct ice_info_ctx *ctx) 560545cc86SMichal Swiatkowski { 570545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 580545cc86SMichal Swiatkowski 590545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", 600545cc86SMichal Swiatkowski hw->fw_maj_ver, hw->fw_min_ver, hw->fw_patch); 610545cc86SMichal Swiatkowski } 620545cc86SMichal Swiatkowski 630545cc86SMichal Swiatkowski static void ice_info_fw_api(struct ice_pf *pf, struct ice_info_ctx *ctx) 640545cc86SMichal Swiatkowski { 650545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 660545cc86SMichal Swiatkowski 670545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", hw->api_maj_ver, 680545cc86SMichal Swiatkowski hw->api_min_ver, hw->api_patch); 690545cc86SMichal Swiatkowski } 700545cc86SMichal Swiatkowski 710545cc86SMichal Swiatkowski static void ice_info_fw_build(struct ice_pf *pf, struct ice_info_ctx *ctx) 720545cc86SMichal Swiatkowski { 730545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 740545cc86SMichal Swiatkowski 750545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", hw->fw_build); 760545cc86SMichal Swiatkowski } 770545cc86SMichal Swiatkowski 780545cc86SMichal Swiatkowski static void ice_info_orom_ver(struct ice_pf *pf, struct ice_info_ctx *ctx) 790545cc86SMichal Swiatkowski { 800545cc86SMichal Swiatkowski struct ice_orom_info *orom = &pf->hw.flash.orom; 810545cc86SMichal Swiatkowski 820545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", 830545cc86SMichal Swiatkowski orom->major, orom->build, orom->patch); 840545cc86SMichal Swiatkowski } 850545cc86SMichal Swiatkowski 860545cc86SMichal Swiatkowski static void 870545cc86SMichal Swiatkowski ice_info_pending_orom_ver(struct ice_pf __always_unused *pf, 880545cc86SMichal Swiatkowski struct ice_info_ctx *ctx) 890545cc86SMichal Swiatkowski { 900545cc86SMichal Swiatkowski struct ice_orom_info *orom = &ctx->pending_orom; 910545cc86SMichal Swiatkowski 920545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_orom) 930545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", 940545cc86SMichal Swiatkowski orom->major, orom->build, orom->patch); 950545cc86SMichal Swiatkowski } 960545cc86SMichal Swiatkowski 970545cc86SMichal Swiatkowski static void ice_info_nvm_ver(struct ice_pf *pf, struct ice_info_ctx *ctx) 980545cc86SMichal Swiatkowski { 990545cc86SMichal Swiatkowski struct ice_nvm_info *nvm = &pf->hw.flash.nvm; 1000545cc86SMichal Swiatkowski 1010545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", nvm->major, nvm->minor); 1020545cc86SMichal Swiatkowski } 1030545cc86SMichal Swiatkowski 1040545cc86SMichal Swiatkowski static void 1050545cc86SMichal Swiatkowski ice_info_pending_nvm_ver(struct ice_pf __always_unused *pf, 1060545cc86SMichal Swiatkowski struct ice_info_ctx *ctx) 1070545cc86SMichal Swiatkowski { 1080545cc86SMichal Swiatkowski struct ice_nvm_info *nvm = &ctx->pending_nvm; 1090545cc86SMichal Swiatkowski 1100545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_nvm) 1110545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", 1120545cc86SMichal Swiatkowski nvm->major, nvm->minor); 1130545cc86SMichal Swiatkowski } 1140545cc86SMichal Swiatkowski 1150545cc86SMichal Swiatkowski static void ice_info_eetrack(struct ice_pf *pf, struct ice_info_ctx *ctx) 1160545cc86SMichal Swiatkowski { 1170545cc86SMichal Swiatkowski struct ice_nvm_info *nvm = &pf->hw.flash.nvm; 1180545cc86SMichal Swiatkowski 1190545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm->eetrack); 1200545cc86SMichal Swiatkowski } 1210545cc86SMichal Swiatkowski 1220545cc86SMichal Swiatkowski static void 1230545cc86SMichal Swiatkowski ice_info_pending_eetrack(struct ice_pf *pf, struct ice_info_ctx *ctx) 1240545cc86SMichal Swiatkowski { 1250545cc86SMichal Swiatkowski struct ice_nvm_info *nvm = &ctx->pending_nvm; 1260545cc86SMichal Swiatkowski 1270545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_nvm) 1280545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm->eetrack); 1290545cc86SMichal Swiatkowski } 1300545cc86SMichal Swiatkowski 1310545cc86SMichal Swiatkowski static void ice_info_ddp_pkg_name(struct ice_pf *pf, struct ice_info_ctx *ctx) 1320545cc86SMichal Swiatkowski { 1330545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 1340545cc86SMichal Swiatkowski 1350545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%s", hw->active_pkg_name); 1360545cc86SMichal Swiatkowski } 1370545cc86SMichal Swiatkowski 1380545cc86SMichal Swiatkowski static void 1390545cc86SMichal Swiatkowski ice_info_ddp_pkg_version(struct ice_pf *pf, struct ice_info_ctx *ctx) 1400545cc86SMichal Swiatkowski { 1410545cc86SMichal Swiatkowski struct ice_pkg_ver *pkg = &pf->hw.active_pkg_ver; 1420545cc86SMichal Swiatkowski 1430545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u.%u", 1440545cc86SMichal Swiatkowski pkg->major, pkg->minor, pkg->update, pkg->draft); 1450545cc86SMichal Swiatkowski } 1460545cc86SMichal Swiatkowski 1470545cc86SMichal Swiatkowski static void 1480545cc86SMichal Swiatkowski ice_info_ddp_pkg_bundle_id(struct ice_pf *pf, struct ice_info_ctx *ctx) 1490545cc86SMichal Swiatkowski { 1500545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", pf->hw.active_track_id); 1510545cc86SMichal Swiatkowski } 1520545cc86SMichal Swiatkowski 1530545cc86SMichal Swiatkowski static void ice_info_netlist_ver(struct ice_pf *pf, struct ice_info_ctx *ctx) 1540545cc86SMichal Swiatkowski { 1550545cc86SMichal Swiatkowski struct ice_netlist_info *netlist = &pf->hw.flash.netlist; 1560545cc86SMichal Swiatkowski 1570545cc86SMichal Swiatkowski /* The netlist version fields are BCD formatted */ 1580545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x", 1590545cc86SMichal Swiatkowski netlist->major, netlist->minor, 1600545cc86SMichal Swiatkowski netlist->type >> 16, netlist->type & 0xFFFF, 1610545cc86SMichal Swiatkowski netlist->rev, netlist->cust_ver); 1620545cc86SMichal Swiatkowski } 1630545cc86SMichal Swiatkowski 1640545cc86SMichal Swiatkowski static void ice_info_netlist_build(struct ice_pf *pf, struct ice_info_ctx *ctx) 1650545cc86SMichal Swiatkowski { 1660545cc86SMichal Swiatkowski struct ice_netlist_info *netlist = &pf->hw.flash.netlist; 1670545cc86SMichal Swiatkowski 1680545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash); 1690545cc86SMichal Swiatkowski } 1700545cc86SMichal Swiatkowski 1710545cc86SMichal Swiatkowski static void 1720545cc86SMichal Swiatkowski ice_info_pending_netlist_ver(struct ice_pf __always_unused *pf, 1730545cc86SMichal Swiatkowski struct ice_info_ctx *ctx) 1740545cc86SMichal Swiatkowski { 1750545cc86SMichal Swiatkowski struct ice_netlist_info *netlist = &ctx->pending_netlist; 1760545cc86SMichal Swiatkowski 1770545cc86SMichal Swiatkowski /* The netlist version fields are BCD formatted */ 1780545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_netlist) 1790545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x", 1800545cc86SMichal Swiatkowski netlist->major, netlist->minor, 1810545cc86SMichal Swiatkowski netlist->type >> 16, netlist->type & 0xFFFF, 1820545cc86SMichal Swiatkowski netlist->rev, netlist->cust_ver); 1830545cc86SMichal Swiatkowski } 1840545cc86SMichal Swiatkowski 1850545cc86SMichal Swiatkowski static void 1860545cc86SMichal Swiatkowski ice_info_pending_netlist_build(struct ice_pf __always_unused *pf, 1870545cc86SMichal Swiatkowski struct ice_info_ctx *ctx) 1880545cc86SMichal Swiatkowski { 1890545cc86SMichal Swiatkowski struct ice_netlist_info *netlist = &ctx->pending_netlist; 1900545cc86SMichal Swiatkowski 1910545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_netlist) 1920545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash); 1930545cc86SMichal Swiatkowski } 1940545cc86SMichal Swiatkowski 1950545cc86SMichal Swiatkowski static void ice_info_cgu_fw_build(struct ice_pf *pf, struct ice_info_ctx *ctx) 1960545cc86SMichal Swiatkowski { 1970545cc86SMichal Swiatkowski u32 id, cfg_ver, fw_ver; 1980545cc86SMichal Swiatkowski 1990545cc86SMichal Swiatkowski if (!ice_is_feature_supported(pf, ICE_F_CGU)) 2000545cc86SMichal Swiatkowski return; 2010545cc86SMichal Swiatkowski if (ice_aq_get_cgu_info(&pf->hw, &id, &cfg_ver, &fw_ver)) 2020545cc86SMichal Swiatkowski return; 2030545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", id, cfg_ver, fw_ver); 2040545cc86SMichal Swiatkowski } 2050545cc86SMichal Swiatkowski 2060545cc86SMichal Swiatkowski static void ice_info_cgu_id(struct ice_pf *pf, struct ice_info_ctx *ctx) 2070545cc86SMichal Swiatkowski { 2080545cc86SMichal Swiatkowski if (!ice_is_feature_supported(pf, ICE_F_CGU)) 2090545cc86SMichal Swiatkowski return; 2100545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%u", pf->hw.cgu_part_number); 2110545cc86SMichal Swiatkowski } 2120545cc86SMichal Swiatkowski 2130545cc86SMichal Swiatkowski #define fixed(key, getter) { ICE_VERSION_FIXED, key, getter, NULL } 2140545cc86SMichal Swiatkowski #define running(key, getter) { ICE_VERSION_RUNNING, key, getter, NULL } 2150545cc86SMichal Swiatkowski #define stored(key, getter, fallback) { ICE_VERSION_STORED, key, getter, fallback } 2160545cc86SMichal Swiatkowski 2170545cc86SMichal Swiatkowski /* The combined() macro inserts both the running entry as well as a stored 2180545cc86SMichal Swiatkowski * entry. The running entry will always report the version from the active 2190545cc86SMichal Swiatkowski * handler. The stored entry will first try the pending handler, and fallback 2200545cc86SMichal Swiatkowski * to the active handler if the pending function does not report a version. 2210545cc86SMichal Swiatkowski * The pending handler should check the status of a pending update for the 2220545cc86SMichal Swiatkowski * relevant flash component. It should only fill in the buffer in the case 2230545cc86SMichal Swiatkowski * where a valid pending version is available. This ensures that the related 2240545cc86SMichal Swiatkowski * stored and running versions remain in sync, and that stored versions are 2250545cc86SMichal Swiatkowski * correctly reported as expected. 2260545cc86SMichal Swiatkowski */ 2270545cc86SMichal Swiatkowski #define combined(key, active, pending) \ 2280545cc86SMichal Swiatkowski running(key, active), \ 2290545cc86SMichal Swiatkowski stored(key, pending, active) 2300545cc86SMichal Swiatkowski 2310545cc86SMichal Swiatkowski enum ice_version_type { 2320545cc86SMichal Swiatkowski ICE_VERSION_FIXED, 2330545cc86SMichal Swiatkowski ICE_VERSION_RUNNING, 2340545cc86SMichal Swiatkowski ICE_VERSION_STORED, 2350545cc86SMichal Swiatkowski }; 2360545cc86SMichal Swiatkowski 2370545cc86SMichal Swiatkowski static const struct ice_devlink_version { 2380545cc86SMichal Swiatkowski enum ice_version_type type; 2390545cc86SMichal Swiatkowski const char *key; 2400545cc86SMichal Swiatkowski void (*getter)(struct ice_pf *pf, struct ice_info_ctx *ctx); 2410545cc86SMichal Swiatkowski void (*fallback)(struct ice_pf *pf, struct ice_info_ctx *ctx); 2420545cc86SMichal Swiatkowski } ice_devlink_versions[] = { 2430545cc86SMichal Swiatkowski fixed(DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, ice_info_pba), 2440545cc86SMichal Swiatkowski running(DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, ice_info_fw_mgmt), 2450545cc86SMichal Swiatkowski running("fw.mgmt.api", ice_info_fw_api), 2460545cc86SMichal Swiatkowski running("fw.mgmt.build", ice_info_fw_build), 2470545cc86SMichal Swiatkowski combined(DEVLINK_INFO_VERSION_GENERIC_FW_UNDI, ice_info_orom_ver, ice_info_pending_orom_ver), 2480545cc86SMichal Swiatkowski combined("fw.psid.api", ice_info_nvm_ver, ice_info_pending_nvm_ver), 2490545cc86SMichal Swiatkowski combined(DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID, ice_info_eetrack, ice_info_pending_eetrack), 2500545cc86SMichal Swiatkowski running("fw.app.name", ice_info_ddp_pkg_name), 2510545cc86SMichal Swiatkowski running(DEVLINK_INFO_VERSION_GENERIC_FW_APP, ice_info_ddp_pkg_version), 2520545cc86SMichal Swiatkowski running("fw.app.bundle_id", ice_info_ddp_pkg_bundle_id), 2530545cc86SMichal Swiatkowski combined("fw.netlist", ice_info_netlist_ver, ice_info_pending_netlist_ver), 2540545cc86SMichal Swiatkowski combined("fw.netlist.build", ice_info_netlist_build, ice_info_pending_netlist_build), 2550545cc86SMichal Swiatkowski fixed("cgu.id", ice_info_cgu_id), 2560545cc86SMichal Swiatkowski running("fw.cgu", ice_info_cgu_fw_build), 2570545cc86SMichal Swiatkowski }; 2580545cc86SMichal Swiatkowski 2590545cc86SMichal Swiatkowski /** 2600545cc86SMichal Swiatkowski * ice_devlink_info_get - .info_get devlink handler 2610545cc86SMichal Swiatkowski * @devlink: devlink instance structure 2620545cc86SMichal Swiatkowski * @req: the devlink info request 2630545cc86SMichal Swiatkowski * @extack: extended netdev ack structure 2640545cc86SMichal Swiatkowski * 2650545cc86SMichal Swiatkowski * Callback for the devlink .info_get operation. Reports information about the 2660545cc86SMichal Swiatkowski * device. 2670545cc86SMichal Swiatkowski * 2680545cc86SMichal Swiatkowski * Return: zero on success or an error code on failure. 2690545cc86SMichal Swiatkowski */ 2700545cc86SMichal Swiatkowski static int ice_devlink_info_get(struct devlink *devlink, 2710545cc86SMichal Swiatkowski struct devlink_info_req *req, 2720545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 2730545cc86SMichal Swiatkowski { 2740545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 2750545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 2760545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 2770545cc86SMichal Swiatkowski struct ice_info_ctx *ctx; 2780545cc86SMichal Swiatkowski size_t i; 2790545cc86SMichal Swiatkowski int err; 2800545cc86SMichal Swiatkowski 2810545cc86SMichal Swiatkowski err = ice_wait_for_reset(pf, 10 * HZ); 2820545cc86SMichal Swiatkowski if (err) { 2830545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Device is busy resetting"); 2840545cc86SMichal Swiatkowski return err; 2850545cc86SMichal Swiatkowski } 2860545cc86SMichal Swiatkowski 2870545cc86SMichal Swiatkowski ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 2880545cc86SMichal Swiatkowski if (!ctx) 2890545cc86SMichal Swiatkowski return -ENOMEM; 2900545cc86SMichal Swiatkowski 2910545cc86SMichal Swiatkowski /* discover capabilities first */ 2920545cc86SMichal Swiatkowski err = ice_discover_dev_caps(hw, &ctx->dev_caps); 2930545cc86SMichal Swiatkowski if (err) { 2940545cc86SMichal Swiatkowski dev_dbg(dev, "Failed to discover device capabilities, status %d aq_err %s\n", 2950545cc86SMichal Swiatkowski err, ice_aq_str(hw->adminq.sq_last_status)); 2960545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unable to discover device capabilities"); 2970545cc86SMichal Swiatkowski goto out_free_ctx; 2980545cc86SMichal Swiatkowski } 2990545cc86SMichal Swiatkowski 3000545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_orom) { 3010545cc86SMichal Swiatkowski err = ice_get_inactive_orom_ver(hw, &ctx->pending_orom); 3020545cc86SMichal Swiatkowski if (err) { 3030545cc86SMichal Swiatkowski dev_dbg(dev, "Unable to read inactive Option ROM version data, status %d aq_err %s\n", 3040545cc86SMichal Swiatkowski err, ice_aq_str(hw->adminq.sq_last_status)); 3050545cc86SMichal Swiatkowski 3060545cc86SMichal Swiatkowski /* disable display of pending Option ROM */ 3070545cc86SMichal Swiatkowski ctx->dev_caps.common_cap.nvm_update_pending_orom = false; 3080545cc86SMichal Swiatkowski } 3090545cc86SMichal Swiatkowski } 3100545cc86SMichal Swiatkowski 3110545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_nvm) { 3120545cc86SMichal Swiatkowski err = ice_get_inactive_nvm_ver(hw, &ctx->pending_nvm); 3130545cc86SMichal Swiatkowski if (err) { 3140545cc86SMichal Swiatkowski dev_dbg(dev, "Unable to read inactive NVM version data, status %d aq_err %s\n", 3150545cc86SMichal Swiatkowski err, ice_aq_str(hw->adminq.sq_last_status)); 3160545cc86SMichal Swiatkowski 3170545cc86SMichal Swiatkowski /* disable display of pending Option ROM */ 3180545cc86SMichal Swiatkowski ctx->dev_caps.common_cap.nvm_update_pending_nvm = false; 3190545cc86SMichal Swiatkowski } 3200545cc86SMichal Swiatkowski } 3210545cc86SMichal Swiatkowski 3220545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_netlist) { 3230545cc86SMichal Swiatkowski err = ice_get_inactive_netlist_ver(hw, &ctx->pending_netlist); 3240545cc86SMichal Swiatkowski if (err) { 3250545cc86SMichal Swiatkowski dev_dbg(dev, "Unable to read inactive Netlist version data, status %d aq_err %s\n", 3260545cc86SMichal Swiatkowski err, ice_aq_str(hw->adminq.sq_last_status)); 3270545cc86SMichal Swiatkowski 3280545cc86SMichal Swiatkowski /* disable display of pending Option ROM */ 3290545cc86SMichal Swiatkowski ctx->dev_caps.common_cap.nvm_update_pending_netlist = false; 3300545cc86SMichal Swiatkowski } 3310545cc86SMichal Swiatkowski } 3320545cc86SMichal Swiatkowski 3330545cc86SMichal Swiatkowski ice_info_get_dsn(pf, ctx); 3340545cc86SMichal Swiatkowski 3350545cc86SMichal Swiatkowski err = devlink_info_serial_number_put(req, ctx->buf); 3360545cc86SMichal Swiatkowski if (err) { 3370545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unable to set serial number"); 3380545cc86SMichal Swiatkowski goto out_free_ctx; 3390545cc86SMichal Swiatkowski } 3400545cc86SMichal Swiatkowski 3410545cc86SMichal Swiatkowski for (i = 0; i < ARRAY_SIZE(ice_devlink_versions); i++) { 3420545cc86SMichal Swiatkowski enum ice_version_type type = ice_devlink_versions[i].type; 3430545cc86SMichal Swiatkowski const char *key = ice_devlink_versions[i].key; 3440545cc86SMichal Swiatkowski 3450545cc86SMichal Swiatkowski memset(ctx->buf, 0, sizeof(ctx->buf)); 3460545cc86SMichal Swiatkowski 3470545cc86SMichal Swiatkowski ice_devlink_versions[i].getter(pf, ctx); 3480545cc86SMichal Swiatkowski 3490545cc86SMichal Swiatkowski /* If the default getter doesn't report a version, use the 3500545cc86SMichal Swiatkowski * fallback function. This is primarily useful in the case of 3510545cc86SMichal Swiatkowski * "stored" versions that want to report the same value as the 3520545cc86SMichal Swiatkowski * running version in the normal case of no pending update. 3530545cc86SMichal Swiatkowski */ 3540545cc86SMichal Swiatkowski if (ctx->buf[0] == '\0' && ice_devlink_versions[i].fallback) 3550545cc86SMichal Swiatkowski ice_devlink_versions[i].fallback(pf, ctx); 3560545cc86SMichal Swiatkowski 3570545cc86SMichal Swiatkowski /* Do not report missing versions */ 3580545cc86SMichal Swiatkowski if (ctx->buf[0] == '\0') 3590545cc86SMichal Swiatkowski continue; 3600545cc86SMichal Swiatkowski 3610545cc86SMichal Swiatkowski switch (type) { 3620545cc86SMichal Swiatkowski case ICE_VERSION_FIXED: 3630545cc86SMichal Swiatkowski err = devlink_info_version_fixed_put(req, key, ctx->buf); 3640545cc86SMichal Swiatkowski if (err) { 3650545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unable to set fixed version"); 3660545cc86SMichal Swiatkowski goto out_free_ctx; 3670545cc86SMichal Swiatkowski } 3680545cc86SMichal Swiatkowski break; 3690545cc86SMichal Swiatkowski case ICE_VERSION_RUNNING: 3700545cc86SMichal Swiatkowski err = devlink_info_version_running_put(req, key, ctx->buf); 3710545cc86SMichal Swiatkowski if (err) { 3720545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unable to set running version"); 3730545cc86SMichal Swiatkowski goto out_free_ctx; 3740545cc86SMichal Swiatkowski } 3750545cc86SMichal Swiatkowski break; 3760545cc86SMichal Swiatkowski case ICE_VERSION_STORED: 3770545cc86SMichal Swiatkowski err = devlink_info_version_stored_put(req, key, ctx->buf); 3780545cc86SMichal Swiatkowski if (err) { 3790545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unable to set stored version"); 3800545cc86SMichal Swiatkowski goto out_free_ctx; 3810545cc86SMichal Swiatkowski } 3820545cc86SMichal Swiatkowski break; 3830545cc86SMichal Swiatkowski } 3840545cc86SMichal Swiatkowski } 3850545cc86SMichal Swiatkowski 3860545cc86SMichal Swiatkowski out_free_ctx: 3870545cc86SMichal Swiatkowski kfree(ctx); 3880545cc86SMichal Swiatkowski return err; 3890545cc86SMichal Swiatkowski } 3900545cc86SMichal Swiatkowski 3910545cc86SMichal Swiatkowski /** 3920545cc86SMichal Swiatkowski * ice_devlink_reload_empr_start - Start EMP reset to activate new firmware 3930545cc86SMichal Swiatkowski * @pf: pointer to the pf instance 3940545cc86SMichal Swiatkowski * @extack: netlink extended ACK structure 3950545cc86SMichal Swiatkowski * 3960545cc86SMichal Swiatkowski * Allow user to activate new Embedded Management Processor firmware by 3970545cc86SMichal Swiatkowski * issuing device specific EMP reset. Called in response to 3980545cc86SMichal Swiatkowski * a DEVLINK_CMD_RELOAD with the DEVLINK_RELOAD_ACTION_FW_ACTIVATE. 3990545cc86SMichal Swiatkowski * 4000545cc86SMichal Swiatkowski * Note that teardown and rebuild of the driver state happens automatically as 4010545cc86SMichal Swiatkowski * part of an interrupt and watchdog task. This is because all physical 4020545cc86SMichal Swiatkowski * functions on the device must be able to reset when an EMP reset occurs from 4030545cc86SMichal Swiatkowski * any source. 4040545cc86SMichal Swiatkowski */ 4050545cc86SMichal Swiatkowski static int 4060545cc86SMichal Swiatkowski ice_devlink_reload_empr_start(struct ice_pf *pf, 4070545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 4080545cc86SMichal Swiatkowski { 4090545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 4100545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 4110545cc86SMichal Swiatkowski u8 pending; 4120545cc86SMichal Swiatkowski int err; 4130545cc86SMichal Swiatkowski 4140545cc86SMichal Swiatkowski err = ice_get_pending_updates(pf, &pending, extack); 4150545cc86SMichal Swiatkowski if (err) 4160545cc86SMichal Swiatkowski return err; 4170545cc86SMichal Swiatkowski 4180545cc86SMichal Swiatkowski /* pending is a bitmask of which flash banks have a pending update, 4190545cc86SMichal Swiatkowski * including the main NVM bank, the Option ROM bank, and the netlist 4200545cc86SMichal Swiatkowski * bank. If any of these bits are set, then there is a pending update 4210545cc86SMichal Swiatkowski * waiting to be activated. 4220545cc86SMichal Swiatkowski */ 4230545cc86SMichal Swiatkowski if (!pending) { 4240545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "No pending firmware update"); 4250545cc86SMichal Swiatkowski return -ECANCELED; 4260545cc86SMichal Swiatkowski } 4270545cc86SMichal Swiatkowski 4280545cc86SMichal Swiatkowski if (pf->fw_emp_reset_disabled) { 4290545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "EMP reset is not available. To activate firmware, a reboot or power cycle is needed"); 4300545cc86SMichal Swiatkowski return -ECANCELED; 4310545cc86SMichal Swiatkowski } 4320545cc86SMichal Swiatkowski 4330545cc86SMichal Swiatkowski dev_dbg(dev, "Issuing device EMP reset to activate firmware\n"); 4340545cc86SMichal Swiatkowski 4350545cc86SMichal Swiatkowski err = ice_aq_nvm_update_empr(hw); 4360545cc86SMichal Swiatkowski if (err) { 4370545cc86SMichal Swiatkowski dev_err(dev, "Failed to trigger EMP device reset to reload firmware, err %d aq_err %s\n", 4380545cc86SMichal Swiatkowski err, ice_aq_str(hw->adminq.sq_last_status)); 4390545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Failed to trigger EMP device reset to reload firmware"); 4400545cc86SMichal Swiatkowski return err; 4410545cc86SMichal Swiatkowski } 4420545cc86SMichal Swiatkowski 4430545cc86SMichal Swiatkowski return 0; 4440545cc86SMichal Swiatkowski } 4450545cc86SMichal Swiatkowski 4460545cc86SMichal Swiatkowski /** 4470545cc86SMichal Swiatkowski * ice_devlink_reinit_down - unload given PF 4480545cc86SMichal Swiatkowski * @pf: pointer to the PF struct 4490545cc86SMichal Swiatkowski */ 4500545cc86SMichal Swiatkowski static void ice_devlink_reinit_down(struct ice_pf *pf) 4510545cc86SMichal Swiatkowski { 4520545cc86SMichal Swiatkowski /* No need to take devl_lock, it's already taken by devlink API */ 4530545cc86SMichal Swiatkowski ice_unload(pf); 4540545cc86SMichal Swiatkowski rtnl_lock(); 4550545cc86SMichal Swiatkowski ice_vsi_decfg(ice_get_main_vsi(pf)); 4560545cc86SMichal Swiatkowski rtnl_unlock(); 4570545cc86SMichal Swiatkowski ice_deinit_dev(pf); 4580545cc86SMichal Swiatkowski } 4590545cc86SMichal Swiatkowski 4600545cc86SMichal Swiatkowski /** 4610545cc86SMichal Swiatkowski * ice_devlink_reload_down - prepare for reload 4620545cc86SMichal Swiatkowski * @devlink: pointer to the devlink instance to reload 4630545cc86SMichal Swiatkowski * @netns_change: if true, the network namespace is changing 4640545cc86SMichal Swiatkowski * @action: the action to perform 4650545cc86SMichal Swiatkowski * @limit: limits on what reload should do, such as not resetting 4660545cc86SMichal Swiatkowski * @extack: netlink extended ACK structure 4670545cc86SMichal Swiatkowski */ 4680545cc86SMichal Swiatkowski static int 4690545cc86SMichal Swiatkowski ice_devlink_reload_down(struct devlink *devlink, bool netns_change, 4700545cc86SMichal Swiatkowski enum devlink_reload_action action, 4710545cc86SMichal Swiatkowski enum devlink_reload_limit limit, 4720545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 4730545cc86SMichal Swiatkowski { 4740545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 4750545cc86SMichal Swiatkowski 4760545cc86SMichal Swiatkowski switch (action) { 4770545cc86SMichal Swiatkowski case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: 4780545cc86SMichal Swiatkowski if (ice_is_eswitch_mode_switchdev(pf)) { 4790545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, 4800545cc86SMichal Swiatkowski "Go to legacy mode before doing reinit"); 4810545cc86SMichal Swiatkowski return -EOPNOTSUPP; 4820545cc86SMichal Swiatkowski } 4830545cc86SMichal Swiatkowski if (ice_is_adq_active(pf)) { 4840545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, 4850545cc86SMichal Swiatkowski "Turn off ADQ before doing reinit"); 4860545cc86SMichal Swiatkowski return -EOPNOTSUPP; 4870545cc86SMichal Swiatkowski } 4880545cc86SMichal Swiatkowski if (ice_has_vfs(pf)) { 4890545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, 4900545cc86SMichal Swiatkowski "Remove all VFs before doing reinit"); 4910545cc86SMichal Swiatkowski return -EOPNOTSUPP; 4920545cc86SMichal Swiatkowski } 4930545cc86SMichal Swiatkowski ice_devlink_reinit_down(pf); 4940545cc86SMichal Swiatkowski return 0; 4950545cc86SMichal Swiatkowski case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: 4960545cc86SMichal Swiatkowski return ice_devlink_reload_empr_start(pf, extack); 4970545cc86SMichal Swiatkowski default: 4980545cc86SMichal Swiatkowski WARN_ON(1); 4990545cc86SMichal Swiatkowski return -EOPNOTSUPP; 5000545cc86SMichal Swiatkowski } 5010545cc86SMichal Swiatkowski } 5020545cc86SMichal Swiatkowski 5030545cc86SMichal Swiatkowski /** 5040545cc86SMichal Swiatkowski * ice_devlink_reload_empr_finish - Wait for EMP reset to finish 5050545cc86SMichal Swiatkowski * @pf: pointer to the pf instance 5060545cc86SMichal Swiatkowski * @extack: netlink extended ACK structure 5070545cc86SMichal Swiatkowski * 5080545cc86SMichal Swiatkowski * Wait for driver to finish rebuilding after EMP reset is completed. This 5090545cc86SMichal Swiatkowski * includes time to wait for both the actual device reset as well as the time 5100545cc86SMichal Swiatkowski * for the driver's rebuild to complete. 5110545cc86SMichal Swiatkowski */ 5120545cc86SMichal Swiatkowski static int 5130545cc86SMichal Swiatkowski ice_devlink_reload_empr_finish(struct ice_pf *pf, 5140545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 5150545cc86SMichal Swiatkowski { 5160545cc86SMichal Swiatkowski int err; 5170545cc86SMichal Swiatkowski 5180545cc86SMichal Swiatkowski err = ice_wait_for_reset(pf, 60 * HZ); 5190545cc86SMichal Swiatkowski if (err) { 5200545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Device still resetting after 1 minute"); 5210545cc86SMichal Swiatkowski return err; 5220545cc86SMichal Swiatkowski } 5230545cc86SMichal Swiatkowski 5240545cc86SMichal Swiatkowski return 0; 5250545cc86SMichal Swiatkowski } 5260545cc86SMichal Swiatkowski 5270545cc86SMichal Swiatkowski /** 528109eb291SLukasz Czapnik * ice_get_tx_topo_user_sel - Read user's choice from flash 529109eb291SLukasz Czapnik * @pf: pointer to pf structure 530109eb291SLukasz Czapnik * @layers: value read from flash will be saved here 531109eb291SLukasz Czapnik * 532109eb291SLukasz Czapnik * Reads user's preference for Tx Scheduler Topology Tree from PFA TLV. 533109eb291SLukasz Czapnik * 534109eb291SLukasz Czapnik * Return: zero when read was successful, negative values otherwise. 535109eb291SLukasz Czapnik */ 536109eb291SLukasz Czapnik static int ice_get_tx_topo_user_sel(struct ice_pf *pf, uint8_t *layers) 537109eb291SLukasz Czapnik { 538109eb291SLukasz Czapnik struct ice_aqc_nvm_tx_topo_user_sel usr_sel = {}; 539109eb291SLukasz Czapnik struct ice_hw *hw = &pf->hw; 540109eb291SLukasz Czapnik int err; 541109eb291SLukasz Czapnik 542109eb291SLukasz Czapnik err = ice_acquire_nvm(hw, ICE_RES_READ); 543109eb291SLukasz Czapnik if (err) 544109eb291SLukasz Czapnik return err; 545109eb291SLukasz Czapnik 546109eb291SLukasz Czapnik err = ice_aq_read_nvm(hw, ICE_AQC_NVM_TX_TOPO_MOD_ID, 0, 547109eb291SLukasz Czapnik sizeof(usr_sel), &usr_sel, true, true, NULL); 548109eb291SLukasz Czapnik if (err) 549109eb291SLukasz Czapnik goto exit_release_res; 550109eb291SLukasz Czapnik 551109eb291SLukasz Czapnik if (usr_sel.data & ICE_AQC_NVM_TX_TOPO_USER_SEL) 552109eb291SLukasz Czapnik *layers = ICE_SCHED_5_LAYERS; 553109eb291SLukasz Czapnik else 554109eb291SLukasz Czapnik *layers = ICE_SCHED_9_LAYERS; 555109eb291SLukasz Czapnik 556109eb291SLukasz Czapnik exit_release_res: 557109eb291SLukasz Czapnik ice_release_nvm(hw); 558109eb291SLukasz Czapnik 559109eb291SLukasz Czapnik return err; 560109eb291SLukasz Czapnik } 561109eb291SLukasz Czapnik 562109eb291SLukasz Czapnik /** 563109eb291SLukasz Czapnik * ice_update_tx_topo_user_sel - Save user's preference in flash 564109eb291SLukasz Czapnik * @pf: pointer to pf structure 565109eb291SLukasz Czapnik * @layers: value to be saved in flash 566109eb291SLukasz Czapnik * 567109eb291SLukasz Czapnik * Variable "layers" defines user's preference about number of layers in Tx 568109eb291SLukasz Czapnik * Scheduler Topology Tree. This choice should be stored in PFA TLV field 569109eb291SLukasz Czapnik * and be picked up by driver, next time during init. 570109eb291SLukasz Czapnik * 571109eb291SLukasz Czapnik * Return: zero when save was successful, negative values otherwise. 572109eb291SLukasz Czapnik */ 573109eb291SLukasz Czapnik static int ice_update_tx_topo_user_sel(struct ice_pf *pf, int layers) 574109eb291SLukasz Czapnik { 575109eb291SLukasz Czapnik struct ice_aqc_nvm_tx_topo_user_sel usr_sel = {}; 576109eb291SLukasz Czapnik struct ice_hw *hw = &pf->hw; 577109eb291SLukasz Czapnik int err; 578109eb291SLukasz Czapnik 579109eb291SLukasz Czapnik err = ice_acquire_nvm(hw, ICE_RES_WRITE); 580109eb291SLukasz Czapnik if (err) 581109eb291SLukasz Czapnik return err; 582109eb291SLukasz Czapnik 583109eb291SLukasz Czapnik err = ice_aq_read_nvm(hw, ICE_AQC_NVM_TX_TOPO_MOD_ID, 0, 584109eb291SLukasz Czapnik sizeof(usr_sel), &usr_sel, true, true, NULL); 585109eb291SLukasz Czapnik if (err) 586109eb291SLukasz Czapnik goto exit_release_res; 587109eb291SLukasz Czapnik 588109eb291SLukasz Czapnik if (layers == ICE_SCHED_5_LAYERS) 589109eb291SLukasz Czapnik usr_sel.data |= ICE_AQC_NVM_TX_TOPO_USER_SEL; 590109eb291SLukasz Czapnik else 591109eb291SLukasz Czapnik usr_sel.data &= ~ICE_AQC_NVM_TX_TOPO_USER_SEL; 592109eb291SLukasz Czapnik 593109eb291SLukasz Czapnik err = ice_write_one_nvm_block(pf, ICE_AQC_NVM_TX_TOPO_MOD_ID, 2, 594109eb291SLukasz Czapnik sizeof(usr_sel.data), &usr_sel.data, 595109eb291SLukasz Czapnik true, NULL, NULL); 596109eb291SLukasz Czapnik exit_release_res: 597109eb291SLukasz Czapnik ice_release_nvm(hw); 598109eb291SLukasz Czapnik 599109eb291SLukasz Czapnik return err; 600109eb291SLukasz Czapnik } 601109eb291SLukasz Czapnik 602109eb291SLukasz Czapnik /** 603109eb291SLukasz Czapnik * ice_devlink_tx_sched_layers_get - Get tx_scheduling_layers parameter 604109eb291SLukasz Czapnik * @devlink: pointer to the devlink instance 605109eb291SLukasz Czapnik * @id: the parameter ID to set 606109eb291SLukasz Czapnik * @ctx: context to store the parameter value 607109eb291SLukasz Czapnik * 608109eb291SLukasz Czapnik * Return: zero on success and negative value on failure. 609109eb291SLukasz Czapnik */ 610109eb291SLukasz Czapnik static int ice_devlink_tx_sched_layers_get(struct devlink *devlink, u32 id, 611109eb291SLukasz Czapnik struct devlink_param_gset_ctx *ctx) 612109eb291SLukasz Czapnik { 613109eb291SLukasz Czapnik struct ice_pf *pf = devlink_priv(devlink); 614109eb291SLukasz Czapnik int err; 615109eb291SLukasz Czapnik 616109eb291SLukasz Czapnik err = ice_get_tx_topo_user_sel(pf, &ctx->val.vu8); 617109eb291SLukasz Czapnik if (err) 618109eb291SLukasz Czapnik return err; 619109eb291SLukasz Czapnik 620109eb291SLukasz Czapnik return 0; 621109eb291SLukasz Czapnik } 622109eb291SLukasz Czapnik 623109eb291SLukasz Czapnik /** 624109eb291SLukasz Czapnik * ice_devlink_tx_sched_layers_set - Set tx_scheduling_layers parameter 625109eb291SLukasz Czapnik * @devlink: pointer to the devlink instance 626109eb291SLukasz Czapnik * @id: the parameter ID to set 627109eb291SLukasz Czapnik * @ctx: context to get the parameter value 628109eb291SLukasz Czapnik * @extack: netlink extended ACK structure 629109eb291SLukasz Czapnik * 630109eb291SLukasz Czapnik * Return: zero on success and negative value on failure. 631109eb291SLukasz Czapnik */ 632109eb291SLukasz Czapnik static int ice_devlink_tx_sched_layers_set(struct devlink *devlink, u32 id, 633109eb291SLukasz Czapnik struct devlink_param_gset_ctx *ctx, 634109eb291SLukasz Czapnik struct netlink_ext_ack *extack) 635109eb291SLukasz Czapnik { 636109eb291SLukasz Czapnik struct ice_pf *pf = devlink_priv(devlink); 637109eb291SLukasz Czapnik int err; 638109eb291SLukasz Czapnik 639109eb291SLukasz Czapnik err = ice_update_tx_topo_user_sel(pf, ctx->val.vu8); 640109eb291SLukasz Czapnik if (err) 641109eb291SLukasz Czapnik return err; 642109eb291SLukasz Czapnik 643109eb291SLukasz Czapnik NL_SET_ERR_MSG_MOD(extack, 644109eb291SLukasz Czapnik "Tx scheduling layers have been changed on this device. You must do the PCI slot powercycle for the change to take effect."); 645109eb291SLukasz Czapnik 646109eb291SLukasz Czapnik return 0; 647109eb291SLukasz Czapnik } 648109eb291SLukasz Czapnik 649109eb291SLukasz Czapnik /** 650109eb291SLukasz Czapnik * ice_devlink_tx_sched_layers_validate - Validate passed tx_scheduling_layers 651109eb291SLukasz Czapnik * parameter value 652109eb291SLukasz Czapnik * @devlink: unused pointer to devlink instance 653109eb291SLukasz Czapnik * @id: the parameter ID to validate 654109eb291SLukasz Czapnik * @val: value to validate 655109eb291SLukasz Czapnik * @extack: netlink extended ACK structure 656109eb291SLukasz Czapnik * 657109eb291SLukasz Czapnik * Supported values are: 658109eb291SLukasz Czapnik * - 5 - five layers Tx Scheduler Topology Tree 659109eb291SLukasz Czapnik * - 9 - nine layers Tx Scheduler Topology Tree 660109eb291SLukasz Czapnik * 661109eb291SLukasz Czapnik * Return: zero when passed parameter value is supported. Negative value on 662109eb291SLukasz Czapnik * error. 663109eb291SLukasz Czapnik */ 664109eb291SLukasz Czapnik static int ice_devlink_tx_sched_layers_validate(struct devlink *devlink, u32 id, 665109eb291SLukasz Czapnik union devlink_param_value val, 666109eb291SLukasz Czapnik struct netlink_ext_ack *extack) 667109eb291SLukasz Czapnik { 668109eb291SLukasz Czapnik if (val.vu8 != ICE_SCHED_5_LAYERS && val.vu8 != ICE_SCHED_9_LAYERS) { 669109eb291SLukasz Czapnik NL_SET_ERR_MSG_MOD(extack, 670109eb291SLukasz Czapnik "Wrong number of tx scheduler layers provided."); 671109eb291SLukasz Czapnik return -EINVAL; 672109eb291SLukasz Czapnik } 673109eb291SLukasz Czapnik 674109eb291SLukasz Czapnik return 0; 675109eb291SLukasz Czapnik } 676109eb291SLukasz Czapnik 677109eb291SLukasz Czapnik /** 6780545cc86SMichal Swiatkowski * ice_tear_down_devlink_rate_tree - removes devlink-rate exported tree 6790545cc86SMichal Swiatkowski * @pf: pf struct 6800545cc86SMichal Swiatkowski * 6810545cc86SMichal Swiatkowski * This function tears down tree exported during VF's creation. 6820545cc86SMichal Swiatkowski */ 6830545cc86SMichal Swiatkowski void ice_tear_down_devlink_rate_tree(struct ice_pf *pf) 6840545cc86SMichal Swiatkowski { 6850545cc86SMichal Swiatkowski struct devlink *devlink; 6860545cc86SMichal Swiatkowski struct ice_vf *vf; 6870545cc86SMichal Swiatkowski unsigned int bkt; 6880545cc86SMichal Swiatkowski 6890545cc86SMichal Swiatkowski devlink = priv_to_devlink(pf); 6900545cc86SMichal Swiatkowski 6910545cc86SMichal Swiatkowski devl_lock(devlink); 6920545cc86SMichal Swiatkowski mutex_lock(&pf->vfs.table_lock); 6930545cc86SMichal Swiatkowski ice_for_each_vf(pf, bkt, vf) { 6940545cc86SMichal Swiatkowski if (vf->devlink_port.devlink_rate) 6950545cc86SMichal Swiatkowski devl_rate_leaf_destroy(&vf->devlink_port); 6960545cc86SMichal Swiatkowski } 6970545cc86SMichal Swiatkowski mutex_unlock(&pf->vfs.table_lock); 6980545cc86SMichal Swiatkowski 6990545cc86SMichal Swiatkowski devl_rate_nodes_destroy(devlink); 7000545cc86SMichal Swiatkowski devl_unlock(devlink); 7010545cc86SMichal Swiatkowski } 7020545cc86SMichal Swiatkowski 7030545cc86SMichal Swiatkowski /** 7040545cc86SMichal Swiatkowski * ice_enable_custom_tx - try to enable custom Tx feature 7050545cc86SMichal Swiatkowski * @pf: pf struct 7060545cc86SMichal Swiatkowski * 7070545cc86SMichal Swiatkowski * This function tries to enable custom Tx feature, 7080545cc86SMichal Swiatkowski * it's not possible to enable it, if DCB or ADQ is active. 7090545cc86SMichal Swiatkowski */ 7100545cc86SMichal Swiatkowski static bool ice_enable_custom_tx(struct ice_pf *pf) 7110545cc86SMichal Swiatkowski { 7120545cc86SMichal Swiatkowski struct ice_port_info *pi = ice_get_main_vsi(pf)->port_info; 7130545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 7140545cc86SMichal Swiatkowski 7150545cc86SMichal Swiatkowski if (pi->is_custom_tx_enabled) 7160545cc86SMichal Swiatkowski /* already enabled, return true */ 7170545cc86SMichal Swiatkowski return true; 7180545cc86SMichal Swiatkowski 7190545cc86SMichal Swiatkowski if (ice_is_adq_active(pf)) { 7200545cc86SMichal Swiatkowski dev_err(dev, "ADQ active, can't modify Tx scheduler tree\n"); 7210545cc86SMichal Swiatkowski return false; 7220545cc86SMichal Swiatkowski } 7230545cc86SMichal Swiatkowski 7240545cc86SMichal Swiatkowski if (ice_is_dcb_active(pf)) { 7250545cc86SMichal Swiatkowski dev_err(dev, "DCB active, can't modify Tx scheduler tree\n"); 7260545cc86SMichal Swiatkowski return false; 7270545cc86SMichal Swiatkowski } 7280545cc86SMichal Swiatkowski 7290545cc86SMichal Swiatkowski pi->is_custom_tx_enabled = true; 7300545cc86SMichal Swiatkowski 7310545cc86SMichal Swiatkowski return true; 7320545cc86SMichal Swiatkowski } 7330545cc86SMichal Swiatkowski 7340545cc86SMichal Swiatkowski /** 7350545cc86SMichal Swiatkowski * ice_traverse_tx_tree - traverse Tx scheduler tree 7360545cc86SMichal Swiatkowski * @devlink: devlink struct 7370545cc86SMichal Swiatkowski * @node: current node, used for recursion 7380545cc86SMichal Swiatkowski * @tc_node: tc_node struct, that is treated as a root 7390545cc86SMichal Swiatkowski * @pf: pf struct 7400545cc86SMichal Swiatkowski * 7410545cc86SMichal Swiatkowski * This function traverses Tx scheduler tree and exports 7420545cc86SMichal Swiatkowski * entire structure to the devlink-rate. 7430545cc86SMichal Swiatkowski */ 7440545cc86SMichal Swiatkowski static void ice_traverse_tx_tree(struct devlink *devlink, struct ice_sched_node *node, 7450545cc86SMichal Swiatkowski struct ice_sched_node *tc_node, struct ice_pf *pf) 7460545cc86SMichal Swiatkowski { 7470545cc86SMichal Swiatkowski struct devlink_rate *rate_node = NULL; 7480545cc86SMichal Swiatkowski struct ice_vf *vf; 7490545cc86SMichal Swiatkowski int i; 7500545cc86SMichal Swiatkowski 7510545cc86SMichal Swiatkowski if (node->rate_node) 7520545cc86SMichal Swiatkowski /* already added, skip to the next */ 7530545cc86SMichal Swiatkowski goto traverse_children; 7540545cc86SMichal Swiatkowski 7550545cc86SMichal Swiatkowski if (node->parent == tc_node) { 7560545cc86SMichal Swiatkowski /* create root node */ 7570545cc86SMichal Swiatkowski rate_node = devl_rate_node_create(devlink, node, node->name, NULL); 7580545cc86SMichal Swiatkowski } else if (node->vsi_handle && 7590545cc86SMichal Swiatkowski pf->vsi[node->vsi_handle]->vf) { 7600545cc86SMichal Swiatkowski vf = pf->vsi[node->vsi_handle]->vf; 7610545cc86SMichal Swiatkowski if (!vf->devlink_port.devlink_rate) 7620545cc86SMichal Swiatkowski /* leaf nodes doesn't have children 7630545cc86SMichal Swiatkowski * so we don't set rate_node 7640545cc86SMichal Swiatkowski */ 7650545cc86SMichal Swiatkowski devl_rate_leaf_create(&vf->devlink_port, node, 7660545cc86SMichal Swiatkowski node->parent->rate_node); 7670545cc86SMichal Swiatkowski } else if (node->info.data.elem_type != ICE_AQC_ELEM_TYPE_LEAF && 7680545cc86SMichal Swiatkowski node->parent->rate_node) { 7690545cc86SMichal Swiatkowski rate_node = devl_rate_node_create(devlink, node, node->name, 7700545cc86SMichal Swiatkowski node->parent->rate_node); 7710545cc86SMichal Swiatkowski } 7720545cc86SMichal Swiatkowski 7730545cc86SMichal Swiatkowski if (rate_node && !IS_ERR(rate_node)) 7740545cc86SMichal Swiatkowski node->rate_node = rate_node; 7750545cc86SMichal Swiatkowski 7760545cc86SMichal Swiatkowski traverse_children: 7770545cc86SMichal Swiatkowski for (i = 0; i < node->num_children; i++) 7780545cc86SMichal Swiatkowski ice_traverse_tx_tree(devlink, node->children[i], tc_node, pf); 7790545cc86SMichal Swiatkowski } 7800545cc86SMichal Swiatkowski 7810545cc86SMichal Swiatkowski /** 7820545cc86SMichal Swiatkowski * ice_devlink_rate_init_tx_topology - export Tx scheduler tree to devlink rate 7830545cc86SMichal Swiatkowski * @devlink: devlink struct 7840545cc86SMichal Swiatkowski * @vsi: main vsi struct 7850545cc86SMichal Swiatkowski * 7860545cc86SMichal Swiatkowski * This function finds a root node, then calls ice_traverse_tx tree, which 7870545cc86SMichal Swiatkowski * traverses the tree and exports it's contents to devlink rate. 7880545cc86SMichal Swiatkowski */ 7890545cc86SMichal Swiatkowski int ice_devlink_rate_init_tx_topology(struct devlink *devlink, struct ice_vsi *vsi) 7900545cc86SMichal Swiatkowski { 7910545cc86SMichal Swiatkowski struct ice_port_info *pi = vsi->port_info; 7920545cc86SMichal Swiatkowski struct ice_sched_node *tc_node; 7930545cc86SMichal Swiatkowski struct ice_pf *pf = vsi->back; 7940545cc86SMichal Swiatkowski int i; 7950545cc86SMichal Swiatkowski 7960545cc86SMichal Swiatkowski tc_node = pi->root->children[0]; 7970545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 7980545cc86SMichal Swiatkowski for (i = 0; i < tc_node->num_children; i++) 7990545cc86SMichal Swiatkowski ice_traverse_tx_tree(devlink, tc_node->children[i], tc_node, pf); 8000545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 8010545cc86SMichal Swiatkowski 8020545cc86SMichal Swiatkowski return 0; 8030545cc86SMichal Swiatkowski } 8040545cc86SMichal Swiatkowski 8050545cc86SMichal Swiatkowski static void ice_clear_rate_nodes(struct ice_sched_node *node) 8060545cc86SMichal Swiatkowski { 8070545cc86SMichal Swiatkowski node->rate_node = NULL; 8080545cc86SMichal Swiatkowski 8090545cc86SMichal Swiatkowski for (int i = 0; i < node->num_children; i++) 8100545cc86SMichal Swiatkowski ice_clear_rate_nodes(node->children[i]); 8110545cc86SMichal Swiatkowski } 8120545cc86SMichal Swiatkowski 8130545cc86SMichal Swiatkowski /** 8140545cc86SMichal Swiatkowski * ice_devlink_rate_clear_tx_topology - clear node->rate_node 8150545cc86SMichal Swiatkowski * @vsi: main vsi struct 8160545cc86SMichal Swiatkowski * 8170545cc86SMichal Swiatkowski * Clear rate_node to cleanup creation of Tx topology. 8180545cc86SMichal Swiatkowski * 8190545cc86SMichal Swiatkowski */ 8200545cc86SMichal Swiatkowski void ice_devlink_rate_clear_tx_topology(struct ice_vsi *vsi) 8210545cc86SMichal Swiatkowski { 8220545cc86SMichal Swiatkowski struct ice_port_info *pi = vsi->port_info; 8230545cc86SMichal Swiatkowski 8240545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 8250545cc86SMichal Swiatkowski ice_clear_rate_nodes(pi->root->children[0]); 8260545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 8270545cc86SMichal Swiatkowski } 8280545cc86SMichal Swiatkowski 8290545cc86SMichal Swiatkowski /** 8300545cc86SMichal Swiatkowski * ice_set_object_tx_share - sets node scheduling parameter 8310545cc86SMichal Swiatkowski * @pi: devlink struct instance 8320545cc86SMichal Swiatkowski * @node: node struct instance 8330545cc86SMichal Swiatkowski * @bw: bandwidth in bytes per second 8340545cc86SMichal Swiatkowski * @extack: extended netdev ack structure 8350545cc86SMichal Swiatkowski * 8360545cc86SMichal Swiatkowski * This function sets ICE_MIN_BW scheduling BW limit. 8370545cc86SMichal Swiatkowski */ 8380545cc86SMichal Swiatkowski static int ice_set_object_tx_share(struct ice_port_info *pi, struct ice_sched_node *node, 8390545cc86SMichal Swiatkowski u64 bw, struct netlink_ext_ack *extack) 8400545cc86SMichal Swiatkowski { 8410545cc86SMichal Swiatkowski int status; 8420545cc86SMichal Swiatkowski 8430545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 8440545cc86SMichal Swiatkowski /* converts bytes per second to kilo bits per second */ 8450545cc86SMichal Swiatkowski node->tx_share = div_u64(bw, 125); 8460545cc86SMichal Swiatkowski status = ice_sched_set_node_bw_lmt(pi, node, ICE_MIN_BW, node->tx_share); 8470545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 8480545cc86SMichal Swiatkowski 8490545cc86SMichal Swiatkowski if (status) 8500545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Can't set scheduling node tx_share"); 8510545cc86SMichal Swiatkowski 8520545cc86SMichal Swiatkowski return status; 8530545cc86SMichal Swiatkowski } 8540545cc86SMichal Swiatkowski 8550545cc86SMichal Swiatkowski /** 8560545cc86SMichal Swiatkowski * ice_set_object_tx_max - sets node scheduling parameter 8570545cc86SMichal Swiatkowski * @pi: devlink struct instance 8580545cc86SMichal Swiatkowski * @node: node struct instance 8590545cc86SMichal Swiatkowski * @bw: bandwidth in bytes per second 8600545cc86SMichal Swiatkowski * @extack: extended netdev ack structure 8610545cc86SMichal Swiatkowski * 8620545cc86SMichal Swiatkowski * This function sets ICE_MAX_BW scheduling BW limit. 8630545cc86SMichal Swiatkowski */ 8640545cc86SMichal Swiatkowski static int ice_set_object_tx_max(struct ice_port_info *pi, struct ice_sched_node *node, 8650545cc86SMichal Swiatkowski u64 bw, struct netlink_ext_ack *extack) 8660545cc86SMichal Swiatkowski { 8670545cc86SMichal Swiatkowski int status; 8680545cc86SMichal Swiatkowski 8690545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 8700545cc86SMichal Swiatkowski /* converts bytes per second value to kilo bits per second */ 8710545cc86SMichal Swiatkowski node->tx_max = div_u64(bw, 125); 8720545cc86SMichal Swiatkowski status = ice_sched_set_node_bw_lmt(pi, node, ICE_MAX_BW, node->tx_max); 8730545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 8740545cc86SMichal Swiatkowski 8750545cc86SMichal Swiatkowski if (status) 8760545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Can't set scheduling node tx_max"); 8770545cc86SMichal Swiatkowski 8780545cc86SMichal Swiatkowski return status; 8790545cc86SMichal Swiatkowski } 8800545cc86SMichal Swiatkowski 8810545cc86SMichal Swiatkowski /** 8820545cc86SMichal Swiatkowski * ice_set_object_tx_priority - sets node scheduling parameter 8830545cc86SMichal Swiatkowski * @pi: devlink struct instance 8840545cc86SMichal Swiatkowski * @node: node struct instance 8850545cc86SMichal Swiatkowski * @priority: value representing priority for strict priority arbitration 8860545cc86SMichal Swiatkowski * @extack: extended netdev ack structure 8870545cc86SMichal Swiatkowski * 8880545cc86SMichal Swiatkowski * This function sets priority of node among siblings. 8890545cc86SMichal Swiatkowski */ 8900545cc86SMichal Swiatkowski static int ice_set_object_tx_priority(struct ice_port_info *pi, struct ice_sched_node *node, 8910545cc86SMichal Swiatkowski u32 priority, struct netlink_ext_ack *extack) 8920545cc86SMichal Swiatkowski { 8930545cc86SMichal Swiatkowski int status; 8940545cc86SMichal Swiatkowski 8950545cc86SMichal Swiatkowski if (priority >= 8) { 8960545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Priority should be less than 8"); 8970545cc86SMichal Swiatkowski return -EINVAL; 8980545cc86SMichal Swiatkowski } 8990545cc86SMichal Swiatkowski 9000545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 9010545cc86SMichal Swiatkowski node->tx_priority = priority; 9020545cc86SMichal Swiatkowski status = ice_sched_set_node_priority(pi, node, node->tx_priority); 9030545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 9040545cc86SMichal Swiatkowski 9050545cc86SMichal Swiatkowski if (status) 9060545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Can't set scheduling node tx_priority"); 9070545cc86SMichal Swiatkowski 9080545cc86SMichal Swiatkowski return status; 9090545cc86SMichal Swiatkowski } 9100545cc86SMichal Swiatkowski 9110545cc86SMichal Swiatkowski /** 9120545cc86SMichal Swiatkowski * ice_set_object_tx_weight - sets node scheduling parameter 9130545cc86SMichal Swiatkowski * @pi: devlink struct instance 9140545cc86SMichal Swiatkowski * @node: node struct instance 9150545cc86SMichal Swiatkowski * @weight: value represeting relative weight for WFQ arbitration 9160545cc86SMichal Swiatkowski * @extack: extended netdev ack structure 9170545cc86SMichal Swiatkowski * 9180545cc86SMichal Swiatkowski * This function sets node weight for WFQ algorithm. 9190545cc86SMichal Swiatkowski */ 9200545cc86SMichal Swiatkowski static int ice_set_object_tx_weight(struct ice_port_info *pi, struct ice_sched_node *node, 9210545cc86SMichal Swiatkowski u32 weight, struct netlink_ext_ack *extack) 9220545cc86SMichal Swiatkowski { 9230545cc86SMichal Swiatkowski int status; 9240545cc86SMichal Swiatkowski 9250545cc86SMichal Swiatkowski if (weight > 200 || weight < 1) { 9260545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Weight must be between 1 and 200"); 9270545cc86SMichal Swiatkowski return -EINVAL; 9280545cc86SMichal Swiatkowski } 9290545cc86SMichal Swiatkowski 9300545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 9310545cc86SMichal Swiatkowski node->tx_weight = weight; 9320545cc86SMichal Swiatkowski status = ice_sched_set_node_weight(pi, node, node->tx_weight); 9330545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 9340545cc86SMichal Swiatkowski 9350545cc86SMichal Swiatkowski if (status) 9360545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Can't set scheduling node tx_weight"); 9370545cc86SMichal Swiatkowski 9380545cc86SMichal Swiatkowski return status; 9390545cc86SMichal Swiatkowski } 9400545cc86SMichal Swiatkowski 9410545cc86SMichal Swiatkowski /** 9420545cc86SMichal Swiatkowski * ice_get_pi_from_dev_rate - get port info from devlink_rate 9430545cc86SMichal Swiatkowski * @rate_node: devlink struct instance 9440545cc86SMichal Swiatkowski * 9450545cc86SMichal Swiatkowski * This function returns corresponding port_info struct of devlink_rate 9460545cc86SMichal Swiatkowski */ 9470545cc86SMichal Swiatkowski static struct ice_port_info *ice_get_pi_from_dev_rate(struct devlink_rate *rate_node) 9480545cc86SMichal Swiatkowski { 9490545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(rate_node->devlink); 9500545cc86SMichal Swiatkowski 9510545cc86SMichal Swiatkowski return ice_get_main_vsi(pf)->port_info; 9520545cc86SMichal Swiatkowski } 9530545cc86SMichal Swiatkowski 9540545cc86SMichal Swiatkowski static int ice_devlink_rate_node_new(struct devlink_rate *rate_node, void **priv, 9550545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 9560545cc86SMichal Swiatkowski { 9570545cc86SMichal Swiatkowski struct ice_sched_node *node; 9580545cc86SMichal Swiatkowski struct ice_port_info *pi; 9590545cc86SMichal Swiatkowski 9600545cc86SMichal Swiatkowski pi = ice_get_pi_from_dev_rate(rate_node); 9610545cc86SMichal Swiatkowski 9620545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink))) 9630545cc86SMichal Swiatkowski return -EBUSY; 9640545cc86SMichal Swiatkowski 9650545cc86SMichal Swiatkowski /* preallocate memory for ice_sched_node */ 9660545cc86SMichal Swiatkowski node = devm_kzalloc(ice_hw_to_dev(pi->hw), sizeof(*node), GFP_KERNEL); 9670545cc86SMichal Swiatkowski *priv = node; 9680545cc86SMichal Swiatkowski 9690545cc86SMichal Swiatkowski return 0; 9700545cc86SMichal Swiatkowski } 9710545cc86SMichal Swiatkowski 9720545cc86SMichal Swiatkowski static int ice_devlink_rate_node_del(struct devlink_rate *rate_node, void *priv, 9730545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 9740545cc86SMichal Swiatkowski { 9750545cc86SMichal Swiatkowski struct ice_sched_node *node, *tc_node; 9760545cc86SMichal Swiatkowski struct ice_port_info *pi; 9770545cc86SMichal Swiatkowski 9780545cc86SMichal Swiatkowski pi = ice_get_pi_from_dev_rate(rate_node); 9790545cc86SMichal Swiatkowski tc_node = pi->root->children[0]; 9800545cc86SMichal Swiatkowski node = priv; 9810545cc86SMichal Swiatkowski 9820545cc86SMichal Swiatkowski if (!rate_node->parent || !node || tc_node == node || !extack) 9830545cc86SMichal Swiatkowski return 0; 9840545cc86SMichal Swiatkowski 9850545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink))) 9860545cc86SMichal Swiatkowski return -EBUSY; 9870545cc86SMichal Swiatkowski 9880545cc86SMichal Swiatkowski /* can't allow to delete a node with children */ 9890545cc86SMichal Swiatkowski if (node->num_children) 9900545cc86SMichal Swiatkowski return -EINVAL; 9910545cc86SMichal Swiatkowski 9920545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 9930545cc86SMichal Swiatkowski ice_free_sched_node(pi, node); 9940545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 9950545cc86SMichal Swiatkowski 9960545cc86SMichal Swiatkowski return 0; 9970545cc86SMichal Swiatkowski } 9980545cc86SMichal Swiatkowski 9990545cc86SMichal Swiatkowski static int ice_devlink_rate_leaf_tx_max_set(struct devlink_rate *rate_leaf, void *priv, 10000545cc86SMichal Swiatkowski u64 tx_max, struct netlink_ext_ack *extack) 10010545cc86SMichal Swiatkowski { 10020545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 10030545cc86SMichal Swiatkowski 10040545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_leaf->devlink))) 10050545cc86SMichal Swiatkowski return -EBUSY; 10060545cc86SMichal Swiatkowski 10070545cc86SMichal Swiatkowski if (!node) 10080545cc86SMichal Swiatkowski return 0; 10090545cc86SMichal Swiatkowski 10100545cc86SMichal Swiatkowski return ice_set_object_tx_max(ice_get_pi_from_dev_rate(rate_leaf), 10110545cc86SMichal Swiatkowski node, tx_max, extack); 10120545cc86SMichal Swiatkowski } 10130545cc86SMichal Swiatkowski 10140545cc86SMichal Swiatkowski static int ice_devlink_rate_leaf_tx_share_set(struct devlink_rate *rate_leaf, void *priv, 10150545cc86SMichal Swiatkowski u64 tx_share, struct netlink_ext_ack *extack) 10160545cc86SMichal Swiatkowski { 10170545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 10180545cc86SMichal Swiatkowski 10190545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_leaf->devlink))) 10200545cc86SMichal Swiatkowski return -EBUSY; 10210545cc86SMichal Swiatkowski 10220545cc86SMichal Swiatkowski if (!node) 10230545cc86SMichal Swiatkowski return 0; 10240545cc86SMichal Swiatkowski 10250545cc86SMichal Swiatkowski return ice_set_object_tx_share(ice_get_pi_from_dev_rate(rate_leaf), node, 10260545cc86SMichal Swiatkowski tx_share, extack); 10270545cc86SMichal Swiatkowski } 10280545cc86SMichal Swiatkowski 10290545cc86SMichal Swiatkowski static int ice_devlink_rate_leaf_tx_priority_set(struct devlink_rate *rate_leaf, void *priv, 10300545cc86SMichal Swiatkowski u32 tx_priority, struct netlink_ext_ack *extack) 10310545cc86SMichal Swiatkowski { 10320545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 10330545cc86SMichal Swiatkowski 10340545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_leaf->devlink))) 10350545cc86SMichal Swiatkowski return -EBUSY; 10360545cc86SMichal Swiatkowski 10370545cc86SMichal Swiatkowski if (!node) 10380545cc86SMichal Swiatkowski return 0; 10390545cc86SMichal Swiatkowski 10400545cc86SMichal Swiatkowski return ice_set_object_tx_priority(ice_get_pi_from_dev_rate(rate_leaf), node, 10410545cc86SMichal Swiatkowski tx_priority, extack); 10420545cc86SMichal Swiatkowski } 10430545cc86SMichal Swiatkowski 10440545cc86SMichal Swiatkowski static int ice_devlink_rate_leaf_tx_weight_set(struct devlink_rate *rate_leaf, void *priv, 10450545cc86SMichal Swiatkowski u32 tx_weight, struct netlink_ext_ack *extack) 10460545cc86SMichal Swiatkowski { 10470545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 10480545cc86SMichal Swiatkowski 10490545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_leaf->devlink))) 10500545cc86SMichal Swiatkowski return -EBUSY; 10510545cc86SMichal Swiatkowski 10520545cc86SMichal Swiatkowski if (!node) 10530545cc86SMichal Swiatkowski return 0; 10540545cc86SMichal Swiatkowski 10550545cc86SMichal Swiatkowski return ice_set_object_tx_weight(ice_get_pi_from_dev_rate(rate_leaf), node, 10560545cc86SMichal Swiatkowski tx_weight, extack); 10570545cc86SMichal Swiatkowski } 10580545cc86SMichal Swiatkowski 10590545cc86SMichal Swiatkowski static int ice_devlink_rate_node_tx_max_set(struct devlink_rate *rate_node, void *priv, 10600545cc86SMichal Swiatkowski u64 tx_max, struct netlink_ext_ack *extack) 10610545cc86SMichal Swiatkowski { 10620545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 10630545cc86SMichal Swiatkowski 10640545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink))) 10650545cc86SMichal Swiatkowski return -EBUSY; 10660545cc86SMichal Swiatkowski 10670545cc86SMichal Swiatkowski if (!node) 10680545cc86SMichal Swiatkowski return 0; 10690545cc86SMichal Swiatkowski 10700545cc86SMichal Swiatkowski return ice_set_object_tx_max(ice_get_pi_from_dev_rate(rate_node), 10710545cc86SMichal Swiatkowski node, tx_max, extack); 10720545cc86SMichal Swiatkowski } 10730545cc86SMichal Swiatkowski 10740545cc86SMichal Swiatkowski static int ice_devlink_rate_node_tx_share_set(struct devlink_rate *rate_node, void *priv, 10750545cc86SMichal Swiatkowski u64 tx_share, struct netlink_ext_ack *extack) 10760545cc86SMichal Swiatkowski { 10770545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 10780545cc86SMichal Swiatkowski 10790545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink))) 10800545cc86SMichal Swiatkowski return -EBUSY; 10810545cc86SMichal Swiatkowski 10820545cc86SMichal Swiatkowski if (!node) 10830545cc86SMichal Swiatkowski return 0; 10840545cc86SMichal Swiatkowski 10850545cc86SMichal Swiatkowski return ice_set_object_tx_share(ice_get_pi_from_dev_rate(rate_node), 10860545cc86SMichal Swiatkowski node, tx_share, extack); 10870545cc86SMichal Swiatkowski } 10880545cc86SMichal Swiatkowski 10890545cc86SMichal Swiatkowski static int ice_devlink_rate_node_tx_priority_set(struct devlink_rate *rate_node, void *priv, 10900545cc86SMichal Swiatkowski u32 tx_priority, struct netlink_ext_ack *extack) 10910545cc86SMichal Swiatkowski { 10920545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 10930545cc86SMichal Swiatkowski 10940545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink))) 10950545cc86SMichal Swiatkowski return -EBUSY; 10960545cc86SMichal Swiatkowski 10970545cc86SMichal Swiatkowski if (!node) 10980545cc86SMichal Swiatkowski return 0; 10990545cc86SMichal Swiatkowski 11000545cc86SMichal Swiatkowski return ice_set_object_tx_priority(ice_get_pi_from_dev_rate(rate_node), 11010545cc86SMichal Swiatkowski node, tx_priority, extack); 11020545cc86SMichal Swiatkowski } 11030545cc86SMichal Swiatkowski 11040545cc86SMichal Swiatkowski static int ice_devlink_rate_node_tx_weight_set(struct devlink_rate *rate_node, void *priv, 11050545cc86SMichal Swiatkowski u32 tx_weight, struct netlink_ext_ack *extack) 11060545cc86SMichal Swiatkowski { 11070545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 11080545cc86SMichal Swiatkowski 11090545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink))) 11100545cc86SMichal Swiatkowski return -EBUSY; 11110545cc86SMichal Swiatkowski 11120545cc86SMichal Swiatkowski if (!node) 11130545cc86SMichal Swiatkowski return 0; 11140545cc86SMichal Swiatkowski 11150545cc86SMichal Swiatkowski return ice_set_object_tx_weight(ice_get_pi_from_dev_rate(rate_node), 11160545cc86SMichal Swiatkowski node, tx_weight, extack); 11170545cc86SMichal Swiatkowski } 11180545cc86SMichal Swiatkowski 11190545cc86SMichal Swiatkowski static int ice_devlink_set_parent(struct devlink_rate *devlink_rate, 11200545cc86SMichal Swiatkowski struct devlink_rate *parent, 11210545cc86SMichal Swiatkowski void *priv, void *parent_priv, 11220545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 11230545cc86SMichal Swiatkowski { 11240545cc86SMichal Swiatkowski struct ice_port_info *pi = ice_get_pi_from_dev_rate(devlink_rate); 11250545cc86SMichal Swiatkowski struct ice_sched_node *tc_node, *node, *parent_node; 11260545cc86SMichal Swiatkowski u16 num_nodes_added; 11270545cc86SMichal Swiatkowski u32 first_node_teid; 11280545cc86SMichal Swiatkowski u32 node_teid; 11290545cc86SMichal Swiatkowski int status; 11300545cc86SMichal Swiatkowski 11310545cc86SMichal Swiatkowski tc_node = pi->root->children[0]; 11320545cc86SMichal Swiatkowski node = priv; 11330545cc86SMichal Swiatkowski 11340545cc86SMichal Swiatkowski if (!extack) 11350545cc86SMichal Swiatkowski return 0; 11360545cc86SMichal Swiatkowski 11370545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(devlink_rate->devlink))) 11380545cc86SMichal Swiatkowski return -EBUSY; 11390545cc86SMichal Swiatkowski 11400545cc86SMichal Swiatkowski if (!parent) { 11410545cc86SMichal Swiatkowski if (!node || tc_node == node || node->num_children) 11420545cc86SMichal Swiatkowski return -EINVAL; 11430545cc86SMichal Swiatkowski 11440545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 11450545cc86SMichal Swiatkowski ice_free_sched_node(pi, node); 11460545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 11470545cc86SMichal Swiatkowski 11480545cc86SMichal Swiatkowski return 0; 11490545cc86SMichal Swiatkowski } 11500545cc86SMichal Swiatkowski 11510545cc86SMichal Swiatkowski parent_node = parent_priv; 11520545cc86SMichal Swiatkowski 11530545cc86SMichal Swiatkowski /* if the node doesn't exist, create it */ 11540545cc86SMichal Swiatkowski if (!node->parent) { 11550545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 11560545cc86SMichal Swiatkowski status = ice_sched_add_elems(pi, tc_node, parent_node, 11570545cc86SMichal Swiatkowski parent_node->tx_sched_layer + 1, 11580545cc86SMichal Swiatkowski 1, &num_nodes_added, &first_node_teid, 11590545cc86SMichal Swiatkowski &node); 11600545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 11610545cc86SMichal Swiatkowski 11620545cc86SMichal Swiatkowski if (status) { 11630545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Can't add a new node"); 11640545cc86SMichal Swiatkowski return status; 11650545cc86SMichal Swiatkowski } 11660545cc86SMichal Swiatkowski 11670545cc86SMichal Swiatkowski if (devlink_rate->tx_share) 11680545cc86SMichal Swiatkowski ice_set_object_tx_share(pi, node, devlink_rate->tx_share, extack); 11690545cc86SMichal Swiatkowski if (devlink_rate->tx_max) 11700545cc86SMichal Swiatkowski ice_set_object_tx_max(pi, node, devlink_rate->tx_max, extack); 11710545cc86SMichal Swiatkowski if (devlink_rate->tx_priority) 11720545cc86SMichal Swiatkowski ice_set_object_tx_priority(pi, node, devlink_rate->tx_priority, extack); 11730545cc86SMichal Swiatkowski if (devlink_rate->tx_weight) 11740545cc86SMichal Swiatkowski ice_set_object_tx_weight(pi, node, devlink_rate->tx_weight, extack); 11750545cc86SMichal Swiatkowski } else { 11760545cc86SMichal Swiatkowski node_teid = le32_to_cpu(node->info.node_teid); 11770545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 11780545cc86SMichal Swiatkowski status = ice_sched_move_nodes(pi, parent_node, 1, &node_teid); 11790545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 11800545cc86SMichal Swiatkowski 11810545cc86SMichal Swiatkowski if (status) 11820545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Can't move existing node to a new parent"); 11830545cc86SMichal Swiatkowski } 11840545cc86SMichal Swiatkowski 11850545cc86SMichal Swiatkowski return status; 11860545cc86SMichal Swiatkowski } 11870545cc86SMichal Swiatkowski 11880545cc86SMichal Swiatkowski /** 11890545cc86SMichal Swiatkowski * ice_devlink_reinit_up - do reinit of the given PF 11900545cc86SMichal Swiatkowski * @pf: pointer to the PF struct 11910545cc86SMichal Swiatkowski */ 11920545cc86SMichal Swiatkowski static int ice_devlink_reinit_up(struct ice_pf *pf) 11930545cc86SMichal Swiatkowski { 11940545cc86SMichal Swiatkowski struct ice_vsi *vsi = ice_get_main_vsi(pf); 11950545cc86SMichal Swiatkowski int err; 11960545cc86SMichal Swiatkowski 11970545cc86SMichal Swiatkowski err = ice_init_dev(pf); 11980545cc86SMichal Swiatkowski if (err) 11990545cc86SMichal Swiatkowski return err; 12000545cc86SMichal Swiatkowski 1201deea427fSMateusz Polchlopek vsi->flags = ICE_VSI_FLAG_INIT; 12020545cc86SMichal Swiatkowski 12030545cc86SMichal Swiatkowski rtnl_lock(); 1204deea427fSMateusz Polchlopek err = ice_vsi_cfg(vsi); 12050545cc86SMichal Swiatkowski rtnl_unlock(); 12060545cc86SMichal Swiatkowski if (err) 12070545cc86SMichal Swiatkowski goto err_vsi_cfg; 12080545cc86SMichal Swiatkowski 12090545cc86SMichal Swiatkowski /* No need to take devl_lock, it's already taken by devlink API */ 12100545cc86SMichal Swiatkowski err = ice_load(pf); 12110545cc86SMichal Swiatkowski if (err) 12120545cc86SMichal Swiatkowski goto err_load; 12130545cc86SMichal Swiatkowski 12140545cc86SMichal Swiatkowski return 0; 12150545cc86SMichal Swiatkowski 12160545cc86SMichal Swiatkowski err_load: 12170545cc86SMichal Swiatkowski rtnl_lock(); 12180545cc86SMichal Swiatkowski ice_vsi_decfg(vsi); 12190545cc86SMichal Swiatkowski rtnl_unlock(); 12200545cc86SMichal Swiatkowski err_vsi_cfg: 12210545cc86SMichal Swiatkowski ice_deinit_dev(pf); 12220545cc86SMichal Swiatkowski return err; 12230545cc86SMichal Swiatkowski } 12240545cc86SMichal Swiatkowski 12250545cc86SMichal Swiatkowski /** 12260545cc86SMichal Swiatkowski * ice_devlink_reload_up - do reload up after reinit 12270545cc86SMichal Swiatkowski * @devlink: pointer to the devlink instance reloading 12280545cc86SMichal Swiatkowski * @action: the action requested 12290545cc86SMichal Swiatkowski * @limit: limits imposed by userspace, such as not resetting 12300545cc86SMichal Swiatkowski * @actions_performed: on return, indicate what actions actually performed 12310545cc86SMichal Swiatkowski * @extack: netlink extended ACK structure 12320545cc86SMichal Swiatkowski */ 12330545cc86SMichal Swiatkowski static int 12340545cc86SMichal Swiatkowski ice_devlink_reload_up(struct devlink *devlink, 12350545cc86SMichal Swiatkowski enum devlink_reload_action action, 12360545cc86SMichal Swiatkowski enum devlink_reload_limit limit, 12370545cc86SMichal Swiatkowski u32 *actions_performed, 12380545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 12390545cc86SMichal Swiatkowski { 12400545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 12410545cc86SMichal Swiatkowski 12420545cc86SMichal Swiatkowski switch (action) { 12430545cc86SMichal Swiatkowski case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: 12440545cc86SMichal Swiatkowski *actions_performed = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT); 12450545cc86SMichal Swiatkowski return ice_devlink_reinit_up(pf); 12460545cc86SMichal Swiatkowski case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: 12470545cc86SMichal Swiatkowski *actions_performed = BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE); 12480545cc86SMichal Swiatkowski return ice_devlink_reload_empr_finish(pf, extack); 12490545cc86SMichal Swiatkowski default: 12500545cc86SMichal Swiatkowski WARN_ON(1); 12510545cc86SMichal Swiatkowski return -EOPNOTSUPP; 12520545cc86SMichal Swiatkowski } 12530545cc86SMichal Swiatkowski } 12540545cc86SMichal Swiatkowski 12550545cc86SMichal Swiatkowski static const struct devlink_ops ice_devlink_ops = { 12560545cc86SMichal Swiatkowski .supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK, 12570545cc86SMichal Swiatkowski .reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) | 12580545cc86SMichal Swiatkowski BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE), 12590545cc86SMichal Swiatkowski .reload_down = ice_devlink_reload_down, 12600545cc86SMichal Swiatkowski .reload_up = ice_devlink_reload_up, 12610545cc86SMichal Swiatkowski .eswitch_mode_get = ice_eswitch_mode_get, 12620545cc86SMichal Swiatkowski .eswitch_mode_set = ice_eswitch_mode_set, 12630545cc86SMichal Swiatkowski .info_get = ice_devlink_info_get, 12640545cc86SMichal Swiatkowski .flash_update = ice_devlink_flash_update, 12650545cc86SMichal Swiatkowski 12660545cc86SMichal Swiatkowski .rate_node_new = ice_devlink_rate_node_new, 12670545cc86SMichal Swiatkowski .rate_node_del = ice_devlink_rate_node_del, 12680545cc86SMichal Swiatkowski 12690545cc86SMichal Swiatkowski .rate_leaf_tx_max_set = ice_devlink_rate_leaf_tx_max_set, 12700545cc86SMichal Swiatkowski .rate_leaf_tx_share_set = ice_devlink_rate_leaf_tx_share_set, 12710545cc86SMichal Swiatkowski .rate_leaf_tx_priority_set = ice_devlink_rate_leaf_tx_priority_set, 12720545cc86SMichal Swiatkowski .rate_leaf_tx_weight_set = ice_devlink_rate_leaf_tx_weight_set, 12730545cc86SMichal Swiatkowski 12740545cc86SMichal Swiatkowski .rate_node_tx_max_set = ice_devlink_rate_node_tx_max_set, 12750545cc86SMichal Swiatkowski .rate_node_tx_share_set = ice_devlink_rate_node_tx_share_set, 12760545cc86SMichal Swiatkowski .rate_node_tx_priority_set = ice_devlink_rate_node_tx_priority_set, 12770545cc86SMichal Swiatkowski .rate_node_tx_weight_set = ice_devlink_rate_node_tx_weight_set, 12780545cc86SMichal Swiatkowski 12790545cc86SMichal Swiatkowski .rate_leaf_parent_set = ice_devlink_set_parent, 12800545cc86SMichal Swiatkowski .rate_node_parent_set = ice_devlink_set_parent, 1281*eda69d65SPiotr Raczynski 1282*eda69d65SPiotr Raczynski .port_new = ice_devlink_port_new, 12830545cc86SMichal Swiatkowski }; 12840545cc86SMichal Swiatkowski 12850545cc86SMichal Swiatkowski static int 12860545cc86SMichal Swiatkowski ice_devlink_enable_roce_get(struct devlink *devlink, u32 id, 12870545cc86SMichal Swiatkowski struct devlink_param_gset_ctx *ctx) 12880545cc86SMichal Swiatkowski { 12890545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 12900545cc86SMichal Swiatkowski 12910545cc86SMichal Swiatkowski ctx->val.vbool = pf->rdma_mode & IIDC_RDMA_PROTOCOL_ROCEV2 ? true : false; 12920545cc86SMichal Swiatkowski 12930545cc86SMichal Swiatkowski return 0; 12940545cc86SMichal Swiatkowski } 12950545cc86SMichal Swiatkowski 12965625ca56SMateusz Polchlopek static int ice_devlink_enable_roce_set(struct devlink *devlink, u32 id, 12975625ca56SMateusz Polchlopek struct devlink_param_gset_ctx *ctx, 12985625ca56SMateusz Polchlopek struct netlink_ext_ack *extack) 12990545cc86SMichal Swiatkowski { 13000545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 13010545cc86SMichal Swiatkowski bool roce_ena = ctx->val.vbool; 13020545cc86SMichal Swiatkowski int ret; 13030545cc86SMichal Swiatkowski 13040545cc86SMichal Swiatkowski if (!roce_ena) { 13050545cc86SMichal Swiatkowski ice_unplug_aux_dev(pf); 13060545cc86SMichal Swiatkowski pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_ROCEV2; 13070545cc86SMichal Swiatkowski return 0; 13080545cc86SMichal Swiatkowski } 13090545cc86SMichal Swiatkowski 13100545cc86SMichal Swiatkowski pf->rdma_mode |= IIDC_RDMA_PROTOCOL_ROCEV2; 13110545cc86SMichal Swiatkowski ret = ice_plug_aux_dev(pf); 13120545cc86SMichal Swiatkowski if (ret) 13130545cc86SMichal Swiatkowski pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_ROCEV2; 13140545cc86SMichal Swiatkowski 13150545cc86SMichal Swiatkowski return ret; 13160545cc86SMichal Swiatkowski } 13170545cc86SMichal Swiatkowski 13180545cc86SMichal Swiatkowski static int 13190545cc86SMichal Swiatkowski ice_devlink_enable_roce_validate(struct devlink *devlink, u32 id, 13200545cc86SMichal Swiatkowski union devlink_param_value val, 13210545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 13220545cc86SMichal Swiatkowski { 13230545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 13240545cc86SMichal Swiatkowski 13250545cc86SMichal Swiatkowski if (!test_bit(ICE_FLAG_RDMA_ENA, pf->flags)) 13260545cc86SMichal Swiatkowski return -EOPNOTSUPP; 13270545cc86SMichal Swiatkowski 13280545cc86SMichal Swiatkowski if (pf->rdma_mode & IIDC_RDMA_PROTOCOL_IWARP) { 13290545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "iWARP is currently enabled. This device cannot enable iWARP and RoCEv2 simultaneously"); 13300545cc86SMichal Swiatkowski return -EOPNOTSUPP; 13310545cc86SMichal Swiatkowski } 13320545cc86SMichal Swiatkowski 13330545cc86SMichal Swiatkowski return 0; 13340545cc86SMichal Swiatkowski } 13350545cc86SMichal Swiatkowski 13360545cc86SMichal Swiatkowski static int 13370545cc86SMichal Swiatkowski ice_devlink_enable_iw_get(struct devlink *devlink, u32 id, 13380545cc86SMichal Swiatkowski struct devlink_param_gset_ctx *ctx) 13390545cc86SMichal Swiatkowski { 13400545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 13410545cc86SMichal Swiatkowski 13420545cc86SMichal Swiatkowski ctx->val.vbool = pf->rdma_mode & IIDC_RDMA_PROTOCOL_IWARP; 13430545cc86SMichal Swiatkowski 13440545cc86SMichal Swiatkowski return 0; 13450545cc86SMichal Swiatkowski } 13460545cc86SMichal Swiatkowski 13475625ca56SMateusz Polchlopek static int ice_devlink_enable_iw_set(struct devlink *devlink, u32 id, 13485625ca56SMateusz Polchlopek struct devlink_param_gset_ctx *ctx, 13495625ca56SMateusz Polchlopek struct netlink_ext_ack *extack) 13500545cc86SMichal Swiatkowski { 13510545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 13520545cc86SMichal Swiatkowski bool iw_ena = ctx->val.vbool; 13530545cc86SMichal Swiatkowski int ret; 13540545cc86SMichal Swiatkowski 13550545cc86SMichal Swiatkowski if (!iw_ena) { 13560545cc86SMichal Swiatkowski ice_unplug_aux_dev(pf); 13570545cc86SMichal Swiatkowski pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_IWARP; 13580545cc86SMichal Swiatkowski return 0; 13590545cc86SMichal Swiatkowski } 13600545cc86SMichal Swiatkowski 13610545cc86SMichal Swiatkowski pf->rdma_mode |= IIDC_RDMA_PROTOCOL_IWARP; 13620545cc86SMichal Swiatkowski ret = ice_plug_aux_dev(pf); 13630545cc86SMichal Swiatkowski if (ret) 13640545cc86SMichal Swiatkowski pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_IWARP; 13650545cc86SMichal Swiatkowski 13660545cc86SMichal Swiatkowski return ret; 13670545cc86SMichal Swiatkowski } 13680545cc86SMichal Swiatkowski 13690545cc86SMichal Swiatkowski static int 13700545cc86SMichal Swiatkowski ice_devlink_enable_iw_validate(struct devlink *devlink, u32 id, 13710545cc86SMichal Swiatkowski union devlink_param_value val, 13720545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 13730545cc86SMichal Swiatkowski { 13740545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 13750545cc86SMichal Swiatkowski 13760545cc86SMichal Swiatkowski if (!test_bit(ICE_FLAG_RDMA_ENA, pf->flags)) 13770545cc86SMichal Swiatkowski return -EOPNOTSUPP; 13780545cc86SMichal Swiatkowski 13790545cc86SMichal Swiatkowski if (pf->rdma_mode & IIDC_RDMA_PROTOCOL_ROCEV2) { 13800545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "RoCEv2 is currently enabled. This device cannot enable iWARP and RoCEv2 simultaneously"); 13810545cc86SMichal Swiatkowski return -EOPNOTSUPP; 13820545cc86SMichal Swiatkowski } 13830545cc86SMichal Swiatkowski 13840545cc86SMichal Swiatkowski return 0; 13850545cc86SMichal Swiatkowski } 13860545cc86SMichal Swiatkowski 1387a59618b9SPawel Kaminski #define DEVLINK_LOCAL_FWD_DISABLED_STR "disabled" 1388a59618b9SPawel Kaminski #define DEVLINK_LOCAL_FWD_ENABLED_STR "enabled" 1389a59618b9SPawel Kaminski #define DEVLINK_LOCAL_FWD_PRIORITIZED_STR "prioritized" 1390a59618b9SPawel Kaminski 1391a59618b9SPawel Kaminski /** 1392a59618b9SPawel Kaminski * ice_devlink_local_fwd_mode_to_str - Get string for local_fwd mode. 1393a59618b9SPawel Kaminski * @mode: local forwarding for mode used in port_info struct. 1394a59618b9SPawel Kaminski * 1395a59618b9SPawel Kaminski * Return: Mode respective string or "Invalid". 1396a59618b9SPawel Kaminski */ 1397a59618b9SPawel Kaminski static const char * 1398a59618b9SPawel Kaminski ice_devlink_local_fwd_mode_to_str(enum ice_local_fwd_mode mode) 1399a59618b9SPawel Kaminski { 1400a59618b9SPawel Kaminski switch (mode) { 1401a59618b9SPawel Kaminski case ICE_LOCAL_FWD_MODE_ENABLED: 1402a59618b9SPawel Kaminski return DEVLINK_LOCAL_FWD_ENABLED_STR; 1403a59618b9SPawel Kaminski case ICE_LOCAL_FWD_MODE_PRIORITIZED: 1404a59618b9SPawel Kaminski return DEVLINK_LOCAL_FWD_PRIORITIZED_STR; 1405a59618b9SPawel Kaminski case ICE_LOCAL_FWD_MODE_DISABLED: 1406a59618b9SPawel Kaminski return DEVLINK_LOCAL_FWD_DISABLED_STR; 1407a59618b9SPawel Kaminski } 1408a59618b9SPawel Kaminski 1409a59618b9SPawel Kaminski return "Invalid"; 1410a59618b9SPawel Kaminski } 1411a59618b9SPawel Kaminski 1412a59618b9SPawel Kaminski /** 1413a59618b9SPawel Kaminski * ice_devlink_local_fwd_str_to_mode - Get local_fwd mode from string name. 1414a59618b9SPawel Kaminski * @mode_str: local forwarding mode string. 1415a59618b9SPawel Kaminski * 1416a59618b9SPawel Kaminski * Return: Mode value or negative number if invalid. 1417a59618b9SPawel Kaminski */ 1418a59618b9SPawel Kaminski static int ice_devlink_local_fwd_str_to_mode(const char *mode_str) 1419a59618b9SPawel Kaminski { 1420a59618b9SPawel Kaminski if (!strcmp(mode_str, DEVLINK_LOCAL_FWD_ENABLED_STR)) 1421a59618b9SPawel Kaminski return ICE_LOCAL_FWD_MODE_ENABLED; 1422a59618b9SPawel Kaminski else if (!strcmp(mode_str, DEVLINK_LOCAL_FWD_PRIORITIZED_STR)) 1423a59618b9SPawel Kaminski return ICE_LOCAL_FWD_MODE_PRIORITIZED; 1424a59618b9SPawel Kaminski else if (!strcmp(mode_str, DEVLINK_LOCAL_FWD_DISABLED_STR)) 1425a59618b9SPawel Kaminski return ICE_LOCAL_FWD_MODE_DISABLED; 1426a59618b9SPawel Kaminski 1427a59618b9SPawel Kaminski return -EINVAL; 1428a59618b9SPawel Kaminski } 1429a59618b9SPawel Kaminski 1430a59618b9SPawel Kaminski /** 1431a59618b9SPawel Kaminski * ice_devlink_local_fwd_get - Get local_fwd parameter. 1432a59618b9SPawel Kaminski * @devlink: Pointer to the devlink instance. 1433a59618b9SPawel Kaminski * @id: The parameter ID to set. 1434a59618b9SPawel Kaminski * @ctx: Context to store the parameter value. 1435a59618b9SPawel Kaminski * 1436a59618b9SPawel Kaminski * Return: Zero. 1437a59618b9SPawel Kaminski */ 1438a59618b9SPawel Kaminski static int ice_devlink_local_fwd_get(struct devlink *devlink, u32 id, 1439a59618b9SPawel Kaminski struct devlink_param_gset_ctx *ctx) 1440a59618b9SPawel Kaminski { 1441a59618b9SPawel Kaminski struct ice_pf *pf = devlink_priv(devlink); 1442a59618b9SPawel Kaminski struct ice_port_info *pi; 1443a59618b9SPawel Kaminski const char *mode_str; 1444a59618b9SPawel Kaminski 1445a59618b9SPawel Kaminski pi = pf->hw.port_info; 1446a59618b9SPawel Kaminski mode_str = ice_devlink_local_fwd_mode_to_str(pi->local_fwd_mode); 1447a59618b9SPawel Kaminski snprintf(ctx->val.vstr, sizeof(ctx->val.vstr), "%s", mode_str); 1448a59618b9SPawel Kaminski 1449a59618b9SPawel Kaminski return 0; 1450a59618b9SPawel Kaminski } 1451a59618b9SPawel Kaminski 1452a59618b9SPawel Kaminski /** 1453a59618b9SPawel Kaminski * ice_devlink_local_fwd_set - Set local_fwd parameter. 1454a59618b9SPawel Kaminski * @devlink: Pointer to the devlink instance. 1455a59618b9SPawel Kaminski * @id: The parameter ID to set. 1456a59618b9SPawel Kaminski * @ctx: Context to get the parameter value. 1457a59618b9SPawel Kaminski * @extack: Netlink extended ACK structure. 1458a59618b9SPawel Kaminski * 1459a59618b9SPawel Kaminski * Return: Zero. 1460a59618b9SPawel Kaminski */ 1461a59618b9SPawel Kaminski static int ice_devlink_local_fwd_set(struct devlink *devlink, u32 id, 1462a59618b9SPawel Kaminski struct devlink_param_gset_ctx *ctx, 1463a59618b9SPawel Kaminski struct netlink_ext_ack *extack) 1464a59618b9SPawel Kaminski { 1465a59618b9SPawel Kaminski int new_local_fwd_mode = ice_devlink_local_fwd_str_to_mode(ctx->val.vstr); 1466a59618b9SPawel Kaminski struct ice_pf *pf = devlink_priv(devlink); 1467a59618b9SPawel Kaminski struct device *dev = ice_pf_to_dev(pf); 1468a59618b9SPawel Kaminski struct ice_port_info *pi; 1469a59618b9SPawel Kaminski 1470a59618b9SPawel Kaminski pi = pf->hw.port_info; 1471a59618b9SPawel Kaminski if (pi->local_fwd_mode != new_local_fwd_mode) { 1472a59618b9SPawel Kaminski pi->local_fwd_mode = new_local_fwd_mode; 1473a59618b9SPawel Kaminski dev_info(dev, "Setting local_fwd to %s\n", ctx->val.vstr); 1474a59618b9SPawel Kaminski ice_schedule_reset(pf, ICE_RESET_CORER); 1475a59618b9SPawel Kaminski } 1476a59618b9SPawel Kaminski 1477a59618b9SPawel Kaminski return 0; 1478a59618b9SPawel Kaminski } 1479a59618b9SPawel Kaminski 1480a59618b9SPawel Kaminski /** 1481a59618b9SPawel Kaminski * ice_devlink_local_fwd_validate - Validate passed local_fwd parameter value. 1482a59618b9SPawel Kaminski * @devlink: Unused pointer to devlink instance. 1483a59618b9SPawel Kaminski * @id: The parameter ID to validate. 1484a59618b9SPawel Kaminski * @val: Value to validate. 1485a59618b9SPawel Kaminski * @extack: Netlink extended ACK structure. 1486a59618b9SPawel Kaminski * 1487a59618b9SPawel Kaminski * Supported values are: 1488a59618b9SPawel Kaminski * "enabled" - local_fwd is enabled, "disabled" - local_fwd is disabled 1489a59618b9SPawel Kaminski * "prioritized" - local_fwd traffic is prioritized in scheduling. 1490a59618b9SPawel Kaminski * 1491a59618b9SPawel Kaminski * Return: Zero when passed parameter value is supported. Negative value on 1492a59618b9SPawel Kaminski * error. 1493a59618b9SPawel Kaminski */ 1494a59618b9SPawel Kaminski static int ice_devlink_local_fwd_validate(struct devlink *devlink, u32 id, 1495a59618b9SPawel Kaminski union devlink_param_value val, 1496a59618b9SPawel Kaminski struct netlink_ext_ack *extack) 1497a59618b9SPawel Kaminski { 1498a59618b9SPawel Kaminski if (ice_devlink_local_fwd_str_to_mode(val.vstr) < 0) { 1499a59618b9SPawel Kaminski NL_SET_ERR_MSG_MOD(extack, "Error: Requested value is not supported."); 1500a59618b9SPawel Kaminski return -EINVAL; 1501a59618b9SPawel Kaminski } 1502a59618b9SPawel Kaminski 1503a59618b9SPawel Kaminski return 0; 1504a59618b9SPawel Kaminski } 1505a59618b9SPawel Kaminski 1506109eb291SLukasz Czapnik enum ice_param_id { 1507109eb291SLukasz Czapnik ICE_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX, 1508109eb291SLukasz Czapnik ICE_DEVLINK_PARAM_ID_TX_SCHED_LAYERS, 1509a59618b9SPawel Kaminski ICE_DEVLINK_PARAM_ID_LOCAL_FWD, 1510109eb291SLukasz Czapnik }; 1511109eb291SLukasz Czapnik 1512a51c9b1cSDave Ertman static const struct devlink_param ice_dvl_rdma_params[] = { 15130545cc86SMichal Swiatkowski DEVLINK_PARAM_GENERIC(ENABLE_ROCE, BIT(DEVLINK_PARAM_CMODE_RUNTIME), 15140545cc86SMichal Swiatkowski ice_devlink_enable_roce_get, 15150545cc86SMichal Swiatkowski ice_devlink_enable_roce_set, 15160545cc86SMichal Swiatkowski ice_devlink_enable_roce_validate), 15170545cc86SMichal Swiatkowski DEVLINK_PARAM_GENERIC(ENABLE_IWARP, BIT(DEVLINK_PARAM_CMODE_RUNTIME), 15180545cc86SMichal Swiatkowski ice_devlink_enable_iw_get, 15190545cc86SMichal Swiatkowski ice_devlink_enable_iw_set, 15200545cc86SMichal Swiatkowski ice_devlink_enable_iw_validate), 1521a51c9b1cSDave Ertman }; 1522a51c9b1cSDave Ertman 1523a51c9b1cSDave Ertman static const struct devlink_param ice_dvl_sched_params[] = { 1524109eb291SLukasz Czapnik DEVLINK_PARAM_DRIVER(ICE_DEVLINK_PARAM_ID_TX_SCHED_LAYERS, 1525109eb291SLukasz Czapnik "tx_scheduling_layers", 1526109eb291SLukasz Czapnik DEVLINK_PARAM_TYPE_U8, 1527109eb291SLukasz Czapnik BIT(DEVLINK_PARAM_CMODE_PERMANENT), 1528109eb291SLukasz Czapnik ice_devlink_tx_sched_layers_get, 1529109eb291SLukasz Czapnik ice_devlink_tx_sched_layers_set, 1530109eb291SLukasz Czapnik ice_devlink_tx_sched_layers_validate), 1531a59618b9SPawel Kaminski DEVLINK_PARAM_DRIVER(ICE_DEVLINK_PARAM_ID_LOCAL_FWD, 1532a59618b9SPawel Kaminski "local_forwarding", DEVLINK_PARAM_TYPE_STRING, 1533a59618b9SPawel Kaminski BIT(DEVLINK_PARAM_CMODE_RUNTIME), 1534a59618b9SPawel Kaminski ice_devlink_local_fwd_get, 1535a59618b9SPawel Kaminski ice_devlink_local_fwd_set, 1536a59618b9SPawel Kaminski ice_devlink_local_fwd_validate), 15370545cc86SMichal Swiatkowski }; 15380545cc86SMichal Swiatkowski 15390545cc86SMichal Swiatkowski static void ice_devlink_free(void *devlink_ptr) 15400545cc86SMichal Swiatkowski { 15410545cc86SMichal Swiatkowski devlink_free((struct devlink *)devlink_ptr); 15420545cc86SMichal Swiatkowski } 15430545cc86SMichal Swiatkowski 15440545cc86SMichal Swiatkowski /** 15450545cc86SMichal Swiatkowski * ice_allocate_pf - Allocate devlink and return PF structure pointer 15460545cc86SMichal Swiatkowski * @dev: the device to allocate for 15470545cc86SMichal Swiatkowski * 15480545cc86SMichal Swiatkowski * Allocate a devlink instance for this device and return the private area as 15490545cc86SMichal Swiatkowski * the PF structure. The devlink memory is kept track of through devres by 15500545cc86SMichal Swiatkowski * adding an action to remove it when unwinding. 15510545cc86SMichal Swiatkowski */ 15520545cc86SMichal Swiatkowski struct ice_pf *ice_allocate_pf(struct device *dev) 15530545cc86SMichal Swiatkowski { 15540545cc86SMichal Swiatkowski struct devlink *devlink; 15550545cc86SMichal Swiatkowski 15560545cc86SMichal Swiatkowski devlink = devlink_alloc(&ice_devlink_ops, sizeof(struct ice_pf), dev); 15570545cc86SMichal Swiatkowski if (!devlink) 15580545cc86SMichal Swiatkowski return NULL; 15590545cc86SMichal Swiatkowski 15600545cc86SMichal Swiatkowski /* Add an action to teardown the devlink when unwinding the driver */ 15610545cc86SMichal Swiatkowski if (devm_add_action_or_reset(dev, ice_devlink_free, devlink)) 15620545cc86SMichal Swiatkowski return NULL; 15630545cc86SMichal Swiatkowski 15640545cc86SMichal Swiatkowski return devlink_priv(devlink); 15650545cc86SMichal Swiatkowski } 15660545cc86SMichal Swiatkowski 15670545cc86SMichal Swiatkowski /** 15680545cc86SMichal Swiatkowski * ice_devlink_register - Register devlink interface for this PF 15690545cc86SMichal Swiatkowski * @pf: the PF to register the devlink for. 15700545cc86SMichal Swiatkowski * 15710545cc86SMichal Swiatkowski * Register the devlink instance associated with this physical function. 15720545cc86SMichal Swiatkowski * 15730545cc86SMichal Swiatkowski * Return: zero on success or an error code on failure. 15740545cc86SMichal Swiatkowski */ 15750545cc86SMichal Swiatkowski void ice_devlink_register(struct ice_pf *pf) 15760545cc86SMichal Swiatkowski { 15770545cc86SMichal Swiatkowski struct devlink *devlink = priv_to_devlink(pf); 15780545cc86SMichal Swiatkowski 1579118c6bdeSMichal Swiatkowski devl_register(devlink); 15800545cc86SMichal Swiatkowski } 15810545cc86SMichal Swiatkowski 15820545cc86SMichal Swiatkowski /** 15830545cc86SMichal Swiatkowski * ice_devlink_unregister - Unregister devlink resources for this PF. 15840545cc86SMichal Swiatkowski * @pf: the PF structure to cleanup 15850545cc86SMichal Swiatkowski * 15860545cc86SMichal Swiatkowski * Releases resources used by devlink and cleans up associated memory. 15870545cc86SMichal Swiatkowski */ 15880545cc86SMichal Swiatkowski void ice_devlink_unregister(struct ice_pf *pf) 15890545cc86SMichal Swiatkowski { 1590118c6bdeSMichal Swiatkowski devl_unregister(priv_to_devlink(pf)); 15910545cc86SMichal Swiatkowski } 15920545cc86SMichal Swiatkowski 15930545cc86SMichal Swiatkowski int ice_devlink_register_params(struct ice_pf *pf) 15940545cc86SMichal Swiatkowski { 15950545cc86SMichal Swiatkowski struct devlink *devlink = priv_to_devlink(pf); 1596109eb291SLukasz Czapnik struct ice_hw *hw = &pf->hw; 1597a51c9b1cSDave Ertman int status; 1598109eb291SLukasz Czapnik 1599a51c9b1cSDave Ertman status = devl_params_register(devlink, ice_dvl_rdma_params, 1600a51c9b1cSDave Ertman ARRAY_SIZE(ice_dvl_rdma_params)); 1601a51c9b1cSDave Ertman if (status) 1602a51c9b1cSDave Ertman return status; 1603109eb291SLukasz Czapnik 1604a51c9b1cSDave Ertman if (hw->func_caps.common_cap.tx_sched_topo_comp_mode_en) 1605a51c9b1cSDave Ertman status = devl_params_register(devlink, ice_dvl_sched_params, 1606a51c9b1cSDave Ertman ARRAY_SIZE(ice_dvl_sched_params)); 16070545cc86SMichal Swiatkowski 1608a51c9b1cSDave Ertman return status; 16090545cc86SMichal Swiatkowski } 16100545cc86SMichal Swiatkowski 16110545cc86SMichal Swiatkowski void ice_devlink_unregister_params(struct ice_pf *pf) 16120545cc86SMichal Swiatkowski { 1613a51c9b1cSDave Ertman struct devlink *devlink = priv_to_devlink(pf); 1614a51c9b1cSDave Ertman struct ice_hw *hw = &pf->hw; 1615a51c9b1cSDave Ertman 1616a51c9b1cSDave Ertman devl_params_unregister(devlink, ice_dvl_rdma_params, 1617a51c9b1cSDave Ertman ARRAY_SIZE(ice_dvl_rdma_params)); 1618a51c9b1cSDave Ertman 1619a51c9b1cSDave Ertman if (hw->func_caps.common_cap.tx_sched_topo_comp_mode_en) 1620a51c9b1cSDave Ertman devl_params_unregister(devlink, ice_dvl_sched_params, 1621a51c9b1cSDave Ertman ARRAY_SIZE(ice_dvl_sched_params)); 16220545cc86SMichal Swiatkowski } 16230545cc86SMichal Swiatkowski 16240545cc86SMichal Swiatkowski #define ICE_DEVLINK_READ_BLK_SIZE (1024 * 1024) 16250545cc86SMichal Swiatkowski 16260545cc86SMichal Swiatkowski static const struct devlink_region_ops ice_nvm_region_ops; 16270545cc86SMichal Swiatkowski static const struct devlink_region_ops ice_sram_region_ops; 16280545cc86SMichal Swiatkowski 16290545cc86SMichal Swiatkowski /** 16300545cc86SMichal Swiatkowski * ice_devlink_nvm_snapshot - Capture a snapshot of the NVM flash contents 16310545cc86SMichal Swiatkowski * @devlink: the devlink instance 16320545cc86SMichal Swiatkowski * @ops: the devlink region to snapshot 16330545cc86SMichal Swiatkowski * @extack: extended ACK response structure 16340545cc86SMichal Swiatkowski * @data: on exit points to snapshot data buffer 16350545cc86SMichal Swiatkowski * 16360545cc86SMichal Swiatkowski * This function is called in response to a DEVLINK_CMD_REGION_NEW for either 16370545cc86SMichal Swiatkowski * the nvm-flash or shadow-ram region. 16380545cc86SMichal Swiatkowski * 16390545cc86SMichal Swiatkowski * It captures a snapshot of the NVM or Shadow RAM flash contents. This 16400545cc86SMichal Swiatkowski * snapshot can then later be viewed via the DEVLINK_CMD_REGION_READ netlink 16410545cc86SMichal Swiatkowski * interface. 16420545cc86SMichal Swiatkowski * 16430545cc86SMichal Swiatkowski * @returns zero on success, and updates the data pointer. Returns a non-zero 16440545cc86SMichal Swiatkowski * error code on failure. 16450545cc86SMichal Swiatkowski */ 16460545cc86SMichal Swiatkowski static int ice_devlink_nvm_snapshot(struct devlink *devlink, 16470545cc86SMichal Swiatkowski const struct devlink_region_ops *ops, 16480545cc86SMichal Swiatkowski struct netlink_ext_ack *extack, u8 **data) 16490545cc86SMichal Swiatkowski { 16500545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 16510545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 16520545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 16530545cc86SMichal Swiatkowski bool read_shadow_ram; 16540545cc86SMichal Swiatkowski u8 *nvm_data, *tmp, i; 16550545cc86SMichal Swiatkowski u32 nvm_size, left; 16560545cc86SMichal Swiatkowski s8 num_blks; 16570545cc86SMichal Swiatkowski int status; 16580545cc86SMichal Swiatkowski 16590545cc86SMichal Swiatkowski if (ops == &ice_nvm_region_ops) { 16600545cc86SMichal Swiatkowski read_shadow_ram = false; 16610545cc86SMichal Swiatkowski nvm_size = hw->flash.flash_size; 16620545cc86SMichal Swiatkowski } else if (ops == &ice_sram_region_ops) { 16630545cc86SMichal Swiatkowski read_shadow_ram = true; 16640545cc86SMichal Swiatkowski nvm_size = hw->flash.sr_words * 2u; 16650545cc86SMichal Swiatkowski } else { 16660545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unexpected region in snapshot function"); 16670545cc86SMichal Swiatkowski return -EOPNOTSUPP; 16680545cc86SMichal Swiatkowski } 16690545cc86SMichal Swiatkowski 16700545cc86SMichal Swiatkowski nvm_data = vzalloc(nvm_size); 16710545cc86SMichal Swiatkowski if (!nvm_data) 16720545cc86SMichal Swiatkowski return -ENOMEM; 16730545cc86SMichal Swiatkowski 16740545cc86SMichal Swiatkowski num_blks = DIV_ROUND_UP(nvm_size, ICE_DEVLINK_READ_BLK_SIZE); 16750545cc86SMichal Swiatkowski tmp = nvm_data; 16760545cc86SMichal Swiatkowski left = nvm_size; 16770545cc86SMichal Swiatkowski 16780545cc86SMichal Swiatkowski /* Some systems take longer to read the NVM than others which causes the 16790545cc86SMichal Swiatkowski * FW to reclaim the NVM lock before the entire NVM has been read. Fix 16800545cc86SMichal Swiatkowski * this by breaking the reads of the NVM into smaller chunks that will 16810545cc86SMichal Swiatkowski * probably not take as long. This has some overhead since we are 16820545cc86SMichal Swiatkowski * increasing the number of AQ commands, but it should always work 16830545cc86SMichal Swiatkowski */ 16840545cc86SMichal Swiatkowski for (i = 0; i < num_blks; i++) { 16850545cc86SMichal Swiatkowski u32 read_sz = min_t(u32, ICE_DEVLINK_READ_BLK_SIZE, left); 16860545cc86SMichal Swiatkowski 16870545cc86SMichal Swiatkowski status = ice_acquire_nvm(hw, ICE_RES_READ); 16880545cc86SMichal Swiatkowski if (status) { 16890545cc86SMichal Swiatkowski dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n", 16900545cc86SMichal Swiatkowski status, hw->adminq.sq_last_status); 16910545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore"); 16920545cc86SMichal Swiatkowski vfree(nvm_data); 16930545cc86SMichal Swiatkowski return -EIO; 16940545cc86SMichal Swiatkowski } 16950545cc86SMichal Swiatkowski 16960545cc86SMichal Swiatkowski status = ice_read_flat_nvm(hw, i * ICE_DEVLINK_READ_BLK_SIZE, 16970545cc86SMichal Swiatkowski &read_sz, tmp, read_shadow_ram); 16980545cc86SMichal Swiatkowski if (status) { 16990545cc86SMichal Swiatkowski dev_dbg(dev, "ice_read_flat_nvm failed after reading %u bytes, err %d aq_err %d\n", 17000545cc86SMichal Swiatkowski read_sz, status, hw->adminq.sq_last_status); 17010545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Failed to read NVM contents"); 17020545cc86SMichal Swiatkowski ice_release_nvm(hw); 17030545cc86SMichal Swiatkowski vfree(nvm_data); 17040545cc86SMichal Swiatkowski return -EIO; 17050545cc86SMichal Swiatkowski } 17060545cc86SMichal Swiatkowski ice_release_nvm(hw); 17070545cc86SMichal Swiatkowski 17080545cc86SMichal Swiatkowski tmp += read_sz; 17090545cc86SMichal Swiatkowski left -= read_sz; 17100545cc86SMichal Swiatkowski } 17110545cc86SMichal Swiatkowski 17120545cc86SMichal Swiatkowski *data = nvm_data; 17130545cc86SMichal Swiatkowski 17140545cc86SMichal Swiatkowski return 0; 17150545cc86SMichal Swiatkowski } 17160545cc86SMichal Swiatkowski 17170545cc86SMichal Swiatkowski /** 17180545cc86SMichal Swiatkowski * ice_devlink_nvm_read - Read a portion of NVM flash contents 17190545cc86SMichal Swiatkowski * @devlink: the devlink instance 17200545cc86SMichal Swiatkowski * @ops: the devlink region to snapshot 17210545cc86SMichal Swiatkowski * @extack: extended ACK response structure 17220545cc86SMichal Swiatkowski * @offset: the offset to start at 17230545cc86SMichal Swiatkowski * @size: the amount to read 17240545cc86SMichal Swiatkowski * @data: the data buffer to read into 17250545cc86SMichal Swiatkowski * 17260545cc86SMichal Swiatkowski * This function is called in response to DEVLINK_CMD_REGION_READ to directly 17270545cc86SMichal Swiatkowski * read a section of the NVM contents. 17280545cc86SMichal Swiatkowski * 17290545cc86SMichal Swiatkowski * It reads from either the nvm-flash or shadow-ram region contents. 17300545cc86SMichal Swiatkowski * 17310545cc86SMichal Swiatkowski * @returns zero on success, and updates the data pointer. Returns a non-zero 17320545cc86SMichal Swiatkowski * error code on failure. 17330545cc86SMichal Swiatkowski */ 17340545cc86SMichal Swiatkowski static int ice_devlink_nvm_read(struct devlink *devlink, 17350545cc86SMichal Swiatkowski const struct devlink_region_ops *ops, 17360545cc86SMichal Swiatkowski struct netlink_ext_ack *extack, 17370545cc86SMichal Swiatkowski u64 offset, u32 size, u8 *data) 17380545cc86SMichal Swiatkowski { 17390545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 17400545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 17410545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 17420545cc86SMichal Swiatkowski bool read_shadow_ram; 17430545cc86SMichal Swiatkowski u64 nvm_size; 17440545cc86SMichal Swiatkowski int status; 17450545cc86SMichal Swiatkowski 17460545cc86SMichal Swiatkowski if (ops == &ice_nvm_region_ops) { 17470545cc86SMichal Swiatkowski read_shadow_ram = false; 17480545cc86SMichal Swiatkowski nvm_size = hw->flash.flash_size; 17490545cc86SMichal Swiatkowski } else if (ops == &ice_sram_region_ops) { 17500545cc86SMichal Swiatkowski read_shadow_ram = true; 17510545cc86SMichal Swiatkowski nvm_size = hw->flash.sr_words * 2u; 17520545cc86SMichal Swiatkowski } else { 17530545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unexpected region in snapshot function"); 17540545cc86SMichal Swiatkowski return -EOPNOTSUPP; 17550545cc86SMichal Swiatkowski } 17560545cc86SMichal Swiatkowski 17570545cc86SMichal Swiatkowski if (offset + size >= nvm_size) { 17580545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Cannot read beyond the region size"); 17590545cc86SMichal Swiatkowski return -ERANGE; 17600545cc86SMichal Swiatkowski } 17610545cc86SMichal Swiatkowski 17620545cc86SMichal Swiatkowski status = ice_acquire_nvm(hw, ICE_RES_READ); 17630545cc86SMichal Swiatkowski if (status) { 17640545cc86SMichal Swiatkowski dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n", 17650545cc86SMichal Swiatkowski status, hw->adminq.sq_last_status); 17660545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore"); 17670545cc86SMichal Swiatkowski return -EIO; 17680545cc86SMichal Swiatkowski } 17690545cc86SMichal Swiatkowski 17700545cc86SMichal Swiatkowski status = ice_read_flat_nvm(hw, (u32)offset, &size, data, 17710545cc86SMichal Swiatkowski read_shadow_ram); 17720545cc86SMichal Swiatkowski if (status) { 17730545cc86SMichal Swiatkowski dev_dbg(dev, "ice_read_flat_nvm failed after reading %u bytes, err %d aq_err %d\n", 17740545cc86SMichal Swiatkowski size, status, hw->adminq.sq_last_status); 17750545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Failed to read NVM contents"); 17760545cc86SMichal Swiatkowski ice_release_nvm(hw); 17770545cc86SMichal Swiatkowski return -EIO; 17780545cc86SMichal Swiatkowski } 17790545cc86SMichal Swiatkowski ice_release_nvm(hw); 17800545cc86SMichal Swiatkowski 17810545cc86SMichal Swiatkowski return 0; 17820545cc86SMichal Swiatkowski } 17830545cc86SMichal Swiatkowski 17840545cc86SMichal Swiatkowski /** 17850545cc86SMichal Swiatkowski * ice_devlink_devcaps_snapshot - Capture snapshot of device capabilities 17860545cc86SMichal Swiatkowski * @devlink: the devlink instance 17870545cc86SMichal Swiatkowski * @ops: the devlink region being snapshotted 17880545cc86SMichal Swiatkowski * @extack: extended ACK response structure 17890545cc86SMichal Swiatkowski * @data: on exit points to snapshot data buffer 17900545cc86SMichal Swiatkowski * 17910545cc86SMichal Swiatkowski * This function is called in response to the DEVLINK_CMD_REGION_TRIGGER for 17920545cc86SMichal Swiatkowski * the device-caps devlink region. It captures a snapshot of the device 17930545cc86SMichal Swiatkowski * capabilities reported by firmware. 17940545cc86SMichal Swiatkowski * 17950545cc86SMichal Swiatkowski * @returns zero on success, and updates the data pointer. Returns a non-zero 17960545cc86SMichal Swiatkowski * error code on failure. 17970545cc86SMichal Swiatkowski */ 17980545cc86SMichal Swiatkowski static int 17990545cc86SMichal Swiatkowski ice_devlink_devcaps_snapshot(struct devlink *devlink, 18000545cc86SMichal Swiatkowski const struct devlink_region_ops *ops, 18010545cc86SMichal Swiatkowski struct netlink_ext_ack *extack, u8 **data) 18020545cc86SMichal Swiatkowski { 18030545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 18040545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 18050545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 18060545cc86SMichal Swiatkowski void *devcaps; 18070545cc86SMichal Swiatkowski int status; 18080545cc86SMichal Swiatkowski 18090545cc86SMichal Swiatkowski devcaps = vzalloc(ICE_AQ_MAX_BUF_LEN); 18100545cc86SMichal Swiatkowski if (!devcaps) 18110545cc86SMichal Swiatkowski return -ENOMEM; 18120545cc86SMichal Swiatkowski 18130545cc86SMichal Swiatkowski status = ice_aq_list_caps(hw, devcaps, ICE_AQ_MAX_BUF_LEN, NULL, 18140545cc86SMichal Swiatkowski ice_aqc_opc_list_dev_caps, NULL); 18150545cc86SMichal Swiatkowski if (status) { 18160545cc86SMichal Swiatkowski dev_dbg(dev, "ice_aq_list_caps: failed to read device capabilities, err %d aq_err %d\n", 18170545cc86SMichal Swiatkowski status, hw->adminq.sq_last_status); 18180545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Failed to read device capabilities"); 18190545cc86SMichal Swiatkowski vfree(devcaps); 18200545cc86SMichal Swiatkowski return status; 18210545cc86SMichal Swiatkowski } 18220545cc86SMichal Swiatkowski 18230545cc86SMichal Swiatkowski *data = (u8 *)devcaps; 18240545cc86SMichal Swiatkowski 18250545cc86SMichal Swiatkowski return 0; 18260545cc86SMichal Swiatkowski } 18270545cc86SMichal Swiatkowski 18280545cc86SMichal Swiatkowski static const struct devlink_region_ops ice_nvm_region_ops = { 18290545cc86SMichal Swiatkowski .name = "nvm-flash", 18300545cc86SMichal Swiatkowski .destructor = vfree, 18310545cc86SMichal Swiatkowski .snapshot = ice_devlink_nvm_snapshot, 18320545cc86SMichal Swiatkowski .read = ice_devlink_nvm_read, 18330545cc86SMichal Swiatkowski }; 18340545cc86SMichal Swiatkowski 18350545cc86SMichal Swiatkowski static const struct devlink_region_ops ice_sram_region_ops = { 18360545cc86SMichal Swiatkowski .name = "shadow-ram", 18370545cc86SMichal Swiatkowski .destructor = vfree, 18380545cc86SMichal Swiatkowski .snapshot = ice_devlink_nvm_snapshot, 18390545cc86SMichal Swiatkowski .read = ice_devlink_nvm_read, 18400545cc86SMichal Swiatkowski }; 18410545cc86SMichal Swiatkowski 18420545cc86SMichal Swiatkowski static const struct devlink_region_ops ice_devcaps_region_ops = { 18430545cc86SMichal Swiatkowski .name = "device-caps", 18440545cc86SMichal Swiatkowski .destructor = vfree, 18450545cc86SMichal Swiatkowski .snapshot = ice_devlink_devcaps_snapshot, 18460545cc86SMichal Swiatkowski }; 18470545cc86SMichal Swiatkowski 18480545cc86SMichal Swiatkowski /** 18490545cc86SMichal Swiatkowski * ice_devlink_init_regions - Initialize devlink regions 18500545cc86SMichal Swiatkowski * @pf: the PF device structure 18510545cc86SMichal Swiatkowski * 18520545cc86SMichal Swiatkowski * Create devlink regions used to enable access to dump the contents of the 18530545cc86SMichal Swiatkowski * flash memory on the device. 18540545cc86SMichal Swiatkowski */ 18550545cc86SMichal Swiatkowski void ice_devlink_init_regions(struct ice_pf *pf) 18560545cc86SMichal Swiatkowski { 18570545cc86SMichal Swiatkowski struct devlink *devlink = priv_to_devlink(pf); 18580545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 18590545cc86SMichal Swiatkowski u64 nvm_size, sram_size; 18600545cc86SMichal Swiatkowski 18610545cc86SMichal Swiatkowski nvm_size = pf->hw.flash.flash_size; 1862118c6bdeSMichal Swiatkowski pf->nvm_region = devl_region_create(devlink, &ice_nvm_region_ops, 1, 18630545cc86SMichal Swiatkowski nvm_size); 18640545cc86SMichal Swiatkowski if (IS_ERR(pf->nvm_region)) { 18650545cc86SMichal Swiatkowski dev_err(dev, "failed to create NVM devlink region, err %ld\n", 18660545cc86SMichal Swiatkowski PTR_ERR(pf->nvm_region)); 18670545cc86SMichal Swiatkowski pf->nvm_region = NULL; 18680545cc86SMichal Swiatkowski } 18690545cc86SMichal Swiatkowski 18700545cc86SMichal Swiatkowski sram_size = pf->hw.flash.sr_words * 2u; 1871118c6bdeSMichal Swiatkowski pf->sram_region = devl_region_create(devlink, &ice_sram_region_ops, 18720545cc86SMichal Swiatkowski 1, sram_size); 18730545cc86SMichal Swiatkowski if (IS_ERR(pf->sram_region)) { 18740545cc86SMichal Swiatkowski dev_err(dev, "failed to create shadow-ram devlink region, err %ld\n", 18750545cc86SMichal Swiatkowski PTR_ERR(pf->sram_region)); 18760545cc86SMichal Swiatkowski pf->sram_region = NULL; 18770545cc86SMichal Swiatkowski } 18780545cc86SMichal Swiatkowski 1879118c6bdeSMichal Swiatkowski pf->devcaps_region = devl_region_create(devlink, 18800545cc86SMichal Swiatkowski &ice_devcaps_region_ops, 10, 18810545cc86SMichal Swiatkowski ICE_AQ_MAX_BUF_LEN); 18820545cc86SMichal Swiatkowski if (IS_ERR(pf->devcaps_region)) { 18830545cc86SMichal Swiatkowski dev_err(dev, "failed to create device-caps devlink region, err %ld\n", 18840545cc86SMichal Swiatkowski PTR_ERR(pf->devcaps_region)); 18850545cc86SMichal Swiatkowski pf->devcaps_region = NULL; 18860545cc86SMichal Swiatkowski } 18870545cc86SMichal Swiatkowski } 18880545cc86SMichal Swiatkowski 18890545cc86SMichal Swiatkowski /** 18900545cc86SMichal Swiatkowski * ice_devlink_destroy_regions - Destroy devlink regions 18910545cc86SMichal Swiatkowski * @pf: the PF device structure 18920545cc86SMichal Swiatkowski * 18930545cc86SMichal Swiatkowski * Remove previously created regions for this PF. 18940545cc86SMichal Swiatkowski */ 18950545cc86SMichal Swiatkowski void ice_devlink_destroy_regions(struct ice_pf *pf) 18960545cc86SMichal Swiatkowski { 18970545cc86SMichal Swiatkowski if (pf->nvm_region) 1898118c6bdeSMichal Swiatkowski devl_region_destroy(pf->nvm_region); 18990545cc86SMichal Swiatkowski 19000545cc86SMichal Swiatkowski if (pf->sram_region) 1901118c6bdeSMichal Swiatkowski devl_region_destroy(pf->sram_region); 19020545cc86SMichal Swiatkowski 19030545cc86SMichal Swiatkowski if (pf->devcaps_region) 1904118c6bdeSMichal Swiatkowski devl_region_destroy(pf->devcaps_region); 19050545cc86SMichal Swiatkowski } 1906