10545cc86SMichal Swiatkowski // SPDX-License-Identifier: GPL-2.0 20545cc86SMichal Swiatkowski /* Copyright (c) 2020, Intel Corporation. */ 30545cc86SMichal Swiatkowski 40545cc86SMichal Swiatkowski #include <linux/vmalloc.h> 50545cc86SMichal Swiatkowski 60545cc86SMichal Swiatkowski #include "ice.h" 70545cc86SMichal Swiatkowski #include "ice_lib.h" 80545cc86SMichal Swiatkowski #include "devlink.h" 90545cc86SMichal Swiatkowski #include "ice_eswitch.h" 100545cc86SMichal Swiatkowski #include "ice_fw_update.h" 110545cc86SMichal Swiatkowski #include "ice_dcb_lib.h" 120545cc86SMichal Swiatkowski 130545cc86SMichal Swiatkowski /* context for devlink info version reporting */ 140545cc86SMichal Swiatkowski struct ice_info_ctx { 150545cc86SMichal Swiatkowski char buf[128]; 160545cc86SMichal Swiatkowski struct ice_orom_info pending_orom; 170545cc86SMichal Swiatkowski struct ice_nvm_info pending_nvm; 180545cc86SMichal Swiatkowski struct ice_netlist_info pending_netlist; 190545cc86SMichal Swiatkowski struct ice_hw_dev_caps dev_caps; 200545cc86SMichal Swiatkowski }; 210545cc86SMichal Swiatkowski 220545cc86SMichal Swiatkowski /* The following functions are used to format specific strings for various 230545cc86SMichal Swiatkowski * devlink info versions. The ctx parameter is used to provide the storage 240545cc86SMichal Swiatkowski * buffer, as well as any ancillary information calculated when the info 250545cc86SMichal Swiatkowski * request was made. 260545cc86SMichal Swiatkowski * 270545cc86SMichal Swiatkowski * If a version does not exist, for example when attempting to get the 280545cc86SMichal Swiatkowski * inactive version of flash when there is no pending update, the function 290545cc86SMichal Swiatkowski * should leave the buffer in the ctx structure empty. 300545cc86SMichal Swiatkowski */ 310545cc86SMichal Swiatkowski 320545cc86SMichal Swiatkowski static void ice_info_get_dsn(struct ice_pf *pf, struct ice_info_ctx *ctx) 330545cc86SMichal Swiatkowski { 340545cc86SMichal Swiatkowski u8 dsn[8]; 350545cc86SMichal Swiatkowski 360545cc86SMichal Swiatkowski /* Copy the DSN into an array in Big Endian format */ 370545cc86SMichal Swiatkowski put_unaligned_be64(pci_get_dsn(pf->pdev), dsn); 380545cc86SMichal Swiatkowski 390545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%8phD", dsn); 400545cc86SMichal Swiatkowski } 410545cc86SMichal Swiatkowski 420545cc86SMichal Swiatkowski static void ice_info_pba(struct ice_pf *pf, struct ice_info_ctx *ctx) 430545cc86SMichal Swiatkowski { 440545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 450545cc86SMichal Swiatkowski int status; 460545cc86SMichal Swiatkowski 470545cc86SMichal Swiatkowski status = ice_read_pba_string(hw, (u8 *)ctx->buf, sizeof(ctx->buf)); 480545cc86SMichal Swiatkowski if (status) 490545cc86SMichal Swiatkowski /* We failed to locate the PBA, so just skip this entry */ 500545cc86SMichal Swiatkowski dev_dbg(ice_pf_to_dev(pf), "Failed to read Product Board Assembly string, status %d\n", 510545cc86SMichal Swiatkowski status); 520545cc86SMichal Swiatkowski } 530545cc86SMichal Swiatkowski 540545cc86SMichal Swiatkowski static void ice_info_fw_mgmt(struct ice_pf *pf, struct ice_info_ctx *ctx) 550545cc86SMichal Swiatkowski { 560545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 570545cc86SMichal Swiatkowski 580545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", 590545cc86SMichal Swiatkowski hw->fw_maj_ver, hw->fw_min_ver, hw->fw_patch); 600545cc86SMichal Swiatkowski } 610545cc86SMichal Swiatkowski 620545cc86SMichal Swiatkowski static void ice_info_fw_api(struct ice_pf *pf, struct ice_info_ctx *ctx) 630545cc86SMichal Swiatkowski { 640545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 650545cc86SMichal Swiatkowski 660545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", hw->api_maj_ver, 670545cc86SMichal Swiatkowski hw->api_min_ver, hw->api_patch); 680545cc86SMichal Swiatkowski } 690545cc86SMichal Swiatkowski 700545cc86SMichal Swiatkowski static void ice_info_fw_build(struct ice_pf *pf, struct ice_info_ctx *ctx) 710545cc86SMichal Swiatkowski { 720545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 730545cc86SMichal Swiatkowski 740545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", hw->fw_build); 750545cc86SMichal Swiatkowski } 760545cc86SMichal Swiatkowski 770545cc86SMichal Swiatkowski static void ice_info_orom_ver(struct ice_pf *pf, struct ice_info_ctx *ctx) 780545cc86SMichal Swiatkowski { 790545cc86SMichal Swiatkowski struct ice_orom_info *orom = &pf->hw.flash.orom; 800545cc86SMichal Swiatkowski 810545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", 820545cc86SMichal Swiatkowski orom->major, orom->build, orom->patch); 830545cc86SMichal Swiatkowski } 840545cc86SMichal Swiatkowski 850545cc86SMichal Swiatkowski static void 860545cc86SMichal Swiatkowski ice_info_pending_orom_ver(struct ice_pf __always_unused *pf, 870545cc86SMichal Swiatkowski struct ice_info_ctx *ctx) 880545cc86SMichal Swiatkowski { 890545cc86SMichal Swiatkowski struct ice_orom_info *orom = &ctx->pending_orom; 900545cc86SMichal Swiatkowski 910545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_orom) 920545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", 930545cc86SMichal Swiatkowski orom->major, orom->build, orom->patch); 940545cc86SMichal Swiatkowski } 950545cc86SMichal Swiatkowski 960545cc86SMichal Swiatkowski static void ice_info_nvm_ver(struct ice_pf *pf, struct ice_info_ctx *ctx) 970545cc86SMichal Swiatkowski { 980545cc86SMichal Swiatkowski struct ice_nvm_info *nvm = &pf->hw.flash.nvm; 990545cc86SMichal Swiatkowski 1000545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", nvm->major, nvm->minor); 1010545cc86SMichal Swiatkowski } 1020545cc86SMichal Swiatkowski 1030545cc86SMichal Swiatkowski static void 1040545cc86SMichal Swiatkowski ice_info_pending_nvm_ver(struct ice_pf __always_unused *pf, 1050545cc86SMichal Swiatkowski struct ice_info_ctx *ctx) 1060545cc86SMichal Swiatkowski { 1070545cc86SMichal Swiatkowski struct ice_nvm_info *nvm = &ctx->pending_nvm; 1080545cc86SMichal Swiatkowski 1090545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_nvm) 1100545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", 1110545cc86SMichal Swiatkowski nvm->major, nvm->minor); 1120545cc86SMichal Swiatkowski } 1130545cc86SMichal Swiatkowski 1140545cc86SMichal Swiatkowski static void ice_info_eetrack(struct ice_pf *pf, struct ice_info_ctx *ctx) 1150545cc86SMichal Swiatkowski { 1160545cc86SMichal Swiatkowski struct ice_nvm_info *nvm = &pf->hw.flash.nvm; 1170545cc86SMichal Swiatkowski 1180545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm->eetrack); 1190545cc86SMichal Swiatkowski } 1200545cc86SMichal Swiatkowski 1210545cc86SMichal Swiatkowski static void 1220545cc86SMichal Swiatkowski ice_info_pending_eetrack(struct ice_pf *pf, struct ice_info_ctx *ctx) 1230545cc86SMichal Swiatkowski { 1240545cc86SMichal Swiatkowski struct ice_nvm_info *nvm = &ctx->pending_nvm; 1250545cc86SMichal Swiatkowski 1260545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_nvm) 1270545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm->eetrack); 1280545cc86SMichal Swiatkowski } 1290545cc86SMichal Swiatkowski 1300545cc86SMichal Swiatkowski static void ice_info_ddp_pkg_name(struct ice_pf *pf, struct ice_info_ctx *ctx) 1310545cc86SMichal Swiatkowski { 1320545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 1330545cc86SMichal Swiatkowski 1340545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%s", hw->active_pkg_name); 1350545cc86SMichal Swiatkowski } 1360545cc86SMichal Swiatkowski 1370545cc86SMichal Swiatkowski static void 1380545cc86SMichal Swiatkowski ice_info_ddp_pkg_version(struct ice_pf *pf, struct ice_info_ctx *ctx) 1390545cc86SMichal Swiatkowski { 1400545cc86SMichal Swiatkowski struct ice_pkg_ver *pkg = &pf->hw.active_pkg_ver; 1410545cc86SMichal Swiatkowski 1420545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u.%u", 1430545cc86SMichal Swiatkowski pkg->major, pkg->minor, pkg->update, pkg->draft); 1440545cc86SMichal Swiatkowski } 1450545cc86SMichal Swiatkowski 1460545cc86SMichal Swiatkowski static void 1470545cc86SMichal Swiatkowski ice_info_ddp_pkg_bundle_id(struct ice_pf *pf, struct ice_info_ctx *ctx) 1480545cc86SMichal Swiatkowski { 1490545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", pf->hw.active_track_id); 1500545cc86SMichal Swiatkowski } 1510545cc86SMichal Swiatkowski 1520545cc86SMichal Swiatkowski static void ice_info_netlist_ver(struct ice_pf *pf, struct ice_info_ctx *ctx) 1530545cc86SMichal Swiatkowski { 1540545cc86SMichal Swiatkowski struct ice_netlist_info *netlist = &pf->hw.flash.netlist; 1550545cc86SMichal Swiatkowski 1560545cc86SMichal Swiatkowski /* The netlist version fields are BCD formatted */ 1570545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x", 1580545cc86SMichal Swiatkowski netlist->major, netlist->minor, 1590545cc86SMichal Swiatkowski netlist->type >> 16, netlist->type & 0xFFFF, 1600545cc86SMichal Swiatkowski netlist->rev, netlist->cust_ver); 1610545cc86SMichal Swiatkowski } 1620545cc86SMichal Swiatkowski 1630545cc86SMichal Swiatkowski static void ice_info_netlist_build(struct ice_pf *pf, struct ice_info_ctx *ctx) 1640545cc86SMichal Swiatkowski { 1650545cc86SMichal Swiatkowski struct ice_netlist_info *netlist = &pf->hw.flash.netlist; 1660545cc86SMichal Swiatkowski 1670545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash); 1680545cc86SMichal Swiatkowski } 1690545cc86SMichal Swiatkowski 1700545cc86SMichal Swiatkowski static void 1710545cc86SMichal Swiatkowski ice_info_pending_netlist_ver(struct ice_pf __always_unused *pf, 1720545cc86SMichal Swiatkowski struct ice_info_ctx *ctx) 1730545cc86SMichal Swiatkowski { 1740545cc86SMichal Swiatkowski struct ice_netlist_info *netlist = &ctx->pending_netlist; 1750545cc86SMichal Swiatkowski 1760545cc86SMichal Swiatkowski /* The netlist version fields are BCD formatted */ 1770545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_netlist) 1780545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x", 1790545cc86SMichal Swiatkowski netlist->major, netlist->minor, 1800545cc86SMichal Swiatkowski netlist->type >> 16, netlist->type & 0xFFFF, 1810545cc86SMichal Swiatkowski netlist->rev, netlist->cust_ver); 1820545cc86SMichal Swiatkowski } 1830545cc86SMichal Swiatkowski 1840545cc86SMichal Swiatkowski static void 1850545cc86SMichal Swiatkowski ice_info_pending_netlist_build(struct ice_pf __always_unused *pf, 1860545cc86SMichal Swiatkowski struct ice_info_ctx *ctx) 1870545cc86SMichal Swiatkowski { 1880545cc86SMichal Swiatkowski struct ice_netlist_info *netlist = &ctx->pending_netlist; 1890545cc86SMichal Swiatkowski 1900545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_netlist) 1910545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash); 1920545cc86SMichal Swiatkowski } 1930545cc86SMichal Swiatkowski 1940545cc86SMichal Swiatkowski static void ice_info_cgu_fw_build(struct ice_pf *pf, struct ice_info_ctx *ctx) 1950545cc86SMichal Swiatkowski { 1960545cc86SMichal Swiatkowski u32 id, cfg_ver, fw_ver; 1970545cc86SMichal Swiatkowski 1980545cc86SMichal Swiatkowski if (!ice_is_feature_supported(pf, ICE_F_CGU)) 1990545cc86SMichal Swiatkowski return; 2000545cc86SMichal Swiatkowski if (ice_aq_get_cgu_info(&pf->hw, &id, &cfg_ver, &fw_ver)) 2010545cc86SMichal Swiatkowski return; 2020545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", id, cfg_ver, fw_ver); 2030545cc86SMichal Swiatkowski } 2040545cc86SMichal Swiatkowski 2050545cc86SMichal Swiatkowski static void ice_info_cgu_id(struct ice_pf *pf, struct ice_info_ctx *ctx) 2060545cc86SMichal Swiatkowski { 2070545cc86SMichal Swiatkowski if (!ice_is_feature_supported(pf, ICE_F_CGU)) 2080545cc86SMichal Swiatkowski return; 2090545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%u", pf->hw.cgu_part_number); 2100545cc86SMichal Swiatkowski } 2110545cc86SMichal Swiatkowski 2120545cc86SMichal Swiatkowski #define fixed(key, getter) { ICE_VERSION_FIXED, key, getter, NULL } 2130545cc86SMichal Swiatkowski #define running(key, getter) { ICE_VERSION_RUNNING, key, getter, NULL } 2140545cc86SMichal Swiatkowski #define stored(key, getter, fallback) { ICE_VERSION_STORED, key, getter, fallback } 2150545cc86SMichal Swiatkowski 2160545cc86SMichal Swiatkowski /* The combined() macro inserts both the running entry as well as a stored 2170545cc86SMichal Swiatkowski * entry. The running entry will always report the version from the active 2180545cc86SMichal Swiatkowski * handler. The stored entry will first try the pending handler, and fallback 2190545cc86SMichal Swiatkowski * to the active handler if the pending function does not report a version. 2200545cc86SMichal Swiatkowski * The pending handler should check the status of a pending update for the 2210545cc86SMichal Swiatkowski * relevant flash component. It should only fill in the buffer in the case 2220545cc86SMichal Swiatkowski * where a valid pending version is available. This ensures that the related 2230545cc86SMichal Swiatkowski * stored and running versions remain in sync, and that stored versions are 2240545cc86SMichal Swiatkowski * correctly reported as expected. 2250545cc86SMichal Swiatkowski */ 2260545cc86SMichal Swiatkowski #define combined(key, active, pending) \ 2270545cc86SMichal Swiatkowski running(key, active), \ 2280545cc86SMichal Swiatkowski stored(key, pending, active) 2290545cc86SMichal Swiatkowski 2300545cc86SMichal Swiatkowski enum ice_version_type { 2310545cc86SMichal Swiatkowski ICE_VERSION_FIXED, 2320545cc86SMichal Swiatkowski ICE_VERSION_RUNNING, 2330545cc86SMichal Swiatkowski ICE_VERSION_STORED, 2340545cc86SMichal Swiatkowski }; 2350545cc86SMichal Swiatkowski 2360545cc86SMichal Swiatkowski static const struct ice_devlink_version { 2370545cc86SMichal Swiatkowski enum ice_version_type type; 2380545cc86SMichal Swiatkowski const char *key; 2390545cc86SMichal Swiatkowski void (*getter)(struct ice_pf *pf, struct ice_info_ctx *ctx); 2400545cc86SMichal Swiatkowski void (*fallback)(struct ice_pf *pf, struct ice_info_ctx *ctx); 2410545cc86SMichal Swiatkowski } ice_devlink_versions[] = { 2420545cc86SMichal Swiatkowski fixed(DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, ice_info_pba), 2430545cc86SMichal Swiatkowski running(DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, ice_info_fw_mgmt), 2440545cc86SMichal Swiatkowski running("fw.mgmt.api", ice_info_fw_api), 2450545cc86SMichal Swiatkowski running("fw.mgmt.build", ice_info_fw_build), 2460545cc86SMichal Swiatkowski combined(DEVLINK_INFO_VERSION_GENERIC_FW_UNDI, ice_info_orom_ver, ice_info_pending_orom_ver), 2470545cc86SMichal Swiatkowski combined("fw.psid.api", ice_info_nvm_ver, ice_info_pending_nvm_ver), 2480545cc86SMichal Swiatkowski combined(DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID, ice_info_eetrack, ice_info_pending_eetrack), 2490545cc86SMichal Swiatkowski running("fw.app.name", ice_info_ddp_pkg_name), 2500545cc86SMichal Swiatkowski running(DEVLINK_INFO_VERSION_GENERIC_FW_APP, ice_info_ddp_pkg_version), 2510545cc86SMichal Swiatkowski running("fw.app.bundle_id", ice_info_ddp_pkg_bundle_id), 2520545cc86SMichal Swiatkowski combined("fw.netlist", ice_info_netlist_ver, ice_info_pending_netlist_ver), 2530545cc86SMichal Swiatkowski combined("fw.netlist.build", ice_info_netlist_build, ice_info_pending_netlist_build), 2540545cc86SMichal Swiatkowski fixed("cgu.id", ice_info_cgu_id), 2550545cc86SMichal Swiatkowski running("fw.cgu", ice_info_cgu_fw_build), 2560545cc86SMichal Swiatkowski }; 2570545cc86SMichal Swiatkowski 2580545cc86SMichal Swiatkowski /** 2590545cc86SMichal Swiatkowski * ice_devlink_info_get - .info_get devlink handler 2600545cc86SMichal Swiatkowski * @devlink: devlink instance structure 2610545cc86SMichal Swiatkowski * @req: the devlink info request 2620545cc86SMichal Swiatkowski * @extack: extended netdev ack structure 2630545cc86SMichal Swiatkowski * 2640545cc86SMichal Swiatkowski * Callback for the devlink .info_get operation. Reports information about the 2650545cc86SMichal Swiatkowski * device. 2660545cc86SMichal Swiatkowski * 2670545cc86SMichal Swiatkowski * Return: zero on success or an error code on failure. 2680545cc86SMichal Swiatkowski */ 2690545cc86SMichal Swiatkowski static int ice_devlink_info_get(struct devlink *devlink, 2700545cc86SMichal Swiatkowski struct devlink_info_req *req, 2710545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 2720545cc86SMichal Swiatkowski { 2730545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 2740545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 2750545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 2760545cc86SMichal Swiatkowski struct ice_info_ctx *ctx; 2770545cc86SMichal Swiatkowski size_t i; 2780545cc86SMichal Swiatkowski int err; 2790545cc86SMichal Swiatkowski 2800545cc86SMichal Swiatkowski err = ice_wait_for_reset(pf, 10 * HZ); 2810545cc86SMichal Swiatkowski if (err) { 2820545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Device is busy resetting"); 2830545cc86SMichal Swiatkowski return err; 2840545cc86SMichal Swiatkowski } 2850545cc86SMichal Swiatkowski 2860545cc86SMichal Swiatkowski ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 2870545cc86SMichal Swiatkowski if (!ctx) 2880545cc86SMichal Swiatkowski return -ENOMEM; 2890545cc86SMichal Swiatkowski 2900545cc86SMichal Swiatkowski /* discover capabilities first */ 2910545cc86SMichal Swiatkowski err = ice_discover_dev_caps(hw, &ctx->dev_caps); 2920545cc86SMichal Swiatkowski if (err) { 2930545cc86SMichal Swiatkowski dev_dbg(dev, "Failed to discover device capabilities, status %d aq_err %s\n", 2940545cc86SMichal Swiatkowski err, ice_aq_str(hw->adminq.sq_last_status)); 2950545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unable to discover device capabilities"); 2960545cc86SMichal Swiatkowski goto out_free_ctx; 2970545cc86SMichal Swiatkowski } 2980545cc86SMichal Swiatkowski 2990545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_orom) { 3000545cc86SMichal Swiatkowski err = ice_get_inactive_orom_ver(hw, &ctx->pending_orom); 3010545cc86SMichal Swiatkowski if (err) { 3020545cc86SMichal Swiatkowski dev_dbg(dev, "Unable to read inactive Option ROM version data, status %d aq_err %s\n", 3030545cc86SMichal Swiatkowski err, ice_aq_str(hw->adminq.sq_last_status)); 3040545cc86SMichal Swiatkowski 3050545cc86SMichal Swiatkowski /* disable display of pending Option ROM */ 3060545cc86SMichal Swiatkowski ctx->dev_caps.common_cap.nvm_update_pending_orom = false; 3070545cc86SMichal Swiatkowski } 3080545cc86SMichal Swiatkowski } 3090545cc86SMichal Swiatkowski 3100545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_nvm) { 3110545cc86SMichal Swiatkowski err = ice_get_inactive_nvm_ver(hw, &ctx->pending_nvm); 3120545cc86SMichal Swiatkowski if (err) { 3130545cc86SMichal Swiatkowski dev_dbg(dev, "Unable to read inactive NVM version data, status %d aq_err %s\n", 3140545cc86SMichal Swiatkowski err, ice_aq_str(hw->adminq.sq_last_status)); 3150545cc86SMichal Swiatkowski 3160545cc86SMichal Swiatkowski /* disable display of pending Option ROM */ 3170545cc86SMichal Swiatkowski ctx->dev_caps.common_cap.nvm_update_pending_nvm = false; 3180545cc86SMichal Swiatkowski } 3190545cc86SMichal Swiatkowski } 3200545cc86SMichal Swiatkowski 3210545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_netlist) { 3220545cc86SMichal Swiatkowski err = ice_get_inactive_netlist_ver(hw, &ctx->pending_netlist); 3230545cc86SMichal Swiatkowski if (err) { 3240545cc86SMichal Swiatkowski dev_dbg(dev, "Unable to read inactive Netlist version data, status %d aq_err %s\n", 3250545cc86SMichal Swiatkowski err, ice_aq_str(hw->adminq.sq_last_status)); 3260545cc86SMichal Swiatkowski 3270545cc86SMichal Swiatkowski /* disable display of pending Option ROM */ 3280545cc86SMichal Swiatkowski ctx->dev_caps.common_cap.nvm_update_pending_netlist = false; 3290545cc86SMichal Swiatkowski } 3300545cc86SMichal Swiatkowski } 3310545cc86SMichal Swiatkowski 3320545cc86SMichal Swiatkowski ice_info_get_dsn(pf, ctx); 3330545cc86SMichal Swiatkowski 3340545cc86SMichal Swiatkowski err = devlink_info_serial_number_put(req, ctx->buf); 3350545cc86SMichal Swiatkowski if (err) { 3360545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unable to set serial number"); 3370545cc86SMichal Swiatkowski goto out_free_ctx; 3380545cc86SMichal Swiatkowski } 3390545cc86SMichal Swiatkowski 3400545cc86SMichal Swiatkowski for (i = 0; i < ARRAY_SIZE(ice_devlink_versions); i++) { 3410545cc86SMichal Swiatkowski enum ice_version_type type = ice_devlink_versions[i].type; 3420545cc86SMichal Swiatkowski const char *key = ice_devlink_versions[i].key; 3430545cc86SMichal Swiatkowski 3440545cc86SMichal Swiatkowski memset(ctx->buf, 0, sizeof(ctx->buf)); 3450545cc86SMichal Swiatkowski 3460545cc86SMichal Swiatkowski ice_devlink_versions[i].getter(pf, ctx); 3470545cc86SMichal Swiatkowski 3480545cc86SMichal Swiatkowski /* If the default getter doesn't report a version, use the 3490545cc86SMichal Swiatkowski * fallback function. This is primarily useful in the case of 3500545cc86SMichal Swiatkowski * "stored" versions that want to report the same value as the 3510545cc86SMichal Swiatkowski * running version in the normal case of no pending update. 3520545cc86SMichal Swiatkowski */ 3530545cc86SMichal Swiatkowski if (ctx->buf[0] == '\0' && ice_devlink_versions[i].fallback) 3540545cc86SMichal Swiatkowski ice_devlink_versions[i].fallback(pf, ctx); 3550545cc86SMichal Swiatkowski 3560545cc86SMichal Swiatkowski /* Do not report missing versions */ 3570545cc86SMichal Swiatkowski if (ctx->buf[0] == '\0') 3580545cc86SMichal Swiatkowski continue; 3590545cc86SMichal Swiatkowski 3600545cc86SMichal Swiatkowski switch (type) { 3610545cc86SMichal Swiatkowski case ICE_VERSION_FIXED: 3620545cc86SMichal Swiatkowski err = devlink_info_version_fixed_put(req, key, ctx->buf); 3630545cc86SMichal Swiatkowski if (err) { 3640545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unable to set fixed version"); 3650545cc86SMichal Swiatkowski goto out_free_ctx; 3660545cc86SMichal Swiatkowski } 3670545cc86SMichal Swiatkowski break; 3680545cc86SMichal Swiatkowski case ICE_VERSION_RUNNING: 3690545cc86SMichal Swiatkowski err = devlink_info_version_running_put(req, key, ctx->buf); 3700545cc86SMichal Swiatkowski if (err) { 3710545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unable to set running version"); 3720545cc86SMichal Swiatkowski goto out_free_ctx; 3730545cc86SMichal Swiatkowski } 3740545cc86SMichal Swiatkowski break; 3750545cc86SMichal Swiatkowski case ICE_VERSION_STORED: 3760545cc86SMichal Swiatkowski err = devlink_info_version_stored_put(req, key, ctx->buf); 3770545cc86SMichal Swiatkowski if (err) { 3780545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unable to set stored version"); 3790545cc86SMichal Swiatkowski goto out_free_ctx; 3800545cc86SMichal Swiatkowski } 3810545cc86SMichal Swiatkowski break; 3820545cc86SMichal Swiatkowski } 3830545cc86SMichal Swiatkowski } 3840545cc86SMichal Swiatkowski 3850545cc86SMichal Swiatkowski out_free_ctx: 3860545cc86SMichal Swiatkowski kfree(ctx); 3870545cc86SMichal Swiatkowski return err; 3880545cc86SMichal Swiatkowski } 3890545cc86SMichal Swiatkowski 3900545cc86SMichal Swiatkowski /** 3910545cc86SMichal Swiatkowski * ice_devlink_reload_empr_start - Start EMP reset to activate new firmware 3920545cc86SMichal Swiatkowski * @pf: pointer to the pf instance 3930545cc86SMichal Swiatkowski * @extack: netlink extended ACK structure 3940545cc86SMichal Swiatkowski * 3950545cc86SMichal Swiatkowski * Allow user to activate new Embedded Management Processor firmware by 3960545cc86SMichal Swiatkowski * issuing device specific EMP reset. Called in response to 3970545cc86SMichal Swiatkowski * a DEVLINK_CMD_RELOAD with the DEVLINK_RELOAD_ACTION_FW_ACTIVATE. 3980545cc86SMichal Swiatkowski * 3990545cc86SMichal Swiatkowski * Note that teardown and rebuild of the driver state happens automatically as 4000545cc86SMichal Swiatkowski * part of an interrupt and watchdog task. This is because all physical 4010545cc86SMichal Swiatkowski * functions on the device must be able to reset when an EMP reset occurs from 4020545cc86SMichal Swiatkowski * any source. 4030545cc86SMichal Swiatkowski */ 4040545cc86SMichal Swiatkowski static int 4050545cc86SMichal Swiatkowski ice_devlink_reload_empr_start(struct ice_pf *pf, 4060545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 4070545cc86SMichal Swiatkowski { 4080545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 4090545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 4100545cc86SMichal Swiatkowski u8 pending; 4110545cc86SMichal Swiatkowski int err; 4120545cc86SMichal Swiatkowski 4130545cc86SMichal Swiatkowski err = ice_get_pending_updates(pf, &pending, extack); 4140545cc86SMichal Swiatkowski if (err) 4150545cc86SMichal Swiatkowski return err; 4160545cc86SMichal Swiatkowski 4170545cc86SMichal Swiatkowski /* pending is a bitmask of which flash banks have a pending update, 4180545cc86SMichal Swiatkowski * including the main NVM bank, the Option ROM bank, and the netlist 4190545cc86SMichal Swiatkowski * bank. If any of these bits are set, then there is a pending update 4200545cc86SMichal Swiatkowski * waiting to be activated. 4210545cc86SMichal Swiatkowski */ 4220545cc86SMichal Swiatkowski if (!pending) { 4230545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "No pending firmware update"); 4240545cc86SMichal Swiatkowski return -ECANCELED; 4250545cc86SMichal Swiatkowski } 4260545cc86SMichal Swiatkowski 4270545cc86SMichal Swiatkowski if (pf->fw_emp_reset_disabled) { 4280545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "EMP reset is not available. To activate firmware, a reboot or power cycle is needed"); 4290545cc86SMichal Swiatkowski return -ECANCELED; 4300545cc86SMichal Swiatkowski } 4310545cc86SMichal Swiatkowski 4320545cc86SMichal Swiatkowski dev_dbg(dev, "Issuing device EMP reset to activate firmware\n"); 4330545cc86SMichal Swiatkowski 4340545cc86SMichal Swiatkowski err = ice_aq_nvm_update_empr(hw); 4350545cc86SMichal Swiatkowski if (err) { 4360545cc86SMichal Swiatkowski dev_err(dev, "Failed to trigger EMP device reset to reload firmware, err %d aq_err %s\n", 4370545cc86SMichal Swiatkowski err, ice_aq_str(hw->adminq.sq_last_status)); 4380545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Failed to trigger EMP device reset to reload firmware"); 4390545cc86SMichal Swiatkowski return err; 4400545cc86SMichal Swiatkowski } 4410545cc86SMichal Swiatkowski 4420545cc86SMichal Swiatkowski return 0; 4430545cc86SMichal Swiatkowski } 4440545cc86SMichal Swiatkowski 4450545cc86SMichal Swiatkowski /** 4460545cc86SMichal Swiatkowski * ice_devlink_reinit_down - unload given PF 4470545cc86SMichal Swiatkowski * @pf: pointer to the PF struct 4480545cc86SMichal Swiatkowski */ 4490545cc86SMichal Swiatkowski static void ice_devlink_reinit_down(struct ice_pf *pf) 4500545cc86SMichal Swiatkowski { 4510545cc86SMichal Swiatkowski /* No need to take devl_lock, it's already taken by devlink API */ 4520545cc86SMichal Swiatkowski ice_unload(pf); 4530545cc86SMichal Swiatkowski rtnl_lock(); 4540545cc86SMichal Swiatkowski ice_vsi_decfg(ice_get_main_vsi(pf)); 4550545cc86SMichal Swiatkowski rtnl_unlock(); 4560545cc86SMichal Swiatkowski ice_deinit_dev(pf); 4570545cc86SMichal Swiatkowski } 4580545cc86SMichal Swiatkowski 4590545cc86SMichal Swiatkowski /** 4600545cc86SMichal Swiatkowski * ice_devlink_reload_down - prepare for reload 4610545cc86SMichal Swiatkowski * @devlink: pointer to the devlink instance to reload 4620545cc86SMichal Swiatkowski * @netns_change: if true, the network namespace is changing 4630545cc86SMichal Swiatkowski * @action: the action to perform 4640545cc86SMichal Swiatkowski * @limit: limits on what reload should do, such as not resetting 4650545cc86SMichal Swiatkowski * @extack: netlink extended ACK structure 4660545cc86SMichal Swiatkowski */ 4670545cc86SMichal Swiatkowski static int 4680545cc86SMichal Swiatkowski ice_devlink_reload_down(struct devlink *devlink, bool netns_change, 4690545cc86SMichal Swiatkowski enum devlink_reload_action action, 4700545cc86SMichal Swiatkowski enum devlink_reload_limit limit, 4710545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 4720545cc86SMichal Swiatkowski { 4730545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 4740545cc86SMichal Swiatkowski 4750545cc86SMichal Swiatkowski switch (action) { 4760545cc86SMichal Swiatkowski case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: 4770545cc86SMichal Swiatkowski if (ice_is_eswitch_mode_switchdev(pf)) { 4780545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, 4790545cc86SMichal Swiatkowski "Go to legacy mode before doing reinit"); 4800545cc86SMichal Swiatkowski return -EOPNOTSUPP; 4810545cc86SMichal Swiatkowski } 4820545cc86SMichal Swiatkowski if (ice_is_adq_active(pf)) { 4830545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, 4840545cc86SMichal Swiatkowski "Turn off ADQ before doing reinit"); 4850545cc86SMichal Swiatkowski return -EOPNOTSUPP; 4860545cc86SMichal Swiatkowski } 4870545cc86SMichal Swiatkowski if (ice_has_vfs(pf)) { 4880545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, 4890545cc86SMichal Swiatkowski "Remove all VFs before doing reinit"); 4900545cc86SMichal Swiatkowski return -EOPNOTSUPP; 4910545cc86SMichal Swiatkowski } 4920545cc86SMichal Swiatkowski ice_devlink_reinit_down(pf); 4930545cc86SMichal Swiatkowski return 0; 4940545cc86SMichal Swiatkowski case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: 4950545cc86SMichal Swiatkowski return ice_devlink_reload_empr_start(pf, extack); 4960545cc86SMichal Swiatkowski default: 4970545cc86SMichal Swiatkowski WARN_ON(1); 4980545cc86SMichal Swiatkowski return -EOPNOTSUPP; 4990545cc86SMichal Swiatkowski } 5000545cc86SMichal Swiatkowski } 5010545cc86SMichal Swiatkowski 5020545cc86SMichal Swiatkowski /** 5030545cc86SMichal Swiatkowski * ice_devlink_reload_empr_finish - Wait for EMP reset to finish 5040545cc86SMichal Swiatkowski * @pf: pointer to the pf instance 5050545cc86SMichal Swiatkowski * @extack: netlink extended ACK structure 5060545cc86SMichal Swiatkowski * 5070545cc86SMichal Swiatkowski * Wait for driver to finish rebuilding after EMP reset is completed. This 5080545cc86SMichal Swiatkowski * includes time to wait for both the actual device reset as well as the time 5090545cc86SMichal Swiatkowski * for the driver's rebuild to complete. 5100545cc86SMichal Swiatkowski */ 5110545cc86SMichal Swiatkowski static int 5120545cc86SMichal Swiatkowski ice_devlink_reload_empr_finish(struct ice_pf *pf, 5130545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 5140545cc86SMichal Swiatkowski { 5150545cc86SMichal Swiatkowski int err; 5160545cc86SMichal Swiatkowski 5170545cc86SMichal Swiatkowski err = ice_wait_for_reset(pf, 60 * HZ); 5180545cc86SMichal Swiatkowski if (err) { 5190545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Device still resetting after 1 minute"); 5200545cc86SMichal Swiatkowski return err; 5210545cc86SMichal Swiatkowski } 5220545cc86SMichal Swiatkowski 5230545cc86SMichal Swiatkowski return 0; 5240545cc86SMichal Swiatkowski } 5250545cc86SMichal Swiatkowski 5260545cc86SMichal Swiatkowski /** 527*109eb291SLukasz Czapnik * ice_get_tx_topo_user_sel - Read user's choice from flash 528*109eb291SLukasz Czapnik * @pf: pointer to pf structure 529*109eb291SLukasz Czapnik * @layers: value read from flash will be saved here 530*109eb291SLukasz Czapnik * 531*109eb291SLukasz Czapnik * Reads user's preference for Tx Scheduler Topology Tree from PFA TLV. 532*109eb291SLukasz Czapnik * 533*109eb291SLukasz Czapnik * Return: zero when read was successful, negative values otherwise. 534*109eb291SLukasz Czapnik */ 535*109eb291SLukasz Czapnik static int ice_get_tx_topo_user_sel(struct ice_pf *pf, uint8_t *layers) 536*109eb291SLukasz Czapnik { 537*109eb291SLukasz Czapnik struct ice_aqc_nvm_tx_topo_user_sel usr_sel = {}; 538*109eb291SLukasz Czapnik struct ice_hw *hw = &pf->hw; 539*109eb291SLukasz Czapnik int err; 540*109eb291SLukasz Czapnik 541*109eb291SLukasz Czapnik err = ice_acquire_nvm(hw, ICE_RES_READ); 542*109eb291SLukasz Czapnik if (err) 543*109eb291SLukasz Czapnik return err; 544*109eb291SLukasz Czapnik 545*109eb291SLukasz Czapnik err = ice_aq_read_nvm(hw, ICE_AQC_NVM_TX_TOPO_MOD_ID, 0, 546*109eb291SLukasz Czapnik sizeof(usr_sel), &usr_sel, true, true, NULL); 547*109eb291SLukasz Czapnik if (err) 548*109eb291SLukasz Czapnik goto exit_release_res; 549*109eb291SLukasz Czapnik 550*109eb291SLukasz Czapnik if (usr_sel.data & ICE_AQC_NVM_TX_TOPO_USER_SEL) 551*109eb291SLukasz Czapnik *layers = ICE_SCHED_5_LAYERS; 552*109eb291SLukasz Czapnik else 553*109eb291SLukasz Czapnik *layers = ICE_SCHED_9_LAYERS; 554*109eb291SLukasz Czapnik 555*109eb291SLukasz Czapnik exit_release_res: 556*109eb291SLukasz Czapnik ice_release_nvm(hw); 557*109eb291SLukasz Czapnik 558*109eb291SLukasz Czapnik return err; 559*109eb291SLukasz Czapnik } 560*109eb291SLukasz Czapnik 561*109eb291SLukasz Czapnik /** 562*109eb291SLukasz Czapnik * ice_update_tx_topo_user_sel - Save user's preference in flash 563*109eb291SLukasz Czapnik * @pf: pointer to pf structure 564*109eb291SLukasz Czapnik * @layers: value to be saved in flash 565*109eb291SLukasz Czapnik * 566*109eb291SLukasz Czapnik * Variable "layers" defines user's preference about number of layers in Tx 567*109eb291SLukasz Czapnik * Scheduler Topology Tree. This choice should be stored in PFA TLV field 568*109eb291SLukasz Czapnik * and be picked up by driver, next time during init. 569*109eb291SLukasz Czapnik * 570*109eb291SLukasz Czapnik * Return: zero when save was successful, negative values otherwise. 571*109eb291SLukasz Czapnik */ 572*109eb291SLukasz Czapnik static int ice_update_tx_topo_user_sel(struct ice_pf *pf, int layers) 573*109eb291SLukasz Czapnik { 574*109eb291SLukasz Czapnik struct ice_aqc_nvm_tx_topo_user_sel usr_sel = {}; 575*109eb291SLukasz Czapnik struct ice_hw *hw = &pf->hw; 576*109eb291SLukasz Czapnik int err; 577*109eb291SLukasz Czapnik 578*109eb291SLukasz Czapnik err = ice_acquire_nvm(hw, ICE_RES_WRITE); 579*109eb291SLukasz Czapnik if (err) 580*109eb291SLukasz Czapnik return err; 581*109eb291SLukasz Czapnik 582*109eb291SLukasz Czapnik err = ice_aq_read_nvm(hw, ICE_AQC_NVM_TX_TOPO_MOD_ID, 0, 583*109eb291SLukasz Czapnik sizeof(usr_sel), &usr_sel, true, true, NULL); 584*109eb291SLukasz Czapnik if (err) 585*109eb291SLukasz Czapnik goto exit_release_res; 586*109eb291SLukasz Czapnik 587*109eb291SLukasz Czapnik if (layers == ICE_SCHED_5_LAYERS) 588*109eb291SLukasz Czapnik usr_sel.data |= ICE_AQC_NVM_TX_TOPO_USER_SEL; 589*109eb291SLukasz Czapnik else 590*109eb291SLukasz Czapnik usr_sel.data &= ~ICE_AQC_NVM_TX_TOPO_USER_SEL; 591*109eb291SLukasz Czapnik 592*109eb291SLukasz Czapnik err = ice_write_one_nvm_block(pf, ICE_AQC_NVM_TX_TOPO_MOD_ID, 2, 593*109eb291SLukasz Czapnik sizeof(usr_sel.data), &usr_sel.data, 594*109eb291SLukasz Czapnik true, NULL, NULL); 595*109eb291SLukasz Czapnik exit_release_res: 596*109eb291SLukasz Czapnik ice_release_nvm(hw); 597*109eb291SLukasz Czapnik 598*109eb291SLukasz Czapnik return err; 599*109eb291SLukasz Czapnik } 600*109eb291SLukasz Czapnik 601*109eb291SLukasz Czapnik /** 602*109eb291SLukasz Czapnik * ice_devlink_tx_sched_layers_get - Get tx_scheduling_layers parameter 603*109eb291SLukasz Czapnik * @devlink: pointer to the devlink instance 604*109eb291SLukasz Czapnik * @id: the parameter ID to set 605*109eb291SLukasz Czapnik * @ctx: context to store the parameter value 606*109eb291SLukasz Czapnik * 607*109eb291SLukasz Czapnik * Return: zero on success and negative value on failure. 608*109eb291SLukasz Czapnik */ 609*109eb291SLukasz Czapnik static int ice_devlink_tx_sched_layers_get(struct devlink *devlink, u32 id, 610*109eb291SLukasz Czapnik struct devlink_param_gset_ctx *ctx) 611*109eb291SLukasz Czapnik { 612*109eb291SLukasz Czapnik struct ice_pf *pf = devlink_priv(devlink); 613*109eb291SLukasz Czapnik int err; 614*109eb291SLukasz Czapnik 615*109eb291SLukasz Czapnik err = ice_get_tx_topo_user_sel(pf, &ctx->val.vu8); 616*109eb291SLukasz Czapnik if (err) 617*109eb291SLukasz Czapnik return err; 618*109eb291SLukasz Czapnik 619*109eb291SLukasz Czapnik return 0; 620*109eb291SLukasz Czapnik } 621*109eb291SLukasz Czapnik 622*109eb291SLukasz Czapnik /** 623*109eb291SLukasz Czapnik * ice_devlink_tx_sched_layers_set - Set tx_scheduling_layers parameter 624*109eb291SLukasz Czapnik * @devlink: pointer to the devlink instance 625*109eb291SLukasz Czapnik * @id: the parameter ID to set 626*109eb291SLukasz Czapnik * @ctx: context to get the parameter value 627*109eb291SLukasz Czapnik * @extack: netlink extended ACK structure 628*109eb291SLukasz Czapnik * 629*109eb291SLukasz Czapnik * Return: zero on success and negative value on failure. 630*109eb291SLukasz Czapnik */ 631*109eb291SLukasz Czapnik static int ice_devlink_tx_sched_layers_set(struct devlink *devlink, u32 id, 632*109eb291SLukasz Czapnik struct devlink_param_gset_ctx *ctx, 633*109eb291SLukasz Czapnik struct netlink_ext_ack *extack) 634*109eb291SLukasz Czapnik { 635*109eb291SLukasz Czapnik struct ice_pf *pf = devlink_priv(devlink); 636*109eb291SLukasz Czapnik int err; 637*109eb291SLukasz Czapnik 638*109eb291SLukasz Czapnik err = ice_update_tx_topo_user_sel(pf, ctx->val.vu8); 639*109eb291SLukasz Czapnik if (err) 640*109eb291SLukasz Czapnik return err; 641*109eb291SLukasz Czapnik 642*109eb291SLukasz Czapnik NL_SET_ERR_MSG_MOD(extack, 643*109eb291SLukasz Czapnik "Tx scheduling layers have been changed on this device. You must do the PCI slot powercycle for the change to take effect."); 644*109eb291SLukasz Czapnik 645*109eb291SLukasz Czapnik return 0; 646*109eb291SLukasz Czapnik } 647*109eb291SLukasz Czapnik 648*109eb291SLukasz Czapnik /** 649*109eb291SLukasz Czapnik * ice_devlink_tx_sched_layers_validate - Validate passed tx_scheduling_layers 650*109eb291SLukasz Czapnik * parameter value 651*109eb291SLukasz Czapnik * @devlink: unused pointer to devlink instance 652*109eb291SLukasz Czapnik * @id: the parameter ID to validate 653*109eb291SLukasz Czapnik * @val: value to validate 654*109eb291SLukasz Czapnik * @extack: netlink extended ACK structure 655*109eb291SLukasz Czapnik * 656*109eb291SLukasz Czapnik * Supported values are: 657*109eb291SLukasz Czapnik * - 5 - five layers Tx Scheduler Topology Tree 658*109eb291SLukasz Czapnik * - 9 - nine layers Tx Scheduler Topology Tree 659*109eb291SLukasz Czapnik * 660*109eb291SLukasz Czapnik * Return: zero when passed parameter value is supported. Negative value on 661*109eb291SLukasz Czapnik * error. 662*109eb291SLukasz Czapnik */ 663*109eb291SLukasz Czapnik static int ice_devlink_tx_sched_layers_validate(struct devlink *devlink, u32 id, 664*109eb291SLukasz Czapnik union devlink_param_value val, 665*109eb291SLukasz Czapnik struct netlink_ext_ack *extack) 666*109eb291SLukasz Czapnik { 667*109eb291SLukasz Czapnik if (val.vu8 != ICE_SCHED_5_LAYERS && val.vu8 != ICE_SCHED_9_LAYERS) { 668*109eb291SLukasz Czapnik NL_SET_ERR_MSG_MOD(extack, 669*109eb291SLukasz Czapnik "Wrong number of tx scheduler layers provided."); 670*109eb291SLukasz Czapnik return -EINVAL; 671*109eb291SLukasz Czapnik } 672*109eb291SLukasz Czapnik 673*109eb291SLukasz Czapnik return 0; 674*109eb291SLukasz Czapnik } 675*109eb291SLukasz Czapnik 676*109eb291SLukasz Czapnik /** 6770545cc86SMichal Swiatkowski * ice_tear_down_devlink_rate_tree - removes devlink-rate exported tree 6780545cc86SMichal Swiatkowski * @pf: pf struct 6790545cc86SMichal Swiatkowski * 6800545cc86SMichal Swiatkowski * This function tears down tree exported during VF's creation. 6810545cc86SMichal Swiatkowski */ 6820545cc86SMichal Swiatkowski void ice_tear_down_devlink_rate_tree(struct ice_pf *pf) 6830545cc86SMichal Swiatkowski { 6840545cc86SMichal Swiatkowski struct devlink *devlink; 6850545cc86SMichal Swiatkowski struct ice_vf *vf; 6860545cc86SMichal Swiatkowski unsigned int bkt; 6870545cc86SMichal Swiatkowski 6880545cc86SMichal Swiatkowski devlink = priv_to_devlink(pf); 6890545cc86SMichal Swiatkowski 6900545cc86SMichal Swiatkowski devl_lock(devlink); 6910545cc86SMichal Swiatkowski mutex_lock(&pf->vfs.table_lock); 6920545cc86SMichal Swiatkowski ice_for_each_vf(pf, bkt, vf) { 6930545cc86SMichal Swiatkowski if (vf->devlink_port.devlink_rate) 6940545cc86SMichal Swiatkowski devl_rate_leaf_destroy(&vf->devlink_port); 6950545cc86SMichal Swiatkowski } 6960545cc86SMichal Swiatkowski mutex_unlock(&pf->vfs.table_lock); 6970545cc86SMichal Swiatkowski 6980545cc86SMichal Swiatkowski devl_rate_nodes_destroy(devlink); 6990545cc86SMichal Swiatkowski devl_unlock(devlink); 7000545cc86SMichal Swiatkowski } 7010545cc86SMichal Swiatkowski 7020545cc86SMichal Swiatkowski /** 7030545cc86SMichal Swiatkowski * ice_enable_custom_tx - try to enable custom Tx feature 7040545cc86SMichal Swiatkowski * @pf: pf struct 7050545cc86SMichal Swiatkowski * 7060545cc86SMichal Swiatkowski * This function tries to enable custom Tx feature, 7070545cc86SMichal Swiatkowski * it's not possible to enable it, if DCB or ADQ is active. 7080545cc86SMichal Swiatkowski */ 7090545cc86SMichal Swiatkowski static bool ice_enable_custom_tx(struct ice_pf *pf) 7100545cc86SMichal Swiatkowski { 7110545cc86SMichal Swiatkowski struct ice_port_info *pi = ice_get_main_vsi(pf)->port_info; 7120545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 7130545cc86SMichal Swiatkowski 7140545cc86SMichal Swiatkowski if (pi->is_custom_tx_enabled) 7150545cc86SMichal Swiatkowski /* already enabled, return true */ 7160545cc86SMichal Swiatkowski return true; 7170545cc86SMichal Swiatkowski 7180545cc86SMichal Swiatkowski if (ice_is_adq_active(pf)) { 7190545cc86SMichal Swiatkowski dev_err(dev, "ADQ active, can't modify Tx scheduler tree\n"); 7200545cc86SMichal Swiatkowski return false; 7210545cc86SMichal Swiatkowski } 7220545cc86SMichal Swiatkowski 7230545cc86SMichal Swiatkowski if (ice_is_dcb_active(pf)) { 7240545cc86SMichal Swiatkowski dev_err(dev, "DCB active, can't modify Tx scheduler tree\n"); 7250545cc86SMichal Swiatkowski return false; 7260545cc86SMichal Swiatkowski } 7270545cc86SMichal Swiatkowski 7280545cc86SMichal Swiatkowski pi->is_custom_tx_enabled = true; 7290545cc86SMichal Swiatkowski 7300545cc86SMichal Swiatkowski return true; 7310545cc86SMichal Swiatkowski } 7320545cc86SMichal Swiatkowski 7330545cc86SMichal Swiatkowski /** 7340545cc86SMichal Swiatkowski * ice_traverse_tx_tree - traverse Tx scheduler tree 7350545cc86SMichal Swiatkowski * @devlink: devlink struct 7360545cc86SMichal Swiatkowski * @node: current node, used for recursion 7370545cc86SMichal Swiatkowski * @tc_node: tc_node struct, that is treated as a root 7380545cc86SMichal Swiatkowski * @pf: pf struct 7390545cc86SMichal Swiatkowski * 7400545cc86SMichal Swiatkowski * This function traverses Tx scheduler tree and exports 7410545cc86SMichal Swiatkowski * entire structure to the devlink-rate. 7420545cc86SMichal Swiatkowski */ 7430545cc86SMichal Swiatkowski static void ice_traverse_tx_tree(struct devlink *devlink, struct ice_sched_node *node, 7440545cc86SMichal Swiatkowski struct ice_sched_node *tc_node, struct ice_pf *pf) 7450545cc86SMichal Swiatkowski { 7460545cc86SMichal Swiatkowski struct devlink_rate *rate_node = NULL; 7470545cc86SMichal Swiatkowski struct ice_vf *vf; 7480545cc86SMichal Swiatkowski int i; 7490545cc86SMichal Swiatkowski 7500545cc86SMichal Swiatkowski if (node->rate_node) 7510545cc86SMichal Swiatkowski /* already added, skip to the next */ 7520545cc86SMichal Swiatkowski goto traverse_children; 7530545cc86SMichal Swiatkowski 7540545cc86SMichal Swiatkowski if (node->parent == tc_node) { 7550545cc86SMichal Swiatkowski /* create root node */ 7560545cc86SMichal Swiatkowski rate_node = devl_rate_node_create(devlink, node, node->name, NULL); 7570545cc86SMichal Swiatkowski } else if (node->vsi_handle && 7580545cc86SMichal Swiatkowski pf->vsi[node->vsi_handle]->vf) { 7590545cc86SMichal Swiatkowski vf = pf->vsi[node->vsi_handle]->vf; 7600545cc86SMichal Swiatkowski if (!vf->devlink_port.devlink_rate) 7610545cc86SMichal Swiatkowski /* leaf nodes doesn't have children 7620545cc86SMichal Swiatkowski * so we don't set rate_node 7630545cc86SMichal Swiatkowski */ 7640545cc86SMichal Swiatkowski devl_rate_leaf_create(&vf->devlink_port, node, 7650545cc86SMichal Swiatkowski node->parent->rate_node); 7660545cc86SMichal Swiatkowski } else if (node->info.data.elem_type != ICE_AQC_ELEM_TYPE_LEAF && 7670545cc86SMichal Swiatkowski node->parent->rate_node) { 7680545cc86SMichal Swiatkowski rate_node = devl_rate_node_create(devlink, node, node->name, 7690545cc86SMichal Swiatkowski node->parent->rate_node); 7700545cc86SMichal Swiatkowski } 7710545cc86SMichal Swiatkowski 7720545cc86SMichal Swiatkowski if (rate_node && !IS_ERR(rate_node)) 7730545cc86SMichal Swiatkowski node->rate_node = rate_node; 7740545cc86SMichal Swiatkowski 7750545cc86SMichal Swiatkowski traverse_children: 7760545cc86SMichal Swiatkowski for (i = 0; i < node->num_children; i++) 7770545cc86SMichal Swiatkowski ice_traverse_tx_tree(devlink, node->children[i], tc_node, pf); 7780545cc86SMichal Swiatkowski } 7790545cc86SMichal Swiatkowski 7800545cc86SMichal Swiatkowski /** 7810545cc86SMichal Swiatkowski * ice_devlink_rate_init_tx_topology - export Tx scheduler tree to devlink rate 7820545cc86SMichal Swiatkowski * @devlink: devlink struct 7830545cc86SMichal Swiatkowski * @vsi: main vsi struct 7840545cc86SMichal Swiatkowski * 7850545cc86SMichal Swiatkowski * This function finds a root node, then calls ice_traverse_tx tree, which 7860545cc86SMichal Swiatkowski * traverses the tree and exports it's contents to devlink rate. 7870545cc86SMichal Swiatkowski */ 7880545cc86SMichal Swiatkowski int ice_devlink_rate_init_tx_topology(struct devlink *devlink, struct ice_vsi *vsi) 7890545cc86SMichal Swiatkowski { 7900545cc86SMichal Swiatkowski struct ice_port_info *pi = vsi->port_info; 7910545cc86SMichal Swiatkowski struct ice_sched_node *tc_node; 7920545cc86SMichal Swiatkowski struct ice_pf *pf = vsi->back; 7930545cc86SMichal Swiatkowski int i; 7940545cc86SMichal Swiatkowski 7950545cc86SMichal Swiatkowski tc_node = pi->root->children[0]; 7960545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 7970545cc86SMichal Swiatkowski devl_lock(devlink); 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 devl_unlock(devlink); 8010545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 8020545cc86SMichal Swiatkowski 8030545cc86SMichal Swiatkowski return 0; 8040545cc86SMichal Swiatkowski } 8050545cc86SMichal Swiatkowski 8060545cc86SMichal Swiatkowski static void ice_clear_rate_nodes(struct ice_sched_node *node) 8070545cc86SMichal Swiatkowski { 8080545cc86SMichal Swiatkowski node->rate_node = NULL; 8090545cc86SMichal Swiatkowski 8100545cc86SMichal Swiatkowski for (int i = 0; i < node->num_children; i++) 8110545cc86SMichal Swiatkowski ice_clear_rate_nodes(node->children[i]); 8120545cc86SMichal Swiatkowski } 8130545cc86SMichal Swiatkowski 8140545cc86SMichal Swiatkowski /** 8150545cc86SMichal Swiatkowski * ice_devlink_rate_clear_tx_topology - clear node->rate_node 8160545cc86SMichal Swiatkowski * @vsi: main vsi struct 8170545cc86SMichal Swiatkowski * 8180545cc86SMichal Swiatkowski * Clear rate_node to cleanup creation of Tx topology. 8190545cc86SMichal Swiatkowski * 8200545cc86SMichal Swiatkowski */ 8210545cc86SMichal Swiatkowski void ice_devlink_rate_clear_tx_topology(struct ice_vsi *vsi) 8220545cc86SMichal Swiatkowski { 8230545cc86SMichal Swiatkowski struct ice_port_info *pi = vsi->port_info; 8240545cc86SMichal Swiatkowski 8250545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 8260545cc86SMichal Swiatkowski ice_clear_rate_nodes(pi->root->children[0]); 8270545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 8280545cc86SMichal Swiatkowski } 8290545cc86SMichal Swiatkowski 8300545cc86SMichal Swiatkowski /** 8310545cc86SMichal Swiatkowski * ice_set_object_tx_share - sets node scheduling parameter 8320545cc86SMichal Swiatkowski * @pi: devlink struct instance 8330545cc86SMichal Swiatkowski * @node: node struct instance 8340545cc86SMichal Swiatkowski * @bw: bandwidth in bytes per second 8350545cc86SMichal Swiatkowski * @extack: extended netdev ack structure 8360545cc86SMichal Swiatkowski * 8370545cc86SMichal Swiatkowski * This function sets ICE_MIN_BW scheduling BW limit. 8380545cc86SMichal Swiatkowski */ 8390545cc86SMichal Swiatkowski static int ice_set_object_tx_share(struct ice_port_info *pi, struct ice_sched_node *node, 8400545cc86SMichal Swiatkowski u64 bw, struct netlink_ext_ack *extack) 8410545cc86SMichal Swiatkowski { 8420545cc86SMichal Swiatkowski int status; 8430545cc86SMichal Swiatkowski 8440545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 8450545cc86SMichal Swiatkowski /* converts bytes per second to kilo bits per second */ 8460545cc86SMichal Swiatkowski node->tx_share = div_u64(bw, 125); 8470545cc86SMichal Swiatkowski status = ice_sched_set_node_bw_lmt(pi, node, ICE_MIN_BW, node->tx_share); 8480545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 8490545cc86SMichal Swiatkowski 8500545cc86SMichal Swiatkowski if (status) 8510545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Can't set scheduling node tx_share"); 8520545cc86SMichal Swiatkowski 8530545cc86SMichal Swiatkowski return status; 8540545cc86SMichal Swiatkowski } 8550545cc86SMichal Swiatkowski 8560545cc86SMichal Swiatkowski /** 8570545cc86SMichal Swiatkowski * ice_set_object_tx_max - sets node scheduling parameter 8580545cc86SMichal Swiatkowski * @pi: devlink struct instance 8590545cc86SMichal Swiatkowski * @node: node struct instance 8600545cc86SMichal Swiatkowski * @bw: bandwidth in bytes per second 8610545cc86SMichal Swiatkowski * @extack: extended netdev ack structure 8620545cc86SMichal Swiatkowski * 8630545cc86SMichal Swiatkowski * This function sets ICE_MAX_BW scheduling BW limit. 8640545cc86SMichal Swiatkowski */ 8650545cc86SMichal Swiatkowski static int ice_set_object_tx_max(struct ice_port_info *pi, struct ice_sched_node *node, 8660545cc86SMichal Swiatkowski u64 bw, struct netlink_ext_ack *extack) 8670545cc86SMichal Swiatkowski { 8680545cc86SMichal Swiatkowski int status; 8690545cc86SMichal Swiatkowski 8700545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 8710545cc86SMichal Swiatkowski /* converts bytes per second value to kilo bits per second */ 8720545cc86SMichal Swiatkowski node->tx_max = div_u64(bw, 125); 8730545cc86SMichal Swiatkowski status = ice_sched_set_node_bw_lmt(pi, node, ICE_MAX_BW, node->tx_max); 8740545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 8750545cc86SMichal Swiatkowski 8760545cc86SMichal Swiatkowski if (status) 8770545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Can't set scheduling node tx_max"); 8780545cc86SMichal Swiatkowski 8790545cc86SMichal Swiatkowski return status; 8800545cc86SMichal Swiatkowski } 8810545cc86SMichal Swiatkowski 8820545cc86SMichal Swiatkowski /** 8830545cc86SMichal Swiatkowski * ice_set_object_tx_priority - sets node scheduling parameter 8840545cc86SMichal Swiatkowski * @pi: devlink struct instance 8850545cc86SMichal Swiatkowski * @node: node struct instance 8860545cc86SMichal Swiatkowski * @priority: value representing priority for strict priority arbitration 8870545cc86SMichal Swiatkowski * @extack: extended netdev ack structure 8880545cc86SMichal Swiatkowski * 8890545cc86SMichal Swiatkowski * This function sets priority of node among siblings. 8900545cc86SMichal Swiatkowski */ 8910545cc86SMichal Swiatkowski static int ice_set_object_tx_priority(struct ice_port_info *pi, struct ice_sched_node *node, 8920545cc86SMichal Swiatkowski u32 priority, struct netlink_ext_ack *extack) 8930545cc86SMichal Swiatkowski { 8940545cc86SMichal Swiatkowski int status; 8950545cc86SMichal Swiatkowski 8960545cc86SMichal Swiatkowski if (priority >= 8) { 8970545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Priority should be less than 8"); 8980545cc86SMichal Swiatkowski return -EINVAL; 8990545cc86SMichal Swiatkowski } 9000545cc86SMichal Swiatkowski 9010545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 9020545cc86SMichal Swiatkowski node->tx_priority = priority; 9030545cc86SMichal Swiatkowski status = ice_sched_set_node_priority(pi, node, node->tx_priority); 9040545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 9050545cc86SMichal Swiatkowski 9060545cc86SMichal Swiatkowski if (status) 9070545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Can't set scheduling node tx_priority"); 9080545cc86SMichal Swiatkowski 9090545cc86SMichal Swiatkowski return status; 9100545cc86SMichal Swiatkowski } 9110545cc86SMichal Swiatkowski 9120545cc86SMichal Swiatkowski /** 9130545cc86SMichal Swiatkowski * ice_set_object_tx_weight - sets node scheduling parameter 9140545cc86SMichal Swiatkowski * @pi: devlink struct instance 9150545cc86SMichal Swiatkowski * @node: node struct instance 9160545cc86SMichal Swiatkowski * @weight: value represeting relative weight for WFQ arbitration 9170545cc86SMichal Swiatkowski * @extack: extended netdev ack structure 9180545cc86SMichal Swiatkowski * 9190545cc86SMichal Swiatkowski * This function sets node weight for WFQ algorithm. 9200545cc86SMichal Swiatkowski */ 9210545cc86SMichal Swiatkowski static int ice_set_object_tx_weight(struct ice_port_info *pi, struct ice_sched_node *node, 9220545cc86SMichal Swiatkowski u32 weight, struct netlink_ext_ack *extack) 9230545cc86SMichal Swiatkowski { 9240545cc86SMichal Swiatkowski int status; 9250545cc86SMichal Swiatkowski 9260545cc86SMichal Swiatkowski if (weight > 200 || weight < 1) { 9270545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Weight must be between 1 and 200"); 9280545cc86SMichal Swiatkowski return -EINVAL; 9290545cc86SMichal Swiatkowski } 9300545cc86SMichal Swiatkowski 9310545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 9320545cc86SMichal Swiatkowski node->tx_weight = weight; 9330545cc86SMichal Swiatkowski status = ice_sched_set_node_weight(pi, node, node->tx_weight); 9340545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 9350545cc86SMichal Swiatkowski 9360545cc86SMichal Swiatkowski if (status) 9370545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Can't set scheduling node tx_weight"); 9380545cc86SMichal Swiatkowski 9390545cc86SMichal Swiatkowski return status; 9400545cc86SMichal Swiatkowski } 9410545cc86SMichal Swiatkowski 9420545cc86SMichal Swiatkowski /** 9430545cc86SMichal Swiatkowski * ice_get_pi_from_dev_rate - get port info from devlink_rate 9440545cc86SMichal Swiatkowski * @rate_node: devlink struct instance 9450545cc86SMichal Swiatkowski * 9460545cc86SMichal Swiatkowski * This function returns corresponding port_info struct of devlink_rate 9470545cc86SMichal Swiatkowski */ 9480545cc86SMichal Swiatkowski static struct ice_port_info *ice_get_pi_from_dev_rate(struct devlink_rate *rate_node) 9490545cc86SMichal Swiatkowski { 9500545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(rate_node->devlink); 9510545cc86SMichal Swiatkowski 9520545cc86SMichal Swiatkowski return ice_get_main_vsi(pf)->port_info; 9530545cc86SMichal Swiatkowski } 9540545cc86SMichal Swiatkowski 9550545cc86SMichal Swiatkowski static int ice_devlink_rate_node_new(struct devlink_rate *rate_node, void **priv, 9560545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 9570545cc86SMichal Swiatkowski { 9580545cc86SMichal Swiatkowski struct ice_sched_node *node; 9590545cc86SMichal Swiatkowski struct ice_port_info *pi; 9600545cc86SMichal Swiatkowski 9610545cc86SMichal Swiatkowski pi = ice_get_pi_from_dev_rate(rate_node); 9620545cc86SMichal Swiatkowski 9630545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink))) 9640545cc86SMichal Swiatkowski return -EBUSY; 9650545cc86SMichal Swiatkowski 9660545cc86SMichal Swiatkowski /* preallocate memory for ice_sched_node */ 9670545cc86SMichal Swiatkowski node = devm_kzalloc(ice_hw_to_dev(pi->hw), sizeof(*node), GFP_KERNEL); 9680545cc86SMichal Swiatkowski *priv = node; 9690545cc86SMichal Swiatkowski 9700545cc86SMichal Swiatkowski return 0; 9710545cc86SMichal Swiatkowski } 9720545cc86SMichal Swiatkowski 9730545cc86SMichal Swiatkowski static int ice_devlink_rate_node_del(struct devlink_rate *rate_node, void *priv, 9740545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 9750545cc86SMichal Swiatkowski { 9760545cc86SMichal Swiatkowski struct ice_sched_node *node, *tc_node; 9770545cc86SMichal Swiatkowski struct ice_port_info *pi; 9780545cc86SMichal Swiatkowski 9790545cc86SMichal Swiatkowski pi = ice_get_pi_from_dev_rate(rate_node); 9800545cc86SMichal Swiatkowski tc_node = pi->root->children[0]; 9810545cc86SMichal Swiatkowski node = priv; 9820545cc86SMichal Swiatkowski 9830545cc86SMichal Swiatkowski if (!rate_node->parent || !node || tc_node == node || !extack) 9840545cc86SMichal Swiatkowski return 0; 9850545cc86SMichal Swiatkowski 9860545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink))) 9870545cc86SMichal Swiatkowski return -EBUSY; 9880545cc86SMichal Swiatkowski 9890545cc86SMichal Swiatkowski /* can't allow to delete a node with children */ 9900545cc86SMichal Swiatkowski if (node->num_children) 9910545cc86SMichal Swiatkowski return -EINVAL; 9920545cc86SMichal Swiatkowski 9930545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 9940545cc86SMichal Swiatkowski ice_free_sched_node(pi, node); 9950545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 9960545cc86SMichal Swiatkowski 9970545cc86SMichal Swiatkowski return 0; 9980545cc86SMichal Swiatkowski } 9990545cc86SMichal Swiatkowski 10000545cc86SMichal Swiatkowski static int ice_devlink_rate_leaf_tx_max_set(struct devlink_rate *rate_leaf, void *priv, 10010545cc86SMichal Swiatkowski u64 tx_max, struct netlink_ext_ack *extack) 10020545cc86SMichal Swiatkowski { 10030545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 10040545cc86SMichal Swiatkowski 10050545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_leaf->devlink))) 10060545cc86SMichal Swiatkowski return -EBUSY; 10070545cc86SMichal Swiatkowski 10080545cc86SMichal Swiatkowski if (!node) 10090545cc86SMichal Swiatkowski return 0; 10100545cc86SMichal Swiatkowski 10110545cc86SMichal Swiatkowski return ice_set_object_tx_max(ice_get_pi_from_dev_rate(rate_leaf), 10120545cc86SMichal Swiatkowski node, tx_max, extack); 10130545cc86SMichal Swiatkowski } 10140545cc86SMichal Swiatkowski 10150545cc86SMichal Swiatkowski static int ice_devlink_rate_leaf_tx_share_set(struct devlink_rate *rate_leaf, void *priv, 10160545cc86SMichal Swiatkowski u64 tx_share, struct netlink_ext_ack *extack) 10170545cc86SMichal Swiatkowski { 10180545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 10190545cc86SMichal Swiatkowski 10200545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_leaf->devlink))) 10210545cc86SMichal Swiatkowski return -EBUSY; 10220545cc86SMichal Swiatkowski 10230545cc86SMichal Swiatkowski if (!node) 10240545cc86SMichal Swiatkowski return 0; 10250545cc86SMichal Swiatkowski 10260545cc86SMichal Swiatkowski return ice_set_object_tx_share(ice_get_pi_from_dev_rate(rate_leaf), node, 10270545cc86SMichal Swiatkowski tx_share, extack); 10280545cc86SMichal Swiatkowski } 10290545cc86SMichal Swiatkowski 10300545cc86SMichal Swiatkowski static int ice_devlink_rate_leaf_tx_priority_set(struct devlink_rate *rate_leaf, void *priv, 10310545cc86SMichal Swiatkowski u32 tx_priority, struct netlink_ext_ack *extack) 10320545cc86SMichal Swiatkowski { 10330545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 10340545cc86SMichal Swiatkowski 10350545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_leaf->devlink))) 10360545cc86SMichal Swiatkowski return -EBUSY; 10370545cc86SMichal Swiatkowski 10380545cc86SMichal Swiatkowski if (!node) 10390545cc86SMichal Swiatkowski return 0; 10400545cc86SMichal Swiatkowski 10410545cc86SMichal Swiatkowski return ice_set_object_tx_priority(ice_get_pi_from_dev_rate(rate_leaf), node, 10420545cc86SMichal Swiatkowski tx_priority, extack); 10430545cc86SMichal Swiatkowski } 10440545cc86SMichal Swiatkowski 10450545cc86SMichal Swiatkowski static int ice_devlink_rate_leaf_tx_weight_set(struct devlink_rate *rate_leaf, void *priv, 10460545cc86SMichal Swiatkowski u32 tx_weight, struct netlink_ext_ack *extack) 10470545cc86SMichal Swiatkowski { 10480545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 10490545cc86SMichal Swiatkowski 10500545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_leaf->devlink))) 10510545cc86SMichal Swiatkowski return -EBUSY; 10520545cc86SMichal Swiatkowski 10530545cc86SMichal Swiatkowski if (!node) 10540545cc86SMichal Swiatkowski return 0; 10550545cc86SMichal Swiatkowski 10560545cc86SMichal Swiatkowski return ice_set_object_tx_weight(ice_get_pi_from_dev_rate(rate_leaf), node, 10570545cc86SMichal Swiatkowski tx_weight, extack); 10580545cc86SMichal Swiatkowski } 10590545cc86SMichal Swiatkowski 10600545cc86SMichal Swiatkowski static int ice_devlink_rate_node_tx_max_set(struct devlink_rate *rate_node, void *priv, 10610545cc86SMichal Swiatkowski u64 tx_max, struct netlink_ext_ack *extack) 10620545cc86SMichal Swiatkowski { 10630545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 10640545cc86SMichal Swiatkowski 10650545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink))) 10660545cc86SMichal Swiatkowski return -EBUSY; 10670545cc86SMichal Swiatkowski 10680545cc86SMichal Swiatkowski if (!node) 10690545cc86SMichal Swiatkowski return 0; 10700545cc86SMichal Swiatkowski 10710545cc86SMichal Swiatkowski return ice_set_object_tx_max(ice_get_pi_from_dev_rate(rate_node), 10720545cc86SMichal Swiatkowski node, tx_max, extack); 10730545cc86SMichal Swiatkowski } 10740545cc86SMichal Swiatkowski 10750545cc86SMichal Swiatkowski static int ice_devlink_rate_node_tx_share_set(struct devlink_rate *rate_node, void *priv, 10760545cc86SMichal Swiatkowski u64 tx_share, struct netlink_ext_ack *extack) 10770545cc86SMichal Swiatkowski { 10780545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 10790545cc86SMichal Swiatkowski 10800545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink))) 10810545cc86SMichal Swiatkowski return -EBUSY; 10820545cc86SMichal Swiatkowski 10830545cc86SMichal Swiatkowski if (!node) 10840545cc86SMichal Swiatkowski return 0; 10850545cc86SMichal Swiatkowski 10860545cc86SMichal Swiatkowski return ice_set_object_tx_share(ice_get_pi_from_dev_rate(rate_node), 10870545cc86SMichal Swiatkowski node, tx_share, extack); 10880545cc86SMichal Swiatkowski } 10890545cc86SMichal Swiatkowski 10900545cc86SMichal Swiatkowski static int ice_devlink_rate_node_tx_priority_set(struct devlink_rate *rate_node, void *priv, 10910545cc86SMichal Swiatkowski u32 tx_priority, struct netlink_ext_ack *extack) 10920545cc86SMichal Swiatkowski { 10930545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 10940545cc86SMichal Swiatkowski 10950545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink))) 10960545cc86SMichal Swiatkowski return -EBUSY; 10970545cc86SMichal Swiatkowski 10980545cc86SMichal Swiatkowski if (!node) 10990545cc86SMichal Swiatkowski return 0; 11000545cc86SMichal Swiatkowski 11010545cc86SMichal Swiatkowski return ice_set_object_tx_priority(ice_get_pi_from_dev_rate(rate_node), 11020545cc86SMichal Swiatkowski node, tx_priority, extack); 11030545cc86SMichal Swiatkowski } 11040545cc86SMichal Swiatkowski 11050545cc86SMichal Swiatkowski static int ice_devlink_rate_node_tx_weight_set(struct devlink_rate *rate_node, void *priv, 11060545cc86SMichal Swiatkowski u32 tx_weight, struct netlink_ext_ack *extack) 11070545cc86SMichal Swiatkowski { 11080545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 11090545cc86SMichal Swiatkowski 11100545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink))) 11110545cc86SMichal Swiatkowski return -EBUSY; 11120545cc86SMichal Swiatkowski 11130545cc86SMichal Swiatkowski if (!node) 11140545cc86SMichal Swiatkowski return 0; 11150545cc86SMichal Swiatkowski 11160545cc86SMichal Swiatkowski return ice_set_object_tx_weight(ice_get_pi_from_dev_rate(rate_node), 11170545cc86SMichal Swiatkowski node, tx_weight, extack); 11180545cc86SMichal Swiatkowski } 11190545cc86SMichal Swiatkowski 11200545cc86SMichal Swiatkowski static int ice_devlink_set_parent(struct devlink_rate *devlink_rate, 11210545cc86SMichal Swiatkowski struct devlink_rate *parent, 11220545cc86SMichal Swiatkowski void *priv, void *parent_priv, 11230545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 11240545cc86SMichal Swiatkowski { 11250545cc86SMichal Swiatkowski struct ice_port_info *pi = ice_get_pi_from_dev_rate(devlink_rate); 11260545cc86SMichal Swiatkowski struct ice_sched_node *tc_node, *node, *parent_node; 11270545cc86SMichal Swiatkowski u16 num_nodes_added; 11280545cc86SMichal Swiatkowski u32 first_node_teid; 11290545cc86SMichal Swiatkowski u32 node_teid; 11300545cc86SMichal Swiatkowski int status; 11310545cc86SMichal Swiatkowski 11320545cc86SMichal Swiatkowski tc_node = pi->root->children[0]; 11330545cc86SMichal Swiatkowski node = priv; 11340545cc86SMichal Swiatkowski 11350545cc86SMichal Swiatkowski if (!extack) 11360545cc86SMichal Swiatkowski return 0; 11370545cc86SMichal Swiatkowski 11380545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(devlink_rate->devlink))) 11390545cc86SMichal Swiatkowski return -EBUSY; 11400545cc86SMichal Swiatkowski 11410545cc86SMichal Swiatkowski if (!parent) { 11420545cc86SMichal Swiatkowski if (!node || tc_node == node || node->num_children) 11430545cc86SMichal Swiatkowski return -EINVAL; 11440545cc86SMichal Swiatkowski 11450545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 11460545cc86SMichal Swiatkowski ice_free_sched_node(pi, node); 11470545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 11480545cc86SMichal Swiatkowski 11490545cc86SMichal Swiatkowski return 0; 11500545cc86SMichal Swiatkowski } 11510545cc86SMichal Swiatkowski 11520545cc86SMichal Swiatkowski parent_node = parent_priv; 11530545cc86SMichal Swiatkowski 11540545cc86SMichal Swiatkowski /* if the node doesn't exist, create it */ 11550545cc86SMichal Swiatkowski if (!node->parent) { 11560545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 11570545cc86SMichal Swiatkowski status = ice_sched_add_elems(pi, tc_node, parent_node, 11580545cc86SMichal Swiatkowski parent_node->tx_sched_layer + 1, 11590545cc86SMichal Swiatkowski 1, &num_nodes_added, &first_node_teid, 11600545cc86SMichal Swiatkowski &node); 11610545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 11620545cc86SMichal Swiatkowski 11630545cc86SMichal Swiatkowski if (status) { 11640545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Can't add a new node"); 11650545cc86SMichal Swiatkowski return status; 11660545cc86SMichal Swiatkowski } 11670545cc86SMichal Swiatkowski 11680545cc86SMichal Swiatkowski if (devlink_rate->tx_share) 11690545cc86SMichal Swiatkowski ice_set_object_tx_share(pi, node, devlink_rate->tx_share, extack); 11700545cc86SMichal Swiatkowski if (devlink_rate->tx_max) 11710545cc86SMichal Swiatkowski ice_set_object_tx_max(pi, node, devlink_rate->tx_max, extack); 11720545cc86SMichal Swiatkowski if (devlink_rate->tx_priority) 11730545cc86SMichal Swiatkowski ice_set_object_tx_priority(pi, node, devlink_rate->tx_priority, extack); 11740545cc86SMichal Swiatkowski if (devlink_rate->tx_weight) 11750545cc86SMichal Swiatkowski ice_set_object_tx_weight(pi, node, devlink_rate->tx_weight, extack); 11760545cc86SMichal Swiatkowski } else { 11770545cc86SMichal Swiatkowski node_teid = le32_to_cpu(node->info.node_teid); 11780545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 11790545cc86SMichal Swiatkowski status = ice_sched_move_nodes(pi, parent_node, 1, &node_teid); 11800545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 11810545cc86SMichal Swiatkowski 11820545cc86SMichal Swiatkowski if (status) 11830545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Can't move existing node to a new parent"); 11840545cc86SMichal Swiatkowski } 11850545cc86SMichal Swiatkowski 11860545cc86SMichal Swiatkowski return status; 11870545cc86SMichal Swiatkowski } 11880545cc86SMichal Swiatkowski 11890545cc86SMichal Swiatkowski /** 11900545cc86SMichal Swiatkowski * ice_devlink_reinit_up - do reinit of the given PF 11910545cc86SMichal Swiatkowski * @pf: pointer to the PF struct 11920545cc86SMichal Swiatkowski */ 11930545cc86SMichal Swiatkowski static int ice_devlink_reinit_up(struct ice_pf *pf) 11940545cc86SMichal Swiatkowski { 11950545cc86SMichal Swiatkowski struct ice_vsi *vsi = ice_get_main_vsi(pf); 11960545cc86SMichal Swiatkowski struct ice_vsi_cfg_params params; 11970545cc86SMichal Swiatkowski int err; 11980545cc86SMichal Swiatkowski 11990545cc86SMichal Swiatkowski err = ice_init_dev(pf); 12000545cc86SMichal Swiatkowski if (err) 12010545cc86SMichal Swiatkowski return err; 12020545cc86SMichal Swiatkowski 12030545cc86SMichal Swiatkowski params = ice_vsi_to_params(vsi); 12040545cc86SMichal Swiatkowski params.flags = ICE_VSI_FLAG_INIT; 12050545cc86SMichal Swiatkowski 12060545cc86SMichal Swiatkowski rtnl_lock(); 12070545cc86SMichal Swiatkowski err = ice_vsi_cfg(vsi, ¶ms); 12080545cc86SMichal Swiatkowski rtnl_unlock(); 12090545cc86SMichal Swiatkowski if (err) 12100545cc86SMichal Swiatkowski goto err_vsi_cfg; 12110545cc86SMichal Swiatkowski 12120545cc86SMichal Swiatkowski /* No need to take devl_lock, it's already taken by devlink API */ 12130545cc86SMichal Swiatkowski err = ice_load(pf); 12140545cc86SMichal Swiatkowski if (err) 12150545cc86SMichal Swiatkowski goto err_load; 12160545cc86SMichal Swiatkowski 12170545cc86SMichal Swiatkowski return 0; 12180545cc86SMichal Swiatkowski 12190545cc86SMichal Swiatkowski err_load: 12200545cc86SMichal Swiatkowski rtnl_lock(); 12210545cc86SMichal Swiatkowski ice_vsi_decfg(vsi); 12220545cc86SMichal Swiatkowski rtnl_unlock(); 12230545cc86SMichal Swiatkowski err_vsi_cfg: 12240545cc86SMichal Swiatkowski ice_deinit_dev(pf); 12250545cc86SMichal Swiatkowski return err; 12260545cc86SMichal Swiatkowski } 12270545cc86SMichal Swiatkowski 12280545cc86SMichal Swiatkowski /** 12290545cc86SMichal Swiatkowski * ice_devlink_reload_up - do reload up after reinit 12300545cc86SMichal Swiatkowski * @devlink: pointer to the devlink instance reloading 12310545cc86SMichal Swiatkowski * @action: the action requested 12320545cc86SMichal Swiatkowski * @limit: limits imposed by userspace, such as not resetting 12330545cc86SMichal Swiatkowski * @actions_performed: on return, indicate what actions actually performed 12340545cc86SMichal Swiatkowski * @extack: netlink extended ACK structure 12350545cc86SMichal Swiatkowski */ 12360545cc86SMichal Swiatkowski static int 12370545cc86SMichal Swiatkowski ice_devlink_reload_up(struct devlink *devlink, 12380545cc86SMichal Swiatkowski enum devlink_reload_action action, 12390545cc86SMichal Swiatkowski enum devlink_reload_limit limit, 12400545cc86SMichal Swiatkowski u32 *actions_performed, 12410545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 12420545cc86SMichal Swiatkowski { 12430545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 12440545cc86SMichal Swiatkowski 12450545cc86SMichal Swiatkowski switch (action) { 12460545cc86SMichal Swiatkowski case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: 12470545cc86SMichal Swiatkowski *actions_performed = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT); 12480545cc86SMichal Swiatkowski return ice_devlink_reinit_up(pf); 12490545cc86SMichal Swiatkowski case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: 12500545cc86SMichal Swiatkowski *actions_performed = BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE); 12510545cc86SMichal Swiatkowski return ice_devlink_reload_empr_finish(pf, extack); 12520545cc86SMichal Swiatkowski default: 12530545cc86SMichal Swiatkowski WARN_ON(1); 12540545cc86SMichal Swiatkowski return -EOPNOTSUPP; 12550545cc86SMichal Swiatkowski } 12560545cc86SMichal Swiatkowski } 12570545cc86SMichal Swiatkowski 12580545cc86SMichal Swiatkowski static const struct devlink_ops ice_devlink_ops = { 12590545cc86SMichal Swiatkowski .supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK, 12600545cc86SMichal Swiatkowski .reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) | 12610545cc86SMichal Swiatkowski BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE), 12620545cc86SMichal Swiatkowski .reload_down = ice_devlink_reload_down, 12630545cc86SMichal Swiatkowski .reload_up = ice_devlink_reload_up, 12640545cc86SMichal Swiatkowski .eswitch_mode_get = ice_eswitch_mode_get, 12650545cc86SMichal Swiatkowski .eswitch_mode_set = ice_eswitch_mode_set, 12660545cc86SMichal Swiatkowski .info_get = ice_devlink_info_get, 12670545cc86SMichal Swiatkowski .flash_update = ice_devlink_flash_update, 12680545cc86SMichal Swiatkowski 12690545cc86SMichal Swiatkowski .rate_node_new = ice_devlink_rate_node_new, 12700545cc86SMichal Swiatkowski .rate_node_del = ice_devlink_rate_node_del, 12710545cc86SMichal Swiatkowski 12720545cc86SMichal Swiatkowski .rate_leaf_tx_max_set = ice_devlink_rate_leaf_tx_max_set, 12730545cc86SMichal Swiatkowski .rate_leaf_tx_share_set = ice_devlink_rate_leaf_tx_share_set, 12740545cc86SMichal Swiatkowski .rate_leaf_tx_priority_set = ice_devlink_rate_leaf_tx_priority_set, 12750545cc86SMichal Swiatkowski .rate_leaf_tx_weight_set = ice_devlink_rate_leaf_tx_weight_set, 12760545cc86SMichal Swiatkowski 12770545cc86SMichal Swiatkowski .rate_node_tx_max_set = ice_devlink_rate_node_tx_max_set, 12780545cc86SMichal Swiatkowski .rate_node_tx_share_set = ice_devlink_rate_node_tx_share_set, 12790545cc86SMichal Swiatkowski .rate_node_tx_priority_set = ice_devlink_rate_node_tx_priority_set, 12800545cc86SMichal Swiatkowski .rate_node_tx_weight_set = ice_devlink_rate_node_tx_weight_set, 12810545cc86SMichal Swiatkowski 12820545cc86SMichal Swiatkowski .rate_leaf_parent_set = ice_devlink_set_parent, 12830545cc86SMichal Swiatkowski .rate_node_parent_set = ice_devlink_set_parent, 12840545cc86SMichal Swiatkowski }; 12850545cc86SMichal Swiatkowski 12860545cc86SMichal Swiatkowski static int 12870545cc86SMichal Swiatkowski ice_devlink_enable_roce_get(struct devlink *devlink, u32 id, 12880545cc86SMichal Swiatkowski struct devlink_param_gset_ctx *ctx) 12890545cc86SMichal Swiatkowski { 12900545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 12910545cc86SMichal Swiatkowski 12920545cc86SMichal Swiatkowski ctx->val.vbool = pf->rdma_mode & IIDC_RDMA_PROTOCOL_ROCEV2 ? true : false; 12930545cc86SMichal Swiatkowski 12940545cc86SMichal Swiatkowski return 0; 12950545cc86SMichal Swiatkowski } 12960545cc86SMichal Swiatkowski 12975625ca56SMateusz Polchlopek static int ice_devlink_enable_roce_set(struct devlink *devlink, u32 id, 12985625ca56SMateusz Polchlopek struct devlink_param_gset_ctx *ctx, 12995625ca56SMateusz Polchlopek struct netlink_ext_ack *extack) 13000545cc86SMichal Swiatkowski { 13010545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 13020545cc86SMichal Swiatkowski bool roce_ena = ctx->val.vbool; 13030545cc86SMichal Swiatkowski int ret; 13040545cc86SMichal Swiatkowski 13050545cc86SMichal Swiatkowski if (!roce_ena) { 13060545cc86SMichal Swiatkowski ice_unplug_aux_dev(pf); 13070545cc86SMichal Swiatkowski pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_ROCEV2; 13080545cc86SMichal Swiatkowski return 0; 13090545cc86SMichal Swiatkowski } 13100545cc86SMichal Swiatkowski 13110545cc86SMichal Swiatkowski pf->rdma_mode |= IIDC_RDMA_PROTOCOL_ROCEV2; 13120545cc86SMichal Swiatkowski ret = ice_plug_aux_dev(pf); 13130545cc86SMichal Swiatkowski if (ret) 13140545cc86SMichal Swiatkowski pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_ROCEV2; 13150545cc86SMichal Swiatkowski 13160545cc86SMichal Swiatkowski return ret; 13170545cc86SMichal Swiatkowski } 13180545cc86SMichal Swiatkowski 13190545cc86SMichal Swiatkowski static int 13200545cc86SMichal Swiatkowski ice_devlink_enable_roce_validate(struct devlink *devlink, u32 id, 13210545cc86SMichal Swiatkowski union devlink_param_value val, 13220545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 13230545cc86SMichal Swiatkowski { 13240545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 13250545cc86SMichal Swiatkowski 13260545cc86SMichal Swiatkowski if (!test_bit(ICE_FLAG_RDMA_ENA, pf->flags)) 13270545cc86SMichal Swiatkowski return -EOPNOTSUPP; 13280545cc86SMichal Swiatkowski 13290545cc86SMichal Swiatkowski if (pf->rdma_mode & IIDC_RDMA_PROTOCOL_IWARP) { 13300545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "iWARP is currently enabled. This device cannot enable iWARP and RoCEv2 simultaneously"); 13310545cc86SMichal Swiatkowski return -EOPNOTSUPP; 13320545cc86SMichal Swiatkowski } 13330545cc86SMichal Swiatkowski 13340545cc86SMichal Swiatkowski return 0; 13350545cc86SMichal Swiatkowski } 13360545cc86SMichal Swiatkowski 13370545cc86SMichal Swiatkowski static int 13380545cc86SMichal Swiatkowski ice_devlink_enable_iw_get(struct devlink *devlink, u32 id, 13390545cc86SMichal Swiatkowski struct devlink_param_gset_ctx *ctx) 13400545cc86SMichal Swiatkowski { 13410545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 13420545cc86SMichal Swiatkowski 13430545cc86SMichal Swiatkowski ctx->val.vbool = pf->rdma_mode & IIDC_RDMA_PROTOCOL_IWARP; 13440545cc86SMichal Swiatkowski 13450545cc86SMichal Swiatkowski return 0; 13460545cc86SMichal Swiatkowski } 13470545cc86SMichal Swiatkowski 13485625ca56SMateusz Polchlopek static int ice_devlink_enable_iw_set(struct devlink *devlink, u32 id, 13495625ca56SMateusz Polchlopek struct devlink_param_gset_ctx *ctx, 13505625ca56SMateusz Polchlopek struct netlink_ext_ack *extack) 13510545cc86SMichal Swiatkowski { 13520545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 13530545cc86SMichal Swiatkowski bool iw_ena = ctx->val.vbool; 13540545cc86SMichal Swiatkowski int ret; 13550545cc86SMichal Swiatkowski 13560545cc86SMichal Swiatkowski if (!iw_ena) { 13570545cc86SMichal Swiatkowski ice_unplug_aux_dev(pf); 13580545cc86SMichal Swiatkowski pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_IWARP; 13590545cc86SMichal Swiatkowski return 0; 13600545cc86SMichal Swiatkowski } 13610545cc86SMichal Swiatkowski 13620545cc86SMichal Swiatkowski pf->rdma_mode |= IIDC_RDMA_PROTOCOL_IWARP; 13630545cc86SMichal Swiatkowski ret = ice_plug_aux_dev(pf); 13640545cc86SMichal Swiatkowski if (ret) 13650545cc86SMichal Swiatkowski pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_IWARP; 13660545cc86SMichal Swiatkowski 13670545cc86SMichal Swiatkowski return ret; 13680545cc86SMichal Swiatkowski } 13690545cc86SMichal Swiatkowski 13700545cc86SMichal Swiatkowski static int 13710545cc86SMichal Swiatkowski ice_devlink_enable_iw_validate(struct devlink *devlink, u32 id, 13720545cc86SMichal Swiatkowski union devlink_param_value val, 13730545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 13740545cc86SMichal Swiatkowski { 13750545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 13760545cc86SMichal Swiatkowski 13770545cc86SMichal Swiatkowski if (!test_bit(ICE_FLAG_RDMA_ENA, pf->flags)) 13780545cc86SMichal Swiatkowski return -EOPNOTSUPP; 13790545cc86SMichal Swiatkowski 13800545cc86SMichal Swiatkowski if (pf->rdma_mode & IIDC_RDMA_PROTOCOL_ROCEV2) { 13810545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "RoCEv2 is currently enabled. This device cannot enable iWARP and RoCEv2 simultaneously"); 13820545cc86SMichal Swiatkowski return -EOPNOTSUPP; 13830545cc86SMichal Swiatkowski } 13840545cc86SMichal Swiatkowski 13850545cc86SMichal Swiatkowski return 0; 13860545cc86SMichal Swiatkowski } 13870545cc86SMichal Swiatkowski 1388*109eb291SLukasz Czapnik enum ice_param_id { 1389*109eb291SLukasz Czapnik ICE_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX, 1390*109eb291SLukasz Czapnik ICE_DEVLINK_PARAM_ID_TX_SCHED_LAYERS, 1391*109eb291SLukasz Czapnik }; 1392*109eb291SLukasz Czapnik 13930545cc86SMichal Swiatkowski static const struct devlink_param ice_devlink_params[] = { 13940545cc86SMichal Swiatkowski DEVLINK_PARAM_GENERIC(ENABLE_ROCE, BIT(DEVLINK_PARAM_CMODE_RUNTIME), 13950545cc86SMichal Swiatkowski ice_devlink_enable_roce_get, 13960545cc86SMichal Swiatkowski ice_devlink_enable_roce_set, 13970545cc86SMichal Swiatkowski ice_devlink_enable_roce_validate), 13980545cc86SMichal Swiatkowski DEVLINK_PARAM_GENERIC(ENABLE_IWARP, BIT(DEVLINK_PARAM_CMODE_RUNTIME), 13990545cc86SMichal Swiatkowski ice_devlink_enable_iw_get, 14000545cc86SMichal Swiatkowski ice_devlink_enable_iw_set, 14010545cc86SMichal Swiatkowski ice_devlink_enable_iw_validate), 1402*109eb291SLukasz Czapnik DEVLINK_PARAM_DRIVER(ICE_DEVLINK_PARAM_ID_TX_SCHED_LAYERS, 1403*109eb291SLukasz Czapnik "tx_scheduling_layers", 1404*109eb291SLukasz Czapnik DEVLINK_PARAM_TYPE_U8, 1405*109eb291SLukasz Czapnik BIT(DEVLINK_PARAM_CMODE_PERMANENT), 1406*109eb291SLukasz Czapnik ice_devlink_tx_sched_layers_get, 1407*109eb291SLukasz Czapnik ice_devlink_tx_sched_layers_set, 1408*109eb291SLukasz Czapnik ice_devlink_tx_sched_layers_validate), 14090545cc86SMichal Swiatkowski }; 14100545cc86SMichal Swiatkowski 14110545cc86SMichal Swiatkowski static void ice_devlink_free(void *devlink_ptr) 14120545cc86SMichal Swiatkowski { 14130545cc86SMichal Swiatkowski devlink_free((struct devlink *)devlink_ptr); 14140545cc86SMichal Swiatkowski } 14150545cc86SMichal Swiatkowski 14160545cc86SMichal Swiatkowski /** 14170545cc86SMichal Swiatkowski * ice_allocate_pf - Allocate devlink and return PF structure pointer 14180545cc86SMichal Swiatkowski * @dev: the device to allocate for 14190545cc86SMichal Swiatkowski * 14200545cc86SMichal Swiatkowski * Allocate a devlink instance for this device and return the private area as 14210545cc86SMichal Swiatkowski * the PF structure. The devlink memory is kept track of through devres by 14220545cc86SMichal Swiatkowski * adding an action to remove it when unwinding. 14230545cc86SMichal Swiatkowski */ 14240545cc86SMichal Swiatkowski struct ice_pf *ice_allocate_pf(struct device *dev) 14250545cc86SMichal Swiatkowski { 14260545cc86SMichal Swiatkowski struct devlink *devlink; 14270545cc86SMichal Swiatkowski 14280545cc86SMichal Swiatkowski devlink = devlink_alloc(&ice_devlink_ops, sizeof(struct ice_pf), dev); 14290545cc86SMichal Swiatkowski if (!devlink) 14300545cc86SMichal Swiatkowski return NULL; 14310545cc86SMichal Swiatkowski 14320545cc86SMichal Swiatkowski /* Add an action to teardown the devlink when unwinding the driver */ 14330545cc86SMichal Swiatkowski if (devm_add_action_or_reset(dev, ice_devlink_free, devlink)) 14340545cc86SMichal Swiatkowski return NULL; 14350545cc86SMichal Swiatkowski 14360545cc86SMichal Swiatkowski return devlink_priv(devlink); 14370545cc86SMichal Swiatkowski } 14380545cc86SMichal Swiatkowski 14390545cc86SMichal Swiatkowski /** 14400545cc86SMichal Swiatkowski * ice_devlink_register - Register devlink interface for this PF 14410545cc86SMichal Swiatkowski * @pf: the PF to register the devlink for. 14420545cc86SMichal Swiatkowski * 14430545cc86SMichal Swiatkowski * Register the devlink instance associated with this physical function. 14440545cc86SMichal Swiatkowski * 14450545cc86SMichal Swiatkowski * Return: zero on success or an error code on failure. 14460545cc86SMichal Swiatkowski */ 14470545cc86SMichal Swiatkowski void ice_devlink_register(struct ice_pf *pf) 14480545cc86SMichal Swiatkowski { 14490545cc86SMichal Swiatkowski struct devlink *devlink = priv_to_devlink(pf); 14500545cc86SMichal Swiatkowski 1451118c6bdeSMichal Swiatkowski devl_register(devlink); 14520545cc86SMichal Swiatkowski } 14530545cc86SMichal Swiatkowski 14540545cc86SMichal Swiatkowski /** 14550545cc86SMichal Swiatkowski * ice_devlink_unregister - Unregister devlink resources for this PF. 14560545cc86SMichal Swiatkowski * @pf: the PF structure to cleanup 14570545cc86SMichal Swiatkowski * 14580545cc86SMichal Swiatkowski * Releases resources used by devlink and cleans up associated memory. 14590545cc86SMichal Swiatkowski */ 14600545cc86SMichal Swiatkowski void ice_devlink_unregister(struct ice_pf *pf) 14610545cc86SMichal Swiatkowski { 1462118c6bdeSMichal Swiatkowski devl_unregister(priv_to_devlink(pf)); 14630545cc86SMichal Swiatkowski } 14640545cc86SMichal Swiatkowski 14650545cc86SMichal Swiatkowski int ice_devlink_register_params(struct ice_pf *pf) 14660545cc86SMichal Swiatkowski { 14670545cc86SMichal Swiatkowski struct devlink *devlink = priv_to_devlink(pf); 1468*109eb291SLukasz Czapnik struct ice_hw *hw = &pf->hw; 1469*109eb291SLukasz Czapnik size_t params_size; 1470*109eb291SLukasz Czapnik 1471*109eb291SLukasz Czapnik params_size = ARRAY_SIZE(ice_devlink_params); 1472*109eb291SLukasz Czapnik 1473*109eb291SLukasz Czapnik if (!hw->func_caps.common_cap.tx_sched_topo_comp_mode_en) 1474*109eb291SLukasz Czapnik params_size--; 14750545cc86SMichal Swiatkowski 1476118c6bdeSMichal Swiatkowski return devl_params_register(devlink, ice_devlink_params, 1477*109eb291SLukasz Czapnik params_size); 14780545cc86SMichal Swiatkowski } 14790545cc86SMichal Swiatkowski 14800545cc86SMichal Swiatkowski void ice_devlink_unregister_params(struct ice_pf *pf) 14810545cc86SMichal Swiatkowski { 1482118c6bdeSMichal Swiatkowski devl_params_unregister(priv_to_devlink(pf), ice_devlink_params, 14830545cc86SMichal Swiatkowski ARRAY_SIZE(ice_devlink_params)); 14840545cc86SMichal Swiatkowski } 14850545cc86SMichal Swiatkowski 14860545cc86SMichal Swiatkowski #define ICE_DEVLINK_READ_BLK_SIZE (1024 * 1024) 14870545cc86SMichal Swiatkowski 14880545cc86SMichal Swiatkowski static const struct devlink_region_ops ice_nvm_region_ops; 14890545cc86SMichal Swiatkowski static const struct devlink_region_ops ice_sram_region_ops; 14900545cc86SMichal Swiatkowski 14910545cc86SMichal Swiatkowski /** 14920545cc86SMichal Swiatkowski * ice_devlink_nvm_snapshot - Capture a snapshot of the NVM flash contents 14930545cc86SMichal Swiatkowski * @devlink: the devlink instance 14940545cc86SMichal Swiatkowski * @ops: the devlink region to snapshot 14950545cc86SMichal Swiatkowski * @extack: extended ACK response structure 14960545cc86SMichal Swiatkowski * @data: on exit points to snapshot data buffer 14970545cc86SMichal Swiatkowski * 14980545cc86SMichal Swiatkowski * This function is called in response to a DEVLINK_CMD_REGION_NEW for either 14990545cc86SMichal Swiatkowski * the nvm-flash or shadow-ram region. 15000545cc86SMichal Swiatkowski * 15010545cc86SMichal Swiatkowski * It captures a snapshot of the NVM or Shadow RAM flash contents. This 15020545cc86SMichal Swiatkowski * snapshot can then later be viewed via the DEVLINK_CMD_REGION_READ netlink 15030545cc86SMichal Swiatkowski * interface. 15040545cc86SMichal Swiatkowski * 15050545cc86SMichal Swiatkowski * @returns zero on success, and updates the data pointer. Returns a non-zero 15060545cc86SMichal Swiatkowski * error code on failure. 15070545cc86SMichal Swiatkowski */ 15080545cc86SMichal Swiatkowski static int ice_devlink_nvm_snapshot(struct devlink *devlink, 15090545cc86SMichal Swiatkowski const struct devlink_region_ops *ops, 15100545cc86SMichal Swiatkowski struct netlink_ext_ack *extack, u8 **data) 15110545cc86SMichal Swiatkowski { 15120545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 15130545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 15140545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 15150545cc86SMichal Swiatkowski bool read_shadow_ram; 15160545cc86SMichal Swiatkowski u8 *nvm_data, *tmp, i; 15170545cc86SMichal Swiatkowski u32 nvm_size, left; 15180545cc86SMichal Swiatkowski s8 num_blks; 15190545cc86SMichal Swiatkowski int status; 15200545cc86SMichal Swiatkowski 15210545cc86SMichal Swiatkowski if (ops == &ice_nvm_region_ops) { 15220545cc86SMichal Swiatkowski read_shadow_ram = false; 15230545cc86SMichal Swiatkowski nvm_size = hw->flash.flash_size; 15240545cc86SMichal Swiatkowski } else if (ops == &ice_sram_region_ops) { 15250545cc86SMichal Swiatkowski read_shadow_ram = true; 15260545cc86SMichal Swiatkowski nvm_size = hw->flash.sr_words * 2u; 15270545cc86SMichal Swiatkowski } else { 15280545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unexpected region in snapshot function"); 15290545cc86SMichal Swiatkowski return -EOPNOTSUPP; 15300545cc86SMichal Swiatkowski } 15310545cc86SMichal Swiatkowski 15320545cc86SMichal Swiatkowski nvm_data = vzalloc(nvm_size); 15330545cc86SMichal Swiatkowski if (!nvm_data) 15340545cc86SMichal Swiatkowski return -ENOMEM; 15350545cc86SMichal Swiatkowski 15360545cc86SMichal Swiatkowski num_blks = DIV_ROUND_UP(nvm_size, ICE_DEVLINK_READ_BLK_SIZE); 15370545cc86SMichal Swiatkowski tmp = nvm_data; 15380545cc86SMichal Swiatkowski left = nvm_size; 15390545cc86SMichal Swiatkowski 15400545cc86SMichal Swiatkowski /* Some systems take longer to read the NVM than others which causes the 15410545cc86SMichal Swiatkowski * FW to reclaim the NVM lock before the entire NVM has been read. Fix 15420545cc86SMichal Swiatkowski * this by breaking the reads of the NVM into smaller chunks that will 15430545cc86SMichal Swiatkowski * probably not take as long. This has some overhead since we are 15440545cc86SMichal Swiatkowski * increasing the number of AQ commands, but it should always work 15450545cc86SMichal Swiatkowski */ 15460545cc86SMichal Swiatkowski for (i = 0; i < num_blks; i++) { 15470545cc86SMichal Swiatkowski u32 read_sz = min_t(u32, ICE_DEVLINK_READ_BLK_SIZE, left); 15480545cc86SMichal Swiatkowski 15490545cc86SMichal Swiatkowski status = ice_acquire_nvm(hw, ICE_RES_READ); 15500545cc86SMichal Swiatkowski if (status) { 15510545cc86SMichal Swiatkowski dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n", 15520545cc86SMichal Swiatkowski status, hw->adminq.sq_last_status); 15530545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore"); 15540545cc86SMichal Swiatkowski vfree(nvm_data); 15550545cc86SMichal Swiatkowski return -EIO; 15560545cc86SMichal Swiatkowski } 15570545cc86SMichal Swiatkowski 15580545cc86SMichal Swiatkowski status = ice_read_flat_nvm(hw, i * ICE_DEVLINK_READ_BLK_SIZE, 15590545cc86SMichal Swiatkowski &read_sz, tmp, read_shadow_ram); 15600545cc86SMichal Swiatkowski if (status) { 15610545cc86SMichal Swiatkowski dev_dbg(dev, "ice_read_flat_nvm failed after reading %u bytes, err %d aq_err %d\n", 15620545cc86SMichal Swiatkowski read_sz, status, hw->adminq.sq_last_status); 15630545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Failed to read NVM contents"); 15640545cc86SMichal Swiatkowski ice_release_nvm(hw); 15650545cc86SMichal Swiatkowski vfree(nvm_data); 15660545cc86SMichal Swiatkowski return -EIO; 15670545cc86SMichal Swiatkowski } 15680545cc86SMichal Swiatkowski ice_release_nvm(hw); 15690545cc86SMichal Swiatkowski 15700545cc86SMichal Swiatkowski tmp += read_sz; 15710545cc86SMichal Swiatkowski left -= read_sz; 15720545cc86SMichal Swiatkowski } 15730545cc86SMichal Swiatkowski 15740545cc86SMichal Swiatkowski *data = nvm_data; 15750545cc86SMichal Swiatkowski 15760545cc86SMichal Swiatkowski return 0; 15770545cc86SMichal Swiatkowski } 15780545cc86SMichal Swiatkowski 15790545cc86SMichal Swiatkowski /** 15800545cc86SMichal Swiatkowski * ice_devlink_nvm_read - Read a portion of NVM flash contents 15810545cc86SMichal Swiatkowski * @devlink: the devlink instance 15820545cc86SMichal Swiatkowski * @ops: the devlink region to snapshot 15830545cc86SMichal Swiatkowski * @extack: extended ACK response structure 15840545cc86SMichal Swiatkowski * @offset: the offset to start at 15850545cc86SMichal Swiatkowski * @size: the amount to read 15860545cc86SMichal Swiatkowski * @data: the data buffer to read into 15870545cc86SMichal Swiatkowski * 15880545cc86SMichal Swiatkowski * This function is called in response to DEVLINK_CMD_REGION_READ to directly 15890545cc86SMichal Swiatkowski * read a section of the NVM contents. 15900545cc86SMichal Swiatkowski * 15910545cc86SMichal Swiatkowski * It reads from either the nvm-flash or shadow-ram region contents. 15920545cc86SMichal Swiatkowski * 15930545cc86SMichal Swiatkowski * @returns zero on success, and updates the data pointer. Returns a non-zero 15940545cc86SMichal Swiatkowski * error code on failure. 15950545cc86SMichal Swiatkowski */ 15960545cc86SMichal Swiatkowski static int ice_devlink_nvm_read(struct devlink *devlink, 15970545cc86SMichal Swiatkowski const struct devlink_region_ops *ops, 15980545cc86SMichal Swiatkowski struct netlink_ext_ack *extack, 15990545cc86SMichal Swiatkowski u64 offset, u32 size, u8 *data) 16000545cc86SMichal Swiatkowski { 16010545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 16020545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 16030545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 16040545cc86SMichal Swiatkowski bool read_shadow_ram; 16050545cc86SMichal Swiatkowski u64 nvm_size; 16060545cc86SMichal Swiatkowski int status; 16070545cc86SMichal Swiatkowski 16080545cc86SMichal Swiatkowski if (ops == &ice_nvm_region_ops) { 16090545cc86SMichal Swiatkowski read_shadow_ram = false; 16100545cc86SMichal Swiatkowski nvm_size = hw->flash.flash_size; 16110545cc86SMichal Swiatkowski } else if (ops == &ice_sram_region_ops) { 16120545cc86SMichal Swiatkowski read_shadow_ram = true; 16130545cc86SMichal Swiatkowski nvm_size = hw->flash.sr_words * 2u; 16140545cc86SMichal Swiatkowski } else { 16150545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unexpected region in snapshot function"); 16160545cc86SMichal Swiatkowski return -EOPNOTSUPP; 16170545cc86SMichal Swiatkowski } 16180545cc86SMichal Swiatkowski 16190545cc86SMichal Swiatkowski if (offset + size >= nvm_size) { 16200545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Cannot read beyond the region size"); 16210545cc86SMichal Swiatkowski return -ERANGE; 16220545cc86SMichal Swiatkowski } 16230545cc86SMichal Swiatkowski 16240545cc86SMichal Swiatkowski status = ice_acquire_nvm(hw, ICE_RES_READ); 16250545cc86SMichal Swiatkowski if (status) { 16260545cc86SMichal Swiatkowski dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n", 16270545cc86SMichal Swiatkowski status, hw->adminq.sq_last_status); 16280545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore"); 16290545cc86SMichal Swiatkowski return -EIO; 16300545cc86SMichal Swiatkowski } 16310545cc86SMichal Swiatkowski 16320545cc86SMichal Swiatkowski status = ice_read_flat_nvm(hw, (u32)offset, &size, data, 16330545cc86SMichal Swiatkowski read_shadow_ram); 16340545cc86SMichal Swiatkowski if (status) { 16350545cc86SMichal Swiatkowski dev_dbg(dev, "ice_read_flat_nvm failed after reading %u bytes, err %d aq_err %d\n", 16360545cc86SMichal Swiatkowski size, status, hw->adminq.sq_last_status); 16370545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Failed to read NVM contents"); 16380545cc86SMichal Swiatkowski ice_release_nvm(hw); 16390545cc86SMichal Swiatkowski return -EIO; 16400545cc86SMichal Swiatkowski } 16410545cc86SMichal Swiatkowski ice_release_nvm(hw); 16420545cc86SMichal Swiatkowski 16430545cc86SMichal Swiatkowski return 0; 16440545cc86SMichal Swiatkowski } 16450545cc86SMichal Swiatkowski 16460545cc86SMichal Swiatkowski /** 16470545cc86SMichal Swiatkowski * ice_devlink_devcaps_snapshot - Capture snapshot of device capabilities 16480545cc86SMichal Swiatkowski * @devlink: the devlink instance 16490545cc86SMichal Swiatkowski * @ops: the devlink region being snapshotted 16500545cc86SMichal Swiatkowski * @extack: extended ACK response structure 16510545cc86SMichal Swiatkowski * @data: on exit points to snapshot data buffer 16520545cc86SMichal Swiatkowski * 16530545cc86SMichal Swiatkowski * This function is called in response to the DEVLINK_CMD_REGION_TRIGGER for 16540545cc86SMichal Swiatkowski * the device-caps devlink region. It captures a snapshot of the device 16550545cc86SMichal Swiatkowski * capabilities reported by firmware. 16560545cc86SMichal Swiatkowski * 16570545cc86SMichal Swiatkowski * @returns zero on success, and updates the data pointer. Returns a non-zero 16580545cc86SMichal Swiatkowski * error code on failure. 16590545cc86SMichal Swiatkowski */ 16600545cc86SMichal Swiatkowski static int 16610545cc86SMichal Swiatkowski ice_devlink_devcaps_snapshot(struct devlink *devlink, 16620545cc86SMichal Swiatkowski const struct devlink_region_ops *ops, 16630545cc86SMichal Swiatkowski struct netlink_ext_ack *extack, u8 **data) 16640545cc86SMichal Swiatkowski { 16650545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 16660545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 16670545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 16680545cc86SMichal Swiatkowski void *devcaps; 16690545cc86SMichal Swiatkowski int status; 16700545cc86SMichal Swiatkowski 16710545cc86SMichal Swiatkowski devcaps = vzalloc(ICE_AQ_MAX_BUF_LEN); 16720545cc86SMichal Swiatkowski if (!devcaps) 16730545cc86SMichal Swiatkowski return -ENOMEM; 16740545cc86SMichal Swiatkowski 16750545cc86SMichal Swiatkowski status = ice_aq_list_caps(hw, devcaps, ICE_AQ_MAX_BUF_LEN, NULL, 16760545cc86SMichal Swiatkowski ice_aqc_opc_list_dev_caps, NULL); 16770545cc86SMichal Swiatkowski if (status) { 16780545cc86SMichal Swiatkowski dev_dbg(dev, "ice_aq_list_caps: failed to read device capabilities, err %d aq_err %d\n", 16790545cc86SMichal Swiatkowski status, hw->adminq.sq_last_status); 16800545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Failed to read device capabilities"); 16810545cc86SMichal Swiatkowski vfree(devcaps); 16820545cc86SMichal Swiatkowski return status; 16830545cc86SMichal Swiatkowski } 16840545cc86SMichal Swiatkowski 16850545cc86SMichal Swiatkowski *data = (u8 *)devcaps; 16860545cc86SMichal Swiatkowski 16870545cc86SMichal Swiatkowski return 0; 16880545cc86SMichal Swiatkowski } 16890545cc86SMichal Swiatkowski 16900545cc86SMichal Swiatkowski static const struct devlink_region_ops ice_nvm_region_ops = { 16910545cc86SMichal Swiatkowski .name = "nvm-flash", 16920545cc86SMichal Swiatkowski .destructor = vfree, 16930545cc86SMichal Swiatkowski .snapshot = ice_devlink_nvm_snapshot, 16940545cc86SMichal Swiatkowski .read = ice_devlink_nvm_read, 16950545cc86SMichal Swiatkowski }; 16960545cc86SMichal Swiatkowski 16970545cc86SMichal Swiatkowski static const struct devlink_region_ops ice_sram_region_ops = { 16980545cc86SMichal Swiatkowski .name = "shadow-ram", 16990545cc86SMichal Swiatkowski .destructor = vfree, 17000545cc86SMichal Swiatkowski .snapshot = ice_devlink_nvm_snapshot, 17010545cc86SMichal Swiatkowski .read = ice_devlink_nvm_read, 17020545cc86SMichal Swiatkowski }; 17030545cc86SMichal Swiatkowski 17040545cc86SMichal Swiatkowski static const struct devlink_region_ops ice_devcaps_region_ops = { 17050545cc86SMichal Swiatkowski .name = "device-caps", 17060545cc86SMichal Swiatkowski .destructor = vfree, 17070545cc86SMichal Swiatkowski .snapshot = ice_devlink_devcaps_snapshot, 17080545cc86SMichal Swiatkowski }; 17090545cc86SMichal Swiatkowski 17100545cc86SMichal Swiatkowski /** 17110545cc86SMichal Swiatkowski * ice_devlink_init_regions - Initialize devlink regions 17120545cc86SMichal Swiatkowski * @pf: the PF device structure 17130545cc86SMichal Swiatkowski * 17140545cc86SMichal Swiatkowski * Create devlink regions used to enable access to dump the contents of the 17150545cc86SMichal Swiatkowski * flash memory on the device. 17160545cc86SMichal Swiatkowski */ 17170545cc86SMichal Swiatkowski void ice_devlink_init_regions(struct ice_pf *pf) 17180545cc86SMichal Swiatkowski { 17190545cc86SMichal Swiatkowski struct devlink *devlink = priv_to_devlink(pf); 17200545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 17210545cc86SMichal Swiatkowski u64 nvm_size, sram_size; 17220545cc86SMichal Swiatkowski 17230545cc86SMichal Swiatkowski nvm_size = pf->hw.flash.flash_size; 1724118c6bdeSMichal Swiatkowski pf->nvm_region = devl_region_create(devlink, &ice_nvm_region_ops, 1, 17250545cc86SMichal Swiatkowski nvm_size); 17260545cc86SMichal Swiatkowski if (IS_ERR(pf->nvm_region)) { 17270545cc86SMichal Swiatkowski dev_err(dev, "failed to create NVM devlink region, err %ld\n", 17280545cc86SMichal Swiatkowski PTR_ERR(pf->nvm_region)); 17290545cc86SMichal Swiatkowski pf->nvm_region = NULL; 17300545cc86SMichal Swiatkowski } 17310545cc86SMichal Swiatkowski 17320545cc86SMichal Swiatkowski sram_size = pf->hw.flash.sr_words * 2u; 1733118c6bdeSMichal Swiatkowski pf->sram_region = devl_region_create(devlink, &ice_sram_region_ops, 17340545cc86SMichal Swiatkowski 1, sram_size); 17350545cc86SMichal Swiatkowski if (IS_ERR(pf->sram_region)) { 17360545cc86SMichal Swiatkowski dev_err(dev, "failed to create shadow-ram devlink region, err %ld\n", 17370545cc86SMichal Swiatkowski PTR_ERR(pf->sram_region)); 17380545cc86SMichal Swiatkowski pf->sram_region = NULL; 17390545cc86SMichal Swiatkowski } 17400545cc86SMichal Swiatkowski 1741118c6bdeSMichal Swiatkowski pf->devcaps_region = devl_region_create(devlink, 17420545cc86SMichal Swiatkowski &ice_devcaps_region_ops, 10, 17430545cc86SMichal Swiatkowski ICE_AQ_MAX_BUF_LEN); 17440545cc86SMichal Swiatkowski if (IS_ERR(pf->devcaps_region)) { 17450545cc86SMichal Swiatkowski dev_err(dev, "failed to create device-caps devlink region, err %ld\n", 17460545cc86SMichal Swiatkowski PTR_ERR(pf->devcaps_region)); 17470545cc86SMichal Swiatkowski pf->devcaps_region = NULL; 17480545cc86SMichal Swiatkowski } 17490545cc86SMichal Swiatkowski } 17500545cc86SMichal Swiatkowski 17510545cc86SMichal Swiatkowski /** 17520545cc86SMichal Swiatkowski * ice_devlink_destroy_regions - Destroy devlink regions 17530545cc86SMichal Swiatkowski * @pf: the PF device structure 17540545cc86SMichal Swiatkowski * 17550545cc86SMichal Swiatkowski * Remove previously created regions for this PF. 17560545cc86SMichal Swiatkowski */ 17570545cc86SMichal Swiatkowski void ice_devlink_destroy_regions(struct ice_pf *pf) 17580545cc86SMichal Swiatkowski { 17590545cc86SMichal Swiatkowski if (pf->nvm_region) 1760118c6bdeSMichal Swiatkowski devl_region_destroy(pf->nvm_region); 17610545cc86SMichal Swiatkowski 17620545cc86SMichal Swiatkowski if (pf->sram_region) 1763118c6bdeSMichal Swiatkowski devl_region_destroy(pf->sram_region); 17640545cc86SMichal Swiatkowski 17650545cc86SMichal Swiatkowski if (pf->devcaps_region) 1766118c6bdeSMichal Swiatkowski devl_region_destroy(pf->devcaps_region); 17670545cc86SMichal Swiatkowski } 1768