@@ -326,6 +326,111 @@ void bnxt_dl_health_fw_recovery_done(struct bnxt *bp)
326
326
static int bnxt_dl_info_get (struct devlink * dl , struct devlink_info_req * req ,
327
327
struct netlink_ext_ack * extack );
328
328
329
+ static void
330
+ bnxt_dl_livepatch_report_err (struct bnxt * bp , struct netlink_ext_ack * extack ,
331
+ struct hwrm_fw_livepatch_output * resp )
332
+ {
333
+ int err = ((struct hwrm_err_output * )resp )-> cmd_err ;
334
+
335
+ switch (err ) {
336
+ case FW_LIVEPATCH_CMD_ERR_CODE_INVALID_OPCODE :
337
+ netdev_err (bp -> dev , "Illegal live patch opcode" );
338
+ NL_SET_ERR_MSG_MOD (extack , "Invalid opcode" );
339
+ break ;
340
+ case FW_LIVEPATCH_CMD_ERR_CODE_NOT_SUPPORTED :
341
+ NL_SET_ERR_MSG_MOD (extack , "Live patch operation not supported" );
342
+ break ;
343
+ case FW_LIVEPATCH_CMD_ERR_CODE_NOT_INSTALLED :
344
+ NL_SET_ERR_MSG_MOD (extack , "Live patch not found" );
345
+ break ;
346
+ case FW_LIVEPATCH_CMD_ERR_CODE_NOT_PATCHED :
347
+ NL_SET_ERR_MSG_MOD (extack ,
348
+ "Live patch deactivation failed. Firmware not patched." );
349
+ break ;
350
+ case FW_LIVEPATCH_CMD_ERR_CODE_AUTH_FAIL :
351
+ NL_SET_ERR_MSG_MOD (extack , "Live patch not authenticated" );
352
+ break ;
353
+ case FW_LIVEPATCH_CMD_ERR_CODE_INVALID_HEADER :
354
+ NL_SET_ERR_MSG_MOD (extack , "Incompatible live patch" );
355
+ break ;
356
+ case FW_LIVEPATCH_CMD_ERR_CODE_INVALID_SIZE :
357
+ NL_SET_ERR_MSG_MOD (extack , "Live patch has invalid size" );
358
+ break ;
359
+ case FW_LIVEPATCH_CMD_ERR_CODE_ALREADY_PATCHED :
360
+ NL_SET_ERR_MSG_MOD (extack , "Live patch already applied" );
361
+ break ;
362
+ default :
363
+ netdev_err (bp -> dev , "Unexpected live patch error: %hhd\n" , err );
364
+ NL_SET_ERR_MSG_MOD (extack , "Failed to activate live patch" );
365
+ break ;
366
+ }
367
+ }
368
+
369
+ static int
370
+ bnxt_dl_livepatch_activate (struct bnxt * bp , struct netlink_ext_ack * extack )
371
+ {
372
+ struct hwrm_fw_livepatch_query_output * query_resp ;
373
+ struct hwrm_fw_livepatch_query_input * query_req ;
374
+ struct hwrm_fw_livepatch_output * patch_resp ;
375
+ struct hwrm_fw_livepatch_input * patch_req ;
376
+ u32 installed = 0 ;
377
+ u16 flags ;
378
+ u8 target ;
379
+ int rc ;
380
+
381
+ if (~bp -> fw_cap & BNXT_FW_CAP_LIVEPATCH ) {
382
+ NL_SET_ERR_MSG_MOD (extack , "Device does not support live patch" );
383
+ return - EOPNOTSUPP ;
384
+ }
385
+
386
+ rc = hwrm_req_init (bp , query_req , HWRM_FW_LIVEPATCH_QUERY );
387
+ if (rc )
388
+ return rc ;
389
+ query_resp = hwrm_req_hold (bp , query_req );
390
+
391
+ rc = hwrm_req_init (bp , patch_req , HWRM_FW_LIVEPATCH );
392
+ if (rc ) {
393
+ hwrm_req_drop (bp , query_req );
394
+ return rc ;
395
+ }
396
+ patch_req -> opcode = FW_LIVEPATCH_REQ_OPCODE_ACTIVATE ;
397
+ patch_req -> loadtype = FW_LIVEPATCH_REQ_LOADTYPE_NVM_INSTALL ;
398
+ patch_resp = hwrm_req_hold (bp , patch_req );
399
+
400
+ for (target = 1 ; target <= FW_LIVEPATCH_REQ_FW_TARGET_LAST ; target ++ ) {
401
+ query_req -> fw_target = target ;
402
+ rc = hwrm_req_send (bp , query_req );
403
+ if (rc ) {
404
+ NL_SET_ERR_MSG_MOD (extack , "Failed to query packages" );
405
+ break ;
406
+ }
407
+
408
+ flags = le16_to_cpu (query_resp -> status_flags );
409
+ if (~flags & FW_LIVEPATCH_QUERY_RESP_STATUS_FLAGS_INSTALL )
410
+ continue ;
411
+ if ((flags & FW_LIVEPATCH_QUERY_RESP_STATUS_FLAGS_ACTIVE ) &&
412
+ !strncmp (query_resp -> active_ver , query_resp -> install_ver ,
413
+ sizeof (query_resp -> active_ver )))
414
+ continue ;
415
+
416
+ patch_req -> fw_target = target ;
417
+ rc = hwrm_req_send (bp , patch_req );
418
+ if (rc ) {
419
+ bnxt_dl_livepatch_report_err (bp , extack , patch_resp );
420
+ break ;
421
+ }
422
+ installed ++ ;
423
+ }
424
+
425
+ if (!rc && !installed ) {
426
+ NL_SET_ERR_MSG_MOD (extack , "No live patches found" );
427
+ rc = - ENOENT ;
428
+ }
429
+ hwrm_req_drop (bp , query_req );
430
+ hwrm_req_drop (bp , patch_req );
431
+ return rc ;
432
+ }
433
+
329
434
static int bnxt_dl_reload_down (struct devlink * dl , bool netns_change ,
330
435
enum devlink_reload_action action ,
331
436
enum devlink_reload_limit limit ,
@@ -372,6 +477,8 @@ static int bnxt_dl_reload_down(struct devlink *dl, bool netns_change,
372
477
break ;
373
478
}
374
479
case DEVLINK_RELOAD_ACTION_FW_ACTIVATE : {
480
+ if (limit == DEVLINK_RELOAD_LIMIT_NO_RESET )
481
+ return bnxt_dl_livepatch_activate (bp , extack );
375
482
if (~bp -> fw_cap & BNXT_FW_CAP_HOT_RESET ) {
376
483
NL_SET_ERR_MSG_MOD (extack , "Device not capable, requires reboot" );
377
484
return - EOPNOTSUPP ;
@@ -432,6 +539,8 @@ static int bnxt_dl_reload_up(struct devlink *dl, enum devlink_reload_action acti
432
539
unsigned long start = jiffies ;
433
540
unsigned long timeout = start + BNXT_DFLT_FW_RST_MAX_DSECS * HZ / 10 ;
434
541
542
+ if (limit == DEVLINK_RELOAD_LIMIT_NO_RESET )
543
+ break ;
435
544
if (bp -> fw_cap & BNXT_FW_CAP_ERROR_RECOVERY )
436
545
timeout = start + bp -> fw_health -> normal_func_wait_dsecs * HZ / 10 ;
437
546
if (!netif_running (bp -> dev ))
@@ -485,6 +594,7 @@ static const struct devlink_ops bnxt_dl_ops = {
485
594
.flash_update = bnxt_dl_flash_update ,
486
595
.reload_actions = BIT (DEVLINK_RELOAD_ACTION_DRIVER_REINIT ) |
487
596
BIT (DEVLINK_RELOAD_ACTION_FW_ACTIVATE ),
597
+ .reload_limits = BIT (DEVLINK_RELOAD_LIMIT_NO_RESET ),
488
598
.reload_down = bnxt_dl_reload_down ,
489
599
.reload_up = bnxt_dl_reload_up ,
490
600
};
@@ -630,6 +740,57 @@ static int bnxt_dl_info_put(struct bnxt *bp, struct devlink_info_req *req,
630
740
return 0 ;
631
741
}
632
742
743
+ #define BNXT_FW_SRT_PATCH "fw.srt.patch"
744
+ #define BNXT_FW_CRT_PATCH "fw.crt.patch"
745
+
746
+ static int bnxt_dl_livepatch_info_put (struct bnxt * bp ,
747
+ struct devlink_info_req * req ,
748
+ const char * key )
749
+ {
750
+ struct hwrm_fw_livepatch_query_input * query ;
751
+ struct hwrm_fw_livepatch_query_output * resp ;
752
+ u16 flags ;
753
+ int rc ;
754
+
755
+ if (~bp -> fw_cap & BNXT_FW_CAP_LIVEPATCH )
756
+ return 0 ;
757
+
758
+ rc = hwrm_req_init (bp , query , HWRM_FW_LIVEPATCH_QUERY );
759
+ if (rc )
760
+ return rc ;
761
+
762
+ if (!strcmp (key , BNXT_FW_SRT_PATCH ))
763
+ query -> fw_target = FW_LIVEPATCH_QUERY_REQ_FW_TARGET_SECURE_FW ;
764
+ else if (!strcmp (key , BNXT_FW_CRT_PATCH ))
765
+ query -> fw_target = FW_LIVEPATCH_QUERY_REQ_FW_TARGET_COMMON_FW ;
766
+ else
767
+ goto exit ;
768
+
769
+ resp = hwrm_req_hold (bp , query );
770
+ rc = hwrm_req_send (bp , query );
771
+ if (rc )
772
+ goto exit ;
773
+
774
+ flags = le16_to_cpu (resp -> status_flags );
775
+ if (flags & FW_LIVEPATCH_QUERY_RESP_STATUS_FLAGS_ACTIVE ) {
776
+ resp -> active_ver [sizeof (resp -> active_ver ) - 1 ] = '\0' ;
777
+ rc = devlink_info_version_running_put (req , key , resp -> active_ver );
778
+ if (rc )
779
+ goto exit ;
780
+ }
781
+
782
+ if (flags & FW_LIVEPATCH_QUERY_RESP_STATUS_FLAGS_INSTALL ) {
783
+ resp -> install_ver [sizeof (resp -> install_ver ) - 1 ] = '\0' ;
784
+ rc = devlink_info_version_stored_put (req , key , resp -> install_ver );
785
+ if (rc )
786
+ goto exit ;
787
+ }
788
+
789
+ exit :
790
+ hwrm_req_drop (bp , query );
791
+ return rc ;
792
+ }
793
+
633
794
#define HWRM_FW_VER_STR_LEN 16
634
795
635
796
static int bnxt_dl_info_get (struct devlink * dl , struct devlink_info_req * req ,
@@ -783,8 +944,16 @@ static int bnxt_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
783
944
snprintf (roce_ver , FW_VER_STR_LEN , "%d.%d.%d.%d" ,
784
945
nvm_dev_info .roce_fw_major , nvm_dev_info .roce_fw_minor ,
785
946
nvm_dev_info .roce_fw_build , nvm_dev_info .roce_fw_patch );
786
- return bnxt_dl_info_put (bp , req , BNXT_VERSION_STORED ,
787
- DEVLINK_INFO_VERSION_GENERIC_FW_ROCE , roce_ver );
947
+ rc = bnxt_dl_info_put (bp , req , BNXT_VERSION_STORED ,
948
+ DEVLINK_INFO_VERSION_GENERIC_FW_ROCE , roce_ver );
949
+ if (rc )
950
+ return rc ;
951
+
952
+ rc = bnxt_dl_livepatch_info_put (bp , req , BNXT_FW_SRT_PATCH );
953
+ if (rc )
954
+ return rc ;
955
+ return bnxt_dl_livepatch_info_put (bp , req , BNXT_FW_CRT_PATCH );
956
+
788
957
}
789
958
790
959
static int bnxt_hwrm_nvm_req (struct bnxt * bp , u32 param_id , void * msg ,
0 commit comments