@@ -326,6 +326,111 @@ void bnxt_dl_health_fw_recovery_done(struct bnxt *bp)
326326static int bnxt_dl_info_get (struct devlink * dl , struct devlink_info_req * req ,
327327 struct netlink_ext_ack * extack );
328328
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+
329434static int bnxt_dl_reload_down (struct devlink * dl , bool netns_change ,
330435 enum devlink_reload_action action ,
331436 enum devlink_reload_limit limit ,
@@ -372,6 +477,8 @@ static int bnxt_dl_reload_down(struct devlink *dl, bool netns_change,
372477 break ;
373478 }
374479 case DEVLINK_RELOAD_ACTION_FW_ACTIVATE : {
480+ if (limit == DEVLINK_RELOAD_LIMIT_NO_RESET )
481+ return bnxt_dl_livepatch_activate (bp , extack );
375482 if (~bp -> fw_cap & BNXT_FW_CAP_HOT_RESET ) {
376483 NL_SET_ERR_MSG_MOD (extack , "Device not capable, requires reboot" );
377484 return - EOPNOTSUPP ;
@@ -432,6 +539,8 @@ static int bnxt_dl_reload_up(struct devlink *dl, enum devlink_reload_action acti
432539 unsigned long start = jiffies ;
433540 unsigned long timeout = start + BNXT_DFLT_FW_RST_MAX_DSECS * HZ / 10 ;
434541
542+ if (limit == DEVLINK_RELOAD_LIMIT_NO_RESET )
543+ break ;
435544 if (bp -> fw_cap & BNXT_FW_CAP_ERROR_RECOVERY )
436545 timeout = start + bp -> fw_health -> normal_func_wait_dsecs * HZ / 10 ;
437546 if (!netif_running (bp -> dev ))
@@ -485,6 +594,7 @@ static const struct devlink_ops bnxt_dl_ops = {
485594 .flash_update = bnxt_dl_flash_update ,
486595 .reload_actions = BIT (DEVLINK_RELOAD_ACTION_DRIVER_REINIT ) |
487596 BIT (DEVLINK_RELOAD_ACTION_FW_ACTIVATE ),
597+ .reload_limits = BIT (DEVLINK_RELOAD_LIMIT_NO_RESET ),
488598 .reload_down = bnxt_dl_reload_down ,
489599 .reload_up = bnxt_dl_reload_up ,
490600};
@@ -630,6 +740,57 @@ static int bnxt_dl_info_put(struct bnxt *bp, struct devlink_info_req *req,
630740 return 0 ;
631741}
632742
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+
633794#define HWRM_FW_VER_STR_LEN 16
634795
635796static 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,
783944 snprintf (roce_ver , FW_VER_STR_LEN , "%d.%d.%d.%d" ,
784945 nvm_dev_info .roce_fw_major , nvm_dev_info .roce_fw_minor ,
785946 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+
788957}
789958
790959static int bnxt_hwrm_nvm_req (struct bnxt * bp , u32 param_id , void * msg ,
0 commit comments