178 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright(c) 2023 Advanced Micro Devices, Inc */3 4#include "core.h"5#include <linux/pds/pds_auxbus.h>6 7static struct8pdsc_viftype *pdsc_dl_find_viftype_by_id(struct pdsc *pdsc,9 enum devlink_param_type dl_id)10{11 int vt;12 13 if (!pdsc->viftype_status)14 return NULL;15 16 for (vt = 0; vt < PDS_DEV_TYPE_MAX; vt++) {17 if (pdsc->viftype_status[vt].dl_id == dl_id)18 return &pdsc->viftype_status[vt];19 }20 21 return NULL;22}23 24int pdsc_dl_enable_get(struct devlink *dl, u32 id,25 struct devlink_param_gset_ctx *ctx)26{27 struct pdsc *pdsc = devlink_priv(dl);28 struct pdsc_viftype *vt_entry;29 30 vt_entry = pdsc_dl_find_viftype_by_id(pdsc, id);31 if (!vt_entry)32 return -ENOENT;33 34 ctx->val.vbool = vt_entry->enabled;35 36 return 0;37}38 39int pdsc_dl_enable_set(struct devlink *dl, u32 id,40 struct devlink_param_gset_ctx *ctx,41 struct netlink_ext_ack *extack)42{43 struct pdsc *pdsc = devlink_priv(dl);44 struct pdsc_viftype *vt_entry;45 int err = 0;46 int vf_id;47 48 vt_entry = pdsc_dl_find_viftype_by_id(pdsc, id);49 if (!vt_entry || !vt_entry->supported)50 return -EOPNOTSUPP;51 52 if (vt_entry->enabled == ctx->val.vbool)53 return 0;54 55 vt_entry->enabled = ctx->val.vbool;56 for (vf_id = 0; vf_id < pdsc->num_vfs; vf_id++) {57 struct pdsc *vf = pdsc->vfs[vf_id].vf;58 59 err = ctx->val.vbool ? pdsc_auxbus_dev_add(vf, pdsc) :60 pdsc_auxbus_dev_del(vf, pdsc);61 }62 63 return err;64}65 66int pdsc_dl_enable_validate(struct devlink *dl, u32 id,67 union devlink_param_value val,68 struct netlink_ext_ack *extack)69{70 struct pdsc *pdsc = devlink_priv(dl);71 struct pdsc_viftype *vt_entry;72 73 vt_entry = pdsc_dl_find_viftype_by_id(pdsc, id);74 if (!vt_entry || !vt_entry->supported)75 return -EOPNOTSUPP;76 77 if (!pdsc->viftype_status[vt_entry->vif_id].supported)78 return -ENODEV;79 80 return 0;81}82 83int pdsc_dl_flash_update(struct devlink *dl,84 struct devlink_flash_update_params *params,85 struct netlink_ext_ack *extack)86{87 struct pdsc *pdsc = devlink_priv(dl);88 89 return pdsc_firmware_update(pdsc, params->fw, extack);90}91 92static char *fw_slotnames[] = {93 "fw.goldfw",94 "fw.mainfwa",95 "fw.mainfwb",96};97 98int pdsc_dl_info_get(struct devlink *dl, struct devlink_info_req *req,99 struct netlink_ext_ack *extack)100{101 union pds_core_dev_cmd cmd = {102 .fw_control.opcode = PDS_CORE_CMD_FW_CONTROL,103 .fw_control.oper = PDS_CORE_FW_GET_LIST,104 };105 struct pds_core_fw_list_info fw_list;106 struct pdsc *pdsc = devlink_priv(dl);107 union pds_core_dev_comp comp;108 char buf[32];109 int listlen;110 int err;111 int i;112 113 mutex_lock(&pdsc->devcmd_lock);114 err = pdsc_devcmd_locked(pdsc, &cmd, &comp, pdsc->devcmd_timeout * 2);115 if (!err)116 memcpy_fromio(&fw_list, pdsc->cmd_regs->data, sizeof(fw_list));117 mutex_unlock(&pdsc->devcmd_lock);118 if (err && err != -EIO)119 return err;120 121 listlen = fw_list.num_fw_slots;122 for (i = 0; i < listlen; i++) {123 if (i < ARRAY_SIZE(fw_slotnames))124 strscpy(buf, fw_slotnames[i], sizeof(buf));125 else126 snprintf(buf, sizeof(buf), "fw.slot_%d", i);127 err = devlink_info_version_stored_put(req, buf,128 fw_list.fw_names[i].fw_version);129 if (err)130 return err;131 }132 133 err = devlink_info_version_running_put(req,134 DEVLINK_INFO_VERSION_GENERIC_FW,135 pdsc->dev_info.fw_version);136 if (err)137 return err;138 139 snprintf(buf, sizeof(buf), "0x%x", pdsc->dev_info.asic_type);140 err = devlink_info_version_fixed_put(req,141 DEVLINK_INFO_VERSION_GENERIC_ASIC_ID,142 buf);143 if (err)144 return err;145 146 snprintf(buf, sizeof(buf), "0x%x", pdsc->dev_info.asic_rev);147 err = devlink_info_version_fixed_put(req,148 DEVLINK_INFO_VERSION_GENERIC_ASIC_REV,149 buf);150 if (err)151 return err;152 153 return devlink_info_serial_number_put(req, pdsc->dev_info.serial_num);154}155 156int pdsc_fw_reporter_diagnose(struct devlink_health_reporter *reporter,157 struct devlink_fmsg *fmsg,158 struct netlink_ext_ack *extack)159{160 struct pdsc *pdsc = devlink_health_reporter_priv(reporter);161 162 mutex_lock(&pdsc->config_lock);163 if (test_bit(PDSC_S_FW_DEAD, &pdsc->state))164 devlink_fmsg_string_pair_put(fmsg, "Status", "dead");165 else if (!pdsc_is_fw_good(pdsc))166 devlink_fmsg_string_pair_put(fmsg, "Status", "unhealthy");167 else168 devlink_fmsg_string_pair_put(fmsg, "Status", "healthy");169 mutex_unlock(&pdsc->config_lock);170 171 devlink_fmsg_u32_pair_put(fmsg, "State",172 pdsc->fw_status & ~PDS_CORE_FW_STS_F_GENERATION);173 devlink_fmsg_u32_pair_put(fmsg, "Generation", pdsc->fw_generation >> 4);174 devlink_fmsg_u32_pair_put(fmsg, "Recoveries", pdsc->fw_recoveries);175 176 return 0;177}178