Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/net/ethernet/sfc/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 20 kB image not shown  

Quelle  efx_devlink.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/****************************************************************************
 * Driver for AMD network controllers and boards
 * Copyright (C) 2023, Advanced Micro Devices, Inc.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published
 * by the Free Software Foundation, incorporated herein by reference.
 */


#include "net_driver.h"
#include "ef100_nic.h"
#include "efx_devlink.h"
#include <linux/rtc.h>
#include "mcdi.h"
#include "mcdi_functions.h"
#include "mcdi_pcol.h"
#ifdef CONFIG_SFC_SRIOV
#include "mae.h"
#include "ef100_rep.h"
#endif
#include "efx_reflash.h"

struct efx_devlink {
 struct efx_nic *efx;
};

#ifdef CONFIG_SFC_SRIOV

static int efx_devlink_port_addr_get(struct devlink_port *port, u8 *hw_addr,
         int *hw_addr_len,
         struct netlink_ext_ack *extack)
{
 struct efx_devlink *devlink = devlink_priv(port->devlink);
 struct mae_mport_desc *mport_desc;
 efx_qword_t pciefn;
 u32 client_id;
 int rc = 0;

 mport_desc = container_of(port, struct mae_mport_desc, dl_port);

 if (!ef100_mport_on_local_intf(devlink->efx, mport_desc)) {
  rc = -EINVAL;
  NL_SET_ERR_MSG_FMT(extack,
       "Port not on local interface (mport: %u)",
       mport_desc->mport_id);
  goto out;
 }

 if (ef100_mport_is_vf(mport_desc))
  EFX_POPULATE_QWORD_3(pciefn,
         PCIE_FUNCTION_PF, PCIE_FUNCTION_PF_NULL,
         PCIE_FUNCTION_VF, mport_desc->vf_idx,
         PCIE_FUNCTION_INTF, PCIE_INTERFACE_CALLER);
 else
  EFX_POPULATE_QWORD_3(pciefn,
         PCIE_FUNCTION_PF, mport_desc->pf_idx,
         PCIE_FUNCTION_VF, PCIE_FUNCTION_VF_NULL,
         PCIE_FUNCTION_INTF, PCIE_INTERFACE_CALLER);

 rc = efx_ef100_lookup_client_id(devlink->efx, pciefn, &client_id);
 if (rc) {
  NL_SET_ERR_MSG_FMT(extack,
       "No internal client_ID for port (mport: %u)",
       mport_desc->mport_id);
  goto out;
 }

 rc = ef100_get_mac_address(devlink->efx, hw_addr, client_id, true);
 if (rc != 0)
  NL_SET_ERR_MSG_FMT(extack,
       "No available MAC for port (mport: %u)",
       mport_desc->mport_id);
out:
 *hw_addr_len = ETH_ALEN;
 return rc;
}

static int efx_devlink_port_addr_set(struct devlink_port *port,
         const u8 *hw_addr, int hw_addr_len,
         struct netlink_ext_ack *extack)
{
 MCDI_DECLARE_BUF(inbuf, MC_CMD_SET_CLIENT_MAC_ADDRESSES_IN_LEN(1));
 struct efx_devlink *devlink = devlink_priv(port->devlink);
 struct mae_mport_desc *mport_desc;
 efx_qword_t pciefn;
 u32 client_id;
 int rc;

 mport_desc = container_of(port, struct mae_mport_desc, dl_port);

 if (!ef100_mport_is_vf(mport_desc)) {
  NL_SET_ERR_MSG_FMT(extack,
       "port mac change not allowed (mport: %u)",
       mport_desc->mport_id);
  return -EPERM;
 }

 EFX_POPULATE_QWORD_3(pciefn,
        PCIE_FUNCTION_PF, PCIE_FUNCTION_PF_NULL,
        PCIE_FUNCTION_VF, mport_desc->vf_idx,
        PCIE_FUNCTION_INTF, PCIE_INTERFACE_CALLER);

 rc = efx_ef100_lookup_client_id(devlink->efx, pciefn, &client_id);
 if (rc) {
  NL_SET_ERR_MSG_FMT(extack,
       "No internal client_ID for port (mport: %u)",
       mport_desc->mport_id);
  return rc;
 }

 MCDI_SET_DWORD(inbuf, SET_CLIENT_MAC_ADDRESSES_IN_CLIENT_HANDLE,
         client_id);

 ether_addr_copy(MCDI_PTR(inbuf, SET_CLIENT_MAC_ADDRESSES_IN_MAC_ADDRS),
   hw_addr);

 rc = efx_mcdi_rpc(devlink->efx, MC_CMD_SET_CLIENT_MAC_ADDRESSES, inbuf,
     sizeof(inbuf), NULL, 0, NULL);
 if (rc)
  NL_SET_ERR_MSG_FMT(extack,
       "sfc MC_CMD_SET_CLIENT_MAC_ADDRESSES mcdi error (mport: %u)",
       mport_desc->mport_id);

 return rc;
}

static const struct devlink_port_ops sfc_devlink_port_ops = {
 .port_fn_hw_addr_get = efx_devlink_port_addr_get,
 .port_fn_hw_addr_set = efx_devlink_port_addr_set,
};

static void efx_devlink_del_port(struct devlink_port *dl_port)
{
 if (!dl_port)
  return;
 devl_port_unregister(dl_port);
}

static int efx_devlink_add_port(struct efx_nic *efx,
    struct mae_mport_desc *mport)
{
 bool external = false;

 if (!ef100_mport_on_local_intf(efx, mport))
  external = true;

 switch (mport->mport_type) {
 case MAE_MPORT_DESC_MPORT_TYPE_VNIC:
  if (mport->vf_idx != MAE_MPORT_DESC_VF_IDX_NULL)
   devlink_port_attrs_pci_vf_set(&mport->dl_port, 0, mport->pf_idx,
            mport->vf_idx,
            external);
  else
   devlink_port_attrs_pci_pf_set(&mport->dl_port, 0, mport->pf_idx,
            external);
  break;
 default:
  /* MAE_MPORT_DESC_MPORT_ALIAS and UNDEFINED */
  return 0;
 }

 mport->dl_port.index = mport->mport_id;

 return devl_port_register_with_ops(efx->devlink, &mport->dl_port,
        mport->mport_id,
        &sfc_devlink_port_ops);
}

#endif

static int efx_devlink_info_nvram_partition(struct efx_nic *efx,
         struct devlink_info_req *req,
         unsigned int partition_type,
         const char *version_name)
{
 char buf[EFX_MAX_VERSION_INFO_LEN];
 u16 version[4];
 int rc;

 rc = efx_mcdi_nvram_metadata(efx, partition_type, NULL, version, NULL,
         0);

 /* If the partition does not exist, that is not an error. */
 if (rc == -ENOENT)
  return 0;

 if (rc) {
  netif_err(efx, drv, efx->net_dev, "mcdi nvram %s: failed (rc=%d)\n",
     version_name, rc);
  return rc;
 }

 snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u", version[0],
   version[1], version[2], version[3]);
 devlink_info_version_stored_put(req, version_name, buf);

 return 0;
}

static int efx_devlink_info_stored_versions(struct efx_nic *efx,
         struct devlink_info_req *req)
{
 int err;

 /* We do not care here about the specific error but just if an error
 * happened. The specific error will be reported inside the call
 * through system messages, and if any error happened in any call
 * below, we report it through extack.
 */

 err = efx_devlink_info_nvram_partition(efx, req,
            NVRAM_PARTITION_TYPE_BUNDLE,
            DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID);

 err |= efx_devlink_info_nvram_partition(efx, req,
      NVRAM_PARTITION_TYPE_MC_FIRMWARE,
      DEVLINK_INFO_VERSION_GENERIC_FW_MGMT);

 err |= efx_devlink_info_nvram_partition(efx, req,
      NVRAM_PARTITION_TYPE_SUC_FIRMWARE,
      EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC);

 err |= efx_devlink_info_nvram_partition(efx, req,
      NVRAM_PARTITION_TYPE_EXPANSION_ROM,
      EFX_DEVLINK_INFO_VERSION_FW_EXPROM);

 err |= efx_devlink_info_nvram_partition(efx, req,
      NVRAM_PARTITION_TYPE_EXPANSION_UEFI,
      EFX_DEVLINK_INFO_VERSION_FW_UEFI);
 return err;
}

#define EFX_VER_FLAG(_f) \
 (MC_CMD_GET_VERSION_V5_OUT_ ## _f ## _PRESENT_LBN)

static void efx_devlink_info_running_v2(struct efx_nic *efx,
     struct devlink_info_req *req,
     unsigned int flags, efx_dword_t *outbuf)
{
 char buf[EFX_MAX_VERSION_INFO_LEN];
 union {
  const __le32 *dwords;
  const __le16 *words;
  const char *str;
 } ver;
 struct rtc_time build_date;
 unsigned int build_id;
 size_t offset;
 __maybe_unused u64 tstamp;

 if (flags & BIT(EFX_VER_FLAG(BOARD_EXT_INFO))) {
  snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%s",
    MCDI_PTR(outbuf, GET_VERSION_V2_OUT_BOARD_NAME));
  devlink_info_version_fixed_put(req,
            DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,
            buf);

  /* Favour full board version if present (in V5 or later) */
  if (~flags & BIT(EFX_VER_FLAG(BOARD_VERSION))) {
   snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u",
     MCDI_DWORD(outbuf,
         GET_VERSION_V2_OUT_BOARD_REVISION));
   devlink_info_version_fixed_put(req,
             DEVLINK_INFO_VERSION_GENERIC_BOARD_REV,
             buf);
  }

  ver.str = MCDI_PTR(outbuf, GET_VERSION_V2_OUT_BOARD_SERIAL);
  if (ver.str[0])
   devlink_info_board_serial_number_put(req, ver.str);
 }

 if (flags & BIT(EFX_VER_FLAG(FPGA_EXT_INFO))) {
  ver.dwords = (__le32 *)MCDI_PTR(outbuf,
      GET_VERSION_V2_OUT_FPGA_VERSION);
  offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u_%c%u",
      le32_to_cpu(ver.dwords[0]),
      'A' + le32_to_cpu(ver.dwords[1]),
      le32_to_cpu(ver.dwords[2]));

  ver.str = MCDI_PTR(outbuf, GET_VERSION_V2_OUT_FPGA_EXTRA);
  if (ver.str[0])
   snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset,
     " (%s)", ver.str);

  devlink_info_version_running_put(req,
       EFX_DEVLINK_INFO_VERSION_FPGA_REV,
       buf);
 }

 if (flags & BIT(EFX_VER_FLAG(CMC_EXT_INFO))) {
  ver.dwords = (__le32 *)MCDI_PTR(outbuf,
      GET_VERSION_V2_OUT_CMCFW_VERSION);
  offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
      le32_to_cpu(ver.dwords[0]),
      le32_to_cpu(ver.dwords[1]),
      le32_to_cpu(ver.dwords[2]),
      le32_to_cpu(ver.dwords[3]));

#ifdef CONFIG_RTC_LIB
  tstamp = MCDI_QWORD(outbuf,
        GET_VERSION_V2_OUT_CMCFW_BUILD_DATE);
  if (tstamp) {
   rtc_time64_to_tm(tstamp, &build_date);
   snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset,
     " (%ptRd)", &build_date);
  }
#endif

  devlink_info_version_running_put(req,
       EFX_DEVLINK_INFO_VERSION_FW_MGMT_CMC,
       buf);
 }

 ver.words = (__le16 *)MCDI_PTR(outbuf, GET_VERSION_V2_OUT_VERSION);
 offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
     le16_to_cpu(ver.words[0]), le16_to_cpu(ver.words[1]),
     le16_to_cpu(ver.words[2]), le16_to_cpu(ver.words[3]));
 if (flags & BIT(EFX_VER_FLAG(MCFW_EXT_INFO))) {
  build_id = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_MCFW_BUILD_ID);
  snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset,
    " (%x) %s", build_id,
    MCDI_PTR(outbuf, GET_VERSION_V2_OUT_MCFW_BUILD_NAME));
 }
 devlink_info_version_running_put(req,
      DEVLINK_INFO_VERSION_GENERIC_FW_MGMT,
      buf);

 if (flags & BIT(EFX_VER_FLAG(SUCFW_EXT_INFO))) {
  ver.dwords = (__le32 *)MCDI_PTR(outbuf,
      GET_VERSION_V2_OUT_SUCFW_VERSION);
#ifdef CONFIG_RTC_LIB
  tstamp = MCDI_QWORD(outbuf,
        GET_VERSION_V2_OUT_SUCFW_BUILD_DATE);
  rtc_time64_to_tm(tstamp, &build_date);
#else
  memset(&build_date, 0, sizeof(build_date));
#endif
  build_id = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_SUCFW_CHIP_ID);

  snprintf(buf, EFX_MAX_VERSION_INFO_LEN,
    "%u.%u.%u.%u type %x (%ptRd)",
    le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
    le32_to_cpu(ver.dwords[2]), le32_to_cpu(ver.dwords[3]),
    build_id, &build_date);

  devlink_info_version_running_put(req,
       EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC,
       buf);
 }
}

static void efx_devlink_info_running_v3(struct efx_nic *efx,
     struct devlink_info_req *req,
     unsigned int flags, efx_dword_t *outbuf)
{
 char buf[EFX_MAX_VERSION_INFO_LEN];
 union {
  const __le32 *dwords;
  const __le16 *words;
  const char *str;
 } ver;

 if (flags & BIT(EFX_VER_FLAG(DATAPATH_HW_VERSION))) {
  ver.dwords = (__le32 *)MCDI_PTR(outbuf,
      GET_VERSION_V3_OUT_DATAPATH_HW_VERSION);

  snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u",
    le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
    le32_to_cpu(ver.dwords[2]));

  devlink_info_version_running_put(req,
       EFX_DEVLINK_INFO_VERSION_DATAPATH_HW,
       buf);
 }

 if (flags & BIT(EFX_VER_FLAG(DATAPATH_FW_VERSION))) {
  ver.dwords = (__le32 *)MCDI_PTR(outbuf,
      GET_VERSION_V3_OUT_DATAPATH_FW_VERSION);

  snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u",
    le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
    le32_to_cpu(ver.dwords[2]));

  devlink_info_version_running_put(req,
       EFX_DEVLINK_INFO_VERSION_DATAPATH_FW,
       buf);
 }
}

static void efx_devlink_info_running_v4(struct efx_nic *efx,
     struct devlink_info_req *req,
     unsigned int flags, efx_dword_t *outbuf)
{
 char buf[EFX_MAX_VERSION_INFO_LEN];
 union {
  const __le32 *dwords;
  const __le16 *words;
  const char *str;
 } ver;

 if (flags & BIT(EFX_VER_FLAG(SOC_BOOT_VERSION))) {
  ver.dwords = (__le32 *)MCDI_PTR(outbuf,
      GET_VERSION_V4_OUT_SOC_BOOT_VERSION);

  snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
    le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
    le32_to_cpu(ver.dwords[2]),
    le32_to_cpu(ver.dwords[3]));

  devlink_info_version_running_put(req,
       EFX_DEVLINK_INFO_VERSION_SOC_BOOT,
       buf);
 }

 if (flags & BIT(EFX_VER_FLAG(SOC_UBOOT_VERSION))) {
  ver.dwords = (__le32 *)MCDI_PTR(outbuf,
      GET_VERSION_V4_OUT_SOC_UBOOT_VERSION);

  snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
    le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
    le32_to_cpu(ver.dwords[2]),
    le32_to_cpu(ver.dwords[3]));

  devlink_info_version_running_put(req,
       EFX_DEVLINK_INFO_VERSION_SOC_UBOOT,
       buf);
 }

 if (flags & BIT(EFX_VER_FLAG(SOC_MAIN_ROOTFS_VERSION))) {
  ver.dwords = (__le32 *)MCDI_PTR(outbuf,
     GET_VERSION_V4_OUT_SOC_MAIN_ROOTFS_VERSION);

  snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
    le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
    le32_to_cpu(ver.dwords[2]),
    le32_to_cpu(ver.dwords[3]));

  devlink_info_version_running_put(req,
       EFX_DEVLINK_INFO_VERSION_SOC_MAIN,
       buf);
 }

 if (flags & BIT(EFX_VER_FLAG(SOC_RECOVERY_BUILDROOT_VERSION))) {
  ver.dwords = (__le32 *)MCDI_PTR(outbuf,
      GET_VERSION_V4_OUT_SOC_RECOVERY_BUILDROOT_VERSION);

  snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
    le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
    le32_to_cpu(ver.dwords[2]),
    le32_to_cpu(ver.dwords[3]));

  devlink_info_version_running_put(req,
       EFX_DEVLINK_INFO_VERSION_SOC_RECOVERY,
       buf);
 }

 if (flags & BIT(EFX_VER_FLAG(SUCFW_VERSION)) &&
     ~flags & BIT(EFX_VER_FLAG(SUCFW_EXT_INFO))) {
  ver.dwords = (__le32 *)MCDI_PTR(outbuf,
      GET_VERSION_V4_OUT_SUCFW_VERSION);

  snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
    le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
    le32_to_cpu(ver.dwords[2]),
    le32_to_cpu(ver.dwords[3]));

  devlink_info_version_running_put(req,
       EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC,
       buf);
 }
}

static void efx_devlink_info_running_v5(struct efx_nic *efx,
     struct devlink_info_req *req,
     unsigned int flags, efx_dword_t *outbuf)
{
 char buf[EFX_MAX_VERSION_INFO_LEN];
 union {
  const __le32 *dwords;
  const __le16 *words;
  const char *str;
 } ver;

 if (flags & BIT(EFX_VER_FLAG(BOARD_VERSION))) {
  ver.dwords = (__le32 *)MCDI_PTR(outbuf,
      GET_VERSION_V5_OUT_BOARD_VERSION);

  snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
    le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
    le32_to_cpu(ver.dwords[2]),
    le32_to_cpu(ver.dwords[3]));

  devlink_info_version_running_put(req,
       DEVLINK_INFO_VERSION_GENERIC_BOARD_REV,
       buf);
 }

 if (flags & BIT(EFX_VER_FLAG(BUNDLE_VERSION))) {
  ver.dwords = (__le32 *)MCDI_PTR(outbuf,
      GET_VERSION_V5_OUT_BUNDLE_VERSION);

  snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
    le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
    le32_to_cpu(ver.dwords[2]),
    le32_to_cpu(ver.dwords[3]));

  devlink_info_version_running_put(req,
       DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID,
       buf);
 }
}

static int efx_devlink_info_running_versions(struct efx_nic *efx,
          struct devlink_info_req *req)
{
 MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_VERSION_V5_OUT_LEN);
 MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_VERSION_EXT_IN_LEN);
 char buf[EFX_MAX_VERSION_INFO_LEN];
 union {
  const __le32 *dwords;
  const __le16 *words;
  const char *str;
 } ver;
 size_t outlength;
 unsigned int flags;
 int rc;

 rc = efx_mcdi_rpc(efx, MC_CMD_GET_VERSION, inbuf, sizeof(inbuf),
     outbuf, sizeof(outbuf), &outlength);
 if (rc || outlength < MC_CMD_GET_VERSION_OUT_LEN) {
  netif_err(efx, drv, efx->net_dev,
     "mcdi MC_CMD_GET_VERSION failed\n");
  return rc;
 }

 /* Handle previous output */
 if (outlength < MC_CMD_GET_VERSION_V2_OUT_LEN) {
  ver.words = (__le16 *)MCDI_PTR(outbuf,
            GET_VERSION_EXT_OUT_VERSION);
  snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
    le16_to_cpu(ver.words[0]),
    le16_to_cpu(ver.words[1]),
    le16_to_cpu(ver.words[2]),
    le16_to_cpu(ver.words[3]));

  devlink_info_version_running_put(req,
       DEVLINK_INFO_VERSION_GENERIC_FW_MGMT,
       buf);
  return 0;
 }

 /* Handle V2 additions */
 flags = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_FLAGS);
 efx_devlink_info_running_v2(efx, req, flags, outbuf);

 if (outlength < MC_CMD_GET_VERSION_V3_OUT_LEN)
  return 0;

 /* Handle V3 additions */
 efx_devlink_info_running_v3(efx, req, flags, outbuf);

 if (outlength < MC_CMD_GET_VERSION_V4_OUT_LEN)
  return 0;

 /* Handle V4 additions */
 efx_devlink_info_running_v4(efx, req, flags, outbuf);

 if (outlength < MC_CMD_GET_VERSION_V5_OUT_LEN)
  return 0;

 /* Handle V5 additions */
 efx_devlink_info_running_v5(efx, req, flags, outbuf);

 return 0;
}

#define EFX_MAX_SERIALNUM_LEN (ETH_ALEN * 2 + 1)

static int efx_devlink_info_board_cfg(struct efx_nic *efx,
          struct devlink_info_req *req)
{
 char sn[EFX_MAX_SERIALNUM_LEN];
 u8 mac_address[ETH_ALEN];
 int rc;

 rc = efx_mcdi_get_board_cfg(efx, (u8 *)mac_address, NULL, NULL);
 if (!rc) {
  snprintf(sn, EFX_MAX_SERIALNUM_LEN, "%pm", mac_address);
  devlink_info_serial_number_put(req, sn);
 }
 return rc;
}

static int efx_devlink_info_get(struct devlink *devlink,
    struct devlink_info_req *req,
    struct netlink_ext_ack *extack)
{
 struct efx_devlink *devlink_private = devlink_priv(devlink);
 struct efx_nic *efx = devlink_private->efx;
 int err;

 /* Several different MCDI commands are used. We report if errors
 * happened through extack. Specific error information via system
 * messages inside the calls.
 */

 err = efx_devlink_info_board_cfg(efx, req);

 err |= efx_devlink_info_stored_versions(efx, req);

 err |= efx_devlink_info_running_versions(efx, req);

 if (err)
  NL_SET_ERR_MSG_MOD(extack, "Errors when getting device info. Check system messages");

 return 0;
}

static int efx_devlink_flash_update(struct devlink *devlink,
        struct devlink_flash_update_params *params,
        struct netlink_ext_ack *extack)
{
 struct efx_devlink *devlink_private = devlink_priv(devlink);
 struct efx_nic *efx = devlink_private->efx;

 return efx_reflash_flash_firmware(efx, params->fw, extack);
}

static const struct devlink_ops sfc_devlink_ops = {
 .supported_flash_update_params = 0,
 .flash_update   = efx_devlink_flash_update,
 .info_get   = efx_devlink_info_get,
};

#ifdef CONFIG_SFC_SRIOV
static struct devlink_port *ef100_set_devlink_port(struct efx_nic *efx, u32 idx)
{
 struct mae_mport_desc *mport;
 u32 id;
 int rc;

 if (!efx->mae)
  return NULL;

 if (efx_mae_lookup_mport(efx, idx, &id)) {
  /* This should not happen. */
  if (idx == MAE_MPORT_DESC_VF_IDX_NULL)
   pci_warn_once(efx->pci_dev, "No mport ID found for PF.\n");
  else
   pci_warn_once(efx->pci_dev, "No mport ID found for VF %u.\n",
          idx);
  return NULL;
 }

 mport = efx_mae_get_mport(efx, id);
 if (!mport) {
  /* This should not happen. */
  if (idx == MAE_MPORT_DESC_VF_IDX_NULL)
   pci_warn_once(efx->pci_dev, "No mport found for PF.\n");
  else
   pci_warn_once(efx->pci_dev, "No mport found for VF %u.\n",
          idx);
  return NULL;
 }

 rc = efx_devlink_add_port(efx, mport);
 if (rc) {
  if (idx == MAE_MPORT_DESC_VF_IDX_NULL)
   pci_warn(efx->pci_dev,
     "devlink port creation for PF failed.\n");
  else
   pci_warn(efx->pci_dev,
     "devlink_port creation for VF %u failed.\n",
     idx);
  return NULL;
 }

 return &mport->dl_port;
}

void ef100_rep_set_devlink_port(struct efx_rep *efv)
{
 efv->dl_port = ef100_set_devlink_port(efv->parent, efv->idx);
}

void ef100_pf_set_devlink_port(struct efx_nic *efx)
{
 efx->dl_port = ef100_set_devlink_port(efx, MAE_MPORT_DESC_VF_IDX_NULL);
}

void ef100_rep_unset_devlink_port(struct efx_rep *efv)
{
 efx_devlink_del_port(efv->dl_port);
}

void ef100_pf_unset_devlink_port(struct efx_nic *efx)
{
 efx_devlink_del_port(efx->dl_port);
}
#endif

void efx_fini_devlink_lock(struct efx_nic *efx)
{
 if (efx->devlink)
  devl_lock(efx->devlink);
}

void efx_fini_devlink_and_unlock(struct efx_nic *efx)
{
 if (efx->devlink) {
  devl_unregister(efx->devlink);
  devl_unlock(efx->devlink);
  devlink_free(efx->devlink);
  efx->devlink = NULL;
 }
}

int efx_probe_devlink_and_lock(struct efx_nic *efx)
{
 struct efx_devlink *devlink_private;

 if (efx->type->is_vf)
  return 0;

 efx->devlink = devlink_alloc(&sfc_devlink_ops,
         sizeof(struct efx_devlink),
         &efx->pci_dev->dev);
 if (!efx->devlink)
  return -ENOMEM;

 devl_lock(efx->devlink);
 devlink_private = devlink_priv(efx->devlink);
 devlink_private->efx = efx;

 devl_register(efx->devlink);

 return 0;
}

void efx_probe_devlink_unlock(struct efx_nic *efx)
{
 if (!efx->devlink)
  return;

 devl_unlock(efx->devlink);
}

Messung V0.5
C=99 H=99 G=98

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.