aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYuval Mintz <Yuval.Mintz@qlogic.com>2014-03-23 12:12:23 -0400
committerDavid S. Miller <davem@davemloft.net>2014-03-25 21:07:03 -0400
commit42f8277f56cf4a9570b1f0fe10a4fec3f48c832a (patch)
treeb67d08a313491f4da5bf72e61fbe3c47dc063ec2
parent869f273911dd37ed9086d6ab25ef832d10813ccd (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.h7
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c7
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h29
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c121
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
1418struct bnx2x_prev_path_list { 1419struct 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
2536void bnx2x_set_local_cmng(struct bnx2x *bp); 2541void bnx2x_set_local_cmng(struct bnx2x *bp);
2537 2542
2543void 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 */
2010struct 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
2006struct ncsi_oem_fcoe_features { 2023struct 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
3485static void bnx2x_handle_drv_info_req(struct bnx2x *bp) 3488static 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
3564out:
3565 mutex_unlock(&bp->drv_info_mutex);
3566}
3567
3568static 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
3589void 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
3626out:
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
3529static void bnx2x_dcc_event(struct bnx2x *bp, u32 dcc_event) 3637static 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