bnxt_devlink.c 35 KB

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