Merge branch 'work.d_path' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[linux-2.6-microblaze.git] / drivers / net / ethernet / broadcom / bnxt / bnxt_devlink.c
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 <net/devlink.h>
13 #include "bnxt_hsi.h"
14 #include "bnxt.h"
15 #include "bnxt_vfr.h"
16 #include "bnxt_devlink.h"
17 #include "bnxt_ethtool.h"
18
19 static int
20 bnxt_dl_flash_update(struct devlink *dl,
21                      struct devlink_flash_update_params *params,
22                      struct netlink_ext_ack *extack)
23 {
24         struct bnxt *bp = bnxt_get_bp_from_dl(dl);
25         int rc;
26
27         if (!BNXT_PF(bp)) {
28                 NL_SET_ERR_MSG_MOD(extack,
29                                    "flash update not supported from a VF");
30                 return -EPERM;
31         }
32
33         devlink_flash_update_status_notify(dl, "Preparing to flash", NULL, 0, 0);
34         rc = bnxt_flash_package_from_fw_obj(bp->dev, params->fw, 0);
35         if (!rc)
36                 devlink_flash_update_status_notify(dl, "Flashing done", NULL, 0, 0);
37         else
38                 devlink_flash_update_status_notify(dl, "Flashing failed", NULL, 0, 0);
39         return rc;
40 }
41
42 static int bnxt_fw_reporter_diagnose(struct devlink_health_reporter *reporter,
43                                      struct devlink_fmsg *fmsg,
44                                      struct netlink_ext_ack *extack)
45 {
46         struct bnxt *bp = devlink_health_reporter_priv(reporter);
47         u32 val;
48         int rc;
49
50         if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))
51                 return 0;
52
53         val = bnxt_fw_health_readl(bp, BNXT_FW_HEALTH_REG);
54
55         if (BNXT_FW_IS_BOOTING(val)) {
56                 rc = devlink_fmsg_string_pair_put(fmsg, "Description",
57                                                   "Not yet completed initialization");
58                 if (rc)
59                         return rc;
60         } else if (BNXT_FW_IS_ERR(val)) {
61                 rc = devlink_fmsg_string_pair_put(fmsg, "Description",
62                                                   "Encountered fatal error and cannot recover");
63                 if (rc)
64                         return rc;
65         }
66
67         if (val >> 16) {
68                 rc = devlink_fmsg_u32_pair_put(fmsg, "Error code", val >> 16);
69                 if (rc)
70                         return rc;
71         }
72
73         val = bnxt_fw_health_readl(bp, BNXT_FW_RESET_CNT_REG);
74         rc = devlink_fmsg_u32_pair_put(fmsg, "Reset count", val);
75         if (rc)
76                 return rc;
77
78         return 0;
79 }
80
81 static const struct devlink_health_reporter_ops bnxt_dl_fw_reporter_ops = {
82         .name = "fw",
83         .diagnose = bnxt_fw_reporter_diagnose,
84 };
85
86 static int bnxt_fw_reset_recover(struct devlink_health_reporter *reporter,
87                                  void *priv_ctx,
88                                  struct netlink_ext_ack *extack)
89 {
90         struct bnxt *bp = devlink_health_reporter_priv(reporter);
91
92         if (!priv_ctx)
93                 return -EOPNOTSUPP;
94
95         bnxt_fw_reset(bp);
96         return -EINPROGRESS;
97 }
98
99 static const
100 struct devlink_health_reporter_ops bnxt_dl_fw_reset_reporter_ops = {
101         .name = "fw_reset",
102         .recover = bnxt_fw_reset_recover,
103 };
104
105 static int bnxt_fw_fatal_recover(struct devlink_health_reporter *reporter,
106                                  void *priv_ctx,
107                                  struct netlink_ext_ack *extack)
108 {
109         struct bnxt *bp = devlink_health_reporter_priv(reporter);
110         struct bnxt_fw_reporter_ctx *fw_reporter_ctx = priv_ctx;
111         unsigned long event;
112
113         if (!priv_ctx)
114                 return -EOPNOTSUPP;
115
116         bp->fw_health->fatal = true;
117         event = fw_reporter_ctx->sp_event;
118         if (event == BNXT_FW_RESET_NOTIFY_SP_EVENT)
119                 bnxt_fw_reset(bp);
120         else if (event == BNXT_FW_EXCEPTION_SP_EVENT)
121                 bnxt_fw_exception(bp);
122
123         return -EINPROGRESS;
124 }
125
126 static const
127 struct devlink_health_reporter_ops bnxt_dl_fw_fatal_reporter_ops = {
128         .name = "fw_fatal",
129         .recover = bnxt_fw_fatal_recover,
130 };
131
132 void bnxt_dl_fw_reporters_create(struct bnxt *bp)
133 {
134         struct bnxt_fw_health *health = bp->fw_health;
135
136         if (!bp->dl || !health)
137                 return;
138
139         if (!(bp->fw_cap & BNXT_FW_CAP_HOT_RESET) || health->fw_reset_reporter)
140                 goto err_recovery;
141
142         health->fw_reset_reporter =
143                 devlink_health_reporter_create(bp->dl,
144                                                &bnxt_dl_fw_reset_reporter_ops,
145                                                0, bp);
146         if (IS_ERR(health->fw_reset_reporter)) {
147                 netdev_warn(bp->dev, "Failed to create FW fatal health reporter, rc = %ld\n",
148                             PTR_ERR(health->fw_reset_reporter));
149                 health->fw_reset_reporter = NULL;
150                 bp->fw_cap &= ~BNXT_FW_CAP_HOT_RESET;
151         }
152
153 err_recovery:
154         if (!(bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY))
155                 return;
156
157         if (!health->fw_reporter) {
158                 health->fw_reporter =
159                         devlink_health_reporter_create(bp->dl,
160                                                        &bnxt_dl_fw_reporter_ops,
161                                                        0, bp);
162                 if (IS_ERR(health->fw_reporter)) {
163                         netdev_warn(bp->dev, "Failed to create FW health reporter, rc = %ld\n",
164                                     PTR_ERR(health->fw_reporter));
165                         health->fw_reporter = NULL;
166                         bp->fw_cap &= ~BNXT_FW_CAP_ERROR_RECOVERY;
167                         return;
168                 }
169         }
170
171         if (health->fw_fatal_reporter)
172                 return;
173
174         health->fw_fatal_reporter =
175                 devlink_health_reporter_create(bp->dl,
176                                                &bnxt_dl_fw_fatal_reporter_ops,
177                                                0, bp);
178         if (IS_ERR(health->fw_fatal_reporter)) {
179                 netdev_warn(bp->dev, "Failed to create FW fatal health reporter, rc = %ld\n",
180                             PTR_ERR(health->fw_fatal_reporter));
181                 health->fw_fatal_reporter = NULL;
182                 bp->fw_cap &= ~BNXT_FW_CAP_ERROR_RECOVERY;
183         }
184 }
185
186 void bnxt_dl_fw_reporters_destroy(struct bnxt *bp, bool all)
187 {
188         struct bnxt_fw_health *health = bp->fw_health;
189
190         if (!bp->dl || !health)
191                 return;
192
193         if ((all || !(bp->fw_cap & BNXT_FW_CAP_HOT_RESET)) &&
194             health->fw_reset_reporter) {
195                 devlink_health_reporter_destroy(health->fw_reset_reporter);
196                 health->fw_reset_reporter = NULL;
197         }
198
199         if ((bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY) && !all)
200                 return;
201
202         if (health->fw_reporter) {
203                 devlink_health_reporter_destroy(health->fw_reporter);
204                 health->fw_reporter = NULL;
205         }
206
207         if (health->fw_fatal_reporter) {
208                 devlink_health_reporter_destroy(health->fw_fatal_reporter);
209                 health->fw_fatal_reporter = NULL;
210         }
211 }
212
213 void bnxt_devlink_health_report(struct bnxt *bp, unsigned long event)
214 {
215         struct bnxt_fw_health *fw_health = bp->fw_health;
216         struct bnxt_fw_reporter_ctx fw_reporter_ctx;
217
218         fw_reporter_ctx.sp_event = event;
219         switch (event) {
220         case BNXT_FW_RESET_NOTIFY_SP_EVENT:
221                 if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state)) {
222                         if (!fw_health->fw_fatal_reporter)
223                                 return;
224
225                         devlink_health_report(fw_health->fw_fatal_reporter,
226                                               "FW fatal async event received",
227                                               &fw_reporter_ctx);
228                         return;
229                 }
230                 if (!fw_health->fw_reset_reporter)
231                         return;
232
233                 devlink_health_report(fw_health->fw_reset_reporter,
234                                       "FW non-fatal reset event received",
235                                       &fw_reporter_ctx);
236                 return;
237
238         case BNXT_FW_EXCEPTION_SP_EVENT:
239                 if (!fw_health->fw_fatal_reporter)
240                         return;
241
242                 devlink_health_report(fw_health->fw_fatal_reporter,
243                                       "FW fatal error reported",
244                                       &fw_reporter_ctx);
245                 return;
246         }
247 }
248
249 void bnxt_dl_health_status_update(struct bnxt *bp, bool healthy)
250 {
251         struct bnxt_fw_health *health = bp->fw_health;
252         u8 state;
253
254         if (healthy)
255                 state = DEVLINK_HEALTH_REPORTER_STATE_HEALTHY;
256         else
257                 state = DEVLINK_HEALTH_REPORTER_STATE_ERROR;
258
259         if (health->fatal)
260                 devlink_health_reporter_state_update(health->fw_fatal_reporter,
261                                                      state);
262         else
263                 devlink_health_reporter_state_update(health->fw_reset_reporter,
264                                                      state);
265
266         health->fatal = false;
267 }
268
269 void bnxt_dl_health_recovery_done(struct bnxt *bp)
270 {
271         struct bnxt_fw_health *hlth = bp->fw_health;
272
273         if (hlth->fatal)
274                 devlink_health_reporter_recovery_done(hlth->fw_fatal_reporter);
275         else
276                 devlink_health_reporter_recovery_done(hlth->fw_reset_reporter);
277 }
278
279 static int bnxt_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
280                             struct netlink_ext_ack *extack);
281
282 static const struct devlink_ops bnxt_dl_ops = {
283 #ifdef CONFIG_BNXT_SRIOV
284         .eswitch_mode_set = bnxt_dl_eswitch_mode_set,
285         .eswitch_mode_get = bnxt_dl_eswitch_mode_get,
286 #endif /* CONFIG_BNXT_SRIOV */
287         .info_get         = bnxt_dl_info_get,
288         .flash_update     = bnxt_dl_flash_update,
289 };
290
291 static const struct devlink_ops bnxt_vf_dl_ops;
292
293 enum bnxt_dl_param_id {
294         BNXT_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
295         BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK,
296 };
297
298 static const struct bnxt_dl_nvm_param nvm_params[] = {
299         {DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV, NVM_OFF_ENABLE_SRIOV,
300          BNXT_NVM_SHARED_CFG, 1, 1},
301         {DEVLINK_PARAM_GENERIC_ID_IGNORE_ARI, NVM_OFF_IGNORE_ARI,
302          BNXT_NVM_SHARED_CFG, 1, 1},
303         {DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX,
304          NVM_OFF_MSIX_VEC_PER_PF_MAX, BNXT_NVM_SHARED_CFG, 10, 4},
305         {DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN,
306          NVM_OFF_MSIX_VEC_PER_PF_MIN, BNXT_NVM_SHARED_CFG, 7, 4},
307         {BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK, NVM_OFF_DIS_GRE_VER_CHECK,
308          BNXT_NVM_SHARED_CFG, 1, 1},
309 };
310
311 union bnxt_nvm_data {
312         u8      val8;
313         __le32  val32;
314 };
315
316 static void bnxt_copy_to_nvm_data(union bnxt_nvm_data *dst,
317                                   union devlink_param_value *src,
318                                   int nvm_num_bits, int dl_num_bytes)
319 {
320         u32 val32 = 0;
321
322         if (nvm_num_bits == 1) {
323                 dst->val8 = src->vbool;
324                 return;
325         }
326         if (dl_num_bytes == 4)
327                 val32 = src->vu32;
328         else if (dl_num_bytes == 2)
329                 val32 = (u32)src->vu16;
330         else if (dl_num_bytes == 1)
331                 val32 = (u32)src->vu8;
332         dst->val32 = cpu_to_le32(val32);
333 }
334
335 static void bnxt_copy_from_nvm_data(union devlink_param_value *dst,
336                                     union bnxt_nvm_data *src,
337                                     int nvm_num_bits, int dl_num_bytes)
338 {
339         u32 val32;
340
341         if (nvm_num_bits == 1) {
342                 dst->vbool = src->val8;
343                 return;
344         }
345         val32 = le32_to_cpu(src->val32);
346         if (dl_num_bytes == 4)
347                 dst->vu32 = val32;
348         else if (dl_num_bytes == 2)
349                 dst->vu16 = (u16)val32;
350         else if (dl_num_bytes == 1)
351                 dst->vu8 = (u8)val32;
352 }
353
354 static int bnxt_hwrm_get_nvm_cfg_ver(struct bnxt *bp,
355                                      union devlink_param_value *nvm_cfg_ver)
356 {
357         struct hwrm_nvm_get_variable_input req = {0};
358         union bnxt_nvm_data *data;
359         dma_addr_t data_dma_addr;
360         int rc;
361
362         bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_GET_VARIABLE, -1, -1);
363         data = dma_alloc_coherent(&bp->pdev->dev, sizeof(*data),
364                                   &data_dma_addr, GFP_KERNEL);
365         if (!data)
366                 return -ENOMEM;
367
368         req.dest_data_addr = cpu_to_le64(data_dma_addr);
369         req.data_len = cpu_to_le16(BNXT_NVM_CFG_VER_BITS);
370         req.option_num = cpu_to_le16(NVM_OFF_NVM_CFG_VER);
371
372         rc = hwrm_send_message_silent(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
373         if (!rc)
374                 bnxt_copy_from_nvm_data(nvm_cfg_ver, data,
375                                         BNXT_NVM_CFG_VER_BITS,
376                                         BNXT_NVM_CFG_VER_BYTES);
377
378         dma_free_coherent(&bp->pdev->dev, sizeof(*data), data, data_dma_addr);
379         return rc;
380 }
381
382 static int bnxt_dl_info_put(struct bnxt *bp, struct devlink_info_req *req,
383                             enum bnxt_dl_version_type type, const char *key,
384                             char *buf)
385 {
386         if (!strlen(buf))
387                 return 0;
388
389         if ((bp->flags & BNXT_FLAG_CHIP_P5) &&
390             (!strcmp(key, DEVLINK_INFO_VERSION_GENERIC_FW_NCSI) ||
391              !strcmp(key, DEVLINK_INFO_VERSION_GENERIC_FW_ROCE)))
392                 return 0;
393
394         switch (type) {
395         case BNXT_VERSION_FIXED:
396                 return devlink_info_version_fixed_put(req, key, buf);
397         case BNXT_VERSION_RUNNING:
398                 return devlink_info_version_running_put(req, key, buf);
399         case BNXT_VERSION_STORED:
400                 return devlink_info_version_stored_put(req, key, buf);
401         }
402         return 0;
403 }
404
405 #define HWRM_FW_VER_STR_LEN     16
406
407 static int bnxt_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
408                             struct netlink_ext_ack *extack)
409 {
410         struct hwrm_nvm_get_dev_info_output nvm_dev_info;
411         struct bnxt *bp = bnxt_get_bp_from_dl(dl);
412         union devlink_param_value nvm_cfg_ver;
413         struct hwrm_ver_get_output *ver_resp;
414         char mgmt_ver[FW_VER_STR_LEN];
415         char roce_ver[FW_VER_STR_LEN];
416         char ncsi_ver[FW_VER_STR_LEN];
417         char buf[32];
418         int rc;
419
420         rc = devlink_info_driver_name_put(req, DRV_MODULE_NAME);
421         if (rc)
422                 return rc;
423
424         if (BNXT_PF(bp) && (bp->flags & BNXT_FLAG_DSN_VALID)) {
425                 sprintf(buf, "%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X",
426                         bp->dsn[7], bp->dsn[6], bp->dsn[5], bp->dsn[4],
427                         bp->dsn[3], bp->dsn[2], bp->dsn[1], bp->dsn[0]);
428                 rc = devlink_info_serial_number_put(req, buf);
429                 if (rc)
430                         return rc;
431         }
432
433         if (strlen(bp->board_serialno)) {
434                 rc = devlink_info_board_serial_number_put(req, bp->board_serialno);
435                 if (rc)
436                         return rc;
437         }
438
439         rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_FIXED,
440                               DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,
441                               bp->board_partno);
442         if (rc)
443                 return rc;
444
445         sprintf(buf, "%X", bp->chip_num);
446         rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_FIXED,
447                               DEVLINK_INFO_VERSION_GENERIC_ASIC_ID, buf);
448         if (rc)
449                 return rc;
450
451         ver_resp = &bp->ver_resp;
452         sprintf(buf, "%X", ver_resp->chip_rev);
453         rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_FIXED,
454                               DEVLINK_INFO_VERSION_GENERIC_ASIC_REV, buf);
455         if (rc)
456                 return rc;
457
458         rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_RUNNING,
459                               DEVLINK_INFO_VERSION_GENERIC_FW_PSID,
460                               bp->nvm_cfg_ver);
461         if (rc)
462                 return rc;
463
464         buf[0] = 0;
465         strncat(buf, ver_resp->active_pkg_name, HWRM_FW_VER_STR_LEN);
466         rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_RUNNING,
467                               DEVLINK_INFO_VERSION_GENERIC_FW, buf);
468         if (rc)
469                 return rc;
470
471         if (BNXT_PF(bp) && !bnxt_hwrm_get_nvm_cfg_ver(bp, &nvm_cfg_ver)) {
472                 u32 ver = nvm_cfg_ver.vu32;
473
474                 sprintf(buf, "%d.%d.%d", (ver >> 16) & 0xf, (ver >> 8) & 0xf,
475                         ver & 0xf);
476                 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED,
477                                       DEVLINK_INFO_VERSION_GENERIC_FW_PSID,
478                                       buf);
479                 if (rc)
480                         return rc;
481         }
482
483         if (ver_resp->flags & VER_GET_RESP_FLAGS_EXT_VER_AVAIL) {
484                 snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
485                          ver_resp->hwrm_fw_major, ver_resp->hwrm_fw_minor,
486                          ver_resp->hwrm_fw_build, ver_resp->hwrm_fw_patch);
487
488                 snprintf(ncsi_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
489                          ver_resp->mgmt_fw_major, ver_resp->mgmt_fw_minor,
490                          ver_resp->mgmt_fw_build, ver_resp->mgmt_fw_patch);
491
492                 snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
493                          ver_resp->roce_fw_major, ver_resp->roce_fw_minor,
494                          ver_resp->roce_fw_build, ver_resp->roce_fw_patch);
495         } else {
496                 snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
497                          ver_resp->hwrm_fw_maj_8b, ver_resp->hwrm_fw_min_8b,
498                          ver_resp->hwrm_fw_bld_8b, ver_resp->hwrm_fw_rsvd_8b);
499
500                 snprintf(ncsi_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
501                          ver_resp->mgmt_fw_maj_8b, ver_resp->mgmt_fw_min_8b,
502                          ver_resp->mgmt_fw_bld_8b, ver_resp->mgmt_fw_rsvd_8b);
503
504                 snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
505                          ver_resp->roce_fw_maj_8b, ver_resp->roce_fw_min_8b,
506                          ver_resp->roce_fw_bld_8b, ver_resp->roce_fw_rsvd_8b);
507         }
508         rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_RUNNING,
509                               DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, mgmt_ver);
510         if (rc)
511                 return rc;
512
513         rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_RUNNING,
514                               DEVLINK_INFO_VERSION_GENERIC_FW_MGMT_API,
515                               bp->hwrm_ver_supp);
516         if (rc)
517                 return rc;
518
519         rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_RUNNING,
520                               DEVLINK_INFO_VERSION_GENERIC_FW_NCSI, ncsi_ver);
521         if (rc)
522                 return rc;
523
524         rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_RUNNING,
525                               DEVLINK_INFO_VERSION_GENERIC_FW_ROCE, roce_ver);
526         if (rc)
527                 return rc;
528
529         rc = bnxt_hwrm_nvm_get_dev_info(bp, &nvm_dev_info);
530         if (rc ||
531             !(nvm_dev_info.flags & NVM_GET_DEV_INFO_RESP_FLAGS_FW_VER_VALID))
532                 return 0;
533
534         buf[0] = 0;
535         strncat(buf, nvm_dev_info.pkg_name, HWRM_FW_VER_STR_LEN);
536         rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED,
537                               DEVLINK_INFO_VERSION_GENERIC_FW, buf);
538         if (rc)
539                 return rc;
540
541         snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
542                  nvm_dev_info.hwrm_fw_major, nvm_dev_info.hwrm_fw_minor,
543                  nvm_dev_info.hwrm_fw_build, nvm_dev_info.hwrm_fw_patch);
544         rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED,
545                               DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, mgmt_ver);
546         if (rc)
547                 return rc;
548
549         snprintf(ncsi_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
550                  nvm_dev_info.mgmt_fw_major, nvm_dev_info.mgmt_fw_minor,
551                  nvm_dev_info.mgmt_fw_build, nvm_dev_info.mgmt_fw_patch);
552         rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED,
553                               DEVLINK_INFO_VERSION_GENERIC_FW_NCSI, ncsi_ver);
554         if (rc)
555                 return rc;
556
557         snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d",
558                  nvm_dev_info.roce_fw_major, nvm_dev_info.roce_fw_minor,
559                  nvm_dev_info.roce_fw_build, nvm_dev_info.roce_fw_patch);
560         return bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED,
561                                 DEVLINK_INFO_VERSION_GENERIC_FW_ROCE, roce_ver);
562 }
563
564 static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg,
565                              int msg_len, union devlink_param_value *val)
566 {
567         struct hwrm_nvm_get_variable_input *req = msg;
568         struct bnxt_dl_nvm_param nvm_param;
569         union bnxt_nvm_data *data;
570         dma_addr_t data_dma_addr;
571         int idx = 0, rc, i;
572
573         /* Get/Set NVM CFG parameter is supported only on PFs */
574         if (BNXT_VF(bp))
575                 return -EPERM;
576
577         for (i = 0; i < ARRAY_SIZE(nvm_params); i++) {
578                 if (nvm_params[i].id == param_id) {
579                         nvm_param = nvm_params[i];
580                         break;
581                 }
582         }
583
584         if (i == ARRAY_SIZE(nvm_params))
585                 return -EOPNOTSUPP;
586
587         if (nvm_param.dir_type == BNXT_NVM_PORT_CFG)
588                 idx = bp->pf.port_id;
589         else if (nvm_param.dir_type == BNXT_NVM_FUNC_CFG)
590                 idx = bp->pf.fw_fid - BNXT_FIRST_PF_FID;
591
592         data = dma_alloc_coherent(&bp->pdev->dev, sizeof(*data),
593                                   &data_dma_addr, GFP_KERNEL);
594         if (!data)
595                 return -ENOMEM;
596
597         req->dest_data_addr = cpu_to_le64(data_dma_addr);
598         req->data_len = cpu_to_le16(nvm_param.nvm_num_bits);
599         req->option_num = cpu_to_le16(nvm_param.offset);
600         req->index_0 = cpu_to_le16(idx);
601         if (idx)
602                 req->dimensions = cpu_to_le16(1);
603
604         if (req->req_type == cpu_to_le16(HWRM_NVM_SET_VARIABLE)) {
605                 bnxt_copy_to_nvm_data(data, val, nvm_param.nvm_num_bits,
606                                       nvm_param.dl_num_bytes);
607                 rc = hwrm_send_message(bp, msg, msg_len, HWRM_CMD_TIMEOUT);
608         } else {
609                 rc = hwrm_send_message_silent(bp, msg, msg_len,
610                                               HWRM_CMD_TIMEOUT);
611                 if (!rc) {
612                         bnxt_copy_from_nvm_data(val, data,
613                                                 nvm_param.nvm_num_bits,
614                                                 nvm_param.dl_num_bytes);
615                 } else {
616                         struct hwrm_err_output *resp = bp->hwrm_cmd_resp_addr;
617
618                         if (resp->cmd_err ==
619                                 NVM_GET_VARIABLE_CMD_ERR_CODE_VAR_NOT_EXIST)
620                                 rc = -EOPNOTSUPP;
621                 }
622         }
623         dma_free_coherent(&bp->pdev->dev, sizeof(*data), data, data_dma_addr);
624         if (rc == -EACCES)
625                 netdev_err(bp->dev, "PF does not have admin privileges to modify NVM config\n");
626         return rc;
627 }
628
629 static int bnxt_dl_nvm_param_get(struct devlink *dl, u32 id,
630                                  struct devlink_param_gset_ctx *ctx)
631 {
632         struct hwrm_nvm_get_variable_input req = {0};
633         struct bnxt *bp = bnxt_get_bp_from_dl(dl);
634         int rc;
635
636         bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_GET_VARIABLE, -1, -1);
637         rc = bnxt_hwrm_nvm_req(bp, id, &req, sizeof(req), &ctx->val);
638         if (!rc)
639                 if (id == BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK)
640                         ctx->val.vbool = !ctx->val.vbool;
641
642         return rc;
643 }
644
645 static int bnxt_dl_nvm_param_set(struct devlink *dl, u32 id,
646                                  struct devlink_param_gset_ctx *ctx)
647 {
648         struct hwrm_nvm_set_variable_input req = {0};
649         struct bnxt *bp = bnxt_get_bp_from_dl(dl);
650
651         bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_SET_VARIABLE, -1, -1);
652
653         if (id == BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK)
654                 ctx->val.vbool = !ctx->val.vbool;
655
656         return bnxt_hwrm_nvm_req(bp, id, &req, sizeof(req), &ctx->val);
657 }
658
659 static int bnxt_dl_msix_validate(struct devlink *dl, u32 id,
660                                  union devlink_param_value val,
661                                  struct netlink_ext_ack *extack)
662 {
663         int max_val = -1;
664
665         if (id == DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX)
666                 max_val = BNXT_MSIX_VEC_MAX;
667
668         if (id == DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN)
669                 max_val = BNXT_MSIX_VEC_MIN_MAX;
670
671         if (val.vu32 > max_val) {
672                 NL_SET_ERR_MSG_MOD(extack, "MSIX value is exceeding the range");
673                 return -EINVAL;
674         }
675
676         return 0;
677 }
678
679 static const struct devlink_param bnxt_dl_params[] = {
680         DEVLINK_PARAM_GENERIC(ENABLE_SRIOV,
681                               BIT(DEVLINK_PARAM_CMODE_PERMANENT),
682                               bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set,
683                               NULL),
684         DEVLINK_PARAM_GENERIC(IGNORE_ARI,
685                               BIT(DEVLINK_PARAM_CMODE_PERMANENT),
686                               bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set,
687                               NULL),
688         DEVLINK_PARAM_GENERIC(MSIX_VEC_PER_PF_MAX,
689                               BIT(DEVLINK_PARAM_CMODE_PERMANENT),
690                               bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set,
691                               bnxt_dl_msix_validate),
692         DEVLINK_PARAM_GENERIC(MSIX_VEC_PER_PF_MIN,
693                               BIT(DEVLINK_PARAM_CMODE_PERMANENT),
694                               bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set,
695                               bnxt_dl_msix_validate),
696         DEVLINK_PARAM_DRIVER(BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK,
697                              "gre_ver_check", DEVLINK_PARAM_TYPE_BOOL,
698                              BIT(DEVLINK_PARAM_CMODE_PERMANENT),
699                              bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set,
700                              NULL),
701 };
702
703 static const struct devlink_param bnxt_dl_port_params[] = {
704 };
705
706 static int bnxt_dl_params_register(struct bnxt *bp)
707 {
708         int rc;
709
710         if (bp->hwrm_spec_code < 0x10600)
711                 return 0;
712
713         rc = devlink_params_register(bp->dl, bnxt_dl_params,
714                                      ARRAY_SIZE(bnxt_dl_params));
715         if (rc) {
716                 netdev_warn(bp->dev, "devlink_params_register failed. rc=%d\n",
717                             rc);
718                 return rc;
719         }
720         rc = devlink_port_params_register(&bp->dl_port, bnxt_dl_port_params,
721                                           ARRAY_SIZE(bnxt_dl_port_params));
722         if (rc) {
723                 netdev_err(bp->dev, "devlink_port_params_register failed\n");
724                 devlink_params_unregister(bp->dl, bnxt_dl_params,
725                                           ARRAY_SIZE(bnxt_dl_params));
726                 return rc;
727         }
728         devlink_params_publish(bp->dl);
729
730         return 0;
731 }
732
733 static void bnxt_dl_params_unregister(struct bnxt *bp)
734 {
735         if (bp->hwrm_spec_code < 0x10600)
736                 return;
737
738         devlink_params_unregister(bp->dl, bnxt_dl_params,
739                                   ARRAY_SIZE(bnxt_dl_params));
740         devlink_port_params_unregister(&bp->dl_port, bnxt_dl_port_params,
741                                        ARRAY_SIZE(bnxt_dl_port_params));
742 }
743
744 int bnxt_dl_register(struct bnxt *bp)
745 {
746         struct devlink_port_attrs attrs = {};
747         struct devlink *dl;
748         int rc;
749
750         if (BNXT_PF(bp))
751                 dl = devlink_alloc(&bnxt_dl_ops, sizeof(struct bnxt_dl));
752         else
753                 dl = devlink_alloc(&bnxt_vf_dl_ops, sizeof(struct bnxt_dl));
754         if (!dl) {
755                 netdev_warn(bp->dev, "devlink_alloc failed\n");
756                 return -ENOMEM;
757         }
758
759         bnxt_link_bp_to_dl(bp, dl);
760
761         /* Add switchdev eswitch mode setting, if SRIOV supported */
762         if (pci_find_ext_capability(bp->pdev, PCI_EXT_CAP_ID_SRIOV) &&
763             bp->hwrm_spec_code > 0x10803)
764                 bp->eswitch_mode = DEVLINK_ESWITCH_MODE_LEGACY;
765
766         rc = devlink_register(dl, &bp->pdev->dev);
767         if (rc) {
768                 netdev_warn(bp->dev, "devlink_register failed. rc=%d\n", rc);
769                 goto err_dl_free;
770         }
771
772         if (!BNXT_PF(bp))
773                 return 0;
774
775         attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
776         attrs.phys.port_number = bp->pf.port_id;
777         memcpy(attrs.switch_id.id, bp->dsn, sizeof(bp->dsn));
778         attrs.switch_id.id_len = sizeof(bp->dsn);
779         devlink_port_attrs_set(&bp->dl_port, &attrs);
780         rc = devlink_port_register(dl, &bp->dl_port, bp->pf.port_id);
781         if (rc) {
782                 netdev_err(bp->dev, "devlink_port_register failed\n");
783                 goto err_dl_unreg;
784         }
785
786         rc = bnxt_dl_params_register(bp);
787         if (rc)
788                 goto err_dl_port_unreg;
789
790         return 0;
791
792 err_dl_port_unreg:
793         devlink_port_unregister(&bp->dl_port);
794 err_dl_unreg:
795         devlink_unregister(dl);
796 err_dl_free:
797         bnxt_link_bp_to_dl(bp, NULL);
798         devlink_free(dl);
799         return rc;
800 }
801
802 void bnxt_dl_unregister(struct bnxt *bp)
803 {
804         struct devlink *dl = bp->dl;
805
806         if (!dl)
807                 return;
808
809         if (BNXT_PF(bp)) {
810                 bnxt_dl_params_unregister(bp);
811                 devlink_port_unregister(&bp->dl_port);
812         }
813         devlink_unregister(dl);
814         devlink_free(dl);
815 }