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" 92846fe56SPrzemek Kitszel #include "port.h" 100545cc86SMichal Swiatkowski #include "ice_eswitch.h" 110545cc86SMichal Swiatkowski #include "ice_fw_update.h" 120545cc86SMichal Swiatkowski #include "ice_dcb_lib.h" 13f43e3be6SPiotr Raczynski #include "ice_sf_eth.h" 140545cc86SMichal Swiatkowski 150545cc86SMichal Swiatkowski /* context for devlink info version reporting */ 160545cc86SMichal Swiatkowski struct ice_info_ctx { 170545cc86SMichal Swiatkowski char buf[128]; 180545cc86SMichal Swiatkowski struct ice_orom_info pending_orom; 190545cc86SMichal Swiatkowski struct ice_nvm_info pending_nvm; 200545cc86SMichal Swiatkowski struct ice_netlist_info pending_netlist; 210545cc86SMichal Swiatkowski struct ice_hw_dev_caps dev_caps; 220545cc86SMichal Swiatkowski }; 230545cc86SMichal Swiatkowski 240545cc86SMichal Swiatkowski /* The following functions are used to format specific strings for various 250545cc86SMichal Swiatkowski * devlink info versions. The ctx parameter is used to provide the storage 260545cc86SMichal Swiatkowski * buffer, as well as any ancillary information calculated when the info 270545cc86SMichal Swiatkowski * request was made. 280545cc86SMichal Swiatkowski * 290545cc86SMichal Swiatkowski * If a version does not exist, for example when attempting to get the 300545cc86SMichal Swiatkowski * inactive version of flash when there is no pending update, the function 310545cc86SMichal Swiatkowski * should leave the buffer in the ctx structure empty. 320545cc86SMichal Swiatkowski */ 330545cc86SMichal Swiatkowski 340545cc86SMichal Swiatkowski static void ice_info_get_dsn(struct ice_pf *pf, struct ice_info_ctx *ctx) 350545cc86SMichal Swiatkowski { 360545cc86SMichal Swiatkowski u8 dsn[8]; 370545cc86SMichal Swiatkowski 380545cc86SMichal Swiatkowski /* Copy the DSN into an array in Big Endian format */ 390545cc86SMichal Swiatkowski put_unaligned_be64(pci_get_dsn(pf->pdev), dsn); 400545cc86SMichal Swiatkowski 410545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%8phD", dsn); 420545cc86SMichal Swiatkowski } 430545cc86SMichal Swiatkowski 440545cc86SMichal Swiatkowski static void ice_info_pba(struct ice_pf *pf, struct ice_info_ctx *ctx) 450545cc86SMichal Swiatkowski { 460545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 470545cc86SMichal Swiatkowski int status; 480545cc86SMichal Swiatkowski 490545cc86SMichal Swiatkowski status = ice_read_pba_string(hw, (u8 *)ctx->buf, sizeof(ctx->buf)); 500545cc86SMichal Swiatkowski if (status) 510545cc86SMichal Swiatkowski /* We failed to locate the PBA, so just skip this entry */ 520545cc86SMichal Swiatkowski dev_dbg(ice_pf_to_dev(pf), "Failed to read Product Board Assembly string, status %d\n", 530545cc86SMichal Swiatkowski status); 540545cc86SMichal Swiatkowski } 550545cc86SMichal Swiatkowski 560545cc86SMichal Swiatkowski static void ice_info_fw_mgmt(struct ice_pf *pf, struct ice_info_ctx *ctx) 570545cc86SMichal Swiatkowski { 580545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 590545cc86SMichal Swiatkowski 600545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", 610545cc86SMichal Swiatkowski hw->fw_maj_ver, hw->fw_min_ver, hw->fw_patch); 620545cc86SMichal Swiatkowski } 630545cc86SMichal Swiatkowski 640545cc86SMichal Swiatkowski static void ice_info_fw_api(struct ice_pf *pf, struct ice_info_ctx *ctx) 650545cc86SMichal Swiatkowski { 660545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 670545cc86SMichal Swiatkowski 680545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", hw->api_maj_ver, 690545cc86SMichal Swiatkowski hw->api_min_ver, hw->api_patch); 700545cc86SMichal Swiatkowski } 710545cc86SMichal Swiatkowski 720545cc86SMichal Swiatkowski static void ice_info_fw_build(struct ice_pf *pf, struct ice_info_ctx *ctx) 730545cc86SMichal Swiatkowski { 740545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 750545cc86SMichal Swiatkowski 760545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", hw->fw_build); 770545cc86SMichal Swiatkowski } 780545cc86SMichal Swiatkowski 790545cc86SMichal Swiatkowski static void ice_info_orom_ver(struct ice_pf *pf, struct ice_info_ctx *ctx) 800545cc86SMichal Swiatkowski { 810545cc86SMichal Swiatkowski struct ice_orom_info *orom = &pf->hw.flash.orom; 820545cc86SMichal Swiatkowski 830545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", 840545cc86SMichal Swiatkowski orom->major, orom->build, orom->patch); 850545cc86SMichal Swiatkowski } 860545cc86SMichal Swiatkowski 870545cc86SMichal Swiatkowski static void 880545cc86SMichal Swiatkowski ice_info_pending_orom_ver(struct ice_pf __always_unused *pf, 890545cc86SMichal Swiatkowski struct ice_info_ctx *ctx) 900545cc86SMichal Swiatkowski { 910545cc86SMichal Swiatkowski struct ice_orom_info *orom = &ctx->pending_orom; 920545cc86SMichal Swiatkowski 930545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_orom) 940545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", 950545cc86SMichal Swiatkowski orom->major, orom->build, orom->patch); 960545cc86SMichal Swiatkowski } 970545cc86SMichal Swiatkowski 980545cc86SMichal Swiatkowski static void ice_info_nvm_ver(struct ice_pf *pf, struct ice_info_ctx *ctx) 990545cc86SMichal Swiatkowski { 1000545cc86SMichal Swiatkowski struct ice_nvm_info *nvm = &pf->hw.flash.nvm; 1010545cc86SMichal Swiatkowski 1020545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", nvm->major, nvm->minor); 1030545cc86SMichal Swiatkowski } 1040545cc86SMichal Swiatkowski 1050545cc86SMichal Swiatkowski static void 1060545cc86SMichal Swiatkowski ice_info_pending_nvm_ver(struct ice_pf __always_unused *pf, 1070545cc86SMichal Swiatkowski struct ice_info_ctx *ctx) 1080545cc86SMichal Swiatkowski { 1090545cc86SMichal Swiatkowski struct ice_nvm_info *nvm = &ctx->pending_nvm; 1100545cc86SMichal Swiatkowski 1110545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_nvm) 1120545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", 1130545cc86SMichal Swiatkowski nvm->major, nvm->minor); 1140545cc86SMichal Swiatkowski } 1150545cc86SMichal Swiatkowski 1160545cc86SMichal Swiatkowski static void ice_info_eetrack(struct ice_pf *pf, struct ice_info_ctx *ctx) 1170545cc86SMichal Swiatkowski { 1180545cc86SMichal Swiatkowski struct ice_nvm_info *nvm = &pf->hw.flash.nvm; 1190545cc86SMichal Swiatkowski 1200545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm->eetrack); 1210545cc86SMichal Swiatkowski } 1220545cc86SMichal Swiatkowski 1230545cc86SMichal Swiatkowski static void 1240545cc86SMichal Swiatkowski ice_info_pending_eetrack(struct ice_pf *pf, struct ice_info_ctx *ctx) 1250545cc86SMichal Swiatkowski { 1260545cc86SMichal Swiatkowski struct ice_nvm_info *nvm = &ctx->pending_nvm; 1270545cc86SMichal Swiatkowski 1280545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_nvm) 1290545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm->eetrack); 1300545cc86SMichal Swiatkowski } 1310545cc86SMichal Swiatkowski 1320545cc86SMichal Swiatkowski static void ice_info_ddp_pkg_name(struct ice_pf *pf, struct ice_info_ctx *ctx) 1330545cc86SMichal Swiatkowski { 1340545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 1350545cc86SMichal Swiatkowski 1360545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%s", hw->active_pkg_name); 1370545cc86SMichal Swiatkowski } 1380545cc86SMichal Swiatkowski 1390545cc86SMichal Swiatkowski static void 1400545cc86SMichal Swiatkowski ice_info_ddp_pkg_version(struct ice_pf *pf, struct ice_info_ctx *ctx) 1410545cc86SMichal Swiatkowski { 1420545cc86SMichal Swiatkowski struct ice_pkg_ver *pkg = &pf->hw.active_pkg_ver; 1430545cc86SMichal Swiatkowski 1440545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u.%u", 1450545cc86SMichal Swiatkowski pkg->major, pkg->minor, pkg->update, pkg->draft); 1460545cc86SMichal Swiatkowski } 1470545cc86SMichal Swiatkowski 1480545cc86SMichal Swiatkowski static void 1490545cc86SMichal Swiatkowski ice_info_ddp_pkg_bundle_id(struct ice_pf *pf, struct ice_info_ctx *ctx) 1500545cc86SMichal Swiatkowski { 1510545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", pf->hw.active_track_id); 1520545cc86SMichal Swiatkowski } 1530545cc86SMichal Swiatkowski 1540545cc86SMichal Swiatkowski static void ice_info_netlist_ver(struct ice_pf *pf, struct ice_info_ctx *ctx) 1550545cc86SMichal Swiatkowski { 1560545cc86SMichal Swiatkowski struct ice_netlist_info *netlist = &pf->hw.flash.netlist; 1570545cc86SMichal Swiatkowski 1580545cc86SMichal Swiatkowski /* The netlist version fields are BCD formatted */ 1590545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x", 1600545cc86SMichal Swiatkowski netlist->major, netlist->minor, 1610545cc86SMichal Swiatkowski netlist->type >> 16, netlist->type & 0xFFFF, 1620545cc86SMichal Swiatkowski netlist->rev, netlist->cust_ver); 1630545cc86SMichal Swiatkowski } 1640545cc86SMichal Swiatkowski 1650545cc86SMichal Swiatkowski static void ice_info_netlist_build(struct ice_pf *pf, struct ice_info_ctx *ctx) 1660545cc86SMichal Swiatkowski { 1670545cc86SMichal Swiatkowski struct ice_netlist_info *netlist = &pf->hw.flash.netlist; 1680545cc86SMichal Swiatkowski 1690545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash); 1700545cc86SMichal Swiatkowski } 1710545cc86SMichal Swiatkowski 1720545cc86SMichal Swiatkowski static void 1730545cc86SMichal Swiatkowski ice_info_pending_netlist_ver(struct ice_pf __always_unused *pf, 1740545cc86SMichal Swiatkowski struct ice_info_ctx *ctx) 1750545cc86SMichal Swiatkowski { 1760545cc86SMichal Swiatkowski struct ice_netlist_info *netlist = &ctx->pending_netlist; 1770545cc86SMichal Swiatkowski 1780545cc86SMichal Swiatkowski /* The netlist version fields are BCD formatted */ 1790545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_netlist) 1800545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x", 1810545cc86SMichal Swiatkowski netlist->major, netlist->minor, 1820545cc86SMichal Swiatkowski netlist->type >> 16, netlist->type & 0xFFFF, 1830545cc86SMichal Swiatkowski netlist->rev, netlist->cust_ver); 1840545cc86SMichal Swiatkowski } 1850545cc86SMichal Swiatkowski 1860545cc86SMichal Swiatkowski static void 1870545cc86SMichal Swiatkowski ice_info_pending_netlist_build(struct ice_pf __always_unused *pf, 1880545cc86SMichal Swiatkowski struct ice_info_ctx *ctx) 1890545cc86SMichal Swiatkowski { 1900545cc86SMichal Swiatkowski struct ice_netlist_info *netlist = &ctx->pending_netlist; 1910545cc86SMichal Swiatkowski 1920545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_netlist) 1930545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash); 1940545cc86SMichal Swiatkowski } 1950545cc86SMichal Swiatkowski 1960545cc86SMichal Swiatkowski static void ice_info_cgu_fw_build(struct ice_pf *pf, struct ice_info_ctx *ctx) 1970545cc86SMichal Swiatkowski { 1980545cc86SMichal Swiatkowski u32 id, cfg_ver, fw_ver; 1990545cc86SMichal Swiatkowski 2000545cc86SMichal Swiatkowski if (!ice_is_feature_supported(pf, ICE_F_CGU)) 2010545cc86SMichal Swiatkowski return; 2020545cc86SMichal Swiatkowski if (ice_aq_get_cgu_info(&pf->hw, &id, &cfg_ver, &fw_ver)) 2030545cc86SMichal Swiatkowski return; 2040545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", id, cfg_ver, fw_ver); 2050545cc86SMichal Swiatkowski } 2060545cc86SMichal Swiatkowski 2070545cc86SMichal Swiatkowski static void ice_info_cgu_id(struct ice_pf *pf, struct ice_info_ctx *ctx) 2080545cc86SMichal Swiatkowski { 2090545cc86SMichal Swiatkowski if (!ice_is_feature_supported(pf, ICE_F_CGU)) 2100545cc86SMichal Swiatkowski return; 2110545cc86SMichal Swiatkowski snprintf(ctx->buf, sizeof(ctx->buf), "%u", pf->hw.cgu_part_number); 2120545cc86SMichal Swiatkowski } 2130545cc86SMichal Swiatkowski 2140545cc86SMichal Swiatkowski #define fixed(key, getter) { ICE_VERSION_FIXED, key, getter, NULL } 2150545cc86SMichal Swiatkowski #define running(key, getter) { ICE_VERSION_RUNNING, key, getter, NULL } 2160545cc86SMichal Swiatkowski #define stored(key, getter, fallback) { ICE_VERSION_STORED, key, getter, fallback } 2170545cc86SMichal Swiatkowski 2180545cc86SMichal Swiatkowski /* The combined() macro inserts both the running entry as well as a stored 2190545cc86SMichal Swiatkowski * entry. The running entry will always report the version from the active 2200545cc86SMichal Swiatkowski * handler. The stored entry will first try the pending handler, and fallback 2210545cc86SMichal Swiatkowski * to the active handler if the pending function does not report a version. 2220545cc86SMichal Swiatkowski * The pending handler should check the status of a pending update for the 2230545cc86SMichal Swiatkowski * relevant flash component. It should only fill in the buffer in the case 2240545cc86SMichal Swiatkowski * where a valid pending version is available. This ensures that the related 2250545cc86SMichal Swiatkowski * stored and running versions remain in sync, and that stored versions are 2260545cc86SMichal Swiatkowski * correctly reported as expected. 2270545cc86SMichal Swiatkowski */ 2280545cc86SMichal Swiatkowski #define combined(key, active, pending) \ 2290545cc86SMichal Swiatkowski running(key, active), \ 2300545cc86SMichal Swiatkowski stored(key, pending, active) 2310545cc86SMichal Swiatkowski 2320545cc86SMichal Swiatkowski enum ice_version_type { 2330545cc86SMichal Swiatkowski ICE_VERSION_FIXED, 2340545cc86SMichal Swiatkowski ICE_VERSION_RUNNING, 2350545cc86SMichal Swiatkowski ICE_VERSION_STORED, 2360545cc86SMichal Swiatkowski }; 2370545cc86SMichal Swiatkowski 2380545cc86SMichal Swiatkowski static const struct ice_devlink_version { 2390545cc86SMichal Swiatkowski enum ice_version_type type; 2400545cc86SMichal Swiatkowski const char *key; 2410545cc86SMichal Swiatkowski void (*getter)(struct ice_pf *pf, struct ice_info_ctx *ctx); 2420545cc86SMichal Swiatkowski void (*fallback)(struct ice_pf *pf, struct ice_info_ctx *ctx); 2430545cc86SMichal Swiatkowski } ice_devlink_versions[] = { 2440545cc86SMichal Swiatkowski fixed(DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, ice_info_pba), 2450545cc86SMichal Swiatkowski running(DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, ice_info_fw_mgmt), 2460545cc86SMichal Swiatkowski running("fw.mgmt.api", ice_info_fw_api), 2470545cc86SMichal Swiatkowski running("fw.mgmt.build", ice_info_fw_build), 2480545cc86SMichal Swiatkowski combined(DEVLINK_INFO_VERSION_GENERIC_FW_UNDI, ice_info_orom_ver, ice_info_pending_orom_ver), 2490545cc86SMichal Swiatkowski combined("fw.psid.api", ice_info_nvm_ver, ice_info_pending_nvm_ver), 2500545cc86SMichal Swiatkowski combined(DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID, ice_info_eetrack, ice_info_pending_eetrack), 2510545cc86SMichal Swiatkowski running("fw.app.name", ice_info_ddp_pkg_name), 2520545cc86SMichal Swiatkowski running(DEVLINK_INFO_VERSION_GENERIC_FW_APP, ice_info_ddp_pkg_version), 2530545cc86SMichal Swiatkowski running("fw.app.bundle_id", ice_info_ddp_pkg_bundle_id), 2540545cc86SMichal Swiatkowski combined("fw.netlist", ice_info_netlist_ver, ice_info_pending_netlist_ver), 2550545cc86SMichal Swiatkowski combined("fw.netlist.build", ice_info_netlist_build, ice_info_pending_netlist_build), 2560545cc86SMichal Swiatkowski fixed("cgu.id", ice_info_cgu_id), 2570545cc86SMichal Swiatkowski running("fw.cgu", ice_info_cgu_fw_build), 2580545cc86SMichal Swiatkowski }; 2590545cc86SMichal Swiatkowski 2600545cc86SMichal Swiatkowski /** 2610545cc86SMichal Swiatkowski * ice_devlink_info_get - .info_get devlink handler 2620545cc86SMichal Swiatkowski * @devlink: devlink instance structure 2630545cc86SMichal Swiatkowski * @req: the devlink info request 2640545cc86SMichal Swiatkowski * @extack: extended netdev ack structure 2650545cc86SMichal Swiatkowski * 2660545cc86SMichal Swiatkowski * Callback for the devlink .info_get operation. Reports information about the 2670545cc86SMichal Swiatkowski * device. 2680545cc86SMichal Swiatkowski * 2690545cc86SMichal Swiatkowski * Return: zero on success or an error code on failure. 2700545cc86SMichal Swiatkowski */ 2710545cc86SMichal Swiatkowski static int ice_devlink_info_get(struct devlink *devlink, 2720545cc86SMichal Swiatkowski struct devlink_info_req *req, 2730545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 2740545cc86SMichal Swiatkowski { 2750545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 2760545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 2770545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 2780545cc86SMichal Swiatkowski struct ice_info_ctx *ctx; 2790545cc86SMichal Swiatkowski size_t i; 2800545cc86SMichal Swiatkowski int err; 2810545cc86SMichal Swiatkowski 2820545cc86SMichal Swiatkowski err = ice_wait_for_reset(pf, 10 * HZ); 2830545cc86SMichal Swiatkowski if (err) { 2840545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Device is busy resetting"); 2850545cc86SMichal Swiatkowski return err; 2860545cc86SMichal Swiatkowski } 2870545cc86SMichal Swiatkowski 2880545cc86SMichal Swiatkowski ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 2890545cc86SMichal Swiatkowski if (!ctx) 2900545cc86SMichal Swiatkowski return -ENOMEM; 2910545cc86SMichal Swiatkowski 2920545cc86SMichal Swiatkowski /* discover capabilities first */ 2930545cc86SMichal Swiatkowski err = ice_discover_dev_caps(hw, &ctx->dev_caps); 2940545cc86SMichal Swiatkowski if (err) { 2950545cc86SMichal Swiatkowski dev_dbg(dev, "Failed to discover device capabilities, status %d aq_err %s\n", 2960545cc86SMichal Swiatkowski err, ice_aq_str(hw->adminq.sq_last_status)); 2970545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unable to discover device capabilities"); 2980545cc86SMichal Swiatkowski goto out_free_ctx; 2990545cc86SMichal Swiatkowski } 3000545cc86SMichal Swiatkowski 3010545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_orom) { 3020545cc86SMichal Swiatkowski err = ice_get_inactive_orom_ver(hw, &ctx->pending_orom); 3030545cc86SMichal Swiatkowski if (err) { 3040545cc86SMichal Swiatkowski dev_dbg(dev, "Unable to read inactive Option ROM version data, status %d aq_err %s\n", 3050545cc86SMichal Swiatkowski err, ice_aq_str(hw->adminq.sq_last_status)); 3060545cc86SMichal Swiatkowski 3070545cc86SMichal Swiatkowski /* disable display of pending Option ROM */ 3080545cc86SMichal Swiatkowski ctx->dev_caps.common_cap.nvm_update_pending_orom = false; 3090545cc86SMichal Swiatkowski } 3100545cc86SMichal Swiatkowski } 3110545cc86SMichal Swiatkowski 3120545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_nvm) { 3130545cc86SMichal Swiatkowski err = ice_get_inactive_nvm_ver(hw, &ctx->pending_nvm); 3140545cc86SMichal Swiatkowski if (err) { 3150545cc86SMichal Swiatkowski dev_dbg(dev, "Unable to read inactive NVM version data, status %d aq_err %s\n", 3160545cc86SMichal Swiatkowski err, ice_aq_str(hw->adminq.sq_last_status)); 3170545cc86SMichal Swiatkowski 3180545cc86SMichal Swiatkowski /* disable display of pending Option ROM */ 3190545cc86SMichal Swiatkowski ctx->dev_caps.common_cap.nvm_update_pending_nvm = false; 3200545cc86SMichal Swiatkowski } 3210545cc86SMichal Swiatkowski } 3220545cc86SMichal Swiatkowski 3230545cc86SMichal Swiatkowski if (ctx->dev_caps.common_cap.nvm_update_pending_netlist) { 3240545cc86SMichal Swiatkowski err = ice_get_inactive_netlist_ver(hw, &ctx->pending_netlist); 3250545cc86SMichal Swiatkowski if (err) { 3260545cc86SMichal Swiatkowski dev_dbg(dev, "Unable to read inactive Netlist version data, status %d aq_err %s\n", 3270545cc86SMichal Swiatkowski err, ice_aq_str(hw->adminq.sq_last_status)); 3280545cc86SMichal Swiatkowski 3290545cc86SMichal Swiatkowski /* disable display of pending Option ROM */ 3300545cc86SMichal Swiatkowski ctx->dev_caps.common_cap.nvm_update_pending_netlist = false; 3310545cc86SMichal Swiatkowski } 3320545cc86SMichal Swiatkowski } 3330545cc86SMichal Swiatkowski 3340545cc86SMichal Swiatkowski ice_info_get_dsn(pf, ctx); 3350545cc86SMichal Swiatkowski 3360545cc86SMichal Swiatkowski err = devlink_info_serial_number_put(req, ctx->buf); 3370545cc86SMichal Swiatkowski if (err) { 3380545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unable to set serial number"); 3390545cc86SMichal Swiatkowski goto out_free_ctx; 3400545cc86SMichal Swiatkowski } 3410545cc86SMichal Swiatkowski 3420545cc86SMichal Swiatkowski for (i = 0; i < ARRAY_SIZE(ice_devlink_versions); i++) { 3430545cc86SMichal Swiatkowski enum ice_version_type type = ice_devlink_versions[i].type; 3440545cc86SMichal Swiatkowski const char *key = ice_devlink_versions[i].key; 3450545cc86SMichal Swiatkowski 3460545cc86SMichal Swiatkowski memset(ctx->buf, 0, sizeof(ctx->buf)); 3470545cc86SMichal Swiatkowski 3480545cc86SMichal Swiatkowski ice_devlink_versions[i].getter(pf, ctx); 3490545cc86SMichal Swiatkowski 3500545cc86SMichal Swiatkowski /* If the default getter doesn't report a version, use the 3510545cc86SMichal Swiatkowski * fallback function. This is primarily useful in the case of 3520545cc86SMichal Swiatkowski * "stored" versions that want to report the same value as the 3530545cc86SMichal Swiatkowski * running version in the normal case of no pending update. 3540545cc86SMichal Swiatkowski */ 3550545cc86SMichal Swiatkowski if (ctx->buf[0] == '\0' && ice_devlink_versions[i].fallback) 3560545cc86SMichal Swiatkowski ice_devlink_versions[i].fallback(pf, ctx); 3570545cc86SMichal Swiatkowski 3580545cc86SMichal Swiatkowski /* Do not report missing versions */ 3590545cc86SMichal Swiatkowski if (ctx->buf[0] == '\0') 3600545cc86SMichal Swiatkowski continue; 3610545cc86SMichal Swiatkowski 3620545cc86SMichal Swiatkowski switch (type) { 3630545cc86SMichal Swiatkowski case ICE_VERSION_FIXED: 3640545cc86SMichal Swiatkowski err = devlink_info_version_fixed_put(req, key, ctx->buf); 3650545cc86SMichal Swiatkowski if (err) { 3660545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unable to set fixed version"); 3670545cc86SMichal Swiatkowski goto out_free_ctx; 3680545cc86SMichal Swiatkowski } 3690545cc86SMichal Swiatkowski break; 3700545cc86SMichal Swiatkowski case ICE_VERSION_RUNNING: 3711de25c6bSKonrad Knitter err = devlink_info_version_running_put_ext(req, key, 3721de25c6bSKonrad Knitter ctx->buf, 3731de25c6bSKonrad Knitter DEVLINK_INFO_VERSION_TYPE_COMPONENT); 3740545cc86SMichal Swiatkowski if (err) { 3750545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unable to set running version"); 3760545cc86SMichal Swiatkowski goto out_free_ctx; 3770545cc86SMichal Swiatkowski } 3780545cc86SMichal Swiatkowski break; 3790545cc86SMichal Swiatkowski case ICE_VERSION_STORED: 3801de25c6bSKonrad Knitter err = devlink_info_version_stored_put_ext(req, key, 3811de25c6bSKonrad Knitter ctx->buf, 3821de25c6bSKonrad Knitter DEVLINK_INFO_VERSION_TYPE_COMPONENT); 3830545cc86SMichal Swiatkowski if (err) { 3840545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unable to set stored version"); 3850545cc86SMichal Swiatkowski goto out_free_ctx; 3860545cc86SMichal Swiatkowski } 3870545cc86SMichal Swiatkowski break; 3880545cc86SMichal Swiatkowski } 3890545cc86SMichal Swiatkowski } 3900545cc86SMichal Swiatkowski 3910545cc86SMichal Swiatkowski out_free_ctx: 3920545cc86SMichal Swiatkowski kfree(ctx); 3930545cc86SMichal Swiatkowski return err; 3940545cc86SMichal Swiatkowski } 3950545cc86SMichal Swiatkowski 3960545cc86SMichal Swiatkowski /** 3970545cc86SMichal Swiatkowski * ice_devlink_reload_empr_start - Start EMP reset to activate new firmware 3980545cc86SMichal Swiatkowski * @pf: pointer to the pf instance 3990545cc86SMichal Swiatkowski * @extack: netlink extended ACK structure 4000545cc86SMichal Swiatkowski * 4010545cc86SMichal Swiatkowski * Allow user to activate new Embedded Management Processor firmware by 4020545cc86SMichal Swiatkowski * issuing device specific EMP reset. Called in response to 4030545cc86SMichal Swiatkowski * a DEVLINK_CMD_RELOAD with the DEVLINK_RELOAD_ACTION_FW_ACTIVATE. 4040545cc86SMichal Swiatkowski * 4050545cc86SMichal Swiatkowski * Note that teardown and rebuild of the driver state happens automatically as 4060545cc86SMichal Swiatkowski * part of an interrupt and watchdog task. This is because all physical 4070545cc86SMichal Swiatkowski * functions on the device must be able to reset when an EMP reset occurs from 4080545cc86SMichal Swiatkowski * any source. 4090545cc86SMichal Swiatkowski */ 4100545cc86SMichal Swiatkowski static int 4110545cc86SMichal Swiatkowski ice_devlink_reload_empr_start(struct ice_pf *pf, 4120545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 4130545cc86SMichal Swiatkowski { 4140545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 4150545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 4160545cc86SMichal Swiatkowski u8 pending; 4170545cc86SMichal Swiatkowski int err; 4180545cc86SMichal Swiatkowski 4190545cc86SMichal Swiatkowski err = ice_get_pending_updates(pf, &pending, extack); 4200545cc86SMichal Swiatkowski if (err) 4210545cc86SMichal Swiatkowski return err; 4220545cc86SMichal Swiatkowski 4230545cc86SMichal Swiatkowski /* pending is a bitmask of which flash banks have a pending update, 4240545cc86SMichal Swiatkowski * including the main NVM bank, the Option ROM bank, and the netlist 4250545cc86SMichal Swiatkowski * bank. If any of these bits are set, then there is a pending update 4260545cc86SMichal Swiatkowski * waiting to be activated. 4270545cc86SMichal Swiatkowski */ 4280545cc86SMichal Swiatkowski if (!pending) { 4290545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "No pending firmware update"); 4300545cc86SMichal Swiatkowski return -ECANCELED; 4310545cc86SMichal Swiatkowski } 4320545cc86SMichal Swiatkowski 4330545cc86SMichal Swiatkowski if (pf->fw_emp_reset_disabled) { 4340545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "EMP reset is not available. To activate firmware, a reboot or power cycle is needed"); 4350545cc86SMichal Swiatkowski return -ECANCELED; 4360545cc86SMichal Swiatkowski } 4370545cc86SMichal Swiatkowski 4380545cc86SMichal Swiatkowski dev_dbg(dev, "Issuing device EMP reset to activate firmware\n"); 4390545cc86SMichal Swiatkowski 4400545cc86SMichal Swiatkowski err = ice_aq_nvm_update_empr(hw); 4410545cc86SMichal Swiatkowski if (err) { 4420545cc86SMichal Swiatkowski dev_err(dev, "Failed to trigger EMP device reset to reload firmware, err %d aq_err %s\n", 4430545cc86SMichal Swiatkowski err, ice_aq_str(hw->adminq.sq_last_status)); 4440545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Failed to trigger EMP device reset to reload firmware"); 4450545cc86SMichal Swiatkowski return err; 4460545cc86SMichal Swiatkowski } 4470545cc86SMichal Swiatkowski 4480545cc86SMichal Swiatkowski return 0; 4490545cc86SMichal Swiatkowski } 4500545cc86SMichal Swiatkowski 4510545cc86SMichal Swiatkowski /** 4520545cc86SMichal Swiatkowski * ice_devlink_reinit_down - unload given PF 4530545cc86SMichal Swiatkowski * @pf: pointer to the PF struct 4540545cc86SMichal Swiatkowski */ 4550545cc86SMichal Swiatkowski static void ice_devlink_reinit_down(struct ice_pf *pf) 4560545cc86SMichal Swiatkowski { 4570545cc86SMichal Swiatkowski /* No need to take devl_lock, it's already taken by devlink API */ 4580545cc86SMichal Swiatkowski ice_unload(pf); 4590545cc86SMichal Swiatkowski rtnl_lock(); 4600545cc86SMichal Swiatkowski ice_vsi_decfg(ice_get_main_vsi(pf)); 4610545cc86SMichal Swiatkowski rtnl_unlock(); 4620545cc86SMichal Swiatkowski ice_deinit_dev(pf); 4630545cc86SMichal Swiatkowski } 4640545cc86SMichal Swiatkowski 4650545cc86SMichal Swiatkowski /** 4660545cc86SMichal Swiatkowski * ice_devlink_reload_down - prepare for reload 4670545cc86SMichal Swiatkowski * @devlink: pointer to the devlink instance to reload 4680545cc86SMichal Swiatkowski * @netns_change: if true, the network namespace is changing 4690545cc86SMichal Swiatkowski * @action: the action to perform 4700545cc86SMichal Swiatkowski * @limit: limits on what reload should do, such as not resetting 4710545cc86SMichal Swiatkowski * @extack: netlink extended ACK structure 4720545cc86SMichal Swiatkowski */ 4730545cc86SMichal Swiatkowski static int 4740545cc86SMichal Swiatkowski ice_devlink_reload_down(struct devlink *devlink, bool netns_change, 4750545cc86SMichal Swiatkowski enum devlink_reload_action action, 4760545cc86SMichal Swiatkowski enum devlink_reload_limit limit, 4770545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 4780545cc86SMichal Swiatkowski { 4790545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 4800545cc86SMichal Swiatkowski 4810545cc86SMichal Swiatkowski switch (action) { 4820545cc86SMichal Swiatkowski case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: 4830545cc86SMichal Swiatkowski if (ice_is_eswitch_mode_switchdev(pf)) { 4840545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, 4850545cc86SMichal Swiatkowski "Go to legacy mode before doing reinit"); 4860545cc86SMichal Swiatkowski return -EOPNOTSUPP; 4870545cc86SMichal Swiatkowski } 4880545cc86SMichal Swiatkowski if (ice_is_adq_active(pf)) { 4890545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, 4900545cc86SMichal Swiatkowski "Turn off ADQ before doing reinit"); 4910545cc86SMichal Swiatkowski return -EOPNOTSUPP; 4920545cc86SMichal Swiatkowski } 4930545cc86SMichal Swiatkowski if (ice_has_vfs(pf)) { 4940545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, 4950545cc86SMichal Swiatkowski "Remove all VFs before doing reinit"); 4960545cc86SMichal Swiatkowski return -EOPNOTSUPP; 4970545cc86SMichal Swiatkowski } 4980545cc86SMichal Swiatkowski ice_devlink_reinit_down(pf); 4990545cc86SMichal Swiatkowski return 0; 5000545cc86SMichal Swiatkowski case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: 5010545cc86SMichal Swiatkowski return ice_devlink_reload_empr_start(pf, extack); 5020545cc86SMichal Swiatkowski default: 5030545cc86SMichal Swiatkowski WARN_ON(1); 5040545cc86SMichal Swiatkowski return -EOPNOTSUPP; 5050545cc86SMichal Swiatkowski } 5060545cc86SMichal Swiatkowski } 5070545cc86SMichal Swiatkowski 5080545cc86SMichal Swiatkowski /** 5090545cc86SMichal Swiatkowski * ice_devlink_reload_empr_finish - Wait for EMP reset to finish 5100545cc86SMichal Swiatkowski * @pf: pointer to the pf instance 5110545cc86SMichal Swiatkowski * @extack: netlink extended ACK structure 5120545cc86SMichal Swiatkowski * 5130545cc86SMichal Swiatkowski * Wait for driver to finish rebuilding after EMP reset is completed. This 5140545cc86SMichal Swiatkowski * includes time to wait for both the actual device reset as well as the time 5150545cc86SMichal Swiatkowski * for the driver's rebuild to complete. 5160545cc86SMichal Swiatkowski */ 5170545cc86SMichal Swiatkowski static int 5180545cc86SMichal Swiatkowski ice_devlink_reload_empr_finish(struct ice_pf *pf, 5190545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 5200545cc86SMichal Swiatkowski { 5210545cc86SMichal Swiatkowski int err; 5220545cc86SMichal Swiatkowski 5230545cc86SMichal Swiatkowski err = ice_wait_for_reset(pf, 60 * HZ); 5240545cc86SMichal Swiatkowski if (err) { 5250545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Device still resetting after 1 minute"); 5260545cc86SMichal Swiatkowski return err; 5270545cc86SMichal Swiatkowski } 5280545cc86SMichal Swiatkowski 5290545cc86SMichal Swiatkowski return 0; 5300545cc86SMichal Swiatkowski } 5310545cc86SMichal Swiatkowski 5320545cc86SMichal Swiatkowski /** 533109eb291SLukasz Czapnik * ice_get_tx_topo_user_sel - Read user's choice from flash 534109eb291SLukasz Czapnik * @pf: pointer to pf structure 535109eb291SLukasz Czapnik * @layers: value read from flash will be saved here 536109eb291SLukasz Czapnik * 537109eb291SLukasz Czapnik * Reads user's preference for Tx Scheduler Topology Tree from PFA TLV. 538109eb291SLukasz Czapnik * 539109eb291SLukasz Czapnik * Return: zero when read was successful, negative values otherwise. 540109eb291SLukasz Czapnik */ 541109eb291SLukasz Czapnik static int ice_get_tx_topo_user_sel(struct ice_pf *pf, uint8_t *layers) 542109eb291SLukasz Czapnik { 543109eb291SLukasz Czapnik struct ice_aqc_nvm_tx_topo_user_sel usr_sel = {}; 544109eb291SLukasz Czapnik struct ice_hw *hw = &pf->hw; 545109eb291SLukasz Czapnik int err; 546109eb291SLukasz Czapnik 547109eb291SLukasz Czapnik err = ice_acquire_nvm(hw, ICE_RES_READ); 548109eb291SLukasz Czapnik if (err) 549109eb291SLukasz Czapnik return err; 550109eb291SLukasz Czapnik 551109eb291SLukasz Czapnik err = ice_aq_read_nvm(hw, ICE_AQC_NVM_TX_TOPO_MOD_ID, 0, 552109eb291SLukasz Czapnik sizeof(usr_sel), &usr_sel, true, true, NULL); 553109eb291SLukasz Czapnik if (err) 554109eb291SLukasz Czapnik goto exit_release_res; 555109eb291SLukasz Czapnik 556109eb291SLukasz Czapnik if (usr_sel.data & ICE_AQC_NVM_TX_TOPO_USER_SEL) 557109eb291SLukasz Czapnik *layers = ICE_SCHED_5_LAYERS; 558109eb291SLukasz Czapnik else 559109eb291SLukasz Czapnik *layers = ICE_SCHED_9_LAYERS; 560109eb291SLukasz Czapnik 561109eb291SLukasz Czapnik exit_release_res: 562109eb291SLukasz Czapnik ice_release_nvm(hw); 563109eb291SLukasz Czapnik 564109eb291SLukasz Czapnik return err; 565109eb291SLukasz Czapnik } 566109eb291SLukasz Czapnik 567109eb291SLukasz Czapnik /** 568109eb291SLukasz Czapnik * ice_update_tx_topo_user_sel - Save user's preference in flash 569109eb291SLukasz Czapnik * @pf: pointer to pf structure 570109eb291SLukasz Czapnik * @layers: value to be saved in flash 571109eb291SLukasz Czapnik * 572109eb291SLukasz Czapnik * Variable "layers" defines user's preference about number of layers in Tx 573109eb291SLukasz Czapnik * Scheduler Topology Tree. This choice should be stored in PFA TLV field 574109eb291SLukasz Czapnik * and be picked up by driver, next time during init. 575109eb291SLukasz Czapnik * 576109eb291SLukasz Czapnik * Return: zero when save was successful, negative values otherwise. 577109eb291SLukasz Czapnik */ 578109eb291SLukasz Czapnik static int ice_update_tx_topo_user_sel(struct ice_pf *pf, int layers) 579109eb291SLukasz Czapnik { 580109eb291SLukasz Czapnik struct ice_aqc_nvm_tx_topo_user_sel usr_sel = {}; 581109eb291SLukasz Czapnik struct ice_hw *hw = &pf->hw; 582109eb291SLukasz Czapnik int err; 583109eb291SLukasz Czapnik 584109eb291SLukasz Czapnik err = ice_acquire_nvm(hw, ICE_RES_WRITE); 585109eb291SLukasz Czapnik if (err) 586109eb291SLukasz Czapnik return err; 587109eb291SLukasz Czapnik 588109eb291SLukasz Czapnik err = ice_aq_read_nvm(hw, ICE_AQC_NVM_TX_TOPO_MOD_ID, 0, 589109eb291SLukasz Czapnik sizeof(usr_sel), &usr_sel, true, true, NULL); 590109eb291SLukasz Czapnik if (err) 591109eb291SLukasz Czapnik goto exit_release_res; 592109eb291SLukasz Czapnik 593109eb291SLukasz Czapnik if (layers == ICE_SCHED_5_LAYERS) 594109eb291SLukasz Czapnik usr_sel.data |= ICE_AQC_NVM_TX_TOPO_USER_SEL; 595109eb291SLukasz Czapnik else 596109eb291SLukasz Czapnik usr_sel.data &= ~ICE_AQC_NVM_TX_TOPO_USER_SEL; 597109eb291SLukasz Czapnik 598109eb291SLukasz Czapnik err = ice_write_one_nvm_block(pf, ICE_AQC_NVM_TX_TOPO_MOD_ID, 2, 599109eb291SLukasz Czapnik sizeof(usr_sel.data), &usr_sel.data, 600109eb291SLukasz Czapnik true, NULL, NULL); 601109eb291SLukasz Czapnik exit_release_res: 602109eb291SLukasz Czapnik ice_release_nvm(hw); 603109eb291SLukasz Czapnik 604109eb291SLukasz Czapnik return err; 605109eb291SLukasz Czapnik } 606109eb291SLukasz Czapnik 607109eb291SLukasz Czapnik /** 608109eb291SLukasz Czapnik * ice_devlink_tx_sched_layers_get - Get tx_scheduling_layers parameter 609109eb291SLukasz Czapnik * @devlink: pointer to the devlink instance 610109eb291SLukasz Czapnik * @id: the parameter ID to set 611109eb291SLukasz Czapnik * @ctx: context to store the parameter value 612109eb291SLukasz Czapnik * 613109eb291SLukasz Czapnik * Return: zero on success and negative value on failure. 614109eb291SLukasz Czapnik */ 615109eb291SLukasz Czapnik static int ice_devlink_tx_sched_layers_get(struct devlink *devlink, u32 id, 616109eb291SLukasz Czapnik struct devlink_param_gset_ctx *ctx) 617109eb291SLukasz Czapnik { 618109eb291SLukasz Czapnik struct ice_pf *pf = devlink_priv(devlink); 619109eb291SLukasz Czapnik int err; 620109eb291SLukasz Czapnik 621109eb291SLukasz Czapnik err = ice_get_tx_topo_user_sel(pf, &ctx->val.vu8); 622109eb291SLukasz Czapnik if (err) 623109eb291SLukasz Czapnik return err; 624109eb291SLukasz Czapnik 625109eb291SLukasz Czapnik return 0; 626109eb291SLukasz Czapnik } 627109eb291SLukasz Czapnik 628109eb291SLukasz Czapnik /** 629109eb291SLukasz Czapnik * ice_devlink_tx_sched_layers_set - Set tx_scheduling_layers parameter 630109eb291SLukasz Czapnik * @devlink: pointer to the devlink instance 631109eb291SLukasz Czapnik * @id: the parameter ID to set 632109eb291SLukasz Czapnik * @ctx: context to get the parameter value 633109eb291SLukasz Czapnik * @extack: netlink extended ACK structure 634109eb291SLukasz Czapnik * 635109eb291SLukasz Czapnik * Return: zero on success and negative value on failure. 636109eb291SLukasz Czapnik */ 637109eb291SLukasz Czapnik static int ice_devlink_tx_sched_layers_set(struct devlink *devlink, u32 id, 638109eb291SLukasz Czapnik struct devlink_param_gset_ctx *ctx, 639109eb291SLukasz Czapnik struct netlink_ext_ack *extack) 640109eb291SLukasz Czapnik { 641109eb291SLukasz Czapnik struct ice_pf *pf = devlink_priv(devlink); 642109eb291SLukasz Czapnik int err; 643109eb291SLukasz Czapnik 644109eb291SLukasz Czapnik err = ice_update_tx_topo_user_sel(pf, ctx->val.vu8); 645109eb291SLukasz Czapnik if (err) 646109eb291SLukasz Czapnik return err; 647109eb291SLukasz Czapnik 648109eb291SLukasz Czapnik NL_SET_ERR_MSG_MOD(extack, 649109eb291SLukasz Czapnik "Tx scheduling layers have been changed on this device. You must do the PCI slot powercycle for the change to take effect."); 650109eb291SLukasz Czapnik 651109eb291SLukasz Czapnik return 0; 652109eb291SLukasz Czapnik } 653109eb291SLukasz Czapnik 654109eb291SLukasz Czapnik /** 655109eb291SLukasz Czapnik * ice_devlink_tx_sched_layers_validate - Validate passed tx_scheduling_layers 656109eb291SLukasz Czapnik * parameter value 657109eb291SLukasz Czapnik * @devlink: unused pointer to devlink instance 658109eb291SLukasz Czapnik * @id: the parameter ID to validate 659109eb291SLukasz Czapnik * @val: value to validate 660109eb291SLukasz Czapnik * @extack: netlink extended ACK structure 661109eb291SLukasz Czapnik * 662109eb291SLukasz Czapnik * Supported values are: 663109eb291SLukasz Czapnik * - 5 - five layers Tx Scheduler Topology Tree 664109eb291SLukasz Czapnik * - 9 - nine layers Tx Scheduler Topology Tree 665109eb291SLukasz Czapnik * 666109eb291SLukasz Czapnik * Return: zero when passed parameter value is supported. Negative value on 667109eb291SLukasz Czapnik * error. 668109eb291SLukasz Czapnik */ 669109eb291SLukasz Czapnik static int ice_devlink_tx_sched_layers_validate(struct devlink *devlink, u32 id, 670109eb291SLukasz Czapnik union devlink_param_value val, 671109eb291SLukasz Czapnik struct netlink_ext_ack *extack) 672109eb291SLukasz Czapnik { 673109eb291SLukasz Czapnik if (val.vu8 != ICE_SCHED_5_LAYERS && val.vu8 != ICE_SCHED_9_LAYERS) { 674109eb291SLukasz Czapnik NL_SET_ERR_MSG_MOD(extack, 675109eb291SLukasz Czapnik "Wrong number of tx scheduler layers provided."); 676109eb291SLukasz Czapnik return -EINVAL; 677109eb291SLukasz Czapnik } 678109eb291SLukasz Czapnik 679109eb291SLukasz Czapnik return 0; 680109eb291SLukasz Czapnik } 681109eb291SLukasz Czapnik 682109eb291SLukasz Czapnik /** 6830545cc86SMichal Swiatkowski * ice_tear_down_devlink_rate_tree - removes devlink-rate exported tree 6840545cc86SMichal Swiatkowski * @pf: pf struct 6850545cc86SMichal Swiatkowski * 6860545cc86SMichal Swiatkowski * This function tears down tree exported during VF's creation. 6870545cc86SMichal Swiatkowski */ 6880545cc86SMichal Swiatkowski void ice_tear_down_devlink_rate_tree(struct ice_pf *pf) 6890545cc86SMichal Swiatkowski { 6900545cc86SMichal Swiatkowski struct devlink *devlink; 6910545cc86SMichal Swiatkowski struct ice_vf *vf; 6920545cc86SMichal Swiatkowski unsigned int bkt; 6930545cc86SMichal Swiatkowski 6940545cc86SMichal Swiatkowski devlink = priv_to_devlink(pf); 6950545cc86SMichal Swiatkowski 6960545cc86SMichal Swiatkowski devl_lock(devlink); 6970545cc86SMichal Swiatkowski mutex_lock(&pf->vfs.table_lock); 6980545cc86SMichal Swiatkowski ice_for_each_vf(pf, bkt, vf) { 6990545cc86SMichal Swiatkowski if (vf->devlink_port.devlink_rate) 7000545cc86SMichal Swiatkowski devl_rate_leaf_destroy(&vf->devlink_port); 7010545cc86SMichal Swiatkowski } 7020545cc86SMichal Swiatkowski mutex_unlock(&pf->vfs.table_lock); 7030545cc86SMichal Swiatkowski 7040545cc86SMichal Swiatkowski devl_rate_nodes_destroy(devlink); 7050545cc86SMichal Swiatkowski devl_unlock(devlink); 7060545cc86SMichal Swiatkowski } 7070545cc86SMichal Swiatkowski 7080545cc86SMichal Swiatkowski /** 7090545cc86SMichal Swiatkowski * ice_enable_custom_tx - try to enable custom Tx feature 7100545cc86SMichal Swiatkowski * @pf: pf struct 7110545cc86SMichal Swiatkowski * 7120545cc86SMichal Swiatkowski * This function tries to enable custom Tx feature, 7130545cc86SMichal Swiatkowski * it's not possible to enable it, if DCB or ADQ is active. 7140545cc86SMichal Swiatkowski */ 7150545cc86SMichal Swiatkowski static bool ice_enable_custom_tx(struct ice_pf *pf) 7160545cc86SMichal Swiatkowski { 7170545cc86SMichal Swiatkowski struct ice_port_info *pi = ice_get_main_vsi(pf)->port_info; 7180545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 7190545cc86SMichal Swiatkowski 7200545cc86SMichal Swiatkowski if (pi->is_custom_tx_enabled) 7210545cc86SMichal Swiatkowski /* already enabled, return true */ 7220545cc86SMichal Swiatkowski return true; 7230545cc86SMichal Swiatkowski 7240545cc86SMichal Swiatkowski if (ice_is_adq_active(pf)) { 7250545cc86SMichal Swiatkowski dev_err(dev, "ADQ active, can't modify Tx scheduler tree\n"); 7260545cc86SMichal Swiatkowski return false; 7270545cc86SMichal Swiatkowski } 7280545cc86SMichal Swiatkowski 7290545cc86SMichal Swiatkowski if (ice_is_dcb_active(pf)) { 7300545cc86SMichal Swiatkowski dev_err(dev, "DCB active, can't modify Tx scheduler tree\n"); 7310545cc86SMichal Swiatkowski return false; 7320545cc86SMichal Swiatkowski } 7330545cc86SMichal Swiatkowski 7340545cc86SMichal Swiatkowski pi->is_custom_tx_enabled = true; 7350545cc86SMichal Swiatkowski 7360545cc86SMichal Swiatkowski return true; 7370545cc86SMichal Swiatkowski } 7380545cc86SMichal Swiatkowski 7390545cc86SMichal Swiatkowski /** 7400545cc86SMichal Swiatkowski * ice_traverse_tx_tree - traverse Tx scheduler tree 7410545cc86SMichal Swiatkowski * @devlink: devlink struct 7420545cc86SMichal Swiatkowski * @node: current node, used for recursion 7430545cc86SMichal Swiatkowski * @tc_node: tc_node struct, that is treated as a root 7440545cc86SMichal Swiatkowski * @pf: pf struct 7450545cc86SMichal Swiatkowski * 7460545cc86SMichal Swiatkowski * This function traverses Tx scheduler tree and exports 7470545cc86SMichal Swiatkowski * entire structure to the devlink-rate. 7480545cc86SMichal Swiatkowski */ 7490545cc86SMichal Swiatkowski static void ice_traverse_tx_tree(struct devlink *devlink, struct ice_sched_node *node, 7500545cc86SMichal Swiatkowski struct ice_sched_node *tc_node, struct ice_pf *pf) 7510545cc86SMichal Swiatkowski { 7520545cc86SMichal Swiatkowski struct devlink_rate *rate_node = NULL; 7537cde4743SMichal Swiatkowski struct ice_dynamic_port *sf; 7540545cc86SMichal Swiatkowski struct ice_vf *vf; 7550545cc86SMichal Swiatkowski int i; 7560545cc86SMichal Swiatkowski 7570545cc86SMichal Swiatkowski if (node->rate_node) 7580545cc86SMichal Swiatkowski /* already added, skip to the next */ 7590545cc86SMichal Swiatkowski goto traverse_children; 7600545cc86SMichal Swiatkowski 7610545cc86SMichal Swiatkowski if (node->parent == tc_node) { 7620545cc86SMichal Swiatkowski /* create root node */ 7630545cc86SMichal Swiatkowski rate_node = devl_rate_node_create(devlink, node, node->name, NULL); 7640545cc86SMichal Swiatkowski } else if (node->vsi_handle && 7657cde4743SMichal Swiatkowski pf->vsi[node->vsi_handle]->type == ICE_VSI_VF && 7660545cc86SMichal Swiatkowski pf->vsi[node->vsi_handle]->vf) { 7670545cc86SMichal Swiatkowski vf = pf->vsi[node->vsi_handle]->vf; 7680545cc86SMichal Swiatkowski if (!vf->devlink_port.devlink_rate) 7690545cc86SMichal Swiatkowski /* leaf nodes doesn't have children 7700545cc86SMichal Swiatkowski * so we don't set rate_node 7710545cc86SMichal Swiatkowski */ 7720545cc86SMichal Swiatkowski devl_rate_leaf_create(&vf->devlink_port, node, 7730545cc86SMichal Swiatkowski node->parent->rate_node); 7747cde4743SMichal Swiatkowski } else if (node->vsi_handle && 7757cde4743SMichal Swiatkowski pf->vsi[node->vsi_handle]->type == ICE_VSI_SF && 7767cde4743SMichal Swiatkowski pf->vsi[node->vsi_handle]->sf) { 7777cde4743SMichal Swiatkowski sf = pf->vsi[node->vsi_handle]->sf; 7787cde4743SMichal Swiatkowski if (!sf->devlink_port.devlink_rate) 7797cde4743SMichal Swiatkowski /* leaf nodes doesn't have children 7807cde4743SMichal Swiatkowski * so we don't set rate_node 7817cde4743SMichal Swiatkowski */ 7827cde4743SMichal Swiatkowski devl_rate_leaf_create(&sf->devlink_port, node, 7837cde4743SMichal Swiatkowski node->parent->rate_node); 7840545cc86SMichal Swiatkowski } else if (node->info.data.elem_type != ICE_AQC_ELEM_TYPE_LEAF && 7850545cc86SMichal Swiatkowski node->parent->rate_node) { 7860545cc86SMichal Swiatkowski rate_node = devl_rate_node_create(devlink, node, node->name, 7870545cc86SMichal Swiatkowski node->parent->rate_node); 7880545cc86SMichal Swiatkowski } 7890545cc86SMichal Swiatkowski 7900545cc86SMichal Swiatkowski if (rate_node && !IS_ERR(rate_node)) 7910545cc86SMichal Swiatkowski node->rate_node = rate_node; 7920545cc86SMichal Swiatkowski 7930545cc86SMichal Swiatkowski traverse_children: 7940545cc86SMichal Swiatkowski for (i = 0; i < node->num_children; i++) 7950545cc86SMichal Swiatkowski ice_traverse_tx_tree(devlink, node->children[i], tc_node, pf); 7960545cc86SMichal Swiatkowski } 7970545cc86SMichal Swiatkowski 7980545cc86SMichal Swiatkowski /** 7990545cc86SMichal Swiatkowski * ice_devlink_rate_init_tx_topology - export Tx scheduler tree to devlink rate 8000545cc86SMichal Swiatkowski * @devlink: devlink struct 8010545cc86SMichal Swiatkowski * @vsi: main vsi struct 8020545cc86SMichal Swiatkowski * 8030545cc86SMichal Swiatkowski * This function finds a root node, then calls ice_traverse_tx tree, which 8040545cc86SMichal Swiatkowski * traverses the tree and exports it's contents to devlink rate. 8050545cc86SMichal Swiatkowski */ 8060545cc86SMichal Swiatkowski int ice_devlink_rate_init_tx_topology(struct devlink *devlink, struct ice_vsi *vsi) 8070545cc86SMichal Swiatkowski { 8080545cc86SMichal Swiatkowski struct ice_port_info *pi = vsi->port_info; 8090545cc86SMichal Swiatkowski struct ice_sched_node *tc_node; 8100545cc86SMichal Swiatkowski struct ice_pf *pf = vsi->back; 8110545cc86SMichal Swiatkowski int i; 8120545cc86SMichal Swiatkowski 8130545cc86SMichal Swiatkowski tc_node = pi->root->children[0]; 8140545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 8150545cc86SMichal Swiatkowski for (i = 0; i < tc_node->num_children; i++) 8160545cc86SMichal Swiatkowski ice_traverse_tx_tree(devlink, tc_node->children[i], tc_node, pf); 8170545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 8180545cc86SMichal Swiatkowski 8190545cc86SMichal Swiatkowski return 0; 8200545cc86SMichal Swiatkowski } 8210545cc86SMichal Swiatkowski 8220545cc86SMichal Swiatkowski static void ice_clear_rate_nodes(struct ice_sched_node *node) 8230545cc86SMichal Swiatkowski { 8240545cc86SMichal Swiatkowski node->rate_node = NULL; 8250545cc86SMichal Swiatkowski 8260545cc86SMichal Swiatkowski for (int i = 0; i < node->num_children; i++) 8270545cc86SMichal Swiatkowski ice_clear_rate_nodes(node->children[i]); 8280545cc86SMichal Swiatkowski } 8290545cc86SMichal Swiatkowski 8300545cc86SMichal Swiatkowski /** 8310545cc86SMichal Swiatkowski * ice_devlink_rate_clear_tx_topology - clear node->rate_node 8320545cc86SMichal Swiatkowski * @vsi: main vsi struct 8330545cc86SMichal Swiatkowski * 8340545cc86SMichal Swiatkowski * Clear rate_node to cleanup creation of Tx topology. 8350545cc86SMichal Swiatkowski * 8360545cc86SMichal Swiatkowski */ 8370545cc86SMichal Swiatkowski void ice_devlink_rate_clear_tx_topology(struct ice_vsi *vsi) 8380545cc86SMichal Swiatkowski { 8390545cc86SMichal Swiatkowski struct ice_port_info *pi = vsi->port_info; 8400545cc86SMichal Swiatkowski 8410545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 8420545cc86SMichal Swiatkowski ice_clear_rate_nodes(pi->root->children[0]); 8430545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 8440545cc86SMichal Swiatkowski } 8450545cc86SMichal Swiatkowski 8460545cc86SMichal Swiatkowski /** 8470545cc86SMichal Swiatkowski * ice_set_object_tx_share - sets node scheduling parameter 8480545cc86SMichal Swiatkowski * @pi: devlink struct instance 8490545cc86SMichal Swiatkowski * @node: node struct instance 8500545cc86SMichal Swiatkowski * @bw: bandwidth in bytes per second 8510545cc86SMichal Swiatkowski * @extack: extended netdev ack structure 8520545cc86SMichal Swiatkowski * 8530545cc86SMichal Swiatkowski * This function sets ICE_MIN_BW scheduling BW limit. 8540545cc86SMichal Swiatkowski */ 8550545cc86SMichal Swiatkowski static int ice_set_object_tx_share(struct ice_port_info *pi, struct ice_sched_node *node, 8560545cc86SMichal Swiatkowski u64 bw, struct netlink_ext_ack *extack) 8570545cc86SMichal Swiatkowski { 8580545cc86SMichal Swiatkowski int status; 8590545cc86SMichal Swiatkowski 8600545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 8610545cc86SMichal Swiatkowski /* converts bytes per second to kilo bits per second */ 8620545cc86SMichal Swiatkowski node->tx_share = div_u64(bw, 125); 8630545cc86SMichal Swiatkowski status = ice_sched_set_node_bw_lmt(pi, node, ICE_MIN_BW, node->tx_share); 8640545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 8650545cc86SMichal Swiatkowski 8660545cc86SMichal Swiatkowski if (status) 8670545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Can't set scheduling node tx_share"); 8680545cc86SMichal Swiatkowski 8690545cc86SMichal Swiatkowski return status; 8700545cc86SMichal Swiatkowski } 8710545cc86SMichal Swiatkowski 8720545cc86SMichal Swiatkowski /** 8730545cc86SMichal Swiatkowski * ice_set_object_tx_max - sets node scheduling parameter 8740545cc86SMichal Swiatkowski * @pi: devlink struct instance 8750545cc86SMichal Swiatkowski * @node: node struct instance 8760545cc86SMichal Swiatkowski * @bw: bandwidth in bytes per second 8770545cc86SMichal Swiatkowski * @extack: extended netdev ack structure 8780545cc86SMichal Swiatkowski * 8790545cc86SMichal Swiatkowski * This function sets ICE_MAX_BW scheduling BW limit. 8800545cc86SMichal Swiatkowski */ 8810545cc86SMichal Swiatkowski static int ice_set_object_tx_max(struct ice_port_info *pi, struct ice_sched_node *node, 8820545cc86SMichal Swiatkowski u64 bw, struct netlink_ext_ack *extack) 8830545cc86SMichal Swiatkowski { 8840545cc86SMichal Swiatkowski int status; 8850545cc86SMichal Swiatkowski 8860545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 8870545cc86SMichal Swiatkowski /* converts bytes per second value to kilo bits per second */ 8880545cc86SMichal Swiatkowski node->tx_max = div_u64(bw, 125); 8890545cc86SMichal Swiatkowski status = ice_sched_set_node_bw_lmt(pi, node, ICE_MAX_BW, node->tx_max); 8900545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 8910545cc86SMichal Swiatkowski 8920545cc86SMichal Swiatkowski if (status) 8930545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Can't set scheduling node tx_max"); 8940545cc86SMichal Swiatkowski 8950545cc86SMichal Swiatkowski return status; 8960545cc86SMichal Swiatkowski } 8970545cc86SMichal Swiatkowski 8980545cc86SMichal Swiatkowski /** 8990545cc86SMichal Swiatkowski * ice_set_object_tx_priority - sets node scheduling parameter 9000545cc86SMichal Swiatkowski * @pi: devlink struct instance 9010545cc86SMichal Swiatkowski * @node: node struct instance 9020545cc86SMichal Swiatkowski * @priority: value representing priority for strict priority arbitration 9030545cc86SMichal Swiatkowski * @extack: extended netdev ack structure 9040545cc86SMichal Swiatkowski * 9050545cc86SMichal Swiatkowski * This function sets priority of node among siblings. 9060545cc86SMichal Swiatkowski */ 9070545cc86SMichal Swiatkowski static int ice_set_object_tx_priority(struct ice_port_info *pi, struct ice_sched_node *node, 9080545cc86SMichal Swiatkowski u32 priority, struct netlink_ext_ack *extack) 9090545cc86SMichal Swiatkowski { 9100545cc86SMichal Swiatkowski int status; 9110545cc86SMichal Swiatkowski 9120545cc86SMichal Swiatkowski if (priority >= 8) { 9130545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Priority should be less than 8"); 9140545cc86SMichal Swiatkowski return -EINVAL; 9150545cc86SMichal Swiatkowski } 9160545cc86SMichal Swiatkowski 9170545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 9180545cc86SMichal Swiatkowski node->tx_priority = priority; 9190545cc86SMichal Swiatkowski status = ice_sched_set_node_priority(pi, node, node->tx_priority); 9200545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 9210545cc86SMichal Swiatkowski 9220545cc86SMichal Swiatkowski if (status) 9230545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Can't set scheduling node tx_priority"); 9240545cc86SMichal Swiatkowski 9250545cc86SMichal Swiatkowski return status; 9260545cc86SMichal Swiatkowski } 9270545cc86SMichal Swiatkowski 9280545cc86SMichal Swiatkowski /** 9290545cc86SMichal Swiatkowski * ice_set_object_tx_weight - sets node scheduling parameter 9300545cc86SMichal Swiatkowski * @pi: devlink struct instance 9310545cc86SMichal Swiatkowski * @node: node struct instance 9320545cc86SMichal Swiatkowski * @weight: value represeting relative weight for WFQ arbitration 9330545cc86SMichal Swiatkowski * @extack: extended netdev ack structure 9340545cc86SMichal Swiatkowski * 9350545cc86SMichal Swiatkowski * This function sets node weight for WFQ algorithm. 9360545cc86SMichal Swiatkowski */ 9370545cc86SMichal Swiatkowski static int ice_set_object_tx_weight(struct ice_port_info *pi, struct ice_sched_node *node, 9380545cc86SMichal Swiatkowski u32 weight, struct netlink_ext_ack *extack) 9390545cc86SMichal Swiatkowski { 9400545cc86SMichal Swiatkowski int status; 9410545cc86SMichal Swiatkowski 9420545cc86SMichal Swiatkowski if (weight > 200 || weight < 1) { 9430545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Weight must be between 1 and 200"); 9440545cc86SMichal Swiatkowski return -EINVAL; 9450545cc86SMichal Swiatkowski } 9460545cc86SMichal Swiatkowski 9470545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 9480545cc86SMichal Swiatkowski node->tx_weight = weight; 9490545cc86SMichal Swiatkowski status = ice_sched_set_node_weight(pi, node, node->tx_weight); 9500545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 9510545cc86SMichal Swiatkowski 9520545cc86SMichal Swiatkowski if (status) 9530545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Can't set scheduling node tx_weight"); 9540545cc86SMichal Swiatkowski 9550545cc86SMichal Swiatkowski return status; 9560545cc86SMichal Swiatkowski } 9570545cc86SMichal Swiatkowski 9580545cc86SMichal Swiatkowski /** 9590545cc86SMichal Swiatkowski * ice_get_pi_from_dev_rate - get port info from devlink_rate 9600545cc86SMichal Swiatkowski * @rate_node: devlink struct instance 9610545cc86SMichal Swiatkowski * 9620545cc86SMichal Swiatkowski * This function returns corresponding port_info struct of devlink_rate 9630545cc86SMichal Swiatkowski */ 9640545cc86SMichal Swiatkowski static struct ice_port_info *ice_get_pi_from_dev_rate(struct devlink_rate *rate_node) 9650545cc86SMichal Swiatkowski { 9660545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(rate_node->devlink); 9670545cc86SMichal Swiatkowski 9680545cc86SMichal Swiatkowski return ice_get_main_vsi(pf)->port_info; 9690545cc86SMichal Swiatkowski } 9700545cc86SMichal Swiatkowski 9710545cc86SMichal Swiatkowski static int ice_devlink_rate_node_new(struct devlink_rate *rate_node, void **priv, 9720545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 9730545cc86SMichal Swiatkowski { 9740545cc86SMichal Swiatkowski struct ice_sched_node *node; 9750545cc86SMichal Swiatkowski struct ice_port_info *pi; 9760545cc86SMichal Swiatkowski 9770545cc86SMichal Swiatkowski pi = ice_get_pi_from_dev_rate(rate_node); 9780545cc86SMichal Swiatkowski 9790545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink))) 9800545cc86SMichal Swiatkowski return -EBUSY; 9810545cc86SMichal Swiatkowski 9820545cc86SMichal Swiatkowski /* preallocate memory for ice_sched_node */ 9830545cc86SMichal Swiatkowski node = devm_kzalloc(ice_hw_to_dev(pi->hw), sizeof(*node), GFP_KERNEL); 9840545cc86SMichal Swiatkowski *priv = node; 9850545cc86SMichal Swiatkowski 9860545cc86SMichal Swiatkowski return 0; 9870545cc86SMichal Swiatkowski } 9880545cc86SMichal Swiatkowski 9890545cc86SMichal Swiatkowski static int ice_devlink_rate_node_del(struct devlink_rate *rate_node, void *priv, 9900545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 9910545cc86SMichal Swiatkowski { 9920545cc86SMichal Swiatkowski struct ice_sched_node *node, *tc_node; 9930545cc86SMichal Swiatkowski struct ice_port_info *pi; 9940545cc86SMichal Swiatkowski 9950545cc86SMichal Swiatkowski pi = ice_get_pi_from_dev_rate(rate_node); 9960545cc86SMichal Swiatkowski tc_node = pi->root->children[0]; 9970545cc86SMichal Swiatkowski node = priv; 9980545cc86SMichal Swiatkowski 9990545cc86SMichal Swiatkowski if (!rate_node->parent || !node || tc_node == node || !extack) 10000545cc86SMichal Swiatkowski return 0; 10010545cc86SMichal Swiatkowski 10020545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink))) 10030545cc86SMichal Swiatkowski return -EBUSY; 10040545cc86SMichal Swiatkowski 10050545cc86SMichal Swiatkowski /* can't allow to delete a node with children */ 10060545cc86SMichal Swiatkowski if (node->num_children) 10070545cc86SMichal Swiatkowski return -EINVAL; 10080545cc86SMichal Swiatkowski 10090545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 10100545cc86SMichal Swiatkowski ice_free_sched_node(pi, node); 10110545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 10120545cc86SMichal Swiatkowski 10130545cc86SMichal Swiatkowski return 0; 10140545cc86SMichal Swiatkowski } 10150545cc86SMichal Swiatkowski 10160545cc86SMichal Swiatkowski static int ice_devlink_rate_leaf_tx_max_set(struct devlink_rate *rate_leaf, void *priv, 10170545cc86SMichal Swiatkowski u64 tx_max, struct netlink_ext_ack *extack) 10180545cc86SMichal Swiatkowski { 10190545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 10200545cc86SMichal Swiatkowski 10210545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_leaf->devlink))) 10220545cc86SMichal Swiatkowski return -EBUSY; 10230545cc86SMichal Swiatkowski 10240545cc86SMichal Swiatkowski if (!node) 10250545cc86SMichal Swiatkowski return 0; 10260545cc86SMichal Swiatkowski 10270545cc86SMichal Swiatkowski return ice_set_object_tx_max(ice_get_pi_from_dev_rate(rate_leaf), 10280545cc86SMichal Swiatkowski node, tx_max, extack); 10290545cc86SMichal Swiatkowski } 10300545cc86SMichal Swiatkowski 10310545cc86SMichal Swiatkowski static int ice_devlink_rate_leaf_tx_share_set(struct devlink_rate *rate_leaf, void *priv, 10320545cc86SMichal Swiatkowski u64 tx_share, struct netlink_ext_ack *extack) 10330545cc86SMichal Swiatkowski { 10340545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 10350545cc86SMichal Swiatkowski 10360545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_leaf->devlink))) 10370545cc86SMichal Swiatkowski return -EBUSY; 10380545cc86SMichal Swiatkowski 10390545cc86SMichal Swiatkowski if (!node) 10400545cc86SMichal Swiatkowski return 0; 10410545cc86SMichal Swiatkowski 10420545cc86SMichal Swiatkowski return ice_set_object_tx_share(ice_get_pi_from_dev_rate(rate_leaf), node, 10430545cc86SMichal Swiatkowski tx_share, extack); 10440545cc86SMichal Swiatkowski } 10450545cc86SMichal Swiatkowski 10460545cc86SMichal Swiatkowski static int ice_devlink_rate_leaf_tx_priority_set(struct devlink_rate *rate_leaf, void *priv, 10470545cc86SMichal Swiatkowski u32 tx_priority, struct netlink_ext_ack *extack) 10480545cc86SMichal Swiatkowski { 10490545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 10500545cc86SMichal Swiatkowski 10510545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_leaf->devlink))) 10520545cc86SMichal Swiatkowski return -EBUSY; 10530545cc86SMichal Swiatkowski 10540545cc86SMichal Swiatkowski if (!node) 10550545cc86SMichal Swiatkowski return 0; 10560545cc86SMichal Swiatkowski 10570545cc86SMichal Swiatkowski return ice_set_object_tx_priority(ice_get_pi_from_dev_rate(rate_leaf), node, 10580545cc86SMichal Swiatkowski tx_priority, extack); 10590545cc86SMichal Swiatkowski } 10600545cc86SMichal Swiatkowski 10610545cc86SMichal Swiatkowski static int ice_devlink_rate_leaf_tx_weight_set(struct devlink_rate *rate_leaf, void *priv, 10620545cc86SMichal Swiatkowski u32 tx_weight, struct netlink_ext_ack *extack) 10630545cc86SMichal Swiatkowski { 10640545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 10650545cc86SMichal Swiatkowski 10660545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_leaf->devlink))) 10670545cc86SMichal Swiatkowski return -EBUSY; 10680545cc86SMichal Swiatkowski 10690545cc86SMichal Swiatkowski if (!node) 10700545cc86SMichal Swiatkowski return 0; 10710545cc86SMichal Swiatkowski 10720545cc86SMichal Swiatkowski return ice_set_object_tx_weight(ice_get_pi_from_dev_rate(rate_leaf), node, 10730545cc86SMichal Swiatkowski tx_weight, extack); 10740545cc86SMichal Swiatkowski } 10750545cc86SMichal Swiatkowski 10760545cc86SMichal Swiatkowski static int ice_devlink_rate_node_tx_max_set(struct devlink_rate *rate_node, void *priv, 10770545cc86SMichal Swiatkowski u64 tx_max, struct netlink_ext_ack *extack) 10780545cc86SMichal Swiatkowski { 10790545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 10800545cc86SMichal Swiatkowski 10810545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink))) 10820545cc86SMichal Swiatkowski return -EBUSY; 10830545cc86SMichal Swiatkowski 10840545cc86SMichal Swiatkowski if (!node) 10850545cc86SMichal Swiatkowski return 0; 10860545cc86SMichal Swiatkowski 10870545cc86SMichal Swiatkowski return ice_set_object_tx_max(ice_get_pi_from_dev_rate(rate_node), 10880545cc86SMichal Swiatkowski node, tx_max, extack); 10890545cc86SMichal Swiatkowski } 10900545cc86SMichal Swiatkowski 10910545cc86SMichal Swiatkowski static int ice_devlink_rate_node_tx_share_set(struct devlink_rate *rate_node, void *priv, 10920545cc86SMichal Swiatkowski u64 tx_share, struct netlink_ext_ack *extack) 10930545cc86SMichal Swiatkowski { 10940545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 10950545cc86SMichal Swiatkowski 10960545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink))) 10970545cc86SMichal Swiatkowski return -EBUSY; 10980545cc86SMichal Swiatkowski 10990545cc86SMichal Swiatkowski if (!node) 11000545cc86SMichal Swiatkowski return 0; 11010545cc86SMichal Swiatkowski 11020545cc86SMichal Swiatkowski return ice_set_object_tx_share(ice_get_pi_from_dev_rate(rate_node), 11030545cc86SMichal Swiatkowski node, tx_share, extack); 11040545cc86SMichal Swiatkowski } 11050545cc86SMichal Swiatkowski 11060545cc86SMichal Swiatkowski static int ice_devlink_rate_node_tx_priority_set(struct devlink_rate *rate_node, void *priv, 11070545cc86SMichal Swiatkowski u32 tx_priority, struct netlink_ext_ack *extack) 11080545cc86SMichal Swiatkowski { 11090545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 11100545cc86SMichal Swiatkowski 11110545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink))) 11120545cc86SMichal Swiatkowski return -EBUSY; 11130545cc86SMichal Swiatkowski 11140545cc86SMichal Swiatkowski if (!node) 11150545cc86SMichal Swiatkowski return 0; 11160545cc86SMichal Swiatkowski 11170545cc86SMichal Swiatkowski return ice_set_object_tx_priority(ice_get_pi_from_dev_rate(rate_node), 11180545cc86SMichal Swiatkowski node, tx_priority, extack); 11190545cc86SMichal Swiatkowski } 11200545cc86SMichal Swiatkowski 11210545cc86SMichal Swiatkowski static int ice_devlink_rate_node_tx_weight_set(struct devlink_rate *rate_node, void *priv, 11220545cc86SMichal Swiatkowski u32 tx_weight, struct netlink_ext_ack *extack) 11230545cc86SMichal Swiatkowski { 11240545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 11250545cc86SMichal Swiatkowski 11260545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink))) 11270545cc86SMichal Swiatkowski return -EBUSY; 11280545cc86SMichal Swiatkowski 11290545cc86SMichal Swiatkowski if (!node) 11300545cc86SMichal Swiatkowski return 0; 11310545cc86SMichal Swiatkowski 11320545cc86SMichal Swiatkowski return ice_set_object_tx_weight(ice_get_pi_from_dev_rate(rate_node), 11330545cc86SMichal Swiatkowski node, tx_weight, extack); 11340545cc86SMichal Swiatkowski } 11350545cc86SMichal Swiatkowski 11360545cc86SMichal Swiatkowski static int ice_devlink_set_parent(struct devlink_rate *devlink_rate, 11370545cc86SMichal Swiatkowski struct devlink_rate *parent, 11380545cc86SMichal Swiatkowski void *priv, void *parent_priv, 11390545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 11400545cc86SMichal Swiatkowski { 11410545cc86SMichal Swiatkowski struct ice_port_info *pi = ice_get_pi_from_dev_rate(devlink_rate); 11420545cc86SMichal Swiatkowski struct ice_sched_node *tc_node, *node, *parent_node; 11430545cc86SMichal Swiatkowski u16 num_nodes_added; 11440545cc86SMichal Swiatkowski u32 first_node_teid; 11450545cc86SMichal Swiatkowski u32 node_teid; 11460545cc86SMichal Swiatkowski int status; 11470545cc86SMichal Swiatkowski 11480545cc86SMichal Swiatkowski tc_node = pi->root->children[0]; 11490545cc86SMichal Swiatkowski node = priv; 11500545cc86SMichal Swiatkowski 11510545cc86SMichal Swiatkowski if (!extack) 11520545cc86SMichal Swiatkowski return 0; 11530545cc86SMichal Swiatkowski 11540545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(devlink_rate->devlink))) 11550545cc86SMichal Swiatkowski return -EBUSY; 11560545cc86SMichal Swiatkowski 11570545cc86SMichal Swiatkowski if (!parent) { 11580545cc86SMichal Swiatkowski if (!node || tc_node == node || node->num_children) 11590545cc86SMichal Swiatkowski return -EINVAL; 11600545cc86SMichal Swiatkowski 11610545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 11620545cc86SMichal Swiatkowski ice_free_sched_node(pi, node); 11630545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 11640545cc86SMichal Swiatkowski 11650545cc86SMichal Swiatkowski return 0; 11660545cc86SMichal Swiatkowski } 11670545cc86SMichal Swiatkowski 11680545cc86SMichal Swiatkowski parent_node = parent_priv; 11690545cc86SMichal Swiatkowski 11700545cc86SMichal Swiatkowski /* if the node doesn't exist, create it */ 11710545cc86SMichal Swiatkowski if (!node->parent) { 11720545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 11730545cc86SMichal Swiatkowski status = ice_sched_add_elems(pi, tc_node, parent_node, 11740545cc86SMichal Swiatkowski parent_node->tx_sched_layer + 1, 11750545cc86SMichal Swiatkowski 1, &num_nodes_added, &first_node_teid, 11760545cc86SMichal Swiatkowski &node); 11770545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 11780545cc86SMichal Swiatkowski 11790545cc86SMichal Swiatkowski if (status) { 11800545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Can't add a new node"); 11810545cc86SMichal Swiatkowski return status; 11820545cc86SMichal Swiatkowski } 11830545cc86SMichal Swiatkowski 11840545cc86SMichal Swiatkowski if (devlink_rate->tx_share) 11850545cc86SMichal Swiatkowski ice_set_object_tx_share(pi, node, devlink_rate->tx_share, extack); 11860545cc86SMichal Swiatkowski if (devlink_rate->tx_max) 11870545cc86SMichal Swiatkowski ice_set_object_tx_max(pi, node, devlink_rate->tx_max, extack); 11880545cc86SMichal Swiatkowski if (devlink_rate->tx_priority) 11890545cc86SMichal Swiatkowski ice_set_object_tx_priority(pi, node, devlink_rate->tx_priority, extack); 11900545cc86SMichal Swiatkowski if (devlink_rate->tx_weight) 11910545cc86SMichal Swiatkowski ice_set_object_tx_weight(pi, node, devlink_rate->tx_weight, extack); 11920545cc86SMichal Swiatkowski } else { 11930545cc86SMichal Swiatkowski node_teid = le32_to_cpu(node->info.node_teid); 11940545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 11950545cc86SMichal Swiatkowski status = ice_sched_move_nodes(pi, parent_node, 1, &node_teid); 11960545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 11970545cc86SMichal Swiatkowski 11980545cc86SMichal Swiatkowski if (status) 11990545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Can't move existing node to a new parent"); 12000545cc86SMichal Swiatkowski } 12010545cc86SMichal Swiatkowski 12020545cc86SMichal Swiatkowski return status; 12030545cc86SMichal Swiatkowski } 12040545cc86SMichal Swiatkowski 1205*b2657259SMichal Swiatkowski static void ice_set_min_max_msix(struct ice_pf *pf) 1206*b2657259SMichal Swiatkowski { 1207*b2657259SMichal Swiatkowski struct devlink *devlink = priv_to_devlink(pf); 1208*b2657259SMichal Swiatkowski union devlink_param_value val; 1209*b2657259SMichal Swiatkowski int err; 1210*b2657259SMichal Swiatkowski 1211*b2657259SMichal Swiatkowski err = devl_param_driverinit_value_get(devlink, 1212*b2657259SMichal Swiatkowski DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN, 1213*b2657259SMichal Swiatkowski &val); 1214*b2657259SMichal Swiatkowski if (!err) 1215*b2657259SMichal Swiatkowski pf->msix.min = val.vu32; 1216*b2657259SMichal Swiatkowski 1217*b2657259SMichal Swiatkowski err = devl_param_driverinit_value_get(devlink, 1218*b2657259SMichal Swiatkowski DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX, 1219*b2657259SMichal Swiatkowski &val); 1220*b2657259SMichal Swiatkowski if (!err) 1221*b2657259SMichal Swiatkowski pf->msix.max = val.vu32; 1222*b2657259SMichal Swiatkowski } 1223*b2657259SMichal Swiatkowski 12240545cc86SMichal Swiatkowski /** 12250545cc86SMichal Swiatkowski * ice_devlink_reinit_up - do reinit of the given PF 12260545cc86SMichal Swiatkowski * @pf: pointer to the PF struct 12270545cc86SMichal Swiatkowski */ 12280545cc86SMichal Swiatkowski static int ice_devlink_reinit_up(struct ice_pf *pf) 12290545cc86SMichal Swiatkowski { 12300545cc86SMichal Swiatkowski struct ice_vsi *vsi = ice_get_main_vsi(pf); 12310545cc86SMichal Swiatkowski int err; 12320545cc86SMichal Swiatkowski 12334d3f59bfSPrzemek Kitszel err = ice_init_hw(&pf->hw); 12344d3f59bfSPrzemek Kitszel if (err) { 12354d3f59bfSPrzemek Kitszel dev_err(ice_pf_to_dev(pf), "ice_init_hw failed: %d\n", err); 12364d3f59bfSPrzemek Kitszel return err; 12374d3f59bfSPrzemek Kitszel } 12384d3f59bfSPrzemek Kitszel 1239*b2657259SMichal Swiatkowski /* load MSI-X values */ 1240*b2657259SMichal Swiatkowski ice_set_min_max_msix(pf); 1241*b2657259SMichal Swiatkowski 12420545cc86SMichal Swiatkowski err = ice_init_dev(pf); 12430545cc86SMichal Swiatkowski if (err) 12444d3f59bfSPrzemek Kitszel goto unroll_hw_init; 12450545cc86SMichal Swiatkowski 1246deea427fSMateusz Polchlopek vsi->flags = ICE_VSI_FLAG_INIT; 12470545cc86SMichal Swiatkowski 12480545cc86SMichal Swiatkowski rtnl_lock(); 1249deea427fSMateusz Polchlopek err = ice_vsi_cfg(vsi); 12500545cc86SMichal Swiatkowski rtnl_unlock(); 12510545cc86SMichal Swiatkowski if (err) 12520545cc86SMichal Swiatkowski goto err_vsi_cfg; 12530545cc86SMichal Swiatkowski 12540545cc86SMichal Swiatkowski /* No need to take devl_lock, it's already taken by devlink API */ 12550545cc86SMichal Swiatkowski err = ice_load(pf); 12560545cc86SMichal Swiatkowski if (err) 12570545cc86SMichal Swiatkowski goto err_load; 12580545cc86SMichal Swiatkowski 12590545cc86SMichal Swiatkowski return 0; 12600545cc86SMichal Swiatkowski 12610545cc86SMichal Swiatkowski err_load: 12620545cc86SMichal Swiatkowski rtnl_lock(); 12630545cc86SMichal Swiatkowski ice_vsi_decfg(vsi); 12640545cc86SMichal Swiatkowski rtnl_unlock(); 12650545cc86SMichal Swiatkowski err_vsi_cfg: 12660545cc86SMichal Swiatkowski ice_deinit_dev(pf); 12674d3f59bfSPrzemek Kitszel unroll_hw_init: 12684d3f59bfSPrzemek Kitszel ice_deinit_hw(&pf->hw); 12690545cc86SMichal Swiatkowski return err; 12700545cc86SMichal Swiatkowski } 12710545cc86SMichal Swiatkowski 12720545cc86SMichal Swiatkowski /** 12730545cc86SMichal Swiatkowski * ice_devlink_reload_up - do reload up after reinit 12740545cc86SMichal Swiatkowski * @devlink: pointer to the devlink instance reloading 12750545cc86SMichal Swiatkowski * @action: the action requested 12760545cc86SMichal Swiatkowski * @limit: limits imposed by userspace, such as not resetting 12770545cc86SMichal Swiatkowski * @actions_performed: on return, indicate what actions actually performed 12780545cc86SMichal Swiatkowski * @extack: netlink extended ACK structure 12790545cc86SMichal Swiatkowski */ 12800545cc86SMichal Swiatkowski static int 12810545cc86SMichal Swiatkowski ice_devlink_reload_up(struct devlink *devlink, 12820545cc86SMichal Swiatkowski enum devlink_reload_action action, 12830545cc86SMichal Swiatkowski enum devlink_reload_limit limit, 12840545cc86SMichal Swiatkowski u32 *actions_performed, 12850545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 12860545cc86SMichal Swiatkowski { 12870545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 12880545cc86SMichal Swiatkowski 12890545cc86SMichal Swiatkowski switch (action) { 12900545cc86SMichal Swiatkowski case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: 12910545cc86SMichal Swiatkowski *actions_performed = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT); 12920545cc86SMichal Swiatkowski return ice_devlink_reinit_up(pf); 12930545cc86SMichal Swiatkowski case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: 12940545cc86SMichal Swiatkowski *actions_performed = BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE); 12950545cc86SMichal Swiatkowski return ice_devlink_reload_empr_finish(pf, extack); 12960545cc86SMichal Swiatkowski default: 12970545cc86SMichal Swiatkowski WARN_ON(1); 12980545cc86SMichal Swiatkowski return -EOPNOTSUPP; 12990545cc86SMichal Swiatkowski } 13000545cc86SMichal Swiatkowski } 13010545cc86SMichal Swiatkowski 13020545cc86SMichal Swiatkowski static const struct devlink_ops ice_devlink_ops = { 13030545cc86SMichal Swiatkowski .supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK, 13040545cc86SMichal Swiatkowski .reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) | 13050545cc86SMichal Swiatkowski BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE), 13060545cc86SMichal Swiatkowski .reload_down = ice_devlink_reload_down, 13070545cc86SMichal Swiatkowski .reload_up = ice_devlink_reload_up, 13080545cc86SMichal Swiatkowski .eswitch_mode_get = ice_eswitch_mode_get, 13090545cc86SMichal Swiatkowski .eswitch_mode_set = ice_eswitch_mode_set, 13100545cc86SMichal Swiatkowski .info_get = ice_devlink_info_get, 13110545cc86SMichal Swiatkowski .flash_update = ice_devlink_flash_update, 13120545cc86SMichal Swiatkowski 13130545cc86SMichal Swiatkowski .rate_node_new = ice_devlink_rate_node_new, 13140545cc86SMichal Swiatkowski .rate_node_del = ice_devlink_rate_node_del, 13150545cc86SMichal Swiatkowski 13160545cc86SMichal Swiatkowski .rate_leaf_tx_max_set = ice_devlink_rate_leaf_tx_max_set, 13170545cc86SMichal Swiatkowski .rate_leaf_tx_share_set = ice_devlink_rate_leaf_tx_share_set, 13180545cc86SMichal Swiatkowski .rate_leaf_tx_priority_set = ice_devlink_rate_leaf_tx_priority_set, 13190545cc86SMichal Swiatkowski .rate_leaf_tx_weight_set = ice_devlink_rate_leaf_tx_weight_set, 13200545cc86SMichal Swiatkowski 13210545cc86SMichal Swiatkowski .rate_node_tx_max_set = ice_devlink_rate_node_tx_max_set, 13220545cc86SMichal Swiatkowski .rate_node_tx_share_set = ice_devlink_rate_node_tx_share_set, 13230545cc86SMichal Swiatkowski .rate_node_tx_priority_set = ice_devlink_rate_node_tx_priority_set, 13240545cc86SMichal Swiatkowski .rate_node_tx_weight_set = ice_devlink_rate_node_tx_weight_set, 13250545cc86SMichal Swiatkowski 13260545cc86SMichal Swiatkowski .rate_leaf_parent_set = ice_devlink_set_parent, 13270545cc86SMichal Swiatkowski .rate_node_parent_set = ice_devlink_set_parent, 1328eda69d65SPiotr Raczynski 1329eda69d65SPiotr Raczynski .port_new = ice_devlink_port_new, 13300545cc86SMichal Swiatkowski }; 13310545cc86SMichal Swiatkowski 1332f43e3be6SPiotr Raczynski static const struct devlink_ops ice_sf_devlink_ops; 1333f43e3be6SPiotr Raczynski 13340545cc86SMichal Swiatkowski static int 13350545cc86SMichal Swiatkowski ice_devlink_enable_roce_get(struct devlink *devlink, u32 id, 13360545cc86SMichal Swiatkowski struct devlink_param_gset_ctx *ctx) 13370545cc86SMichal Swiatkowski { 13380545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 13390545cc86SMichal Swiatkowski 13400545cc86SMichal Swiatkowski ctx->val.vbool = pf->rdma_mode & IIDC_RDMA_PROTOCOL_ROCEV2 ? true : false; 13410545cc86SMichal Swiatkowski 13420545cc86SMichal Swiatkowski return 0; 13430545cc86SMichal Swiatkowski } 13440545cc86SMichal Swiatkowski 13455625ca56SMateusz Polchlopek static int ice_devlink_enable_roce_set(struct devlink *devlink, u32 id, 13465625ca56SMateusz Polchlopek struct devlink_param_gset_ctx *ctx, 13475625ca56SMateusz Polchlopek struct netlink_ext_ack *extack) 13480545cc86SMichal Swiatkowski { 13490545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 13500545cc86SMichal Swiatkowski bool roce_ena = ctx->val.vbool; 13510545cc86SMichal Swiatkowski int ret; 13520545cc86SMichal Swiatkowski 13530545cc86SMichal Swiatkowski if (!roce_ena) { 13540545cc86SMichal Swiatkowski ice_unplug_aux_dev(pf); 13550545cc86SMichal Swiatkowski pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_ROCEV2; 13560545cc86SMichal Swiatkowski return 0; 13570545cc86SMichal Swiatkowski } 13580545cc86SMichal Swiatkowski 13590545cc86SMichal Swiatkowski pf->rdma_mode |= IIDC_RDMA_PROTOCOL_ROCEV2; 13600545cc86SMichal Swiatkowski ret = ice_plug_aux_dev(pf); 13610545cc86SMichal Swiatkowski if (ret) 13620545cc86SMichal Swiatkowski pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_ROCEV2; 13630545cc86SMichal Swiatkowski 13640545cc86SMichal Swiatkowski return ret; 13650545cc86SMichal Swiatkowski } 13660545cc86SMichal Swiatkowski 13670545cc86SMichal Swiatkowski static int 13680545cc86SMichal Swiatkowski ice_devlink_enable_roce_validate(struct devlink *devlink, u32 id, 13690545cc86SMichal Swiatkowski union devlink_param_value val, 13700545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 13710545cc86SMichal Swiatkowski { 13720545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 13730545cc86SMichal Swiatkowski 13740545cc86SMichal Swiatkowski if (!test_bit(ICE_FLAG_RDMA_ENA, pf->flags)) 13750545cc86SMichal Swiatkowski return -EOPNOTSUPP; 13760545cc86SMichal Swiatkowski 13770545cc86SMichal Swiatkowski if (pf->rdma_mode & IIDC_RDMA_PROTOCOL_IWARP) { 13780545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "iWARP is currently enabled. This device cannot enable iWARP and RoCEv2 simultaneously"); 13790545cc86SMichal Swiatkowski return -EOPNOTSUPP; 13800545cc86SMichal Swiatkowski } 13810545cc86SMichal Swiatkowski 13820545cc86SMichal Swiatkowski return 0; 13830545cc86SMichal Swiatkowski } 13840545cc86SMichal Swiatkowski 13850545cc86SMichal Swiatkowski static int 13860545cc86SMichal Swiatkowski ice_devlink_enable_iw_get(struct devlink *devlink, u32 id, 13870545cc86SMichal Swiatkowski struct devlink_param_gset_ctx *ctx) 13880545cc86SMichal Swiatkowski { 13890545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 13900545cc86SMichal Swiatkowski 13910545cc86SMichal Swiatkowski ctx->val.vbool = pf->rdma_mode & IIDC_RDMA_PROTOCOL_IWARP; 13920545cc86SMichal Swiatkowski 13930545cc86SMichal Swiatkowski return 0; 13940545cc86SMichal Swiatkowski } 13950545cc86SMichal Swiatkowski 13965625ca56SMateusz Polchlopek static int ice_devlink_enable_iw_set(struct devlink *devlink, u32 id, 13975625ca56SMateusz Polchlopek struct devlink_param_gset_ctx *ctx, 13985625ca56SMateusz Polchlopek struct netlink_ext_ack *extack) 13990545cc86SMichal Swiatkowski { 14000545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 14010545cc86SMichal Swiatkowski bool iw_ena = ctx->val.vbool; 14020545cc86SMichal Swiatkowski int ret; 14030545cc86SMichal Swiatkowski 14040545cc86SMichal Swiatkowski if (!iw_ena) { 14050545cc86SMichal Swiatkowski ice_unplug_aux_dev(pf); 14060545cc86SMichal Swiatkowski pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_IWARP; 14070545cc86SMichal Swiatkowski return 0; 14080545cc86SMichal Swiatkowski } 14090545cc86SMichal Swiatkowski 14100545cc86SMichal Swiatkowski pf->rdma_mode |= IIDC_RDMA_PROTOCOL_IWARP; 14110545cc86SMichal Swiatkowski ret = ice_plug_aux_dev(pf); 14120545cc86SMichal Swiatkowski if (ret) 14130545cc86SMichal Swiatkowski pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_IWARP; 14140545cc86SMichal Swiatkowski 14150545cc86SMichal Swiatkowski return ret; 14160545cc86SMichal Swiatkowski } 14170545cc86SMichal Swiatkowski 14180545cc86SMichal Swiatkowski static int 14190545cc86SMichal Swiatkowski ice_devlink_enable_iw_validate(struct devlink *devlink, u32 id, 14200545cc86SMichal Swiatkowski union devlink_param_value val, 14210545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 14220545cc86SMichal Swiatkowski { 14230545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 14240545cc86SMichal Swiatkowski 14250545cc86SMichal Swiatkowski if (!test_bit(ICE_FLAG_RDMA_ENA, pf->flags)) 14260545cc86SMichal Swiatkowski return -EOPNOTSUPP; 14270545cc86SMichal Swiatkowski 14280545cc86SMichal Swiatkowski if (pf->rdma_mode & IIDC_RDMA_PROTOCOL_ROCEV2) { 14290545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "RoCEv2 is currently enabled. This device cannot enable iWARP and RoCEv2 simultaneously"); 14300545cc86SMichal Swiatkowski return -EOPNOTSUPP; 14310545cc86SMichal Swiatkowski } 14320545cc86SMichal Swiatkowski 14330545cc86SMichal Swiatkowski return 0; 14340545cc86SMichal Swiatkowski } 14350545cc86SMichal Swiatkowski 1436a59618b9SPawel Kaminski #define DEVLINK_LOCAL_FWD_DISABLED_STR "disabled" 1437a59618b9SPawel Kaminski #define DEVLINK_LOCAL_FWD_ENABLED_STR "enabled" 1438a59618b9SPawel Kaminski #define DEVLINK_LOCAL_FWD_PRIORITIZED_STR "prioritized" 1439a59618b9SPawel Kaminski 1440a59618b9SPawel Kaminski /** 1441a59618b9SPawel Kaminski * ice_devlink_local_fwd_mode_to_str - Get string for local_fwd mode. 1442a59618b9SPawel Kaminski * @mode: local forwarding for mode used in port_info struct. 1443a59618b9SPawel Kaminski * 1444a59618b9SPawel Kaminski * Return: Mode respective string or "Invalid". 1445a59618b9SPawel Kaminski */ 1446a59618b9SPawel Kaminski static const char * 1447a59618b9SPawel Kaminski ice_devlink_local_fwd_mode_to_str(enum ice_local_fwd_mode mode) 1448a59618b9SPawel Kaminski { 1449a59618b9SPawel Kaminski switch (mode) { 1450a59618b9SPawel Kaminski case ICE_LOCAL_FWD_MODE_ENABLED: 1451a59618b9SPawel Kaminski return DEVLINK_LOCAL_FWD_ENABLED_STR; 1452a59618b9SPawel Kaminski case ICE_LOCAL_FWD_MODE_PRIORITIZED: 1453a59618b9SPawel Kaminski return DEVLINK_LOCAL_FWD_PRIORITIZED_STR; 1454a59618b9SPawel Kaminski case ICE_LOCAL_FWD_MODE_DISABLED: 1455a59618b9SPawel Kaminski return DEVLINK_LOCAL_FWD_DISABLED_STR; 1456a59618b9SPawel Kaminski } 1457a59618b9SPawel Kaminski 1458a59618b9SPawel Kaminski return "Invalid"; 1459a59618b9SPawel Kaminski } 1460a59618b9SPawel Kaminski 1461a59618b9SPawel Kaminski /** 1462a59618b9SPawel Kaminski * ice_devlink_local_fwd_str_to_mode - Get local_fwd mode from string name. 1463a59618b9SPawel Kaminski * @mode_str: local forwarding mode string. 1464a59618b9SPawel Kaminski * 1465a59618b9SPawel Kaminski * Return: Mode value or negative number if invalid. 1466a59618b9SPawel Kaminski */ 1467a59618b9SPawel Kaminski static int ice_devlink_local_fwd_str_to_mode(const char *mode_str) 1468a59618b9SPawel Kaminski { 1469a59618b9SPawel Kaminski if (!strcmp(mode_str, DEVLINK_LOCAL_FWD_ENABLED_STR)) 1470a59618b9SPawel Kaminski return ICE_LOCAL_FWD_MODE_ENABLED; 1471a59618b9SPawel Kaminski else if (!strcmp(mode_str, DEVLINK_LOCAL_FWD_PRIORITIZED_STR)) 1472a59618b9SPawel Kaminski return ICE_LOCAL_FWD_MODE_PRIORITIZED; 1473a59618b9SPawel Kaminski else if (!strcmp(mode_str, DEVLINK_LOCAL_FWD_DISABLED_STR)) 1474a59618b9SPawel Kaminski return ICE_LOCAL_FWD_MODE_DISABLED; 1475a59618b9SPawel Kaminski 1476a59618b9SPawel Kaminski return -EINVAL; 1477a59618b9SPawel Kaminski } 1478a59618b9SPawel Kaminski 1479a59618b9SPawel Kaminski /** 1480a59618b9SPawel Kaminski * ice_devlink_local_fwd_get - Get local_fwd parameter. 1481a59618b9SPawel Kaminski * @devlink: Pointer to the devlink instance. 1482a59618b9SPawel Kaminski * @id: The parameter ID to set. 1483a59618b9SPawel Kaminski * @ctx: Context to store the parameter value. 1484a59618b9SPawel Kaminski * 1485a59618b9SPawel Kaminski * Return: Zero. 1486a59618b9SPawel Kaminski */ 1487a59618b9SPawel Kaminski static int ice_devlink_local_fwd_get(struct devlink *devlink, u32 id, 1488a59618b9SPawel Kaminski struct devlink_param_gset_ctx *ctx) 1489a59618b9SPawel Kaminski { 1490a59618b9SPawel Kaminski struct ice_pf *pf = devlink_priv(devlink); 1491a59618b9SPawel Kaminski struct ice_port_info *pi; 1492a59618b9SPawel Kaminski const char *mode_str; 1493a59618b9SPawel Kaminski 1494a59618b9SPawel Kaminski pi = pf->hw.port_info; 1495a59618b9SPawel Kaminski mode_str = ice_devlink_local_fwd_mode_to_str(pi->local_fwd_mode); 1496a59618b9SPawel Kaminski snprintf(ctx->val.vstr, sizeof(ctx->val.vstr), "%s", mode_str); 1497a59618b9SPawel Kaminski 1498a59618b9SPawel Kaminski return 0; 1499a59618b9SPawel Kaminski } 1500a59618b9SPawel Kaminski 1501a59618b9SPawel Kaminski /** 1502a59618b9SPawel Kaminski * ice_devlink_local_fwd_set - Set local_fwd parameter. 1503a59618b9SPawel Kaminski * @devlink: Pointer to the devlink instance. 1504a59618b9SPawel Kaminski * @id: The parameter ID to set. 1505a59618b9SPawel Kaminski * @ctx: Context to get the parameter value. 1506a59618b9SPawel Kaminski * @extack: Netlink extended ACK structure. 1507a59618b9SPawel Kaminski * 1508a59618b9SPawel Kaminski * Return: Zero. 1509a59618b9SPawel Kaminski */ 1510a59618b9SPawel Kaminski static int ice_devlink_local_fwd_set(struct devlink *devlink, u32 id, 1511a59618b9SPawel Kaminski struct devlink_param_gset_ctx *ctx, 1512a59618b9SPawel Kaminski struct netlink_ext_ack *extack) 1513a59618b9SPawel Kaminski { 1514a59618b9SPawel Kaminski int new_local_fwd_mode = ice_devlink_local_fwd_str_to_mode(ctx->val.vstr); 1515a59618b9SPawel Kaminski struct ice_pf *pf = devlink_priv(devlink); 1516a59618b9SPawel Kaminski struct device *dev = ice_pf_to_dev(pf); 1517a59618b9SPawel Kaminski struct ice_port_info *pi; 1518a59618b9SPawel Kaminski 1519a59618b9SPawel Kaminski pi = pf->hw.port_info; 1520a59618b9SPawel Kaminski if (pi->local_fwd_mode != new_local_fwd_mode) { 1521a59618b9SPawel Kaminski pi->local_fwd_mode = new_local_fwd_mode; 1522a59618b9SPawel Kaminski dev_info(dev, "Setting local_fwd to %s\n", ctx->val.vstr); 1523a59618b9SPawel Kaminski ice_schedule_reset(pf, ICE_RESET_CORER); 1524a59618b9SPawel Kaminski } 1525a59618b9SPawel Kaminski 1526a59618b9SPawel Kaminski return 0; 1527a59618b9SPawel Kaminski } 1528a59618b9SPawel Kaminski 1529a59618b9SPawel Kaminski /** 1530a59618b9SPawel Kaminski * ice_devlink_local_fwd_validate - Validate passed local_fwd parameter value. 1531a59618b9SPawel Kaminski * @devlink: Unused pointer to devlink instance. 1532a59618b9SPawel Kaminski * @id: The parameter ID to validate. 1533a59618b9SPawel Kaminski * @val: Value to validate. 1534a59618b9SPawel Kaminski * @extack: Netlink extended ACK structure. 1535a59618b9SPawel Kaminski * 1536a59618b9SPawel Kaminski * Supported values are: 1537a59618b9SPawel Kaminski * "enabled" - local_fwd is enabled, "disabled" - local_fwd is disabled 1538a59618b9SPawel Kaminski * "prioritized" - local_fwd traffic is prioritized in scheduling. 1539a59618b9SPawel Kaminski * 1540a59618b9SPawel Kaminski * Return: Zero when passed parameter value is supported. Negative value on 1541a59618b9SPawel Kaminski * error. 1542a59618b9SPawel Kaminski */ 1543a59618b9SPawel Kaminski static int ice_devlink_local_fwd_validate(struct devlink *devlink, u32 id, 1544a59618b9SPawel Kaminski union devlink_param_value val, 1545a59618b9SPawel Kaminski struct netlink_ext_ack *extack) 1546a59618b9SPawel Kaminski { 1547a59618b9SPawel Kaminski if (ice_devlink_local_fwd_str_to_mode(val.vstr) < 0) { 1548a59618b9SPawel Kaminski NL_SET_ERR_MSG_MOD(extack, "Error: Requested value is not supported."); 1549a59618b9SPawel Kaminski return -EINVAL; 1550a59618b9SPawel Kaminski } 1551a59618b9SPawel Kaminski 1552a59618b9SPawel Kaminski return 0; 1553a59618b9SPawel Kaminski } 1554a59618b9SPawel Kaminski 1555*b2657259SMichal Swiatkowski static int 1556*b2657259SMichal Swiatkowski ice_devlink_msix_max_pf_validate(struct devlink *devlink, u32 id, 1557*b2657259SMichal Swiatkowski union devlink_param_value val, 1558*b2657259SMichal Swiatkowski struct netlink_ext_ack *extack) 1559*b2657259SMichal Swiatkowski { 1560*b2657259SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 1561*b2657259SMichal Swiatkowski 1562*b2657259SMichal Swiatkowski if (val.vu32 > pf->hw.func_caps.common_cap.num_msix_vectors) 1563*b2657259SMichal Swiatkowski return -EINVAL; 1564*b2657259SMichal Swiatkowski 1565*b2657259SMichal Swiatkowski return 0; 1566*b2657259SMichal Swiatkowski } 1567*b2657259SMichal Swiatkowski 1568*b2657259SMichal Swiatkowski static int 1569*b2657259SMichal Swiatkowski ice_devlink_msix_min_pf_validate(struct devlink *devlink, u32 id, 1570*b2657259SMichal Swiatkowski union devlink_param_value val, 1571*b2657259SMichal Swiatkowski struct netlink_ext_ack *extack) 1572*b2657259SMichal Swiatkowski { 1573*b2657259SMichal Swiatkowski if (val.vu32 < ICE_MIN_MSIX) 1574*b2657259SMichal Swiatkowski return -EINVAL; 1575*b2657259SMichal Swiatkowski 1576*b2657259SMichal Swiatkowski return 0; 1577*b2657259SMichal Swiatkowski } 1578*b2657259SMichal Swiatkowski 1579109eb291SLukasz Czapnik enum ice_param_id { 1580109eb291SLukasz Czapnik ICE_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX, 1581109eb291SLukasz Czapnik ICE_DEVLINK_PARAM_ID_TX_SCHED_LAYERS, 1582a59618b9SPawel Kaminski ICE_DEVLINK_PARAM_ID_LOCAL_FWD, 1583109eb291SLukasz Czapnik }; 1584109eb291SLukasz Czapnik 1585a51c9b1cSDave Ertman static const struct devlink_param ice_dvl_rdma_params[] = { 15860545cc86SMichal Swiatkowski DEVLINK_PARAM_GENERIC(ENABLE_ROCE, BIT(DEVLINK_PARAM_CMODE_RUNTIME), 15870545cc86SMichal Swiatkowski ice_devlink_enable_roce_get, 15880545cc86SMichal Swiatkowski ice_devlink_enable_roce_set, 15890545cc86SMichal Swiatkowski ice_devlink_enable_roce_validate), 15900545cc86SMichal Swiatkowski DEVLINK_PARAM_GENERIC(ENABLE_IWARP, BIT(DEVLINK_PARAM_CMODE_RUNTIME), 15910545cc86SMichal Swiatkowski ice_devlink_enable_iw_get, 15920545cc86SMichal Swiatkowski ice_devlink_enable_iw_set, 15930545cc86SMichal Swiatkowski ice_devlink_enable_iw_validate), 1594a51c9b1cSDave Ertman }; 1595a51c9b1cSDave Ertman 1596*b2657259SMichal Swiatkowski static const struct devlink_param ice_dvl_msix_params[] = { 1597*b2657259SMichal Swiatkowski DEVLINK_PARAM_GENERIC(MSIX_VEC_PER_PF_MAX, 1598*b2657259SMichal Swiatkowski BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), 1599*b2657259SMichal Swiatkowski NULL, NULL, ice_devlink_msix_max_pf_validate), 1600*b2657259SMichal Swiatkowski DEVLINK_PARAM_GENERIC(MSIX_VEC_PER_PF_MIN, 1601*b2657259SMichal Swiatkowski BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), 1602*b2657259SMichal Swiatkowski NULL, NULL, ice_devlink_msix_min_pf_validate), 1603*b2657259SMichal Swiatkowski }; 1604*b2657259SMichal Swiatkowski 1605a51c9b1cSDave Ertman static const struct devlink_param ice_dvl_sched_params[] = { 1606109eb291SLukasz Czapnik DEVLINK_PARAM_DRIVER(ICE_DEVLINK_PARAM_ID_TX_SCHED_LAYERS, 1607109eb291SLukasz Czapnik "tx_scheduling_layers", 1608109eb291SLukasz Czapnik DEVLINK_PARAM_TYPE_U8, 1609109eb291SLukasz Czapnik BIT(DEVLINK_PARAM_CMODE_PERMANENT), 1610109eb291SLukasz Czapnik ice_devlink_tx_sched_layers_get, 1611109eb291SLukasz Czapnik ice_devlink_tx_sched_layers_set, 1612109eb291SLukasz Czapnik ice_devlink_tx_sched_layers_validate), 1613a59618b9SPawel Kaminski DEVLINK_PARAM_DRIVER(ICE_DEVLINK_PARAM_ID_LOCAL_FWD, 1614a59618b9SPawel Kaminski "local_forwarding", DEVLINK_PARAM_TYPE_STRING, 1615a59618b9SPawel Kaminski BIT(DEVLINK_PARAM_CMODE_RUNTIME), 1616a59618b9SPawel Kaminski ice_devlink_local_fwd_get, 1617a59618b9SPawel Kaminski ice_devlink_local_fwd_set, 1618a59618b9SPawel Kaminski ice_devlink_local_fwd_validate), 16190545cc86SMichal Swiatkowski }; 16200545cc86SMichal Swiatkowski 16210545cc86SMichal Swiatkowski static void ice_devlink_free(void *devlink_ptr) 16220545cc86SMichal Swiatkowski { 16230545cc86SMichal Swiatkowski devlink_free((struct devlink *)devlink_ptr); 16240545cc86SMichal Swiatkowski } 16250545cc86SMichal Swiatkowski 16260545cc86SMichal Swiatkowski /** 16270545cc86SMichal Swiatkowski * ice_allocate_pf - Allocate devlink and return PF structure pointer 16280545cc86SMichal Swiatkowski * @dev: the device to allocate for 16290545cc86SMichal Swiatkowski * 16300545cc86SMichal Swiatkowski * Allocate a devlink instance for this device and return the private area as 16310545cc86SMichal Swiatkowski * the PF structure. The devlink memory is kept track of through devres by 16320545cc86SMichal Swiatkowski * adding an action to remove it when unwinding. 16330545cc86SMichal Swiatkowski */ 16340545cc86SMichal Swiatkowski struct ice_pf *ice_allocate_pf(struct device *dev) 16350545cc86SMichal Swiatkowski { 16360545cc86SMichal Swiatkowski struct devlink *devlink; 16370545cc86SMichal Swiatkowski 16380545cc86SMichal Swiatkowski devlink = devlink_alloc(&ice_devlink_ops, sizeof(struct ice_pf), dev); 16390545cc86SMichal Swiatkowski if (!devlink) 16400545cc86SMichal Swiatkowski return NULL; 16410545cc86SMichal Swiatkowski 16420545cc86SMichal Swiatkowski /* Add an action to teardown the devlink when unwinding the driver */ 16430545cc86SMichal Swiatkowski if (devm_add_action_or_reset(dev, ice_devlink_free, devlink)) 16440545cc86SMichal Swiatkowski return NULL; 16450545cc86SMichal Swiatkowski 16460545cc86SMichal Swiatkowski return devlink_priv(devlink); 16470545cc86SMichal Swiatkowski } 16480545cc86SMichal Swiatkowski 16490545cc86SMichal Swiatkowski /** 1650f43e3be6SPiotr Raczynski * ice_allocate_sf - Allocate devlink and return SF structure pointer 1651f43e3be6SPiotr Raczynski * @dev: the device to allocate for 1652f43e3be6SPiotr Raczynski * @pf: pointer to the PF structure 1653f43e3be6SPiotr Raczynski * 1654f43e3be6SPiotr Raczynski * Allocate a devlink instance for SF. 1655f43e3be6SPiotr Raczynski * 1656f43e3be6SPiotr Raczynski * Return: ice_sf_priv pointer to allocated memory or ERR_PTR in case of error 1657f43e3be6SPiotr Raczynski */ 1658f43e3be6SPiotr Raczynski struct ice_sf_priv *ice_allocate_sf(struct device *dev, struct ice_pf *pf) 1659f43e3be6SPiotr Raczynski { 1660f43e3be6SPiotr Raczynski struct devlink *devlink; 1661f43e3be6SPiotr Raczynski int err; 1662f43e3be6SPiotr Raczynski 1663f43e3be6SPiotr Raczynski devlink = devlink_alloc(&ice_sf_devlink_ops, sizeof(struct ice_sf_priv), 1664f43e3be6SPiotr Raczynski dev); 1665f43e3be6SPiotr Raczynski if (!devlink) 1666f43e3be6SPiotr Raczynski return ERR_PTR(-ENOMEM); 1667f43e3be6SPiotr Raczynski 1668f43e3be6SPiotr Raczynski err = devl_nested_devlink_set(priv_to_devlink(pf), devlink); 1669f43e3be6SPiotr Raczynski if (err) { 1670f43e3be6SPiotr Raczynski devlink_free(devlink); 1671f43e3be6SPiotr Raczynski return ERR_PTR(err); 1672f43e3be6SPiotr Raczynski } 1673f43e3be6SPiotr Raczynski 1674f43e3be6SPiotr Raczynski return devlink_priv(devlink); 1675f43e3be6SPiotr Raczynski } 1676f43e3be6SPiotr Raczynski 1677f43e3be6SPiotr Raczynski /** 16780545cc86SMichal Swiatkowski * ice_devlink_register - Register devlink interface for this PF 16790545cc86SMichal Swiatkowski * @pf: the PF to register the devlink for. 16800545cc86SMichal Swiatkowski * 16810545cc86SMichal Swiatkowski * Register the devlink instance associated with this physical function. 16820545cc86SMichal Swiatkowski * 16830545cc86SMichal Swiatkowski * Return: zero on success or an error code on failure. 16840545cc86SMichal Swiatkowski */ 16850545cc86SMichal Swiatkowski void ice_devlink_register(struct ice_pf *pf) 16860545cc86SMichal Swiatkowski { 16870545cc86SMichal Swiatkowski struct devlink *devlink = priv_to_devlink(pf); 16880545cc86SMichal Swiatkowski 1689118c6bdeSMichal Swiatkowski devl_register(devlink); 16900545cc86SMichal Swiatkowski } 16910545cc86SMichal Swiatkowski 16920545cc86SMichal Swiatkowski /** 16930545cc86SMichal Swiatkowski * ice_devlink_unregister - Unregister devlink resources for this PF. 16940545cc86SMichal Swiatkowski * @pf: the PF structure to cleanup 16950545cc86SMichal Swiatkowski * 16960545cc86SMichal Swiatkowski * Releases resources used by devlink and cleans up associated memory. 16970545cc86SMichal Swiatkowski */ 16980545cc86SMichal Swiatkowski void ice_devlink_unregister(struct ice_pf *pf) 16990545cc86SMichal Swiatkowski { 1700118c6bdeSMichal Swiatkowski devl_unregister(priv_to_devlink(pf)); 17010545cc86SMichal Swiatkowski } 17020545cc86SMichal Swiatkowski 17030545cc86SMichal Swiatkowski int ice_devlink_register_params(struct ice_pf *pf) 17040545cc86SMichal Swiatkowski { 17050545cc86SMichal Swiatkowski struct devlink *devlink = priv_to_devlink(pf); 1706*b2657259SMichal Swiatkowski union devlink_param_value value; 1707109eb291SLukasz Czapnik struct ice_hw *hw = &pf->hw; 1708a51c9b1cSDave Ertman int status; 1709109eb291SLukasz Czapnik 1710a51c9b1cSDave Ertman status = devl_params_register(devlink, ice_dvl_rdma_params, 1711a51c9b1cSDave Ertman ARRAY_SIZE(ice_dvl_rdma_params)); 1712a51c9b1cSDave Ertman if (status) 1713a51c9b1cSDave Ertman return status; 1714109eb291SLukasz Czapnik 1715*b2657259SMichal Swiatkowski status = devl_params_register(devlink, ice_dvl_msix_params, 1716*b2657259SMichal Swiatkowski ARRAY_SIZE(ice_dvl_msix_params)); 1717*b2657259SMichal Swiatkowski if (status) 1718*b2657259SMichal Swiatkowski goto unregister_rdma_params; 1719*b2657259SMichal Swiatkowski 1720a51c9b1cSDave Ertman if (hw->func_caps.common_cap.tx_sched_topo_comp_mode_en) 1721a51c9b1cSDave Ertman status = devl_params_register(devlink, ice_dvl_sched_params, 1722a51c9b1cSDave Ertman ARRAY_SIZE(ice_dvl_sched_params)); 1723*b2657259SMichal Swiatkowski if (status) 1724*b2657259SMichal Swiatkowski goto unregister_msix_params; 17250545cc86SMichal Swiatkowski 1726*b2657259SMichal Swiatkowski value.vu32 = pf->msix.max; 1727*b2657259SMichal Swiatkowski devl_param_driverinit_value_set(devlink, 1728*b2657259SMichal Swiatkowski DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX, 1729*b2657259SMichal Swiatkowski value); 1730*b2657259SMichal Swiatkowski value.vu32 = pf->msix.min; 1731*b2657259SMichal Swiatkowski devl_param_driverinit_value_set(devlink, 1732*b2657259SMichal Swiatkowski DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN, 1733*b2657259SMichal Swiatkowski value); 1734*b2657259SMichal Swiatkowski return 0; 1735*b2657259SMichal Swiatkowski 1736*b2657259SMichal Swiatkowski unregister_msix_params: 1737*b2657259SMichal Swiatkowski devl_params_unregister(devlink, ice_dvl_msix_params, 1738*b2657259SMichal Swiatkowski ARRAY_SIZE(ice_dvl_msix_params)); 1739*b2657259SMichal Swiatkowski unregister_rdma_params: 1740*b2657259SMichal Swiatkowski devl_params_unregister(devlink, ice_dvl_rdma_params, 1741*b2657259SMichal Swiatkowski ARRAY_SIZE(ice_dvl_rdma_params)); 1742a51c9b1cSDave Ertman return status; 17430545cc86SMichal Swiatkowski } 17440545cc86SMichal Swiatkowski 17450545cc86SMichal Swiatkowski void ice_devlink_unregister_params(struct ice_pf *pf) 17460545cc86SMichal Swiatkowski { 1747a51c9b1cSDave Ertman struct devlink *devlink = priv_to_devlink(pf); 1748a51c9b1cSDave Ertman struct ice_hw *hw = &pf->hw; 1749a51c9b1cSDave Ertman 1750a51c9b1cSDave Ertman devl_params_unregister(devlink, ice_dvl_rdma_params, 1751a51c9b1cSDave Ertman ARRAY_SIZE(ice_dvl_rdma_params)); 1752*b2657259SMichal Swiatkowski devl_params_unregister(devlink, ice_dvl_msix_params, 1753*b2657259SMichal Swiatkowski ARRAY_SIZE(ice_dvl_msix_params)); 1754a51c9b1cSDave Ertman 1755a51c9b1cSDave Ertman if (hw->func_caps.common_cap.tx_sched_topo_comp_mode_en) 1756a51c9b1cSDave Ertman devl_params_unregister(devlink, ice_dvl_sched_params, 1757a51c9b1cSDave Ertman ARRAY_SIZE(ice_dvl_sched_params)); 17580545cc86SMichal Swiatkowski } 17590545cc86SMichal Swiatkowski 17600545cc86SMichal Swiatkowski #define ICE_DEVLINK_READ_BLK_SIZE (1024 * 1024) 17610545cc86SMichal Swiatkowski 17620545cc86SMichal Swiatkowski static const struct devlink_region_ops ice_nvm_region_ops; 17630545cc86SMichal Swiatkowski static const struct devlink_region_ops ice_sram_region_ops; 17640545cc86SMichal Swiatkowski 17650545cc86SMichal Swiatkowski /** 17660545cc86SMichal Swiatkowski * ice_devlink_nvm_snapshot - Capture a snapshot of the NVM flash contents 17670545cc86SMichal Swiatkowski * @devlink: the devlink instance 17680545cc86SMichal Swiatkowski * @ops: the devlink region to snapshot 17690545cc86SMichal Swiatkowski * @extack: extended ACK response structure 17700545cc86SMichal Swiatkowski * @data: on exit points to snapshot data buffer 17710545cc86SMichal Swiatkowski * 17720545cc86SMichal Swiatkowski * This function is called in response to a DEVLINK_CMD_REGION_NEW for either 17730545cc86SMichal Swiatkowski * the nvm-flash or shadow-ram region. 17740545cc86SMichal Swiatkowski * 17750545cc86SMichal Swiatkowski * It captures a snapshot of the NVM or Shadow RAM flash contents. This 17760545cc86SMichal Swiatkowski * snapshot can then later be viewed via the DEVLINK_CMD_REGION_READ netlink 17770545cc86SMichal Swiatkowski * interface. 17780545cc86SMichal Swiatkowski * 17790545cc86SMichal Swiatkowski * @returns zero on success, and updates the data pointer. Returns a non-zero 17800545cc86SMichal Swiatkowski * error code on failure. 17810545cc86SMichal Swiatkowski */ 17820545cc86SMichal Swiatkowski static int ice_devlink_nvm_snapshot(struct devlink *devlink, 17830545cc86SMichal Swiatkowski const struct devlink_region_ops *ops, 17840545cc86SMichal Swiatkowski struct netlink_ext_ack *extack, u8 **data) 17850545cc86SMichal Swiatkowski { 17860545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 17870545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 17880545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 17890545cc86SMichal Swiatkowski bool read_shadow_ram; 17900545cc86SMichal Swiatkowski u8 *nvm_data, *tmp, i; 17910545cc86SMichal Swiatkowski u32 nvm_size, left; 17920545cc86SMichal Swiatkowski s8 num_blks; 17930545cc86SMichal Swiatkowski int status; 17940545cc86SMichal Swiatkowski 17950545cc86SMichal Swiatkowski if (ops == &ice_nvm_region_ops) { 17960545cc86SMichal Swiatkowski read_shadow_ram = false; 17970545cc86SMichal Swiatkowski nvm_size = hw->flash.flash_size; 17980545cc86SMichal Swiatkowski } else if (ops == &ice_sram_region_ops) { 17990545cc86SMichal Swiatkowski read_shadow_ram = true; 18000545cc86SMichal Swiatkowski nvm_size = hw->flash.sr_words * 2u; 18010545cc86SMichal Swiatkowski } else { 18020545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unexpected region in snapshot function"); 18030545cc86SMichal Swiatkowski return -EOPNOTSUPP; 18040545cc86SMichal Swiatkowski } 18050545cc86SMichal Swiatkowski 18060545cc86SMichal Swiatkowski nvm_data = vzalloc(nvm_size); 18070545cc86SMichal Swiatkowski if (!nvm_data) 18080545cc86SMichal Swiatkowski return -ENOMEM; 18090545cc86SMichal Swiatkowski 18100545cc86SMichal Swiatkowski num_blks = DIV_ROUND_UP(nvm_size, ICE_DEVLINK_READ_BLK_SIZE); 18110545cc86SMichal Swiatkowski tmp = nvm_data; 18120545cc86SMichal Swiatkowski left = nvm_size; 18130545cc86SMichal Swiatkowski 18140545cc86SMichal Swiatkowski /* Some systems take longer to read the NVM than others which causes the 18150545cc86SMichal Swiatkowski * FW to reclaim the NVM lock before the entire NVM has been read. Fix 18160545cc86SMichal Swiatkowski * this by breaking the reads of the NVM into smaller chunks that will 18170545cc86SMichal Swiatkowski * probably not take as long. This has some overhead since we are 18180545cc86SMichal Swiatkowski * increasing the number of AQ commands, but it should always work 18190545cc86SMichal Swiatkowski */ 18200545cc86SMichal Swiatkowski for (i = 0; i < num_blks; i++) { 18210545cc86SMichal Swiatkowski u32 read_sz = min_t(u32, ICE_DEVLINK_READ_BLK_SIZE, left); 18220545cc86SMichal Swiatkowski 18230545cc86SMichal Swiatkowski status = ice_acquire_nvm(hw, ICE_RES_READ); 18240545cc86SMichal Swiatkowski if (status) { 18250545cc86SMichal Swiatkowski dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n", 18260545cc86SMichal Swiatkowski status, hw->adminq.sq_last_status); 18270545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore"); 18280545cc86SMichal Swiatkowski vfree(nvm_data); 18290545cc86SMichal Swiatkowski return -EIO; 18300545cc86SMichal Swiatkowski } 18310545cc86SMichal Swiatkowski 18320545cc86SMichal Swiatkowski status = ice_read_flat_nvm(hw, i * ICE_DEVLINK_READ_BLK_SIZE, 18330545cc86SMichal Swiatkowski &read_sz, tmp, read_shadow_ram); 18340545cc86SMichal Swiatkowski if (status) { 18350545cc86SMichal Swiatkowski dev_dbg(dev, "ice_read_flat_nvm failed after reading %u bytes, err %d aq_err %d\n", 18360545cc86SMichal Swiatkowski read_sz, status, hw->adminq.sq_last_status); 18370545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Failed to read NVM contents"); 18380545cc86SMichal Swiatkowski ice_release_nvm(hw); 18390545cc86SMichal Swiatkowski vfree(nvm_data); 18400545cc86SMichal Swiatkowski return -EIO; 18410545cc86SMichal Swiatkowski } 18420545cc86SMichal Swiatkowski ice_release_nvm(hw); 18430545cc86SMichal Swiatkowski 18440545cc86SMichal Swiatkowski tmp += read_sz; 18450545cc86SMichal Swiatkowski left -= read_sz; 18460545cc86SMichal Swiatkowski } 18470545cc86SMichal Swiatkowski 18480545cc86SMichal Swiatkowski *data = nvm_data; 18490545cc86SMichal Swiatkowski 18500545cc86SMichal Swiatkowski return 0; 18510545cc86SMichal Swiatkowski } 18520545cc86SMichal Swiatkowski 18530545cc86SMichal Swiatkowski /** 18540545cc86SMichal Swiatkowski * ice_devlink_nvm_read - Read a portion of NVM flash contents 18550545cc86SMichal Swiatkowski * @devlink: the devlink instance 18560545cc86SMichal Swiatkowski * @ops: the devlink region to snapshot 18570545cc86SMichal Swiatkowski * @extack: extended ACK response structure 18580545cc86SMichal Swiatkowski * @offset: the offset to start at 18590545cc86SMichal Swiatkowski * @size: the amount to read 18600545cc86SMichal Swiatkowski * @data: the data buffer to read into 18610545cc86SMichal Swiatkowski * 18620545cc86SMichal Swiatkowski * This function is called in response to DEVLINK_CMD_REGION_READ to directly 18630545cc86SMichal Swiatkowski * read a section of the NVM contents. 18640545cc86SMichal Swiatkowski * 18650545cc86SMichal Swiatkowski * It reads from either the nvm-flash or shadow-ram region contents. 18660545cc86SMichal Swiatkowski * 18670545cc86SMichal Swiatkowski * @returns zero on success, and updates the data pointer. Returns a non-zero 18680545cc86SMichal Swiatkowski * error code on failure. 18690545cc86SMichal Swiatkowski */ 18700545cc86SMichal Swiatkowski static int ice_devlink_nvm_read(struct devlink *devlink, 18710545cc86SMichal Swiatkowski const struct devlink_region_ops *ops, 18720545cc86SMichal Swiatkowski struct netlink_ext_ack *extack, 18730545cc86SMichal Swiatkowski u64 offset, u32 size, u8 *data) 18740545cc86SMichal Swiatkowski { 18750545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 18760545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 18770545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 18780545cc86SMichal Swiatkowski bool read_shadow_ram; 18790545cc86SMichal Swiatkowski u64 nvm_size; 18800545cc86SMichal Swiatkowski int status; 18810545cc86SMichal Swiatkowski 18820545cc86SMichal Swiatkowski if (ops == &ice_nvm_region_ops) { 18830545cc86SMichal Swiatkowski read_shadow_ram = false; 18840545cc86SMichal Swiatkowski nvm_size = hw->flash.flash_size; 18850545cc86SMichal Swiatkowski } else if (ops == &ice_sram_region_ops) { 18860545cc86SMichal Swiatkowski read_shadow_ram = true; 18870545cc86SMichal Swiatkowski nvm_size = hw->flash.sr_words * 2u; 18880545cc86SMichal Swiatkowski } else { 18890545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unexpected region in snapshot function"); 18900545cc86SMichal Swiatkowski return -EOPNOTSUPP; 18910545cc86SMichal Swiatkowski } 18920545cc86SMichal Swiatkowski 18930545cc86SMichal Swiatkowski if (offset + size >= nvm_size) { 18940545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Cannot read beyond the region size"); 18950545cc86SMichal Swiatkowski return -ERANGE; 18960545cc86SMichal Swiatkowski } 18970545cc86SMichal Swiatkowski 18980545cc86SMichal Swiatkowski status = ice_acquire_nvm(hw, ICE_RES_READ); 18990545cc86SMichal Swiatkowski if (status) { 19000545cc86SMichal Swiatkowski dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n", 19010545cc86SMichal Swiatkowski status, hw->adminq.sq_last_status); 19020545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore"); 19030545cc86SMichal Swiatkowski return -EIO; 19040545cc86SMichal Swiatkowski } 19050545cc86SMichal Swiatkowski 19060545cc86SMichal Swiatkowski status = ice_read_flat_nvm(hw, (u32)offset, &size, data, 19070545cc86SMichal Swiatkowski read_shadow_ram); 19080545cc86SMichal Swiatkowski if (status) { 19090545cc86SMichal Swiatkowski dev_dbg(dev, "ice_read_flat_nvm failed after reading %u bytes, err %d aq_err %d\n", 19100545cc86SMichal Swiatkowski size, status, hw->adminq.sq_last_status); 19110545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Failed to read NVM contents"); 19120545cc86SMichal Swiatkowski ice_release_nvm(hw); 19130545cc86SMichal Swiatkowski return -EIO; 19140545cc86SMichal Swiatkowski } 19150545cc86SMichal Swiatkowski ice_release_nvm(hw); 19160545cc86SMichal Swiatkowski 19170545cc86SMichal Swiatkowski return 0; 19180545cc86SMichal Swiatkowski } 19190545cc86SMichal Swiatkowski 19200545cc86SMichal Swiatkowski /** 19210545cc86SMichal Swiatkowski * ice_devlink_devcaps_snapshot - Capture snapshot of device capabilities 19220545cc86SMichal Swiatkowski * @devlink: the devlink instance 19230545cc86SMichal Swiatkowski * @ops: the devlink region being snapshotted 19240545cc86SMichal Swiatkowski * @extack: extended ACK response structure 19250545cc86SMichal Swiatkowski * @data: on exit points to snapshot data buffer 19260545cc86SMichal Swiatkowski * 19270545cc86SMichal Swiatkowski * This function is called in response to the DEVLINK_CMD_REGION_TRIGGER for 19280545cc86SMichal Swiatkowski * the device-caps devlink region. It captures a snapshot of the device 19290545cc86SMichal Swiatkowski * capabilities reported by firmware. 19300545cc86SMichal Swiatkowski * 19310545cc86SMichal Swiatkowski * @returns zero on success, and updates the data pointer. Returns a non-zero 19320545cc86SMichal Swiatkowski * error code on failure. 19330545cc86SMichal Swiatkowski */ 19340545cc86SMichal Swiatkowski static int 19350545cc86SMichal Swiatkowski ice_devlink_devcaps_snapshot(struct devlink *devlink, 19360545cc86SMichal Swiatkowski const struct devlink_region_ops *ops, 19370545cc86SMichal Swiatkowski struct netlink_ext_ack *extack, u8 **data) 19380545cc86SMichal Swiatkowski { 19390545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 19400545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 19410545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 19420545cc86SMichal Swiatkowski void *devcaps; 19430545cc86SMichal Swiatkowski int status; 19440545cc86SMichal Swiatkowski 19450545cc86SMichal Swiatkowski devcaps = vzalloc(ICE_AQ_MAX_BUF_LEN); 19460545cc86SMichal Swiatkowski if (!devcaps) 19470545cc86SMichal Swiatkowski return -ENOMEM; 19480545cc86SMichal Swiatkowski 19490545cc86SMichal Swiatkowski status = ice_aq_list_caps(hw, devcaps, ICE_AQ_MAX_BUF_LEN, NULL, 19500545cc86SMichal Swiatkowski ice_aqc_opc_list_dev_caps, NULL); 19510545cc86SMichal Swiatkowski if (status) { 19520545cc86SMichal Swiatkowski dev_dbg(dev, "ice_aq_list_caps: failed to read device capabilities, err %d aq_err %d\n", 19530545cc86SMichal Swiatkowski status, hw->adminq.sq_last_status); 19540545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Failed to read device capabilities"); 19550545cc86SMichal Swiatkowski vfree(devcaps); 19560545cc86SMichal Swiatkowski return status; 19570545cc86SMichal Swiatkowski } 19580545cc86SMichal Swiatkowski 19590545cc86SMichal Swiatkowski *data = (u8 *)devcaps; 19600545cc86SMichal Swiatkowski 19610545cc86SMichal Swiatkowski return 0; 19620545cc86SMichal Swiatkowski } 19630545cc86SMichal Swiatkowski 19640545cc86SMichal Swiatkowski static const struct devlink_region_ops ice_nvm_region_ops = { 19650545cc86SMichal Swiatkowski .name = "nvm-flash", 19660545cc86SMichal Swiatkowski .destructor = vfree, 19670545cc86SMichal Swiatkowski .snapshot = ice_devlink_nvm_snapshot, 19680545cc86SMichal Swiatkowski .read = ice_devlink_nvm_read, 19690545cc86SMichal Swiatkowski }; 19700545cc86SMichal Swiatkowski 19710545cc86SMichal Swiatkowski static const struct devlink_region_ops ice_sram_region_ops = { 19720545cc86SMichal Swiatkowski .name = "shadow-ram", 19730545cc86SMichal Swiatkowski .destructor = vfree, 19740545cc86SMichal Swiatkowski .snapshot = ice_devlink_nvm_snapshot, 19750545cc86SMichal Swiatkowski .read = ice_devlink_nvm_read, 19760545cc86SMichal Swiatkowski }; 19770545cc86SMichal Swiatkowski 19780545cc86SMichal Swiatkowski static const struct devlink_region_ops ice_devcaps_region_ops = { 19790545cc86SMichal Swiatkowski .name = "device-caps", 19800545cc86SMichal Swiatkowski .destructor = vfree, 19810545cc86SMichal Swiatkowski .snapshot = ice_devlink_devcaps_snapshot, 19820545cc86SMichal Swiatkowski }; 19830545cc86SMichal Swiatkowski 19840545cc86SMichal Swiatkowski /** 19850545cc86SMichal Swiatkowski * ice_devlink_init_regions - Initialize devlink regions 19860545cc86SMichal Swiatkowski * @pf: the PF device structure 19870545cc86SMichal Swiatkowski * 19880545cc86SMichal Swiatkowski * Create devlink regions used to enable access to dump the contents of the 19890545cc86SMichal Swiatkowski * flash memory on the device. 19900545cc86SMichal Swiatkowski */ 19910545cc86SMichal Swiatkowski void ice_devlink_init_regions(struct ice_pf *pf) 19920545cc86SMichal Swiatkowski { 19930545cc86SMichal Swiatkowski struct devlink *devlink = priv_to_devlink(pf); 19940545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 19950545cc86SMichal Swiatkowski u64 nvm_size, sram_size; 19960545cc86SMichal Swiatkowski 19970545cc86SMichal Swiatkowski nvm_size = pf->hw.flash.flash_size; 1998118c6bdeSMichal Swiatkowski pf->nvm_region = devl_region_create(devlink, &ice_nvm_region_ops, 1, 19990545cc86SMichal Swiatkowski nvm_size); 20000545cc86SMichal Swiatkowski if (IS_ERR(pf->nvm_region)) { 20010545cc86SMichal Swiatkowski dev_err(dev, "failed to create NVM devlink region, err %ld\n", 20020545cc86SMichal Swiatkowski PTR_ERR(pf->nvm_region)); 20030545cc86SMichal Swiatkowski pf->nvm_region = NULL; 20040545cc86SMichal Swiatkowski } 20050545cc86SMichal Swiatkowski 20060545cc86SMichal Swiatkowski sram_size = pf->hw.flash.sr_words * 2u; 2007118c6bdeSMichal Swiatkowski pf->sram_region = devl_region_create(devlink, &ice_sram_region_ops, 20080545cc86SMichal Swiatkowski 1, sram_size); 20090545cc86SMichal Swiatkowski if (IS_ERR(pf->sram_region)) { 20100545cc86SMichal Swiatkowski dev_err(dev, "failed to create shadow-ram devlink region, err %ld\n", 20110545cc86SMichal Swiatkowski PTR_ERR(pf->sram_region)); 20120545cc86SMichal Swiatkowski pf->sram_region = NULL; 20130545cc86SMichal Swiatkowski } 20140545cc86SMichal Swiatkowski 2015118c6bdeSMichal Swiatkowski pf->devcaps_region = devl_region_create(devlink, 20160545cc86SMichal Swiatkowski &ice_devcaps_region_ops, 10, 20170545cc86SMichal Swiatkowski ICE_AQ_MAX_BUF_LEN); 20180545cc86SMichal Swiatkowski if (IS_ERR(pf->devcaps_region)) { 20190545cc86SMichal Swiatkowski dev_err(dev, "failed to create device-caps devlink region, err %ld\n", 20200545cc86SMichal Swiatkowski PTR_ERR(pf->devcaps_region)); 20210545cc86SMichal Swiatkowski pf->devcaps_region = NULL; 20220545cc86SMichal Swiatkowski } 20230545cc86SMichal Swiatkowski } 20240545cc86SMichal Swiatkowski 20250545cc86SMichal Swiatkowski /** 20260545cc86SMichal Swiatkowski * ice_devlink_destroy_regions - Destroy devlink regions 20270545cc86SMichal Swiatkowski * @pf: the PF device structure 20280545cc86SMichal Swiatkowski * 20290545cc86SMichal Swiatkowski * Remove previously created regions for this PF. 20300545cc86SMichal Swiatkowski */ 20310545cc86SMichal Swiatkowski void ice_devlink_destroy_regions(struct ice_pf *pf) 20320545cc86SMichal Swiatkowski { 20330545cc86SMichal Swiatkowski if (pf->nvm_region) 2034118c6bdeSMichal Swiatkowski devl_region_destroy(pf->nvm_region); 20350545cc86SMichal Swiatkowski 20360545cc86SMichal Swiatkowski if (pf->sram_region) 2037118c6bdeSMichal Swiatkowski devl_region_destroy(pf->sram_region); 20380545cc86SMichal Swiatkowski 20390545cc86SMichal Swiatkowski if (pf->devcaps_region) 2040118c6bdeSMichal Swiatkowski devl_region_destroy(pf->devcaps_region); 20410545cc86SMichal Swiatkowski } 2042