1/* Broadcom NetXtreme-C/E network driver.
2 *
3 * Copyright (c) 2017 Broadcom Limited
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation.
8 */
9
10#include <linux/pci.h>
11#include <linux/netdevice.h>
12#include <linux/vmalloc.h>
13#include <net/devlink.h>
14#include "bnxt_hsi.h"
15#include "bnxt.h"
16#include "bnxt_hwrm.h"
17#include "bnxt_vfr.h"
18#include "bnxt_devlink.h"
19#include "bnxt_ethtool.h"
20#include "bnxt_ulp.h"
21#include "bnxt_ptp.h"
22#include "bnxt_coredump.h"
23#include "bnxt_nvm_defs.h"
24
25static void __bnxt_fw_recover(struct bnxt *bp)
26{
27	if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state) ||
28	    test_bit(BNXT_STATE_FW_NON_FATAL_COND, &bp->state))
29		bnxt_fw_reset(bp);
30	else
31		bnxt_fw_exception(bp);
32}
33
34static int
35bnxt_dl_flash_update(struct devlink *dl,
36		     struct devlink_flash_update_params *params,
37		     struct netlink_ext_ack *extack)
38{
39	struct bnxt *bp = bnxt_get_bp_from_dl(dl);
40	int rc;
41
42	if (!BNXT_PF(bp)) {
43		NL_SET_ERR_MSG_MOD(extack,
44				   "flash update not supported from a VF");
45		return -EPERM;
46	}
47
48	devlink_flash_update_status_notify(dl, "Preparing to flash", NULL, 0, 0);
49	rc = bnxt_flash_package_from_fw_obj(bp->dev, params->fw, 0, extack);
50	if (!rc)
51		devlink_flash_update_status_notify(dl, "Flashing done", NULL, 0, 0);
52	else
53		devlink_flash_update_status_notify(dl, "Flashing failed", NULL, 0, 0);
54	return rc;
55}
56
57static int bnxt_hwrm_remote_dev_reset_set(struct bnxt *bp, bool remote_reset)
58{
59	struct hwrm_func_cfg_input *req;
60	int rc;
61
62	if (~bp->fw_cap & BNXT_FW_CAP_HOT_RESET_IF)
63		return -EOPNOTSUPP;
64
65	rc = bnxt_hwrm_func_cfg_short_req_init(bp, &req);
66	if (rc)
67		return rc;
68
69	req->fid = cpu_to_le16(0xffff);
70	req->enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_HOT_RESET_IF_SUPPORT);
71	if (remote_reset)
72		req->flags = cpu_to_le32(FUNC_CFG_REQ_FLAGS_HOT_RESET_IF_EN_DIS);
73
74	return hwrm_req_send(bp, req);
75}
76
77static char *bnxt_health_severity_str(enum bnxt_health_severity severity)
78{
79	switch (severity) {
80	case SEVERITY_NORMAL: return "normal";
81	case SEVERITY_WARNING: return "warning";
82	case SEVERITY_RECOVERABLE: return "recoverable";
83	case SEVERITY_FATAL: return "fatal";
84	default: return "unknown";
85	}
86}
87
88static char *bnxt_health_remedy_str(enum bnxt_health_remedy remedy)
89{
90	switch (remedy) {
91	case REMEDY_DEVLINK_RECOVER: return "devlink recover";
92	case REMEDY_POWER_CYCLE_DEVICE: return "device power cycle";
93	case REMEDY_POWER_CYCLE_HOST: return "host power cycle";
94	case REMEDY_FW_UPDATE: return "update firmware";
95	case REMEDY_HW_REPLACE: return "replace hardware";
96	default: return "unknown";
97	}
98}
99
100static int bnxt_fw_diagnose(struct devlink_health_reporter *reporter,
101			    struct devlink_fmsg *fmsg,
102			    struct netlink_ext_ack *extack)
103{
104	struct bnxt *bp = devlink_health_reporter_priv(reporter);
105	struct bnxt_fw_health *h = bp->fw_health;
106	u32 fw_status, fw_resets;
107
108	if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) {
109		devlink_fmsg_string_pair_put(fmsg, "Status", "recovering");
110		return 0;
111	}
112
113	if (!h->status_reliable) {
114		devlink_fmsg_string_pair_put(fmsg, "Status", "unknown");
115		return 0;
116	}
117
118	mutex_lock(&h->lock);
119	fw_status = bnxt_fw_health_readl(bp, BNXT_FW_HEALTH_REG);
120	if (BNXT_FW_IS_BOOTING(fw_status)) {
121		devlink_fmsg_string_pair_put(fmsg, "Status", "initializing");
122	} else if (h->severity || fw_status != BNXT_FW_STATUS_HEALTHY) {
123		if (!h->severity) {
124			h->severity = SEVERITY_FATAL;
125			h->remedy = REMEDY_POWER_CYCLE_DEVICE;
126			h->diagnoses++;
127			devlink_health_report(h->fw_reporter,
128					      "FW error diagnosed", h);
129		}
130		devlink_fmsg_string_pair_put(fmsg, "Status", "error");
131		devlink_fmsg_u32_pair_put(fmsg, "Syndrome", fw_status);
132	} else {
133		devlink_fmsg_string_pair_put(fmsg, "Status", "healthy");
134	}
135
136	devlink_fmsg_string_pair_put(fmsg, "Severity",
137				     bnxt_health_severity_str(h->severity));
138
139	if (h->severity) {
140		devlink_fmsg_string_pair_put(fmsg, "Remedy",
141					     bnxt_health_remedy_str(h->remedy));
142		if (h->remedy == REMEDY_DEVLINK_RECOVER)
143			devlink_fmsg_string_pair_put(fmsg, "Impact",
144						     "traffic+ntuple_cfg");
145	}
146
147	mutex_unlock(&h->lock);
148	if (!h->resets_reliable)
149		return 0;
150
151	fw_resets = bnxt_fw_health_readl(bp, BNXT_FW_RESET_CNT_REG);
152	devlink_fmsg_u32_pair_put(fmsg, "Resets", fw_resets);
153	devlink_fmsg_u32_pair_put(fmsg, "Arrests", h->arrests);
154	devlink_fmsg_u32_pair_put(fmsg, "Survivals", h->survivals);
155	devlink_fmsg_u32_pair_put(fmsg, "Discoveries", h->discoveries);
156	devlink_fmsg_u32_pair_put(fmsg, "Fatalities", h->fatalities);
157	devlink_fmsg_u32_pair_put(fmsg, "Diagnoses", h->diagnoses);
158	return 0;
159}
160
161static int bnxt_fw_dump(struct devlink_health_reporter *reporter,
162			struct devlink_fmsg *fmsg, void *priv_ctx,
163			struct netlink_ext_ack *extack)
164{
165	struct bnxt *bp = devlink_health_reporter_priv(reporter);
166	u32 dump_len;
167	void *data;
168	int rc;
169
170	/* TODO: no firmware dump support in devlink_health_report() context */
171	if (priv_ctx)
172		return -EOPNOTSUPP;
173
174	dump_len = bnxt_get_coredump_length(bp, BNXT_DUMP_LIVE);
175	if (!dump_len)
176		return -EIO;
177
178	data = vmalloc(dump_len);
179	if (!data)
180		return -ENOMEM;
181
182	rc = bnxt_get_coredump(bp, BNXT_DUMP_LIVE, data, &dump_len);
183	if (!rc) {
184		devlink_fmsg_pair_nest_start(fmsg, "core");
185		devlink_fmsg_binary_pair_put(fmsg, "data", data, dump_len);
186		devlink_fmsg_u32_pair_put(fmsg, "size", dump_len);
187		devlink_fmsg_pair_nest_end(fmsg);
188	}
189
190	vfree(data);
191	return rc;
192}
193
194static int bnxt_fw_recover(struct devlink_health_reporter *reporter,
195			   void *priv_ctx,
196			   struct netlink_ext_ack *extack)
197{
198	struct bnxt *bp = devlink_health_reporter_priv(reporter);
199
200	if (bp->fw_health->severity == SEVERITY_FATAL)
201		return -ENODEV;
202
203	set_bit(BNXT_STATE_RECOVER, &bp->state);
204	__bnxt_fw_recover(bp);
205
206	return -EINPROGRESS;
207}
208
209static const struct devlink_health_reporter_ops bnxt_dl_fw_reporter_ops = {
210	.name = "fw",
211	.diagnose = bnxt_fw_diagnose,
212	.dump = bnxt_fw_dump,
213	.recover = bnxt_fw_recover,
214};
215
216static struct devlink_health_reporter *
217__bnxt_dl_reporter_create(struct bnxt *bp,
218			  const struct devlink_health_reporter_ops *ops)
219{
220	struct devlink_health_reporter *reporter;
221
222	reporter = devlink_health_reporter_create(bp->dl, ops, 0, bp);
223	if (IS_ERR(reporter)) {
224		netdev_warn(bp->dev, "Failed to create %s health reporter, rc = %ld\n",
225			    ops->name, PTR_ERR(reporter));
226		return NULL;
227	}
228
229	return reporter;
230}
231
232void bnxt_dl_fw_reporters_create(struct bnxt *bp)
233{
234	struct bnxt_fw_health *fw_health = bp->fw_health;
235
236	if (fw_health && !fw_health->fw_reporter)
237		fw_health->fw_reporter = __bnxt_dl_reporter_create(bp, &bnxt_dl_fw_reporter_ops);
238}
239
240void bnxt_dl_fw_reporters_destroy(struct bnxt *bp)
241{
242	struct bnxt_fw_health *fw_health = bp->fw_health;
243
244	if (fw_health && fw_health->fw_reporter) {
245		devlink_health_reporter_destroy(fw_health->fw_reporter);
246		fw_health->fw_reporter = NULL;
247	}
248}
249
250void bnxt_devlink_health_fw_report(struct bnxt *bp)
251{
252	struct bnxt_fw_health *fw_health = bp->fw_health;
253	int rc;
254
255	if (!fw_health)
256		return;
257
258	if (!fw_health->fw_reporter) {
259		__bnxt_fw_recover(bp);
260		return;
261	}
262
263	mutex_lock(&fw_health->lock);
264	fw_health->severity = SEVERITY_RECOVERABLE;
265	fw_health->remedy = REMEDY_DEVLINK_RECOVER;
266	mutex_unlock(&fw_health->lock);
267	rc = devlink_health_report(fw_health->fw_reporter, "FW error reported",
268				   fw_health);
269	if (rc == -ECANCELED)
270		__bnxt_fw_recover(bp);
271}
272
273void bnxt_dl_health_fw_status_update(struct bnxt *bp, bool healthy)
274{
275	struct bnxt_fw_health *fw_health = bp->fw_health;
276	u8 state;
277
278	mutex_lock(&fw_health->lock);
279	if (healthy) {
280		fw_health->severity = SEVERITY_NORMAL;
281		state = DEVLINK_HEALTH_REPORTER_STATE_HEALTHY;
282	} else {
283		fw_health->severity = SEVERITY_FATAL;
284		fw_health->remedy = REMEDY_POWER_CYCLE_DEVICE;
285		state = DEVLINK_HEALTH_REPORTER_STATE_ERROR;
286	}
287	mutex_unlock(&fw_health->lock);
288	devlink_health_reporter_state_update(fw_health->fw_reporter, state);
289}
290
291void bnxt_dl_health_fw_recovery_done(struct bnxt *bp)
292{
293	struct bnxt_dl *dl = devlink_priv(bp->dl);
294
295	devlink_health_reporter_recovery_done(bp->fw_health->fw_reporter);
296	bnxt_hwrm_remote_dev_reset_set(bp, dl->remote_reset);
297}
298
299static int bnxt_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
300			    struct netlink_ext_ack *extack);
301
302static void
303bnxt_dl_livepatch_report_err(struct bnxt *bp, struct netlink_ext_ack *extack,
304			     struct hwrm_fw_livepatch_output *resp)
305{
306	int err = ((struct hwrm_err_output *)resp)->cmd_err;
307
308	switch (err) {
309	case FW_LIVEPATCH_CMD_ERR_CODE_INVALID_OPCODE:
310		netdev_err(bp->dev, "Illegal live patch opcode");
311		NL_SET_ERR_MSG_MOD(extack, "Invalid opcode");
312		break;
313	case FW_LIVEPATCH_CMD_ERR_CODE_NOT_SUPPORTED:
314		NL_SET_ERR_MSG_MOD(extack, "Live patch operation not supported");
315		break;
316	case FW_LIVEPATCH_CMD_ERR_CODE_NOT_INSTALLED:
317		NL_SET_ERR_MSG_MOD(extack, "Live patch not found");
318		break;
319	case FW_LIVEPATCH_CMD_ERR_CODE_NOT_PATCHED:
320		NL_SET_ERR_MSG_MOD(extack,
321				   "Live patch deactivation failed. Firmware not patched.");
322		break;
323	case FW_LIVEPATCH_CMD_ERR_CODE_AUTH_FAIL:
324		NL_SET_ERR_MSG_MOD(extack, "Live patch not authenticated");
325		break;
326	case FW_LIVEPATCH_CMD_ERR_CODE_INVALID_HEADER:
327		NL_SET_ERR_MSG_MOD(extack, "Incompatible live patch");
328		break;
329	case FW_LIVEPATCH_CMD_ERR_CODE_INVALID_SIZE:
330		NL_SET_ERR_MSG_MOD(extack, "Live patch has invalid size");
331		break;
332	case FW_LIVEPATCH_CMD_ERR_CODE_ALREADY_PATCHED:
333		NL_SET_ERR_MSG_MOD(extack, "Live patch already applied");
334		break;
335	default:
336		netdev_err(bp->dev, "Unexpected live patch error: %d\n", err);
337		NL_SET_ERR_MSG_MOD(extack, "Failed to activate live patch");
338		break;
339	}
340}
341
342/* Live patch status in NVM */
343#define BNXT_LIVEPATCH_NOT_INSTALLED	0
344#define BNXT_LIVEPATCH_INSTALLED	FW_LIVEPATCH_QUERY_RESP_STATUS_FLAGS_INSTALL
345#define BNXT_LIVEPATCH_REMOVED		FW_LIVEPATCH_QUERY_RESP_STATUS_FLAGS_ACTIVE
346#define BNXT_LIVEPATCH_MASK		(FW_LIVEPATCH_QUERY_RESP_STATUS_FLAGS_INSTALL | \
347					 FW_LIVEPATCH_QUERY_RESP_STATUS_FLAGS_ACTIVE)
348#define BNXT_LIVEPATCH_ACTIVATED	BNXT_LIVEPATCH_MASK
349
350#define BNXT_LIVEPATCH_STATE(flags)	((flags) & BNXT_LIVEPATCH_MASK)
351
352static int
353bnxt_dl_livepatch_activate(struct bnxt *bp, struct netlink_ext_ack *extack)
354{
355	struct hwrm_fw_livepatch_query_output *query_resp;
356	struct hwrm_fw_livepatch_query_input *query_req;
357	struct hwrm_fw_livepatch_output *patch_resp;
358	struct hwrm_fw_livepatch_input *patch_req;
359	u16 flags, live_patch_state;
360	bool activated = false;
361	u32 installed = 0;
362	u8 target;
363	int rc;
364
365	if (~bp->fw_cap & BNXT_FW_CAP_LIVEPATCH) {
366		NL_SET_ERR_MSG_MOD(extack, "Device does not support live patch");
367		return -EOPNOTSUPP;
368	}
369
370	rc = hwrm_req_init(bp, query_req, HWRM_FW_LIVEPATCH_QUERY);
371	if (rc)
372		return rc;
373	query_resp = hwrm_req_hold(bp, query_req);
374
375	rc = hwrm_req_init(bp, patch_req, HWRM_FW_LIVEPATCH);
376	if (rc) {
377		hwrm_req_drop(bp, query_req);
378		return rc;
379	}
380	patch_req->loadtype = FW_LIVEPATCH_REQ_LOADTYPE_NVM_INSTALL;
381	patch_resp = hwrm_req_hold(bp, patch_req);
382
383	for (target = 1; target <= FW_LIVEPATCH_REQ_FW_TARGET_LAST; target++) {
384		query_req->fw_target = target;
385		rc = hwrm_req_send(bp, query_req);
386		if (rc) {
387			NL_SET_ERR_MSG_MOD(extack, "Failed to query packages");
388			break;
389		}
390
391		flags = le16_to_cpu(query_resp->status_flags);
392		live_patch_state = BNXT_LIVEPATCH_STATE(flags);
393
394		if (live_patch_state == BNXT_LIVEPATCH_NOT_INSTALLED)
395			continue;
396
397		if (live_patch_state == BNXT_LIVEPATCH_ACTIVATED) {
398			activated = true;
399			continue;
400		}
401
402		if (live_patch_state == BNXT_LIVEPATCH_INSTALLED)
403			patch_req->opcode = FW_LIVEPATCH_REQ_OPCODE_ACTIVATE;
404		else if (live_patch_state == BNXT_LIVEPATCH_REMOVED)
405			patch_req->opcode = FW_LIVEPATCH_REQ_OPCODE_DEACTIVATE;
406
407		patch_req->fw_target = target;
408		rc = hwrm_req_send(bp, patch_req);
409		if (rc) {
410			bnxt_dl_livepatch_report_err(bp, extack, patch_resp);
411			break;
412		}
413		installed++;
414	}
415
416	if (!rc && !installed) {
417		if (activated) {
418			NL_SET_ERR_MSG_MOD(extack, "Live patch already activated");
419			rc = -EEXIST;
420		} else {
421			NL_SET_ERR_MSG_MOD(extack, "No live patches found");
422			rc = -ENOENT;
423		}
424	}
425	hwrm_req_drop(bp, query_req);
426	hwrm_req_drop(bp, patch_req);
427	return rc;
428}
429
430static int bnxt_dl_reload_down(struct devlink *dl, bool netns_change,
431			       enum devlink_reload_action action,
432			       enum devlink_reload_limit limit,
433			       struct netlink_ext_ack *extack)
434{
435	struct bnxt *bp = bnxt_get_bp_from_dl(dl);
436	int rc = 0;
437
438	switch (action) {
439	case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: {
440		rtnl_lock();
441		if (bnxt_sriov_cfg(bp)) {
442			NL_SET_ERR_MSG_MOD(extack,
443					   "reload is unsupported while VFs are allocated or being configured");
444			rtnl_unlock();
445			return -EOPNOTSUPP;
446		}
447		if (bp->dev->reg_state == NETREG_UNREGISTERED) {
448			rtnl_unlock();
449			return -ENODEV;
450		}
451		bnxt_ulp_stop(bp);
452		if (netif_running(bp->dev))
453			bnxt_close_nic(bp, true, true);
454		bnxt_vf_reps_free(bp);
455		rc = bnxt_hwrm_func_drv_unrgtr(bp);
456		if (rc) {
457			NL_SET_ERR_MSG_MOD(extack, "Failed to deregister");
458			if (netif_running(bp->dev))
459				dev_close(bp->dev);
460			rtnl_unlock();
461			break;
462		}
463		bnxt_cancel_reservations(bp, false);
464		bnxt_free_ctx_mem(bp);
465		break;
466	}
467	case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: {
468		if (limit == DEVLINK_RELOAD_LIMIT_NO_RESET)
469			return bnxt_dl_livepatch_activate(bp, extack);
470		if (~bp->fw_cap & BNXT_FW_CAP_HOT_RESET) {
471			NL_SET_ERR_MSG_MOD(extack, "Device not capable, requires reboot");
472			return -EOPNOTSUPP;
473		}
474		if (!bnxt_hwrm_reset_permitted(bp)) {
475			NL_SET_ERR_MSG_MOD(extack,
476					   "Reset denied by firmware, it may be inhibited by remote driver");
477			return -EPERM;
478		}
479		rtnl_lock();
480		if (bp->dev->reg_state == NETREG_UNREGISTERED) {
481			rtnl_unlock();
482			return -ENODEV;
483		}
484		if (netif_running(bp->dev))
485			set_bit(BNXT_STATE_FW_ACTIVATE, &bp->state);
486		rc = bnxt_hwrm_firmware_reset(bp->dev,
487					      FW_RESET_REQ_EMBEDDED_PROC_TYPE_CHIP,
488					      FW_RESET_REQ_SELFRST_STATUS_SELFRSTASAP,
489					      FW_RESET_REQ_FLAGS_RESET_GRACEFUL |
490					      FW_RESET_REQ_FLAGS_FW_ACTIVATION);
491		if (rc) {
492			NL_SET_ERR_MSG_MOD(extack, "Failed to activate firmware");
493			clear_bit(BNXT_STATE_FW_ACTIVATE, &bp->state);
494			rtnl_unlock();
495		}
496		break;
497	}
498	default:
499		rc = -EOPNOTSUPP;
500	}
501
502	return rc;
503}
504
505static int bnxt_dl_reload_up(struct devlink *dl, enum devlink_reload_action action,
506			     enum devlink_reload_limit limit, u32 *actions_performed,
507			     struct netlink_ext_ack *extack)
508{
509	struct bnxt *bp = bnxt_get_bp_from_dl(dl);
510	int rc = 0;
511
512	*actions_performed = 0;
513	switch (action) {
514	case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: {
515		bnxt_fw_init_one(bp);
516		bnxt_vf_reps_alloc(bp);
517		if (netif_running(bp->dev))
518			rc = bnxt_open_nic(bp, true, true);
519		bnxt_ulp_start(bp, rc);
520		if (!rc) {
521			bnxt_reenable_sriov(bp);
522			bnxt_ptp_reapply_pps(bp);
523		}
524		break;
525	}
526	case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: {
527		unsigned long start = jiffies;
528		unsigned long timeout = start + BNXT_DFLT_FW_RST_MAX_DSECS * HZ / 10;
529
530		if (limit == DEVLINK_RELOAD_LIMIT_NO_RESET)
531			break;
532		if (bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY)
533			timeout = start + bp->fw_health->normal_func_wait_dsecs * HZ / 10;
534		if (!netif_running(bp->dev))
535			NL_SET_ERR_MSG_MOD(extack,
536					   "Device is closed, not waiting for reset notice that will never come");
537		rtnl_unlock();
538		while (test_bit(BNXT_STATE_FW_ACTIVATE, &bp->state)) {
539			if (time_after(jiffies, timeout)) {
540				NL_SET_ERR_MSG_MOD(extack, "Activation incomplete");
541				rc = -ETIMEDOUT;
542				break;
543			}
544			if (test_bit(BNXT_STATE_ABORT_ERR, &bp->state)) {
545				NL_SET_ERR_MSG_MOD(extack, "Activation aborted");
546				rc = -ENODEV;
547				break;
548			}
549			msleep(50);
550		}
551		rtnl_lock();
552		if (!rc)
553			*actions_performed |= BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT);
554		clear_bit(BNXT_STATE_FW_ACTIVATE, &bp->state);
555		break;
556	}
557	default:
558		return -EOPNOTSUPP;
559	}
560
561	if (!rc) {
562		bnxt_print_device_info(bp);
563		if (netif_running(bp->dev)) {
564			mutex_lock(&bp->link_lock);
565			bnxt_report_link(bp);
566			mutex_unlock(&bp->link_lock);
567		}
568		*actions_performed |= BIT(action);
569	} else if (netif_running(bp->dev)) {
570		dev_close(bp->dev);
571	}
572	rtnl_unlock();
573	return rc;
574}
575
576static bool bnxt_nvm_test(struct bnxt *bp, struct netlink_ext_ack *extack)
577{
578	bool rc = false;
579	u32 datalen;
580	u16 index;
581	u8 *buf;
582
583	if (bnxt_find_nvram_item(bp->dev, BNX_DIR_TYPE_VPD,
584				 BNX_DIR_ORDINAL_FIRST, BNX_DIR_EXT_NONE,
585				 &index, NULL, &datalen) || !datalen) {
586		NL_SET_ERR_MSG_MOD(extack, "nvm test vpd entry error");
587		return false;
588	}
589
590	buf = kzalloc(datalen, GFP_KERNEL);
591	if (!buf) {
592		NL_SET_ERR_MSG_MOD(extack, "insufficient memory for nvm test");
593		return false;
594	}
595
596	if (bnxt_get_nvram_item(bp->dev, index, 0, datalen, buf)) {
597		NL_SET_ERR_MSG_MOD(extack, "nvm test vpd read error");
598		goto done;
599	}
600
601	if (bnxt_flash_nvram(bp->dev, BNX_DIR_TYPE_VPD, BNX_DIR_ORDINAL_FIRST,
602			     BNX_DIR_EXT_NONE, 0, 0, buf, datalen)) {
603		NL_SET_ERR_MSG_MOD(extack, "nvm test vpd write error");
604		goto done;
605	}
606
607	rc = true;
608
609done:
610	kfree(buf);
611	return rc;
612}
613
614static bool bnxt_dl_selftest_check(struct devlink *dl, unsigned int id,
615				   struct netlink_ext_ack *extack)
616{
617	return id == DEVLINK_ATTR_SELFTEST_ID_FLASH;
618}
619
620static enum devlink_selftest_status bnxt_dl_selftest_run(struct devlink *dl,
621							 unsigned int id,
622							 struct netlink_ext_ack *extack)
623{
624	struct bnxt *bp = bnxt_get_bp_from_dl(dl);
625
626	if (id == DEVLINK_ATTR_SELFTEST_ID_FLASH)
627		return bnxt_nvm_test(bp, extack) ?
628				DEVLINK_SELFTEST_STATUS_PASS :
629				DEVLINK_SELFTEST_STATUS_FAIL;
630
631	return DEVLINK_SELFTEST_STATUS_SKIP;
632}
633
634static const struct devlink_ops bnxt_dl_ops = {
635#ifdef CONFIG_BNXT_SRIOV
636	.eswitch_mode_set = bnxt_dl_eswitch_mode_set,
637	.eswitch_mode_get = bnxt_dl_eswitch_mode_get,
638#endif /* CONFIG_BNXT_SRIOV */
639	.info_get	  = bnxt_dl_info_get,
640	.flash_update	  = bnxt_dl_flash_update,
641	.reload_actions	  = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) |
642			    BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE),
643	.reload_limits	  = BIT(DEVLINK_RELOAD_LIMIT_NO_RESET),
644	.reload_down	  = bnxt_dl_reload_down,
645	.reload_up	  = bnxt_dl_reload_up,
646	.selftest_check	  = bnxt_dl_selftest_check,
647	.selftest_run	  = bnxt_dl_selftest_run,
648};
649
650static const struct devlink_ops bnxt_vf_dl_ops;
651
652enum bnxt_dl_param_id {
653	BNXT_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
654	BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK,
655};
656
657static const struct bnxt_dl_nvm_param nvm_params[] = {
658	{DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV, NVM_OFF_ENABLE_SRIOV,
659	 BNXT_NVM_SHARED_CFG, 1, 1},
660	{DEVLINK_PARAM_GENERIC_ID_IGNORE_ARI, NVM_OFF_IGNORE_ARI,
661	 BNXT_NVM_SHARED_CFG, 1, 1},
662	{DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX,
663	 NVM_OFF_MSIX_VEC_PER_PF_MAX, BNXT_NVM_SHARED_CFG, 10, 4},
664	{DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN,
665	 NVM_OFF_MSIX_VEC_PER_PF_MIN, BNXT_NVM_SHARED_CFG, 7, 4},
666	{BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK, NVM_OFF_DIS_GRE_VER_CHECK,
667	 BNXT_NVM_SHARED_CFG, 1, 1},
668};
669
670union bnxt_nvm_data {
671	u8	val8;
672	__le32	val32;
673};
674
675static void bnxt_copy_to_nvm_data(union bnxt_nvm_data *dst,
676				  union devlink_param_value *src,
677				  int nvm_num_bits, int dl_num_bytes)
678{
679	u32 val32 = 0;
680
681	if (nvm_num_bits == 1) {
682		dst->val8 = src->vbool;
683		return;
684	}
685	if (dl_num_bytes == 4)
686		val32 = src->vu32;
687	else if (dl_num_bytes == 2)
688		val32 = (u32)src->vu16;
689	else if (dl_num_bytes == 1)
690		val32 = (u32)src->vu8;
691	dst->val32 = cpu_to_le32(val32);
692}
693
694static void bnxt_copy_from_nvm_data(union devlink_param_value *dst,
695				    union bnxt_nvm_data *src,
696				    int nvm_num_bits, int dl_num_bytes)
697{
698	u32 val32;
699
700	if (nvm_num_bits == 1) {
701		dst->vbool = src->val8;
702		return;
703	}
704	val32 = le32_to_cpu(src->val32);
705	if (dl_num_bytes == 4)
706		dst->vu32 = val32;
707	else if (dl_num_bytes == 2)
708		dst->vu16 = (u16)val32;
709	else if (dl_num_bytes == 1)
710		dst->vu8 = (u8)val32;
711}
712
713static int bnxt_hwrm_get_nvm_cfg_ver(struct bnxt *bp, u32 *nvm_cfg_ver)
714{
715	struct hwrm_nvm_get_variable_input *req;
716	u16 bytes = BNXT_NVM_CFG_VER_BYTES;
717	u16 bits = BNXT_NVM_CFG_VER_BITS;
718	union devlink_param_value ver;
719	union bnxt_nvm_data *data;
720	dma_addr_t data_dma_addr;
721	int rc, i = 2;
722	u16 dim = 1;
723
724	rc = hwrm_req_init(bp, req, HWRM_NVM_GET_VARIABLE);
725	if (rc)
726		return rc;
727
728	data = hwrm_req_dma_slice(bp, req, sizeof(*data), &data_dma_addr);
729	if (!data) {
730		rc = -ENOMEM;
731		goto exit;
732	}
733
734	/* earlier devices present as an array of raw bytes */
735	if (!BNXT_CHIP_P5_PLUS(bp)) {
736		dim = 0;
737		i = 0;
738		bits *= 3;  /* array of 3 version components */
739		bytes *= 4; /* copy whole word */
740	}
741
742	hwrm_req_hold(bp, req);
743	req->dest_data_addr = cpu_to_le64(data_dma_addr);
744	req->data_len = cpu_to_le16(bits);
745	req->option_num = cpu_to_le16(NVM_OFF_NVM_CFG_VER);
746	req->dimensions = cpu_to_le16(dim);
747
748	while (i >= 0) {
749		req->index_0 = cpu_to_le16(i--);
750		rc = hwrm_req_send_silent(bp, req);
751		if (rc)
752			goto exit;
753		bnxt_copy_from_nvm_data(&ver, data, bits, bytes);
754
755		if (BNXT_CHIP_P5_PLUS(bp)) {
756			*nvm_cfg_ver <<= 8;
757			*nvm_cfg_ver |= ver.vu8;
758		} else {
759			*nvm_cfg_ver = ver.vu32;
760		}
761	}
762
763exit:
764	hwrm_req_drop(bp, req);
765	return rc;
766}
767
768static int bnxt_dl_info_put(struct bnxt *bp, struct devlink_info_req *req,
769			    enum bnxt_dl_version_type type, const char *key,
770			    char *buf)
771{
772	if (!strlen(buf))
773		return 0;
774
775	if ((bp->flags & BNXT_FLAG_CHIP_P5_PLUS) &&
776	    (!strcmp(key, DEVLINK_INFO_VERSION_GENERIC_FW_NCSI) ||
777	     !strcmp(key, DEVLINK_INFO_VERSION_GENERIC_FW_ROCE)))
778		return 0;
779
780	switch (type) {
781	case BNXT_VERSION_FIXED:
782		return devlink_info_version_fixed_put(req, key, buf);
783	case BNXT_VERSION_RUNNING:
784		return devlink_info_version_running_put(req, key, buf);
785	case BNXT_VERSION_STORED:
786		return devlink_info_version_stored_put(req, key, buf);
787	}
788	return 0;
789}
790
791#define BNXT_FW_SRT_PATCH	"fw.srt.patch"
792#define BNXT_FW_CRT_PATCH	"fw.crt.patch"
793
794static int bnxt_dl_livepatch_info_put(struct bnxt *bp,
795				      struct devlink_info_req *req,
796				      const char *key)
797{
798	struct hwrm_fw_livepatch_query_input *query;
799	struct hwrm_fw_livepatch_query_output *resp;
800	u16 flags;
801	int rc;
802
803	if (~bp->fw_cap & BNXT_FW_CAP_LIVEPATCH)
804		return 0;
805
806	rc = hwrm_req_init(bp, query, HWRM_FW_LIVEPATCH_QUERY);
807	if (rc)
808		return rc;
809
810	if (!strcmp(key, BNXT_FW_SRT_PATCH))
811		query->fw_target = FW_LIVEPATCH_QUERY_REQ_FW_TARGET_SECURE_FW;
812	else if (!strcmp(key, BNXT_FW_CRT_PATCH))
813		query->fw_target = FW_LIVEPATCH_QUERY_REQ_FW_TARGET_COMMON_FW;
814	else
815		goto exit;
816
817	resp = hwrm_req_hold(bp, query);
818	rc = hwrm_req_send(bp, query);
819	if (rc)
820		goto exit;
821
822	flags = le16_to_cpu(resp->status_flags);
823	if (flags & FW_LIVEPATCH_QUERY_RESP_STATUS_FLAGS_ACTIVE) {
824		resp->active_ver[sizeof(resp->active_ver) - 1] = '\0';
825		rc = devlink_info_version_running_put(req, key, resp->active_ver);
826		if (rc)
827			goto exit;
828	}
829
830	if (flags & FW_LIVEPATCH_QUERY_RESP_STATUS_FLAGS_INSTALL) {
831		resp->install_ver[sizeof(resp->install_ver) - 1] = '\0';
832		rc = devlink_info_version_stored_put(req, key, resp->install_ver);
833		if (rc)
834			goto exit;
835	}
836
837exit:
838	hwrm_req_drop(bp, query);
839	return rc;
840}
841
842#define HWRM_FW_VER_STR_LEN	16
843
844static int bnxt_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
845			    struct netlink_ext_ack *extack)
846{
847	struct hwrm_nvm_get_dev_info_output nvm_dev_info;
848	struct bnxt *bp = bnxt_get_bp_from_dl(dl);
849	struct hwrm_ver_get_output *ver_resp;
850	char mgmt_ver[FW_VER_STR_LEN];
851	char roce_ver[FW_VER_STR_LEN];
852	char ncsi_ver[FW_VER_STR_LEN];
853	char buf[32];
854	u32 ver = 0;
855	int rc;
856
857	if (BNXT_PF(bp) && (bp->flags & BNXT_FLAG_DSN_VALID)) {
858		sprintf(buf, "%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X",
859			bp->dsn[7], bp->dsn[6], bp->dsn[5], bp->dsn[4],
860			bp->dsn[3], bp->dsn[2], bp->dsn[1], bp->dsn[0]);
861		rc = devlink_info_serial_number_put(req, buf);
862		if (rc)
863			return rc;
864	}
865
866	if (strlen(bp->board_serialno)) {
867		rc = devlink_info_board_serial_number_put(req, bp->board_serialno);
868		if (rc)
869			return rc;
870	}
871
872	rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_FIXED,
873			      DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,
874			      bp->board_partno);
875	if (rc)
876		return rc;
877
878	sprintf(buf, "%X", bp->chip_num);
879	rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_FIXED,
880			      DEVLINK_INFO_VERSION_GENERIC_ASIC_ID, buf);
881	if (rc)
882		return rc;
883
884	ver_resp = &bp->ver_resp;
885	sprintf(buf, "%c%d", 'A' + ver_resp->chip_rev, ver_resp->chip_metal);
886	rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_FIXED,
887			      DEVLINK_INFO_VERSION_GENERIC_ASIC_REV, buf);
888	if (rc)
889		return rc;
890
891	rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_RUNNING,
892			      DEVLINK_INFO_VERSION_GENERIC_FW_PSID,
893			      bp->nvm_cfg_ver);
894	if (rc)
895		return rc;
896
897	buf[0] = 0;
898	strncat(buf, ver_resp->active_pkg_name, HWRM_FW_VER_STR_LEN);
899	rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_RUNNING,
900			      DEVLINK_INFO_VERSION_GENERIC_FW, buf);
901	if (rc)
902		return rc;
903
904	if (BNXT_PF(bp) && !bnxt_hwrm_get_nvm_cfg_ver(bp, &ver)) {
905		sprintf(buf, "%d.%d.%d", (ver >> 16) & 0xff, (ver >> 8) & 0xff,
906			ver & 0xff);
907		rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED,
908				      DEVLINK_INFO_VERSION_GENERIC_FW_PSID,
909				      buf);
910		if (rc)
911			return rc;
912	}
913
914	if (ver_resp->flags & VER_GET_RESP_FLAGS_EXT_VER_AVAIL) {
915		snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
916			 ver_resp->hwrm_fw_major, ver_resp->hwrm_fw_minor,
917			 ver_resp->hwrm_fw_build, ver_resp->hwrm_fw_patch);
918
919		snprintf(ncsi_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
920			 ver_resp->mgmt_fw_major, ver_resp->mgmt_fw_minor,
921			 ver_resp->mgmt_fw_build, ver_resp->mgmt_fw_patch);
922
923		snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
924			 ver_resp->roce_fw_major, ver_resp->roce_fw_minor,
925			 ver_resp->roce_fw_build, ver_resp->roce_fw_patch);
926	} else {
927		snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
928			 ver_resp->hwrm_fw_maj_8b, ver_resp->hwrm_fw_min_8b,
929			 ver_resp->hwrm_fw_bld_8b, ver_resp->hwrm_fw_rsvd_8b);
930
931		snprintf(ncsi_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
932			 ver_resp->mgmt_fw_maj_8b, ver_resp->mgmt_fw_min_8b,
933			 ver_resp->mgmt_fw_bld_8b, ver_resp->mgmt_fw_rsvd_8b);
934
935		snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
936			 ver_resp->roce_fw_maj_8b, ver_resp->roce_fw_min_8b,
937			 ver_resp->roce_fw_bld_8b, ver_resp->roce_fw_rsvd_8b);
938	}
939	rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_RUNNING,
940			      DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, mgmt_ver);
941	if (rc)
942		return rc;
943
944	rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_RUNNING,
945			      DEVLINK_INFO_VERSION_GENERIC_FW_MGMT_API,
946			      bp->hwrm_ver_supp);
947	if (rc)
948		return rc;
949
950	rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_RUNNING,
951			      DEVLINK_INFO_VERSION_GENERIC_FW_NCSI, ncsi_ver);
952	if (rc)
953		return rc;
954
955	rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_RUNNING,
956			      DEVLINK_INFO_VERSION_GENERIC_FW_ROCE, roce_ver);
957	if (rc)
958		return rc;
959
960	rc = bnxt_hwrm_nvm_get_dev_info(bp, &nvm_dev_info);
961	if (rc ||
962	    !(nvm_dev_info.flags & NVM_GET_DEV_INFO_RESP_FLAGS_FW_VER_VALID)) {
963		if (!bnxt_get_pkginfo(bp->dev, buf, sizeof(buf)))
964			return bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED,
965						DEVLINK_INFO_VERSION_GENERIC_FW,
966						buf);
967		return 0;
968	}
969
970	buf[0] = 0;
971	strncat(buf, nvm_dev_info.pkg_name, HWRM_FW_VER_STR_LEN);
972	rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED,
973			      DEVLINK_INFO_VERSION_GENERIC_FW, buf);
974	if (rc)
975		return rc;
976
977	snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
978		 nvm_dev_info.hwrm_fw_major, nvm_dev_info.hwrm_fw_minor,
979		 nvm_dev_info.hwrm_fw_build, nvm_dev_info.hwrm_fw_patch);
980	rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED,
981			      DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, mgmt_ver);
982	if (rc)
983		return rc;
984
985	snprintf(ncsi_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
986		 nvm_dev_info.mgmt_fw_major, nvm_dev_info.mgmt_fw_minor,
987		 nvm_dev_info.mgmt_fw_build, nvm_dev_info.mgmt_fw_patch);
988	rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED,
989			      DEVLINK_INFO_VERSION_GENERIC_FW_NCSI, ncsi_ver);
990	if (rc)
991		return rc;
992
993	snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
994		 nvm_dev_info.roce_fw_major, nvm_dev_info.roce_fw_minor,
995		 nvm_dev_info.roce_fw_build, nvm_dev_info.roce_fw_patch);
996	rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED,
997			      DEVLINK_INFO_VERSION_GENERIC_FW_ROCE, roce_ver);
998	if (rc)
999		return rc;
1000
1001	if (BNXT_CHIP_P5_PLUS(bp)) {
1002		rc = bnxt_dl_livepatch_info_put(bp, req, BNXT_FW_SRT_PATCH);
1003		if (rc)
1004			return rc;
1005	}
1006	return bnxt_dl_livepatch_info_put(bp, req, BNXT_FW_CRT_PATCH);
1007
1008}
1009
1010static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg,
1011			     union devlink_param_value *val)
1012{
1013	struct hwrm_nvm_get_variable_input *req = msg;
1014	struct bnxt_dl_nvm_param nvm_param;
1015	struct hwrm_err_output *resp;
1016	union bnxt_nvm_data *data;
1017	dma_addr_t data_dma_addr;
1018	int idx = 0, rc, i;
1019
1020	/* Get/Set NVM CFG parameter is supported only on PFs */
1021	if (BNXT_VF(bp)) {
1022		hwrm_req_drop(bp, req);
1023		return -EPERM;
1024	}
1025
1026	for (i = 0; i < ARRAY_SIZE(nvm_params); i++) {
1027		if (nvm_params[i].id == param_id) {
1028			nvm_param = nvm_params[i];
1029			break;
1030		}
1031	}
1032
1033	if (i == ARRAY_SIZE(nvm_params)) {
1034		hwrm_req_drop(bp, req);
1035		return -EOPNOTSUPP;
1036	}
1037
1038	if (nvm_param.dir_type == BNXT_NVM_PORT_CFG)
1039		idx = bp->pf.port_id;
1040	else if (nvm_param.dir_type == BNXT_NVM_FUNC_CFG)
1041		idx = bp->pf.fw_fid - BNXT_FIRST_PF_FID;
1042
1043	data = hwrm_req_dma_slice(bp, req, sizeof(*data), &data_dma_addr);
1044
1045	if (!data) {
1046		hwrm_req_drop(bp, req);
1047		return -ENOMEM;
1048	}
1049
1050	req->dest_data_addr = cpu_to_le64(data_dma_addr);
1051	req->data_len = cpu_to_le16(nvm_param.nvm_num_bits);
1052	req->option_num = cpu_to_le16(nvm_param.offset);
1053	req->index_0 = cpu_to_le16(idx);
1054	if (idx)
1055		req->dimensions = cpu_to_le16(1);
1056
1057	resp = hwrm_req_hold(bp, req);
1058	if (req->req_type == cpu_to_le16(HWRM_NVM_SET_VARIABLE)) {
1059		bnxt_copy_to_nvm_data(data, val, nvm_param.nvm_num_bits,
1060				      nvm_param.dl_num_bytes);
1061		rc = hwrm_req_send(bp, msg);
1062	} else {
1063		rc = hwrm_req_send_silent(bp, msg);
1064		if (!rc) {
1065			bnxt_copy_from_nvm_data(val, data,
1066						nvm_param.nvm_num_bits,
1067						nvm_param.dl_num_bytes);
1068		} else {
1069			if (resp->cmd_err ==
1070				NVM_GET_VARIABLE_CMD_ERR_CODE_VAR_NOT_EXIST)
1071				rc = -EOPNOTSUPP;
1072		}
1073	}
1074	hwrm_req_drop(bp, req);
1075	if (rc == -EACCES)
1076		netdev_err(bp->dev, "PF does not have admin privileges to modify NVM config\n");
1077	return rc;
1078}
1079
1080static int bnxt_dl_nvm_param_get(struct devlink *dl, u32 id,
1081				 struct devlink_param_gset_ctx *ctx)
1082{
1083	struct bnxt *bp = bnxt_get_bp_from_dl(dl);
1084	struct hwrm_nvm_get_variable_input *req;
1085	int rc;
1086
1087	rc = hwrm_req_init(bp, req, HWRM_NVM_GET_VARIABLE);
1088	if (rc)
1089		return rc;
1090
1091	rc = bnxt_hwrm_nvm_req(bp, id, req, &ctx->val);
1092	if (!rc && id == BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK)
1093		ctx->val.vbool = !ctx->val.vbool;
1094
1095	return rc;
1096}
1097
1098static int bnxt_dl_nvm_param_set(struct devlink *dl, u32 id,
1099				 struct devlink_param_gset_ctx *ctx)
1100{
1101	struct bnxt *bp = bnxt_get_bp_from_dl(dl);
1102	struct hwrm_nvm_set_variable_input *req;
1103	int rc;
1104
1105	rc = hwrm_req_init(bp, req, HWRM_NVM_SET_VARIABLE);
1106	if (rc)
1107		return rc;
1108
1109	if (id == BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK)
1110		ctx->val.vbool = !ctx->val.vbool;
1111
1112	return bnxt_hwrm_nvm_req(bp, id, req, &ctx->val);
1113}
1114
1115static int bnxt_dl_msix_validate(struct devlink *dl, u32 id,
1116				 union devlink_param_value val,
1117				 struct netlink_ext_ack *extack)
1118{
1119	int max_val = -1;
1120
1121	if (id == DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX)
1122		max_val = BNXT_MSIX_VEC_MAX;
1123
1124	if (id == DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN)
1125		max_val = BNXT_MSIX_VEC_MIN_MAX;
1126
1127	if (val.vu32 > max_val) {
1128		NL_SET_ERR_MSG_MOD(extack, "MSIX value is exceeding the range");
1129		return -EINVAL;
1130	}
1131
1132	return 0;
1133}
1134
1135static int bnxt_remote_dev_reset_get(struct devlink *dl, u32 id,
1136				     struct devlink_param_gset_ctx *ctx)
1137{
1138	struct bnxt *bp = bnxt_get_bp_from_dl(dl);
1139
1140	if (~bp->fw_cap & BNXT_FW_CAP_HOT_RESET_IF)
1141		return -EOPNOTSUPP;
1142
1143	ctx->val.vbool = bnxt_dl_get_remote_reset(dl);
1144	return 0;
1145}
1146
1147static int bnxt_remote_dev_reset_set(struct devlink *dl, u32 id,
1148				     struct devlink_param_gset_ctx *ctx)
1149{
1150	struct bnxt *bp = bnxt_get_bp_from_dl(dl);
1151	int rc;
1152
1153	rc = bnxt_hwrm_remote_dev_reset_set(bp, ctx->val.vbool);
1154	if (rc)
1155		return rc;
1156
1157	bnxt_dl_set_remote_reset(dl, ctx->val.vbool);
1158	return rc;
1159}
1160
1161static const struct devlink_param bnxt_dl_params[] = {
1162	DEVLINK_PARAM_GENERIC(ENABLE_SRIOV,
1163			      BIT(DEVLINK_PARAM_CMODE_PERMANENT),
1164			      bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set,
1165			      NULL),
1166	DEVLINK_PARAM_GENERIC(IGNORE_ARI,
1167			      BIT(DEVLINK_PARAM_CMODE_PERMANENT),
1168			      bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set,
1169			      NULL),
1170	DEVLINK_PARAM_GENERIC(MSIX_VEC_PER_PF_MAX,
1171			      BIT(DEVLINK_PARAM_CMODE_PERMANENT),
1172			      bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set,
1173			      bnxt_dl_msix_validate),
1174	DEVLINK_PARAM_GENERIC(MSIX_VEC_PER_PF_MIN,
1175			      BIT(DEVLINK_PARAM_CMODE_PERMANENT),
1176			      bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set,
1177			      bnxt_dl_msix_validate),
1178	DEVLINK_PARAM_DRIVER(BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK,
1179			     "gre_ver_check", DEVLINK_PARAM_TYPE_BOOL,
1180			     BIT(DEVLINK_PARAM_CMODE_PERMANENT),
1181			     bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set,
1182			     NULL),
1183	/* keep REMOTE_DEV_RESET last, it is excluded based on caps */
1184	DEVLINK_PARAM_GENERIC(ENABLE_REMOTE_DEV_RESET,
1185			      BIT(DEVLINK_PARAM_CMODE_RUNTIME),
1186			      bnxt_remote_dev_reset_get,
1187			      bnxt_remote_dev_reset_set, NULL),
1188};
1189
1190static int bnxt_dl_params_register(struct bnxt *bp)
1191{
1192	int num_params = ARRAY_SIZE(bnxt_dl_params);
1193	int rc;
1194
1195	if (bp->hwrm_spec_code < 0x10600)
1196		return 0;
1197
1198	if (~bp->fw_cap & BNXT_FW_CAP_HOT_RESET_IF)
1199		num_params--;
1200
1201	rc = devlink_params_register(bp->dl, bnxt_dl_params, num_params);
1202	if (rc)
1203		netdev_warn(bp->dev, "devlink_params_register failed. rc=%d\n",
1204			    rc);
1205	return rc;
1206}
1207
1208static void bnxt_dl_params_unregister(struct bnxt *bp)
1209{
1210	int num_params = ARRAY_SIZE(bnxt_dl_params);
1211
1212	if (bp->hwrm_spec_code < 0x10600)
1213		return;
1214
1215	if (~bp->fw_cap & BNXT_FW_CAP_HOT_RESET_IF)
1216		num_params--;
1217
1218	devlink_params_unregister(bp->dl, bnxt_dl_params, num_params);
1219}
1220
1221int bnxt_dl_register(struct bnxt *bp)
1222{
1223	const struct devlink_ops *devlink_ops;
1224	struct devlink_port_attrs attrs = {};
1225	struct bnxt_dl *bp_dl;
1226	struct devlink *dl;
1227	int rc;
1228
1229	if (BNXT_PF(bp))
1230		devlink_ops = &bnxt_dl_ops;
1231	else
1232		devlink_ops = &bnxt_vf_dl_ops;
1233
1234	dl = devlink_alloc(devlink_ops, sizeof(struct bnxt_dl), &bp->pdev->dev);
1235	if (!dl) {
1236		netdev_warn(bp->dev, "devlink_alloc failed\n");
1237		return -ENOMEM;
1238	}
1239
1240	bp->dl = dl;
1241	bp_dl = devlink_priv(dl);
1242	bp_dl->bp = bp;
1243	bnxt_dl_set_remote_reset(dl, true);
1244
1245	/* Add switchdev eswitch mode setting, if SRIOV supported */
1246	if (pci_find_ext_capability(bp->pdev, PCI_EXT_CAP_ID_SRIOV) &&
1247	    bp->hwrm_spec_code > 0x10803)
1248		bp->eswitch_mode = DEVLINK_ESWITCH_MODE_LEGACY;
1249
1250	if (!BNXT_PF(bp))
1251		goto out;
1252
1253	attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
1254	attrs.phys.port_number = bp->pf.port_id;
1255	memcpy(attrs.switch_id.id, bp->dsn, sizeof(bp->dsn));
1256	attrs.switch_id.id_len = sizeof(bp->dsn);
1257	devlink_port_attrs_set(&bp->dl_port, &attrs);
1258	rc = devlink_port_register(dl, &bp->dl_port, bp->pf.port_id);
1259	if (rc) {
1260		netdev_err(bp->dev, "devlink_port_register failed\n");
1261		goto err_dl_free;
1262	}
1263
1264	rc = bnxt_dl_params_register(bp);
1265	if (rc)
1266		goto err_dl_port_unreg;
1267
1268out:
1269	devlink_register(dl);
1270	return 0;
1271
1272err_dl_port_unreg:
1273	devlink_port_unregister(&bp->dl_port);
1274err_dl_free:
1275	devlink_free(dl);
1276	return rc;
1277}
1278
1279void bnxt_dl_unregister(struct bnxt *bp)
1280{
1281	struct devlink *dl = bp->dl;
1282
1283	devlink_unregister(dl);
1284	if (BNXT_PF(bp)) {
1285		bnxt_dl_params_unregister(bp);
1286		devlink_port_unregister(&bp->dl_port);
1287	}
1288	devlink_free(dl);
1289}
1290