]> Git Repo - J-linux.git/blob - drivers/net/ethernet/amd/pds_core/devlink.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / drivers / net / ethernet / amd / pds_core / devlink.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
7 static struct
8 pdsc_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
24 int 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
39 int 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
66 int 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
83 int 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
92 static char *fw_slotnames[] = {
93         "fw.goldfw",
94         "fw.mainfwa",
95         "fw.mainfwb",
96 };
97
98 int 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                 else
126                         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
156 int 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         else
168                 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 }
This page took 0.037595 seconds and 4 git commands to generate.