diff options
author | Ariel Elior <ariele@broadcom.com> | 2012-01-26 01:01:50 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-01-26 13:39:52 -0500 |
commit | f16da43b5df947cef427f19b8f5c4b2f5d566231 (patch) | |
tree | a9076701c918b56a4daedc4e7bd6336101f4cdf8 /drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | |
parent | d1e2d9660e6bca2f06606b4bc65ea669bf669b0a (diff) |
bnx2x: Lock PF-common resources
Use hardware locks to protect resources common to several Physical Functions. In
a virtualized environment the RTNL lock only protects a PF's driver against
the PFs sharing it's VMs with regard to device resources. Other PFs may reside
in other VMs under other OSs, and are not subject to the lock. Such resources
which were previously protected implicitly by the RTNL lock must now be
protected explicitly with dedicated HW locks.
Signed-off-by: Ariel Elior <ariele@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c')
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 73 |
1 files changed, 41 insertions, 32 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 9a1c4501f0ec..4824b0f8bd23 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | |||
@@ -3724,11 +3724,11 @@ static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn) | |||
3724 | */ | 3724 | */ |
3725 | void bnx2x_set_reset_global(struct bnx2x *bp) | 3725 | void bnx2x_set_reset_global(struct bnx2x *bp) |
3726 | { | 3726 | { |
3727 | u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); | 3727 | u32 val; |
3728 | 3728 | bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); | |
3729 | val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); | ||
3729 | REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val | BNX2X_GLOBAL_RESET_BIT); | 3730 | REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val | BNX2X_GLOBAL_RESET_BIT); |
3730 | barrier(); | 3731 | bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); |
3731 | mmiowb(); | ||
3732 | } | 3732 | } |
3733 | 3733 | ||
3734 | /* | 3734 | /* |
@@ -3738,11 +3738,11 @@ void bnx2x_set_reset_global(struct bnx2x *bp) | |||
3738 | */ | 3738 | */ |
3739 | static inline void bnx2x_clear_reset_global(struct bnx2x *bp) | 3739 | static inline void bnx2x_clear_reset_global(struct bnx2x *bp) |
3740 | { | 3740 | { |
3741 | u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); | 3741 | u32 val; |
3742 | 3742 | bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); | |
3743 | val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); | ||
3743 | REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val & (~BNX2X_GLOBAL_RESET_BIT)); | 3744 | REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val & (~BNX2X_GLOBAL_RESET_BIT)); |
3744 | barrier(); | 3745 | bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); |
3745 | mmiowb(); | ||
3746 | } | 3746 | } |
3747 | 3747 | ||
3748 | /* | 3748 | /* |
@@ -3765,15 +3765,17 @@ static inline bool bnx2x_reset_is_global(struct bnx2x *bp) | |||
3765 | */ | 3765 | */ |
3766 | static inline void bnx2x_set_reset_done(struct bnx2x *bp) | 3766 | static inline void bnx2x_set_reset_done(struct bnx2x *bp) |
3767 | { | 3767 | { |
3768 | u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); | 3768 | u32 val; |
3769 | u32 bit = BP_PATH(bp) ? | 3769 | u32 bit = BP_PATH(bp) ? |
3770 | BNX2X_PATH1_RST_IN_PROG_BIT : BNX2X_PATH0_RST_IN_PROG_BIT; | 3770 | BNX2X_PATH1_RST_IN_PROG_BIT : BNX2X_PATH0_RST_IN_PROG_BIT; |
3771 | bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); | ||
3772 | val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); | ||
3771 | 3773 | ||
3772 | /* Clear the bit */ | 3774 | /* Clear the bit */ |
3773 | val &= ~bit; | 3775 | val &= ~bit; |
3774 | REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val); | 3776 | REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val); |
3775 | barrier(); | 3777 | |
3776 | mmiowb(); | 3778 | bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); |
3777 | } | 3779 | } |
3778 | 3780 | ||
3779 | /* | 3781 | /* |
@@ -3783,15 +3785,16 @@ static inline void bnx2x_set_reset_done(struct bnx2x *bp) | |||
3783 | */ | 3785 | */ |
3784 | void bnx2x_set_reset_in_progress(struct bnx2x *bp) | 3786 | void bnx2x_set_reset_in_progress(struct bnx2x *bp) |
3785 | { | 3787 | { |
3786 | u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); | 3788 | u32 val; |
3787 | u32 bit = BP_PATH(bp) ? | 3789 | u32 bit = BP_PATH(bp) ? |
3788 | BNX2X_PATH1_RST_IN_PROG_BIT : BNX2X_PATH0_RST_IN_PROG_BIT; | 3790 | BNX2X_PATH1_RST_IN_PROG_BIT : BNX2X_PATH0_RST_IN_PROG_BIT; |
3791 | bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); | ||
3792 | val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); | ||
3789 | 3793 | ||
3790 | /* Set the bit */ | 3794 | /* Set the bit */ |
3791 | val |= bit; | 3795 | val |= bit; |
3792 | REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val); | 3796 | REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val); |
3793 | barrier(); | 3797 | bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); |
3794 | mmiowb(); | ||
3795 | } | 3798 | } |
3796 | 3799 | ||
3797 | /* | 3800 | /* |
@@ -3815,12 +3818,15 @@ bool bnx2x_reset_is_done(struct bnx2x *bp, int engine) | |||
3815 | */ | 3818 | */ |
3816 | void bnx2x_inc_load_cnt(struct bnx2x *bp) | 3819 | void bnx2x_inc_load_cnt(struct bnx2x *bp) |
3817 | { | 3820 | { |
3818 | u32 val1, val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); | 3821 | u32 val1, val; |
3819 | u32 mask = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK : | 3822 | u32 mask = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK : |
3820 | BNX2X_PATH0_LOAD_CNT_MASK; | 3823 | BNX2X_PATH0_LOAD_CNT_MASK; |
3821 | u32 shift = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_SHIFT : | 3824 | u32 shift = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_SHIFT : |
3822 | BNX2X_PATH0_LOAD_CNT_SHIFT; | 3825 | BNX2X_PATH0_LOAD_CNT_SHIFT; |
3823 | 3826 | ||
3827 | bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); | ||
3828 | val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); | ||
3829 | |||
3824 | DP(NETIF_MSG_HW, "Old GEN_REG_VAL=0x%08x\n", val); | 3830 | DP(NETIF_MSG_HW, "Old GEN_REG_VAL=0x%08x\n", val); |
3825 | 3831 | ||
3826 | /* get the current counter value */ | 3832 | /* get the current counter value */ |
@@ -3836,8 +3842,7 @@ void bnx2x_inc_load_cnt(struct bnx2x *bp) | |||
3836 | val |= ((val1 << shift) & mask); | 3842 | val |= ((val1 << shift) & mask); |
3837 | 3843 | ||
3838 | REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val); | 3844 | REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val); |
3839 | barrier(); | 3845 | bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); |
3840 | mmiowb(); | ||
3841 | } | 3846 | } |
3842 | 3847 | ||
3843 | /** | 3848 | /** |
@@ -3851,12 +3856,14 @@ void bnx2x_inc_load_cnt(struct bnx2x *bp) | |||
3851 | */ | 3856 | */ |
3852 | u32 bnx2x_dec_load_cnt(struct bnx2x *bp) | 3857 | u32 bnx2x_dec_load_cnt(struct bnx2x *bp) |
3853 | { | 3858 | { |
3854 | u32 val1, val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); | 3859 | u32 val1, val; |
3855 | u32 mask = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK : | 3860 | u32 mask = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK : |
3856 | BNX2X_PATH0_LOAD_CNT_MASK; | 3861 | BNX2X_PATH0_LOAD_CNT_MASK; |
3857 | u32 shift = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_SHIFT : | 3862 | u32 shift = BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_SHIFT : |
3858 | BNX2X_PATH0_LOAD_CNT_SHIFT; | 3863 | BNX2X_PATH0_LOAD_CNT_SHIFT; |
3859 | 3864 | ||
3865 | bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); | ||
3866 | val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); | ||
3860 | DP(NETIF_MSG_HW, "Old GEN_REG_VAL=0x%08x\n", val); | 3867 | DP(NETIF_MSG_HW, "Old GEN_REG_VAL=0x%08x\n", val); |
3861 | 3868 | ||
3862 | /* get the current counter value */ | 3869 | /* get the current counter value */ |
@@ -3872,10 +3879,8 @@ u32 bnx2x_dec_load_cnt(struct bnx2x *bp) | |||
3872 | val |= ((val1 << shift) & mask); | 3879 | val |= ((val1 << shift) & mask); |
3873 | 3880 | ||
3874 | REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val); | 3881 | REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val); |
3875 | barrier(); | 3882 | bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); |
3876 | mmiowb(); | 3883 | return val1 != 0; |
3877 | |||
3878 | return val1; | ||
3879 | } | 3884 | } |
3880 | 3885 | ||
3881 | /* | 3886 | /* |
@@ -3907,11 +3912,13 @@ static inline u32 bnx2x_get_load_cnt(struct bnx2x *bp, int engine) | |||
3907 | */ | 3912 | */ |
3908 | static inline void bnx2x_clear_load_cnt(struct bnx2x *bp) | 3913 | static inline void bnx2x_clear_load_cnt(struct bnx2x *bp) |
3909 | { | 3914 | { |
3910 | u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); | 3915 | u32 val; |
3911 | u32 mask = (BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK : | 3916 | u32 mask = (BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK : |
3912 | BNX2X_PATH0_LOAD_CNT_MASK); | 3917 | BNX2X_PATH0_LOAD_CNT_MASK); |
3913 | 3918 | bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); | |
3919 | val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); | ||
3914 | REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val & (~mask)); | 3920 | REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val & (~mask)); |
3921 | bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); | ||
3915 | } | 3922 | } |
3916 | 3923 | ||
3917 | static inline void _print_next_block(int idx, const char *blk) | 3924 | static inline void _print_next_block(int idx, const char *blk) |
@@ -8809,11 +8816,13 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp) | |||
8809 | { | 8816 | { |
8810 | u32 val; | 8817 | u32 val; |
8811 | 8818 | ||
8812 | /* Check if there is any driver already loaded */ | 8819 | /* possibly another driver is trying to reset the chip */ |
8813 | val = REG_RD(bp, MISC_REG_UNPREPARED); | 8820 | bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RESET); |
8814 | if (val == 0x1) { | 8821 | |
8822 | /* check if doorbell queue is reset */ | ||
8823 | if (REG_RD(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET) | ||
8824 | & MISC_REGISTERS_RESET_REG_1_RST_DORQ) { | ||
8815 | 8825 | ||
8816 | bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RESET); | ||
8817 | /* | 8826 | /* |
8818 | * Check if it is the UNDI driver | 8827 | * Check if it is the UNDI driver |
8819 | * UNDI driver initializes CID offset for normal bell to 0x7 | 8828 | * UNDI driver initializes CID offset for normal bell to 0x7 |
@@ -8905,10 +8914,10 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp) | |||
8905 | (SHMEM_RD(bp, func_mb[bp->pf_num].drv_mb_header) & | 8914 | (SHMEM_RD(bp, func_mb[bp->pf_num].drv_mb_header) & |
8906 | DRV_MSG_SEQ_NUMBER_MASK); | 8915 | DRV_MSG_SEQ_NUMBER_MASK); |
8907 | } | 8916 | } |
8908 | |||
8909 | /* now it's safe to release the lock */ | ||
8910 | bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RESET); | ||
8911 | } | 8917 | } |
8918 | |||
8919 | /* now it's safe to release the lock */ | ||
8920 | bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RESET); | ||
8912 | } | 8921 | } |
8913 | 8922 | ||
8914 | static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp) | 8923 | static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp) |