diff options
author | Jeff Garzik <jeff@garzik.org> | 2008-09-03 10:21:20 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2008-09-03 10:21:20 -0400 |
commit | 9389523a77be0a7e01d957c836733b5c9d5530a1 (patch) | |
tree | 5ef303e24f23ffbcf74973f3d6238f2a4b71fd1d /drivers/net | |
parent | 3be1adfb912867e244729c3826b457ee76b8f737 (diff) | |
parent | 2857ffb7b8913ef713533ac5783abd70a20529e4 (diff) |
Merge branch 'r8169-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/romieu/netdev-2.6 into upstream-next
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/r8169.c | 401 |
1 files changed, 335 insertions, 66 deletions
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 0f6f9747d255..1822491f19cb 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c | |||
@@ -61,6 +61,7 @@ static const int multicast_filter_limit = 32; | |||
61 | /* MAC address length */ | 61 | /* MAC address length */ |
62 | #define MAC_ADDR_LEN 6 | 62 | #define MAC_ADDR_LEN 6 |
63 | 63 | ||
64 | #define MAX_READ_REQUEST_SHIFT 12 | ||
64 | #define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ | 65 | #define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ |
65 | #define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ | 66 | #define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ |
66 | #define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ | 67 | #define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ |
@@ -95,6 +96,10 @@ enum mac_version { | |||
95 | RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB | 96 | RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB |
96 | RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd | 97 | RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd |
97 | RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe | 98 | RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe |
99 | RTL_GIGA_MAC_VER_07 = 0x07, // 8102e | ||
100 | RTL_GIGA_MAC_VER_08 = 0x08, // 8102e | ||
101 | RTL_GIGA_MAC_VER_09 = 0x09, // 8102e | ||
102 | RTL_GIGA_MAC_VER_10 = 0x0a, // 8101e | ||
98 | RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb | 103 | RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb |
99 | RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be | 104 | RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be |
100 | RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb | 105 | RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb |
@@ -121,6 +126,10 @@ static const struct { | |||
121 | _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB | 126 | _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB |
122 | _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd | 127 | _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd |
123 | _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe | 128 | _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe |
129 | _R("RTL8102e", RTL_GIGA_MAC_VER_07, 0xff7e1880), // PCI-E | ||
130 | _R("RTL8102e", RTL_GIGA_MAC_VER_08, 0xff7e1880), // PCI-E | ||
131 | _R("RTL8102e", RTL_GIGA_MAC_VER_09, 0xff7e1880), // PCI-E | ||
132 | _R("RTL8101e", RTL_GIGA_MAC_VER_10, 0xff7e1880), // PCI-E | ||
124 | _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E | 133 | _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E |
125 | _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E | 134 | _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E |
126 | _R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139 | 135 | _R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139 |
@@ -196,9 +205,6 @@ enum rtl_registers { | |||
196 | Config5 = 0x56, | 205 | Config5 = 0x56, |
197 | MultiIntr = 0x5c, | 206 | MultiIntr = 0x5c, |
198 | PHYAR = 0x60, | 207 | PHYAR = 0x60, |
199 | TBICSR = 0x64, | ||
200 | TBI_ANAR = 0x68, | ||
201 | TBI_LPAR = 0x6a, | ||
202 | PHYstatus = 0x6c, | 208 | PHYstatus = 0x6c, |
203 | RxMaxSize = 0xda, | 209 | RxMaxSize = 0xda, |
204 | CPlusCmd = 0xe0, | 210 | CPlusCmd = 0xe0, |
@@ -212,6 +218,32 @@ enum rtl_registers { | |||
212 | FuncForceEvent = 0xfc, | 218 | FuncForceEvent = 0xfc, |
213 | }; | 219 | }; |
214 | 220 | ||
221 | enum rtl8110_registers { | ||
222 | TBICSR = 0x64, | ||
223 | TBI_ANAR = 0x68, | ||
224 | TBI_LPAR = 0x6a, | ||
225 | }; | ||
226 | |||
227 | enum rtl8168_8101_registers { | ||
228 | CSIDR = 0x64, | ||
229 | CSIAR = 0x68, | ||
230 | #define CSIAR_FLAG 0x80000000 | ||
231 | #define CSIAR_WRITE_CMD 0x80000000 | ||
232 | #define CSIAR_BYTE_ENABLE 0x0f | ||
233 | #define CSIAR_BYTE_ENABLE_SHIFT 12 | ||
234 | #define CSIAR_ADDR_MASK 0x0fff | ||
235 | |||
236 | EPHYAR = 0x80, | ||
237 | #define EPHYAR_FLAG 0x80000000 | ||
238 | #define EPHYAR_WRITE_CMD 0x80000000 | ||
239 | #define EPHYAR_REG_MASK 0x1f | ||
240 | #define EPHYAR_REG_SHIFT 16 | ||
241 | #define EPHYAR_DATA_MASK 0xffff | ||
242 | DBG_REG = 0xd1, | ||
243 | #define FIX_NAK_1 (1 << 4) | ||
244 | #define FIX_NAK_2 (1 << 3) | ||
245 | }; | ||
246 | |||
215 | enum rtl_register_content { | 247 | enum rtl_register_content { |
216 | /* InterruptStatusBits */ | 248 | /* InterruptStatusBits */ |
217 | SYSErr = 0x8000, | 249 | SYSErr = 0x8000, |
@@ -265,7 +297,13 @@ enum rtl_register_content { | |||
265 | TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ | 297 | TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ |
266 | 298 | ||
267 | /* Config1 register p.24 */ | 299 | /* Config1 register p.24 */ |
300 | LEDS1 = (1 << 7), | ||
301 | LEDS0 = (1 << 6), | ||
268 | MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */ | 302 | MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */ |
303 | Speed_down = (1 << 4), | ||
304 | MEMMAP = (1 << 3), | ||
305 | IOMAP = (1 << 2), | ||
306 | VPD = (1 << 1), | ||
269 | PMEnable = (1 << 0), /* Power Management Enable */ | 307 | PMEnable = (1 << 0), /* Power Management Enable */ |
270 | 308 | ||
271 | /* Config2 register p. 25 */ | 309 | /* Config2 register p. 25 */ |
@@ -275,6 +313,7 @@ enum rtl_register_content { | |||
275 | /* Config3 register p.25 */ | 313 | /* Config3 register p.25 */ |
276 | MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ | 314 | MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ |
277 | LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ | 315 | LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ |
316 | Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */ | ||
278 | 317 | ||
279 | /* Config5 register p.27 */ | 318 | /* Config5 register p.27 */ |
280 | BWF = (1 << 6), /* Accept Broadcast wakeup frame */ | 319 | BWF = (1 << 6), /* Accept Broadcast wakeup frame */ |
@@ -292,7 +331,16 @@ enum rtl_register_content { | |||
292 | TBINwComplete = 0x01000000, | 331 | TBINwComplete = 0x01000000, |
293 | 332 | ||
294 | /* CPlusCmd p.31 */ | 333 | /* CPlusCmd p.31 */ |
295 | PktCntrDisable = (1 << 7), // 8168 | 334 | EnableBist = (1 << 15), // 8168 8101 |
335 | Mac_dbgo_oe = (1 << 14), // 8168 8101 | ||
336 | Normal_mode = (1 << 13), // unused | ||
337 | Force_half_dup = (1 << 12), // 8168 8101 | ||
338 | Force_rxflow_en = (1 << 11), // 8168 8101 | ||
339 | Force_txflow_en = (1 << 10), // 8168 8101 | ||
340 | Cxpl_dbg_sel = (1 << 9), // 8168 8101 | ||
341 | ASF = (1 << 8), // 8168 8101 | ||
342 | PktCntrDisable = (1 << 7), // 8168 8101 | ||
343 | Mac_dbgo_sel = 0x001c, // 8168 | ||
296 | RxVlan = (1 << 6), | 344 | RxVlan = (1 << 6), |
297 | RxChkSum = (1 << 5), | 345 | RxChkSum = (1 << 5), |
298 | PCIDAC = (1 << 4), | 346 | PCIDAC = (1 << 4), |
@@ -370,8 +418,9 @@ struct ring_info { | |||
370 | }; | 418 | }; |
371 | 419 | ||
372 | enum features { | 420 | enum features { |
373 | RTL_FEATURE_WOL = (1 << 0), | 421 | RTL_FEATURE_WOL = (1 << 0), |
374 | RTL_FEATURE_MSI = (1 << 1), | 422 | RTL_FEATURE_MSI = (1 << 1), |
423 | RTL_FEATURE_GMII = (1 << 2), | ||
375 | }; | 424 | }; |
376 | 425 | ||
377 | struct rtl8169_private { | 426 | struct rtl8169_private { |
@@ -406,13 +455,16 @@ struct rtl8169_private { | |||
406 | struct vlan_group *vlgrp; | 455 | struct vlan_group *vlgrp; |
407 | #endif | 456 | #endif |
408 | int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); | 457 | int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); |
409 | void (*get_settings)(struct net_device *, struct ethtool_cmd *); | 458 | int (*get_settings)(struct net_device *, struct ethtool_cmd *); |
410 | void (*phy_reset_enable)(void __iomem *); | 459 | void (*phy_reset_enable)(void __iomem *); |
411 | void (*hw_start)(struct net_device *); | 460 | void (*hw_start)(struct net_device *); |
412 | unsigned int (*phy_reset_pending)(void __iomem *); | 461 | unsigned int (*phy_reset_pending)(void __iomem *); |
413 | unsigned int (*link_ok)(void __iomem *); | 462 | unsigned int (*link_ok)(void __iomem *); |
463 | int pcie_cap; | ||
414 | struct delayed_work task; | 464 | struct delayed_work task; |
415 | unsigned features; | 465 | unsigned features; |
466 | |||
467 | struct mii_if_info mii; | ||
416 | }; | 468 | }; |
417 | 469 | ||
418 | MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>"); | 470 | MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>"); |
@@ -482,6 +534,94 @@ static int mdio_read(void __iomem *ioaddr, int reg_addr) | |||
482 | return value; | 534 | return value; |
483 | } | 535 | } |
484 | 536 | ||
537 | static void mdio_patch(void __iomem *ioaddr, int reg_addr, int value) | ||
538 | { | ||
539 | mdio_write(ioaddr, reg_addr, mdio_read(ioaddr, reg_addr) | value); | ||
540 | } | ||
541 | |||
542 | static void rtl_mdio_write(struct net_device *dev, int phy_id, int location, | ||
543 | int val) | ||
544 | { | ||
545 | struct rtl8169_private *tp = netdev_priv(dev); | ||
546 | void __iomem *ioaddr = tp->mmio_addr; | ||
547 | |||
548 | mdio_write(ioaddr, location, val); | ||
549 | } | ||
550 | |||
551 | static int rtl_mdio_read(struct net_device *dev, int phy_id, int location) | ||
552 | { | ||
553 | struct rtl8169_private *tp = netdev_priv(dev); | ||
554 | void __iomem *ioaddr = tp->mmio_addr; | ||
555 | |||
556 | return mdio_read(ioaddr, location); | ||
557 | } | ||
558 | |||
559 | static void rtl_ephy_write(void __iomem *ioaddr, int reg_addr, int value) | ||
560 | { | ||
561 | unsigned int i; | ||
562 | |||
563 | RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) | | ||
564 | (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); | ||
565 | |||
566 | for (i = 0; i < 100; i++) { | ||
567 | if (!(RTL_R32(EPHYAR) & EPHYAR_FLAG)) | ||
568 | break; | ||
569 | udelay(10); | ||
570 | } | ||
571 | } | ||
572 | |||
573 | static u16 rtl_ephy_read(void __iomem *ioaddr, int reg_addr) | ||
574 | { | ||
575 | u16 value = 0xffff; | ||
576 | unsigned int i; | ||
577 | |||
578 | RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); | ||
579 | |||
580 | for (i = 0; i < 100; i++) { | ||
581 | if (RTL_R32(EPHYAR) & EPHYAR_FLAG) { | ||
582 | value = RTL_R32(EPHYAR) & EPHYAR_DATA_MASK; | ||
583 | break; | ||
584 | } | ||
585 | udelay(10); | ||
586 | } | ||
587 | |||
588 | return value; | ||
589 | } | ||
590 | |||
591 | static void rtl_csi_write(void __iomem *ioaddr, int addr, int value) | ||
592 | { | ||
593 | unsigned int i; | ||
594 | |||
595 | RTL_W32(CSIDR, value); | ||
596 | RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | | ||
597 | CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); | ||
598 | |||
599 | for (i = 0; i < 100; i++) { | ||
600 | if (!(RTL_R32(CSIAR) & CSIAR_FLAG)) | ||
601 | break; | ||
602 | udelay(10); | ||
603 | } | ||
604 | } | ||
605 | |||
606 | static u32 rtl_csi_read(void __iomem *ioaddr, int addr) | ||
607 | { | ||
608 | u32 value = ~0x00; | ||
609 | unsigned int i; | ||
610 | |||
611 | RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | | ||
612 | CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); | ||
613 | |||
614 | for (i = 0; i < 100; i++) { | ||
615 | if (RTL_R32(CSIAR) & CSIAR_FLAG) { | ||
616 | value = RTL_R32(CSIDR); | ||
617 | break; | ||
618 | } | ||
619 | udelay(10); | ||
620 | } | ||
621 | |||
622 | return value; | ||
623 | } | ||
624 | |||
485 | static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) | 625 | static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) |
486 | { | 626 | { |
487 | RTL_W16(IntrMask, 0x0000); | 627 | RTL_W16(IntrMask, 0x0000); |
@@ -705,8 +845,12 @@ static int rtl8169_set_speed_xmii(struct net_device *dev, | |||
705 | } | 845 | } |
706 | } | 846 | } |
707 | 847 | ||
708 | /* The 8100e/8101e do Fast Ethernet only. */ | 848 | /* The 8100e/8101e/8102e do Fast Ethernet only. */ |
709 | if ((tp->mac_version == RTL_GIGA_MAC_VER_13) || | 849 | if ((tp->mac_version == RTL_GIGA_MAC_VER_07) || |
850 | (tp->mac_version == RTL_GIGA_MAC_VER_08) || | ||
851 | (tp->mac_version == RTL_GIGA_MAC_VER_09) || | ||
852 | (tp->mac_version == RTL_GIGA_MAC_VER_10) || | ||
853 | (tp->mac_version == RTL_GIGA_MAC_VER_13) || | ||
710 | (tp->mac_version == RTL_GIGA_MAC_VER_14) || | 854 | (tp->mac_version == RTL_GIGA_MAC_VER_14) || |
711 | (tp->mac_version == RTL_GIGA_MAC_VER_15) || | 855 | (tp->mac_version == RTL_GIGA_MAC_VER_15) || |
712 | (tp->mac_version == RTL_GIGA_MAC_VER_16)) { | 856 | (tp->mac_version == RTL_GIGA_MAC_VER_16)) { |
@@ -850,7 +994,7 @@ static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, | |||
850 | 994 | ||
851 | #endif | 995 | #endif |
852 | 996 | ||
853 | static void rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) | 997 | static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) |
854 | { | 998 | { |
855 | struct rtl8169_private *tp = netdev_priv(dev); | 999 | struct rtl8169_private *tp = netdev_priv(dev); |
856 | void __iomem *ioaddr = tp->mmio_addr; | 1000 | void __iomem *ioaddr = tp->mmio_addr; |
@@ -867,65 +1011,29 @@ static void rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) | |||
867 | 1011 | ||
868 | cmd->speed = SPEED_1000; | 1012 | cmd->speed = SPEED_1000; |
869 | cmd->duplex = DUPLEX_FULL; /* Always set */ | 1013 | cmd->duplex = DUPLEX_FULL; /* Always set */ |
1014 | |||
1015 | return 0; | ||
870 | } | 1016 | } |
871 | 1017 | ||
872 | static void rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) | 1018 | static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) |
873 | { | 1019 | { |
874 | struct rtl8169_private *tp = netdev_priv(dev); | 1020 | struct rtl8169_private *tp = netdev_priv(dev); |
875 | void __iomem *ioaddr = tp->mmio_addr; | 1021 | |
876 | u8 status; | 1022 | return mii_ethtool_gset(&tp->mii, cmd); |
877 | |||
878 | cmd->supported = SUPPORTED_10baseT_Half | | ||
879 | SUPPORTED_10baseT_Full | | ||
880 | SUPPORTED_100baseT_Half | | ||
881 | SUPPORTED_100baseT_Full | | ||
882 | SUPPORTED_1000baseT_Full | | ||
883 | SUPPORTED_Autoneg | | ||
884 | SUPPORTED_TP; | ||
885 | |||
886 | cmd->autoneg = 1; | ||
887 | cmd->advertising = ADVERTISED_TP | ADVERTISED_Autoneg; | ||
888 | |||
889 | if (tp->phy_auto_nego_reg & ADVERTISE_10HALF) | ||
890 | cmd->advertising |= ADVERTISED_10baseT_Half; | ||
891 | if (tp->phy_auto_nego_reg & ADVERTISE_10FULL) | ||
892 | cmd->advertising |= ADVERTISED_10baseT_Full; | ||
893 | if (tp->phy_auto_nego_reg & ADVERTISE_100HALF) | ||
894 | cmd->advertising |= ADVERTISED_100baseT_Half; | ||
895 | if (tp->phy_auto_nego_reg & ADVERTISE_100FULL) | ||
896 | cmd->advertising |= ADVERTISED_100baseT_Full; | ||
897 | if (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL) | ||
898 | cmd->advertising |= ADVERTISED_1000baseT_Full; | ||
899 | |||
900 | status = RTL_R8(PHYstatus); | ||
901 | |||
902 | if (status & _1000bpsF) | ||
903 | cmd->speed = SPEED_1000; | ||
904 | else if (status & _100bps) | ||
905 | cmd->speed = SPEED_100; | ||
906 | else if (status & _10bps) | ||
907 | cmd->speed = SPEED_10; | ||
908 | |||
909 | if (status & TxFlowCtrl) | ||
910 | cmd->advertising |= ADVERTISED_Asym_Pause; | ||
911 | if (status & RxFlowCtrl) | ||
912 | cmd->advertising |= ADVERTISED_Pause; | ||
913 | |||
914 | cmd->duplex = ((status & _1000bpsF) || (status & FullDup)) ? | ||
915 | DUPLEX_FULL : DUPLEX_HALF; | ||
916 | } | 1023 | } |
917 | 1024 | ||
918 | static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | 1025 | static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) |
919 | { | 1026 | { |
920 | struct rtl8169_private *tp = netdev_priv(dev); | 1027 | struct rtl8169_private *tp = netdev_priv(dev); |
921 | unsigned long flags; | 1028 | unsigned long flags; |
1029 | int rc; | ||
922 | 1030 | ||
923 | spin_lock_irqsave(&tp->lock, flags); | 1031 | spin_lock_irqsave(&tp->lock, flags); |
924 | 1032 | ||
925 | tp->get_settings(dev, cmd); | 1033 | rc = tp->get_settings(dev, cmd); |
926 | 1034 | ||
927 | spin_unlock_irqrestore(&tp->lock, flags); | 1035 | spin_unlock_irqrestore(&tp->lock, flags); |
928 | return 0; | 1036 | return rc; |
929 | } | 1037 | } |
930 | 1038 | ||
931 | static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, | 1039 | static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, |
@@ -1116,8 +1224,17 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, | |||
1116 | { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 }, | 1224 | { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 }, |
1117 | 1225 | ||
1118 | /* 8101 family. */ | 1226 | /* 8101 family. */ |
1227 | { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 }, | ||
1228 | { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 }, | ||
1229 | { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 }, | ||
1230 | { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 }, | ||
1231 | { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 }, | ||
1232 | { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 }, | ||
1119 | { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 }, | 1233 | { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 }, |
1234 | { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 }, | ||
1120 | { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 }, | 1235 | { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 }, |
1236 | { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 }, | ||
1237 | { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 }, | ||
1121 | { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 }, | 1238 | { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 }, |
1122 | /* FIXME: where did these entries come from ? -- FR */ | 1239 | /* FIXME: where did these entries come from ? -- FR */ |
1123 | { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 }, | 1240 | { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 }, |
@@ -1279,6 +1396,22 @@ static void rtl8168cx_hw_phy_config(void __iomem *ioaddr) | |||
1279 | rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); | 1396 | rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); |
1280 | } | 1397 | } |
1281 | 1398 | ||
1399 | static void rtl8102e_hw_phy_config(void __iomem *ioaddr) | ||
1400 | { | ||
1401 | struct phy_reg phy_reg_init[] = { | ||
1402 | { 0x1f, 0x0003 }, | ||
1403 | { 0x08, 0x441d }, | ||
1404 | { 0x01, 0x9100 }, | ||
1405 | { 0x1f, 0x0000 } | ||
1406 | }; | ||
1407 | |||
1408 | mdio_write(ioaddr, 0x1f, 0x0000); | ||
1409 | mdio_patch(ioaddr, 0x11, 1 << 12); | ||
1410 | mdio_patch(ioaddr, 0x19, 1 << 13); | ||
1411 | |||
1412 | rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); | ||
1413 | } | ||
1414 | |||
1282 | static void rtl_hw_phy_config(struct net_device *dev) | 1415 | static void rtl_hw_phy_config(struct net_device *dev) |
1283 | { | 1416 | { |
1284 | struct rtl8169_private *tp = netdev_priv(dev); | 1417 | struct rtl8169_private *tp = netdev_priv(dev); |
@@ -1296,6 +1429,11 @@ static void rtl_hw_phy_config(struct net_device *dev) | |||
1296 | case RTL_GIGA_MAC_VER_04: | 1429 | case RTL_GIGA_MAC_VER_04: |
1297 | rtl8169sb_hw_phy_config(ioaddr); | 1430 | rtl8169sb_hw_phy_config(ioaddr); |
1298 | break; | 1431 | break; |
1432 | case RTL_GIGA_MAC_VER_07: | ||
1433 | case RTL_GIGA_MAC_VER_08: | ||
1434 | case RTL_GIGA_MAC_VER_09: | ||
1435 | rtl8102e_hw_phy_config(ioaddr); | ||
1436 | break; | ||
1299 | case RTL_GIGA_MAC_VER_18: | 1437 | case RTL_GIGA_MAC_VER_18: |
1300 | rtl8168cp_hw_phy_config(ioaddr); | 1438 | rtl8168cp_hw_phy_config(ioaddr); |
1301 | break; | 1439 | break; |
@@ -1513,7 +1651,7 @@ static const struct rtl_cfg_info { | |||
1513 | unsigned int align; | 1651 | unsigned int align; |
1514 | u16 intr_event; | 1652 | u16 intr_event; |
1515 | u16 napi_event; | 1653 | u16 napi_event; |
1516 | unsigned msi; | 1654 | unsigned features; |
1517 | } rtl_cfg_infos [] = { | 1655 | } rtl_cfg_infos [] = { |
1518 | [RTL_CFG_0] = { | 1656 | [RTL_CFG_0] = { |
1519 | .hw_start = rtl_hw_start_8169, | 1657 | .hw_start = rtl_hw_start_8169, |
@@ -1522,7 +1660,7 @@ static const struct rtl_cfg_info { | |||
1522 | .intr_event = SYSErr | LinkChg | RxOverflow | | 1660 | .intr_event = SYSErr | LinkChg | RxOverflow | |
1523 | RxFIFOOver | TxErr | TxOK | RxOK | RxErr, | 1661 | RxFIFOOver | TxErr | TxOK | RxOK | RxErr, |
1524 | .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, | 1662 | .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, |
1525 | .msi = 0 | 1663 | .features = RTL_FEATURE_GMII |
1526 | }, | 1664 | }, |
1527 | [RTL_CFG_1] = { | 1665 | [RTL_CFG_1] = { |
1528 | .hw_start = rtl_hw_start_8168, | 1666 | .hw_start = rtl_hw_start_8168, |
@@ -1531,7 +1669,7 @@ static const struct rtl_cfg_info { | |||
1531 | .intr_event = SYSErr | LinkChg | RxOverflow | | 1669 | .intr_event = SYSErr | LinkChg | RxOverflow | |
1532 | TxErr | TxOK | RxOK | RxErr, | 1670 | TxErr | TxOK | RxOK | RxErr, |
1533 | .napi_event = TxErr | TxOK | RxOK | RxOverflow, | 1671 | .napi_event = TxErr | TxOK | RxOK | RxOverflow, |
1534 | .msi = RTL_FEATURE_MSI | 1672 | .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI |
1535 | }, | 1673 | }, |
1536 | [RTL_CFG_2] = { | 1674 | [RTL_CFG_2] = { |
1537 | .hw_start = rtl_hw_start_8101, | 1675 | .hw_start = rtl_hw_start_8101, |
@@ -1540,7 +1678,7 @@ static const struct rtl_cfg_info { | |||
1540 | .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | | 1678 | .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | |
1541 | RxFIFOOver | TxErr | TxOK | RxOK | RxErr, | 1679 | RxFIFOOver | TxErr | TxOK | RxOK | RxErr, |
1542 | .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, | 1680 | .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, |
1543 | .msi = RTL_FEATURE_MSI | 1681 | .features = RTL_FEATURE_MSI |
1544 | } | 1682 | } |
1545 | }; | 1683 | }; |
1546 | 1684 | ||
@@ -1552,7 +1690,7 @@ static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr, | |||
1552 | u8 cfg2; | 1690 | u8 cfg2; |
1553 | 1691 | ||
1554 | cfg2 = RTL_R8(Config2) & ~MSIEnable; | 1692 | cfg2 = RTL_R8(Config2) & ~MSIEnable; |
1555 | if (cfg->msi) { | 1693 | if (cfg->features & RTL_FEATURE_MSI) { |
1556 | if (pci_enable_msi(pdev)) { | 1694 | if (pci_enable_msi(pdev)) { |
1557 | dev_info(&pdev->dev, "no MSI. Back to INTx.\n"); | 1695 | dev_info(&pdev->dev, "no MSI. Back to INTx.\n"); |
1558 | } else { | 1696 | } else { |
@@ -1578,6 +1716,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1578 | const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; | 1716 | const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; |
1579 | const unsigned int region = cfg->region; | 1717 | const unsigned int region = cfg->region; |
1580 | struct rtl8169_private *tp; | 1718 | struct rtl8169_private *tp; |
1719 | struct mii_if_info *mii; | ||
1581 | struct net_device *dev; | 1720 | struct net_device *dev; |
1582 | void __iomem *ioaddr; | 1721 | void __iomem *ioaddr; |
1583 | unsigned int i; | 1722 | unsigned int i; |
@@ -1602,6 +1741,14 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1602 | tp->pci_dev = pdev; | 1741 | tp->pci_dev = pdev; |
1603 | tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); | 1742 | tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); |
1604 | 1743 | ||
1744 | mii = &tp->mii; | ||
1745 | mii->dev = dev; | ||
1746 | mii->mdio_read = rtl_mdio_read; | ||
1747 | mii->mdio_write = rtl_mdio_write; | ||
1748 | mii->phy_id_mask = 0x1f; | ||
1749 | mii->reg_num_mask = 0x1f; | ||
1750 | mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII); | ||
1751 | |||
1605 | /* enable device (incl. PCI PM wakeup and hotplug setup) */ | 1752 | /* enable device (incl. PCI PM wakeup and hotplug setup) */ |
1606 | rc = pci_enable_device(pdev); | 1753 | rc = pci_enable_device(pdev); |
1607 | if (rc < 0) { | 1754 | if (rc < 0) { |
@@ -1670,6 +1817,10 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1670 | goto err_out_free_res_4; | 1817 | goto err_out_free_res_4; |
1671 | } | 1818 | } |
1672 | 1819 | ||
1820 | tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); | ||
1821 | if (!tp->pcie_cap && netif_msg_probe(tp)) | ||
1822 | dev_info(&pdev->dev, "no PCI Express capability\n"); | ||
1823 | |||
1673 | /* Unneeded ? Don't mess with Mrs. Murphy. */ | 1824 | /* Unneeded ? Don't mess with Mrs. Murphy. */ |
1674 | rtl8169_irq_mask_and_ack(ioaddr); | 1825 | rtl8169_irq_mask_and_ack(ioaddr); |
1675 | 1826 | ||
@@ -2061,12 +2212,51 @@ static void rtl_hw_start_8169(struct net_device *dev) | |||
2061 | RTL_W16(IntrMask, tp->intr_event); | 2212 | RTL_W16(IntrMask, tp->intr_event); |
2062 | } | 2213 | } |
2063 | 2214 | ||
2215 | static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) | ||
2216 | { | ||
2217 | struct net_device *dev = pci_get_drvdata(pdev); | ||
2218 | struct rtl8169_private *tp = netdev_priv(dev); | ||
2219 | int cap = tp->pcie_cap; | ||
2220 | |||
2221 | if (cap) { | ||
2222 | u16 ctl; | ||
2223 | |||
2224 | pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); | ||
2225 | ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force; | ||
2226 | pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); | ||
2227 | } | ||
2228 | } | ||
2229 | |||
2230 | static void rtl_csi_access_enable(void __iomem *ioaddr) | ||
2231 | { | ||
2232 | u32 csi; | ||
2233 | |||
2234 | csi = rtl_csi_read(ioaddr, 0x070c) & 0x00ffffff; | ||
2235 | rtl_csi_write(ioaddr, 0x070c, csi | 0x27000000); | ||
2236 | } | ||
2237 | |||
2238 | struct ephy_info { | ||
2239 | unsigned int offset; | ||
2240 | u16 mask; | ||
2241 | u16 bits; | ||
2242 | }; | ||
2243 | |||
2244 | static void rtl_ephy_init(void __iomem *ioaddr, struct ephy_info *e, int len) | ||
2245 | { | ||
2246 | u16 w; | ||
2247 | |||
2248 | while (len-- > 0) { | ||
2249 | w = (rtl_ephy_read(ioaddr, e->offset) & ~e->mask) | e->bits; | ||
2250 | rtl_ephy_write(ioaddr, e->offset, w); | ||
2251 | e++; | ||
2252 | } | ||
2253 | } | ||
2254 | |||
2064 | static void rtl_hw_start_8168(struct net_device *dev) | 2255 | static void rtl_hw_start_8168(struct net_device *dev) |
2065 | { | 2256 | { |
2066 | struct rtl8169_private *tp = netdev_priv(dev); | 2257 | struct rtl8169_private *tp = netdev_priv(dev); |
2067 | void __iomem *ioaddr = tp->mmio_addr; | 2258 | void __iomem *ioaddr = tp->mmio_addr; |
2068 | struct pci_dev *pdev = tp->pci_dev; | 2259 | struct pci_dev *pdev = tp->pci_dev; |
2069 | u8 ctl; | ||
2070 | 2260 | ||
2071 | RTL_W8(Cfg9346, Cfg9346_Unlock); | 2261 | RTL_W8(Cfg9346, Cfg9346_Unlock); |
2072 | 2262 | ||
@@ -2080,10 +2270,7 @@ static void rtl_hw_start_8168(struct net_device *dev) | |||
2080 | 2270 | ||
2081 | RTL_W16(CPlusCmd, tp->cp_cmd); | 2271 | RTL_W16(CPlusCmd, tp->cp_cmd); |
2082 | 2272 | ||
2083 | /* Tx performance tweak. */ | 2273 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); |
2084 | pci_read_config_byte(pdev, 0x69, &ctl); | ||
2085 | ctl = (ctl & ~0x70) | 0x50; | ||
2086 | pci_write_config_byte(pdev, 0x69, ctl); | ||
2087 | 2274 | ||
2088 | RTL_W16(IntrMitigate, 0x5151); | 2275 | RTL_W16(IntrMitigate, 0x5151); |
2089 | 2276 | ||
@@ -2110,6 +2297,70 @@ static void rtl_hw_start_8168(struct net_device *dev) | |||
2110 | RTL_W16(IntrMask, tp->intr_event); | 2297 | RTL_W16(IntrMask, tp->intr_event); |
2111 | } | 2298 | } |
2112 | 2299 | ||
2300 | #define R810X_CPCMD_QUIRK_MASK (\ | ||
2301 | EnableBist | \ | ||
2302 | Mac_dbgo_oe | \ | ||
2303 | Force_half_dup | \ | ||
2304 | Force_half_dup | \ | ||
2305 | Force_txflow_en | \ | ||
2306 | Cxpl_dbg_sel | \ | ||
2307 | ASF | \ | ||
2308 | PktCntrDisable | \ | ||
2309 | PCIDAC | \ | ||
2310 | PCIMulRW) | ||
2311 | |||
2312 | static void rtl_hw_start_8102e_1(void __iomem *ioaddr, struct pci_dev *pdev) | ||
2313 | { | ||
2314 | static struct ephy_info e_info_8102e_1[] = { | ||
2315 | { 0x01, 0, 0x6e65 }, | ||
2316 | { 0x02, 0, 0x091f }, | ||
2317 | { 0x03, 0, 0xc2f9 }, | ||
2318 | { 0x06, 0, 0xafb5 }, | ||
2319 | { 0x07, 0, 0x0e00 }, | ||
2320 | { 0x19, 0, 0xec80 }, | ||
2321 | { 0x01, 0, 0x2e65 }, | ||
2322 | { 0x01, 0, 0x6e65 } | ||
2323 | }; | ||
2324 | u8 cfg1; | ||
2325 | |||
2326 | rtl_csi_access_enable(ioaddr); | ||
2327 | |||
2328 | RTL_W8(DBG_REG, FIX_NAK_1); | ||
2329 | |||
2330 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); | ||
2331 | |||
2332 | RTL_W8(Config1, | ||
2333 | LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable); | ||
2334 | RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); | ||
2335 | |||
2336 | cfg1 = RTL_R8(Config1); | ||
2337 | if ((cfg1 & LEDS0) && (cfg1 & LEDS1)) | ||
2338 | RTL_W8(Config1, cfg1 & ~LEDS0); | ||
2339 | |||
2340 | RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); | ||
2341 | |||
2342 | rtl_ephy_init(ioaddr, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1)); | ||
2343 | } | ||
2344 | |||
2345 | static void rtl_hw_start_8102e_2(void __iomem *ioaddr, struct pci_dev *pdev) | ||
2346 | { | ||
2347 | rtl_csi_access_enable(ioaddr); | ||
2348 | |||
2349 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); | ||
2350 | |||
2351 | RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable); | ||
2352 | RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); | ||
2353 | |||
2354 | RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R810X_CPCMD_QUIRK_MASK); | ||
2355 | } | ||
2356 | |||
2357 | static void rtl_hw_start_8102e_3(void __iomem *ioaddr, struct pci_dev *pdev) | ||
2358 | { | ||
2359 | rtl_hw_start_8102e_2(ioaddr, pdev); | ||
2360 | |||
2361 | rtl_ephy_write(ioaddr, 0x03, 0xc2f9); | ||
2362 | } | ||
2363 | |||
2113 | static void rtl_hw_start_8101(struct net_device *dev) | 2364 | static void rtl_hw_start_8101(struct net_device *dev) |
2114 | { | 2365 | { |
2115 | struct rtl8169_private *tp = netdev_priv(dev); | 2366 | struct rtl8169_private *tp = netdev_priv(dev); |
@@ -2118,8 +2369,26 @@ static void rtl_hw_start_8101(struct net_device *dev) | |||
2118 | 2369 | ||
2119 | if ((tp->mac_version == RTL_GIGA_MAC_VER_13) || | 2370 | if ((tp->mac_version == RTL_GIGA_MAC_VER_13) || |
2120 | (tp->mac_version == RTL_GIGA_MAC_VER_16)) { | 2371 | (tp->mac_version == RTL_GIGA_MAC_VER_16)) { |
2121 | pci_write_config_word(pdev, 0x68, 0x00); | 2372 | int cap = tp->pcie_cap; |
2122 | pci_write_config_word(pdev, 0x69, 0x08); | 2373 | |
2374 | if (cap) { | ||
2375 | pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, | ||
2376 | PCI_EXP_DEVCTL_NOSNOOP_EN); | ||
2377 | } | ||
2378 | } | ||
2379 | |||
2380 | switch (tp->mac_version) { | ||
2381 | case RTL_GIGA_MAC_VER_07: | ||
2382 | rtl_hw_start_8102e_1(ioaddr, pdev); | ||
2383 | break; | ||
2384 | |||
2385 | case RTL_GIGA_MAC_VER_08: | ||
2386 | rtl_hw_start_8102e_3(ioaddr, pdev); | ||
2387 | break; | ||
2388 | |||
2389 | case RTL_GIGA_MAC_VER_09: | ||
2390 | rtl_hw_start_8102e_2(ioaddr, pdev); | ||
2391 | break; | ||
2123 | } | 2392 | } |
2124 | 2393 | ||
2125 | RTL_W8(Cfg9346, Cfg9346_Unlock); | 2394 | RTL_W8(Cfg9346, Cfg9346_Unlock); |