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