Commit 2a69bf42 authored by Jeff Garzik's avatar Jeff Garzik

Merge tag 'r8169-20060912-00' of git://electric-eye.fr.zoreil.com/home/romieu/linux-2.6 into tmp

parents cb930205 b39fe41f
...@@ -6,26 +6,26 @@ ...@@ -6,26 +6,26 @@
History: History:
Feb 4 2002 - created initially by ShuChen <shuchen@realtek.com.tw>. Feb 4 2002 - created initially by ShuChen <shuchen@realtek.com.tw>.
May 20 2002 - Add link status force-mode and TBI mode support. May 20 2002 - Add link status force-mode and TBI mode support.
2004 - Massive updates. See kernel SCM system for details. 2004 - Massive updates. See kernel SCM system for details.
========================================================================= =========================================================================
1. [DEPRECATED: use ethtool instead] The media can be forced in 5 modes. 1. [DEPRECATED: use ethtool instead] The media can be forced in 5 modes.
Command: 'insmod r8169 media = SET_MEDIA' Command: 'insmod r8169 media = SET_MEDIA'
Ex: 'insmod r8169 media = 0x04' will force PHY to operate in 100Mpbs Half-duplex. Ex: 'insmod r8169 media = 0x04' will force PHY to operate in 100Mpbs Half-duplex.
SET_MEDIA can be: SET_MEDIA can be:
_10_Half = 0x01 _10_Half = 0x01
_10_Full = 0x02 _10_Full = 0x02
_100_Half = 0x04 _100_Half = 0x04
_100_Full = 0x08 _100_Full = 0x08
_1000_Full = 0x10 _1000_Full = 0x10
2. Support TBI mode. 2. Support TBI mode.
========================================================================= =========================================================================
VERSION 1.1 <2002/10/4> VERSION 1.1 <2002/10/4>
The bit4:0 of MII register 4 is called "selector field", and have to be The bit4:0 of MII register 4 is called "selector field", and have to be
00001b to indicate support of IEEE std 802.3 during NWay process of 00001b to indicate support of IEEE std 802.3 during NWay process of
exchanging Link Code Word (FLP). exchanging Link Code Word (FLP).
VERSION 1.2 <2002/11/30> VERSION 1.2 <2002/11/30>
...@@ -81,10 +81,10 @@ VERSION 2.2LK <2005/01/25> ...@@ -81,10 +81,10 @@ VERSION 2.2LK <2005/01/25>
#ifdef RTL8169_DEBUG #ifdef RTL8169_DEBUG
#define assert(expr) \ #define assert(expr) \
if(!(expr)) { \ if (!(expr)) { \
printk( "Assertion failed! %s,%s,%s,line=%d\n", \ printk( "Assertion failed! %s,%s,%s,line=%d\n", \
#expr,__FILE__,__FUNCTION__,__LINE__); \ #expr,__FILE__,__FUNCTION__,__LINE__); \
} }
#define dprintk(fmt, args...) do { printk(PFX fmt, ## args); } while (0) #define dprintk(fmt, args...) do { printk(PFX fmt, ## args); } while (0)
#else #else
#define assert(expr) do {} while (0) #define assert(expr) do {} while (0)
...@@ -150,11 +150,16 @@ static const int multicast_filter_limit = 32; ...@@ -150,11 +150,16 @@ static const int multicast_filter_limit = 32;
#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) #define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg)))
enum mac_version { enum mac_version {
RTL_GIGA_MAC_VER_B = 0x00, RTL_GIGA_MAC_VER_01 = 0x00,
/* RTL_GIGA_MAC_VER_C = 0x03, */ RTL_GIGA_MAC_VER_02 = 0x01,
RTL_GIGA_MAC_VER_D = 0x01, RTL_GIGA_MAC_VER_03 = 0x02,
RTL_GIGA_MAC_VER_E = 0x02, RTL_GIGA_MAC_VER_04 = 0x03,
RTL_GIGA_MAC_VER_X = 0x04 /* Greater than RTL_GIGA_MAC_VER_E */ RTL_GIGA_MAC_VER_05 = 0x04,
RTL_GIGA_MAC_VER_11 = 0x0b,
RTL_GIGA_MAC_VER_12 = 0x0c,
RTL_GIGA_MAC_VER_13 = 0x0d,
RTL_GIGA_MAC_VER_14 = 0x0e,
RTL_GIGA_MAC_VER_15 = 0x0f
}; };
enum phy_version { enum phy_version {
...@@ -166,7 +171,6 @@ enum phy_version { ...@@ -166,7 +171,6 @@ enum phy_version {
RTL_GIGA_PHY_VER_H = 0x08, /* PHY Reg 0x03 bit0-3 == 0x0003 */ RTL_GIGA_PHY_VER_H = 0x08, /* PHY Reg 0x03 bit0-3 == 0x0003 */
}; };
#define _R(NAME,MAC,MASK) \ #define _R(NAME,MAC,MASK) \
{ .name = NAME, .mac_version = MAC, .RxConfigMask = MASK } { .name = NAME, .mac_version = MAC, .RxConfigMask = MASK }
...@@ -175,19 +179,44 @@ static const struct { ...@@ -175,19 +179,44 @@ static const struct {
u8 mac_version; u8 mac_version;
u32 RxConfigMask; /* Clears the bits supported by this chip */ u32 RxConfigMask; /* Clears the bits supported by this chip */
} rtl_chip_info[] = { } rtl_chip_info[] = {
_R("RTL8169", RTL_GIGA_MAC_VER_B, 0xff7e1880), _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880),
_R("RTL8169s/8110s", RTL_GIGA_MAC_VER_D, 0xff7e1880), _R("RTL8169s/8110s", RTL_GIGA_MAC_VER_02, 0xff7e1880),
_R("RTL8169s/8110s", RTL_GIGA_MAC_VER_E, 0xff7e1880), _R("RTL8169s/8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880),
_R("RTL8169s/8110s", RTL_GIGA_MAC_VER_X, 0xff7e1880), _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880),
_R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880),
_R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E
_R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E
_R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139
_R("RTL8100e", RTL_GIGA_MAC_VER_14, 0xff7e1880), // PCI-E 8139
_R("RTL8100e", RTL_GIGA_MAC_VER_15, 0xff7e1880) // PCI-E 8139
}; };
#undef _R #undef _R
enum cfg_version {
RTL_CFG_0 = 0x00,
RTL_CFG_1,
RTL_CFG_2
};
static const struct {
unsigned int region;
unsigned int align;
} rtl_cfg_info[] = {
[RTL_CFG_0] = { 1, NET_IP_ALIGN },
[RTL_CFG_1] = { 2, NET_IP_ALIGN },
[RTL_CFG_2] = { 2, 8 }
};
static struct pci_device_id rtl8169_pci_tbl[] = { static struct pci_device_id rtl8169_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 },
{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_1 },
{ PCI_DEVICE(0x16ec, 0x0116), }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_2 },
{ PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0024, }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 },
{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 },
{ PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 },
{ PCI_VENDOR_ID_LINKSYS, 0x1032,
PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 },
{0,}, {0,},
}; };
...@@ -257,10 +286,11 @@ enum RTL8169_register_content { ...@@ -257,10 +286,11 @@ enum RTL8169_register_content {
RxOK = 0x01, RxOK = 0x01,
/* RxStatusDesc */ /* RxStatusDesc */
RxRES = 0x00200000, RxFOVF = (1 << 23),
RxCRC = 0x00080000, RxRWT = (1 << 22),
RxRUNT = 0x00100000, RxRES = (1 << 21),
RxRWT = 0x00400000, RxRUNT = (1 << 20),
RxCRC = (1 << 19),
/* ChipCmdBits */ /* ChipCmdBits */
CmdReset = 0x10, CmdReset = 0x10,
...@@ -326,30 +356,6 @@ enum RTL8169_register_content { ...@@ -326,30 +356,6 @@ enum RTL8169_register_content {
LinkStatus = 0x02, LinkStatus = 0x02,
FullDup = 0x01, FullDup = 0x01,
/* GIGABIT_PHY_registers */
PHY_CTRL_REG = 0,
PHY_STAT_REG = 1,
PHY_AUTO_NEGO_REG = 4,
PHY_1000_CTRL_REG = 9,
/* GIGABIT_PHY_REG_BIT */
PHY_Restart_Auto_Nego = 0x0200,
PHY_Enable_Auto_Nego = 0x1000,
/* PHY_STAT_REG = 1 */
PHY_Auto_Neco_Comp = 0x0020,
/* PHY_AUTO_NEGO_REG = 4 */
PHY_Cap_10_Half = 0x0020,
PHY_Cap_10_Full = 0x0040,
PHY_Cap_100_Half = 0x0080,
PHY_Cap_100_Full = 0x0100,
/* PHY_1000_CTRL_REG = 9 */
PHY_Cap_1000_Full = 0x0200,
PHY_Cap_Null = 0x0,
/* _MediaType */ /* _MediaType */
_10_Half = 0x01, _10_Half = 0x01,
_10_Full = 0x02, _10_Full = 0x02,
...@@ -433,6 +439,7 @@ struct rtl8169_private { ...@@ -433,6 +439,7 @@ struct rtl8169_private {
dma_addr_t RxPhyAddr; dma_addr_t RxPhyAddr;
struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */
struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */
unsigned align;
unsigned rx_buf_sz; unsigned rx_buf_sz;
struct timer_list timer; struct timer_list timer;
u16 cp_cmd; u16 cp_cmd;
...@@ -488,12 +495,7 @@ static const u16 rtl8169_intr_mask = ...@@ -488,12 +495,7 @@ static const u16 rtl8169_intr_mask =
static const u16 rtl8169_napi_event = static const u16 rtl8169_napi_event =
RxOK | RxOverflow | RxFIFOOver | TxOK | TxErr; RxOK | RxOverflow | RxFIFOOver | TxOK | TxErr;
static const unsigned int rtl8169_rx_config = static const unsigned int rtl8169_rx_config =
(RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift);
#define PHY_Cap_10_Half_Or_Less PHY_Cap_10_Half
#define PHY_Cap_10_Full_Or_Less PHY_Cap_10_Full | PHY_Cap_10_Half_Or_Less
#define PHY_Cap_100_Half_Or_Less PHY_Cap_100_Half | PHY_Cap_10_Full_Or_Less
#define PHY_Cap_100_Full_Or_Less PHY_Cap_100_Full | PHY_Cap_100_Half_Or_Less
static void mdio_write(void __iomem *ioaddr, int RegAddr, int value) static void mdio_write(void __iomem *ioaddr, int RegAddr, int value)
{ {
...@@ -503,7 +505,7 @@ static void mdio_write(void __iomem *ioaddr, int RegAddr, int value) ...@@ -503,7 +505,7 @@ static void mdio_write(void __iomem *ioaddr, int RegAddr, int value)
for (i = 20; i > 0; i--) { for (i = 20; i > 0; i--) {
/* Check if the RTL8169 has completed writing to the specified MII register */ /* Check if the RTL8169 has completed writing to the specified MII register */
if (!(RTL_R32(PHYAR) & 0x80000000)) if (!(RTL_R32(PHYAR) & 0x80000000))
break; break;
udelay(25); udelay(25);
} }
...@@ -547,7 +549,7 @@ static unsigned int rtl8169_tbi_reset_pending(void __iomem *ioaddr) ...@@ -547,7 +549,7 @@ static unsigned int rtl8169_tbi_reset_pending(void __iomem *ioaddr)
static unsigned int rtl8169_xmii_reset_pending(void __iomem *ioaddr) static unsigned int rtl8169_xmii_reset_pending(void __iomem *ioaddr)
{ {
return mdio_read(ioaddr, 0) & 0x8000; return mdio_read(ioaddr, MII_BMCR) & BMCR_RESET;
} }
static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr) static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr)
...@@ -569,8 +571,8 @@ static void rtl8169_xmii_reset_enable(void __iomem *ioaddr) ...@@ -569,8 +571,8 @@ static void rtl8169_xmii_reset_enable(void __iomem *ioaddr)
{ {
unsigned int val; unsigned int val;
val = (mdio_read(ioaddr, PHY_CTRL_REG) | 0x8000) & 0xffff; val = (mdio_read(ioaddr, MII_BMCR) | BMCR_RESET) & 0xffff;
mdio_write(ioaddr, PHY_CTRL_REG, val); mdio_write(ioaddr, MII_BMCR, val);
} }
static void rtl8169_check_link_status(struct net_device *dev, static void rtl8169_check_link_status(struct net_device *dev,
...@@ -608,7 +610,7 @@ static void rtl8169_link_option(int idx, u8 *autoneg, u16 *speed, u8 *duplex) ...@@ -608,7 +610,7 @@ static void rtl8169_link_option(int idx, u8 *autoneg, u16 *speed, u8 *duplex)
{ SPEED_1000, DUPLEX_FULL, AUTONEG_ENABLE, 0xff } { SPEED_1000, DUPLEX_FULL, AUTONEG_ENABLE, 0xff }
}, *p; }, *p;
unsigned char option; unsigned char option;
option = ((idx < MAX_UNITS) && (idx >= 0)) ? media[idx] : 0xff; option = ((idx < MAX_UNITS) && (idx >= 0)) ? media[idx] : 0xff;
if ((option != 0xff) && !idx && netif_msg_drv(&debug)) if ((option != 0xff) && !idx && netif_msg_drv(&debug))
...@@ -650,9 +652,9 @@ static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) ...@@ -650,9 +652,9 @@ static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
if (options & UWF) if (options & UWF)
wol->wolopts |= WAKE_UCAST; wol->wolopts |= WAKE_UCAST;
if (options & BWF) if (options & BWF)
wol->wolopts |= WAKE_BCAST; wol->wolopts |= WAKE_BCAST;
if (options & MWF) if (options & MWF)
wol->wolopts |= WAKE_MCAST; wol->wolopts |= WAKE_MCAST;
out_unlock: out_unlock:
spin_unlock_irq(&tp->lock); spin_unlock_irq(&tp->lock);
...@@ -745,38 +747,57 @@ static int rtl8169_set_speed_xmii(struct net_device *dev, ...@@ -745,38 +747,57 @@ static int rtl8169_set_speed_xmii(struct net_device *dev,
void __iomem *ioaddr = tp->mmio_addr; void __iomem *ioaddr = tp->mmio_addr;
int auto_nego, giga_ctrl; int auto_nego, giga_ctrl;
auto_nego = mdio_read(ioaddr, PHY_AUTO_NEGO_REG); auto_nego = mdio_read(ioaddr, MII_ADVERTISE);
auto_nego &= ~(PHY_Cap_10_Half | PHY_Cap_10_Full | auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL |
PHY_Cap_100_Half | PHY_Cap_100_Full); ADVERTISE_100HALF | ADVERTISE_100FULL);
giga_ctrl = mdio_read(ioaddr, PHY_1000_CTRL_REG); giga_ctrl = mdio_read(ioaddr, MII_CTRL1000);
giga_ctrl &= ~(PHY_Cap_1000_Full | PHY_Cap_Null); giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
if (autoneg == AUTONEG_ENABLE) { if (autoneg == AUTONEG_ENABLE) {
auto_nego |= (PHY_Cap_10_Half | PHY_Cap_10_Full | auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL |
PHY_Cap_100_Half | PHY_Cap_100_Full); ADVERTISE_100HALF | ADVERTISE_100FULL);
giga_ctrl |= PHY_Cap_1000_Full; giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;
} else { } else {
if (speed == SPEED_10) if (speed == SPEED_10)
auto_nego |= PHY_Cap_10_Half | PHY_Cap_10_Full; auto_nego |= ADVERTISE_10HALF | ADVERTISE_10FULL;
else if (speed == SPEED_100) else if (speed == SPEED_100)
auto_nego |= PHY_Cap_100_Half | PHY_Cap_100_Full; auto_nego |= ADVERTISE_100HALF | ADVERTISE_100FULL;
else if (speed == SPEED_1000) else if (speed == SPEED_1000)
giga_ctrl |= PHY_Cap_1000_Full; giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;
if (duplex == DUPLEX_HALF) if (duplex == DUPLEX_HALF)
auto_nego &= ~(PHY_Cap_10_Full | PHY_Cap_100_Full); auto_nego &= ~(ADVERTISE_10FULL | ADVERTISE_100FULL);
if (duplex == DUPLEX_FULL) if (duplex == DUPLEX_FULL)
auto_nego &= ~(PHY_Cap_10_Half | PHY_Cap_100_Half); auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_100HALF);
/* This tweak comes straight from Realtek's driver. */
if ((speed == SPEED_100) && (duplex == DUPLEX_HALF) &&
(tp->mac_version == RTL_GIGA_MAC_VER_13)) {
auto_nego = ADVERTISE_100HALF | ADVERTISE_CSMA;
}
}
/* The 8100e/8101e do Fast Ethernet only. */
if ((tp->mac_version == RTL_GIGA_MAC_VER_13) ||
(tp->mac_version == RTL_GIGA_MAC_VER_14) ||
(tp->mac_version == RTL_GIGA_MAC_VER_15)) {
if ((giga_ctrl & (ADVERTISE_1000FULL | ADVERTISE_1000HALF)) &&
netif_msg_link(tp)) {
printk(KERN_INFO "%s: PHY does not support 1000Mbps.\n",
dev->name);
}
giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
} }
auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
tp->phy_auto_nego_reg = auto_nego; tp->phy_auto_nego_reg = auto_nego;
tp->phy_1000_ctrl_reg = giga_ctrl; tp->phy_1000_ctrl_reg = giga_ctrl;
mdio_write(ioaddr, PHY_AUTO_NEGO_REG, auto_nego); mdio_write(ioaddr, MII_ADVERTISE, auto_nego);
mdio_write(ioaddr, PHY_1000_CTRL_REG, giga_ctrl); mdio_write(ioaddr, MII_CTRL1000, giga_ctrl);
mdio_write(ioaddr, PHY_CTRL_REG, PHY_Enable_Auto_Nego | mdio_write(ioaddr, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART);
PHY_Restart_Auto_Nego);
return 0; return 0;
} }
...@@ -788,7 +809,7 @@ static int rtl8169_set_speed(struct net_device *dev, ...@@ -788,7 +809,7 @@ static int rtl8169_set_speed(struct net_device *dev,
ret = tp->set_speed(dev, autoneg, speed, duplex); ret = tp->set_speed(dev, autoneg, speed, duplex);
if (netif_running(dev) && (tp->phy_1000_ctrl_reg & PHY_Cap_1000_Full)) if (netif_running(dev) && (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL))
mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT);
return ret; return ret;
...@@ -803,7 +824,7 @@ static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) ...@@ -803,7 +824,7 @@ static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
spin_lock_irqsave(&tp->lock, flags); spin_lock_irqsave(&tp->lock, flags);
ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex); ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex);
spin_unlock_irqrestore(&tp->lock, flags); spin_unlock_irqrestore(&tp->lock, flags);
return ret; return ret;
} }
...@@ -936,20 +957,20 @@ static void rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) ...@@ -936,20 +957,20 @@ static void rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd)
SUPPORTED_100baseT_Full | SUPPORTED_100baseT_Full |
SUPPORTED_1000baseT_Full | SUPPORTED_1000baseT_Full |
SUPPORTED_Autoneg | SUPPORTED_Autoneg |
SUPPORTED_TP; SUPPORTED_TP;
cmd->autoneg = 1; cmd->autoneg = 1;
cmd->advertising = ADVERTISED_TP | ADVERTISED_Autoneg; cmd->advertising = ADVERTISED_TP | ADVERTISED_Autoneg;
if (tp->phy_auto_nego_reg & PHY_Cap_10_Half) if (tp->phy_auto_nego_reg & ADVERTISE_10HALF)
cmd->advertising |= ADVERTISED_10baseT_Half; cmd->advertising |= ADVERTISED_10baseT_Half;
if (tp->phy_auto_nego_reg & PHY_Cap_10_Full) if (tp->phy_auto_nego_reg & ADVERTISE_10FULL)
cmd->advertising |= ADVERTISED_10baseT_Full; cmd->advertising |= ADVERTISED_10baseT_Full;
if (tp->phy_auto_nego_reg & PHY_Cap_100_Half) if (tp->phy_auto_nego_reg & ADVERTISE_100HALF)
cmd->advertising |= ADVERTISED_100baseT_Half; cmd->advertising |= ADVERTISED_100baseT_Half;
if (tp->phy_auto_nego_reg & PHY_Cap_100_Full) if (tp->phy_auto_nego_reg & ADVERTISE_100FULL)
cmd->advertising |= ADVERTISED_100baseT_Full; cmd->advertising |= ADVERTISED_100baseT_Full;
if (tp->phy_1000_ctrl_reg & PHY_Cap_1000_Full) if (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL)
cmd->advertising |= ADVERTISED_1000baseT_Full; cmd->advertising |= ADVERTISED_1000baseT_Full;
status = RTL_R8(PHYstatus); status = RTL_R8(PHYstatus);
...@@ -961,6 +982,11 @@ static void rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) ...@@ -961,6 +982,11 @@ static void rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd)
else if (status & _10bps) else if (status & _10bps)
cmd->speed = SPEED_10; cmd->speed = SPEED_10;
if (status & TxFlowCtrl)
cmd->advertising |= ADVERTISED_Asym_Pause;
if (status & RxFlowCtrl)
cmd->advertising |= ADVERTISED_Pause;
cmd->duplex = ((status & _1000bpsF) || (status & FullDup)) ? cmd->duplex = ((status & _1000bpsF) || (status & FullDup)) ?
DUPLEX_FULL : DUPLEX_HALF; DUPLEX_FULL : DUPLEX_HALF;
} }
...@@ -981,15 +1007,15 @@ static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) ...@@ -981,15 +1007,15 @@ static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs,
void *p) void *p)
{ {
struct rtl8169_private *tp = netdev_priv(dev); struct rtl8169_private *tp = netdev_priv(dev);
unsigned long flags; unsigned long flags;
if (regs->len > R8169_REGS_SIZE) if (regs->len > R8169_REGS_SIZE)
regs->len = R8169_REGS_SIZE; regs->len = R8169_REGS_SIZE;
spin_lock_irqsave(&tp->lock, flags); spin_lock_irqsave(&tp->lock, flags);
memcpy_fromio(p, tp->mmio_addr, regs->len); memcpy_fromio(p, tp->mmio_addr, regs->len);
spin_unlock_irqrestore(&tp->lock, flags); spin_unlock_irqrestore(&tp->lock, flags);
} }
static u32 rtl8169_get_msglevel(struct net_device *dev) static u32 rtl8169_get_msglevel(struct net_device *dev)
...@@ -1071,7 +1097,7 @@ static void rtl8169_get_ethtool_stats(struct net_device *dev, ...@@ -1071,7 +1097,7 @@ static void rtl8169_get_ethtool_stats(struct net_device *dev,
RTL_W32(CounterAddrLow, 0); RTL_W32(CounterAddrLow, 0);
RTL_W32(CounterAddrHigh, 0); RTL_W32(CounterAddrHigh, 0);
data[0] = le64_to_cpu(counters->tx_packets); data[0] = le64_to_cpu(counters->tx_packets);
data[1] = le64_to_cpu(counters->rx_packets); data[1] = le64_to_cpu(counters->rx_packets);
data[2] = le64_to_cpu(counters->tx_errors); data[2] = le64_to_cpu(counters->tx_errors);
data[3] = le32_to_cpu(counters->rx_errors); data[3] = le32_to_cpu(counters->rx_errors);
...@@ -1131,7 +1157,7 @@ static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum ...@@ -1131,7 +1157,7 @@ static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum
val = mdio_read(ioaddr, reg); val = mdio_read(ioaddr, reg);
val = (bitval == 1) ? val = (bitval == 1) ?
val | (bitval << bitnum) : val & ~(0x0001 << bitnum); val | (bitval << bitnum) : val & ~(0x0001 << bitnum);
mdio_write(ioaddr, reg, val & 0xffff); mdio_write(ioaddr, reg, val & 0xffff);
} }
static void rtl8169_get_mac_version(struct rtl8169_private *tp, void __iomem *ioaddr) static void rtl8169_get_mac_version(struct rtl8169_private *tp, void __iomem *ioaddr)
...@@ -1140,10 +1166,16 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, void __iomem *io ...@@ -1140,10 +1166,16 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, void __iomem *io
u32 mask; u32 mask;
int mac_version; int mac_version;
} mac_info[] = { } mac_info[] = {
{ 0x1 << 28, RTL_GIGA_MAC_VER_X }, { 0x38800000, RTL_GIGA_MAC_VER_15 },
{ 0x1 << 26, RTL_GIGA_MAC_VER_E }, { 0x38000000, RTL_GIGA_MAC_VER_12 },
{ 0x1 << 23, RTL_GIGA_MAC_VER_D }, { 0x34000000, RTL_GIGA_MAC_VER_13 },
{ 0x00000000, RTL_GIGA_MAC_VER_B } /* Catch-all */ { 0x30800000, RTL_GIGA_MAC_VER_14 },
{ 0x30000000, RTL_GIGA_MAC_VER_11 },
{ 0x18000000, RTL_GIGA_MAC_VER_05 },
{ 0x10000000, RTL_GIGA_MAC_VER_04 },
{ 0x04000000, RTL_GIGA_MAC_VER_03 },
{ 0x00800000, RTL_GIGA_MAC_VER_02 },
{ 0x00000000, RTL_GIGA_MAC_VER_01 } /* Catch-all */
}, *p = mac_info; }, *p = mac_info;
u32 reg; u32 reg;
...@@ -1155,24 +1187,7 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, void __iomem *io ...@@ -1155,24 +1187,7 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, void __iomem *io
static void rtl8169_print_mac_version(struct rtl8169_private *tp) static void rtl8169_print_mac_version(struct rtl8169_private *tp)
{ {
struct { dprintk("mac_version = 0x%02x\n", tp->mac_version);
int version;
char *msg;
} mac_print[] = {
{ RTL_GIGA_MAC_VER_E, "RTL_GIGA_MAC_VER_E" },
{ RTL_GIGA_MAC_VER_D, "RTL_GIGA_MAC_VER_D" },
{ RTL_GIGA_MAC_VER_B, "RTL_GIGA_MAC_VER_B" },
{ 0, NULL }
}, *p;
for (p = mac_print; p->msg; p++) {
if (tp->mac_version == p->version) {
dprintk("mac_version == %s (%04d)\n", p->msg,
p->version);
return;
}
}
dprintk("mac_version == Unknown\n");
} }
static void rtl8169_get_phy_version(struct rtl8169_private *tp, void __iomem *ioaddr) static void rtl8169_get_phy_version(struct rtl8169_private *tp, void __iomem *ioaddr)
...@@ -1189,7 +1204,7 @@ static void rtl8169_get_phy_version(struct rtl8169_private *tp, void __iomem *io ...@@ -1189,7 +1204,7 @@ static void rtl8169_get_phy_version(struct rtl8169_private *tp, void __iomem *io
}, *p = phy_info; }, *p = phy_info;
u16 reg; u16 reg;
reg = mdio_read(ioaddr, 3) & 0xffff; reg = mdio_read(ioaddr, MII_PHYSID2) & 0xffff;
while ((reg & p->mask) != p->set) while ((reg & p->mask) != p->set)
p++; p++;
tp->phy_version = p->phy_version; tp->phy_version = p->phy_version;
...@@ -1257,7 +1272,7 @@ static void rtl8169_hw_phy_config(struct net_device *dev) ...@@ -1257,7 +1272,7 @@ static void rtl8169_hw_phy_config(struct net_device *dev)
rtl8169_print_mac_version(tp); rtl8169_print_mac_version(tp);
rtl8169_print_phy_version(tp); rtl8169_print_phy_version(tp);
if (tp->mac_version <= RTL_GIGA_MAC_VER_B) if (tp->mac_version <= RTL_GIGA_MAC_VER_01)
return; return;
if (tp->phy_version >= RTL_GIGA_PHY_VER_H) if (tp->phy_version >= RTL_GIGA_PHY_VER_H)
return; return;
...@@ -1267,7 +1282,7 @@ static void rtl8169_hw_phy_config(struct net_device *dev) ...@@ -1267,7 +1282,7 @@ static void rtl8169_hw_phy_config(struct net_device *dev)
/* Shazam ! */ /* Shazam ! */
if (tp->mac_version == RTL_GIGA_MAC_VER_X) { if (tp->mac_version == RTL_GIGA_MAC_VER_04) {
mdio_write(ioaddr, 31, 0x0001); mdio_write(ioaddr, 31, 0x0001);
mdio_write(ioaddr, 9, 0x273a); mdio_write(ioaddr, 9, 0x273a);
mdio_write(ioaddr, 14, 0x7bfb); mdio_write(ioaddr, 14, 0x7bfb);
...@@ -1306,16 +1321,16 @@ static void rtl8169_phy_timer(unsigned long __opaque) ...@@ -1306,16 +1321,16 @@ static void rtl8169_phy_timer(unsigned long __opaque)
void __iomem *ioaddr = tp->mmio_addr; void __iomem *ioaddr = tp->mmio_addr;
unsigned long timeout = RTL8169_PHY_TIMEOUT; unsigned long timeout = RTL8169_PHY_TIMEOUT;
assert(tp->mac_version > RTL_GIGA_MAC_VER_B); assert(tp->mac_version > RTL_GIGA_MAC_VER_01);
assert(tp->phy_version < RTL_GIGA_PHY_VER_H); assert(tp->phy_version < RTL_GIGA_PHY_VER_H);
if (!(tp->phy_1000_ctrl_reg & PHY_Cap_1000_Full)) if (!(tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL))
return; return;
spin_lock_irq(&tp->lock); spin_lock_irq(&tp->lock);
if (tp->phy_reset_pending(ioaddr)) { if (tp->phy_reset_pending(ioaddr)) {
/* /*
* A busy loop could burn quite a few cycles on nowadays CPU. * A busy loop could burn quite a few cycles on nowadays CPU.
* Let's delay the execution of the timer for a few ticks. * Let's delay the execution of the timer for a few ticks.
*/ */
...@@ -1342,7 +1357,7 @@ static inline void rtl8169_delete_timer(struct net_device *dev) ...@@ -1342,7 +1357,7 @@ static inline void rtl8169_delete_timer(struct net_device *dev)
struct rtl8169_private *tp = netdev_priv(dev); struct rtl8169_private *tp = netdev_priv(dev);
struct timer_list *timer = &tp->timer; struct timer_list *timer = &tp->timer;
if ((tp->mac_version <= RTL_GIGA_MAC_VER_B) || if ((tp->mac_version <= RTL_GIGA_MAC_VER_01) ||
(tp->phy_version >= RTL_GIGA_PHY_VER_H)) (tp->phy_version >= RTL_GIGA_PHY_VER_H))
return; return;
...@@ -1354,7 +1369,7 @@ static inline void rtl8169_request_timer(struct net_device *dev) ...@@ -1354,7 +1369,7 @@ static inline void rtl8169_request_timer(struct net_device *dev)
struct rtl8169_private *tp = netdev_priv(dev); struct rtl8169_private *tp = netdev_priv(dev);
struct timer_list *timer = &tp->timer; struct timer_list *timer = &tp->timer;
if ((tp->mac_version <= RTL_GIGA_MAC_VER_B) || if ((tp->mac_version <= RTL_GIGA_MAC_VER_01) ||
(tp->phy_version >= RTL_GIGA_PHY_VER_H)) (tp->phy_version >= RTL_GIGA_PHY_VER_H))
return; return;
...@@ -1382,6 +1397,41 @@ static void rtl8169_netpoll(struct net_device *dev) ...@@ -1382,6 +1397,41 @@ static void rtl8169_netpoll(struct net_device *dev)
} }
#endif #endif
static void __rtl8169_set_mac_addr(struct net_device *dev, void __iomem *ioaddr)
{
unsigned int i, j;
RTL_W8(Cfg9346, Cfg9346_Unlock);
for (i = 0; i < 2; i++) {
__le32 l = 0;
for (j = 0; j < 4; j++) {
l <<= 8;
l |= dev->dev_addr[4*i + j];
}
RTL_W32(MAC0 + 4*i, cpu_to_be32(l));
}
RTL_W8(Cfg9346, Cfg9346_Lock);
}
static int rtl8169_set_mac_addr(struct net_device *dev, void *p)
{
struct rtl8169_private *tp = netdev_priv(dev);
struct sockaddr *addr = p;
if (!is_valid_ether_addr(addr->sa_data))
return -EINVAL;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
if (netif_running(dev)) {
spin_lock_irq(&tp->lock);
__rtl8169_set_mac_addr(dev, tp->mmio_addr);
spin_unlock_irq(&tp->lock);
}
return 0;
}
static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev,
void __iomem *ioaddr) void __iomem *ioaddr)
{ {
...@@ -1391,23 +1441,87 @@ static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, ...@@ -1391,23 +1441,87 @@ static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev,
free_netdev(dev); free_netdev(dev);
} }
static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
{
void __iomem *ioaddr = tp->mmio_addr;
static int board_idx = -1;
u8 autoneg, duplex;
u16 speed;
board_idx++;
rtl8169_hw_phy_config(dev);
dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
RTL_W8(0x82, 0x01);
if (tp->mac_version < RTL_GIGA_MAC_VER_03) {
dprintk("Set PCI Latency=0x40\n");
pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40);
}
if (tp->mac_version == RTL_GIGA_MAC_VER_02) {
dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
RTL_W8(0x82, 0x01);
dprintk("Set PHY Reg 0x0bh = 0x00h\n");
mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0
}
rtl8169_link_option(board_idx, &autoneg, &speed, &duplex);
rtl8169_set_speed(dev, autoneg, speed, duplex);
if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp))
printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name);
}
static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
struct rtl8169_private *tp = netdev_priv(dev);
struct mii_ioctl_data *data = if_mii(ifr);
if (!netif_running(dev))
return -ENODEV;
switch (cmd) {
case SIOCGMIIPHY:
data->phy_id = 32; /* Internal PHY */
return 0;
case SIOCGMIIREG:
data->val_out = mdio_read(tp->mmio_addr, data->reg_num & 0x1f);
return 0;
case SIOCSMIIREG:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
mdio_write(tp->mmio_addr, data->reg_num & 0x1f, data->val_in);
return 0;
}
return -EOPNOTSUPP;
}
static int __devinit static int __devinit
rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out, rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
void __iomem **ioaddr_out)
{ {
void __iomem *ioaddr; const unsigned int region = rtl_cfg_info[ent->driver_data].region;
struct net_device *dev;
struct rtl8169_private *tp; struct rtl8169_private *tp;
int rc = -ENOMEM, i, acpi_idle_state = 0, pm_cap; struct net_device *dev;
void __iomem *ioaddr;
unsigned int i, pm_cap;
int rc;
assert(ioaddr_out != NULL); if (netif_msg_drv(&debug)) {
printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n",
MODULENAME, RTL8169_VERSION);
}
/* dev zeroed in alloc_etherdev */
dev = alloc_etherdev(sizeof (*tp)); dev = alloc_etherdev(sizeof (*tp));
if (dev == NULL) { if (!dev) {
if (netif_msg_drv(&debug)) if (netif_msg_drv(&debug))
dev_err(&pdev->dev, "unable to alloc new ethernet\n"); dev_err(&pdev->dev, "unable to alloc new ethernet\n");
goto err_out; rc = -ENOMEM;
goto out;
} }
SET_MODULE_OWNER(dev); SET_MODULE_OWNER(dev);
...@@ -1420,48 +1534,53 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out, ...@@ -1420,48 +1534,53 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
if (rc < 0) { if (rc < 0) {
if (netif_msg_probe(tp)) if (netif_msg_probe(tp))
dev_err(&pdev->dev, "enable failure\n"); dev_err(&pdev->dev, "enable failure\n");
goto err_out_free_dev; goto err_out_free_dev_1;
} }
rc = pci_set_mwi(pdev); rc = pci_set_mwi(pdev);
if (rc < 0) if (rc < 0)
goto err_out_disable; goto err_out_disable_2;
/* save power state before pci_enable_device overwrites it */ /* save power state before pci_enable_device overwrites it */
pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
if (pm_cap) { if (pm_cap) {
u16 pwr_command; u16 pwr_command, acpi_idle_state;
pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command); pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command);
acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK; acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK;
} else { } else {
if (netif_msg_probe(tp)) if (netif_msg_probe(tp)) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"PowerManagement capability not found.\n"); "PowerManagement capability not found.\n");
}
} }
/* make sure PCI base addr 1 is MMIO */ /* make sure PCI base addr 1 is MMIO */
if (!(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) { if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) {
if (netif_msg_probe(tp)) if (netif_msg_probe(tp)) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"region #1 not an MMIO resource, aborting\n"); "region #%d not an MMIO resource, aborting\n",
region);
}
rc = -ENODEV; rc = -ENODEV;
goto err_out_mwi; goto err_out_mwi_3;
} }
/* check for weird/broken PCI region reporting */ /* check for weird/broken PCI region reporting */
if (pci_resource_len(pdev, 1) < R8169_REGS_SIZE) { if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) {
if (netif_msg_probe(tp)) if (netif_msg_probe(tp)) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"Invalid PCI region size(s), aborting\n"); "Invalid PCI region size(s), aborting\n");
}
rc = -ENODEV; rc = -ENODEV;
goto err_out_mwi; goto err_out_mwi_3;
} }
rc = pci_request_regions(pdev, MODULENAME); rc = pci_request_regions(pdev, MODULENAME);
if (rc < 0) { if (rc < 0) {
if (netif_msg_probe(tp)) if (netif_msg_probe(tp))
dev_err(&pdev->dev, "could not request regions.\n"); dev_err(&pdev->dev, "could not request regions.\n");
goto err_out_mwi; goto err_out_mwi_3;
} }
tp->cp_cmd = PCIMulRW | RxChkSum; tp->cp_cmd = PCIMulRW | RxChkSum;
...@@ -1473,22 +1592,23 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out, ...@@ -1473,22 +1592,23 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
} else { } else {
rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (rc < 0) { if (rc < 0) {
if (netif_msg_probe(tp)) if (netif_msg_probe(tp)) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"DMA configuration failed.\n"); "DMA configuration failed.\n");
goto err_out_free_res; }
goto err_out_free_res_4;
} }
} }
pci_set_master(pdev); pci_set_master(pdev);
/* ioremap MMIO region */ /* ioremap MMIO region */
ioaddr = ioremap(pci_resource_start(pdev, 1), R8169_REGS_SIZE); ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE);
if (ioaddr == NULL) { if (!ioaddr) {
if (netif_msg_probe(tp)) if (netif_msg_probe(tp))
dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); dev_err(&pdev->dev, "cannot remap MMIO, aborting\n");
rc = -EIO; rc = -EIO;
goto err_out_free_res; goto err_out_free_res_4;
} }
/* Unneeded ? Don't mess with Mrs. Murphy. */ /* Unneeded ? Don't mess with Mrs. Murphy. */
...@@ -1498,10 +1618,10 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out, ...@@ -1498,10 +1618,10 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
RTL_W8(ChipCmd, CmdReset); RTL_W8(ChipCmd, CmdReset);
/* Check that the chip has finished the reset. */ /* Check that the chip has finished the reset. */
for (i = 1000; i > 0; i--) { for (i = 100; i > 0; i--) {
if ((RTL_R8(ChipCmd) & CmdReset) == 0) if ((RTL_R8(ChipCmd) & CmdReset) == 0)
break; break;
udelay(10); msleep_interruptible(1);
} }
/* Identify chip attached to board */ /* Identify chip attached to board */
...@@ -1519,8 +1639,8 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out, ...@@ -1519,8 +1639,8 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
/* Unknown chip: assume array element #0, original RTL-8169 */ /* Unknown chip: assume array element #0, original RTL-8169 */
if (netif_msg_probe(tp)) { if (netif_msg_probe(tp)) {
dev_printk(KERN_DEBUG, &pdev->dev, dev_printk(KERN_DEBUG, &pdev->dev,
"unknown chip version, assuming %s\n", "unknown chip version, assuming %s\n",
rtl_chip_info[0].name); rtl_chip_info[0].name);
} }
i++; i++;
} }
...@@ -1531,56 +1651,6 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out, ...@@ -1531,56 +1651,6 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
RTL_W8(Config5, RTL_R8(Config5) & PMEStatus); RTL_W8(Config5, RTL_R8(Config5) & PMEStatus);
RTL_W8(Cfg9346, Cfg9346_Lock); RTL_W8(Cfg9346, Cfg9346_Lock);
*ioaddr_out = ioaddr;
*dev_out = dev;
out:
return rc;
err_out_free_res:
pci_release_regions(pdev);
err_out_mwi:
pci_clear_mwi(pdev);
err_out_disable:
pci_disable_device(pdev);
err_out_free_dev:
free_netdev(dev);
err_out:
*ioaddr_out = NULL;
*dev_out = NULL;
goto out;
}
static int __devinit
rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *dev = NULL;
struct rtl8169_private *tp;
void __iomem *ioaddr = NULL;
static int board_idx = -1;
u8 autoneg, duplex;
u16 speed;
int i, rc;
assert(pdev != NULL);
assert(ent != NULL);
board_idx++;
if (netif_msg_drv(&debug)) {
printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n",
MODULENAME, RTL8169_VERSION);
}
rc = rtl8169_init_board(pdev, &dev, &ioaddr);
if (rc)
return rc;
tp = netdev_priv(dev);
assert(ioaddr != NULL);
if (RTL_R8(PHYstatus) & TBI_Enable) { if (RTL_R8(PHYstatus) & TBI_Enable) {
tp->set_speed = rtl8169_set_speed_tbi; tp->set_speed = rtl8169_set_speed_tbi;
tp->get_settings = rtl8169_gset_tbi; tp->get_settings = rtl8169_gset_tbi;
...@@ -1588,13 +1658,15 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1588,13 +1658,15 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->phy_reset_pending = rtl8169_tbi_reset_pending; tp->phy_reset_pending = rtl8169_tbi_reset_pending;
tp->link_ok = rtl8169_tbi_link_ok; tp->link_ok = rtl8169_tbi_link_ok;
tp->phy_1000_ctrl_reg = PHY_Cap_1000_Full; /* Implied by TBI */ tp->phy_1000_ctrl_reg = ADVERTISE_1000FULL; /* Implied by TBI */
} else { } else {
tp->set_speed = rtl8169_set_speed_xmii; tp->set_speed = rtl8169_set_speed_xmii;
tp->get_settings = rtl8169_gset_xmii; tp->get_settings = rtl8169_gset_xmii;
tp->phy_reset_enable = rtl8169_xmii_reset_enable; tp->phy_reset_enable = rtl8169_xmii_reset_enable;
tp->phy_reset_pending = rtl8169_xmii_reset_pending; tp->phy_reset_pending = rtl8169_xmii_reset_pending;
tp->link_ok = rtl8169_xmii_link_ok; tp->link_ok = rtl8169_xmii_link_ok;
dev->do_ioctl = rtl8169_ioctl;
} }
/* Get MAC address. FIXME: read EEPROM */ /* Get MAC address. FIXME: read EEPROM */
...@@ -1609,6 +1681,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1609,6 +1681,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
dev->stop = rtl8169_close; dev->stop = rtl8169_close;
dev->tx_timeout = rtl8169_tx_timeout; dev->tx_timeout = rtl8169_tx_timeout;
dev->set_multicast_list = rtl8169_set_rx_mode; dev->set_multicast_list = rtl8169_set_rx_mode;
dev->set_mac_address = rtl8169_set_mac_addr;
dev->watchdog_timeo = RTL8169_TX_TIMEOUT; dev->watchdog_timeo = RTL8169_TX_TIMEOUT;
dev->irq = pdev->irq; dev->irq = pdev->irq;
dev->base_addr = (unsigned long) ioaddr; dev->base_addr = (unsigned long) ioaddr;
...@@ -1632,19 +1705,13 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1632,19 +1705,13 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->intr_mask = 0xffff; tp->intr_mask = 0xffff;
tp->pci_dev = pdev; tp->pci_dev = pdev;
tp->mmio_addr = ioaddr; tp->mmio_addr = ioaddr;
tp->align = rtl_cfg_info[ent->driver_data].align;
spin_lock_init(&tp->lock); spin_lock_init(&tp->lock);
rc = register_netdev(dev); rc = register_netdev(dev);
if (rc) { if (rc < 0)
rtl8169_release_board(pdev, dev, ioaddr); goto err_out_unmap_5;
return rc;
}
if (netif_msg_probe(tp)) {
printk(KERN_DEBUG "%s: Identified chip type is '%s'.\n",
dev->name, rtl_chip_info[tp->chipset].name);
}
pci_set_drvdata(pdev, dev); pci_set_drvdata(pdev, dev);
...@@ -1653,38 +1720,29 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1653,38 +1720,29 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
"IRQ %d\n", "IRQ %d\n",
dev->name, dev->name,
rtl_chip_info[ent->driver_data].name, rtl_chip_info[tp->chipset].name,
dev->base_addr, dev->base_addr,
dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[0], dev->dev_addr[1],
dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[2], dev->dev_addr[3],
dev->dev_addr[4], dev->dev_addr[5], dev->irq); dev->dev_addr[4], dev->dev_addr[5], dev->irq);
} }
rtl8169_hw_phy_config(dev); rtl8169_init_phy(dev, tp);
dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
RTL_W8(0x82, 0x01);
if (tp->mac_version < RTL_GIGA_MAC_VER_E) { out:
dprintk("Set PCI Latency=0x40\n"); return rc;
pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40);
}
if (tp->mac_version == RTL_GIGA_MAC_VER_D) {
dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
RTL_W8(0x82, 0x01);
dprintk("Set PHY Reg 0x0bh = 0x00h\n");
mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0
}
rtl8169_link_option(board_idx, &autoneg, &speed, &duplex);
rtl8169_set_speed(dev, autoneg, speed, duplex);
if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp))
printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name);
return 0; err_out_unmap_5:
iounmap(ioaddr);
err_out_free_res_4:
pci_release_regions(pdev);
err_out_mwi_3:
pci_clear_mwi(pdev);
err_out_disable_2:
pci_disable_device(pdev);
err_out_free_dev_1:
free_netdev(dev);
goto out;
} }
static void __devexit static void __devexit
...@@ -1780,20 +1838,41 @@ rtl8169_hw_start(struct net_device *dev) ...@@ -1780,20 +1838,41 @@ rtl8169_hw_start(struct net_device *dev)
{ {
struct rtl8169_private *tp = netdev_priv(dev); struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr; void __iomem *ioaddr = tp->mmio_addr;
struct pci_dev *pdev = tp->pci_dev;
u32 i; u32 i;
/* Soft reset the chip. */ /* Soft reset the chip. */
RTL_W8(ChipCmd, CmdReset); RTL_W8(ChipCmd, CmdReset);
/* Check that the chip has finished the reset. */ /* Check that the chip has finished the reset. */
for (i = 1000; i > 0; i--) { for (i = 100; i > 0; i--) {
if ((RTL_R8(ChipCmd) & CmdReset) == 0) if ((RTL_R8(ChipCmd) & CmdReset) == 0)
break; break;
udelay(10); msleep_interruptible(1);
}
if (tp->mac_version == RTL_GIGA_MAC_VER_13) {
pci_write_config_word(pdev, 0x68, 0x00);
pci_write_config_word(pdev, 0x69, 0x08);
}
/* Undocumented stuff. */
if (tp->mac_version == RTL_GIGA_MAC_VER_05) {
u16 cmd;
/* Realtek's r1000_n.c driver uses '&& 0x01' here. Well... */
if ((RTL_R8(Config2) & 0x07) & 0x01)
RTL_W32(0x7c, 0x0007ffff);
RTL_W32(0x7c, 0x0007ff00);
pci_read_config_word(pdev, PCI_COMMAND, &cmd);
cmd = cmd & 0xef;
pci_write_config_word(pdev, PCI_COMMAND, cmd);
} }
RTL_W8(Cfg9346, Cfg9346_Unlock); RTL_W8(Cfg9346, Cfg9346_Unlock);
RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
RTL_W8(EarlyTxThres, EarlyTxThld); RTL_W8(EarlyTxThres, EarlyTxThld);
/* Low hurts. Let's disable the filtering. */ /* Low hurts. Let's disable the filtering. */
...@@ -1805,32 +1884,40 @@ rtl8169_hw_start(struct net_device *dev) ...@@ -1805,32 +1884,40 @@ rtl8169_hw_start(struct net_device *dev)
RTL_W32(RxConfig, i); RTL_W32(RxConfig, i);
/* Set DMA burst size and Interframe Gap Time */ /* Set DMA burst size and Interframe Gap Time */
RTL_W32(TxConfig, RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) |
(TX_DMA_BURST << TxDMAShift) | (InterFrameGap << (InterFrameGap << TxInterFrameGapShift));
TxInterFrameGapShift));
tp->cp_cmd |= RTL_R16(CPlusCmd); tp->cp_cmd |= RTL_R16(CPlusCmd) | PCIMulRW;
RTL_W16(CPlusCmd, tp->cp_cmd);
if ((tp->mac_version == RTL_GIGA_MAC_VER_D) || if ((tp->mac_version == RTL_GIGA_MAC_VER_02) ||
(tp->mac_version == RTL_GIGA_MAC_VER_E)) { (tp->mac_version == RTL_GIGA_MAC_VER_03)) {
dprintk(KERN_INFO PFX "Set MAC Reg C+CR Offset 0xE0. " dprintk(KERN_INFO PFX "Set MAC Reg C+CR Offset 0xE0. "
"Bit-3 and bit-14 MUST be 1\n"); "Bit-3 and bit-14 MUST be 1\n");
tp->cp_cmd |= (1 << 14) | PCIMulRW; tp->cp_cmd |= (1 << 14);
RTL_W16(CPlusCmd, tp->cp_cmd);
} }
RTL_W16(CPlusCmd, tp->cp_cmd);
/* /*
* Undocumented corner. Supposedly: * Undocumented corner. Supposedly:
* (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets
*/ */
RTL_W16(IntrMitigate, 0x0000); RTL_W16(IntrMitigate, 0x0000);
RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr & DMA_32BIT_MASK)); /*
* Magic spell: some iop3xx ARM board needs the TxDescAddrHigh
* register to be written before TxDescAddrLow to work.
* Switching from MMIO to I/O access fixes the issue as well.
*/
RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr >> 32)); RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr >> 32));
RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr & DMA_32BIT_MASK)); RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr & DMA_32BIT_MASK));
RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr >> 32)); RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr >> 32));
RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr & DMA_32BIT_MASK));
RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
RTL_W8(Cfg9346, Cfg9346_Lock); RTL_W8(Cfg9346, Cfg9346_Lock);
udelay(10);
/* Initially a 10 us delay. Turned it into a PCI commit. - FR */
RTL_R8(IntrMask);
RTL_W32(RxMissed, 0); RTL_W32(RxMissed, 0);
...@@ -1842,6 +1929,8 @@ rtl8169_hw_start(struct net_device *dev) ...@@ -1842,6 +1929,8 @@ rtl8169_hw_start(struct net_device *dev)
/* Enable all known interrupts by setting the interrupt mask. */ /* Enable all known interrupts by setting the interrupt mask. */
RTL_W16(IntrMask, rtl8169_intr_mask); RTL_W16(IntrMask, rtl8169_intr_mask);
__rtl8169_set_mac_addr(dev, ioaddr);
netif_start_queue(dev); netif_start_queue(dev);
} }
...@@ -1910,17 +1999,18 @@ static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, ...@@ -1910,17 +1999,18 @@ static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping,
} }
static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff, static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff,
struct RxDesc *desc, int rx_buf_sz) struct RxDesc *desc, int rx_buf_sz,
unsigned int align)
{ {
struct sk_buff *skb; struct sk_buff *skb;
dma_addr_t mapping; dma_addr_t mapping;
int ret = 0; int ret = 0;
skb = dev_alloc_skb(rx_buf_sz + NET_IP_ALIGN); skb = dev_alloc_skb(rx_buf_sz + align);
if (!skb) if (!skb)
goto err_out; goto err_out;
skb_reserve(skb, NET_IP_ALIGN); skb_reserve(skb, align);
*sk_buff = skb; *sk_buff = skb;
mapping = pci_map_single(pdev, skb->data, rx_buf_sz, mapping = pci_map_single(pdev, skb->data, rx_buf_sz,
...@@ -1953,15 +2043,15 @@ static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, ...@@ -1953,15 +2043,15 @@ static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev,
u32 start, u32 end) u32 start, u32 end)
{ {
u32 cur; u32 cur;
for (cur = start; end - cur > 0; cur++) { for (cur = start; end - cur > 0; cur++) {
int ret, i = cur % NUM_RX_DESC; int ret, i = cur % NUM_RX_DESC;
if (tp->Rx_skbuff[i]) if (tp->Rx_skbuff[i])
continue; continue;
ret = rtl8169_alloc_rx_skb(tp->pci_dev, tp->Rx_skbuff + i, ret = rtl8169_alloc_rx_skb(tp->pci_dev, tp->Rx_skbuff + i,
tp->RxDescArray + i, tp->rx_buf_sz); tp->RxDescArray + i, tp->rx_buf_sz, tp->align);
if (ret < 0) if (ret < 0)
break; break;
} }
...@@ -2190,8 +2280,8 @@ static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -2190,8 +2280,8 @@ static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev)
dma_addr_t mapping; dma_addr_t mapping;
u32 status, len; u32 status, len;
u32 opts1; u32 opts1;
int ret = 0; int ret = NETDEV_TX_OK;
if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) { if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) {
if (netif_msg_drv(tp)) { if (netif_msg_drv(tp)) {
printk(KERN_ERR printk(KERN_ERR
...@@ -2255,7 +2345,7 @@ static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -2255,7 +2345,7 @@ static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev)
err_stop: err_stop:
netif_stop_queue(dev); netif_stop_queue(dev);
ret = 1; ret = NETDEV_TX_BUSY;
err_update_stats: err_update_stats:
tp->stats.tx_dropped++; tp->stats.tx_dropped++;
goto out; goto out;
...@@ -2372,16 +2462,17 @@ static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc) ...@@ -2372,16 +2462,17 @@ static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc)
} }
static inline int rtl8169_try_rx_copy(struct sk_buff **sk_buff, int pkt_size, static inline int rtl8169_try_rx_copy(struct sk_buff **sk_buff, int pkt_size,
struct RxDesc *desc, int rx_buf_sz) struct RxDesc *desc, int rx_buf_sz,
unsigned int align)
{ {
int ret = -1; int ret = -1;
if (pkt_size < rx_copybreak) { if (pkt_size < rx_copybreak) {
struct sk_buff *skb; struct sk_buff *skb;
skb = dev_alloc_skb(pkt_size + NET_IP_ALIGN); skb = dev_alloc_skb(pkt_size + align);
if (skb) { if (skb) {
skb_reserve(skb, NET_IP_ALIGN); skb_reserve(skb, align);
eth_copy_and_sum(skb, sk_buff[0]->data, pkt_size, 0); eth_copy_and_sum(skb, sk_buff[0]->data, pkt_size, 0);
*sk_buff = skb; *sk_buff = skb;
rtl8169_mark_to_asic(desc, rx_buf_sz); rtl8169_mark_to_asic(desc, rx_buf_sz);
...@@ -2427,6 +2518,10 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, ...@@ -2427,6 +2518,10 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
tp->stats.rx_length_errors++; tp->stats.rx_length_errors++;
if (status & RxCRC) if (status & RxCRC)
tp->stats.rx_crc_errors++; tp->stats.rx_crc_errors++;
if (status & RxFOVF) {
rtl8169_schedule_work(dev, rtl8169_reset_task);
tp->stats.rx_fifo_errors++;
}
rtl8169_mark_to_asic(desc, tp->rx_buf_sz); rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
} else { } else {
struct sk_buff *skb = tp->Rx_skbuff[entry]; struct sk_buff *skb = tp->Rx_skbuff[entry];
...@@ -2447,13 +2542,13 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, ...@@ -2447,13 +2542,13 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
} }
rtl8169_rx_csum(skb, desc); rtl8169_rx_csum(skb, desc);
pci_dma_sync_single_for_cpu(tp->pci_dev, pci_dma_sync_single_for_cpu(tp->pci_dev,
le64_to_cpu(desc->addr), tp->rx_buf_sz, le64_to_cpu(desc->addr), tp->rx_buf_sz,
PCI_DMA_FROMDEVICE); PCI_DMA_FROMDEVICE);
if (rtl8169_try_rx_copy(&skb, pkt_size, desc, if (rtl8169_try_rx_copy(&skb, pkt_size, desc,
tp->rx_buf_sz)) { tp->rx_buf_sz, tp->align)) {
pci_action = pci_unmap_single; pci_action = pci_unmap_single;
tp->Rx_skbuff[entry] = NULL; tp->Rx_skbuff[entry] = NULL;
} }
...@@ -2543,7 +2638,7 @@ rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs) ...@@ -2543,7 +2638,7 @@ rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
__netif_rx_schedule(dev); __netif_rx_schedule(dev);
else if (netif_msg_intr(tp)) { else if (netif_msg_intr(tp)) {
printk(KERN_INFO "%s: interrupt %04x taken in poll\n", printk(KERN_INFO "%s: interrupt %04x taken in poll\n",
dev->name, status); dev->name, status);
} }
break; break;
#else #else
...@@ -2716,6 +2811,15 @@ rtl8169_set_rx_mode(struct net_device *dev) ...@@ -2716,6 +2811,15 @@ rtl8169_set_rx_mode(struct net_device *dev)
tmp = rtl8169_rx_config | rx_mode | tmp = rtl8169_rx_config | rx_mode |
(RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask);
if ((tp->mac_version == RTL_GIGA_MAC_VER_11) ||
(tp->mac_version == RTL_GIGA_MAC_VER_12) ||
(tp->mac_version == RTL_GIGA_MAC_VER_13) ||
(tp->mac_version == RTL_GIGA_MAC_VER_14) ||
(tp->mac_version == RTL_GIGA_MAC_VER_15)) {
mc_filter[0] = 0xffffffff;
mc_filter[1] = 0xffffffff;
}
RTL_W32(RxConfig, tmp); RTL_W32(RxConfig, tmp);
RTL_W32(MAR0 + 0, mc_filter[0]); RTL_W32(MAR0 + 0, mc_filter[0]);
RTL_W32(MAR0 + 4, mc_filter[1]); RTL_W32(MAR0 + 4, mc_filter[1]);
...@@ -2741,7 +2845,7 @@ static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) ...@@ -2741,7 +2845,7 @@ static struct net_device_stats *rtl8169_get_stats(struct net_device *dev)
RTL_W32(RxMissed, 0); RTL_W32(RxMissed, 0);
spin_unlock_irqrestore(&tp->lock, flags); spin_unlock_irqrestore(&tp->lock, flags);
} }
return &tp->stats; return &tp->stats;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment