diff options
author | Matt Carlson <mcarlson@broadcom.com> | 2008-05-26 02:44:14 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-05-29 04:36:00 -0400 |
commit | 95e2869adc13041baf3beecb97ab8e38c01525ae (patch) | |
tree | 5783e7e904ed4be6c3b9d8549a4378954662e9f7 /drivers | |
parent | 54064600981ab0fe977b0e760732c30f4472d693 (diff) |
tg3: Pure code movement.
This patch moves some functions towards the top of the file to avoid
unnecessary function prototypes.
Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: Benjamin Li <benli@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/tg3.c | 476 |
1 files changed, 237 insertions, 239 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 07b3f77e7626..7928acc1ec7a 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -804,6 +804,243 @@ static int tg3_writephy(struct tg3 *tp, int reg, u32 val) | |||
804 | return ret; | 804 | return ret; |
805 | } | 805 | } |
806 | 806 | ||
807 | static int tg3_bmcr_reset(struct tg3 *tp) | ||
808 | { | ||
809 | u32 phy_control; | ||
810 | int limit, err; | ||
811 | |||
812 | /* OK, reset it, and poll the BMCR_RESET bit until it | ||
813 | * clears or we time out. | ||
814 | */ | ||
815 | phy_control = BMCR_RESET; | ||
816 | err = tg3_writephy(tp, MII_BMCR, phy_control); | ||
817 | if (err != 0) | ||
818 | return -EBUSY; | ||
819 | |||
820 | limit = 5000; | ||
821 | while (limit--) { | ||
822 | err = tg3_readphy(tp, MII_BMCR, &phy_control); | ||
823 | if (err != 0) | ||
824 | return -EBUSY; | ||
825 | |||
826 | if ((phy_control & BMCR_RESET) == 0) { | ||
827 | udelay(40); | ||
828 | break; | ||
829 | } | ||
830 | udelay(10); | ||
831 | } | ||
832 | if (limit <= 0) | ||
833 | return -EBUSY; | ||
834 | |||
835 | return 0; | ||
836 | } | ||
837 | |||
838 | /* tp->lock is held. */ | ||
839 | static void tg3_wait_for_event_ack(struct tg3 *tp) | ||
840 | { | ||
841 | int i; | ||
842 | |||
843 | /* Wait for up to 2.5 milliseconds */ | ||
844 | for (i = 0; i < 250000; i++) { | ||
845 | if (!(tr32(GRC_RX_CPU_EVENT) & GRC_RX_CPU_DRIVER_EVENT)) | ||
846 | break; | ||
847 | udelay(10); | ||
848 | } | ||
849 | } | ||
850 | |||
851 | /* tp->lock is held. */ | ||
852 | static void tg3_ump_link_report(struct tg3 *tp) | ||
853 | { | ||
854 | u32 reg; | ||
855 | u32 val; | ||
856 | |||
857 | if (!(tp->tg3_flags2 & TG3_FLG2_5780_CLASS) || | ||
858 | !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) | ||
859 | return; | ||
860 | |||
861 | tg3_wait_for_event_ack(tp); | ||
862 | |||
863 | tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_LINK_UPDATE); | ||
864 | |||
865 | tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 14); | ||
866 | |||
867 | val = 0; | ||
868 | if (!tg3_readphy(tp, MII_BMCR, ®)) | ||
869 | val = reg << 16; | ||
870 | if (!tg3_readphy(tp, MII_BMSR, ®)) | ||
871 | val |= (reg & 0xffff); | ||
872 | tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, val); | ||
873 | |||
874 | val = 0; | ||
875 | if (!tg3_readphy(tp, MII_ADVERTISE, ®)) | ||
876 | val = reg << 16; | ||
877 | if (!tg3_readphy(tp, MII_LPA, ®)) | ||
878 | val |= (reg & 0xffff); | ||
879 | tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 4, val); | ||
880 | |||
881 | val = 0; | ||
882 | if (!(tp->tg3_flags2 & TG3_FLG2_MII_SERDES)) { | ||
883 | if (!tg3_readphy(tp, MII_CTRL1000, ®)) | ||
884 | val = reg << 16; | ||
885 | if (!tg3_readphy(tp, MII_STAT1000, ®)) | ||
886 | val |= (reg & 0xffff); | ||
887 | } | ||
888 | tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 8, val); | ||
889 | |||
890 | if (!tg3_readphy(tp, MII_PHYADDR, ®)) | ||
891 | val = reg << 16; | ||
892 | else | ||
893 | val = 0; | ||
894 | tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 12, val); | ||
895 | |||
896 | val = tr32(GRC_RX_CPU_EVENT); | ||
897 | val |= GRC_RX_CPU_DRIVER_EVENT; | ||
898 | tw32_f(GRC_RX_CPU_EVENT, val); | ||
899 | } | ||
900 | |||
901 | static void tg3_link_report(struct tg3 *tp) | ||
902 | { | ||
903 | if (!netif_carrier_ok(tp->dev)) { | ||
904 | if (netif_msg_link(tp)) | ||
905 | printk(KERN_INFO PFX "%s: Link is down.\n", | ||
906 | tp->dev->name); | ||
907 | tg3_ump_link_report(tp); | ||
908 | } else if (netif_msg_link(tp)) { | ||
909 | printk(KERN_INFO PFX "%s: Link is up at %d Mbps, %s duplex.\n", | ||
910 | tp->dev->name, | ||
911 | (tp->link_config.active_speed == SPEED_1000 ? | ||
912 | 1000 : | ||
913 | (tp->link_config.active_speed == SPEED_100 ? | ||
914 | 100 : 10)), | ||
915 | (tp->link_config.active_duplex == DUPLEX_FULL ? | ||
916 | "full" : "half")); | ||
917 | |||
918 | printk(KERN_INFO PFX | ||
919 | "%s: Flow control is %s for TX and %s for RX.\n", | ||
920 | tp->dev->name, | ||
921 | (tp->link_config.active_flowctrl & TG3_FLOW_CTRL_TX) ? | ||
922 | "on" : "off", | ||
923 | (tp->link_config.active_flowctrl & TG3_FLOW_CTRL_RX) ? | ||
924 | "on" : "off"); | ||
925 | tg3_ump_link_report(tp); | ||
926 | } | ||
927 | } | ||
928 | |||
929 | static u16 tg3_advert_flowctrl_1000T(u8 flow_ctrl) | ||
930 | { | ||
931 | u16 miireg; | ||
932 | |||
933 | if ((flow_ctrl & TG3_FLOW_CTRL_TX) && (flow_ctrl & TG3_FLOW_CTRL_RX)) | ||
934 | miireg = ADVERTISE_PAUSE_CAP; | ||
935 | else if (flow_ctrl & TG3_FLOW_CTRL_TX) | ||
936 | miireg = ADVERTISE_PAUSE_ASYM; | ||
937 | else if (flow_ctrl & TG3_FLOW_CTRL_RX) | ||
938 | miireg = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; | ||
939 | else | ||
940 | miireg = 0; | ||
941 | |||
942 | return miireg; | ||
943 | } | ||
944 | |||
945 | static u16 tg3_advert_flowctrl_1000X(u8 flow_ctrl) | ||
946 | { | ||
947 | u16 miireg; | ||
948 | |||
949 | if ((flow_ctrl & TG3_FLOW_CTRL_TX) && (flow_ctrl & TG3_FLOW_CTRL_RX)) | ||
950 | miireg = ADVERTISE_1000XPAUSE; | ||
951 | else if (flow_ctrl & TG3_FLOW_CTRL_TX) | ||
952 | miireg = ADVERTISE_1000XPSE_ASYM; | ||
953 | else if (flow_ctrl & TG3_FLOW_CTRL_RX) | ||
954 | miireg = ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM; | ||
955 | else | ||
956 | miireg = 0; | ||
957 | |||
958 | return miireg; | ||
959 | } | ||
960 | |||
961 | static u8 tg3_resolve_flowctrl_1000T(u16 lcladv, u16 rmtadv) | ||
962 | { | ||
963 | u8 cap = 0; | ||
964 | |||
965 | if (lcladv & ADVERTISE_PAUSE_CAP) { | ||
966 | if (lcladv & ADVERTISE_PAUSE_ASYM) { | ||
967 | if (rmtadv & LPA_PAUSE_CAP) | ||
968 | cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX; | ||
969 | else if (rmtadv & LPA_PAUSE_ASYM) | ||
970 | cap = TG3_FLOW_CTRL_RX; | ||
971 | } else { | ||
972 | if (rmtadv & LPA_PAUSE_CAP) | ||
973 | cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX; | ||
974 | } | ||
975 | } else if (lcladv & ADVERTISE_PAUSE_ASYM) { | ||
976 | if ((rmtadv & LPA_PAUSE_CAP) && (rmtadv & LPA_PAUSE_ASYM)) | ||
977 | cap = TG3_FLOW_CTRL_TX; | ||
978 | } | ||
979 | |||
980 | return cap; | ||
981 | } | ||
982 | |||
983 | static u8 tg3_resolve_flowctrl_1000X(u16 lcladv, u16 rmtadv) | ||
984 | { | ||
985 | u8 cap = 0; | ||
986 | |||
987 | if (lcladv & ADVERTISE_1000XPAUSE) { | ||
988 | if (lcladv & ADVERTISE_1000XPSE_ASYM) { | ||
989 | if (rmtadv & LPA_1000XPAUSE) | ||
990 | cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX; | ||
991 | else if (rmtadv & LPA_1000XPAUSE_ASYM) | ||
992 | cap = TG3_FLOW_CTRL_RX; | ||
993 | } else { | ||
994 | if (rmtadv & LPA_1000XPAUSE) | ||
995 | cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX; | ||
996 | } | ||
997 | } else if (lcladv & ADVERTISE_1000XPSE_ASYM) { | ||
998 | if ((rmtadv & LPA_1000XPAUSE) && (rmtadv & LPA_1000XPAUSE_ASYM)) | ||
999 | cap = TG3_FLOW_CTRL_TX; | ||
1000 | } | ||
1001 | |||
1002 | return cap; | ||
1003 | } | ||
1004 | |||
1005 | static void tg3_setup_flow_control(struct tg3 *tp, u32 local_adv, u32 remote_adv) | ||
1006 | { | ||
1007 | u8 new_tg3_flags = 0; | ||
1008 | u32 old_rx_mode = tp->rx_mode; | ||
1009 | u32 old_tx_mode = tp->tx_mode; | ||
1010 | |||
1011 | if (tp->link_config.autoneg == AUTONEG_ENABLE && | ||
1012 | (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG)) { | ||
1013 | if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) | ||
1014 | new_tg3_flags = tg3_resolve_flowctrl_1000X(local_adv, | ||
1015 | remote_adv); | ||
1016 | else | ||
1017 | new_tg3_flags = tg3_resolve_flowctrl_1000T(local_adv, | ||
1018 | remote_adv); | ||
1019 | } else { | ||
1020 | new_tg3_flags = tp->link_config.flowctrl; | ||
1021 | } | ||
1022 | |||
1023 | tp->link_config.active_flowctrl = new_tg3_flags; | ||
1024 | |||
1025 | if (new_tg3_flags & TG3_FLOW_CTRL_RX) | ||
1026 | tp->rx_mode |= RX_MODE_FLOW_CTRL_ENABLE; | ||
1027 | else | ||
1028 | tp->rx_mode &= ~RX_MODE_FLOW_CTRL_ENABLE; | ||
1029 | |||
1030 | if (old_rx_mode != tp->rx_mode) { | ||
1031 | tw32_f(MAC_RX_MODE, tp->rx_mode); | ||
1032 | } | ||
1033 | |||
1034 | if (new_tg3_flags & TG3_FLOW_CTRL_TX) | ||
1035 | tp->tx_mode |= TX_MODE_FLOW_CTRL_ENABLE; | ||
1036 | else | ||
1037 | tp->tx_mode &= ~TX_MODE_FLOW_CTRL_ENABLE; | ||
1038 | |||
1039 | if (old_tx_mode != tp->tx_mode) { | ||
1040 | tw32_f(MAC_TX_MODE, tp->tx_mode); | ||
1041 | } | ||
1042 | } | ||
1043 | |||
807 | static void tg3_phydsp_write(struct tg3 *tp, u32 reg, u32 val) | 1044 | static void tg3_phydsp_write(struct tg3 *tp, u32 reg, u32 val) |
808 | { | 1045 | { |
809 | tg3_writephy(tp, MII_TG3_DSP_ADDRESS, reg); | 1046 | tg3_writephy(tp, MII_TG3_DSP_ADDRESS, reg); |
@@ -861,37 +1098,6 @@ static void tg3_phy_set_wirespeed(struct tg3 *tp) | |||
861 | (val | (1 << 15) | (1 << 4))); | 1098 | (val | (1 << 15) | (1 << 4))); |
862 | } | 1099 | } |
863 | 1100 | ||
864 | static int tg3_bmcr_reset(struct tg3 *tp) | ||
865 | { | ||
866 | u32 phy_control; | ||
867 | int limit, err; | ||
868 | |||
869 | /* OK, reset it, and poll the BMCR_RESET bit until it | ||
870 | * clears or we time out. | ||
871 | */ | ||
872 | phy_control = BMCR_RESET; | ||
873 | err = tg3_writephy(tp, MII_BMCR, phy_control); | ||
874 | if (err != 0) | ||
875 | return -EBUSY; | ||
876 | |||
877 | limit = 5000; | ||
878 | while (limit--) { | ||
879 | err = tg3_readphy(tp, MII_BMCR, &phy_control); | ||
880 | if (err != 0) | ||
881 | return -EBUSY; | ||
882 | |||
883 | if ((phy_control & BMCR_RESET) == 0) { | ||
884 | udelay(40); | ||
885 | break; | ||
886 | } | ||
887 | udelay(10); | ||
888 | } | ||
889 | if (limit <= 0) | ||
890 | return -EBUSY; | ||
891 | |||
892 | return 0; | ||
893 | } | ||
894 | |||
895 | static void tg3_phy_apply_otp(struct tg3 *tp) | 1101 | static void tg3_phy_apply_otp(struct tg3 *tp) |
896 | { | 1102 | { |
897 | u32 otp, phy; | 1103 | u32 otp, phy; |
@@ -1115,8 +1321,6 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) | |||
1115 | return err; | 1321 | return err; |
1116 | } | 1322 | } |
1117 | 1323 | ||
1118 | static void tg3_link_report(struct tg3 *); | ||
1119 | |||
1120 | /* This will reset the tigon3 PHY if there is no valid | 1324 | /* This will reset the tigon3 PHY if there is no valid |
1121 | * link unless the FORCE argument is non-zero. | 1325 | * link unless the FORCE argument is non-zero. |
1122 | */ | 1326 | */ |
@@ -1656,212 +1860,6 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) | |||
1656 | return 0; | 1860 | return 0; |
1657 | } | 1861 | } |
1658 | 1862 | ||
1659 | /* tp->lock is held. */ | ||
1660 | static void tg3_wait_for_event_ack(struct tg3 *tp) | ||
1661 | { | ||
1662 | int i; | ||
1663 | |||
1664 | /* Wait for up to 2.5 milliseconds */ | ||
1665 | for (i = 0; i < 250000; i++) { | ||
1666 | if (!(tr32(GRC_RX_CPU_EVENT) & GRC_RX_CPU_DRIVER_EVENT)) | ||
1667 | break; | ||
1668 | udelay(10); | ||
1669 | } | ||
1670 | } | ||
1671 | |||
1672 | /* tp->lock is held. */ | ||
1673 | static void tg3_ump_link_report(struct tg3 *tp) | ||
1674 | { | ||
1675 | u32 reg; | ||
1676 | u32 val; | ||
1677 | |||
1678 | if (!(tp->tg3_flags2 & TG3_FLG2_5780_CLASS) || | ||
1679 | !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) | ||
1680 | return; | ||
1681 | |||
1682 | tg3_wait_for_event_ack(tp); | ||
1683 | |||
1684 | tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_LINK_UPDATE); | ||
1685 | |||
1686 | tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 14); | ||
1687 | |||
1688 | val = 0; | ||
1689 | if (!tg3_readphy(tp, MII_BMCR, ®)) | ||
1690 | val = reg << 16; | ||
1691 | if (!tg3_readphy(tp, MII_BMSR, ®)) | ||
1692 | val |= (reg & 0xffff); | ||
1693 | tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, val); | ||
1694 | |||
1695 | val = 0; | ||
1696 | if (!tg3_readphy(tp, MII_ADVERTISE, ®)) | ||
1697 | val = reg << 16; | ||
1698 | if (!tg3_readphy(tp, MII_LPA, ®)) | ||
1699 | val |= (reg & 0xffff); | ||
1700 | tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 4, val); | ||
1701 | |||
1702 | val = 0; | ||
1703 | if (!(tp->tg3_flags2 & TG3_FLG2_MII_SERDES)) { | ||
1704 | if (!tg3_readphy(tp, MII_CTRL1000, ®)) | ||
1705 | val = reg << 16; | ||
1706 | if (!tg3_readphy(tp, MII_STAT1000, ®)) | ||
1707 | val |= (reg & 0xffff); | ||
1708 | } | ||
1709 | tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 8, val); | ||
1710 | |||
1711 | if (!tg3_readphy(tp, MII_PHYADDR, ®)) | ||
1712 | val = reg << 16; | ||
1713 | else | ||
1714 | val = 0; | ||
1715 | tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 12, val); | ||
1716 | |||
1717 | val = tr32(GRC_RX_CPU_EVENT); | ||
1718 | val |= GRC_RX_CPU_DRIVER_EVENT; | ||
1719 | tw32_f(GRC_RX_CPU_EVENT, val); | ||
1720 | } | ||
1721 | |||
1722 | static void tg3_link_report(struct tg3 *tp) | ||
1723 | { | ||
1724 | if (!netif_carrier_ok(tp->dev)) { | ||
1725 | if (netif_msg_link(tp)) | ||
1726 | printk(KERN_INFO PFX "%s: Link is down.\n", | ||
1727 | tp->dev->name); | ||
1728 | tg3_ump_link_report(tp); | ||
1729 | } else if (netif_msg_link(tp)) { | ||
1730 | printk(KERN_INFO PFX "%s: Link is up at %d Mbps, %s duplex.\n", | ||
1731 | tp->dev->name, | ||
1732 | (tp->link_config.active_speed == SPEED_1000 ? | ||
1733 | 1000 : | ||
1734 | (tp->link_config.active_speed == SPEED_100 ? | ||
1735 | 100 : 10)), | ||
1736 | (tp->link_config.active_duplex == DUPLEX_FULL ? | ||
1737 | "full" : "half")); | ||
1738 | |||
1739 | printk(KERN_INFO PFX | ||
1740 | "%s: Flow control is %s for TX and %s for RX.\n", | ||
1741 | tp->dev->name, | ||
1742 | (tp->link_config.active_flowctrl & TG3_FLOW_CTRL_TX) ? | ||
1743 | "on" : "off", | ||
1744 | (tp->link_config.active_flowctrl & TG3_FLOW_CTRL_RX) ? | ||
1745 | "on" : "off"); | ||
1746 | tg3_ump_link_report(tp); | ||
1747 | } | ||
1748 | } | ||
1749 | |||
1750 | static u16 tg3_advert_flowctrl_1000T(u8 flow_ctrl) | ||
1751 | { | ||
1752 | u16 miireg; | ||
1753 | |||
1754 | if ((flow_ctrl & TG3_FLOW_CTRL_TX) && (flow_ctrl & TG3_FLOW_CTRL_RX)) | ||
1755 | miireg = ADVERTISE_PAUSE_CAP; | ||
1756 | else if (flow_ctrl & TG3_FLOW_CTRL_TX) | ||
1757 | miireg = ADVERTISE_PAUSE_ASYM; | ||
1758 | else if (flow_ctrl & TG3_FLOW_CTRL_RX) | ||
1759 | miireg = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; | ||
1760 | else | ||
1761 | miireg = 0; | ||
1762 | |||
1763 | return miireg; | ||
1764 | } | ||
1765 | |||
1766 | static u16 tg3_advert_flowctrl_1000X(u8 flow_ctrl) | ||
1767 | { | ||
1768 | u16 miireg; | ||
1769 | |||
1770 | if ((flow_ctrl & TG3_FLOW_CTRL_TX) && (flow_ctrl & TG3_FLOW_CTRL_RX)) | ||
1771 | miireg = ADVERTISE_1000XPAUSE; | ||
1772 | else if (flow_ctrl & TG3_FLOW_CTRL_TX) | ||
1773 | miireg = ADVERTISE_1000XPSE_ASYM; | ||
1774 | else if (flow_ctrl & TG3_FLOW_CTRL_RX) | ||
1775 | miireg = ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM; | ||
1776 | else | ||
1777 | miireg = 0; | ||
1778 | |||
1779 | return miireg; | ||
1780 | } | ||
1781 | |||
1782 | static u8 tg3_resolve_flowctrl_1000T(u16 lcladv, u16 rmtadv) | ||
1783 | { | ||
1784 | u8 cap = 0; | ||
1785 | |||
1786 | if (lcladv & ADVERTISE_PAUSE_CAP) { | ||
1787 | if (lcladv & ADVERTISE_PAUSE_ASYM) { | ||
1788 | if (rmtadv & LPA_PAUSE_CAP) | ||
1789 | cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX; | ||
1790 | else if (rmtadv & LPA_PAUSE_ASYM) | ||
1791 | cap = TG3_FLOW_CTRL_RX; | ||
1792 | } else { | ||
1793 | if (rmtadv & LPA_PAUSE_CAP) | ||
1794 | cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX; | ||
1795 | } | ||
1796 | } else if (lcladv & ADVERTISE_PAUSE_ASYM) { | ||
1797 | if ((rmtadv & LPA_PAUSE_CAP) && (rmtadv & LPA_PAUSE_ASYM)) | ||
1798 | cap = TG3_FLOW_CTRL_TX; | ||
1799 | } | ||
1800 | |||
1801 | return cap; | ||
1802 | } | ||
1803 | |||
1804 | static u8 tg3_resolve_flowctrl_1000X(u16 lcladv, u16 rmtadv) | ||
1805 | { | ||
1806 | u8 cap = 0; | ||
1807 | |||
1808 | if (lcladv & ADVERTISE_1000XPAUSE) { | ||
1809 | if (lcladv & ADVERTISE_1000XPSE_ASYM) { | ||
1810 | if (rmtadv & LPA_1000XPAUSE) | ||
1811 | cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX; | ||
1812 | else if (rmtadv & LPA_1000XPAUSE_ASYM) | ||
1813 | cap = TG3_FLOW_CTRL_RX; | ||
1814 | } else { | ||
1815 | if (rmtadv & LPA_1000XPAUSE) | ||
1816 | cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX; | ||
1817 | } | ||
1818 | } else if (lcladv & ADVERTISE_1000XPSE_ASYM) { | ||
1819 | if ((rmtadv & LPA_1000XPAUSE) && (rmtadv & LPA_1000XPAUSE_ASYM)) | ||
1820 | cap = TG3_FLOW_CTRL_TX; | ||
1821 | } | ||
1822 | |||
1823 | return cap; | ||
1824 | } | ||
1825 | |||
1826 | static void tg3_setup_flow_control(struct tg3 *tp, u32 local_adv, u32 remote_adv) | ||
1827 | { | ||
1828 | u8 new_tg3_flags = 0; | ||
1829 | u32 old_rx_mode = tp->rx_mode; | ||
1830 | u32 old_tx_mode = tp->tx_mode; | ||
1831 | |||
1832 | if (tp->link_config.autoneg == AUTONEG_ENABLE && | ||
1833 | (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG)) { | ||
1834 | if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) | ||
1835 | new_tg3_flags = tg3_resolve_flowctrl_1000X(local_adv, | ||
1836 | remote_adv); | ||
1837 | else | ||
1838 | new_tg3_flags = tg3_resolve_flowctrl_1000T(local_adv, | ||
1839 | remote_adv); | ||
1840 | } else { | ||
1841 | new_tg3_flags = tp->link_config.flowctrl; | ||
1842 | } | ||
1843 | |||
1844 | tp->link_config.active_flowctrl = new_tg3_flags; | ||
1845 | |||
1846 | if (new_tg3_flags & TG3_FLOW_CTRL_RX) | ||
1847 | tp->rx_mode |= RX_MODE_FLOW_CTRL_ENABLE; | ||
1848 | else | ||
1849 | tp->rx_mode &= ~RX_MODE_FLOW_CTRL_ENABLE; | ||
1850 | |||
1851 | if (old_rx_mode != tp->rx_mode) { | ||
1852 | tw32_f(MAC_RX_MODE, tp->rx_mode); | ||
1853 | } | ||
1854 | |||
1855 | if (new_tg3_flags & TG3_FLOW_CTRL_TX) | ||
1856 | tp->tx_mode |= TX_MODE_FLOW_CTRL_ENABLE; | ||
1857 | else | ||
1858 | tp->tx_mode &= ~TX_MODE_FLOW_CTRL_ENABLE; | ||
1859 | |||
1860 | if (old_tx_mode != tp->tx_mode) { | ||
1861 | tw32_f(MAC_TX_MODE, tp->tx_mode); | ||
1862 | } | ||
1863 | } | ||
1864 | |||
1865 | static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 *duplex) | 1863 | static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 *duplex) |
1866 | { | 1864 | { |
1867 | switch (val & MII_TG3_AUX_STAT_SPDMASK) { | 1865 | switch (val & MII_TG3_AUX_STAT_SPDMASK) { |