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