1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2023 Advanced Micro Devices, Inc */
5 #include <linux/pds/pds_auxbus.h>
8 pdsc_viftype
*pdsc_dl_find_viftype_by_id(struct pdsc
*pdsc
,
9 enum devlink_param_type dl_id
)
13 if (!pdsc
->viftype_status
)
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
];
24 int pdsc_dl_enable_get(struct devlink
*dl
, u32 id
,
25 struct devlink_param_gset_ctx
*ctx
)
27 struct pdsc
*pdsc
= devlink_priv(dl
);
28 struct pdsc_viftype
*vt_entry
;
30 vt_entry
= pdsc_dl_find_viftype_by_id(pdsc
, id
);
34 ctx
->val
.vbool
= vt_entry
->enabled
;
39 int pdsc_dl_enable_set(struct devlink
*dl
, u32 id
,
40 struct devlink_param_gset_ctx
*ctx
)
42 struct pdsc
*pdsc
= devlink_priv(dl
);
43 struct pdsc_viftype
*vt_entry
;
47 vt_entry
= pdsc_dl_find_viftype_by_id(pdsc
, id
);
48 if (!vt_entry
|| !vt_entry
->supported
)
51 if (vt_entry
->enabled
== ctx
->val
.vbool
)
54 vt_entry
->enabled
= ctx
->val
.vbool
;
55 for (vf_id
= 0; vf_id
< pdsc
->num_vfs
; vf_id
++) {
56 struct pdsc
*vf
= pdsc
->vfs
[vf_id
].vf
;
58 err
= ctx
->val
.vbool
? pdsc_auxbus_dev_add(vf
, pdsc
) :
59 pdsc_auxbus_dev_del(vf
, pdsc
);
65 int pdsc_dl_enable_validate(struct devlink
*dl
, u32 id
,
66 union devlink_param_value val
,
67 struct netlink_ext_ack
*extack
)
69 struct pdsc
*pdsc
= devlink_priv(dl
);
70 struct pdsc_viftype
*vt_entry
;
72 vt_entry
= pdsc_dl_find_viftype_by_id(pdsc
, id
);
73 if (!vt_entry
|| !vt_entry
->supported
)
76 if (!pdsc
->viftype_status
[vt_entry
->vif_id
].supported
)
82 int pdsc_dl_flash_update(struct devlink
*dl
,
83 struct devlink_flash_update_params
*params
,
84 struct netlink_ext_ack
*extack
)
86 struct pdsc
*pdsc
= devlink_priv(dl
);
88 return pdsc_firmware_update(pdsc
, params
->fw
, extack
);
91 static char *fw_slotnames
[] = {
97 int pdsc_dl_info_get(struct devlink
*dl
, struct devlink_info_req
*req
,
98 struct netlink_ext_ack
*extack
)
100 union pds_core_dev_cmd cmd
= {
101 .fw_control
.opcode
= PDS_CORE_CMD_FW_CONTROL
,
102 .fw_control
.oper
= PDS_CORE_FW_GET_LIST
,
104 struct pds_core_fw_list_info fw_list
;
105 struct pdsc
*pdsc
= devlink_priv(dl
);
106 union pds_core_dev_comp comp
;
112 mutex_lock(&pdsc
->devcmd_lock
);
113 err
= pdsc_devcmd_locked(pdsc
, &cmd
, &comp
, pdsc
->devcmd_timeout
* 2);
114 memcpy_fromio(&fw_list
, pdsc
->cmd_regs
->data
, sizeof(fw_list
));
115 mutex_unlock(&pdsc
->devcmd_lock
);
116 if (err
&& err
!= -EIO
)
119 listlen
= fw_list
.num_fw_slots
;
120 for (i
= 0; i
< listlen
; i
++) {
121 if (i
< ARRAY_SIZE(fw_slotnames
))
122 strscpy(buf
, fw_slotnames
[i
], sizeof(buf
));
124 snprintf(buf
, sizeof(buf
), "fw.slot_%d", i
);
125 err
= devlink_info_version_stored_put(req
, buf
,
126 fw_list
.fw_names
[i
].fw_version
);
131 err
= devlink_info_version_running_put(req
,
132 DEVLINK_INFO_VERSION_GENERIC_FW
,
133 pdsc
->dev_info
.fw_version
);
137 snprintf(buf
, sizeof(buf
), "0x%x", pdsc
->dev_info
.asic_type
);
138 err
= devlink_info_version_fixed_put(req
,
139 DEVLINK_INFO_VERSION_GENERIC_ASIC_ID
,
144 snprintf(buf
, sizeof(buf
), "0x%x", pdsc
->dev_info
.asic_rev
);
145 err
= devlink_info_version_fixed_put(req
,
146 DEVLINK_INFO_VERSION_GENERIC_ASIC_REV
,
151 return devlink_info_serial_number_put(req
, pdsc
->dev_info
.serial_num
);
154 int pdsc_fw_reporter_diagnose(struct devlink_health_reporter
*reporter
,
155 struct devlink_fmsg
*fmsg
,
156 struct netlink_ext_ack
*extack
)
158 struct pdsc
*pdsc
= devlink_health_reporter_priv(reporter
);
160 mutex_lock(&pdsc
->config_lock
);
161 if (test_bit(PDSC_S_FW_DEAD
, &pdsc
->state
))
162 devlink_fmsg_string_pair_put(fmsg
, "Status", "dead");
163 else if (!pdsc_is_fw_good(pdsc
))
164 devlink_fmsg_string_pair_put(fmsg
, "Status", "unhealthy");
166 devlink_fmsg_string_pair_put(fmsg
, "Status", "healthy");
167 mutex_unlock(&pdsc
->config_lock
);
169 devlink_fmsg_u32_pair_put(fmsg
, "State",
170 pdsc
->fw_status
& ~PDS_CORE_FW_STS_F_GENERATION
);
171 devlink_fmsg_u32_pair_put(fmsg
, "Generation", pdsc
->fw_generation
>> 4);
172 devlink_fmsg_u32_pair_put(fmsg
, "Recoveries", pdsc
->fw_recoveries
);