diff options
author | Yuval Mintz <Yuval.Mintz@qlogic.com> | 2014-03-23 12:12:23 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-03-25 21:07:03 -0400 |
commit | 42f8277f56cf4a9570b1f0fe10a4fec3f48c832a (patch) | |
tree | b67d08a313491f4da5bf72e61fbe3c47dc063ec2 | |
parent | 869f273911dd37ed9086d6ab25ef832d10813ccd (diff) |
bnx2x: Support mng. request for driver version
This adds support in a new management feature which needs the driver versions
(bnx2x, bnx2fc and bnx2i) loaded for each interface.
Signed-off-by: Yuval Mintz <Yuval.Mintz@qlogic.com>
Signed-off-by: Ariel Elior <Ariel.Elior@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 7 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 7 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h | 29 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 121 |
4 files changed, 163 insertions, 1 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 722160940ab9..f33fab6abb95 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | |||
@@ -1413,6 +1413,7 @@ enum sp_rtnl_flag { | |||
1413 | BNX2X_SP_RTNL_RX_MODE, | 1413 | BNX2X_SP_RTNL_RX_MODE, |
1414 | BNX2X_SP_RTNL_HYPERVISOR_VLAN, | 1414 | BNX2X_SP_RTNL_HYPERVISOR_VLAN, |
1415 | BNX2X_SP_RTNL_TX_STOP, | 1415 | BNX2X_SP_RTNL_TX_STOP, |
1416 | BNX2X_SP_RTNL_GET_DRV_VERSION, | ||
1416 | }; | 1417 | }; |
1417 | 1418 | ||
1418 | struct bnx2x_prev_path_list { | 1419 | struct bnx2x_prev_path_list { |
@@ -1703,6 +1704,10 @@ struct bnx2x { | |||
1703 | struct bnx2x_slowpath *slowpath; | 1704 | struct bnx2x_slowpath *slowpath; |
1704 | dma_addr_t slowpath_mapping; | 1705 | dma_addr_t slowpath_mapping; |
1705 | 1706 | ||
1707 | /* Mechanism protecting the drv_info_to_mcp */ | ||
1708 | struct mutex drv_info_mutex; | ||
1709 | bool drv_info_mng_owner; | ||
1710 | |||
1706 | /* Total number of FW statistics requests */ | 1711 | /* Total number of FW statistics requests */ |
1707 | u8 fw_stats_num; | 1712 | u8 fw_stats_num; |
1708 | 1713 | ||
@@ -2535,6 +2540,8 @@ enum { | |||
2535 | 2540 | ||
2536 | void bnx2x_set_local_cmng(struct bnx2x *bp); | 2541 | void bnx2x_set_local_cmng(struct bnx2x *bp); |
2537 | 2542 | ||
2543 | void bnx2x_update_mng_version(struct bnx2x *bp); | ||
2544 | |||
2538 | #define MCPR_SCRATCH_BASE(bp) \ | 2545 | #define MCPR_SCRATCH_BASE(bp) \ |
2539 | (CHIP_IS_E1x(bp) ? MCP_REG_MCPR_SCRATCH : MCP_A_REG_MCPR_SCRATCH) | 2546 | (CHIP_IS_E1x(bp) ? MCP_REG_MCPR_SCRATCH : MCP_A_REG_MCPR_SCRATCH) |
2540 | 2547 | ||
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index acd494647f25..9261d5313b5b 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | |||
@@ -2804,6 +2804,9 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) | |||
2804 | if (CNIC_ENABLED(bp)) | 2804 | if (CNIC_ENABLED(bp)) |
2805 | bnx2x_load_cnic(bp); | 2805 | bnx2x_load_cnic(bp); |
2806 | 2806 | ||
2807 | if (IS_PF(bp)) | ||
2808 | bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_GET_DRV_VERSION, 0); | ||
2809 | |||
2807 | if (IS_PF(bp) && SHMEM2_HAS(bp, drv_capabilities_flag)) { | 2810 | if (IS_PF(bp) && SHMEM2_HAS(bp, drv_capabilities_flag)) { |
2808 | /* mark driver is loaded in shmem2 */ | 2811 | /* mark driver is loaded in shmem2 */ |
2809 | u32 val; | 2812 | u32 val; |
@@ -3030,6 +3033,10 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link) | |||
3030 | bp->state = BNX2X_STATE_CLOSED; | 3033 | bp->state = BNX2X_STATE_CLOSED; |
3031 | bp->cnic_loaded = false; | 3034 | bp->cnic_loaded = false; |
3032 | 3035 | ||
3036 | /* Clear driver version indication in shmem */ | ||
3037 | if (IS_PF(bp)) | ||
3038 | bnx2x_update_mng_version(bp); | ||
3039 | |||
3033 | /* Check if there are pending parity attentions. If there are - set | 3040 | /* Check if there are pending parity attentions. If there are - set |
3034 | * RECOVERY_IN_PROGRESS. | 3041 | * RECOVERY_IN_PROGRESS. |
3035 | */ | 3042 | */ |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h index 46e2f18df2cb..5ba8af50c84f 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h | |||
@@ -2003,6 +2003,23 @@ struct shmem_lfa { | |||
2003 | #define SHMEM_LFA_DONT_CLEAR_STAT (1<<24) | 2003 | #define SHMEM_LFA_DONT_CLEAR_STAT (1<<24) |
2004 | }; | 2004 | }; |
2005 | 2005 | ||
2006 | /* Used to support NSCI get OS driver version | ||
2007 | * on driver load the version value will be set | ||
2008 | * on driver unload driver value of 0x0 will be set. | ||
2009 | */ | ||
2010 | struct os_drv_ver { | ||
2011 | #define DRV_VER_NOT_LOADED 0 | ||
2012 | |||
2013 | /* personalties order is important */ | ||
2014 | #define DRV_PERS_ETHERNET 0 | ||
2015 | #define DRV_PERS_ISCSI 1 | ||
2016 | #define DRV_PERS_FCOE 2 | ||
2017 | |||
2018 | /* shmem2 struct is constant can't add more personalties here */ | ||
2019 | #define MAX_DRV_PERS 3 | ||
2020 | u32 versions[MAX_DRV_PERS]; | ||
2021 | }; | ||
2022 | |||
2006 | struct ncsi_oem_fcoe_features { | 2023 | struct ncsi_oem_fcoe_features { |
2007 | u32 fcoe_features1; | 2024 | u32 fcoe_features1; |
2008 | #define FCOE_FEATURES1_IOS_PER_CONNECTION_MASK 0x0000FFFF | 2025 | #define FCOE_FEATURES1_IOS_PER_CONNECTION_MASK 0x0000FFFF |
@@ -2217,6 +2234,18 @@ struct shmem2_region { | |||
2217 | u32 reserved4; /* Offset 0x150 */ | 2234 | u32 reserved4; /* Offset 0x150 */ |
2218 | u32 link_attr_sync[PORT_MAX]; /* Offset 0x154 */ | 2235 | u32 link_attr_sync[PORT_MAX]; /* Offset 0x154 */ |
2219 | #define LINK_ATTR_SYNC_KR2_ENABLE (1<<0) | 2236 | #define LINK_ATTR_SYNC_KR2_ENABLE (1<<0) |
2237 | |||
2238 | u32 reserved5[2]; | ||
2239 | u32 reserved6[PORT_MAX]; | ||
2240 | |||
2241 | /* driver version for each personality */ | ||
2242 | struct os_drv_ver func_os_drv_ver[E2_FUNC_MAX]; /* Offset 0x16c */ | ||
2243 | |||
2244 | /* Flag to the driver that PF's drv_info_host_addr buffer was read */ | ||
2245 | u32 mfw_drv_indication; | ||
2246 | |||
2247 | /* We use indication for each PF (0..3) */ | ||
2248 | #define MFW_DRV_IND_READ_DONE_OFFSET(_pf_) (1 << (_pf_)) | ||
2220 | }; | 2249 | }; |
2221 | 2250 | ||
2222 | 2251 | ||
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 5e74599b05c7..faef7b19a529 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | |||
@@ -3482,10 +3482,15 @@ static void bnx2x_handle_eee_event(struct bnx2x *bp) | |||
3482 | bnx2x_fw_command(bp, DRV_MSG_CODE_EEE_RESULTS_ACK, 0); | 3482 | bnx2x_fw_command(bp, DRV_MSG_CODE_EEE_RESULTS_ACK, 0); |
3483 | } | 3483 | } |
3484 | 3484 | ||
3485 | #define BNX2X_UPDATE_DRV_INFO_IND_LENGTH (20) | ||
3486 | #define BNX2X_UPDATE_DRV_INFO_IND_COUNT (25) | ||
3487 | |||
3485 | static void bnx2x_handle_drv_info_req(struct bnx2x *bp) | 3488 | static void bnx2x_handle_drv_info_req(struct bnx2x *bp) |
3486 | { | 3489 | { |
3487 | enum drv_info_opcode op_code; | 3490 | enum drv_info_opcode op_code; |
3488 | u32 drv_info_ctl = SHMEM2_RD(bp, drv_info_control); | 3491 | u32 drv_info_ctl = SHMEM2_RD(bp, drv_info_control); |
3492 | bool release = false; | ||
3493 | int wait; | ||
3489 | 3494 | ||
3490 | /* if drv_info version supported by MFW doesn't match - send NACK */ | 3495 | /* if drv_info version supported by MFW doesn't match - send NACK */ |
3491 | if ((drv_info_ctl & DRV_INFO_CONTROL_VER_MASK) != DRV_INFO_CUR_VER) { | 3496 | if ((drv_info_ctl & DRV_INFO_CONTROL_VER_MASK) != DRV_INFO_CUR_VER) { |
@@ -3496,6 +3501,9 @@ static void bnx2x_handle_drv_info_req(struct bnx2x *bp) | |||
3496 | op_code = (drv_info_ctl & DRV_INFO_CONTROL_OP_CODE_MASK) >> | 3501 | op_code = (drv_info_ctl & DRV_INFO_CONTROL_OP_CODE_MASK) >> |
3497 | DRV_INFO_CONTROL_OP_CODE_SHIFT; | 3502 | DRV_INFO_CONTROL_OP_CODE_SHIFT; |
3498 | 3503 | ||
3504 | /* Must prevent other flows from accessing drv_info_to_mcp */ | ||
3505 | mutex_lock(&bp->drv_info_mutex); | ||
3506 | |||
3499 | memset(&bp->slowpath->drv_info_to_mcp, 0, | 3507 | memset(&bp->slowpath->drv_info_to_mcp, 0, |
3500 | sizeof(union drv_info_to_mcp)); | 3508 | sizeof(union drv_info_to_mcp)); |
3501 | 3509 | ||
@@ -3512,7 +3520,7 @@ static void bnx2x_handle_drv_info_req(struct bnx2x *bp) | |||
3512 | default: | 3520 | default: |
3513 | /* if op code isn't supported - send NACK */ | 3521 | /* if op code isn't supported - send NACK */ |
3514 | bnx2x_fw_command(bp, DRV_MSG_CODE_DRV_INFO_NACK, 0); | 3522 | bnx2x_fw_command(bp, DRV_MSG_CODE_DRV_INFO_NACK, 0); |
3515 | return; | 3523 | goto out; |
3516 | } | 3524 | } |
3517 | 3525 | ||
3518 | /* if we got drv_info attn from MFW then these fields are defined in | 3526 | /* if we got drv_info attn from MFW then these fields are defined in |
@@ -3524,6 +3532,106 @@ static void bnx2x_handle_drv_info_req(struct bnx2x *bp) | |||
3524 | U64_HI(bnx2x_sp_mapping(bp, drv_info_to_mcp))); | 3532 | U64_HI(bnx2x_sp_mapping(bp, drv_info_to_mcp))); |
3525 | 3533 | ||
3526 | bnx2x_fw_command(bp, DRV_MSG_CODE_DRV_INFO_ACK, 0); | 3534 | bnx2x_fw_command(bp, DRV_MSG_CODE_DRV_INFO_ACK, 0); |
3535 | |||
3536 | /* Since possible management wants both this and get_driver_version | ||
3537 | * need to wait until management notifies us it finished utilizing | ||
3538 | * the buffer. | ||
3539 | */ | ||
3540 | if (!SHMEM2_HAS(bp, mfw_drv_indication)) { | ||
3541 | DP(BNX2X_MSG_MCP, "Management does not support indication\n"); | ||
3542 | } else if (!bp->drv_info_mng_owner) { | ||
3543 | u32 bit = MFW_DRV_IND_READ_DONE_OFFSET((BP_ABS_FUNC(bp) >> 1)); | ||
3544 | |||
3545 | for (wait = 0; wait < BNX2X_UPDATE_DRV_INFO_IND_COUNT; wait++) { | ||
3546 | u32 indication = SHMEM2_RD(bp, mfw_drv_indication); | ||
3547 | |||
3548 | /* Management is done; need to clear indication */ | ||
3549 | if (indication & bit) { | ||
3550 | SHMEM2_WR(bp, mfw_drv_indication, | ||
3551 | indication & ~bit); | ||
3552 | release = true; | ||
3553 | break; | ||
3554 | } | ||
3555 | |||
3556 | msleep(BNX2X_UPDATE_DRV_INFO_IND_LENGTH); | ||
3557 | } | ||
3558 | } | ||
3559 | if (!release) { | ||
3560 | DP(BNX2X_MSG_MCP, "Management did not release indication\n"); | ||
3561 | bp->drv_info_mng_owner = true; | ||
3562 | } | ||
3563 | |||
3564 | out: | ||
3565 | mutex_unlock(&bp->drv_info_mutex); | ||
3566 | } | ||
3567 | |||
3568 | static u32 bnx2x_update_mng_version_utility(u8 *version, bool bnx2x_format) | ||
3569 | { | ||
3570 | u8 vals[4]; | ||
3571 | int i = 0; | ||
3572 | |||
3573 | if (bnx2x_format) { | ||
3574 | i = sscanf(version, "1.%c%hhd.%hhd.%hhd", | ||
3575 | &vals[0], &vals[1], &vals[2], &vals[3]); | ||
3576 | if (i > 0) | ||
3577 | vals[0] -= '0'; | ||
3578 | } else { | ||
3579 | i = sscanf(version, "%hhd.%hhd.%hhd.%hhd", | ||
3580 | &vals[0], &vals[1], &vals[2], &vals[3]); | ||
3581 | } | ||
3582 | |||
3583 | while (i < 4) | ||
3584 | vals[i++] = 0; | ||
3585 | |||
3586 | return (vals[0] << 24) | (vals[1] << 16) | (vals[2] << 8) | vals[3]; | ||
3587 | } | ||
3588 | |||
3589 | void bnx2x_update_mng_version(struct bnx2x *bp) | ||
3590 | { | ||
3591 | u32 iscsiver = DRV_VER_NOT_LOADED; | ||
3592 | u32 fcoever = DRV_VER_NOT_LOADED; | ||
3593 | u32 ethver = DRV_VER_NOT_LOADED; | ||
3594 | int idx = BP_FW_MB_IDX(bp); | ||
3595 | u8 *version; | ||
3596 | |||
3597 | if (!SHMEM2_HAS(bp, func_os_drv_ver)) | ||
3598 | return; | ||
3599 | |||
3600 | mutex_lock(&bp->drv_info_mutex); | ||
3601 | /* Must not proceed when `bnx2x_handle_drv_info_req' is feasible */ | ||
3602 | if (bp->drv_info_mng_owner) | ||
3603 | goto out; | ||
3604 | |||
3605 | if (bp->state != BNX2X_STATE_OPEN) | ||
3606 | goto out; | ||
3607 | |||
3608 | /* Parse ethernet driver version */ | ||
3609 | ethver = bnx2x_update_mng_version_utility(DRV_MODULE_VERSION, true); | ||
3610 | if (!CNIC_LOADED(bp)) | ||
3611 | goto out; | ||
3612 | |||
3613 | /* Try getting storage driver version via cnic */ | ||
3614 | memset(&bp->slowpath->drv_info_to_mcp, 0, | ||
3615 | sizeof(union drv_info_to_mcp)); | ||
3616 | bnx2x_drv_info_iscsi_stat(bp); | ||
3617 | version = bp->slowpath->drv_info_to_mcp.iscsi_stat.version; | ||
3618 | iscsiver = bnx2x_update_mng_version_utility(version, false); | ||
3619 | |||
3620 | memset(&bp->slowpath->drv_info_to_mcp, 0, | ||
3621 | sizeof(union drv_info_to_mcp)); | ||
3622 | bnx2x_drv_info_fcoe_stat(bp); | ||
3623 | version = bp->slowpath->drv_info_to_mcp.fcoe_stat.version; | ||
3624 | fcoever = bnx2x_update_mng_version_utility(version, false); | ||
3625 | |||
3626 | out: | ||
3627 | SHMEM2_WR(bp, func_os_drv_ver[idx].versions[DRV_PERS_ETHERNET], ethver); | ||
3628 | SHMEM2_WR(bp, func_os_drv_ver[idx].versions[DRV_PERS_ISCSI], iscsiver); | ||
3629 | SHMEM2_WR(bp, func_os_drv_ver[idx].versions[DRV_PERS_FCOE], fcoever); | ||
3630 | |||
3631 | mutex_unlock(&bp->drv_info_mutex); | ||
3632 | |||
3633 | DP(BNX2X_MSG_MCP, "Setting driver version: ETH [%08x] iSCSI [%08x] FCoE [%08x]\n", | ||
3634 | ethver, iscsiver, fcoever); | ||
3527 | } | 3635 | } |
3528 | 3636 | ||
3529 | static void bnx2x_dcc_event(struct bnx2x *bp, u32 dcc_event) | 3637 | static void bnx2x_dcc_event(struct bnx2x *bp, u32 dcc_event) |
@@ -9807,6 +9915,10 @@ sp_rtnl_not_reset: | |||
9807 | bnx2x_dcbx_resume_hw_tx(bp); | 9915 | bnx2x_dcbx_resume_hw_tx(bp); |
9808 | } | 9916 | } |
9809 | 9917 | ||
9918 | if (test_and_clear_bit(BNX2X_SP_RTNL_GET_DRV_VERSION, | ||
9919 | &bp->sp_rtnl_state)) | ||
9920 | bnx2x_update_mng_version(bp); | ||
9921 | |||
9810 | /* work which needs rtnl lock not-taken (as it takes the lock itself and | 9922 | /* work which needs rtnl lock not-taken (as it takes the lock itself and |
9811 | * can be called from other contexts as well) | 9923 | * can be called from other contexts as well) |
9812 | */ | 9924 | */ |
@@ -11757,6 +11869,8 @@ static int bnx2x_init_bp(struct bnx2x *bp) | |||
11757 | 11869 | ||
11758 | mutex_init(&bp->port.phy_mutex); | 11870 | mutex_init(&bp->port.phy_mutex); |
11759 | mutex_init(&bp->fw_mb_mutex); | 11871 | mutex_init(&bp->fw_mb_mutex); |
11872 | mutex_init(&bp->drv_info_mutex); | ||
11873 | bp->drv_info_mng_owner = false; | ||
11760 | spin_lock_init(&bp->stats_lock); | 11874 | spin_lock_init(&bp->stats_lock); |
11761 | sema_init(&bp->stats_sema, 1); | 11875 | sema_init(&bp->stats_sema, 1); |
11762 | 11876 | ||
@@ -13794,6 +13908,7 @@ static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl) | |||
13794 | REG_WR(bp, scratch_offset + i, | 13908 | REG_WR(bp, scratch_offset + i, |
13795 | *(host_addr + i/4)); | 13909 | *(host_addr + i/4)); |
13796 | } | 13910 | } |
13911 | bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_GET_DRV_VERSION, 0); | ||
13797 | break; | 13912 | break; |
13798 | } | 13913 | } |
13799 | 13914 | ||
@@ -13811,6 +13926,7 @@ static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl) | |||
13811 | cap &= ~DRV_FLAGS_CAPABILITIES_LOADED_FCOE; | 13926 | cap &= ~DRV_FLAGS_CAPABILITIES_LOADED_FCOE; |
13812 | SHMEM2_WR(bp, drv_capabilities_flag[idx], cap); | 13927 | SHMEM2_WR(bp, drv_capabilities_flag[idx], cap); |
13813 | } | 13928 | } |
13929 | bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_GET_DRV_VERSION, 0); | ||
13814 | break; | 13930 | break; |
13815 | } | 13931 | } |
13816 | 13932 | ||
@@ -13916,6 +14032,9 @@ static int bnx2x_register_cnic(struct net_device *dev, struct cnic_ops *ops, | |||
13916 | 14032 | ||
13917 | rcu_assign_pointer(bp->cnic_ops, ops); | 14033 | rcu_assign_pointer(bp->cnic_ops, ops); |
13918 | 14034 | ||
14035 | /* Schedule driver to read CNIC driver versions */ | ||
14036 | bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_GET_DRV_VERSION, 0); | ||
14037 | |||
13919 | return 0; | 14038 | return 0; |
13920 | } | 14039 | } |
13921 | 14040 | ||