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/bnx2x_cmn.c | |
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/bnx2x_cmn.c')
-rw-r--r-- | drivers/net/bnx2x/bnx2x_cmn.c | 129 |
1 files changed, 108 insertions, 21 deletions
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 | ||