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