| 1 | |
| 2 |
|
| 3 |
|
| 4 | #include "ixgbe.h"
|
| 5 | #include "devlink.h"
|
| 6 | #include "ixgbe_fw_update.h"
|
| 7 |
|
| 8 | struct ixgbe_info_ctx {
|
| 9 | char buf[128];
|
| 10 | struct ixgbe_orom_info pending_orom;
|
| 11 | struct ixgbe_nvm_info pending_nvm;
|
| 12 | struct ixgbe_netlist_info pending_netlist;
|
| 13 | struct ixgbe_hw_dev_caps dev_caps;
|
| 14 | };
|
| 15 |
|
| 16 | enum ixgbe_devlink_version_type {
|
| 17 | IXGBE_DL_VERSION_RUNNING,
|
| 18 | IXGBE_DL_VERSION_STORED
|
| 19 | };
|
| 20 |
|
| 21 | static void ixgbe_info_get_dsn(struct ixgbe_adapter *adapter,
|
| 22 | struct ixgbe_info_ctx *ctx)
|
| 23 | {
|
| 24 | u8 dsn[8];
|
| 25 |
|
| 26 |
|
| 27 | put_unaligned_be64(pci_get_dsn(adapter->pdev), dsn);
|
| 28 |
|
| 29 | snprintf(ctx->buf, sizeof(ctx->buf), "%8phD", dsn);
|
| 30 | }
|
| 31 |
|
| 32 | static void ixgbe_info_orom_ver(struct ixgbe_adapter *adapter,
|
| 33 | struct ixgbe_info_ctx *ctx,
|
| 34 | enum ixgbe_devlink_version_type type)
|
| 35 | {
|
| 36 | struct ixgbe_hw *hw = &adapter->hw;
|
| 37 | struct ixgbe_nvm_version nvm_ver;
|
| 38 |
|
| 39 | ctx->buf[0] = '\0';
|
| 40 |
|
| 41 | if (hw->mac.type == ixgbe_mac_e610) {
|
| 42 | struct ixgbe_orom_info *orom = &adapter->hw.flash.orom;
|
| 43 |
|
| 44 | if (type == IXGBE_DL_VERSION_STORED &&
|
| 45 | ctx->dev_caps.common_cap.nvm_update_pending_orom)
|
| 46 | orom = &ctx->pending_orom;
|
| 47 |
|
| 48 | snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u",
|
| 49 | orom->major, orom->build, orom->patch);
|
| 50 | return;
|
| 51 | }
|
| 52 |
|
| 53 | ixgbe_get_oem_prod_version(hw, &nvm_ver);
|
| 54 | if (nvm_ver.oem_valid) {
|
| 55 | snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x",
|
| 56 | nvm_ver.oem_major, nvm_ver.oem_minor,
|
| 57 | nvm_ver.oem_release);
|
| 58 |
|
| 59 | return;
|
| 60 | }
|
| 61 |
|
| 62 | ixgbe_get_orom_version(hw, &nvm_ver);
|
| 63 | if (nvm_ver.or_valid)
|
| 64 | snprintf(ctx->buf, sizeof(ctx->buf), "%d.%d.%d",
|
| 65 | nvm_ver.or_major, nvm_ver.or_build, nvm_ver.or_patch);
|
| 66 | }
|
| 67 |
|
| 68 | static void ixgbe_info_eetrack(struct ixgbe_adapter *adapter,
|
| 69 | struct ixgbe_info_ctx *ctx,
|
| 70 | enum ixgbe_devlink_version_type type)
|
| 71 | {
|
| 72 | struct ixgbe_hw *hw = &adapter->hw;
|
| 73 | struct ixgbe_nvm_version nvm_ver;
|
| 74 |
|
| 75 | if (hw->mac.type == ixgbe_mac_e610) {
|
| 76 | u32 eetrack = hw->flash.nvm.eetrack;
|
| 77 |
|
| 78 | if (type == IXGBE_DL_VERSION_STORED &&
|
| 79 | ctx->dev_caps.common_cap.nvm_update_pending_nvm)
|
| 80 | eetrack = ctx->pending_nvm.eetrack;
|
| 81 |
|
| 82 | snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", eetrack);
|
| 83 | return;
|
| 84 | }
|
| 85 |
|
| 86 | ixgbe_get_oem_prod_version(hw, &nvm_ver);
|
| 87 |
|
| 88 |
|
| 89 | if (nvm_ver.oem_valid) {
|
| 90 | ctx->buf[0] = '\0';
|
| 91 | return;
|
| 92 | }
|
| 93 |
|
| 94 | ixgbe_get_etk_id(hw, &nvm_ver);
|
| 95 | snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm_ver.etk_id);
|
| 96 | }
|
| 97 |
|
| 98 | static void ixgbe_info_fw_api(struct ixgbe_adapter *adapter,
|
| 99 | struct ixgbe_info_ctx *ctx)
|
| 100 | {
|
| 101 | struct ixgbe_hw *hw = &adapter->hw;
|
| 102 |
|
| 103 | snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u",
|
| 104 | hw->api_maj_ver, hw->api_min_ver, hw->api_patch);
|
| 105 | }
|
| 106 |
|
| 107 | static void ixgbe_info_fw_build(struct ixgbe_adapter *adapter,
|
| 108 | struct ixgbe_info_ctx *ctx)
|
| 109 | {
|
| 110 | struct ixgbe_hw *hw = &adapter->hw;
|
| 111 |
|
| 112 | snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", hw->fw_build);
|
| 113 | }
|
| 114 |
|
| 115 | static void ixgbe_info_fw_srev(struct ixgbe_adapter *adapter,
|
| 116 | struct ixgbe_info_ctx *ctx,
|
| 117 | enum ixgbe_devlink_version_type type)
|
| 118 | {
|
| 119 | struct ixgbe_nvm_info *nvm = &adapter->hw.flash.nvm;
|
| 120 |
|
| 121 | if (type == IXGBE_DL_VERSION_STORED &&
|
| 122 | ctx->dev_caps.common_cap.nvm_update_pending_nvm)
|
| 123 | nvm = &ctx->pending_nvm;
|
| 124 |
|
| 125 | snprintf(ctx->buf, sizeof(ctx->buf), "%u", nvm->srev);
|
| 126 | }
|
| 127 |
|
| 128 | static void ixgbe_info_orom_srev(struct ixgbe_adapter *adapter,
|
| 129 | struct ixgbe_info_ctx *ctx,
|
| 130 | enum ixgbe_devlink_version_type type)
|
| 131 | {
|
| 132 | struct ixgbe_orom_info *orom = &adapter->hw.flash.orom;
|
| 133 |
|
| 134 | if (type == IXGBE_DL_VERSION_STORED &&
|
| 135 | ctx->dev_caps.common_cap.nvm_update_pending_orom)
|
| 136 | orom = &ctx->pending_orom;
|
| 137 |
|
| 138 | snprintf(ctx->buf, sizeof(ctx->buf), "%u", orom->srev);
|
| 139 | }
|
| 140 |
|
| 141 | static void ixgbe_info_nvm_ver(struct ixgbe_adapter *adapter,
|
| 142 | struct ixgbe_info_ctx *ctx,
|
| 143 | enum ixgbe_devlink_version_type type)
|
| 144 | {
|
| 145 | struct ixgbe_nvm_info *nvm = &adapter->hw.flash.nvm;
|
| 146 |
|
| 147 | if (type == IXGBE_DL_VERSION_STORED &&
|
| 148 | ctx->dev_caps.common_cap.nvm_update_pending_nvm)
|
| 149 | nvm = &ctx->pending_nvm;
|
| 150 |
|
| 151 | snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", nvm->major, nvm->minor);
|
| 152 | }
|
| 153 |
|
| 154 | static void ixgbe_info_netlist_ver(struct ixgbe_adapter *adapter,
|
| 155 | struct ixgbe_info_ctx *ctx,
|
| 156 | enum ixgbe_devlink_version_type type)
|
| 157 | {
|
| 158 | struct ixgbe_netlist_info *netlist = &adapter->hw.flash.netlist;
|
| 159 |
|
| 160 | if (type == IXGBE_DL_VERSION_STORED &&
|
| 161 | ctx->dev_caps.common_cap.nvm_update_pending_netlist)
|
| 162 | netlist = &ctx->pending_netlist;
|
| 163 |
|
| 164 |
|
| 165 | snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x",
|
| 166 | netlist->major, netlist->minor,
|
| 167 | netlist->type >> 16, netlist->type & 0xFFFF,
|
| 168 | netlist->rev, netlist->cust_ver);
|
| 169 | }
|
| 170 |
|
| 171 | static void ixgbe_info_netlist_build(struct ixgbe_adapter *adapter,
|
| 172 | struct ixgbe_info_ctx *ctx,
|
| 173 | enum ixgbe_devlink_version_type type)
|
| 174 | {
|
| 175 | struct ixgbe_netlist_info *netlist = &adapter->hw.flash.netlist;
|
| 176 |
|
| 177 | if (type == IXGBE_DL_VERSION_STORED &&
|
| 178 | ctx->dev_caps.common_cap.nvm_update_pending_netlist)
|
| 179 | netlist = &ctx->pending_netlist;
|
| 180 |
|
| 181 | snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash);
|
| 182 | }
|
| 183 |
|
| 184 | static int ixgbe_set_ctx_dev_caps(struct ixgbe_hw *hw,
|
| 185 | struct ixgbe_info_ctx *ctx,
|
| 186 | struct netlink_ext_ack *extack)
|
| 187 | {
|
| 188 | bool *pending_orom, *pending_nvm, *pending_netlist;
|
| 189 | int err;
|
| 190 |
|
| 191 | err = ixgbe_discover_dev_caps(hw, &ctx->dev_caps);
|
| 192 | if (err) {
|
| 193 | NL_SET_ERR_MSG_MOD(extack,
|
| 194 | "Unable to discover device capabilities");
|
| 195 | return err;
|
| 196 | }
|
| 197 |
|
| 198 | pending_orom = &ctx->dev_caps.common_cap.nvm_update_pending_orom;
|
| 199 | pending_nvm = &ctx->dev_caps.common_cap.nvm_update_pending_nvm;
|
| 200 | pending_netlist = &ctx->dev_caps.common_cap.nvm_update_pending_netlist;
|
| 201 |
|
| 202 | if (*pending_orom) {
|
| 203 | err = ixgbe_get_inactive_orom_ver(hw, &ctx->pending_orom);
|
| 204 | if (err)
|
| 205 | *pending_orom = false;
|
| 206 | }
|
| 207 |
|
| 208 | if (*pending_nvm) {
|
| 209 | err = ixgbe_get_inactive_nvm_ver(hw, &ctx->pending_nvm);
|
| 210 | if (err)
|
| 211 | *pending_nvm = false;
|
| 212 | }
|
| 213 |
|
| 214 | if (*pending_netlist) {
|
| 215 | err = ixgbe_get_inactive_netlist_ver(hw, &ctx->pending_netlist);
|
| 216 | if (err)
|
| 217 | *pending_netlist = false;
|
| 218 | }
|
| 219 |
|
| 220 | return 0;
|
| 221 | }
|
| 222 |
|
| 223 | static int ixgbe_devlink_info_get_e610(struct ixgbe_adapter *adapter,
|
| 224 | struct devlink_info_req *req,
|
| 225 | struct ixgbe_info_ctx *ctx)
|
| 226 | {
|
| 227 | int err;
|
| 228 |
|
| 229 | ixgbe_info_fw_api(adapter, ctx);
|
| 230 | err = devlink_info_version_running_put(req,
|
| 231 | DEVLINK_INFO_VERSION_GENERIC_FW_MGMT_API,
|
| 232 | ctx->buf);
|
| 233 | if (err)
|
| 234 | return err;
|
| 235 |
|
| 236 | ixgbe_info_fw_build(adapter, ctx);
|
| 237 | err = devlink_info_version_running_put(req, "fw.mgmt.build", ctx->buf);
|
| 238 | if (err)
|
| 239 | return err;
|
| 240 |
|
| 241 | ixgbe_info_fw_srev(adapter, ctx, IXGBE_DL_VERSION_RUNNING);
|
| 242 | err = devlink_info_version_running_put(req, "fw.mgmt.srev", ctx->buf);
|
| 243 | if (err)
|
| 244 | return err;
|
| 245 |
|
| 246 | ixgbe_info_orom_srev(adapter, ctx, IXGBE_DL_VERSION_RUNNING);
|
| 247 | err = devlink_info_version_running_put(req, "fw.undi.srev", ctx->buf);
|
| 248 | if (err)
|
| 249 | return err;
|
| 250 |
|
| 251 | ixgbe_info_nvm_ver(adapter, ctx, IXGBE_DL_VERSION_RUNNING);
|
| 252 | err = devlink_info_version_running_put(req, "fw.psid.api", ctx->buf);
|
| 253 | if (err)
|
| 254 | return err;
|
| 255 |
|
| 256 | ixgbe_info_netlist_ver(adapter, ctx, IXGBE_DL_VERSION_RUNNING);
|
| 257 | err = devlink_info_version_running_put(req, "fw.netlist", ctx->buf);
|
| 258 | if (err)
|
| 259 | return err;
|
| 260 |
|
| 261 | ixgbe_info_netlist_build(adapter, ctx, IXGBE_DL_VERSION_RUNNING);
|
| 262 | return devlink_info_version_running_put(req, "fw.netlist.build",
|
| 263 | ctx->buf);
|
| 264 | }
|
| 265 |
|
| 266 | static int
|
| 267 | ixgbe_devlink_pending_info_get_e610(struct ixgbe_adapter *adapter,
|
| 268 | struct devlink_info_req *req,
|
| 269 | struct ixgbe_info_ctx *ctx)
|
| 270 | {
|
| 271 | int err;
|
| 272 |
|
| 273 | ixgbe_info_orom_ver(adapter, ctx, IXGBE_DL_VERSION_STORED);
|
| 274 | err = devlink_info_version_stored_put(req,
|
| 275 | DEVLINK_INFO_VERSION_GENERIC_FW_UNDI,
|
| 276 | ctx->buf);
|
| 277 | if (err)
|
| 278 | return err;
|
| 279 |
|
| 280 | ixgbe_info_eetrack(adapter, ctx, IXGBE_DL_VERSION_STORED);
|
| 281 | err = devlink_info_version_stored_put(req,
|
| 282 | DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID,
|
| 283 | ctx->buf);
|
| 284 | if (err)
|
| 285 | return err;
|
| 286 |
|
| 287 | ixgbe_info_fw_srev(adapter, ctx, IXGBE_DL_VERSION_STORED);
|
| 288 | err = devlink_info_version_stored_put(req, "fw.mgmt.srev", ctx->buf);
|
| 289 | if (err)
|
| 290 | return err;
|
| 291 |
|
| 292 | ixgbe_info_orom_srev(adapter, ctx, IXGBE_DL_VERSION_STORED);
|
| 293 | err = devlink_info_version_stored_put(req, "fw.undi.srev", ctx->buf);
|
| 294 | if (err)
|
| 295 | return err;
|
| 296 |
|
| 297 | ixgbe_info_nvm_ver(adapter, ctx, IXGBE_DL_VERSION_STORED);
|
| 298 | err = devlink_info_version_stored_put(req, "fw.psid.api", ctx->buf);
|
| 299 | if (err)
|
| 300 | return err;
|
| 301 |
|
| 302 | ixgbe_info_netlist_ver(adapter, ctx, IXGBE_DL_VERSION_STORED);
|
| 303 | err = devlink_info_version_stored_put(req, "fw.netlist", ctx->buf);
|
| 304 | if (err)
|
| 305 | return err;
|
| 306 |
|
| 307 | ixgbe_info_netlist_build(adapter, ctx, IXGBE_DL_VERSION_STORED);
|
| 308 | return devlink_info_version_stored_put(req, "fw.netlist.build",
|
| 309 | ctx->buf);
|
| 310 | }
|
| 311 |
|
| 312 | static int ixgbe_devlink_info_get(struct devlink *devlink,
|
| 313 | struct devlink_info_req *req,
|
| 314 | struct netlink_ext_ack *extack)
|
| 315 | {
|
| 316 | struct ixgbe_adapter *adapter = devlink_priv(devlink);
|
| 317 | struct ixgbe_hw *hw = &adapter->hw;
|
| 318 | struct ixgbe_info_ctx *ctx;
|
| 319 | int err;
|
| 320 |
|
| 321 | ctx = kmalloc_obj(*ctx);
|
| 322 | if (!ctx)
|
| 323 | return -ENOMEM;
|
| 324 |
|
| 325 | if (hw->mac.type == ixgbe_mac_e610)
|
| 326 | ixgbe_refresh_fw_version(adapter);
|
| 327 |
|
| 328 | ixgbe_info_get_dsn(adapter, ctx);
|
| 329 | err = devlink_info_serial_number_put(req, ctx->buf);
|
| 330 | if (err)
|
| 331 | goto free_ctx;
|
| 332 |
|
| 333 | err = hw->eeprom.ops.read_pba_string(hw, ctx->buf, sizeof(ctx->buf));
|
| 334 | if (err)
|
| 335 | goto free_ctx;
|
| 336 |
|
| 337 | err = devlink_info_version_fixed_put(req,
|
| 338 | DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,
|
| 339 | ctx->buf);
|
| 340 | if (err)
|
| 341 | goto free_ctx;
|
| 342 |
|
| 343 | ixgbe_info_orom_ver(adapter, ctx, IXGBE_DL_VERSION_RUNNING);
|
| 344 | err = devlink_info_version_running_put(req,
|
| 345 | DEVLINK_INFO_VERSION_GENERIC_FW_UNDI,
|
| 346 | ctx->buf);
|
| 347 | if (err)
|
| 348 | goto free_ctx;
|
| 349 |
|
| 350 | ixgbe_info_eetrack(adapter, ctx, IXGBE_DL_VERSION_RUNNING);
|
| 351 | err = devlink_info_version_running_put(req,
|
| 352 | DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID,
|
| 353 | ctx->buf);
|
| 354 | if (err || hw->mac.type != ixgbe_mac_e610)
|
| 355 | goto free_ctx;
|
| 356 |
|
| 357 | err = ixgbe_set_ctx_dev_caps(hw, ctx, extack);
|
| 358 | if (err)
|
| 359 | goto free_ctx;
|
| 360 |
|
| 361 | err = ixgbe_devlink_info_get_e610(adapter, req, ctx);
|
| 362 | if (err)
|
| 363 | goto free_ctx;
|
| 364 |
|
| 365 | err = ixgbe_devlink_pending_info_get_e610(adapter, req, ctx);
|
| 366 | free_ctx:
|
| 367 | kfree(ctx);
|
| 368 | return err;
|
| 369 | }
|
| 370 |
|
| 371 | |
| 372 | * ixgbe_devlink_reload_empr_start - Start EMP reset to activate new firmware
|
| 373 | * @devlink: pointer to the devlink instance to reload
|
| 374 | * @netns_change: if true, the network namespace is changing
|
| 375 | * @action: the action to perform. Must be DEVLINK_RELOAD_ACTION_FW_ACTIVATE
|
| 376 | * @limit: limits on what reload should do, such as not resetting
|
| 377 | * @extack: netlink extended ACK structure
|
| 378 | *
|
| 379 | * Allow user to activate new Embedded Management Processor firmware by
|
| 380 | * issuing device specific EMP reset. Called in response to
|
| 381 | * a DEVLINK_CMD_RELOAD with the DEVLINK_RELOAD_ACTION_FW_ACTIVATE.
|
| 382 | *
|
| 383 | * Note that teardown and rebuild of the driver state happens automatically as
|
| 384 | * part of an interrupt and watchdog task. This is because all physical
|
| 385 | * functions on the device must be able to reset when an EMP reset occurs from
|
| 386 | * any source.
|
| 387 | *
|
| 388 | * Return: the exit code of the operation.
|
| 389 |
|
| 390 | static int ixgbe_devlink_reload_empr_start(struct devlink *devlink,
|
| 391 | bool netns_change,
|
| 392 | enum devlink_reload_action action,
|
| 393 | enum devlink_reload_limit limit,
|
| 394 | struct netlink_ext_ack *extack)
|
| 395 | {
|
| 396 | struct ixgbe_adapter *adapter = devlink_priv(devlink);
|
| 397 | struct ixgbe_hw *hw = &adapter->hw;
|
| 398 | u8 pending;
|
| 399 | int err;
|
| 400 |
|
| 401 | if (hw->mac.type != ixgbe_mac_e610)
|
| 402 | return -EOPNOTSUPP;
|
| 403 |
|
| 404 | err = ixgbe_get_pending_updates(adapter, &pending, extack);
|
| 405 | if (err)
|
| 406 | return err;
|
| 407 |
|
| 408 | |
| 409 | * including the main NVM bank, the Option ROM bank, and the netlist
|
| 410 | * bank. If any of these bits are set, then there is a pending update
|
| 411 | * waiting to be activated.
|
| 412 |
|
| 413 | if (!pending) {
|
| 414 | NL_SET_ERR_MSG_MOD(extack, "No pending firmware update");
|
| 415 | return -ECANCELED;
|
| 416 | }
|
| 417 |
|
| 418 | if (adapter->fw_emp_reset_disabled) {
|
| 419 | NL_SET_ERR_MSG_MOD(extack,
|
| 420 | "EMP reset is not available. To activate firmware, a reboot or power cycle is needed");
|
| 421 | return -ECANCELED;
|
| 422 | }
|
| 423 |
|
| 424 | err = ixgbe_aci_nvm_update_empr(hw);
|
| 425 | if (err)
|
| 426 | NL_SET_ERR_MSG_MOD(extack,
|
| 427 | "Failed to trigger EMP device reset to reload firmware");
|
| 428 |
|
| 429 | return err;
|
| 430 | }
|
| 431 |
|
| 432 |
|
| 433 | #define IXGBE_DEVLINK_RELOAD_TIMEOUT_SEC 20
|
| 434 |
|
| 435 | |
| 436 | * ixgbe_devlink_reload_empr_finish - finishes EMP reset
|
| 437 | * @devlink: pointer to the devlink instance
|
| 438 | * @action: the action to perform.
|
| 439 | * @limit: limits on what reload should do
|
| 440 | * @actions_performed: actions performed
|
| 441 | * @extack: netlink extended ACK structure
|
| 442 | *
|
| 443 | * Wait for new NVM to be loaded during EMP reset.
|
| 444 | *
|
| 445 | * Return: -ETIME when timer is exceeded, 0 on success.
|
| 446 |
|
| 447 | static int ixgbe_devlink_reload_empr_finish(struct devlink *devlink,
|
| 448 | enum devlink_reload_action action,
|
| 449 | enum devlink_reload_limit limit,
|
| 450 | u32 *actions_performed,
|
| 451 | struct netlink_ext_ack *extack)
|
| 452 | {
|
| 453 | struct ixgbe_adapter *adapter = devlink_priv(devlink);
|
| 454 | struct ixgbe_hw *hw = &adapter->hw;
|
| 455 | int i = 0;
|
| 456 | u32 fwsm;
|
| 457 |
|
| 458 | do {
|
| 459 | |
| 460 | * may be not cleared yet, so begin the loop with the delay
|
| 461 | * in order to not check the not updated register.
|
| 462 |
|
| 463 | mdelay(500);
|
| 464 |
|
| 465 | fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM(hw));
|
| 466 |
|
| 467 | if (i++ >= IXGBE_DEVLINK_RELOAD_TIMEOUT_SEC)
|
| 468 | return -ETIME;
|
| 469 |
|
| 470 | } while (!(fwsm & IXGBE_FWSM_FW_VAL_BIT));
|
| 471 |
|
| 472 | *actions_performed = BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE);
|
| 473 |
|
| 474 | adapter->flags2 &= ~(IXGBE_FLAG2_API_MISMATCH |
|
| 475 | IXGBE_FLAG2_FW_ROLLBACK);
|
| 476 |
|
| 477 | return ixgbe_refresh_fw_version(adapter);
|
| 478 | }
|
| 479 |
|
| 480 | static const struct devlink_ops ixgbe_devlink_ops = {
|
| 481 | .info_get = ixgbe_devlink_info_get,
|
| 482 | .supported_flash_update_params =
|
| 483 | DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK,
|
| 484 | .flash_update = ixgbe_flash_pldm_image,
|
| 485 | .reload_actions = BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE),
|
| 486 | .reload_down = ixgbe_devlink_reload_empr_start,
|
| 487 | .reload_up = ixgbe_devlink_reload_empr_finish,
|
| 488 | };
|
| 489 |
|
| 490 | |
| 491 | * ixgbe_allocate_devlink - Allocate devlink instance
|
| 492 | * @dev: device to allocate devlink for
|
| 493 | *
|
| 494 | * Allocate a devlink instance for this physical function.
|
| 495 | *
|
| 496 | * Return: pointer to the device adapter structure on success,
|
| 497 | * ERR_PTR(-ENOMEM) when allocation failed.
|
| 498 |
|
| 499 | struct ixgbe_adapter *ixgbe_allocate_devlink(struct device *dev)
|
| 500 | {
|
| 501 | struct ixgbe_adapter *adapter;
|
| 502 | struct devlink *devlink;
|
| 503 |
|
| 504 | devlink = devlink_alloc(&ixgbe_devlink_ops, sizeof(*adapter), dev);
|
| 505 | if (!devlink)
|
| 506 | return ERR_PTR(-ENOMEM);
|
| 507 |
|
| 508 | adapter = devlink_priv(devlink);
|
| 509 | adapter->devlink = devlink;
|
| 510 |
|
| 511 | return adapter;
|
| 512 | }
|
| 513 |
|
| 514 | |
| 515 | * ixgbe_devlink_set_switch_id - Set unique switch ID based on PCI DSN
|
| 516 | * @adapter: pointer to the device adapter structure
|
| 517 | * @ppid: struct with switch id information
|
| 518 |
|
| 519 | static void ixgbe_devlink_set_switch_id(struct ixgbe_adapter *adapter,
|
| 520 | struct netdev_phys_item_id *ppid)
|
| 521 | {
|
| 522 | u64 id = pci_get_dsn(adapter->pdev);
|
| 523 |
|
| 524 | ppid->id_len = sizeof(id);
|
| 525 | put_unaligned_be64(id, &ppid->id);
|
| 526 | }
|
| 527 |
|
| 528 | |
| 529 | * ixgbe_devlink_register_port - Register devlink port
|
| 530 | * @adapter: pointer to the device adapter structure
|
| 531 | *
|
| 532 | * Create and register a devlink_port for this physical function.
|
| 533 | *
|
| 534 | * Return: 0 on success, error code on failure.
|
| 535 |
|
| 536 | int ixgbe_devlink_register_port(struct ixgbe_adapter *adapter)
|
| 537 | {
|
| 538 | struct devlink_port *devlink_port = &adapter->devlink_port;
|
| 539 | struct devlink *devlink = adapter->devlink;
|
| 540 | struct device *dev = &adapter->pdev->dev;
|
| 541 | struct devlink_port_attrs attrs = {};
|
| 542 | int err;
|
| 543 |
|
| 544 | attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
|
| 545 | attrs.phys.port_number = adapter->hw.bus.func;
|
| 546 | attrs.no_phys_port_name = 1;
|
| 547 | ixgbe_devlink_set_switch_id(adapter, &attrs.switch_id);
|
| 548 |
|
| 549 | devlink_port_attrs_set(devlink_port, &attrs);
|
| 550 |
|
| 551 | err = devl_port_register(devlink, devlink_port, 0);
|
| 552 | if (err) {
|
| 553 | dev_err(dev,
|
| 554 | "devlink port registration failed, err %d\n", err);
|
| 555 | }
|
| 556 |
|
| 557 | return err;
|
| 558 | }
|