File Index
Files and directories
Sign in
FILE

devlink.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/amd/pds_core/devlink.c C
  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}
~/ Read-only file preview.