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" 9eda69d65SPiotr Raczynski #include "devlink_port.h" 100545cc86SMichal Swiatkowski #include "ice_eswitch.h" 110545cc86SMichal Swiatkowski #include "ice_fw_update.h" 120545cc86SMichal Swiatkowski #include "ice_dcb_lib.h" 13*f43e3be6SPiotr 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: 3710545cc86SMichal Swiatkowski err = devlink_info_version_running_put(req, key, ctx->buf); 3720545cc86SMichal Swiatkowski if (err) { 3730545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unable to set running version"); 3740545cc86SMichal Swiatkowski goto out_free_ctx; 3750545cc86SMichal Swiatkowski } 3760545cc86SMichal Swiatkowski break; 3770545cc86SMichal Swiatkowski case ICE_VERSION_STORED: 3780545cc86SMichal Swiatkowski err = devlink_info_version_stored_put(req, key, ctx->buf); 3790545cc86SMichal Swiatkowski if (err) { 3800545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unable to set stored version"); 3810545cc86SMichal Swiatkowski goto out_free_ctx; 3820545cc86SMichal Swiatkowski } 3830545cc86SMichal Swiatkowski break; 3840545cc86SMichal Swiatkowski } 3850545cc86SMichal Swiatkowski } 3860545cc86SMichal Swiatkowski 3870545cc86SMichal Swiatkowski out_free_ctx: 3880545cc86SMichal Swiatkowski kfree(ctx); 3890545cc86SMichal Swiatkowski return err; 3900545cc86SMichal Swiatkowski } 3910545cc86SMichal Swiatkowski 3920545cc86SMichal Swiatkowski /** 3930545cc86SMichal Swiatkowski * ice_devlink_reload_empr_start - Start EMP reset to activate new firmware 3940545cc86SMichal Swiatkowski * @pf: pointer to the pf instance 3950545cc86SMichal Swiatkowski * @extack: netlink extended ACK structure 3960545cc86SMichal Swiatkowski * 3970545cc86SMichal Swiatkowski * Allow user to activate new Embedded Management Processor firmware by 3980545cc86SMichal Swiatkowski * issuing device specific EMP reset. Called in response to 3990545cc86SMichal Swiatkowski * a DEVLINK_CMD_RELOAD with the DEVLINK_RELOAD_ACTION_FW_ACTIVATE. 4000545cc86SMichal Swiatkowski * 4010545cc86SMichal Swiatkowski * Note that teardown and rebuild of the driver state happens automatically as 4020545cc86SMichal Swiatkowski * part of an interrupt and watchdog task. This is because all physical 4030545cc86SMichal Swiatkowski * functions on the device must be able to reset when an EMP reset occurs from 4040545cc86SMichal Swiatkowski * any source. 4050545cc86SMichal Swiatkowski */ 4060545cc86SMichal Swiatkowski static int 4070545cc86SMichal Swiatkowski ice_devlink_reload_empr_start(struct ice_pf *pf, 4080545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 4090545cc86SMichal Swiatkowski { 4100545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 4110545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 4120545cc86SMichal Swiatkowski u8 pending; 4130545cc86SMichal Swiatkowski int err; 4140545cc86SMichal Swiatkowski 4150545cc86SMichal Swiatkowski err = ice_get_pending_updates(pf, &pending, extack); 4160545cc86SMichal Swiatkowski if (err) 4170545cc86SMichal Swiatkowski return err; 4180545cc86SMichal Swiatkowski 4190545cc86SMichal Swiatkowski /* pending is a bitmask of which flash banks have a pending update, 4200545cc86SMichal Swiatkowski * including the main NVM bank, the Option ROM bank, and the netlist 4210545cc86SMichal Swiatkowski * bank. If any of these bits are set, then there is a pending update 4220545cc86SMichal Swiatkowski * waiting to be activated. 4230545cc86SMichal Swiatkowski */ 4240545cc86SMichal Swiatkowski if (!pending) { 4250545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "No pending firmware update"); 4260545cc86SMichal Swiatkowski return -ECANCELED; 4270545cc86SMichal Swiatkowski } 4280545cc86SMichal Swiatkowski 4290545cc86SMichal Swiatkowski if (pf->fw_emp_reset_disabled) { 4300545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "EMP reset is not available. To activate firmware, a reboot or power cycle is needed"); 4310545cc86SMichal Swiatkowski return -ECANCELED; 4320545cc86SMichal Swiatkowski } 4330545cc86SMichal Swiatkowski 4340545cc86SMichal Swiatkowski dev_dbg(dev, "Issuing device EMP reset to activate firmware\n"); 4350545cc86SMichal Swiatkowski 4360545cc86SMichal Swiatkowski err = ice_aq_nvm_update_empr(hw); 4370545cc86SMichal Swiatkowski if (err) { 4380545cc86SMichal Swiatkowski dev_err(dev, "Failed to trigger EMP device reset to reload firmware, err %d aq_err %s\n", 4390545cc86SMichal Swiatkowski err, ice_aq_str(hw->adminq.sq_last_status)); 4400545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Failed to trigger EMP device reset to reload firmware"); 4410545cc86SMichal Swiatkowski return err; 4420545cc86SMichal Swiatkowski } 4430545cc86SMichal Swiatkowski 4440545cc86SMichal Swiatkowski return 0; 4450545cc86SMichal Swiatkowski } 4460545cc86SMichal Swiatkowski 4470545cc86SMichal Swiatkowski /** 4480545cc86SMichal Swiatkowski * ice_devlink_reinit_down - unload given PF 4490545cc86SMichal Swiatkowski * @pf: pointer to the PF struct 4500545cc86SMichal Swiatkowski */ 4510545cc86SMichal Swiatkowski static void ice_devlink_reinit_down(struct ice_pf *pf) 4520545cc86SMichal Swiatkowski { 4530545cc86SMichal Swiatkowski /* No need to take devl_lock, it's already taken by devlink API */ 4540545cc86SMichal Swiatkowski ice_unload(pf); 4550545cc86SMichal Swiatkowski rtnl_lock(); 4560545cc86SMichal Swiatkowski ice_vsi_decfg(ice_get_main_vsi(pf)); 4570545cc86SMichal Swiatkowski rtnl_unlock(); 4580545cc86SMichal Swiatkowski ice_deinit_dev(pf); 4590545cc86SMichal Swiatkowski } 4600545cc86SMichal Swiatkowski 4610545cc86SMichal Swiatkowski /** 4620545cc86SMichal Swiatkowski * ice_devlink_reload_down - prepare for reload 4630545cc86SMichal Swiatkowski * @devlink: pointer to the devlink instance to reload 4640545cc86SMichal Swiatkowski * @netns_change: if true, the network namespace is changing 4650545cc86SMichal Swiatkowski * @action: the action to perform 4660545cc86SMichal Swiatkowski * @limit: limits on what reload should do, such as not resetting 4670545cc86SMichal Swiatkowski * @extack: netlink extended ACK structure 4680545cc86SMichal Swiatkowski */ 4690545cc86SMichal Swiatkowski static int 4700545cc86SMichal Swiatkowski ice_devlink_reload_down(struct devlink *devlink, bool netns_change, 4710545cc86SMichal Swiatkowski enum devlink_reload_action action, 4720545cc86SMichal Swiatkowski enum devlink_reload_limit limit, 4730545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 4740545cc86SMichal Swiatkowski { 4750545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 4760545cc86SMichal Swiatkowski 4770545cc86SMichal Swiatkowski switch (action) { 4780545cc86SMichal Swiatkowski case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: 4790545cc86SMichal Swiatkowski if (ice_is_eswitch_mode_switchdev(pf)) { 4800545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, 4810545cc86SMichal Swiatkowski "Go to legacy mode before doing reinit"); 4820545cc86SMichal Swiatkowski return -EOPNOTSUPP; 4830545cc86SMichal Swiatkowski } 4840545cc86SMichal Swiatkowski if (ice_is_adq_active(pf)) { 4850545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, 4860545cc86SMichal Swiatkowski "Turn off ADQ before doing reinit"); 4870545cc86SMichal Swiatkowski return -EOPNOTSUPP; 4880545cc86SMichal Swiatkowski } 4890545cc86SMichal Swiatkowski if (ice_has_vfs(pf)) { 4900545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, 4910545cc86SMichal Swiatkowski "Remove all VFs before doing reinit"); 4920545cc86SMichal Swiatkowski return -EOPNOTSUPP; 4930545cc86SMichal Swiatkowski } 4940545cc86SMichal Swiatkowski ice_devlink_reinit_down(pf); 4950545cc86SMichal Swiatkowski return 0; 4960545cc86SMichal Swiatkowski case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: 4970545cc86SMichal Swiatkowski return ice_devlink_reload_empr_start(pf, extack); 4980545cc86SMichal Swiatkowski default: 4990545cc86SMichal Swiatkowski WARN_ON(1); 5000545cc86SMichal Swiatkowski return -EOPNOTSUPP; 5010545cc86SMichal Swiatkowski } 5020545cc86SMichal Swiatkowski } 5030545cc86SMichal Swiatkowski 5040545cc86SMichal Swiatkowski /** 5050545cc86SMichal Swiatkowski * ice_devlink_reload_empr_finish - Wait for EMP reset to finish 5060545cc86SMichal Swiatkowski * @pf: pointer to the pf instance 5070545cc86SMichal Swiatkowski * @extack: netlink extended ACK structure 5080545cc86SMichal Swiatkowski * 5090545cc86SMichal Swiatkowski * Wait for driver to finish rebuilding after EMP reset is completed. This 5100545cc86SMichal Swiatkowski * includes time to wait for both the actual device reset as well as the time 5110545cc86SMichal Swiatkowski * for the driver's rebuild to complete. 5120545cc86SMichal Swiatkowski */ 5130545cc86SMichal Swiatkowski static int 5140545cc86SMichal Swiatkowski ice_devlink_reload_empr_finish(struct ice_pf *pf, 5150545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 5160545cc86SMichal Swiatkowski { 5170545cc86SMichal Swiatkowski int err; 5180545cc86SMichal Swiatkowski 5190545cc86SMichal Swiatkowski err = ice_wait_for_reset(pf, 60 * HZ); 5200545cc86SMichal Swiatkowski if (err) { 5210545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Device still resetting after 1 minute"); 5220545cc86SMichal Swiatkowski return err; 5230545cc86SMichal Swiatkowski } 5240545cc86SMichal Swiatkowski 5250545cc86SMichal Swiatkowski return 0; 5260545cc86SMichal Swiatkowski } 5270545cc86SMichal Swiatkowski 5280545cc86SMichal Swiatkowski /** 529109eb291SLukasz Czapnik * ice_get_tx_topo_user_sel - Read user's choice from flash 530109eb291SLukasz Czapnik * @pf: pointer to pf structure 531109eb291SLukasz Czapnik * @layers: value read from flash will be saved here 532109eb291SLukasz Czapnik * 533109eb291SLukasz Czapnik * Reads user's preference for Tx Scheduler Topology Tree from PFA TLV. 534109eb291SLukasz Czapnik * 535109eb291SLukasz Czapnik * Return: zero when read was successful, negative values otherwise. 536109eb291SLukasz Czapnik */ 537109eb291SLukasz Czapnik static int ice_get_tx_topo_user_sel(struct ice_pf *pf, uint8_t *layers) 538109eb291SLukasz Czapnik { 539109eb291SLukasz Czapnik struct ice_aqc_nvm_tx_topo_user_sel usr_sel = {}; 540109eb291SLukasz Czapnik struct ice_hw *hw = &pf->hw; 541109eb291SLukasz Czapnik int err; 542109eb291SLukasz Czapnik 543109eb291SLukasz Czapnik err = ice_acquire_nvm(hw, ICE_RES_READ); 544109eb291SLukasz Czapnik if (err) 545109eb291SLukasz Czapnik return err; 546109eb291SLukasz Czapnik 547109eb291SLukasz Czapnik err = ice_aq_read_nvm(hw, ICE_AQC_NVM_TX_TOPO_MOD_ID, 0, 548109eb291SLukasz Czapnik sizeof(usr_sel), &usr_sel, true, true, NULL); 549109eb291SLukasz Czapnik if (err) 550109eb291SLukasz Czapnik goto exit_release_res; 551109eb291SLukasz Czapnik 552109eb291SLukasz Czapnik if (usr_sel.data & ICE_AQC_NVM_TX_TOPO_USER_SEL) 553109eb291SLukasz Czapnik *layers = ICE_SCHED_5_LAYERS; 554109eb291SLukasz Czapnik else 555109eb291SLukasz Czapnik *layers = ICE_SCHED_9_LAYERS; 556109eb291SLukasz Czapnik 557109eb291SLukasz Czapnik exit_release_res: 558109eb291SLukasz Czapnik ice_release_nvm(hw); 559109eb291SLukasz Czapnik 560109eb291SLukasz Czapnik return err; 561109eb291SLukasz Czapnik } 562109eb291SLukasz Czapnik 563109eb291SLukasz Czapnik /** 564109eb291SLukasz Czapnik * ice_update_tx_topo_user_sel - Save user's preference in flash 565109eb291SLukasz Czapnik * @pf: pointer to pf structure 566109eb291SLukasz Czapnik * @layers: value to be saved in flash 567109eb291SLukasz Czapnik * 568109eb291SLukasz Czapnik * Variable "layers" defines user's preference about number of layers in Tx 569109eb291SLukasz Czapnik * Scheduler Topology Tree. This choice should be stored in PFA TLV field 570109eb291SLukasz Czapnik * and be picked up by driver, next time during init. 571109eb291SLukasz Czapnik * 572109eb291SLukasz Czapnik * Return: zero when save was successful, negative values otherwise. 573109eb291SLukasz Czapnik */ 574109eb291SLukasz Czapnik static int ice_update_tx_topo_user_sel(struct ice_pf *pf, int layers) 575109eb291SLukasz Czapnik { 576109eb291SLukasz Czapnik struct ice_aqc_nvm_tx_topo_user_sel usr_sel = {}; 577109eb291SLukasz Czapnik struct ice_hw *hw = &pf->hw; 578109eb291SLukasz Czapnik int err; 579109eb291SLukasz Czapnik 580109eb291SLukasz Czapnik err = ice_acquire_nvm(hw, ICE_RES_WRITE); 581109eb291SLukasz Czapnik if (err) 582109eb291SLukasz Czapnik return err; 583109eb291SLukasz Czapnik 584109eb291SLukasz Czapnik err = ice_aq_read_nvm(hw, ICE_AQC_NVM_TX_TOPO_MOD_ID, 0, 585109eb291SLukasz Czapnik sizeof(usr_sel), &usr_sel, true, true, NULL); 586109eb291SLukasz Czapnik if (err) 587109eb291SLukasz Czapnik goto exit_release_res; 588109eb291SLukasz Czapnik 589109eb291SLukasz Czapnik if (layers == ICE_SCHED_5_LAYERS) 590109eb291SLukasz Czapnik usr_sel.data |= ICE_AQC_NVM_TX_TOPO_USER_SEL; 591109eb291SLukasz Czapnik else 592109eb291SLukasz Czapnik usr_sel.data &= ~ICE_AQC_NVM_TX_TOPO_USER_SEL; 593109eb291SLukasz Czapnik 594109eb291SLukasz Czapnik err = ice_write_one_nvm_block(pf, ICE_AQC_NVM_TX_TOPO_MOD_ID, 2, 595109eb291SLukasz Czapnik sizeof(usr_sel.data), &usr_sel.data, 596109eb291SLukasz Czapnik true, NULL, NULL); 597109eb291SLukasz Czapnik exit_release_res: 598109eb291SLukasz Czapnik ice_release_nvm(hw); 599109eb291SLukasz Czapnik 600109eb291SLukasz Czapnik return err; 601109eb291SLukasz Czapnik } 602109eb291SLukasz Czapnik 603109eb291SLukasz Czapnik /** 604109eb291SLukasz Czapnik * ice_devlink_tx_sched_layers_get - Get tx_scheduling_layers parameter 605109eb291SLukasz Czapnik * @devlink: pointer to the devlink instance 606109eb291SLukasz Czapnik * @id: the parameter ID to set 607109eb291SLukasz Czapnik * @ctx: context to store the parameter value 608109eb291SLukasz Czapnik * 609109eb291SLukasz Czapnik * Return: zero on success and negative value on failure. 610109eb291SLukasz Czapnik */ 611109eb291SLukasz Czapnik static int ice_devlink_tx_sched_layers_get(struct devlink *devlink, u32 id, 612109eb291SLukasz Czapnik struct devlink_param_gset_ctx *ctx) 613109eb291SLukasz Czapnik { 614109eb291SLukasz Czapnik struct ice_pf *pf = devlink_priv(devlink); 615109eb291SLukasz Czapnik int err; 616109eb291SLukasz Czapnik 617109eb291SLukasz Czapnik err = ice_get_tx_topo_user_sel(pf, &ctx->val.vu8); 618109eb291SLukasz Czapnik if (err) 619109eb291SLukasz Czapnik return err; 620109eb291SLukasz Czapnik 621109eb291SLukasz Czapnik return 0; 622109eb291SLukasz Czapnik } 623109eb291SLukasz Czapnik 624109eb291SLukasz Czapnik /** 625109eb291SLukasz Czapnik * ice_devlink_tx_sched_layers_set - Set tx_scheduling_layers parameter 626109eb291SLukasz Czapnik * @devlink: pointer to the devlink instance 627109eb291SLukasz Czapnik * @id: the parameter ID to set 628109eb291SLukasz Czapnik * @ctx: context to get the parameter value 629109eb291SLukasz Czapnik * @extack: netlink extended ACK structure 630109eb291SLukasz Czapnik * 631109eb291SLukasz Czapnik * Return: zero on success and negative value on failure. 632109eb291SLukasz Czapnik */ 633109eb291SLukasz Czapnik static int ice_devlink_tx_sched_layers_set(struct devlink *devlink, u32 id, 634109eb291SLukasz Czapnik struct devlink_param_gset_ctx *ctx, 635109eb291SLukasz Czapnik struct netlink_ext_ack *extack) 636109eb291SLukasz Czapnik { 637109eb291SLukasz Czapnik struct ice_pf *pf = devlink_priv(devlink); 638109eb291SLukasz Czapnik int err; 639109eb291SLukasz Czapnik 640109eb291SLukasz Czapnik err = ice_update_tx_topo_user_sel(pf, ctx->val.vu8); 641109eb291SLukasz Czapnik if (err) 642109eb291SLukasz Czapnik return err; 643109eb291SLukasz Czapnik 644109eb291SLukasz Czapnik NL_SET_ERR_MSG_MOD(extack, 645109eb291SLukasz Czapnik "Tx scheduling layers have been changed on this device. You must do the PCI slot powercycle for the change to take effect."); 646109eb291SLukasz Czapnik 647109eb291SLukasz Czapnik return 0; 648109eb291SLukasz Czapnik } 649109eb291SLukasz Czapnik 650109eb291SLukasz Czapnik /** 651109eb291SLukasz Czapnik * ice_devlink_tx_sched_layers_validate - Validate passed tx_scheduling_layers 652109eb291SLukasz Czapnik * parameter value 653109eb291SLukasz Czapnik * @devlink: unused pointer to devlink instance 654109eb291SLukasz Czapnik * @id: the parameter ID to validate 655109eb291SLukasz Czapnik * @val: value to validate 656109eb291SLukasz Czapnik * @extack: netlink extended ACK structure 657109eb291SLukasz Czapnik * 658109eb291SLukasz Czapnik * Supported values are: 659109eb291SLukasz Czapnik * - 5 - five layers Tx Scheduler Topology Tree 660109eb291SLukasz Czapnik * - 9 - nine layers Tx Scheduler Topology Tree 661109eb291SLukasz Czapnik * 662109eb291SLukasz Czapnik * Return: zero when passed parameter value is supported. Negative value on 663109eb291SLukasz Czapnik * error. 664109eb291SLukasz Czapnik */ 665109eb291SLukasz Czapnik static int ice_devlink_tx_sched_layers_validate(struct devlink *devlink, u32 id, 666109eb291SLukasz Czapnik union devlink_param_value val, 667109eb291SLukasz Czapnik struct netlink_ext_ack *extack) 668109eb291SLukasz Czapnik { 669109eb291SLukasz Czapnik if (val.vu8 != ICE_SCHED_5_LAYERS && val.vu8 != ICE_SCHED_9_LAYERS) { 670109eb291SLukasz Czapnik NL_SET_ERR_MSG_MOD(extack, 671109eb291SLukasz Czapnik "Wrong number of tx scheduler layers provided."); 672109eb291SLukasz Czapnik return -EINVAL; 673109eb291SLukasz Czapnik } 674109eb291SLukasz Czapnik 675109eb291SLukasz Czapnik return 0; 676109eb291SLukasz Czapnik } 677109eb291SLukasz Czapnik 678109eb291SLukasz Czapnik /** 6790545cc86SMichal Swiatkowski * ice_tear_down_devlink_rate_tree - removes devlink-rate exported tree 6800545cc86SMichal Swiatkowski * @pf: pf struct 6810545cc86SMichal Swiatkowski * 6820545cc86SMichal Swiatkowski * This function tears down tree exported during VF's creation. 6830545cc86SMichal Swiatkowski */ 6840545cc86SMichal Swiatkowski void ice_tear_down_devlink_rate_tree(struct ice_pf *pf) 6850545cc86SMichal Swiatkowski { 6860545cc86SMichal Swiatkowski struct devlink *devlink; 6870545cc86SMichal Swiatkowski struct ice_vf *vf; 6880545cc86SMichal Swiatkowski unsigned int bkt; 6890545cc86SMichal Swiatkowski 6900545cc86SMichal Swiatkowski devlink = priv_to_devlink(pf); 6910545cc86SMichal Swiatkowski 6920545cc86SMichal Swiatkowski devl_lock(devlink); 6930545cc86SMichal Swiatkowski mutex_lock(&pf->vfs.table_lock); 6940545cc86SMichal Swiatkowski ice_for_each_vf(pf, bkt, vf) { 6950545cc86SMichal Swiatkowski if (vf->devlink_port.devlink_rate) 6960545cc86SMichal Swiatkowski devl_rate_leaf_destroy(&vf->devlink_port); 6970545cc86SMichal Swiatkowski } 6980545cc86SMichal Swiatkowski mutex_unlock(&pf->vfs.table_lock); 6990545cc86SMichal Swiatkowski 7000545cc86SMichal Swiatkowski devl_rate_nodes_destroy(devlink); 7010545cc86SMichal Swiatkowski devl_unlock(devlink); 7020545cc86SMichal Swiatkowski } 7030545cc86SMichal Swiatkowski 7040545cc86SMichal Swiatkowski /** 7050545cc86SMichal Swiatkowski * ice_enable_custom_tx - try to enable custom Tx feature 7060545cc86SMichal Swiatkowski * @pf: pf struct 7070545cc86SMichal Swiatkowski * 7080545cc86SMichal Swiatkowski * This function tries to enable custom Tx feature, 7090545cc86SMichal Swiatkowski * it's not possible to enable it, if DCB or ADQ is active. 7100545cc86SMichal Swiatkowski */ 7110545cc86SMichal Swiatkowski static bool ice_enable_custom_tx(struct ice_pf *pf) 7120545cc86SMichal Swiatkowski { 7130545cc86SMichal Swiatkowski struct ice_port_info *pi = ice_get_main_vsi(pf)->port_info; 7140545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 7150545cc86SMichal Swiatkowski 7160545cc86SMichal Swiatkowski if (pi->is_custom_tx_enabled) 7170545cc86SMichal Swiatkowski /* already enabled, return true */ 7180545cc86SMichal Swiatkowski return true; 7190545cc86SMichal Swiatkowski 7200545cc86SMichal Swiatkowski if (ice_is_adq_active(pf)) { 7210545cc86SMichal Swiatkowski dev_err(dev, "ADQ active, can't modify Tx scheduler tree\n"); 7220545cc86SMichal Swiatkowski return false; 7230545cc86SMichal Swiatkowski } 7240545cc86SMichal Swiatkowski 7250545cc86SMichal Swiatkowski if (ice_is_dcb_active(pf)) { 7260545cc86SMichal Swiatkowski dev_err(dev, "DCB active, can't modify Tx scheduler tree\n"); 7270545cc86SMichal Swiatkowski return false; 7280545cc86SMichal Swiatkowski } 7290545cc86SMichal Swiatkowski 7300545cc86SMichal Swiatkowski pi->is_custom_tx_enabled = true; 7310545cc86SMichal Swiatkowski 7320545cc86SMichal Swiatkowski return true; 7330545cc86SMichal Swiatkowski } 7340545cc86SMichal Swiatkowski 7350545cc86SMichal Swiatkowski /** 7360545cc86SMichal Swiatkowski * ice_traverse_tx_tree - traverse Tx scheduler tree 7370545cc86SMichal Swiatkowski * @devlink: devlink struct 7380545cc86SMichal Swiatkowski * @node: current node, used for recursion 7390545cc86SMichal Swiatkowski * @tc_node: tc_node struct, that is treated as a root 7400545cc86SMichal Swiatkowski * @pf: pf struct 7410545cc86SMichal Swiatkowski * 7420545cc86SMichal Swiatkowski * This function traverses Tx scheduler tree and exports 7430545cc86SMichal Swiatkowski * entire structure to the devlink-rate. 7440545cc86SMichal Swiatkowski */ 7450545cc86SMichal Swiatkowski static void ice_traverse_tx_tree(struct devlink *devlink, struct ice_sched_node *node, 7460545cc86SMichal Swiatkowski struct ice_sched_node *tc_node, struct ice_pf *pf) 7470545cc86SMichal Swiatkowski { 7480545cc86SMichal Swiatkowski struct devlink_rate *rate_node = NULL; 7490545cc86SMichal Swiatkowski struct ice_vf *vf; 7500545cc86SMichal Swiatkowski int i; 7510545cc86SMichal Swiatkowski 7520545cc86SMichal Swiatkowski if (node->rate_node) 7530545cc86SMichal Swiatkowski /* already added, skip to the next */ 7540545cc86SMichal Swiatkowski goto traverse_children; 7550545cc86SMichal Swiatkowski 7560545cc86SMichal Swiatkowski if (node->parent == tc_node) { 7570545cc86SMichal Swiatkowski /* create root node */ 7580545cc86SMichal Swiatkowski rate_node = devl_rate_node_create(devlink, node, node->name, NULL); 7590545cc86SMichal Swiatkowski } else if (node->vsi_handle && 7600545cc86SMichal Swiatkowski pf->vsi[node->vsi_handle]->vf) { 7610545cc86SMichal Swiatkowski vf = pf->vsi[node->vsi_handle]->vf; 7620545cc86SMichal Swiatkowski if (!vf->devlink_port.devlink_rate) 7630545cc86SMichal Swiatkowski /* leaf nodes doesn't have children 7640545cc86SMichal Swiatkowski * so we don't set rate_node 7650545cc86SMichal Swiatkowski */ 7660545cc86SMichal Swiatkowski devl_rate_leaf_create(&vf->devlink_port, node, 7670545cc86SMichal Swiatkowski node->parent->rate_node); 7680545cc86SMichal Swiatkowski } else if (node->info.data.elem_type != ICE_AQC_ELEM_TYPE_LEAF && 7690545cc86SMichal Swiatkowski node->parent->rate_node) { 7700545cc86SMichal Swiatkowski rate_node = devl_rate_node_create(devlink, node, node->name, 7710545cc86SMichal Swiatkowski node->parent->rate_node); 7720545cc86SMichal Swiatkowski } 7730545cc86SMichal Swiatkowski 7740545cc86SMichal Swiatkowski if (rate_node && !IS_ERR(rate_node)) 7750545cc86SMichal Swiatkowski node->rate_node = rate_node; 7760545cc86SMichal Swiatkowski 7770545cc86SMichal Swiatkowski traverse_children: 7780545cc86SMichal Swiatkowski for (i = 0; i < node->num_children; i++) 7790545cc86SMichal Swiatkowski ice_traverse_tx_tree(devlink, node->children[i], tc_node, pf); 7800545cc86SMichal Swiatkowski } 7810545cc86SMichal Swiatkowski 7820545cc86SMichal Swiatkowski /** 7830545cc86SMichal Swiatkowski * ice_devlink_rate_init_tx_topology - export Tx scheduler tree to devlink rate 7840545cc86SMichal Swiatkowski * @devlink: devlink struct 7850545cc86SMichal Swiatkowski * @vsi: main vsi struct 7860545cc86SMichal Swiatkowski * 7870545cc86SMichal Swiatkowski * This function finds a root node, then calls ice_traverse_tx tree, which 7880545cc86SMichal Swiatkowski * traverses the tree and exports it's contents to devlink rate. 7890545cc86SMichal Swiatkowski */ 7900545cc86SMichal Swiatkowski int ice_devlink_rate_init_tx_topology(struct devlink *devlink, struct ice_vsi *vsi) 7910545cc86SMichal Swiatkowski { 7920545cc86SMichal Swiatkowski struct ice_port_info *pi = vsi->port_info; 7930545cc86SMichal Swiatkowski struct ice_sched_node *tc_node; 7940545cc86SMichal Swiatkowski struct ice_pf *pf = vsi->back; 7950545cc86SMichal Swiatkowski int i; 7960545cc86SMichal Swiatkowski 7970545cc86SMichal Swiatkowski tc_node = pi->root->children[0]; 7980545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 7990545cc86SMichal Swiatkowski for (i = 0; i < tc_node->num_children; i++) 8000545cc86SMichal Swiatkowski ice_traverse_tx_tree(devlink, tc_node->children[i], tc_node, pf); 8010545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 8020545cc86SMichal Swiatkowski 8030545cc86SMichal Swiatkowski return 0; 8040545cc86SMichal Swiatkowski } 8050545cc86SMichal Swiatkowski 8060545cc86SMichal Swiatkowski static void ice_clear_rate_nodes(struct ice_sched_node *node) 8070545cc86SMichal Swiatkowski { 8080545cc86SMichal Swiatkowski node->rate_node = NULL; 8090545cc86SMichal Swiatkowski 8100545cc86SMichal Swiatkowski for (int i = 0; i < node->num_children; i++) 8110545cc86SMichal Swiatkowski ice_clear_rate_nodes(node->children[i]); 8120545cc86SMichal Swiatkowski } 8130545cc86SMichal Swiatkowski 8140545cc86SMichal Swiatkowski /** 8150545cc86SMichal Swiatkowski * ice_devlink_rate_clear_tx_topology - clear node->rate_node 8160545cc86SMichal Swiatkowski * @vsi: main vsi struct 8170545cc86SMichal Swiatkowski * 8180545cc86SMichal Swiatkowski * Clear rate_node to cleanup creation of Tx topology. 8190545cc86SMichal Swiatkowski * 8200545cc86SMichal Swiatkowski */ 8210545cc86SMichal Swiatkowski void ice_devlink_rate_clear_tx_topology(struct ice_vsi *vsi) 8220545cc86SMichal Swiatkowski { 8230545cc86SMichal Swiatkowski struct ice_port_info *pi = vsi->port_info; 8240545cc86SMichal Swiatkowski 8250545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 8260545cc86SMichal Swiatkowski ice_clear_rate_nodes(pi->root->children[0]); 8270545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 8280545cc86SMichal Swiatkowski } 8290545cc86SMichal Swiatkowski 8300545cc86SMichal Swiatkowski /** 8310545cc86SMichal Swiatkowski * ice_set_object_tx_share - sets node scheduling parameter 8320545cc86SMichal Swiatkowski * @pi: devlink struct instance 8330545cc86SMichal Swiatkowski * @node: node struct instance 8340545cc86SMichal Swiatkowski * @bw: bandwidth in bytes per second 8350545cc86SMichal Swiatkowski * @extack: extended netdev ack structure 8360545cc86SMichal Swiatkowski * 8370545cc86SMichal Swiatkowski * This function sets ICE_MIN_BW scheduling BW limit. 8380545cc86SMichal Swiatkowski */ 8390545cc86SMichal Swiatkowski static int ice_set_object_tx_share(struct ice_port_info *pi, struct ice_sched_node *node, 8400545cc86SMichal Swiatkowski u64 bw, struct netlink_ext_ack *extack) 8410545cc86SMichal Swiatkowski { 8420545cc86SMichal Swiatkowski int status; 8430545cc86SMichal Swiatkowski 8440545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 8450545cc86SMichal Swiatkowski /* converts bytes per second to kilo bits per second */ 8460545cc86SMichal Swiatkowski node->tx_share = div_u64(bw, 125); 8470545cc86SMichal Swiatkowski status = ice_sched_set_node_bw_lmt(pi, node, ICE_MIN_BW, node->tx_share); 8480545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 8490545cc86SMichal Swiatkowski 8500545cc86SMichal Swiatkowski if (status) 8510545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Can't set scheduling node tx_share"); 8520545cc86SMichal Swiatkowski 8530545cc86SMichal Swiatkowski return status; 8540545cc86SMichal Swiatkowski } 8550545cc86SMichal Swiatkowski 8560545cc86SMichal Swiatkowski /** 8570545cc86SMichal Swiatkowski * ice_set_object_tx_max - sets node scheduling parameter 8580545cc86SMichal Swiatkowski * @pi: devlink struct instance 8590545cc86SMichal Swiatkowski * @node: node struct instance 8600545cc86SMichal Swiatkowski * @bw: bandwidth in bytes per second 8610545cc86SMichal Swiatkowski * @extack: extended netdev ack structure 8620545cc86SMichal Swiatkowski * 8630545cc86SMichal Swiatkowski * This function sets ICE_MAX_BW scheduling BW limit. 8640545cc86SMichal Swiatkowski */ 8650545cc86SMichal Swiatkowski static int ice_set_object_tx_max(struct ice_port_info *pi, struct ice_sched_node *node, 8660545cc86SMichal Swiatkowski u64 bw, struct netlink_ext_ack *extack) 8670545cc86SMichal Swiatkowski { 8680545cc86SMichal Swiatkowski int status; 8690545cc86SMichal Swiatkowski 8700545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 8710545cc86SMichal Swiatkowski /* converts bytes per second value to kilo bits per second */ 8720545cc86SMichal Swiatkowski node->tx_max = div_u64(bw, 125); 8730545cc86SMichal Swiatkowski status = ice_sched_set_node_bw_lmt(pi, node, ICE_MAX_BW, node->tx_max); 8740545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 8750545cc86SMichal Swiatkowski 8760545cc86SMichal Swiatkowski if (status) 8770545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Can't set scheduling node tx_max"); 8780545cc86SMichal Swiatkowski 8790545cc86SMichal Swiatkowski return status; 8800545cc86SMichal Swiatkowski } 8810545cc86SMichal Swiatkowski 8820545cc86SMichal Swiatkowski /** 8830545cc86SMichal Swiatkowski * ice_set_object_tx_priority - sets node scheduling parameter 8840545cc86SMichal Swiatkowski * @pi: devlink struct instance 8850545cc86SMichal Swiatkowski * @node: node struct instance 8860545cc86SMichal Swiatkowski * @priority: value representing priority for strict priority arbitration 8870545cc86SMichal Swiatkowski * @extack: extended netdev ack structure 8880545cc86SMichal Swiatkowski * 8890545cc86SMichal Swiatkowski * This function sets priority of node among siblings. 8900545cc86SMichal Swiatkowski */ 8910545cc86SMichal Swiatkowski static int ice_set_object_tx_priority(struct ice_port_info *pi, struct ice_sched_node *node, 8920545cc86SMichal Swiatkowski u32 priority, struct netlink_ext_ack *extack) 8930545cc86SMichal Swiatkowski { 8940545cc86SMichal Swiatkowski int status; 8950545cc86SMichal Swiatkowski 8960545cc86SMichal Swiatkowski if (priority >= 8) { 8970545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Priority should be less than 8"); 8980545cc86SMichal Swiatkowski return -EINVAL; 8990545cc86SMichal Swiatkowski } 9000545cc86SMichal Swiatkowski 9010545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 9020545cc86SMichal Swiatkowski node->tx_priority = priority; 9030545cc86SMichal Swiatkowski status = ice_sched_set_node_priority(pi, node, node->tx_priority); 9040545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 9050545cc86SMichal Swiatkowski 9060545cc86SMichal Swiatkowski if (status) 9070545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Can't set scheduling node tx_priority"); 9080545cc86SMichal Swiatkowski 9090545cc86SMichal Swiatkowski return status; 9100545cc86SMichal Swiatkowski } 9110545cc86SMichal Swiatkowski 9120545cc86SMichal Swiatkowski /** 9130545cc86SMichal Swiatkowski * ice_set_object_tx_weight - sets node scheduling parameter 9140545cc86SMichal Swiatkowski * @pi: devlink struct instance 9150545cc86SMichal Swiatkowski * @node: node struct instance 9160545cc86SMichal Swiatkowski * @weight: value represeting relative weight for WFQ arbitration 9170545cc86SMichal Swiatkowski * @extack: extended netdev ack structure 9180545cc86SMichal Swiatkowski * 9190545cc86SMichal Swiatkowski * This function sets node weight for WFQ algorithm. 9200545cc86SMichal Swiatkowski */ 9210545cc86SMichal Swiatkowski static int ice_set_object_tx_weight(struct ice_port_info *pi, struct ice_sched_node *node, 9220545cc86SMichal Swiatkowski u32 weight, struct netlink_ext_ack *extack) 9230545cc86SMichal Swiatkowski { 9240545cc86SMichal Swiatkowski int status; 9250545cc86SMichal Swiatkowski 9260545cc86SMichal Swiatkowski if (weight > 200 || weight < 1) { 9270545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Weight must be between 1 and 200"); 9280545cc86SMichal Swiatkowski return -EINVAL; 9290545cc86SMichal Swiatkowski } 9300545cc86SMichal Swiatkowski 9310545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 9320545cc86SMichal Swiatkowski node->tx_weight = weight; 9330545cc86SMichal Swiatkowski status = ice_sched_set_node_weight(pi, node, node->tx_weight); 9340545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 9350545cc86SMichal Swiatkowski 9360545cc86SMichal Swiatkowski if (status) 9370545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Can't set scheduling node tx_weight"); 9380545cc86SMichal Swiatkowski 9390545cc86SMichal Swiatkowski return status; 9400545cc86SMichal Swiatkowski } 9410545cc86SMichal Swiatkowski 9420545cc86SMichal Swiatkowski /** 9430545cc86SMichal Swiatkowski * ice_get_pi_from_dev_rate - get port info from devlink_rate 9440545cc86SMichal Swiatkowski * @rate_node: devlink struct instance 9450545cc86SMichal Swiatkowski * 9460545cc86SMichal Swiatkowski * This function returns corresponding port_info struct of devlink_rate 9470545cc86SMichal Swiatkowski */ 9480545cc86SMichal Swiatkowski static struct ice_port_info *ice_get_pi_from_dev_rate(struct devlink_rate *rate_node) 9490545cc86SMichal Swiatkowski { 9500545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(rate_node->devlink); 9510545cc86SMichal Swiatkowski 9520545cc86SMichal Swiatkowski return ice_get_main_vsi(pf)->port_info; 9530545cc86SMichal Swiatkowski } 9540545cc86SMichal Swiatkowski 9550545cc86SMichal Swiatkowski static int ice_devlink_rate_node_new(struct devlink_rate *rate_node, void **priv, 9560545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 9570545cc86SMichal Swiatkowski { 9580545cc86SMichal Swiatkowski struct ice_sched_node *node; 9590545cc86SMichal Swiatkowski struct ice_port_info *pi; 9600545cc86SMichal Swiatkowski 9610545cc86SMichal Swiatkowski pi = ice_get_pi_from_dev_rate(rate_node); 9620545cc86SMichal Swiatkowski 9630545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink))) 9640545cc86SMichal Swiatkowski return -EBUSY; 9650545cc86SMichal Swiatkowski 9660545cc86SMichal Swiatkowski /* preallocate memory for ice_sched_node */ 9670545cc86SMichal Swiatkowski node = devm_kzalloc(ice_hw_to_dev(pi->hw), sizeof(*node), GFP_KERNEL); 9680545cc86SMichal Swiatkowski *priv = node; 9690545cc86SMichal Swiatkowski 9700545cc86SMichal Swiatkowski return 0; 9710545cc86SMichal Swiatkowski } 9720545cc86SMichal Swiatkowski 9730545cc86SMichal Swiatkowski static int ice_devlink_rate_node_del(struct devlink_rate *rate_node, void *priv, 9740545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 9750545cc86SMichal Swiatkowski { 9760545cc86SMichal Swiatkowski struct ice_sched_node *node, *tc_node; 9770545cc86SMichal Swiatkowski struct ice_port_info *pi; 9780545cc86SMichal Swiatkowski 9790545cc86SMichal Swiatkowski pi = ice_get_pi_from_dev_rate(rate_node); 9800545cc86SMichal Swiatkowski tc_node = pi->root->children[0]; 9810545cc86SMichal Swiatkowski node = priv; 9820545cc86SMichal Swiatkowski 9830545cc86SMichal Swiatkowski if (!rate_node->parent || !node || tc_node == node || !extack) 9840545cc86SMichal Swiatkowski return 0; 9850545cc86SMichal Swiatkowski 9860545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink))) 9870545cc86SMichal Swiatkowski return -EBUSY; 9880545cc86SMichal Swiatkowski 9890545cc86SMichal Swiatkowski /* can't allow to delete a node with children */ 9900545cc86SMichal Swiatkowski if (node->num_children) 9910545cc86SMichal Swiatkowski return -EINVAL; 9920545cc86SMichal Swiatkowski 9930545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 9940545cc86SMichal Swiatkowski ice_free_sched_node(pi, node); 9950545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 9960545cc86SMichal Swiatkowski 9970545cc86SMichal Swiatkowski return 0; 9980545cc86SMichal Swiatkowski } 9990545cc86SMichal Swiatkowski 10000545cc86SMichal Swiatkowski static int ice_devlink_rate_leaf_tx_max_set(struct devlink_rate *rate_leaf, void *priv, 10010545cc86SMichal Swiatkowski u64 tx_max, struct netlink_ext_ack *extack) 10020545cc86SMichal Swiatkowski { 10030545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 10040545cc86SMichal Swiatkowski 10050545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_leaf->devlink))) 10060545cc86SMichal Swiatkowski return -EBUSY; 10070545cc86SMichal Swiatkowski 10080545cc86SMichal Swiatkowski if (!node) 10090545cc86SMichal Swiatkowski return 0; 10100545cc86SMichal Swiatkowski 10110545cc86SMichal Swiatkowski return ice_set_object_tx_max(ice_get_pi_from_dev_rate(rate_leaf), 10120545cc86SMichal Swiatkowski node, tx_max, extack); 10130545cc86SMichal Swiatkowski } 10140545cc86SMichal Swiatkowski 10150545cc86SMichal Swiatkowski static int ice_devlink_rate_leaf_tx_share_set(struct devlink_rate *rate_leaf, void *priv, 10160545cc86SMichal Swiatkowski u64 tx_share, struct netlink_ext_ack *extack) 10170545cc86SMichal Swiatkowski { 10180545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 10190545cc86SMichal Swiatkowski 10200545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_leaf->devlink))) 10210545cc86SMichal Swiatkowski return -EBUSY; 10220545cc86SMichal Swiatkowski 10230545cc86SMichal Swiatkowski if (!node) 10240545cc86SMichal Swiatkowski return 0; 10250545cc86SMichal Swiatkowski 10260545cc86SMichal Swiatkowski return ice_set_object_tx_share(ice_get_pi_from_dev_rate(rate_leaf), node, 10270545cc86SMichal Swiatkowski tx_share, extack); 10280545cc86SMichal Swiatkowski } 10290545cc86SMichal Swiatkowski 10300545cc86SMichal Swiatkowski static int ice_devlink_rate_leaf_tx_priority_set(struct devlink_rate *rate_leaf, void *priv, 10310545cc86SMichal Swiatkowski u32 tx_priority, struct netlink_ext_ack *extack) 10320545cc86SMichal Swiatkowski { 10330545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 10340545cc86SMichal Swiatkowski 10350545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_leaf->devlink))) 10360545cc86SMichal Swiatkowski return -EBUSY; 10370545cc86SMichal Swiatkowski 10380545cc86SMichal Swiatkowski if (!node) 10390545cc86SMichal Swiatkowski return 0; 10400545cc86SMichal Swiatkowski 10410545cc86SMichal Swiatkowski return ice_set_object_tx_priority(ice_get_pi_from_dev_rate(rate_leaf), node, 10420545cc86SMichal Swiatkowski tx_priority, extack); 10430545cc86SMichal Swiatkowski } 10440545cc86SMichal Swiatkowski 10450545cc86SMichal Swiatkowski static int ice_devlink_rate_leaf_tx_weight_set(struct devlink_rate *rate_leaf, void *priv, 10460545cc86SMichal Swiatkowski u32 tx_weight, struct netlink_ext_ack *extack) 10470545cc86SMichal Swiatkowski { 10480545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 10490545cc86SMichal Swiatkowski 10500545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_leaf->devlink))) 10510545cc86SMichal Swiatkowski return -EBUSY; 10520545cc86SMichal Swiatkowski 10530545cc86SMichal Swiatkowski if (!node) 10540545cc86SMichal Swiatkowski return 0; 10550545cc86SMichal Swiatkowski 10560545cc86SMichal Swiatkowski return ice_set_object_tx_weight(ice_get_pi_from_dev_rate(rate_leaf), node, 10570545cc86SMichal Swiatkowski tx_weight, extack); 10580545cc86SMichal Swiatkowski } 10590545cc86SMichal Swiatkowski 10600545cc86SMichal Swiatkowski static int ice_devlink_rate_node_tx_max_set(struct devlink_rate *rate_node, void *priv, 10610545cc86SMichal Swiatkowski u64 tx_max, struct netlink_ext_ack *extack) 10620545cc86SMichal Swiatkowski { 10630545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 10640545cc86SMichal Swiatkowski 10650545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink))) 10660545cc86SMichal Swiatkowski return -EBUSY; 10670545cc86SMichal Swiatkowski 10680545cc86SMichal Swiatkowski if (!node) 10690545cc86SMichal Swiatkowski return 0; 10700545cc86SMichal Swiatkowski 10710545cc86SMichal Swiatkowski return ice_set_object_tx_max(ice_get_pi_from_dev_rate(rate_node), 10720545cc86SMichal Swiatkowski node, tx_max, extack); 10730545cc86SMichal Swiatkowski } 10740545cc86SMichal Swiatkowski 10750545cc86SMichal Swiatkowski static int ice_devlink_rate_node_tx_share_set(struct devlink_rate *rate_node, void *priv, 10760545cc86SMichal Swiatkowski u64 tx_share, struct netlink_ext_ack *extack) 10770545cc86SMichal Swiatkowski { 10780545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 10790545cc86SMichal Swiatkowski 10800545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink))) 10810545cc86SMichal Swiatkowski return -EBUSY; 10820545cc86SMichal Swiatkowski 10830545cc86SMichal Swiatkowski if (!node) 10840545cc86SMichal Swiatkowski return 0; 10850545cc86SMichal Swiatkowski 10860545cc86SMichal Swiatkowski return ice_set_object_tx_share(ice_get_pi_from_dev_rate(rate_node), 10870545cc86SMichal Swiatkowski node, tx_share, extack); 10880545cc86SMichal Swiatkowski } 10890545cc86SMichal Swiatkowski 10900545cc86SMichal Swiatkowski static int ice_devlink_rate_node_tx_priority_set(struct devlink_rate *rate_node, void *priv, 10910545cc86SMichal Swiatkowski u32 tx_priority, struct netlink_ext_ack *extack) 10920545cc86SMichal Swiatkowski { 10930545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 10940545cc86SMichal Swiatkowski 10950545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink))) 10960545cc86SMichal Swiatkowski return -EBUSY; 10970545cc86SMichal Swiatkowski 10980545cc86SMichal Swiatkowski if (!node) 10990545cc86SMichal Swiatkowski return 0; 11000545cc86SMichal Swiatkowski 11010545cc86SMichal Swiatkowski return ice_set_object_tx_priority(ice_get_pi_from_dev_rate(rate_node), 11020545cc86SMichal Swiatkowski node, tx_priority, extack); 11030545cc86SMichal Swiatkowski } 11040545cc86SMichal Swiatkowski 11050545cc86SMichal Swiatkowski static int ice_devlink_rate_node_tx_weight_set(struct devlink_rate *rate_node, void *priv, 11060545cc86SMichal Swiatkowski u32 tx_weight, struct netlink_ext_ack *extack) 11070545cc86SMichal Swiatkowski { 11080545cc86SMichal Swiatkowski struct ice_sched_node *node = priv; 11090545cc86SMichal Swiatkowski 11100545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(rate_node->devlink))) 11110545cc86SMichal Swiatkowski return -EBUSY; 11120545cc86SMichal Swiatkowski 11130545cc86SMichal Swiatkowski if (!node) 11140545cc86SMichal Swiatkowski return 0; 11150545cc86SMichal Swiatkowski 11160545cc86SMichal Swiatkowski return ice_set_object_tx_weight(ice_get_pi_from_dev_rate(rate_node), 11170545cc86SMichal Swiatkowski node, tx_weight, extack); 11180545cc86SMichal Swiatkowski } 11190545cc86SMichal Swiatkowski 11200545cc86SMichal Swiatkowski static int ice_devlink_set_parent(struct devlink_rate *devlink_rate, 11210545cc86SMichal Swiatkowski struct devlink_rate *parent, 11220545cc86SMichal Swiatkowski void *priv, void *parent_priv, 11230545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 11240545cc86SMichal Swiatkowski { 11250545cc86SMichal Swiatkowski struct ice_port_info *pi = ice_get_pi_from_dev_rate(devlink_rate); 11260545cc86SMichal Swiatkowski struct ice_sched_node *tc_node, *node, *parent_node; 11270545cc86SMichal Swiatkowski u16 num_nodes_added; 11280545cc86SMichal Swiatkowski u32 first_node_teid; 11290545cc86SMichal Swiatkowski u32 node_teid; 11300545cc86SMichal Swiatkowski int status; 11310545cc86SMichal Swiatkowski 11320545cc86SMichal Swiatkowski tc_node = pi->root->children[0]; 11330545cc86SMichal Swiatkowski node = priv; 11340545cc86SMichal Swiatkowski 11350545cc86SMichal Swiatkowski if (!extack) 11360545cc86SMichal Swiatkowski return 0; 11370545cc86SMichal Swiatkowski 11380545cc86SMichal Swiatkowski if (!ice_enable_custom_tx(devlink_priv(devlink_rate->devlink))) 11390545cc86SMichal Swiatkowski return -EBUSY; 11400545cc86SMichal Swiatkowski 11410545cc86SMichal Swiatkowski if (!parent) { 11420545cc86SMichal Swiatkowski if (!node || tc_node == node || node->num_children) 11430545cc86SMichal Swiatkowski return -EINVAL; 11440545cc86SMichal Swiatkowski 11450545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 11460545cc86SMichal Swiatkowski ice_free_sched_node(pi, node); 11470545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 11480545cc86SMichal Swiatkowski 11490545cc86SMichal Swiatkowski return 0; 11500545cc86SMichal Swiatkowski } 11510545cc86SMichal Swiatkowski 11520545cc86SMichal Swiatkowski parent_node = parent_priv; 11530545cc86SMichal Swiatkowski 11540545cc86SMichal Swiatkowski /* if the node doesn't exist, create it */ 11550545cc86SMichal Swiatkowski if (!node->parent) { 11560545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 11570545cc86SMichal Swiatkowski status = ice_sched_add_elems(pi, tc_node, parent_node, 11580545cc86SMichal Swiatkowski parent_node->tx_sched_layer + 1, 11590545cc86SMichal Swiatkowski 1, &num_nodes_added, &first_node_teid, 11600545cc86SMichal Swiatkowski &node); 11610545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 11620545cc86SMichal Swiatkowski 11630545cc86SMichal Swiatkowski if (status) { 11640545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Can't add a new node"); 11650545cc86SMichal Swiatkowski return status; 11660545cc86SMichal Swiatkowski } 11670545cc86SMichal Swiatkowski 11680545cc86SMichal Swiatkowski if (devlink_rate->tx_share) 11690545cc86SMichal Swiatkowski ice_set_object_tx_share(pi, node, devlink_rate->tx_share, extack); 11700545cc86SMichal Swiatkowski if (devlink_rate->tx_max) 11710545cc86SMichal Swiatkowski ice_set_object_tx_max(pi, node, devlink_rate->tx_max, extack); 11720545cc86SMichal Swiatkowski if (devlink_rate->tx_priority) 11730545cc86SMichal Swiatkowski ice_set_object_tx_priority(pi, node, devlink_rate->tx_priority, extack); 11740545cc86SMichal Swiatkowski if (devlink_rate->tx_weight) 11750545cc86SMichal Swiatkowski ice_set_object_tx_weight(pi, node, devlink_rate->tx_weight, extack); 11760545cc86SMichal Swiatkowski } else { 11770545cc86SMichal Swiatkowski node_teid = le32_to_cpu(node->info.node_teid); 11780545cc86SMichal Swiatkowski mutex_lock(&pi->sched_lock); 11790545cc86SMichal Swiatkowski status = ice_sched_move_nodes(pi, parent_node, 1, &node_teid); 11800545cc86SMichal Swiatkowski mutex_unlock(&pi->sched_lock); 11810545cc86SMichal Swiatkowski 11820545cc86SMichal Swiatkowski if (status) 11830545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Can't move existing node to a new parent"); 11840545cc86SMichal Swiatkowski } 11850545cc86SMichal Swiatkowski 11860545cc86SMichal Swiatkowski return status; 11870545cc86SMichal Swiatkowski } 11880545cc86SMichal Swiatkowski 11890545cc86SMichal Swiatkowski /** 11900545cc86SMichal Swiatkowski * ice_devlink_reinit_up - do reinit of the given PF 11910545cc86SMichal Swiatkowski * @pf: pointer to the PF struct 11920545cc86SMichal Swiatkowski */ 11930545cc86SMichal Swiatkowski static int ice_devlink_reinit_up(struct ice_pf *pf) 11940545cc86SMichal Swiatkowski { 11950545cc86SMichal Swiatkowski struct ice_vsi *vsi = ice_get_main_vsi(pf); 11960545cc86SMichal Swiatkowski int err; 11970545cc86SMichal Swiatkowski 11980545cc86SMichal Swiatkowski err = ice_init_dev(pf); 11990545cc86SMichal Swiatkowski if (err) 12000545cc86SMichal Swiatkowski return err; 12010545cc86SMichal Swiatkowski 1202deea427fSMateusz Polchlopek vsi->flags = ICE_VSI_FLAG_INIT; 12030545cc86SMichal Swiatkowski 12040545cc86SMichal Swiatkowski rtnl_lock(); 1205deea427fSMateusz Polchlopek err = ice_vsi_cfg(vsi); 12060545cc86SMichal Swiatkowski rtnl_unlock(); 12070545cc86SMichal Swiatkowski if (err) 12080545cc86SMichal Swiatkowski goto err_vsi_cfg; 12090545cc86SMichal Swiatkowski 12100545cc86SMichal Swiatkowski /* No need to take devl_lock, it's already taken by devlink API */ 12110545cc86SMichal Swiatkowski err = ice_load(pf); 12120545cc86SMichal Swiatkowski if (err) 12130545cc86SMichal Swiatkowski goto err_load; 12140545cc86SMichal Swiatkowski 12150545cc86SMichal Swiatkowski return 0; 12160545cc86SMichal Swiatkowski 12170545cc86SMichal Swiatkowski err_load: 12180545cc86SMichal Swiatkowski rtnl_lock(); 12190545cc86SMichal Swiatkowski ice_vsi_decfg(vsi); 12200545cc86SMichal Swiatkowski rtnl_unlock(); 12210545cc86SMichal Swiatkowski err_vsi_cfg: 12220545cc86SMichal Swiatkowski ice_deinit_dev(pf); 12230545cc86SMichal Swiatkowski return err; 12240545cc86SMichal Swiatkowski } 12250545cc86SMichal Swiatkowski 12260545cc86SMichal Swiatkowski /** 12270545cc86SMichal Swiatkowski * ice_devlink_reload_up - do reload up after reinit 12280545cc86SMichal Swiatkowski * @devlink: pointer to the devlink instance reloading 12290545cc86SMichal Swiatkowski * @action: the action requested 12300545cc86SMichal Swiatkowski * @limit: limits imposed by userspace, such as not resetting 12310545cc86SMichal Swiatkowski * @actions_performed: on return, indicate what actions actually performed 12320545cc86SMichal Swiatkowski * @extack: netlink extended ACK structure 12330545cc86SMichal Swiatkowski */ 12340545cc86SMichal Swiatkowski static int 12350545cc86SMichal Swiatkowski ice_devlink_reload_up(struct devlink *devlink, 12360545cc86SMichal Swiatkowski enum devlink_reload_action action, 12370545cc86SMichal Swiatkowski enum devlink_reload_limit limit, 12380545cc86SMichal Swiatkowski u32 *actions_performed, 12390545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 12400545cc86SMichal Swiatkowski { 12410545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 12420545cc86SMichal Swiatkowski 12430545cc86SMichal Swiatkowski switch (action) { 12440545cc86SMichal Swiatkowski case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: 12450545cc86SMichal Swiatkowski *actions_performed = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT); 12460545cc86SMichal Swiatkowski return ice_devlink_reinit_up(pf); 12470545cc86SMichal Swiatkowski case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: 12480545cc86SMichal Swiatkowski *actions_performed = BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE); 12490545cc86SMichal Swiatkowski return ice_devlink_reload_empr_finish(pf, extack); 12500545cc86SMichal Swiatkowski default: 12510545cc86SMichal Swiatkowski WARN_ON(1); 12520545cc86SMichal Swiatkowski return -EOPNOTSUPP; 12530545cc86SMichal Swiatkowski } 12540545cc86SMichal Swiatkowski } 12550545cc86SMichal Swiatkowski 12560545cc86SMichal Swiatkowski static const struct devlink_ops ice_devlink_ops = { 12570545cc86SMichal Swiatkowski .supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK, 12580545cc86SMichal Swiatkowski .reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) | 12590545cc86SMichal Swiatkowski BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE), 12600545cc86SMichal Swiatkowski .reload_down = ice_devlink_reload_down, 12610545cc86SMichal Swiatkowski .reload_up = ice_devlink_reload_up, 12620545cc86SMichal Swiatkowski .eswitch_mode_get = ice_eswitch_mode_get, 12630545cc86SMichal Swiatkowski .eswitch_mode_set = ice_eswitch_mode_set, 12640545cc86SMichal Swiatkowski .info_get = ice_devlink_info_get, 12650545cc86SMichal Swiatkowski .flash_update = ice_devlink_flash_update, 12660545cc86SMichal Swiatkowski 12670545cc86SMichal Swiatkowski .rate_node_new = ice_devlink_rate_node_new, 12680545cc86SMichal Swiatkowski .rate_node_del = ice_devlink_rate_node_del, 12690545cc86SMichal Swiatkowski 12700545cc86SMichal Swiatkowski .rate_leaf_tx_max_set = ice_devlink_rate_leaf_tx_max_set, 12710545cc86SMichal Swiatkowski .rate_leaf_tx_share_set = ice_devlink_rate_leaf_tx_share_set, 12720545cc86SMichal Swiatkowski .rate_leaf_tx_priority_set = ice_devlink_rate_leaf_tx_priority_set, 12730545cc86SMichal Swiatkowski .rate_leaf_tx_weight_set = ice_devlink_rate_leaf_tx_weight_set, 12740545cc86SMichal Swiatkowski 12750545cc86SMichal Swiatkowski .rate_node_tx_max_set = ice_devlink_rate_node_tx_max_set, 12760545cc86SMichal Swiatkowski .rate_node_tx_share_set = ice_devlink_rate_node_tx_share_set, 12770545cc86SMichal Swiatkowski .rate_node_tx_priority_set = ice_devlink_rate_node_tx_priority_set, 12780545cc86SMichal Swiatkowski .rate_node_tx_weight_set = ice_devlink_rate_node_tx_weight_set, 12790545cc86SMichal Swiatkowski 12800545cc86SMichal Swiatkowski .rate_leaf_parent_set = ice_devlink_set_parent, 12810545cc86SMichal Swiatkowski .rate_node_parent_set = ice_devlink_set_parent, 1282eda69d65SPiotr Raczynski 1283eda69d65SPiotr Raczynski .port_new = ice_devlink_port_new, 12840545cc86SMichal Swiatkowski }; 12850545cc86SMichal Swiatkowski 1286*f43e3be6SPiotr Raczynski static const struct devlink_ops ice_sf_devlink_ops; 1287*f43e3be6SPiotr Raczynski 12880545cc86SMichal Swiatkowski static int 12890545cc86SMichal Swiatkowski ice_devlink_enable_roce_get(struct devlink *devlink, u32 id, 12900545cc86SMichal Swiatkowski struct devlink_param_gset_ctx *ctx) 12910545cc86SMichal Swiatkowski { 12920545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 12930545cc86SMichal Swiatkowski 12940545cc86SMichal Swiatkowski ctx->val.vbool = pf->rdma_mode & IIDC_RDMA_PROTOCOL_ROCEV2 ? true : false; 12950545cc86SMichal Swiatkowski 12960545cc86SMichal Swiatkowski return 0; 12970545cc86SMichal Swiatkowski } 12980545cc86SMichal Swiatkowski 12995625ca56SMateusz Polchlopek static int ice_devlink_enable_roce_set(struct devlink *devlink, u32 id, 13005625ca56SMateusz Polchlopek struct devlink_param_gset_ctx *ctx, 13015625ca56SMateusz Polchlopek struct netlink_ext_ack *extack) 13020545cc86SMichal Swiatkowski { 13030545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 13040545cc86SMichal Swiatkowski bool roce_ena = ctx->val.vbool; 13050545cc86SMichal Swiatkowski int ret; 13060545cc86SMichal Swiatkowski 13070545cc86SMichal Swiatkowski if (!roce_ena) { 13080545cc86SMichal Swiatkowski ice_unplug_aux_dev(pf); 13090545cc86SMichal Swiatkowski pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_ROCEV2; 13100545cc86SMichal Swiatkowski return 0; 13110545cc86SMichal Swiatkowski } 13120545cc86SMichal Swiatkowski 13130545cc86SMichal Swiatkowski pf->rdma_mode |= IIDC_RDMA_PROTOCOL_ROCEV2; 13140545cc86SMichal Swiatkowski ret = ice_plug_aux_dev(pf); 13150545cc86SMichal Swiatkowski if (ret) 13160545cc86SMichal Swiatkowski pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_ROCEV2; 13170545cc86SMichal Swiatkowski 13180545cc86SMichal Swiatkowski return ret; 13190545cc86SMichal Swiatkowski } 13200545cc86SMichal Swiatkowski 13210545cc86SMichal Swiatkowski static int 13220545cc86SMichal Swiatkowski ice_devlink_enable_roce_validate(struct devlink *devlink, u32 id, 13230545cc86SMichal Swiatkowski union devlink_param_value val, 13240545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 13250545cc86SMichal Swiatkowski { 13260545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 13270545cc86SMichal Swiatkowski 13280545cc86SMichal Swiatkowski if (!test_bit(ICE_FLAG_RDMA_ENA, pf->flags)) 13290545cc86SMichal Swiatkowski return -EOPNOTSUPP; 13300545cc86SMichal Swiatkowski 13310545cc86SMichal Swiatkowski if (pf->rdma_mode & IIDC_RDMA_PROTOCOL_IWARP) { 13320545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "iWARP is currently enabled. This device cannot enable iWARP and RoCEv2 simultaneously"); 13330545cc86SMichal Swiatkowski return -EOPNOTSUPP; 13340545cc86SMichal Swiatkowski } 13350545cc86SMichal Swiatkowski 13360545cc86SMichal Swiatkowski return 0; 13370545cc86SMichal Swiatkowski } 13380545cc86SMichal Swiatkowski 13390545cc86SMichal Swiatkowski static int 13400545cc86SMichal Swiatkowski ice_devlink_enable_iw_get(struct devlink *devlink, u32 id, 13410545cc86SMichal Swiatkowski struct devlink_param_gset_ctx *ctx) 13420545cc86SMichal Swiatkowski { 13430545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 13440545cc86SMichal Swiatkowski 13450545cc86SMichal Swiatkowski ctx->val.vbool = pf->rdma_mode & IIDC_RDMA_PROTOCOL_IWARP; 13460545cc86SMichal Swiatkowski 13470545cc86SMichal Swiatkowski return 0; 13480545cc86SMichal Swiatkowski } 13490545cc86SMichal Swiatkowski 13505625ca56SMateusz Polchlopek static int ice_devlink_enable_iw_set(struct devlink *devlink, u32 id, 13515625ca56SMateusz Polchlopek struct devlink_param_gset_ctx *ctx, 13525625ca56SMateusz Polchlopek struct netlink_ext_ack *extack) 13530545cc86SMichal Swiatkowski { 13540545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 13550545cc86SMichal Swiatkowski bool iw_ena = ctx->val.vbool; 13560545cc86SMichal Swiatkowski int ret; 13570545cc86SMichal Swiatkowski 13580545cc86SMichal Swiatkowski if (!iw_ena) { 13590545cc86SMichal Swiatkowski ice_unplug_aux_dev(pf); 13600545cc86SMichal Swiatkowski pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_IWARP; 13610545cc86SMichal Swiatkowski return 0; 13620545cc86SMichal Swiatkowski } 13630545cc86SMichal Swiatkowski 13640545cc86SMichal Swiatkowski pf->rdma_mode |= IIDC_RDMA_PROTOCOL_IWARP; 13650545cc86SMichal Swiatkowski ret = ice_plug_aux_dev(pf); 13660545cc86SMichal Swiatkowski if (ret) 13670545cc86SMichal Swiatkowski pf->rdma_mode &= ~IIDC_RDMA_PROTOCOL_IWARP; 13680545cc86SMichal Swiatkowski 13690545cc86SMichal Swiatkowski return ret; 13700545cc86SMichal Swiatkowski } 13710545cc86SMichal Swiatkowski 13720545cc86SMichal Swiatkowski static int 13730545cc86SMichal Swiatkowski ice_devlink_enable_iw_validate(struct devlink *devlink, u32 id, 13740545cc86SMichal Swiatkowski union devlink_param_value val, 13750545cc86SMichal Swiatkowski struct netlink_ext_ack *extack) 13760545cc86SMichal Swiatkowski { 13770545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 13780545cc86SMichal Swiatkowski 13790545cc86SMichal Swiatkowski if (!test_bit(ICE_FLAG_RDMA_ENA, pf->flags)) 13800545cc86SMichal Swiatkowski return -EOPNOTSUPP; 13810545cc86SMichal Swiatkowski 13820545cc86SMichal Swiatkowski if (pf->rdma_mode & IIDC_RDMA_PROTOCOL_ROCEV2) { 13830545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "RoCEv2 is currently enabled. This device cannot enable iWARP and RoCEv2 simultaneously"); 13840545cc86SMichal Swiatkowski return -EOPNOTSUPP; 13850545cc86SMichal Swiatkowski } 13860545cc86SMichal Swiatkowski 13870545cc86SMichal Swiatkowski return 0; 13880545cc86SMichal Swiatkowski } 13890545cc86SMichal Swiatkowski 1390a59618b9SPawel Kaminski #define DEVLINK_LOCAL_FWD_DISABLED_STR "disabled" 1391a59618b9SPawel Kaminski #define DEVLINK_LOCAL_FWD_ENABLED_STR "enabled" 1392a59618b9SPawel Kaminski #define DEVLINK_LOCAL_FWD_PRIORITIZED_STR "prioritized" 1393a59618b9SPawel Kaminski 1394a59618b9SPawel Kaminski /** 1395a59618b9SPawel Kaminski * ice_devlink_local_fwd_mode_to_str - Get string for local_fwd mode. 1396a59618b9SPawel Kaminski * @mode: local forwarding for mode used in port_info struct. 1397a59618b9SPawel Kaminski * 1398a59618b9SPawel Kaminski * Return: Mode respective string or "Invalid". 1399a59618b9SPawel Kaminski */ 1400a59618b9SPawel Kaminski static const char * 1401a59618b9SPawel Kaminski ice_devlink_local_fwd_mode_to_str(enum ice_local_fwd_mode mode) 1402a59618b9SPawel Kaminski { 1403a59618b9SPawel Kaminski switch (mode) { 1404a59618b9SPawel Kaminski case ICE_LOCAL_FWD_MODE_ENABLED: 1405a59618b9SPawel Kaminski return DEVLINK_LOCAL_FWD_ENABLED_STR; 1406a59618b9SPawel Kaminski case ICE_LOCAL_FWD_MODE_PRIORITIZED: 1407a59618b9SPawel Kaminski return DEVLINK_LOCAL_FWD_PRIORITIZED_STR; 1408a59618b9SPawel Kaminski case ICE_LOCAL_FWD_MODE_DISABLED: 1409a59618b9SPawel Kaminski return DEVLINK_LOCAL_FWD_DISABLED_STR; 1410a59618b9SPawel Kaminski } 1411a59618b9SPawel Kaminski 1412a59618b9SPawel Kaminski return "Invalid"; 1413a59618b9SPawel Kaminski } 1414a59618b9SPawel Kaminski 1415a59618b9SPawel Kaminski /** 1416a59618b9SPawel Kaminski * ice_devlink_local_fwd_str_to_mode - Get local_fwd mode from string name. 1417a59618b9SPawel Kaminski * @mode_str: local forwarding mode string. 1418a59618b9SPawel Kaminski * 1419a59618b9SPawel Kaminski * Return: Mode value or negative number if invalid. 1420a59618b9SPawel Kaminski */ 1421a59618b9SPawel Kaminski static int ice_devlink_local_fwd_str_to_mode(const char *mode_str) 1422a59618b9SPawel Kaminski { 1423a59618b9SPawel Kaminski if (!strcmp(mode_str, DEVLINK_LOCAL_FWD_ENABLED_STR)) 1424a59618b9SPawel Kaminski return ICE_LOCAL_FWD_MODE_ENABLED; 1425a59618b9SPawel Kaminski else if (!strcmp(mode_str, DEVLINK_LOCAL_FWD_PRIORITIZED_STR)) 1426a59618b9SPawel Kaminski return ICE_LOCAL_FWD_MODE_PRIORITIZED; 1427a59618b9SPawel Kaminski else if (!strcmp(mode_str, DEVLINK_LOCAL_FWD_DISABLED_STR)) 1428a59618b9SPawel Kaminski return ICE_LOCAL_FWD_MODE_DISABLED; 1429a59618b9SPawel Kaminski 1430a59618b9SPawel Kaminski return -EINVAL; 1431a59618b9SPawel Kaminski } 1432a59618b9SPawel Kaminski 1433a59618b9SPawel Kaminski /** 1434a59618b9SPawel Kaminski * ice_devlink_local_fwd_get - Get local_fwd parameter. 1435a59618b9SPawel Kaminski * @devlink: Pointer to the devlink instance. 1436a59618b9SPawel Kaminski * @id: The parameter ID to set. 1437a59618b9SPawel Kaminski * @ctx: Context to store the parameter value. 1438a59618b9SPawel Kaminski * 1439a59618b9SPawel Kaminski * Return: Zero. 1440a59618b9SPawel Kaminski */ 1441a59618b9SPawel Kaminski static int ice_devlink_local_fwd_get(struct devlink *devlink, u32 id, 1442a59618b9SPawel Kaminski struct devlink_param_gset_ctx *ctx) 1443a59618b9SPawel Kaminski { 1444a59618b9SPawel Kaminski struct ice_pf *pf = devlink_priv(devlink); 1445a59618b9SPawel Kaminski struct ice_port_info *pi; 1446a59618b9SPawel Kaminski const char *mode_str; 1447a59618b9SPawel Kaminski 1448a59618b9SPawel Kaminski pi = pf->hw.port_info; 1449a59618b9SPawel Kaminski mode_str = ice_devlink_local_fwd_mode_to_str(pi->local_fwd_mode); 1450a59618b9SPawel Kaminski snprintf(ctx->val.vstr, sizeof(ctx->val.vstr), "%s", mode_str); 1451a59618b9SPawel Kaminski 1452a59618b9SPawel Kaminski return 0; 1453a59618b9SPawel Kaminski } 1454a59618b9SPawel Kaminski 1455a59618b9SPawel Kaminski /** 1456a59618b9SPawel Kaminski * ice_devlink_local_fwd_set - Set local_fwd parameter. 1457a59618b9SPawel Kaminski * @devlink: Pointer to the devlink instance. 1458a59618b9SPawel Kaminski * @id: The parameter ID to set. 1459a59618b9SPawel Kaminski * @ctx: Context to get the parameter value. 1460a59618b9SPawel Kaminski * @extack: Netlink extended ACK structure. 1461a59618b9SPawel Kaminski * 1462a59618b9SPawel Kaminski * Return: Zero. 1463a59618b9SPawel Kaminski */ 1464a59618b9SPawel Kaminski static int ice_devlink_local_fwd_set(struct devlink *devlink, u32 id, 1465a59618b9SPawel Kaminski struct devlink_param_gset_ctx *ctx, 1466a59618b9SPawel Kaminski struct netlink_ext_ack *extack) 1467a59618b9SPawel Kaminski { 1468a59618b9SPawel Kaminski int new_local_fwd_mode = ice_devlink_local_fwd_str_to_mode(ctx->val.vstr); 1469a59618b9SPawel Kaminski struct ice_pf *pf = devlink_priv(devlink); 1470a59618b9SPawel Kaminski struct device *dev = ice_pf_to_dev(pf); 1471a59618b9SPawel Kaminski struct ice_port_info *pi; 1472a59618b9SPawel Kaminski 1473a59618b9SPawel Kaminski pi = pf->hw.port_info; 1474a59618b9SPawel Kaminski if (pi->local_fwd_mode != new_local_fwd_mode) { 1475a59618b9SPawel Kaminski pi->local_fwd_mode = new_local_fwd_mode; 1476a59618b9SPawel Kaminski dev_info(dev, "Setting local_fwd to %s\n", ctx->val.vstr); 1477a59618b9SPawel Kaminski ice_schedule_reset(pf, ICE_RESET_CORER); 1478a59618b9SPawel Kaminski } 1479a59618b9SPawel Kaminski 1480a59618b9SPawel Kaminski return 0; 1481a59618b9SPawel Kaminski } 1482a59618b9SPawel Kaminski 1483a59618b9SPawel Kaminski /** 1484a59618b9SPawel Kaminski * ice_devlink_local_fwd_validate - Validate passed local_fwd parameter value. 1485a59618b9SPawel Kaminski * @devlink: Unused pointer to devlink instance. 1486a59618b9SPawel Kaminski * @id: The parameter ID to validate. 1487a59618b9SPawel Kaminski * @val: Value to validate. 1488a59618b9SPawel Kaminski * @extack: Netlink extended ACK structure. 1489a59618b9SPawel Kaminski * 1490a59618b9SPawel Kaminski * Supported values are: 1491a59618b9SPawel Kaminski * "enabled" - local_fwd is enabled, "disabled" - local_fwd is disabled 1492a59618b9SPawel Kaminski * "prioritized" - local_fwd traffic is prioritized in scheduling. 1493a59618b9SPawel Kaminski * 1494a59618b9SPawel Kaminski * Return: Zero when passed parameter value is supported. Negative value on 1495a59618b9SPawel Kaminski * error. 1496a59618b9SPawel Kaminski */ 1497a59618b9SPawel Kaminski static int ice_devlink_local_fwd_validate(struct devlink *devlink, u32 id, 1498a59618b9SPawel Kaminski union devlink_param_value val, 1499a59618b9SPawel Kaminski struct netlink_ext_ack *extack) 1500a59618b9SPawel Kaminski { 1501a59618b9SPawel Kaminski if (ice_devlink_local_fwd_str_to_mode(val.vstr) < 0) { 1502a59618b9SPawel Kaminski NL_SET_ERR_MSG_MOD(extack, "Error: Requested value is not supported."); 1503a59618b9SPawel Kaminski return -EINVAL; 1504a59618b9SPawel Kaminski } 1505a59618b9SPawel Kaminski 1506a59618b9SPawel Kaminski return 0; 1507a59618b9SPawel Kaminski } 1508a59618b9SPawel Kaminski 1509109eb291SLukasz Czapnik enum ice_param_id { 1510109eb291SLukasz Czapnik ICE_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX, 1511109eb291SLukasz Czapnik ICE_DEVLINK_PARAM_ID_TX_SCHED_LAYERS, 1512a59618b9SPawel Kaminski ICE_DEVLINK_PARAM_ID_LOCAL_FWD, 1513109eb291SLukasz Czapnik }; 1514109eb291SLukasz Czapnik 1515a51c9b1cSDave Ertman static const struct devlink_param ice_dvl_rdma_params[] = { 15160545cc86SMichal Swiatkowski DEVLINK_PARAM_GENERIC(ENABLE_ROCE, BIT(DEVLINK_PARAM_CMODE_RUNTIME), 15170545cc86SMichal Swiatkowski ice_devlink_enable_roce_get, 15180545cc86SMichal Swiatkowski ice_devlink_enable_roce_set, 15190545cc86SMichal Swiatkowski ice_devlink_enable_roce_validate), 15200545cc86SMichal Swiatkowski DEVLINK_PARAM_GENERIC(ENABLE_IWARP, BIT(DEVLINK_PARAM_CMODE_RUNTIME), 15210545cc86SMichal Swiatkowski ice_devlink_enable_iw_get, 15220545cc86SMichal Swiatkowski ice_devlink_enable_iw_set, 15230545cc86SMichal Swiatkowski ice_devlink_enable_iw_validate), 1524a51c9b1cSDave Ertman }; 1525a51c9b1cSDave Ertman 1526a51c9b1cSDave Ertman static const struct devlink_param ice_dvl_sched_params[] = { 1527109eb291SLukasz Czapnik DEVLINK_PARAM_DRIVER(ICE_DEVLINK_PARAM_ID_TX_SCHED_LAYERS, 1528109eb291SLukasz Czapnik "tx_scheduling_layers", 1529109eb291SLukasz Czapnik DEVLINK_PARAM_TYPE_U8, 1530109eb291SLukasz Czapnik BIT(DEVLINK_PARAM_CMODE_PERMANENT), 1531109eb291SLukasz Czapnik ice_devlink_tx_sched_layers_get, 1532109eb291SLukasz Czapnik ice_devlink_tx_sched_layers_set, 1533109eb291SLukasz Czapnik ice_devlink_tx_sched_layers_validate), 1534a59618b9SPawel Kaminski DEVLINK_PARAM_DRIVER(ICE_DEVLINK_PARAM_ID_LOCAL_FWD, 1535a59618b9SPawel Kaminski "local_forwarding", DEVLINK_PARAM_TYPE_STRING, 1536a59618b9SPawel Kaminski BIT(DEVLINK_PARAM_CMODE_RUNTIME), 1537a59618b9SPawel Kaminski ice_devlink_local_fwd_get, 1538a59618b9SPawel Kaminski ice_devlink_local_fwd_set, 1539a59618b9SPawel Kaminski ice_devlink_local_fwd_validate), 15400545cc86SMichal Swiatkowski }; 15410545cc86SMichal Swiatkowski 15420545cc86SMichal Swiatkowski static void ice_devlink_free(void *devlink_ptr) 15430545cc86SMichal Swiatkowski { 15440545cc86SMichal Swiatkowski devlink_free((struct devlink *)devlink_ptr); 15450545cc86SMichal Swiatkowski } 15460545cc86SMichal Swiatkowski 15470545cc86SMichal Swiatkowski /** 15480545cc86SMichal Swiatkowski * ice_allocate_pf - Allocate devlink and return PF structure pointer 15490545cc86SMichal Swiatkowski * @dev: the device to allocate for 15500545cc86SMichal Swiatkowski * 15510545cc86SMichal Swiatkowski * Allocate a devlink instance for this device and return the private area as 15520545cc86SMichal Swiatkowski * the PF structure. The devlink memory is kept track of through devres by 15530545cc86SMichal Swiatkowski * adding an action to remove it when unwinding. 15540545cc86SMichal Swiatkowski */ 15550545cc86SMichal Swiatkowski struct ice_pf *ice_allocate_pf(struct device *dev) 15560545cc86SMichal Swiatkowski { 15570545cc86SMichal Swiatkowski struct devlink *devlink; 15580545cc86SMichal Swiatkowski 15590545cc86SMichal Swiatkowski devlink = devlink_alloc(&ice_devlink_ops, sizeof(struct ice_pf), dev); 15600545cc86SMichal Swiatkowski if (!devlink) 15610545cc86SMichal Swiatkowski return NULL; 15620545cc86SMichal Swiatkowski 15630545cc86SMichal Swiatkowski /* Add an action to teardown the devlink when unwinding the driver */ 15640545cc86SMichal Swiatkowski if (devm_add_action_or_reset(dev, ice_devlink_free, devlink)) 15650545cc86SMichal Swiatkowski return NULL; 15660545cc86SMichal Swiatkowski 15670545cc86SMichal Swiatkowski return devlink_priv(devlink); 15680545cc86SMichal Swiatkowski } 15690545cc86SMichal Swiatkowski 15700545cc86SMichal Swiatkowski /** 1571*f43e3be6SPiotr Raczynski * ice_allocate_sf - Allocate devlink and return SF structure pointer 1572*f43e3be6SPiotr Raczynski * @dev: the device to allocate for 1573*f43e3be6SPiotr Raczynski * @pf: pointer to the PF structure 1574*f43e3be6SPiotr Raczynski * 1575*f43e3be6SPiotr Raczynski * Allocate a devlink instance for SF. 1576*f43e3be6SPiotr Raczynski * 1577*f43e3be6SPiotr Raczynski * Return: ice_sf_priv pointer to allocated memory or ERR_PTR in case of error 1578*f43e3be6SPiotr Raczynski */ 1579*f43e3be6SPiotr Raczynski struct ice_sf_priv *ice_allocate_sf(struct device *dev, struct ice_pf *pf) 1580*f43e3be6SPiotr Raczynski { 1581*f43e3be6SPiotr Raczynski struct devlink *devlink; 1582*f43e3be6SPiotr Raczynski int err; 1583*f43e3be6SPiotr Raczynski 1584*f43e3be6SPiotr Raczynski devlink = devlink_alloc(&ice_sf_devlink_ops, sizeof(struct ice_sf_priv), 1585*f43e3be6SPiotr Raczynski dev); 1586*f43e3be6SPiotr Raczynski if (!devlink) 1587*f43e3be6SPiotr Raczynski return ERR_PTR(-ENOMEM); 1588*f43e3be6SPiotr Raczynski 1589*f43e3be6SPiotr Raczynski err = devl_nested_devlink_set(priv_to_devlink(pf), devlink); 1590*f43e3be6SPiotr Raczynski if (err) { 1591*f43e3be6SPiotr Raczynski devlink_free(devlink); 1592*f43e3be6SPiotr Raczynski return ERR_PTR(err); 1593*f43e3be6SPiotr Raczynski } 1594*f43e3be6SPiotr Raczynski 1595*f43e3be6SPiotr Raczynski return devlink_priv(devlink); 1596*f43e3be6SPiotr Raczynski } 1597*f43e3be6SPiotr Raczynski 1598*f43e3be6SPiotr Raczynski /** 15990545cc86SMichal Swiatkowski * ice_devlink_register - Register devlink interface for this PF 16000545cc86SMichal Swiatkowski * @pf: the PF to register the devlink for. 16010545cc86SMichal Swiatkowski * 16020545cc86SMichal Swiatkowski * Register the devlink instance associated with this physical function. 16030545cc86SMichal Swiatkowski * 16040545cc86SMichal Swiatkowski * Return: zero on success or an error code on failure. 16050545cc86SMichal Swiatkowski */ 16060545cc86SMichal Swiatkowski void ice_devlink_register(struct ice_pf *pf) 16070545cc86SMichal Swiatkowski { 16080545cc86SMichal Swiatkowski struct devlink *devlink = priv_to_devlink(pf); 16090545cc86SMichal Swiatkowski 1610118c6bdeSMichal Swiatkowski devl_register(devlink); 16110545cc86SMichal Swiatkowski } 16120545cc86SMichal Swiatkowski 16130545cc86SMichal Swiatkowski /** 16140545cc86SMichal Swiatkowski * ice_devlink_unregister - Unregister devlink resources for this PF. 16150545cc86SMichal Swiatkowski * @pf: the PF structure to cleanup 16160545cc86SMichal Swiatkowski * 16170545cc86SMichal Swiatkowski * Releases resources used by devlink and cleans up associated memory. 16180545cc86SMichal Swiatkowski */ 16190545cc86SMichal Swiatkowski void ice_devlink_unregister(struct ice_pf *pf) 16200545cc86SMichal Swiatkowski { 1621118c6bdeSMichal Swiatkowski devl_unregister(priv_to_devlink(pf)); 16220545cc86SMichal Swiatkowski } 16230545cc86SMichal Swiatkowski 16240545cc86SMichal Swiatkowski int ice_devlink_register_params(struct ice_pf *pf) 16250545cc86SMichal Swiatkowski { 16260545cc86SMichal Swiatkowski struct devlink *devlink = priv_to_devlink(pf); 1627109eb291SLukasz Czapnik struct ice_hw *hw = &pf->hw; 1628a51c9b1cSDave Ertman int status; 1629109eb291SLukasz Czapnik 1630a51c9b1cSDave Ertman status = devl_params_register(devlink, ice_dvl_rdma_params, 1631a51c9b1cSDave Ertman ARRAY_SIZE(ice_dvl_rdma_params)); 1632a51c9b1cSDave Ertman if (status) 1633a51c9b1cSDave Ertman return status; 1634109eb291SLukasz Czapnik 1635a51c9b1cSDave Ertman if (hw->func_caps.common_cap.tx_sched_topo_comp_mode_en) 1636a51c9b1cSDave Ertman status = devl_params_register(devlink, ice_dvl_sched_params, 1637a51c9b1cSDave Ertman ARRAY_SIZE(ice_dvl_sched_params)); 16380545cc86SMichal Swiatkowski 1639a51c9b1cSDave Ertman return status; 16400545cc86SMichal Swiatkowski } 16410545cc86SMichal Swiatkowski 16420545cc86SMichal Swiatkowski void ice_devlink_unregister_params(struct ice_pf *pf) 16430545cc86SMichal Swiatkowski { 1644a51c9b1cSDave Ertman struct devlink *devlink = priv_to_devlink(pf); 1645a51c9b1cSDave Ertman struct ice_hw *hw = &pf->hw; 1646a51c9b1cSDave Ertman 1647a51c9b1cSDave Ertman devl_params_unregister(devlink, ice_dvl_rdma_params, 1648a51c9b1cSDave Ertman ARRAY_SIZE(ice_dvl_rdma_params)); 1649a51c9b1cSDave Ertman 1650a51c9b1cSDave Ertman if (hw->func_caps.common_cap.tx_sched_topo_comp_mode_en) 1651a51c9b1cSDave Ertman devl_params_unregister(devlink, ice_dvl_sched_params, 1652a51c9b1cSDave Ertman ARRAY_SIZE(ice_dvl_sched_params)); 16530545cc86SMichal Swiatkowski } 16540545cc86SMichal Swiatkowski 16550545cc86SMichal Swiatkowski #define ICE_DEVLINK_READ_BLK_SIZE (1024 * 1024) 16560545cc86SMichal Swiatkowski 16570545cc86SMichal Swiatkowski static const struct devlink_region_ops ice_nvm_region_ops; 16580545cc86SMichal Swiatkowski static const struct devlink_region_ops ice_sram_region_ops; 16590545cc86SMichal Swiatkowski 16600545cc86SMichal Swiatkowski /** 16610545cc86SMichal Swiatkowski * ice_devlink_nvm_snapshot - Capture a snapshot of the NVM flash contents 16620545cc86SMichal Swiatkowski * @devlink: the devlink instance 16630545cc86SMichal Swiatkowski * @ops: the devlink region to snapshot 16640545cc86SMichal Swiatkowski * @extack: extended ACK response structure 16650545cc86SMichal Swiatkowski * @data: on exit points to snapshot data buffer 16660545cc86SMichal Swiatkowski * 16670545cc86SMichal Swiatkowski * This function is called in response to a DEVLINK_CMD_REGION_NEW for either 16680545cc86SMichal Swiatkowski * the nvm-flash or shadow-ram region. 16690545cc86SMichal Swiatkowski * 16700545cc86SMichal Swiatkowski * It captures a snapshot of the NVM or Shadow RAM flash contents. This 16710545cc86SMichal Swiatkowski * snapshot can then later be viewed via the DEVLINK_CMD_REGION_READ netlink 16720545cc86SMichal Swiatkowski * interface. 16730545cc86SMichal Swiatkowski * 16740545cc86SMichal Swiatkowski * @returns zero on success, and updates the data pointer. Returns a non-zero 16750545cc86SMichal Swiatkowski * error code on failure. 16760545cc86SMichal Swiatkowski */ 16770545cc86SMichal Swiatkowski static int ice_devlink_nvm_snapshot(struct devlink *devlink, 16780545cc86SMichal Swiatkowski const struct devlink_region_ops *ops, 16790545cc86SMichal Swiatkowski struct netlink_ext_ack *extack, u8 **data) 16800545cc86SMichal Swiatkowski { 16810545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 16820545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 16830545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 16840545cc86SMichal Swiatkowski bool read_shadow_ram; 16850545cc86SMichal Swiatkowski u8 *nvm_data, *tmp, i; 16860545cc86SMichal Swiatkowski u32 nvm_size, left; 16870545cc86SMichal Swiatkowski s8 num_blks; 16880545cc86SMichal Swiatkowski int status; 16890545cc86SMichal Swiatkowski 16900545cc86SMichal Swiatkowski if (ops == &ice_nvm_region_ops) { 16910545cc86SMichal Swiatkowski read_shadow_ram = false; 16920545cc86SMichal Swiatkowski nvm_size = hw->flash.flash_size; 16930545cc86SMichal Swiatkowski } else if (ops == &ice_sram_region_ops) { 16940545cc86SMichal Swiatkowski read_shadow_ram = true; 16950545cc86SMichal Swiatkowski nvm_size = hw->flash.sr_words * 2u; 16960545cc86SMichal Swiatkowski } else { 16970545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unexpected region in snapshot function"); 16980545cc86SMichal Swiatkowski return -EOPNOTSUPP; 16990545cc86SMichal Swiatkowski } 17000545cc86SMichal Swiatkowski 17010545cc86SMichal Swiatkowski nvm_data = vzalloc(nvm_size); 17020545cc86SMichal Swiatkowski if (!nvm_data) 17030545cc86SMichal Swiatkowski return -ENOMEM; 17040545cc86SMichal Swiatkowski 17050545cc86SMichal Swiatkowski num_blks = DIV_ROUND_UP(nvm_size, ICE_DEVLINK_READ_BLK_SIZE); 17060545cc86SMichal Swiatkowski tmp = nvm_data; 17070545cc86SMichal Swiatkowski left = nvm_size; 17080545cc86SMichal Swiatkowski 17090545cc86SMichal Swiatkowski /* Some systems take longer to read the NVM than others which causes the 17100545cc86SMichal Swiatkowski * FW to reclaim the NVM lock before the entire NVM has been read. Fix 17110545cc86SMichal Swiatkowski * this by breaking the reads of the NVM into smaller chunks that will 17120545cc86SMichal Swiatkowski * probably not take as long. This has some overhead since we are 17130545cc86SMichal Swiatkowski * increasing the number of AQ commands, but it should always work 17140545cc86SMichal Swiatkowski */ 17150545cc86SMichal Swiatkowski for (i = 0; i < num_blks; i++) { 17160545cc86SMichal Swiatkowski u32 read_sz = min_t(u32, ICE_DEVLINK_READ_BLK_SIZE, left); 17170545cc86SMichal Swiatkowski 17180545cc86SMichal Swiatkowski status = ice_acquire_nvm(hw, ICE_RES_READ); 17190545cc86SMichal Swiatkowski if (status) { 17200545cc86SMichal Swiatkowski dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n", 17210545cc86SMichal Swiatkowski status, hw->adminq.sq_last_status); 17220545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore"); 17230545cc86SMichal Swiatkowski vfree(nvm_data); 17240545cc86SMichal Swiatkowski return -EIO; 17250545cc86SMichal Swiatkowski } 17260545cc86SMichal Swiatkowski 17270545cc86SMichal Swiatkowski status = ice_read_flat_nvm(hw, i * ICE_DEVLINK_READ_BLK_SIZE, 17280545cc86SMichal Swiatkowski &read_sz, tmp, read_shadow_ram); 17290545cc86SMichal Swiatkowski if (status) { 17300545cc86SMichal Swiatkowski dev_dbg(dev, "ice_read_flat_nvm failed after reading %u bytes, err %d aq_err %d\n", 17310545cc86SMichal Swiatkowski read_sz, status, hw->adminq.sq_last_status); 17320545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Failed to read NVM contents"); 17330545cc86SMichal Swiatkowski ice_release_nvm(hw); 17340545cc86SMichal Swiatkowski vfree(nvm_data); 17350545cc86SMichal Swiatkowski return -EIO; 17360545cc86SMichal Swiatkowski } 17370545cc86SMichal Swiatkowski ice_release_nvm(hw); 17380545cc86SMichal Swiatkowski 17390545cc86SMichal Swiatkowski tmp += read_sz; 17400545cc86SMichal Swiatkowski left -= read_sz; 17410545cc86SMichal Swiatkowski } 17420545cc86SMichal Swiatkowski 17430545cc86SMichal Swiatkowski *data = nvm_data; 17440545cc86SMichal Swiatkowski 17450545cc86SMichal Swiatkowski return 0; 17460545cc86SMichal Swiatkowski } 17470545cc86SMichal Swiatkowski 17480545cc86SMichal Swiatkowski /** 17490545cc86SMichal Swiatkowski * ice_devlink_nvm_read - Read a portion of NVM flash contents 17500545cc86SMichal Swiatkowski * @devlink: the devlink instance 17510545cc86SMichal Swiatkowski * @ops: the devlink region to snapshot 17520545cc86SMichal Swiatkowski * @extack: extended ACK response structure 17530545cc86SMichal Swiatkowski * @offset: the offset to start at 17540545cc86SMichal Swiatkowski * @size: the amount to read 17550545cc86SMichal Swiatkowski * @data: the data buffer to read into 17560545cc86SMichal Swiatkowski * 17570545cc86SMichal Swiatkowski * This function is called in response to DEVLINK_CMD_REGION_READ to directly 17580545cc86SMichal Swiatkowski * read a section of the NVM contents. 17590545cc86SMichal Swiatkowski * 17600545cc86SMichal Swiatkowski * It reads from either the nvm-flash or shadow-ram region contents. 17610545cc86SMichal Swiatkowski * 17620545cc86SMichal Swiatkowski * @returns zero on success, and updates the data pointer. Returns a non-zero 17630545cc86SMichal Swiatkowski * error code on failure. 17640545cc86SMichal Swiatkowski */ 17650545cc86SMichal Swiatkowski static int ice_devlink_nvm_read(struct devlink *devlink, 17660545cc86SMichal Swiatkowski const struct devlink_region_ops *ops, 17670545cc86SMichal Swiatkowski struct netlink_ext_ack *extack, 17680545cc86SMichal Swiatkowski u64 offset, u32 size, u8 *data) 17690545cc86SMichal Swiatkowski { 17700545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 17710545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 17720545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 17730545cc86SMichal Swiatkowski bool read_shadow_ram; 17740545cc86SMichal Swiatkowski u64 nvm_size; 17750545cc86SMichal Swiatkowski int status; 17760545cc86SMichal Swiatkowski 17770545cc86SMichal Swiatkowski if (ops == &ice_nvm_region_ops) { 17780545cc86SMichal Swiatkowski read_shadow_ram = false; 17790545cc86SMichal Swiatkowski nvm_size = hw->flash.flash_size; 17800545cc86SMichal Swiatkowski } else if (ops == &ice_sram_region_ops) { 17810545cc86SMichal Swiatkowski read_shadow_ram = true; 17820545cc86SMichal Swiatkowski nvm_size = hw->flash.sr_words * 2u; 17830545cc86SMichal Swiatkowski } else { 17840545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Unexpected region in snapshot function"); 17850545cc86SMichal Swiatkowski return -EOPNOTSUPP; 17860545cc86SMichal Swiatkowski } 17870545cc86SMichal Swiatkowski 17880545cc86SMichal Swiatkowski if (offset + size >= nvm_size) { 17890545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Cannot read beyond the region size"); 17900545cc86SMichal Swiatkowski return -ERANGE; 17910545cc86SMichal Swiatkowski } 17920545cc86SMichal Swiatkowski 17930545cc86SMichal Swiatkowski status = ice_acquire_nvm(hw, ICE_RES_READ); 17940545cc86SMichal Swiatkowski if (status) { 17950545cc86SMichal Swiatkowski dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n", 17960545cc86SMichal Swiatkowski status, hw->adminq.sq_last_status); 17970545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore"); 17980545cc86SMichal Swiatkowski return -EIO; 17990545cc86SMichal Swiatkowski } 18000545cc86SMichal Swiatkowski 18010545cc86SMichal Swiatkowski status = ice_read_flat_nvm(hw, (u32)offset, &size, data, 18020545cc86SMichal Swiatkowski read_shadow_ram); 18030545cc86SMichal Swiatkowski if (status) { 18040545cc86SMichal Swiatkowski dev_dbg(dev, "ice_read_flat_nvm failed after reading %u bytes, err %d aq_err %d\n", 18050545cc86SMichal Swiatkowski size, status, hw->adminq.sq_last_status); 18060545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Failed to read NVM contents"); 18070545cc86SMichal Swiatkowski ice_release_nvm(hw); 18080545cc86SMichal Swiatkowski return -EIO; 18090545cc86SMichal Swiatkowski } 18100545cc86SMichal Swiatkowski ice_release_nvm(hw); 18110545cc86SMichal Swiatkowski 18120545cc86SMichal Swiatkowski return 0; 18130545cc86SMichal Swiatkowski } 18140545cc86SMichal Swiatkowski 18150545cc86SMichal Swiatkowski /** 18160545cc86SMichal Swiatkowski * ice_devlink_devcaps_snapshot - Capture snapshot of device capabilities 18170545cc86SMichal Swiatkowski * @devlink: the devlink instance 18180545cc86SMichal Swiatkowski * @ops: the devlink region being snapshotted 18190545cc86SMichal Swiatkowski * @extack: extended ACK response structure 18200545cc86SMichal Swiatkowski * @data: on exit points to snapshot data buffer 18210545cc86SMichal Swiatkowski * 18220545cc86SMichal Swiatkowski * This function is called in response to the DEVLINK_CMD_REGION_TRIGGER for 18230545cc86SMichal Swiatkowski * the device-caps devlink region. It captures a snapshot of the device 18240545cc86SMichal Swiatkowski * capabilities reported by firmware. 18250545cc86SMichal Swiatkowski * 18260545cc86SMichal Swiatkowski * @returns zero on success, and updates the data pointer. Returns a non-zero 18270545cc86SMichal Swiatkowski * error code on failure. 18280545cc86SMichal Swiatkowski */ 18290545cc86SMichal Swiatkowski static int 18300545cc86SMichal Swiatkowski ice_devlink_devcaps_snapshot(struct devlink *devlink, 18310545cc86SMichal Swiatkowski const struct devlink_region_ops *ops, 18320545cc86SMichal Swiatkowski struct netlink_ext_ack *extack, u8 **data) 18330545cc86SMichal Swiatkowski { 18340545cc86SMichal Swiatkowski struct ice_pf *pf = devlink_priv(devlink); 18350545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 18360545cc86SMichal Swiatkowski struct ice_hw *hw = &pf->hw; 18370545cc86SMichal Swiatkowski void *devcaps; 18380545cc86SMichal Swiatkowski int status; 18390545cc86SMichal Swiatkowski 18400545cc86SMichal Swiatkowski devcaps = vzalloc(ICE_AQ_MAX_BUF_LEN); 18410545cc86SMichal Swiatkowski if (!devcaps) 18420545cc86SMichal Swiatkowski return -ENOMEM; 18430545cc86SMichal Swiatkowski 18440545cc86SMichal Swiatkowski status = ice_aq_list_caps(hw, devcaps, ICE_AQ_MAX_BUF_LEN, NULL, 18450545cc86SMichal Swiatkowski ice_aqc_opc_list_dev_caps, NULL); 18460545cc86SMichal Swiatkowski if (status) { 18470545cc86SMichal Swiatkowski dev_dbg(dev, "ice_aq_list_caps: failed to read device capabilities, err %d aq_err %d\n", 18480545cc86SMichal Swiatkowski status, hw->adminq.sq_last_status); 18490545cc86SMichal Swiatkowski NL_SET_ERR_MSG_MOD(extack, "Failed to read device capabilities"); 18500545cc86SMichal Swiatkowski vfree(devcaps); 18510545cc86SMichal Swiatkowski return status; 18520545cc86SMichal Swiatkowski } 18530545cc86SMichal Swiatkowski 18540545cc86SMichal Swiatkowski *data = (u8 *)devcaps; 18550545cc86SMichal Swiatkowski 18560545cc86SMichal Swiatkowski return 0; 18570545cc86SMichal Swiatkowski } 18580545cc86SMichal Swiatkowski 18590545cc86SMichal Swiatkowski static const struct devlink_region_ops ice_nvm_region_ops = { 18600545cc86SMichal Swiatkowski .name = "nvm-flash", 18610545cc86SMichal Swiatkowski .destructor = vfree, 18620545cc86SMichal Swiatkowski .snapshot = ice_devlink_nvm_snapshot, 18630545cc86SMichal Swiatkowski .read = ice_devlink_nvm_read, 18640545cc86SMichal Swiatkowski }; 18650545cc86SMichal Swiatkowski 18660545cc86SMichal Swiatkowski static const struct devlink_region_ops ice_sram_region_ops = { 18670545cc86SMichal Swiatkowski .name = "shadow-ram", 18680545cc86SMichal Swiatkowski .destructor = vfree, 18690545cc86SMichal Swiatkowski .snapshot = ice_devlink_nvm_snapshot, 18700545cc86SMichal Swiatkowski .read = ice_devlink_nvm_read, 18710545cc86SMichal Swiatkowski }; 18720545cc86SMichal Swiatkowski 18730545cc86SMichal Swiatkowski static const struct devlink_region_ops ice_devcaps_region_ops = { 18740545cc86SMichal Swiatkowski .name = "device-caps", 18750545cc86SMichal Swiatkowski .destructor = vfree, 18760545cc86SMichal Swiatkowski .snapshot = ice_devlink_devcaps_snapshot, 18770545cc86SMichal Swiatkowski }; 18780545cc86SMichal Swiatkowski 18790545cc86SMichal Swiatkowski /** 18800545cc86SMichal Swiatkowski * ice_devlink_init_regions - Initialize devlink regions 18810545cc86SMichal Swiatkowski * @pf: the PF device structure 18820545cc86SMichal Swiatkowski * 18830545cc86SMichal Swiatkowski * Create devlink regions used to enable access to dump the contents of the 18840545cc86SMichal Swiatkowski * flash memory on the device. 18850545cc86SMichal Swiatkowski */ 18860545cc86SMichal Swiatkowski void ice_devlink_init_regions(struct ice_pf *pf) 18870545cc86SMichal Swiatkowski { 18880545cc86SMichal Swiatkowski struct devlink *devlink = priv_to_devlink(pf); 18890545cc86SMichal Swiatkowski struct device *dev = ice_pf_to_dev(pf); 18900545cc86SMichal Swiatkowski u64 nvm_size, sram_size; 18910545cc86SMichal Swiatkowski 18920545cc86SMichal Swiatkowski nvm_size = pf->hw.flash.flash_size; 1893118c6bdeSMichal Swiatkowski pf->nvm_region = devl_region_create(devlink, &ice_nvm_region_ops, 1, 18940545cc86SMichal Swiatkowski nvm_size); 18950545cc86SMichal Swiatkowski if (IS_ERR(pf->nvm_region)) { 18960545cc86SMichal Swiatkowski dev_err(dev, "failed to create NVM devlink region, err %ld\n", 18970545cc86SMichal Swiatkowski PTR_ERR(pf->nvm_region)); 18980545cc86SMichal Swiatkowski pf->nvm_region = NULL; 18990545cc86SMichal Swiatkowski } 19000545cc86SMichal Swiatkowski 19010545cc86SMichal Swiatkowski sram_size = pf->hw.flash.sr_words * 2u; 1902118c6bdeSMichal Swiatkowski pf->sram_region = devl_region_create(devlink, &ice_sram_region_ops, 19030545cc86SMichal Swiatkowski 1, sram_size); 19040545cc86SMichal Swiatkowski if (IS_ERR(pf->sram_region)) { 19050545cc86SMichal Swiatkowski dev_err(dev, "failed to create shadow-ram devlink region, err %ld\n", 19060545cc86SMichal Swiatkowski PTR_ERR(pf->sram_region)); 19070545cc86SMichal Swiatkowski pf->sram_region = NULL; 19080545cc86SMichal Swiatkowski } 19090545cc86SMichal Swiatkowski 1910118c6bdeSMichal Swiatkowski pf->devcaps_region = devl_region_create(devlink, 19110545cc86SMichal Swiatkowski &ice_devcaps_region_ops, 10, 19120545cc86SMichal Swiatkowski ICE_AQ_MAX_BUF_LEN); 19130545cc86SMichal Swiatkowski if (IS_ERR(pf->devcaps_region)) { 19140545cc86SMichal Swiatkowski dev_err(dev, "failed to create device-caps devlink region, err %ld\n", 19150545cc86SMichal Swiatkowski PTR_ERR(pf->devcaps_region)); 19160545cc86SMichal Swiatkowski pf->devcaps_region = NULL; 19170545cc86SMichal Swiatkowski } 19180545cc86SMichal Swiatkowski } 19190545cc86SMichal Swiatkowski 19200545cc86SMichal Swiatkowski /** 19210545cc86SMichal Swiatkowski * ice_devlink_destroy_regions - Destroy devlink regions 19220545cc86SMichal Swiatkowski * @pf: the PF device structure 19230545cc86SMichal Swiatkowski * 19240545cc86SMichal Swiatkowski * Remove previously created regions for this PF. 19250545cc86SMichal Swiatkowski */ 19260545cc86SMichal Swiatkowski void ice_devlink_destroy_regions(struct ice_pf *pf) 19270545cc86SMichal Swiatkowski { 19280545cc86SMichal Swiatkowski if (pf->nvm_region) 1929118c6bdeSMichal Swiatkowski devl_region_destroy(pf->nvm_region); 19300545cc86SMichal Swiatkowski 19310545cc86SMichal Swiatkowski if (pf->sram_region) 1932118c6bdeSMichal Swiatkowski devl_region_destroy(pf->sram_region); 19330545cc86SMichal Swiatkowski 19340545cc86SMichal Swiatkowski if (pf->devcaps_region) 1935118c6bdeSMichal Swiatkowski devl_region_destroy(pf->devcaps_region); 19360545cc86SMichal Swiatkowski } 1937