1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /* Copyright (c) 2020, Intel Corporation. */
3*4882a593Smuzhiyun
4*4882a593Smuzhiyun #include "ice.h"
5*4882a593Smuzhiyun #include "ice_lib.h"
6*4882a593Smuzhiyun #include "ice_devlink.h"
7*4882a593Smuzhiyun #include "ice_fw_update.h"
8*4882a593Smuzhiyun
ice_info_get_dsn(struct ice_pf * pf,char * buf,size_t len)9*4882a593Smuzhiyun static void ice_info_get_dsn(struct ice_pf *pf, char *buf, size_t len)
10*4882a593Smuzhiyun {
11*4882a593Smuzhiyun u8 dsn[8];
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun /* Copy the DSN into an array in Big Endian format */
14*4882a593Smuzhiyun put_unaligned_be64(pci_get_dsn(pf->pdev), dsn);
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun snprintf(buf, len, "%8phD", dsn);
17*4882a593Smuzhiyun }
18*4882a593Smuzhiyun
ice_info_pba(struct ice_pf * pf,char * buf,size_t len)19*4882a593Smuzhiyun static int ice_info_pba(struct ice_pf *pf, char *buf, size_t len)
20*4882a593Smuzhiyun {
21*4882a593Smuzhiyun struct ice_hw *hw = &pf->hw;
22*4882a593Smuzhiyun enum ice_status status;
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun status = ice_read_pba_string(hw, (u8 *)buf, len);
25*4882a593Smuzhiyun if (status)
26*4882a593Smuzhiyun /* We failed to locate the PBA, so just skip this entry */
27*4882a593Smuzhiyun dev_dbg(ice_pf_to_dev(pf), "Failed to read Product Board Assembly string, status %s\n",
28*4882a593Smuzhiyun ice_stat_str(status));
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun return 0;
31*4882a593Smuzhiyun }
32*4882a593Smuzhiyun
ice_info_fw_mgmt(struct ice_pf * pf,char * buf,size_t len)33*4882a593Smuzhiyun static int ice_info_fw_mgmt(struct ice_pf *pf, char *buf, size_t len)
34*4882a593Smuzhiyun {
35*4882a593Smuzhiyun struct ice_hw *hw = &pf->hw;
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun snprintf(buf, len, "%u.%u.%u", hw->fw_maj_ver, hw->fw_min_ver,
38*4882a593Smuzhiyun hw->fw_patch);
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun return 0;
41*4882a593Smuzhiyun }
42*4882a593Smuzhiyun
ice_info_fw_api(struct ice_pf * pf,char * buf,size_t len)43*4882a593Smuzhiyun static int ice_info_fw_api(struct ice_pf *pf, char *buf, size_t len)
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun struct ice_hw *hw = &pf->hw;
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun snprintf(buf, len, "%u.%u", hw->api_maj_ver, hw->api_min_ver);
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun return 0;
50*4882a593Smuzhiyun }
51*4882a593Smuzhiyun
ice_info_fw_build(struct ice_pf * pf,char * buf,size_t len)52*4882a593Smuzhiyun static int ice_info_fw_build(struct ice_pf *pf, char *buf, size_t len)
53*4882a593Smuzhiyun {
54*4882a593Smuzhiyun struct ice_hw *hw = &pf->hw;
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun snprintf(buf, len, "0x%08x", hw->fw_build);
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun return 0;
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun
ice_info_orom_ver(struct ice_pf * pf,char * buf,size_t len)61*4882a593Smuzhiyun static int ice_info_orom_ver(struct ice_pf *pf, char *buf, size_t len)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun struct ice_orom_info *orom = &pf->hw.nvm.orom;
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun snprintf(buf, len, "%u.%u.%u", orom->major, orom->build, orom->patch);
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun return 0;
68*4882a593Smuzhiyun }
69*4882a593Smuzhiyun
ice_info_nvm_ver(struct ice_pf * pf,char * buf,size_t len)70*4882a593Smuzhiyun static int ice_info_nvm_ver(struct ice_pf *pf, char *buf, size_t len)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun struct ice_nvm_info *nvm = &pf->hw.nvm;
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun snprintf(buf, len, "%x.%02x", nvm->major_ver, nvm->minor_ver);
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun return 0;
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun
ice_info_eetrack(struct ice_pf * pf,char * buf,size_t len)79*4882a593Smuzhiyun static int ice_info_eetrack(struct ice_pf *pf, char *buf, size_t len)
80*4882a593Smuzhiyun {
81*4882a593Smuzhiyun struct ice_nvm_info *nvm = &pf->hw.nvm;
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun snprintf(buf, len, "0x%08x", nvm->eetrack);
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun return 0;
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun
ice_info_ddp_pkg_name(struct ice_pf * pf,char * buf,size_t len)88*4882a593Smuzhiyun static int ice_info_ddp_pkg_name(struct ice_pf *pf, char *buf, size_t len)
89*4882a593Smuzhiyun {
90*4882a593Smuzhiyun struct ice_hw *hw = &pf->hw;
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun snprintf(buf, len, "%s", hw->active_pkg_name);
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun return 0;
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun
ice_info_ddp_pkg_version(struct ice_pf * pf,char * buf,size_t len)97*4882a593Smuzhiyun static int ice_info_ddp_pkg_version(struct ice_pf *pf, char *buf, size_t len)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun struct ice_pkg_ver *pkg = &pf->hw.active_pkg_ver;
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun snprintf(buf, len, "%u.%u.%u.%u", pkg->major, pkg->minor, pkg->update,
102*4882a593Smuzhiyun pkg->draft);
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun return 0;
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun
ice_info_ddp_pkg_bundle_id(struct ice_pf * pf,char * buf,size_t len)107*4882a593Smuzhiyun static int ice_info_ddp_pkg_bundle_id(struct ice_pf *pf, char *buf, size_t len)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun snprintf(buf, len, "0x%08x", pf->hw.active_track_id);
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun return 0;
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun
ice_info_netlist_ver(struct ice_pf * pf,char * buf,size_t len)114*4882a593Smuzhiyun static int ice_info_netlist_ver(struct ice_pf *pf, char *buf, size_t len)
115*4882a593Smuzhiyun {
116*4882a593Smuzhiyun struct ice_netlist_ver_info *netlist = &pf->hw.netlist_ver;
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun /* The netlist version fields are BCD formatted */
119*4882a593Smuzhiyun snprintf(buf, len, "%x.%x.%x-%x.%x.%x", netlist->major, netlist->minor,
120*4882a593Smuzhiyun netlist->type >> 16, netlist->type & 0xFFFF, netlist->rev,
121*4882a593Smuzhiyun netlist->cust_ver);
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun return 0;
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun
ice_info_netlist_build(struct ice_pf * pf,char * buf,size_t len)126*4882a593Smuzhiyun static int ice_info_netlist_build(struct ice_pf *pf, char *buf, size_t len)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun struct ice_netlist_ver_info *netlist = &pf->hw.netlist_ver;
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun snprintf(buf, len, "0x%08x", netlist->hash);
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun return 0;
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun #define fixed(key, getter) { ICE_VERSION_FIXED, key, getter }
136*4882a593Smuzhiyun #define running(key, getter) { ICE_VERSION_RUNNING, key, getter }
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun enum ice_version_type {
139*4882a593Smuzhiyun ICE_VERSION_FIXED,
140*4882a593Smuzhiyun ICE_VERSION_RUNNING,
141*4882a593Smuzhiyun ICE_VERSION_STORED,
142*4882a593Smuzhiyun };
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun static const struct ice_devlink_version {
145*4882a593Smuzhiyun enum ice_version_type type;
146*4882a593Smuzhiyun const char *key;
147*4882a593Smuzhiyun int (*getter)(struct ice_pf *pf, char *buf, size_t len);
148*4882a593Smuzhiyun } ice_devlink_versions[] = {
149*4882a593Smuzhiyun fixed(DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, ice_info_pba),
150*4882a593Smuzhiyun running(DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, ice_info_fw_mgmt),
151*4882a593Smuzhiyun running("fw.mgmt.api", ice_info_fw_api),
152*4882a593Smuzhiyun running("fw.mgmt.build", ice_info_fw_build),
153*4882a593Smuzhiyun running(DEVLINK_INFO_VERSION_GENERIC_FW_UNDI, ice_info_orom_ver),
154*4882a593Smuzhiyun running("fw.psid.api", ice_info_nvm_ver),
155*4882a593Smuzhiyun running(DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID, ice_info_eetrack),
156*4882a593Smuzhiyun running("fw.app.name", ice_info_ddp_pkg_name),
157*4882a593Smuzhiyun running(DEVLINK_INFO_VERSION_GENERIC_FW_APP, ice_info_ddp_pkg_version),
158*4882a593Smuzhiyun running("fw.app.bundle_id", ice_info_ddp_pkg_bundle_id),
159*4882a593Smuzhiyun running("fw.netlist", ice_info_netlist_ver),
160*4882a593Smuzhiyun running("fw.netlist.build", ice_info_netlist_build),
161*4882a593Smuzhiyun };
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun /**
164*4882a593Smuzhiyun * ice_devlink_info_get - .info_get devlink handler
165*4882a593Smuzhiyun * @devlink: devlink instance structure
166*4882a593Smuzhiyun * @req: the devlink info request
167*4882a593Smuzhiyun * @extack: extended netdev ack structure
168*4882a593Smuzhiyun *
169*4882a593Smuzhiyun * Callback for the devlink .info_get operation. Reports information about the
170*4882a593Smuzhiyun * device.
171*4882a593Smuzhiyun *
172*4882a593Smuzhiyun * Return: zero on success or an error code on failure.
173*4882a593Smuzhiyun */
ice_devlink_info_get(struct devlink * devlink,struct devlink_info_req * req,struct netlink_ext_ack * extack)174*4882a593Smuzhiyun static int ice_devlink_info_get(struct devlink *devlink,
175*4882a593Smuzhiyun struct devlink_info_req *req,
176*4882a593Smuzhiyun struct netlink_ext_ack *extack)
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun struct ice_pf *pf = devlink_priv(devlink);
179*4882a593Smuzhiyun char buf[100];
180*4882a593Smuzhiyun size_t i;
181*4882a593Smuzhiyun int err;
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun err = devlink_info_driver_name_put(req, KBUILD_MODNAME);
184*4882a593Smuzhiyun if (err) {
185*4882a593Smuzhiyun NL_SET_ERR_MSG_MOD(extack, "Unable to set driver name");
186*4882a593Smuzhiyun return err;
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun ice_info_get_dsn(pf, buf, sizeof(buf));
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun err = devlink_info_serial_number_put(req, buf);
192*4882a593Smuzhiyun if (err) {
193*4882a593Smuzhiyun NL_SET_ERR_MSG_MOD(extack, "Unable to set serial number");
194*4882a593Smuzhiyun return err;
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(ice_devlink_versions); i++) {
198*4882a593Smuzhiyun enum ice_version_type type = ice_devlink_versions[i].type;
199*4882a593Smuzhiyun const char *key = ice_devlink_versions[i].key;
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun err = ice_devlink_versions[i].getter(pf, buf, sizeof(buf));
202*4882a593Smuzhiyun if (err) {
203*4882a593Smuzhiyun NL_SET_ERR_MSG_MOD(extack, "Unable to obtain version info");
204*4882a593Smuzhiyun return err;
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun switch (type) {
208*4882a593Smuzhiyun case ICE_VERSION_FIXED:
209*4882a593Smuzhiyun err = devlink_info_version_fixed_put(req, key, buf);
210*4882a593Smuzhiyun if (err) {
211*4882a593Smuzhiyun NL_SET_ERR_MSG_MOD(extack, "Unable to set fixed version");
212*4882a593Smuzhiyun return err;
213*4882a593Smuzhiyun }
214*4882a593Smuzhiyun break;
215*4882a593Smuzhiyun case ICE_VERSION_RUNNING:
216*4882a593Smuzhiyun err = devlink_info_version_running_put(req, key, buf);
217*4882a593Smuzhiyun if (err) {
218*4882a593Smuzhiyun NL_SET_ERR_MSG_MOD(extack, "Unable to set running version");
219*4882a593Smuzhiyun return err;
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun break;
222*4882a593Smuzhiyun case ICE_VERSION_STORED:
223*4882a593Smuzhiyun err = devlink_info_version_stored_put(req, key, buf);
224*4882a593Smuzhiyun if (err) {
225*4882a593Smuzhiyun NL_SET_ERR_MSG_MOD(extack, "Unable to set stored version");
226*4882a593Smuzhiyun return err;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun break;
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun return 0;
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun /**
236*4882a593Smuzhiyun * ice_devlink_flash_update - Update firmware stored in flash on the device
237*4882a593Smuzhiyun * @devlink: pointer to devlink associated with device to update
238*4882a593Smuzhiyun * @params: flash update parameters
239*4882a593Smuzhiyun * @extack: netlink extended ACK structure
240*4882a593Smuzhiyun *
241*4882a593Smuzhiyun * Perform a device flash update. The bulk of the update logic is contained
242*4882a593Smuzhiyun * within the ice_flash_pldm_image function.
243*4882a593Smuzhiyun *
244*4882a593Smuzhiyun * Returns: zero on success, or an error code on failure.
245*4882a593Smuzhiyun */
246*4882a593Smuzhiyun static int
ice_devlink_flash_update(struct devlink * devlink,struct devlink_flash_update_params * params,struct netlink_ext_ack * extack)247*4882a593Smuzhiyun ice_devlink_flash_update(struct devlink *devlink,
248*4882a593Smuzhiyun struct devlink_flash_update_params *params,
249*4882a593Smuzhiyun struct netlink_ext_ack *extack)
250*4882a593Smuzhiyun {
251*4882a593Smuzhiyun struct ice_pf *pf = devlink_priv(devlink);
252*4882a593Smuzhiyun struct device *dev = &pf->pdev->dev;
253*4882a593Smuzhiyun struct ice_hw *hw = &pf->hw;
254*4882a593Smuzhiyun const struct firmware *fw;
255*4882a593Smuzhiyun u8 preservation;
256*4882a593Smuzhiyun int err;
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun if (!params->overwrite_mask) {
259*4882a593Smuzhiyun /* preserve all settings and identifiers */
260*4882a593Smuzhiyun preservation = ICE_AQC_NVM_PRESERVE_ALL;
261*4882a593Smuzhiyun } else if (params->overwrite_mask == DEVLINK_FLASH_OVERWRITE_SETTINGS) {
262*4882a593Smuzhiyun /* overwrite settings, but preserve the vital device identifiers */
263*4882a593Smuzhiyun preservation = ICE_AQC_NVM_PRESERVE_SELECTED;
264*4882a593Smuzhiyun } else if (params->overwrite_mask == (DEVLINK_FLASH_OVERWRITE_SETTINGS |
265*4882a593Smuzhiyun DEVLINK_FLASH_OVERWRITE_IDENTIFIERS)) {
266*4882a593Smuzhiyun /* overwrite both settings and identifiers, preserve nothing */
267*4882a593Smuzhiyun preservation = ICE_AQC_NVM_NO_PRESERVATION;
268*4882a593Smuzhiyun } else {
269*4882a593Smuzhiyun NL_SET_ERR_MSG_MOD(extack, "Requested overwrite mask is not supported");
270*4882a593Smuzhiyun return -EOPNOTSUPP;
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun if (!hw->dev_caps.common_cap.nvm_unified_update) {
274*4882a593Smuzhiyun NL_SET_ERR_MSG_MOD(extack, "Current firmware does not support unified update");
275*4882a593Smuzhiyun return -EOPNOTSUPP;
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun err = ice_check_for_pending_update(pf, NULL, extack);
279*4882a593Smuzhiyun if (err)
280*4882a593Smuzhiyun return err;
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun err = request_firmware(&fw, params->file_name, dev);
283*4882a593Smuzhiyun if (err) {
284*4882a593Smuzhiyun NL_SET_ERR_MSG_MOD(extack, "Unable to read file from disk");
285*4882a593Smuzhiyun return err;
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun dev_dbg(dev, "Beginning flash update with file '%s'\n", params->file_name);
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun devlink_flash_update_begin_notify(devlink);
291*4882a593Smuzhiyun devlink_flash_update_status_notify(devlink, "Preparing to flash", NULL, 0, 0);
292*4882a593Smuzhiyun err = ice_flash_pldm_image(pf, fw, preservation, extack);
293*4882a593Smuzhiyun devlink_flash_update_end_notify(devlink);
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun release_firmware(fw);
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun return err;
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun static const struct devlink_ops ice_devlink_ops = {
301*4882a593Smuzhiyun .supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK,
302*4882a593Smuzhiyun .info_get = ice_devlink_info_get,
303*4882a593Smuzhiyun .flash_update = ice_devlink_flash_update,
304*4882a593Smuzhiyun };
305*4882a593Smuzhiyun
ice_devlink_free(void * devlink_ptr)306*4882a593Smuzhiyun static void ice_devlink_free(void *devlink_ptr)
307*4882a593Smuzhiyun {
308*4882a593Smuzhiyun devlink_free((struct devlink *)devlink_ptr);
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun /**
312*4882a593Smuzhiyun * ice_allocate_pf - Allocate devlink and return PF structure pointer
313*4882a593Smuzhiyun * @dev: the device to allocate for
314*4882a593Smuzhiyun *
315*4882a593Smuzhiyun * Allocate a devlink instance for this device and return the private area as
316*4882a593Smuzhiyun * the PF structure. The devlink memory is kept track of through devres by
317*4882a593Smuzhiyun * adding an action to remove it when unwinding.
318*4882a593Smuzhiyun */
ice_allocate_pf(struct device * dev)319*4882a593Smuzhiyun struct ice_pf *ice_allocate_pf(struct device *dev)
320*4882a593Smuzhiyun {
321*4882a593Smuzhiyun struct devlink *devlink;
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun devlink = devlink_alloc(&ice_devlink_ops, sizeof(struct ice_pf));
324*4882a593Smuzhiyun if (!devlink)
325*4882a593Smuzhiyun return NULL;
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun /* Add an action to teardown the devlink when unwinding the driver */
328*4882a593Smuzhiyun if (devm_add_action(dev, ice_devlink_free, devlink)) {
329*4882a593Smuzhiyun devlink_free(devlink);
330*4882a593Smuzhiyun return NULL;
331*4882a593Smuzhiyun }
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun return devlink_priv(devlink);
334*4882a593Smuzhiyun }
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun /**
337*4882a593Smuzhiyun * ice_devlink_register - Register devlink interface for this PF
338*4882a593Smuzhiyun * @pf: the PF to register the devlink for.
339*4882a593Smuzhiyun *
340*4882a593Smuzhiyun * Register the devlink instance associated with this physical function.
341*4882a593Smuzhiyun *
342*4882a593Smuzhiyun * Return: zero on success or an error code on failure.
343*4882a593Smuzhiyun */
ice_devlink_register(struct ice_pf * pf)344*4882a593Smuzhiyun int ice_devlink_register(struct ice_pf *pf)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun struct devlink *devlink = priv_to_devlink(pf);
347*4882a593Smuzhiyun struct device *dev = ice_pf_to_dev(pf);
348*4882a593Smuzhiyun int err;
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun err = devlink_register(devlink, dev);
351*4882a593Smuzhiyun if (err) {
352*4882a593Smuzhiyun dev_err(dev, "devlink registration failed: %d\n", err);
353*4882a593Smuzhiyun return err;
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun return 0;
357*4882a593Smuzhiyun }
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun /**
360*4882a593Smuzhiyun * ice_devlink_unregister - Unregister devlink resources for this PF.
361*4882a593Smuzhiyun * @pf: the PF structure to cleanup
362*4882a593Smuzhiyun *
363*4882a593Smuzhiyun * Releases resources used by devlink and cleans up associated memory.
364*4882a593Smuzhiyun */
ice_devlink_unregister(struct ice_pf * pf)365*4882a593Smuzhiyun void ice_devlink_unregister(struct ice_pf *pf)
366*4882a593Smuzhiyun {
367*4882a593Smuzhiyun devlink_unregister(priv_to_devlink(pf));
368*4882a593Smuzhiyun }
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun /**
371*4882a593Smuzhiyun * ice_devlink_create_port - Create a devlink port for this VSI
372*4882a593Smuzhiyun * @vsi: the VSI to create a port for
373*4882a593Smuzhiyun *
374*4882a593Smuzhiyun * Create and register a devlink_port for this VSI.
375*4882a593Smuzhiyun *
376*4882a593Smuzhiyun * Return: zero on success or an error code on failure.
377*4882a593Smuzhiyun */
ice_devlink_create_port(struct ice_vsi * vsi)378*4882a593Smuzhiyun int ice_devlink_create_port(struct ice_vsi *vsi)
379*4882a593Smuzhiyun {
380*4882a593Smuzhiyun struct devlink_port_attrs attrs = {};
381*4882a593Smuzhiyun struct ice_port_info *pi;
382*4882a593Smuzhiyun struct devlink *devlink;
383*4882a593Smuzhiyun struct device *dev;
384*4882a593Smuzhiyun struct ice_pf *pf;
385*4882a593Smuzhiyun int err;
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun /* Currently we only create devlink_port instances for PF VSIs */
388*4882a593Smuzhiyun if (vsi->type != ICE_VSI_PF)
389*4882a593Smuzhiyun return -EINVAL;
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun pf = vsi->back;
392*4882a593Smuzhiyun devlink = priv_to_devlink(pf);
393*4882a593Smuzhiyun dev = ice_pf_to_dev(pf);
394*4882a593Smuzhiyun pi = pf->hw.port_info;
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
397*4882a593Smuzhiyun attrs.phys.port_number = pi->lport;
398*4882a593Smuzhiyun devlink_port_attrs_set(&vsi->devlink_port, &attrs);
399*4882a593Smuzhiyun err = devlink_port_register(devlink, &vsi->devlink_port, vsi->idx);
400*4882a593Smuzhiyun if (err) {
401*4882a593Smuzhiyun dev_err(dev, "devlink_port_register failed: %d\n", err);
402*4882a593Smuzhiyun return err;
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun vsi->devlink_port_registered = true;
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun return 0;
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun /**
411*4882a593Smuzhiyun * ice_devlink_destroy_port - Destroy the devlink_port for this VSI
412*4882a593Smuzhiyun * @vsi: the VSI to cleanup
413*4882a593Smuzhiyun *
414*4882a593Smuzhiyun * Unregisters the devlink_port structure associated with this VSI.
415*4882a593Smuzhiyun */
ice_devlink_destroy_port(struct ice_vsi * vsi)416*4882a593Smuzhiyun void ice_devlink_destroy_port(struct ice_vsi *vsi)
417*4882a593Smuzhiyun {
418*4882a593Smuzhiyun if (!vsi->devlink_port_registered)
419*4882a593Smuzhiyun return;
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun devlink_port_type_clear(&vsi->devlink_port);
422*4882a593Smuzhiyun devlink_port_unregister(&vsi->devlink_port);
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun vsi->devlink_port_registered = false;
425*4882a593Smuzhiyun }
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun /**
428*4882a593Smuzhiyun * ice_devlink_nvm_snapshot - Capture a snapshot of the Shadow RAM contents
429*4882a593Smuzhiyun * @devlink: the devlink instance
430*4882a593Smuzhiyun * @ops: the devlink region being snapshotted
431*4882a593Smuzhiyun * @extack: extended ACK response structure
432*4882a593Smuzhiyun * @data: on exit points to snapshot data buffer
433*4882a593Smuzhiyun *
434*4882a593Smuzhiyun * This function is called in response to the DEVLINK_CMD_REGION_TRIGGER for
435*4882a593Smuzhiyun * the shadow-ram devlink region. It captures a snapshot of the shadow ram
436*4882a593Smuzhiyun * contents. This snapshot can later be viewed via the devlink-region
437*4882a593Smuzhiyun * interface.
438*4882a593Smuzhiyun *
439*4882a593Smuzhiyun * @returns zero on success, and updates the data pointer. Returns a non-zero
440*4882a593Smuzhiyun * error code on failure.
441*4882a593Smuzhiyun */
ice_devlink_nvm_snapshot(struct devlink * devlink,const struct devlink_region_ops * ops,struct netlink_ext_ack * extack,u8 ** data)442*4882a593Smuzhiyun static int ice_devlink_nvm_snapshot(struct devlink *devlink,
443*4882a593Smuzhiyun const struct devlink_region_ops *ops,
444*4882a593Smuzhiyun struct netlink_ext_ack *extack, u8 **data)
445*4882a593Smuzhiyun {
446*4882a593Smuzhiyun struct ice_pf *pf = devlink_priv(devlink);
447*4882a593Smuzhiyun struct device *dev = ice_pf_to_dev(pf);
448*4882a593Smuzhiyun struct ice_hw *hw = &pf->hw;
449*4882a593Smuzhiyun enum ice_status status;
450*4882a593Smuzhiyun void *nvm_data;
451*4882a593Smuzhiyun u32 nvm_size;
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun nvm_size = hw->nvm.flash_size;
454*4882a593Smuzhiyun nvm_data = vzalloc(nvm_size);
455*4882a593Smuzhiyun if (!nvm_data)
456*4882a593Smuzhiyun return -ENOMEM;
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun status = ice_acquire_nvm(hw, ICE_RES_READ);
459*4882a593Smuzhiyun if (status) {
460*4882a593Smuzhiyun dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n",
461*4882a593Smuzhiyun status, hw->adminq.sq_last_status);
462*4882a593Smuzhiyun NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore");
463*4882a593Smuzhiyun vfree(nvm_data);
464*4882a593Smuzhiyun return -EIO;
465*4882a593Smuzhiyun }
466*4882a593Smuzhiyun
467*4882a593Smuzhiyun status = ice_read_flat_nvm(hw, 0, &nvm_size, nvm_data, false);
468*4882a593Smuzhiyun if (status) {
469*4882a593Smuzhiyun dev_dbg(dev, "ice_read_flat_nvm failed after reading %u bytes, err %d aq_err %d\n",
470*4882a593Smuzhiyun nvm_size, status, hw->adminq.sq_last_status);
471*4882a593Smuzhiyun NL_SET_ERR_MSG_MOD(extack, "Failed to read NVM contents");
472*4882a593Smuzhiyun ice_release_nvm(hw);
473*4882a593Smuzhiyun vfree(nvm_data);
474*4882a593Smuzhiyun return -EIO;
475*4882a593Smuzhiyun }
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun ice_release_nvm(hw);
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun *data = nvm_data;
480*4882a593Smuzhiyun
481*4882a593Smuzhiyun return 0;
482*4882a593Smuzhiyun }
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun /**
485*4882a593Smuzhiyun * ice_devlink_devcaps_snapshot - Capture snapshot of device capabilities
486*4882a593Smuzhiyun * @devlink: the devlink instance
487*4882a593Smuzhiyun * @ops: the devlink region being snapshotted
488*4882a593Smuzhiyun * @extack: extended ACK response structure
489*4882a593Smuzhiyun * @data: on exit points to snapshot data buffer
490*4882a593Smuzhiyun *
491*4882a593Smuzhiyun * This function is called in response to the DEVLINK_CMD_REGION_TRIGGER for
492*4882a593Smuzhiyun * the device-caps devlink region. It captures a snapshot of the device
493*4882a593Smuzhiyun * capabilities reported by firmware.
494*4882a593Smuzhiyun *
495*4882a593Smuzhiyun * @returns zero on success, and updates the data pointer. Returns a non-zero
496*4882a593Smuzhiyun * error code on failure.
497*4882a593Smuzhiyun */
498*4882a593Smuzhiyun static int
ice_devlink_devcaps_snapshot(struct devlink * devlink,const struct devlink_region_ops * ops,struct netlink_ext_ack * extack,u8 ** data)499*4882a593Smuzhiyun ice_devlink_devcaps_snapshot(struct devlink *devlink,
500*4882a593Smuzhiyun const struct devlink_region_ops *ops,
501*4882a593Smuzhiyun struct netlink_ext_ack *extack, u8 **data)
502*4882a593Smuzhiyun {
503*4882a593Smuzhiyun struct ice_pf *pf = devlink_priv(devlink);
504*4882a593Smuzhiyun struct device *dev = ice_pf_to_dev(pf);
505*4882a593Smuzhiyun struct ice_hw *hw = &pf->hw;
506*4882a593Smuzhiyun enum ice_status status;
507*4882a593Smuzhiyun void *devcaps;
508*4882a593Smuzhiyun
509*4882a593Smuzhiyun devcaps = vzalloc(ICE_AQ_MAX_BUF_LEN);
510*4882a593Smuzhiyun if (!devcaps)
511*4882a593Smuzhiyun return -ENOMEM;
512*4882a593Smuzhiyun
513*4882a593Smuzhiyun status = ice_aq_list_caps(hw, devcaps, ICE_AQ_MAX_BUF_LEN, NULL,
514*4882a593Smuzhiyun ice_aqc_opc_list_dev_caps, NULL);
515*4882a593Smuzhiyun if (status) {
516*4882a593Smuzhiyun dev_dbg(dev, "ice_aq_list_caps: failed to read device capabilities, err %d aq_err %d\n",
517*4882a593Smuzhiyun status, hw->adminq.sq_last_status);
518*4882a593Smuzhiyun NL_SET_ERR_MSG_MOD(extack, "Failed to read device capabilities");
519*4882a593Smuzhiyun vfree(devcaps);
520*4882a593Smuzhiyun return -EIO;
521*4882a593Smuzhiyun }
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun *data = (u8 *)devcaps;
524*4882a593Smuzhiyun
525*4882a593Smuzhiyun return 0;
526*4882a593Smuzhiyun }
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun static const struct devlink_region_ops ice_nvm_region_ops = {
529*4882a593Smuzhiyun .name = "nvm-flash",
530*4882a593Smuzhiyun .destructor = vfree,
531*4882a593Smuzhiyun .snapshot = ice_devlink_nvm_snapshot,
532*4882a593Smuzhiyun };
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun static const struct devlink_region_ops ice_devcaps_region_ops = {
535*4882a593Smuzhiyun .name = "device-caps",
536*4882a593Smuzhiyun .destructor = vfree,
537*4882a593Smuzhiyun .snapshot = ice_devlink_devcaps_snapshot,
538*4882a593Smuzhiyun };
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun /**
541*4882a593Smuzhiyun * ice_devlink_init_regions - Initialize devlink regions
542*4882a593Smuzhiyun * @pf: the PF device structure
543*4882a593Smuzhiyun *
544*4882a593Smuzhiyun * Create devlink regions used to enable access to dump the contents of the
545*4882a593Smuzhiyun * flash memory on the device.
546*4882a593Smuzhiyun */
ice_devlink_init_regions(struct ice_pf * pf)547*4882a593Smuzhiyun void ice_devlink_init_regions(struct ice_pf *pf)
548*4882a593Smuzhiyun {
549*4882a593Smuzhiyun struct devlink *devlink = priv_to_devlink(pf);
550*4882a593Smuzhiyun struct device *dev = ice_pf_to_dev(pf);
551*4882a593Smuzhiyun u64 nvm_size;
552*4882a593Smuzhiyun
553*4882a593Smuzhiyun nvm_size = pf->hw.nvm.flash_size;
554*4882a593Smuzhiyun pf->nvm_region = devlink_region_create(devlink, &ice_nvm_region_ops, 1,
555*4882a593Smuzhiyun nvm_size);
556*4882a593Smuzhiyun if (IS_ERR(pf->nvm_region)) {
557*4882a593Smuzhiyun dev_err(dev, "failed to create NVM devlink region, err %ld\n",
558*4882a593Smuzhiyun PTR_ERR(pf->nvm_region));
559*4882a593Smuzhiyun pf->nvm_region = NULL;
560*4882a593Smuzhiyun }
561*4882a593Smuzhiyun
562*4882a593Smuzhiyun pf->devcaps_region = devlink_region_create(devlink,
563*4882a593Smuzhiyun &ice_devcaps_region_ops, 10,
564*4882a593Smuzhiyun ICE_AQ_MAX_BUF_LEN);
565*4882a593Smuzhiyun if (IS_ERR(pf->devcaps_region)) {
566*4882a593Smuzhiyun dev_err(dev, "failed to create device-caps devlink region, err %ld\n",
567*4882a593Smuzhiyun PTR_ERR(pf->devcaps_region));
568*4882a593Smuzhiyun pf->devcaps_region = NULL;
569*4882a593Smuzhiyun }
570*4882a593Smuzhiyun }
571*4882a593Smuzhiyun
572*4882a593Smuzhiyun /**
573*4882a593Smuzhiyun * ice_devlink_destroy_regions - Destroy devlink regions
574*4882a593Smuzhiyun * @pf: the PF device structure
575*4882a593Smuzhiyun *
576*4882a593Smuzhiyun * Remove previously created regions for this PF.
577*4882a593Smuzhiyun */
ice_devlink_destroy_regions(struct ice_pf * pf)578*4882a593Smuzhiyun void ice_devlink_destroy_regions(struct ice_pf *pf)
579*4882a593Smuzhiyun {
580*4882a593Smuzhiyun if (pf->nvm_region)
581*4882a593Smuzhiyun devlink_region_destroy(pf->nvm_region);
582*4882a593Smuzhiyun if (pf->devcaps_region)
583*4882a593Smuzhiyun devlink_region_destroy(pf->devcaps_region);
584*4882a593Smuzhiyun }
585