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
...@@ -81,7 +81,7 @@ VERSION 2.2LK <2005/01/25> ...@@ -81,7 +81,7 @@ 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__); \
} }
...@@ -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;
...@@ -490,11 +497,6 @@ static const u16 rtl8169_napi_event = ...@@ -490,11 +497,6 @@ static const u16 rtl8169_napi_event =
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)
{ {
int i; int i;
...@@ -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,
...@@ -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;
...@@ -941,15 +962,15 @@ static void rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) ...@@ -941,15 +962,15 @@ static void rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd)
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;
} }
...@@ -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,10 +1321,10 @@ static void rtl8169_phy_timer(unsigned long __opaque) ...@@ -1306,10 +1321,10 @@ 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);
...@@ -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 */
...@@ -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) {
dprintk("Set PCI Latency=0x40\n");
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)) out:
printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name); return rc;
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);
RTL_W16(CPlusCmd, tp->cp_cmd);
if ((tp->mac_version == RTL_GIGA_MAC_VER_D) || tp->cp_cmd |= RTL_R16(CPlusCmd) | PCIMulRW;
(tp->mac_version == RTL_GIGA_MAC_VER_E)) {
if ((tp->mac_version == RTL_GIGA_MAC_VER_02) ||
(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,
...@@ -1961,7 +2051,7 @@ static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, ...@@ -1961,7 +2051,7 @@ static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev,
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,7 +2280,7 @@ static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -2190,7 +2280,7 @@ 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)) {
...@@ -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];
...@@ -2453,7 +2548,7 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, ...@@ -2453,7 +2548,7 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
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;
} }
...@@ -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]);
......
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