1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright(c) 2023 Intel Corporation. */ 3 4 #include <net/devlink.h> 5 #include "i40e.h" 6 #include "i40e_devlink.h" 7 8 static int i40e_max_mac_per_vf_set(struct devlink *devlink, 9 u32 id, 10 struct devlink_param_gset_ctx *ctx, 11 struct netlink_ext_ack *extack) 12 { 13 struct i40e_pf *pf = devlink_priv(devlink); 14 15 if (pf->num_alloc_vfs > 0) { 16 NL_SET_ERR_MSG_MOD(extack, 17 "Cannot change max_mac_per_vf while SR-IOV is enabled"); 18 return -EBUSY; 19 } 20 21 pf->max_mac_per_vf = ctx->val.vu32; 22 return 0; 23 } 24 25 static int i40e_max_mac_per_vf_get(struct devlink *devlink, 26 u32 id, 27 struct devlink_param_gset_ctx *ctx, 28 struct netlink_ext_ack *extack) 29 { 30 struct i40e_pf *pf = devlink_priv(devlink); 31 32 ctx->val.vu32 = pf->max_mac_per_vf; 33 return 0; 34 } 35 36 static const struct devlink_param i40e_dl_params[] = { 37 DEVLINK_PARAM_GENERIC(MAX_MAC_PER_VF, 38 BIT(DEVLINK_PARAM_CMODE_RUNTIME), 39 i40e_max_mac_per_vf_get, 40 i40e_max_mac_per_vf_set, 41 NULL), 42 }; 43 44 static void i40e_info_get_dsn(struct i40e_pf *pf, char *buf, size_t len) 45 { 46 u8 dsn[8]; 47 48 put_unaligned_be64(pci_get_dsn(pf->pdev), dsn); 49 50 snprintf(buf, len, "%8phD", dsn); 51 } 52 53 static void i40e_info_fw_mgmt(struct i40e_hw *hw, char *buf, size_t len) 54 { 55 struct i40e_adminq_info *aq = &hw->aq; 56 57 snprintf(buf, len, "%u.%u", aq->fw_maj_ver, aq->fw_min_ver); 58 } 59 60 static void i40e_info_fw_mgmt_build(struct i40e_hw *hw, char *buf, size_t len) 61 { 62 struct i40e_adminq_info *aq = &hw->aq; 63 64 snprintf(buf, len, "%05d", aq->fw_build); 65 } 66 67 static void i40e_info_fw_api(struct i40e_hw *hw, char *buf, size_t len) 68 { 69 struct i40e_adminq_info *aq = &hw->aq; 70 71 snprintf(buf, len, "%u.%u", aq->api_maj_ver, aq->api_min_ver); 72 } 73 74 static void i40e_info_pba(struct i40e_hw *hw, char *buf, size_t len) 75 { 76 buf[0] = '\0'; 77 if (hw->pba_id) 78 strscpy(buf, hw->pba_id, len); 79 } 80 81 enum i40e_devlink_version_type { 82 I40E_DL_VERSION_FIXED, 83 I40E_DL_VERSION_RUNNING, 84 }; 85 86 static int i40e_devlink_info_put(struct devlink_info_req *req, 87 enum i40e_devlink_version_type type, 88 const char *key, const char *value) 89 { 90 if (!strlen(value)) 91 return 0; 92 93 switch (type) { 94 case I40E_DL_VERSION_FIXED: 95 return devlink_info_version_fixed_put(req, key, value); 96 case I40E_DL_VERSION_RUNNING: 97 return devlink_info_version_running_put(req, key, value); 98 } 99 return 0; 100 } 101 102 static int i40e_devlink_info_get(struct devlink *dl, 103 struct devlink_info_req *req, 104 struct netlink_ext_ack *extack) 105 { 106 struct i40e_pf *pf = devlink_priv(dl); 107 struct i40e_hw *hw = &pf->hw; 108 char buf[32]; 109 int err; 110 111 i40e_info_get_dsn(pf, buf, sizeof(buf)); 112 err = devlink_info_serial_number_put(req, buf); 113 if (err) 114 return err; 115 116 i40e_info_fw_mgmt(hw, buf, sizeof(buf)); 117 err = i40e_devlink_info_put(req, I40E_DL_VERSION_RUNNING, 118 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, buf); 119 if (err) 120 return err; 121 122 i40e_info_fw_mgmt_build(hw, buf, sizeof(buf)); 123 err = i40e_devlink_info_put(req, I40E_DL_VERSION_RUNNING, 124 "fw.mgmt.build", buf); 125 if (err) 126 return err; 127 128 i40e_info_fw_api(hw, buf, sizeof(buf)); 129 err = i40e_devlink_info_put(req, I40E_DL_VERSION_RUNNING, 130 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT_API, 131 buf); 132 if (err) 133 return err; 134 135 i40e_info_nvm_ver(hw, buf, sizeof(buf)); 136 err = i40e_devlink_info_put(req, I40E_DL_VERSION_RUNNING, 137 "fw.psid.api", buf); 138 if (err) 139 return err; 140 141 i40e_info_eetrack(hw, buf, sizeof(buf)); 142 err = i40e_devlink_info_put(req, I40E_DL_VERSION_RUNNING, 143 DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID, 144 buf); 145 if (err) 146 return err; 147 148 i40e_info_civd_ver(hw, buf, sizeof(buf)); 149 err = i40e_devlink_info_put(req, I40E_DL_VERSION_RUNNING, 150 DEVLINK_INFO_VERSION_GENERIC_FW_UNDI, buf); 151 if (err) 152 return err; 153 154 i40e_info_pba(hw, buf, sizeof(buf)); 155 err = i40e_devlink_info_put(req, I40E_DL_VERSION_FIXED, 156 DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, buf); 157 158 return err; 159 } 160 161 static const struct devlink_ops i40e_devlink_ops = { 162 .info_get = i40e_devlink_info_get, 163 }; 164 165 /** 166 * i40e_alloc_pf - Allocate devlink and return i40e_pf structure pointer 167 * @dev: the device to allocate for 168 * 169 * Allocate a devlink instance for this device and return the private 170 * area as the i40e_pf structure. 171 **/ 172 struct i40e_pf *i40e_alloc_pf(struct device *dev) 173 { 174 struct devlink *devlink; 175 176 devlink = devlink_alloc(&i40e_devlink_ops, sizeof(struct i40e_pf), dev); 177 if (!devlink) 178 return NULL; 179 180 return devlink_priv(devlink); 181 } 182 183 /** 184 * i40e_free_pf - Free i40e_pf structure and associated devlink 185 * @pf: the PF structure 186 * 187 * Free i40e_pf structure and devlink allocated by devlink_alloc. 188 **/ 189 void i40e_free_pf(struct i40e_pf *pf) 190 { 191 struct devlink *devlink = priv_to_devlink(pf); 192 193 devlink_free(devlink); 194 } 195 196 /** 197 * i40e_devlink_register - Register devlink interface for this PF 198 * @pf: the PF to register the devlink for. 199 * 200 * Register the devlink instance associated with this physical function. 201 **/ 202 void i40e_devlink_register(struct i40e_pf *pf) 203 { 204 struct devlink *dl = priv_to_devlink(pf); 205 struct device *dev = &pf->pdev->dev; 206 int err; 207 208 err = devlink_params_register(dl, i40e_dl_params, 209 ARRAY_SIZE(i40e_dl_params)); 210 if (err) 211 dev_err(dev, 212 "devlink params register failed with error %d", err); 213 214 devlink_register(dl); 215 216 } 217 218 /** 219 * i40e_devlink_unregister - Unregister devlink resources for this PF. 220 * @pf: the PF structure to cleanup 221 * 222 * Releases resources used by devlink and cleans up associated memory. 223 **/ 224 void i40e_devlink_unregister(struct i40e_pf *pf) 225 { 226 struct devlink *dl = priv_to_devlink(pf); 227 228 devlink_unregister(dl); 229 devlink_params_unregister(dl, i40e_dl_params, 230 ARRAY_SIZE(i40e_dl_params)); 231 } 232 233 /** 234 * i40e_devlink_set_switch_id - Set unique switch id based on pci dsn 235 * @pf: the PF to create a devlink port for 236 * @ppid: struct with switch id information 237 */ 238 static void i40e_devlink_set_switch_id(struct i40e_pf *pf, 239 struct netdev_phys_item_id *ppid) 240 { 241 u64 id = pci_get_dsn(pf->pdev); 242 243 ppid->id_len = sizeof(id); 244 put_unaligned_be64(id, &ppid->id); 245 } 246 247 /** 248 * i40e_devlink_create_port - Create a devlink port for this PF 249 * @pf: the PF to create a port for 250 * 251 * Create and register a devlink_port for this PF. Note that although each 252 * physical function is connected to a separate devlink instance, the port 253 * will still be numbered according to the physical function id. 254 * 255 * Return: zero on success or an error code on failure. 256 **/ 257 int i40e_devlink_create_port(struct i40e_pf *pf) 258 { 259 struct devlink *devlink = priv_to_devlink(pf); 260 struct devlink_port_attrs attrs = {}; 261 struct device *dev = &pf->pdev->dev; 262 int err; 263 264 attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; 265 attrs.phys.port_number = pf->hw.pf_id; 266 i40e_devlink_set_switch_id(pf, &attrs.switch_id); 267 devlink_port_attrs_set(&pf->devlink_port, &attrs); 268 err = devlink_port_register(devlink, &pf->devlink_port, pf->hw.pf_id); 269 if (err) { 270 dev_err(dev, "devlink_port_register failed: %d\n", err); 271 return err; 272 } 273 274 return 0; 275 } 276 277 /** 278 * i40e_devlink_destroy_port - Destroy the devlink_port for this PF 279 * @pf: the PF to cleanup 280 * 281 * Unregisters the devlink_port structure associated with this PF. 282 **/ 283 void i40e_devlink_destroy_port(struct i40e_pf *pf) 284 { 285 devlink_port_unregister(&pf->devlink_port); 286 } 287