aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bnx2x
diff options
context:
space:
mode:
authorVladislav Zolotarov <vladz@broadcom.com>2011-05-04 19:48:23 -0400
committerDavid S. Miller <davem@davemloft.net>2011-05-05 13:44:33 -0400
commit2ae17f666099c952053eea7c64cac8189dd76f72 (patch)
tree69da6881c755adccec1ef4e09ec28bc499e979e9 /drivers/net/bnx2x
parent34da9e50e908c4553ddefb38da2c5bacbe2bba58 (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.h21
-rw-r--r--drivers/net/bnx2x/bnx2x_cmn.c129
-rw-r--r--drivers/net/bnx2x/bnx2x_cmn.h5
-rw-r--r--drivers/net/bnx2x/bnx2x_main.c21
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 */
900struct bnx2x_link_report_data {
901 u16 line_speed; /* Effective line speed */
902 unsigned long link_report_flags;/* BNX2X_LINK_REPORT_XXX flags */
903};
904
905enum {
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
896struct bnx2x { 912struct 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
1463void bnx2x_read_mf_cfg(struct bnx2x *bp);
1464
1444/* dmae */ 1465/* dmae */
1445void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32); 1466void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32);
1446void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr, 1467void 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 */
769static 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
761void bnx2x_link_report(struct bnx2x *bp) 807void 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 */
822void __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 */
73void bnx2x_link_report(struct bnx2x *bp); 71void bnx2x_link_report(struct bnx2x *bp);
74 72
73/* None-atomic version of bnx2x_link_report() */
74void __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
2039static void bnx2x_read_mf_cfg(struct bnx2x *bp) 2039void 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 */
2124static void bnx2x_link_attn(struct bnx2x *bp) 2124static 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
2179void bnx2x__link_status_update(struct bnx2x *bp) 2176void 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)