diff options
author | Vladislav Zolotarov <vladz@broadcom.com> | 2011-05-04 19:48:23 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-05-05 13:44:33 -0400 |
commit | 2ae17f666099c952053eea7c64cac8189dd76f72 (patch) | |
tree | 69da6881c755adccec1ef4e09ec28bc499e979e9 /drivers/net/bnx2x | |
parent | 34da9e50e908c4553ddefb38da2c5bacbe2bba58 (diff) |
bnx2x: link report improvements
To avoid link notification duplication
Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com>
Signed-off-by: Vladislav Zolotarov <vladz@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bnx2x')
-rw-r--r-- | drivers/net/bnx2x/bnx2x.h | 21 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_cmn.c | 129 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_cmn.h | 5 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_main.c | 21 |
4 files changed, 141 insertions, 35 deletions
diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h index 9e87417f6ec7..1a005a484bea 100644 --- a/drivers/net/bnx2x/bnx2x.h +++ b/drivers/net/bnx2x/bnx2x.h | |||
@@ -893,6 +893,22 @@ typedef enum { | |||
893 | (&bp->def_status_blk->sp_sb.\ | 893 | (&bp->def_status_blk->sp_sb.\ |
894 | index_values[HC_SP_INDEX_EQ_CONS]) | 894 | index_values[HC_SP_INDEX_EQ_CONS]) |
895 | 895 | ||
896 | /* This is a data that will be used to create a link report message. | ||
897 | * We will keep the data used for the last link report in order | ||
898 | * to prevent reporting the same link parameters twice. | ||
899 | */ | ||
900 | struct bnx2x_link_report_data { | ||
901 | u16 line_speed; /* Effective line speed */ | ||
902 | unsigned long link_report_flags;/* BNX2X_LINK_REPORT_XXX flags */ | ||
903 | }; | ||
904 | |||
905 | enum { | ||
906 | BNX2X_LINK_REPORT_FD, /* Full DUPLEX */ | ||
907 | BNX2X_LINK_REPORT_LINK_DOWN, | ||
908 | BNX2X_LINK_REPORT_RX_FC_ON, | ||
909 | BNX2X_LINK_REPORT_TX_FC_ON, | ||
910 | }; | ||
911 | |||
896 | struct bnx2x { | 912 | struct bnx2x { |
897 | /* Fields used in the tx and intr/napi performance paths | 913 | /* Fields used in the tx and intr/napi performance paths |
898 | * are grouped together in the beginning of the structure | 914 | * are grouped together in the beginning of the structure |
@@ -1025,6 +1041,9 @@ struct bnx2x { | |||
1025 | 1041 | ||
1026 | struct link_params link_params; | 1042 | struct link_params link_params; |
1027 | struct link_vars link_vars; | 1043 | struct link_vars link_vars; |
1044 | u32 link_cnt; | ||
1045 | struct bnx2x_link_report_data last_reported_link; | ||
1046 | |||
1028 | struct mdio_if_info mdio; | 1047 | struct mdio_if_info mdio; |
1029 | 1048 | ||
1030 | struct bnx2x_common common; | 1049 | struct bnx2x_common common; |
@@ -1441,6 +1460,8 @@ struct bnx2x_func_init_params { | |||
1441 | #define WAIT_RAMROD_POLL 0x01 | 1460 | #define WAIT_RAMROD_POLL 0x01 |
1442 | #define WAIT_RAMROD_COMMON 0x02 | 1461 | #define WAIT_RAMROD_COMMON 0x02 |
1443 | 1462 | ||
1463 | void bnx2x_read_mf_cfg(struct bnx2x *bp); | ||
1464 | |||
1444 | /* dmae */ | 1465 | /* dmae */ |
1445 | void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32); | 1466 | void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32); |
1446 | void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr, | 1467 | void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr, |
diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c index 8729061a4fd5..8853ae2a042e 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.c +++ b/drivers/net/bnx2x/bnx2x_cmn.c | |||
@@ -758,35 +758,119 @@ u16 bnx2x_get_mf_speed(struct bnx2x *bp) | |||
758 | return line_speed; | 758 | return line_speed; |
759 | } | 759 | } |
760 | 760 | ||
761 | /** | ||
762 | * bnx2x_fill_report_data - fill link report data to report | ||
763 | * | ||
764 | * @bp: driver handle | ||
765 | * @data: link state to update | ||
766 | * | ||
767 | * It uses a none-atomic bit operations because is called under the mutex. | ||
768 | */ | ||
769 | static inline void bnx2x_fill_report_data(struct bnx2x *bp, | ||
770 | struct bnx2x_link_report_data *data) | ||
771 | { | ||
772 | u16 line_speed = bnx2x_get_mf_speed(bp); | ||
773 | |||
774 | memset(data, 0, sizeof(*data)); | ||
775 | |||
776 | /* Fill the report data: efective line speed */ | ||
777 | data->line_speed = line_speed; | ||
778 | |||
779 | /* Link is down */ | ||
780 | if (!bp->link_vars.link_up || (bp->flags & MF_FUNC_DIS)) | ||
781 | __set_bit(BNX2X_LINK_REPORT_LINK_DOWN, | ||
782 | &data->link_report_flags); | ||
783 | |||
784 | /* Full DUPLEX */ | ||
785 | if (bp->link_vars.duplex == DUPLEX_FULL) | ||
786 | __set_bit(BNX2X_LINK_REPORT_FD, &data->link_report_flags); | ||
787 | |||
788 | /* Rx Flow Control is ON */ | ||
789 | if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX) | ||
790 | __set_bit(BNX2X_LINK_REPORT_RX_FC_ON, &data->link_report_flags); | ||
791 | |||
792 | /* Tx Flow Control is ON */ | ||
793 | if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_TX) | ||
794 | __set_bit(BNX2X_LINK_REPORT_TX_FC_ON, &data->link_report_flags); | ||
795 | } | ||
796 | |||
797 | /** | ||
798 | * bnx2x_link_report - report link status to OS. | ||
799 | * | ||
800 | * @bp: driver handle | ||
801 | * | ||
802 | * Calls the __bnx2x_link_report() under the same locking scheme | ||
803 | * as a link/PHY state managing code to ensure a consistent link | ||
804 | * reporting. | ||
805 | */ | ||
806 | |||
761 | void bnx2x_link_report(struct bnx2x *bp) | 807 | void bnx2x_link_report(struct bnx2x *bp) |
762 | { | 808 | { |
763 | if (bp->flags & MF_FUNC_DIS) { | 809 | bnx2x_acquire_phy_lock(bp); |
764 | netif_carrier_off(bp->dev); | 810 | __bnx2x_link_report(bp); |
765 | netdev_err(bp->dev, "NIC Link is Down\n"); | 811 | bnx2x_release_phy_lock(bp); |
766 | return; | 812 | } |
767 | } | ||
768 | 813 | ||
769 | if (bp->link_vars.link_up) { | 814 | /** |
770 | u16 line_speed; | 815 | * __bnx2x_link_report - report link status to OS. |
816 | * | ||
817 | * @bp: driver handle | ||
818 | * | ||
819 | * None atomic inmlementation. | ||
820 | * Should be called under the phy_lock. | ||
821 | */ | ||
822 | void __bnx2x_link_report(struct bnx2x *bp) | ||
823 | { | ||
824 | struct bnx2x_link_report_data cur_data; | ||
771 | 825 | ||
772 | if (bp->state == BNX2X_STATE_OPEN) | 826 | /* reread mf_cfg */ |
773 | netif_carrier_on(bp->dev); | 827 | if (!CHIP_IS_E1(bp)) |
774 | netdev_info(bp->dev, "NIC Link is Up, "); | 828 | bnx2x_read_mf_cfg(bp); |
829 | |||
830 | /* Read the current link report info */ | ||
831 | bnx2x_fill_report_data(bp, &cur_data); | ||
832 | |||
833 | /* Don't report link down or exactly the same link status twice */ | ||
834 | if (!memcmp(&cur_data, &bp->last_reported_link, sizeof(cur_data)) || | ||
835 | (test_bit(BNX2X_LINK_REPORT_LINK_DOWN, | ||
836 | &bp->last_reported_link.link_report_flags) && | ||
837 | test_bit(BNX2X_LINK_REPORT_LINK_DOWN, | ||
838 | &cur_data.link_report_flags))) | ||
839 | return; | ||
840 | |||
841 | bp->link_cnt++; | ||
775 | 842 | ||
776 | line_speed = bnx2x_get_mf_speed(bp); | 843 | /* We are going to report a new link parameters now - |
844 | * remember the current data for the next time. | ||
845 | */ | ||
846 | memcpy(&bp->last_reported_link, &cur_data, sizeof(cur_data)); | ||
777 | 847 | ||
778 | pr_cont("%d Mbps ", line_speed); | 848 | if (test_bit(BNX2X_LINK_REPORT_LINK_DOWN, |
849 | &cur_data.link_report_flags)) { | ||
850 | netif_carrier_off(bp->dev); | ||
851 | netdev_err(bp->dev, "NIC Link is Down\n"); | ||
852 | return; | ||
853 | } else { | ||
854 | netif_carrier_on(bp->dev); | ||
855 | netdev_info(bp->dev, "NIC Link is Up, "); | ||
856 | pr_cont("%d Mbps ", cur_data.line_speed); | ||
779 | 857 | ||
780 | if (bp->link_vars.duplex == DUPLEX_FULL) | 858 | if (test_and_clear_bit(BNX2X_LINK_REPORT_FD, |
859 | &cur_data.link_report_flags)) | ||
781 | pr_cont("full duplex"); | 860 | pr_cont("full duplex"); |
782 | else | 861 | else |
783 | pr_cont("half duplex"); | 862 | pr_cont("half duplex"); |
784 | 863 | ||
785 | if (bp->link_vars.flow_ctrl != BNX2X_FLOW_CTRL_NONE) { | 864 | /* Handle the FC at the end so that only these flags would be |
786 | if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX) { | 865 | * possibly set. This way we may easily check if there is no FC |
866 | * enabled. | ||
867 | */ | ||
868 | if (cur_data.link_report_flags) { | ||
869 | if (test_bit(BNX2X_LINK_REPORT_RX_FC_ON, | ||
870 | &cur_data.link_report_flags)) { | ||
787 | pr_cont(", receive "); | 871 | pr_cont(", receive "); |
788 | if (bp->link_vars.flow_ctrl & | 872 | if (test_bit(BNX2X_LINK_REPORT_TX_FC_ON, |
789 | BNX2X_FLOW_CTRL_TX) | 873 | &cur_data.link_report_flags)) |
790 | pr_cont("& transmit "); | 874 | pr_cont("& transmit "); |
791 | } else { | 875 | } else { |
792 | pr_cont(", transmit "); | 876 | pr_cont(", transmit "); |
@@ -794,10 +878,6 @@ void bnx2x_link_report(struct bnx2x *bp) | |||
794 | pr_cont("flow control ON"); | 878 | pr_cont("flow control ON"); |
795 | } | 879 | } |
796 | pr_cont("\n"); | 880 | pr_cont("\n"); |
797 | |||
798 | } else { /* link_down */ | ||
799 | netif_carrier_off(bp->dev); | ||
800 | netdev_err(bp->dev, "NIC Link is Down\n"); | ||
801 | } | 881 | } |
802 | } | 882 | } |
803 | 883 | ||
@@ -1345,6 +1425,13 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) | |||
1345 | 1425 | ||
1346 | bp->state = BNX2X_STATE_OPENING_WAIT4_LOAD; | 1426 | bp->state = BNX2X_STATE_OPENING_WAIT4_LOAD; |
1347 | 1427 | ||
1428 | /* Set the initial link reported state to link down */ | ||
1429 | bnx2x_acquire_phy_lock(bp); | ||
1430 | memset(&bp->last_reported_link, 0, sizeof(bp->last_reported_link)); | ||
1431 | __set_bit(BNX2X_LINK_REPORT_LINK_DOWN, | ||
1432 | &bp->last_reported_link.link_report_flags); | ||
1433 | bnx2x_release_phy_lock(bp); | ||
1434 | |||
1348 | /* must be called before memory allocation and HW init */ | 1435 | /* must be called before memory allocation and HW init */ |
1349 | bnx2x_ilt_set_info(bp); | 1436 | bnx2x_ilt_set_info(bp); |
1350 | 1437 | ||
diff --git a/drivers/net/bnx2x/bnx2x_cmn.h b/drivers/net/bnx2x/bnx2x_cmn.h index 1cdab69b2a51..007f29495c2e 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.h +++ b/drivers/net/bnx2x/bnx2x_cmn.h | |||
@@ -67,11 +67,12 @@ void bnx2x__link_status_update(struct bnx2x *bp); | |||
67 | * Report link status to upper layer | 67 | * Report link status to upper layer |
68 | * | 68 | * |
69 | * @param bp | 69 | * @param bp |
70 | * | ||
71 | * @return int | ||
72 | */ | 70 | */ |
73 | void bnx2x_link_report(struct bnx2x *bp); | 71 | void bnx2x_link_report(struct bnx2x *bp); |
74 | 72 | ||
73 | /* None-atomic version of bnx2x_link_report() */ | ||
74 | void __bnx2x_link_report(struct bnx2x *bp); | ||
75 | |||
75 | /** | 76 | /** |
76 | * calculates MF speed according to current linespeed and MF | 77 | * calculates MF speed according to current linespeed and MF |
77 | * configuration | 78 | * configuration |
diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index bfd7ac98248b..3f4ff41cd333 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c | |||
@@ -2036,7 +2036,7 @@ static int bnx2x_get_cmng_fns_mode(struct bnx2x *bp) | |||
2036 | return CMNG_FNS_NONE; | 2036 | return CMNG_FNS_NONE; |
2037 | } | 2037 | } |
2038 | 2038 | ||
2039 | static void bnx2x_read_mf_cfg(struct bnx2x *bp) | 2039 | void bnx2x_read_mf_cfg(struct bnx2x *bp) |
2040 | { | 2040 | { |
2041 | int vn, n = (CHIP_MODE_IS_4_PORT(bp) ? 2 : 1); | 2041 | int vn, n = (CHIP_MODE_IS_4_PORT(bp) ? 2 : 1); |
2042 | 2042 | ||
@@ -2123,7 +2123,6 @@ static inline void bnx2x_link_sync_notify(struct bnx2x *bp) | |||
2123 | /* This function is called upon link interrupt */ | 2123 | /* This function is called upon link interrupt */ |
2124 | static void bnx2x_link_attn(struct bnx2x *bp) | 2124 | static void bnx2x_link_attn(struct bnx2x *bp) |
2125 | { | 2125 | { |
2126 | u32 prev_link_status = bp->link_vars.link_status; | ||
2127 | /* Make sure that we are synced with the current statistics */ | 2126 | /* Make sure that we are synced with the current statistics */ |
2128 | bnx2x_stats_handle(bp, STATS_EVENT_STOP); | 2127 | bnx2x_stats_handle(bp, STATS_EVENT_STOP); |
2129 | 2128 | ||
@@ -2168,17 +2167,15 @@ static void bnx2x_link_attn(struct bnx2x *bp) | |||
2168 | "single function mode without fairness\n"); | 2167 | "single function mode without fairness\n"); |
2169 | } | 2168 | } |
2170 | 2169 | ||
2170 | __bnx2x_link_report(bp); | ||
2171 | |||
2171 | if (IS_MF(bp)) | 2172 | if (IS_MF(bp)) |
2172 | bnx2x_link_sync_notify(bp); | 2173 | bnx2x_link_sync_notify(bp); |
2173 | |||
2174 | /* indicate link status only if link status actually changed */ | ||
2175 | if (prev_link_status != bp->link_vars.link_status) | ||
2176 | bnx2x_link_report(bp); | ||
2177 | } | 2174 | } |
2178 | 2175 | ||
2179 | void bnx2x__link_status_update(struct bnx2x *bp) | 2176 | void bnx2x__link_status_update(struct bnx2x *bp) |
2180 | { | 2177 | { |
2181 | if ((bp->state != BNX2X_STATE_OPEN) || (bp->flags & MF_FUNC_DIS)) | 2178 | if (bp->state != BNX2X_STATE_OPEN) |
2182 | return; | 2179 | return; |
2183 | 2180 | ||
2184 | bnx2x_link_status_update(&bp->link_params, &bp->link_vars); | 2181 | bnx2x_link_status_update(&bp->link_params, &bp->link_vars); |
@@ -2188,10 +2185,6 @@ void bnx2x__link_status_update(struct bnx2x *bp) | |||
2188 | else | 2185 | else |
2189 | bnx2x_stats_handle(bp, STATS_EVENT_STOP); | 2186 | bnx2x_stats_handle(bp, STATS_EVENT_STOP); |
2190 | 2187 | ||
2191 | /* the link status update could be the result of a DCC event | ||
2192 | hence re-read the shmem mf configuration */ | ||
2193 | bnx2x_read_mf_cfg(bp); | ||
2194 | |||
2195 | /* indicate link status */ | 2188 | /* indicate link status */ |
2196 | bnx2x_link_report(bp); | 2189 | bnx2x_link_report(bp); |
2197 | } | 2190 | } |
@@ -3120,10 +3113,14 @@ static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn) | |||
3120 | if (val & DRV_STATUS_SET_MF_BW) | 3113 | if (val & DRV_STATUS_SET_MF_BW) |
3121 | bnx2x_set_mf_bw(bp); | 3114 | bnx2x_set_mf_bw(bp); |
3122 | 3115 | ||
3123 | bnx2x__link_status_update(bp); | ||
3124 | if ((bp->port.pmf == 0) && (val & DRV_STATUS_PMF)) | 3116 | if ((bp->port.pmf == 0) && (val & DRV_STATUS_PMF)) |
3125 | bnx2x_pmf_update(bp); | 3117 | bnx2x_pmf_update(bp); |
3126 | 3118 | ||
3119 | /* Always call it here: bnx2x_link_report() will | ||
3120 | * prevent the link indication duplication. | ||
3121 | */ | ||
3122 | bnx2x__link_status_update(bp); | ||
3123 | |||
3127 | if (bp->port.pmf && | 3124 | if (bp->port.pmf && |
3128 | (val & DRV_STATUS_DCBX_NEGOTIATION_RESULTS) && | 3125 | (val & DRV_STATUS_DCBX_NEGOTIATION_RESULTS) && |
3129 | bp->dcbx_enabled > 0) | 3126 | bp->dcbx_enabled > 0) |