Commit f52ee141 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'upstream-fixes' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6

parents c0eea79b ad9f6713
...@@ -287,6 +287,20 @@ enum RTL8169_register_content { ...@@ -287,6 +287,20 @@ enum RTL8169_register_content {
TxInterFrameGapShift = 24, TxInterFrameGapShift = 24,
TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */
/* Config1 register p.24 */
PMEnable = (1 << 0), /* Power Management Enable */
/* Config3 register p.25 */
MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */
LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */
/* Config5 register p.27 */
BWF = (1 << 6), /* Accept Broadcast wakeup frame */
MWF = (1 << 5), /* Accept Multicast wakeup frame */
UWF = (1 << 4), /* Accept Unicast wakeup frame */
LanWake = (1 << 1), /* LanWake enable/disable */
PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */
/* TBICSR p.28 */ /* TBICSR p.28 */
TBIReset = 0x80000000, TBIReset = 0x80000000,
TBILoopback = 0x40000000, TBILoopback = 0x40000000,
...@@ -433,6 +447,7 @@ struct rtl8169_private { ...@@ -433,6 +447,7 @@ struct rtl8169_private {
unsigned int (*phy_reset_pending)(void __iomem *); unsigned int (*phy_reset_pending)(void __iomem *);
unsigned int (*link_ok)(void __iomem *); unsigned int (*link_ok)(void __iomem *);
struct work_struct task; struct work_struct task;
unsigned wol_enabled : 1;
}; };
MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>"); MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
...@@ -607,6 +622,80 @@ static void rtl8169_link_option(int idx, u8 *autoneg, u16 *speed, u8 *duplex) ...@@ -607,6 +622,80 @@ static void rtl8169_link_option(int idx, u8 *autoneg, u16 *speed, u8 *duplex)
*duplex = p->duplex; *duplex = p->duplex;
} }
static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
u8 options;
wol->wolopts = 0;
#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)
wol->supported = WAKE_ANY;
spin_lock_irq(&tp->lock);
options = RTL_R8(Config1);
if (!(options & PMEnable))
goto out_unlock;
options = RTL_R8(Config3);
if (options & LinkUp)
wol->wolopts |= WAKE_PHY;
if (options & MagicPacket)
wol->wolopts |= WAKE_MAGIC;
options = RTL_R8(Config5);
if (options & UWF)
wol->wolopts |= WAKE_UCAST;
if (options & BWF)
wol->wolopts |= WAKE_BCAST;
if (options & MWF)
wol->wolopts |= WAKE_MCAST;
out_unlock:
spin_unlock_irq(&tp->lock);
}
static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
int i;
static struct {
u32 opt;
u16 reg;
u8 mask;
} cfg[] = {
{ WAKE_ANY, Config1, PMEnable },
{ WAKE_PHY, Config3, LinkUp },
{ WAKE_MAGIC, Config3, MagicPacket },
{ WAKE_UCAST, Config5, UWF },
{ WAKE_BCAST, Config5, BWF },
{ WAKE_MCAST, Config5, MWF },
{ WAKE_ANY, Config5, LanWake }
};
spin_lock_irq(&tp->lock);
RTL_W8(Cfg9346, Cfg9346_Unlock);
for (i = 0; i < ARRAY_SIZE(cfg); i++) {
u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask;
if (wol->wolopts & cfg[i].opt)
options |= cfg[i].mask;
RTL_W8(cfg[i].reg, options);
}
RTL_W8(Cfg9346, Cfg9346_Lock);
tp->wol_enabled = (wol->wolopts) ? 1 : 0;
spin_unlock_irq(&tp->lock);
return 0;
}
static void rtl8169_get_drvinfo(struct net_device *dev, static void rtl8169_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info) struct ethtool_drvinfo *info)
{ {
...@@ -1025,6 +1114,8 @@ static struct ethtool_ops rtl8169_ethtool_ops = { ...@@ -1025,6 +1114,8 @@ static struct ethtool_ops rtl8169_ethtool_ops = {
.get_tso = ethtool_op_get_tso, .get_tso = ethtool_op_get_tso,
.set_tso = ethtool_op_set_tso, .set_tso = ethtool_op_set_tso,
.get_regs = rtl8169_get_regs, .get_regs = rtl8169_get_regs,
.get_wol = rtl8169_get_wol,
.set_wol = rtl8169_set_wol,
.get_strings = rtl8169_get_strings, .get_strings = rtl8169_get_strings,
.get_stats_count = rtl8169_get_stats_count, .get_stats_count = rtl8169_get_stats_count,
.get_ethtool_stats = rtl8169_get_ethtool_stats, .get_ethtool_stats = rtl8169_get_ethtool_stats,
...@@ -1442,6 +1533,11 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out, ...@@ -1442,6 +1533,11 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
} }
tp->chipset = i; tp->chipset = i;
RTL_W8(Cfg9346, Cfg9346_Unlock);
RTL_W8(Config1, RTL_R8(Config1) | PMEnable);
RTL_W8(Config5, RTL_R8(Config5) & PMEStatus);
RTL_W8(Cfg9346, Cfg9346_Lock);
*ioaddr_out = ioaddr; *ioaddr_out = ioaddr;
*dev_out = dev; *dev_out = dev;
out: out:
...@@ -1612,49 +1708,6 @@ rtl8169_remove_one(struct pci_dev *pdev) ...@@ -1612,49 +1708,6 @@ rtl8169_remove_one(struct pci_dev *pdev)
pci_set_drvdata(pdev, NULL); pci_set_drvdata(pdev, NULL);
} }
#ifdef CONFIG_PM
static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
unsigned long flags;
if (!netif_running(dev))
return 0;
netif_device_detach(dev);
netif_stop_queue(dev);
spin_lock_irqsave(&tp->lock, flags);
/* Disable interrupts, stop Rx and Tx */
RTL_W16(IntrMask, 0);
RTL_W8(ChipCmd, 0);
/* Update the error counts. */
tp->stats.rx_missed_errors += RTL_R32(RxMissed);
RTL_W32(RxMissed, 0);
spin_unlock_irqrestore(&tp->lock, flags);
return 0;
}
static int rtl8169_resume(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
if (!netif_running(dev))
return 0;
netif_device_attach(dev);
rtl8169_hw_start(dev);
return 0;
}
#endif /* CONFIG_PM */
static void rtl8169_set_rxbufsize(struct rtl8169_private *tp, static void rtl8169_set_rxbufsize(struct rtl8169_private *tp,
struct net_device *dev) struct net_device *dev)
{ {
...@@ -2700,6 +2753,56 @@ static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) ...@@ -2700,6 +2753,56 @@ static struct net_device_stats *rtl8169_get_stats(struct net_device *dev)
return &tp->stats; return &tp->stats;
} }
#ifdef CONFIG_PM
static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
if (!netif_running(dev))
goto out;
netif_device_detach(dev);
netif_stop_queue(dev);
spin_lock_irq(&tp->lock);
rtl8169_asic_down(ioaddr);
tp->stats.rx_missed_errors += RTL_R32(RxMissed);
RTL_W32(RxMissed, 0);
spin_unlock_irq(&tp->lock);
pci_save_state(pdev);
pci_enable_wake(pdev, pci_choose_state(pdev, state), tp->wol_enabled);
pci_set_power_state(pdev, pci_choose_state(pdev, state));
out:
return 0;
}
static int rtl8169_resume(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
if (!netif_running(dev))
goto out;
netif_device_attach(dev);
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
pci_enable_wake(pdev, PCI_D0, 0);
rtl8169_schedule_work(dev, rtl8169_reset_task);
out:
return 0;
}
#endif /* CONFIG_PM */
static struct pci_driver rtl8169_pci_driver = { static struct pci_driver rtl8169_pci_driver = {
.name = MODULENAME, .name = MODULENAME,
.id_table = rtl8169_pci_tbl, .id_table = rtl8169_pci_tbl,
......
...@@ -879,13 +879,12 @@ static int __xm_phy_read(struct skge_hw *hw, int port, u16 reg, u16 *val) ...@@ -879,13 +879,12 @@ static int __xm_phy_read(struct skge_hw *hw, int port, u16 reg, u16 *val)
int i; int i;
xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr); xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr);
xm_read16(hw, port, XM_PHY_DATA); *val = xm_read16(hw, port, XM_PHY_DATA);
/* Need to wait for external PHY */
for (i = 0; i < PHY_RETRIES; i++) { for (i = 0; i < PHY_RETRIES; i++) {
udelay(1);
if (xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_RDY) if (xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_RDY)
goto ready; goto ready;
udelay(1);
} }
return -ETIMEDOUT; return -ETIMEDOUT;
...@@ -918,7 +917,12 @@ static int xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val) ...@@ -918,7 +917,12 @@ static int xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val)
ready: ready:
xm_write16(hw, port, XM_PHY_DATA, val); xm_write16(hw, port, XM_PHY_DATA, val);
return 0; for (i = 0; i < PHY_RETRIES; i++) {
if (!(xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_BUSY))
return 0;
udelay(1);
}
return -ETIMEDOUT;
} }
static void genesis_init(struct skge_hw *hw) static void genesis_init(struct skge_hw *hw)
...@@ -1168,13 +1172,17 @@ static void genesis_mac_init(struct skge_hw *hw, int port) ...@@ -1168,13 +1172,17 @@ static void genesis_mac_init(struct skge_hw *hw, int port)
u32 r; u32 r;
const u8 zero[6] = { 0 }; const u8 zero[6] = { 0 };
/* Clear MIB counters */ for (i = 0; i < 10; i++) {
xm_write16(hw, port, XM_STAT_CMD, skge_write16(hw, SK_REG(port, TX_MFF_CTRL1),
XM_SC_CLR_RXC | XM_SC_CLR_TXC); MFF_SET_MAC_RST);
/* Clear two times according to Errata #3 */ if (skge_read16(hw, SK_REG(port, TX_MFF_CTRL1)) & MFF_SET_MAC_RST)
xm_write16(hw, port, XM_STAT_CMD, goto reset_ok;
XM_SC_CLR_RXC | XM_SC_CLR_TXC); udelay(1);
}
printk(KERN_WARNING PFX "%s: genesis reset failed\n", dev->name);
reset_ok:
/* Unreset the XMAC. */ /* Unreset the XMAC. */
skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_CLR_MAC_RST); skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
...@@ -1191,7 +1199,7 @@ static void genesis_mac_init(struct skge_hw *hw, int port) ...@@ -1191,7 +1199,7 @@ static void genesis_mac_init(struct skge_hw *hw, int port)
r |= GP_DIR_2|GP_IO_2; r |= GP_DIR_2|GP_IO_2;
skge_write32(hw, B2_GP_IO, r); skge_write32(hw, B2_GP_IO, r);
skge_read32(hw, B2_GP_IO);
/* Enable GMII interface */ /* Enable GMII interface */
xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD); xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD);
...@@ -1205,6 +1213,13 @@ static void genesis_mac_init(struct skge_hw *hw, int port) ...@@ -1205,6 +1213,13 @@ static void genesis_mac_init(struct skge_hw *hw, int port)
for (i = 1; i < 16; i++) for (i = 1; i < 16; i++)
xm_outaddr(hw, port, XM_EXM(i), zero); xm_outaddr(hw, port, XM_EXM(i), zero);
/* Clear MIB counters */
xm_write16(hw, port, XM_STAT_CMD,
XM_SC_CLR_RXC | XM_SC_CLR_TXC);
/* Clear two times according to Errata #3 */
xm_write16(hw, port, XM_STAT_CMD,
XM_SC_CLR_RXC | XM_SC_CLR_TXC);
/* configure Rx High Water Mark (XM_RX_HI_WM) */ /* configure Rx High Water Mark (XM_RX_HI_WM) */
xm_write16(hw, port, XM_RX_HI_WM, 1450); xm_write16(hw, port, XM_RX_HI_WM, 1450);
...@@ -2170,8 +2185,10 @@ static int skge_up(struct net_device *dev) ...@@ -2170,8 +2185,10 @@ static int skge_up(struct net_device *dev)
skge->tx_avail = skge->tx_ring.count - 1; skge->tx_avail = skge->tx_ring.count - 1;
/* Enable IRQ from port */ /* Enable IRQ from port */
spin_lock_irq(&hw->hw_lock);
hw->intr_mask |= portirqmask[port]; hw->intr_mask |= portirqmask[port];
skge_write32(hw, B0_IMSK, hw->intr_mask); skge_write32(hw, B0_IMSK, hw->intr_mask);
spin_unlock_irq(&hw->hw_lock);
/* Initialize MAC */ /* Initialize MAC */
spin_lock_bh(&hw->phy_lock); spin_lock_bh(&hw->phy_lock);
...@@ -2229,8 +2246,10 @@ static int skge_down(struct net_device *dev) ...@@ -2229,8 +2246,10 @@ static int skge_down(struct net_device *dev)
else else
yukon_stop(skge); yukon_stop(skge);
spin_lock_irq(&hw->hw_lock);
hw->intr_mask &= ~portirqmask[skge->port]; hw->intr_mask &= ~portirqmask[skge->port];
skge_write32(hw, B0_IMSK, hw->intr_mask); skge_write32(hw, B0_IMSK, hw->intr_mask);
spin_unlock_irq(&hw->hw_lock);
/* Stop transmitter */ /* Stop transmitter */
skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP); skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP);
...@@ -2678,8 +2697,7 @@ static int skge_poll(struct net_device *dev, int *budget) ...@@ -2678,8 +2697,7 @@ static int skge_poll(struct net_device *dev, int *budget)
/* restart receiver */ /* restart receiver */
wmb(); wmb();
skge_write8(hw, Q_ADDR(rxqaddr[skge->port], Q_CSR), skge_write8(hw, Q_ADDR(rxqaddr[skge->port], Q_CSR), CSR_START);
CSR_START | CSR_IRQ_CL_F);
*budget -= work_done; *budget -= work_done;
dev->quota -= work_done; dev->quota -= work_done;
...@@ -2687,10 +2705,11 @@ static int skge_poll(struct net_device *dev, int *budget) ...@@ -2687,10 +2705,11 @@ static int skge_poll(struct net_device *dev, int *budget)
if (work_done >= to_do) if (work_done >= to_do)
return 1; /* not done */ return 1; /* not done */
netif_rx_complete(dev); spin_lock_irq(&hw->hw_lock);
hw->intr_mask |= portirqmask[skge->port]; __netif_rx_complete(dev);
skge_write32(hw, B0_IMSK, hw->intr_mask); hw->intr_mask |= portirqmask[skge->port];
skge_read32(hw, B0_IMSK); skge_write32(hw, B0_IMSK, hw->intr_mask);
spin_unlock_irq(&hw->hw_lock);
return 0; return 0;
} }
...@@ -2850,18 +2869,10 @@ static void skge_extirq(unsigned long data) ...@@ -2850,18 +2869,10 @@ static void skge_extirq(unsigned long data)
} }
spin_unlock(&hw->phy_lock); spin_unlock(&hw->phy_lock);
local_irq_disable(); spin_lock_irq(&hw->hw_lock);
hw->intr_mask |= IS_EXT_REG; hw->intr_mask |= IS_EXT_REG;
skge_write32(hw, B0_IMSK, hw->intr_mask); skge_write32(hw, B0_IMSK, hw->intr_mask);
local_irq_enable(); spin_unlock_irq(&hw->hw_lock);
}
static inline void skge_wakeup(struct net_device *dev)
{
struct skge_port *skge = netdev_priv(dev);
prefetch(skge->rx_ring.to_clean);
netif_rx_schedule(dev);
} }
static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs)
...@@ -2872,15 +2883,17 @@ static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs) ...@@ -2872,15 +2883,17 @@ static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs)
if (status == 0 || status == ~0) /* hotplug or shared irq */ if (status == 0 || status == ~0) /* hotplug or shared irq */
return IRQ_NONE; return IRQ_NONE;
status &= hw->intr_mask; spin_lock(&hw->hw_lock);
if (status & IS_R1_F) { if (status & IS_R1_F) {
skge_write8(hw, Q_ADDR(Q_R1, Q_CSR), CSR_IRQ_CL_F);
hw->intr_mask &= ~IS_R1_F; hw->intr_mask &= ~IS_R1_F;
skge_wakeup(hw->dev[0]); netif_rx_schedule(hw->dev[0]);
} }
if (status & IS_R2_F) { if (status & IS_R2_F) {
skge_write8(hw, Q_ADDR(Q_R2, Q_CSR), CSR_IRQ_CL_F);
hw->intr_mask &= ~IS_R2_F; hw->intr_mask &= ~IS_R2_F;
skge_wakeup(hw->dev[1]); netif_rx_schedule(hw->dev[1]);
} }
if (status & IS_XA1_F) if (status & IS_XA1_F)
...@@ -2922,6 +2935,7 @@ static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs) ...@@ -2922,6 +2935,7 @@ static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs)
} }
skge_write32(hw, B0_IMSK, hw->intr_mask); skge_write32(hw, B0_IMSK, hw->intr_mask);
spin_unlock(&hw->hw_lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -3290,6 +3304,7 @@ static int __devinit skge_probe(struct pci_dev *pdev, ...@@ -3290,6 +3304,7 @@ static int __devinit skge_probe(struct pci_dev *pdev,
hw->pdev = pdev; hw->pdev = pdev;
spin_lock_init(&hw->phy_lock); spin_lock_init(&hw->phy_lock);
spin_lock_init(&hw->hw_lock);
tasklet_init(&hw->ext_tasklet, skge_extirq, (unsigned long) hw); tasklet_init(&hw->ext_tasklet, skge_extirq, (unsigned long) hw);
hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000); hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000);
......
...@@ -2402,6 +2402,7 @@ struct skge_hw { ...@@ -2402,6 +2402,7 @@ struct skge_hw {
struct tasklet_struct ext_tasklet; struct tasklet_struct ext_tasklet;
spinlock_t phy_lock; spinlock_t phy_lock;
spinlock_t hw_lock;
}; };
enum { enum {
......
...@@ -195,11 +195,11 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state) ...@@ -195,11 +195,11 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state)
pr_debug("sky2_set_power_state %d\n", state); pr_debug("sky2_set_power_state %d\n", state);
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_PMC, &power_control); power_control = sky2_pci_read16(hw, hw->pm_cap + PCI_PM_PMC);
vaux = (sky2_read16(hw, B0_CTST) & Y2_VAUX_AVAIL) && vaux = (sky2_read16(hw, B0_CTST) & Y2_VAUX_AVAIL) &&
(power_control & PCI_PM_CAP_PME_D3cold); (power_control & PCI_PM_CAP_PME_D3cold);
pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_CTRL, &power_control); power_control = sky2_pci_read16(hw, hw->pm_cap + PCI_PM_CTRL);
power_control |= PCI_PM_CTRL_PME_STATUS; power_control |= PCI_PM_CTRL_PME_STATUS;
power_control &= ~(PCI_PM_CTRL_STATE_MASK); power_control &= ~(PCI_PM_CTRL_STATE_MASK);
...@@ -223,7 +223,7 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state) ...@@ -223,7 +223,7 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state)
sky2_write8(hw, B2_Y2_CLK_GATE, 0); sky2_write8(hw, B2_Y2_CLK_GATE, 0);
/* Turn off phy power saving */ /* Turn off phy power saving */
pci_read_config_dword(hw->pdev, PCI_DEV_REG1, &reg1); reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
reg1 &= ~(PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD); reg1 &= ~(PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD);
/* looks like this XL is back asswards .. */ /* looks like this XL is back asswards .. */
...@@ -232,18 +232,28 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state) ...@@ -232,18 +232,28 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state)
if (hw->ports > 1) if (hw->ports > 1)
reg1 |= PCI_Y2_PHY2_COMA; reg1 |= PCI_Y2_PHY2_COMA;
} }
pci_write_config_dword(hw->pdev, PCI_DEV_REG1, reg1);
if (hw->chip_id == CHIP_ID_YUKON_EC_U) {
sky2_pci_write32(hw, PCI_DEV_REG3, 0);
reg1 = sky2_pci_read32(hw, PCI_DEV_REG4);
reg1 &= P_ASPM_CONTROL_MSK;
sky2_pci_write32(hw, PCI_DEV_REG4, reg1);
sky2_pci_write32(hw, PCI_DEV_REG5, 0);
}
sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
break; break;
case PCI_D3hot: case PCI_D3hot:
case PCI_D3cold: case PCI_D3cold:
/* Turn on phy power saving */ /* Turn on phy power saving */
pci_read_config_dword(hw->pdev, PCI_DEV_REG1, &reg1); reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1)
reg1 &= ~(PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD); reg1 &= ~(PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD);
else else
reg1 |= (PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD); reg1 |= (PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD);
pci_write_config_dword(hw->pdev, PCI_DEV_REG1, reg1); sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1)
sky2_write8(hw, B2_Y2_CLK_GATE, 0); sky2_write8(hw, B2_Y2_CLK_GATE, 0);
...@@ -265,7 +275,7 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state) ...@@ -265,7 +275,7 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state)
ret = -1; ret = -1;
} }
pci_write_config_byte(hw->pdev, hw->pm_cap + PCI_PM_CTRL, power_control); sky2_pci_write16(hw, hw->pm_cap + PCI_PM_CTRL, power_control);
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
return ret; return ret;
} }
...@@ -463,16 +473,31 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) ...@@ -463,16 +473,31 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
ledover |= PHY_M_LED_MO_RX(MO_LED_OFF); ledover |= PHY_M_LED_MO_RX(MO_LED_OFF);
} }
gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev >= 2) {
/* apply fixes in PHY AFE */
gm_phy_write(hw, port, 22, 255);
/* increase differential signal amplitude in 10BASE-T */
gm_phy_write(hw, port, 24, 0xaa99);
gm_phy_write(hw, port, 23, 0x2011);
if (sky2->autoneg == AUTONEG_DISABLE || sky2->speed == SPEED_100) { /* fix for IEEE A/B Symmetry failure in 1000BASE-T */
/* turn on 100 Mbps LED (LED_LINK100) */ gm_phy_write(hw, port, 24, 0xa204);
ledover |= PHY_M_LED_MO_100(MO_LED_ON); gm_phy_write(hw, port, 23, 0x2002);
}
if (ledover) /* set page register to 0 */
gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover); gm_phy_write(hw, port, 22, 0);
} else {
gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl);
if (sky2->autoneg == AUTONEG_DISABLE || sky2->speed == SPEED_100) {
/* turn on 100 Mbps LED (LED_LINK100) */
ledover |= PHY_M_LED_MO_100(MO_LED_ON);
}
if (ledover)
gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover);
}
/* Enable phy interrupt on auto-negotiation complete (or link up) */ /* Enable phy interrupt on auto-negotiation complete (or link up) */
if (sky2->autoneg == AUTONEG_ENABLE) if (sky2->autoneg == AUTONEG_ENABLE)
gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL); gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL);
...@@ -953,6 +978,12 @@ static int sky2_rx_start(struct sky2_port *sky2) ...@@ -953,6 +978,12 @@ static int sky2_rx_start(struct sky2_port *sky2)
sky2->rx_put = sky2->rx_next = 0; sky2->rx_put = sky2->rx_next = 0;
sky2_qset(hw, rxq); sky2_qset(hw, rxq);
if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev >= 2) {
/* MAC Rx RAM Read is controlled by hardware */
sky2_write32(hw, Q_ADDR(rxq, Q_F), F_M_RX_RAM_DIS);
}
sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1); sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1);
rx_set_checksum(sky2); rx_set_checksum(sky2);
...@@ -1035,9 +1066,10 @@ static int sky2_up(struct net_device *dev) ...@@ -1035,9 +1066,10 @@ static int sky2_up(struct net_device *dev)
RB_RST_SET); RB_RST_SET);
sky2_qset(hw, txqaddr[port]); sky2_qset(hw, txqaddr[port]);
if (hw->chip_id == CHIP_ID_YUKON_EC_U)
sky2_write16(hw, Q_ADDR(txqaddr[port], Q_AL), 0x1a0);
/* Set almost empty threshold */
if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev == 1)
sky2_write16(hw, Q_ADDR(txqaddr[port], Q_AL), 0x1a0);
sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map, sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map,
TX_RING_SIZE - 1); TX_RING_SIZE - 1);
...@@ -1047,8 +1079,10 @@ static int sky2_up(struct net_device *dev) ...@@ -1047,8 +1079,10 @@ static int sky2_up(struct net_device *dev)
goto err_out; goto err_out;
/* Enable interrupts from phy/mac for port */ /* Enable interrupts from phy/mac for port */
spin_lock_irq(&hw->hw_lock);
hw->intr_mask |= (port == 0) ? Y2_IS_PORT_1 : Y2_IS_PORT_2; hw->intr_mask |= (port == 0) ? Y2_IS_PORT_1 : Y2_IS_PORT_2;
sky2_write32(hw, B0_IMSK, hw->intr_mask); sky2_write32(hw, B0_IMSK, hw->intr_mask);
spin_unlock_irq(&hw->hw_lock);
return 0; return 0;
err_out: err_out:
...@@ -1348,10 +1382,10 @@ static int sky2_down(struct net_device *dev) ...@@ -1348,10 +1382,10 @@ static int sky2_down(struct net_device *dev)
netif_stop_queue(dev); netif_stop_queue(dev);
/* Disable port IRQ */ /* Disable port IRQ */
local_irq_disable(); spin_lock_irq(&hw->hw_lock);
hw->intr_mask &= ~((sky2->port == 0) ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2); hw->intr_mask &= ~((sky2->port == 0) ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2);
sky2_write32(hw, B0_IMSK, hw->intr_mask); sky2_write32(hw, B0_IMSK, hw->intr_mask);
local_irq_enable(); spin_unlock_irq(&hw->hw_lock);
flush_scheduled_work(); flush_scheduled_work();
...@@ -1633,10 +1667,10 @@ static void sky2_phy_task(void *arg) ...@@ -1633,10 +1667,10 @@ static void sky2_phy_task(void *arg)
out: out:
up(&sky2->phy_sema); up(&sky2->phy_sema);
local_irq_disable(); spin_lock_irq(&hw->hw_lock);
hw->intr_mask |= (sky2->port == 0) ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2; hw->intr_mask |= (sky2->port == 0) ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2;
sky2_write32(hw, B0_IMSK, hw->intr_mask); sky2_write32(hw, B0_IMSK, hw->intr_mask);
local_irq_enable(); spin_unlock_irq(&hw->hw_lock);
} }
...@@ -1863,6 +1897,17 @@ static int sky2_poll(struct net_device *dev0, int *budget) ...@@ -1863,6 +1897,17 @@ static int sky2_poll(struct net_device *dev0, int *budget)
sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
/*
* Kick the STAT_LEV_TIMER_CTRL timer.
* This fixes my hangs on Yukon-EC (0xb6) rev 1.
* The if clause is there to start the timer only if it has been
* configured correctly and not been disabled via ethtool.
*/
if (sky2_read8(hw, STAT_LEV_TIMER_CTRL) == TIM_START) {
sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_STOP);
sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_START);
}
hwidx = sky2_read16(hw, STAT_PUT_IDX); hwidx = sky2_read16(hw, STAT_PUT_IDX);
BUG_ON(hwidx >= STATUS_RING_SIZE); BUG_ON(hwidx >= STATUS_RING_SIZE);
rmb(); rmb();
...@@ -1945,16 +1990,19 @@ static int sky2_poll(struct net_device *dev0, int *budget) ...@@ -1945,16 +1990,19 @@ static int sky2_poll(struct net_device *dev0, int *budget)
sky2_tx_check(hw, 0, tx_done[0]); sky2_tx_check(hw, 0, tx_done[0]);
sky2_tx_check(hw, 1, tx_done[1]); sky2_tx_check(hw, 1, tx_done[1]);
if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_START) {
sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
}
if (likely(work_done < to_do)) { if (likely(work_done < to_do)) {
/* need to restart TX timer */ spin_lock_irq(&hw->hw_lock);
if (is_ec_a1(hw)) { __netif_rx_complete(dev0);
sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
}
netif_rx_complete(dev0);
hw->intr_mask |= Y2_IS_STAT_BMU; hw->intr_mask |= Y2_IS_STAT_BMU;
sky2_write32(hw, B0_IMSK, hw->intr_mask); sky2_write32(hw, B0_IMSK, hw->intr_mask);
spin_unlock_irq(&hw->hw_lock);
return 0; return 0;
} else { } else {
*budget -= work_done; *budget -= work_done;
...@@ -2017,13 +2065,13 @@ static void sky2_hw_intr(struct sky2_hw *hw) ...@@ -2017,13 +2065,13 @@ static void sky2_hw_intr(struct sky2_hw *hw)
if (status & (Y2_IS_MST_ERR | Y2_IS_IRQ_STAT)) { if (status & (Y2_IS_MST_ERR | Y2_IS_IRQ_STAT)) {
u16 pci_err; u16 pci_err;
pci_read_config_word(hw->pdev, PCI_STATUS, &pci_err); pci_err = sky2_pci_read16(hw, PCI_STATUS);
if (net_ratelimit()) if (net_ratelimit())
printk(KERN_ERR PFX "%s: pci hw error (0x%x)\n", printk(KERN_ERR PFX "%s: pci hw error (0x%x)\n",
pci_name(hw->pdev), pci_err); pci_name(hw->pdev), pci_err);
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
pci_write_config_word(hw->pdev, PCI_STATUS, sky2_pci_write16(hw, PCI_STATUS,
pci_err | PCI_STATUS_ERROR_BITS); pci_err | PCI_STATUS_ERROR_BITS);
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
} }
...@@ -2032,7 +2080,7 @@ static void sky2_hw_intr(struct sky2_hw *hw) ...@@ -2032,7 +2080,7 @@ static void sky2_hw_intr(struct sky2_hw *hw)
/* PCI-Express uncorrectable Error occurred */ /* PCI-Express uncorrectable Error occurred */
u32 pex_err; u32 pex_err;
pci_read_config_dword(hw->pdev, PEX_UNC_ERR_STAT, &pex_err); pex_err = sky2_pci_read32(hw, PEX_UNC_ERR_STAT);
if (net_ratelimit()) if (net_ratelimit())
printk(KERN_ERR PFX "%s: pci express error (0x%x)\n", printk(KERN_ERR PFX "%s: pci express error (0x%x)\n",
...@@ -2040,7 +2088,7 @@ static void sky2_hw_intr(struct sky2_hw *hw) ...@@ -2040,7 +2088,7 @@ static void sky2_hw_intr(struct sky2_hw *hw)
/* clear the interrupt */ /* clear the interrupt */
sky2_write32(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); sky2_write32(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
pci_write_config_dword(hw->pdev, PEX_UNC_ERR_STAT, sky2_pci_write32(hw, PEX_UNC_ERR_STAT,
0xffffffffUL); 0xffffffffUL);
sky2_write32(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); sky2_write32(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
...@@ -2086,6 +2134,7 @@ static void sky2_phy_intr(struct sky2_hw *hw, unsigned port) ...@@ -2086,6 +2134,7 @@ static void sky2_phy_intr(struct sky2_hw *hw, unsigned port)
hw->intr_mask &= ~(port == 0 ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2); hw->intr_mask &= ~(port == 0 ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2);
sky2_write32(hw, B0_IMSK, hw->intr_mask); sky2_write32(hw, B0_IMSK, hw->intr_mask);
schedule_work(&sky2->phy_task); schedule_work(&sky2->phy_task);
} }
...@@ -2099,6 +2148,7 @@ static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs) ...@@ -2099,6 +2148,7 @@ static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs)
if (status == 0 || status == ~0) if (status == 0 || status == ~0)
return IRQ_NONE; return IRQ_NONE;
spin_lock(&hw->hw_lock);
if (status & Y2_IS_HW_ERR) if (status & Y2_IS_HW_ERR)
sky2_hw_intr(hw); sky2_hw_intr(hw);
...@@ -2127,7 +2177,7 @@ static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs) ...@@ -2127,7 +2177,7 @@ static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs)
sky2_write32(hw, B0_Y2_SP_ICR, 2); sky2_write32(hw, B0_Y2_SP_ICR, 2);
sky2_read32(hw, B0_IMSK); spin_unlock(&hw->hw_lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -2170,7 +2220,7 @@ static int sky2_reset(struct sky2_hw *hw) ...@@ -2170,7 +2220,7 @@ static int sky2_reset(struct sky2_hw *hw)
{ {
u16 status; u16 status;
u8 t8, pmd_type; u8 t8, pmd_type;
int i, err; int i;
sky2_write8(hw, B0_CTST, CS_RST_CLR); sky2_write8(hw, B0_CTST, CS_RST_CLR);
...@@ -2192,25 +2242,18 @@ static int sky2_reset(struct sky2_hw *hw) ...@@ -2192,25 +2242,18 @@ static int sky2_reset(struct sky2_hw *hw)
sky2_write8(hw, B0_CTST, CS_RST_CLR); sky2_write8(hw, B0_CTST, CS_RST_CLR);
/* clear PCI errors, if any */ /* clear PCI errors, if any */
err = pci_read_config_word(hw->pdev, PCI_STATUS, &status); status = sky2_pci_read16(hw, PCI_STATUS);
if (err)
goto pci_err;
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
err = pci_write_config_word(hw->pdev, PCI_STATUS, sky2_pci_write16(hw, PCI_STATUS, status | PCI_STATUS_ERROR_BITS);
status | PCI_STATUS_ERROR_BITS);
if (err)
goto pci_err;
sky2_write8(hw, B0_CTST, CS_MRST_CLR); sky2_write8(hw, B0_CTST, CS_MRST_CLR);
/* clear any PEX errors */ /* clear any PEX errors */
if (pci_find_capability(hw->pdev, PCI_CAP_ID_EXP)) { if (pci_find_capability(hw->pdev, PCI_CAP_ID_EXP))
err = pci_write_config_dword(hw->pdev, PEX_UNC_ERR_STAT, sky2_pci_write32(hw, PEX_UNC_ERR_STAT, 0xffffffffUL);
0xffffffffUL);
if (err)
goto pci_err;
}
pmd_type = sky2_read8(hw, B2_PMD_TYP); pmd_type = sky2_read8(hw, B2_PMD_TYP);
hw->copper = !(pmd_type == 'L' || pmd_type == 'S'); hw->copper = !(pmd_type == 'L' || pmd_type == 'S');
...@@ -2309,8 +2352,7 @@ static int sky2_reset(struct sky2_hw *hw) ...@@ -2309,8 +2352,7 @@ static int sky2_reset(struct sky2_hw *hw)
sky2_write8(hw, STAT_FIFO_ISR_WM, 16); sky2_write8(hw, STAT_FIFO_ISR_WM, 16);
sky2_write32(hw, STAT_TX_TIMER_INI, sky2_us2clk(hw, 1000)); sky2_write32(hw, STAT_TX_TIMER_INI, sky2_us2clk(hw, 1000));
sky2_write32(hw, STAT_LEV_TIMER_INI, sky2_us2clk(hw, 100)); sky2_write32(hw, STAT_ISR_TIMER_INI, sky2_us2clk(hw, 7));
sky2_write32(hw, STAT_ISR_TIMER_INI, sky2_us2clk(hw, 20));
} }
/* enable status unit */ /* enable status unit */
...@@ -2321,14 +2363,6 @@ static int sky2_reset(struct sky2_hw *hw) ...@@ -2321,14 +2363,6 @@ static int sky2_reset(struct sky2_hw *hw)
sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START); sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START);
return 0; return 0;
pci_err:
/* This is to catch a BIOS bug workaround where
* mmconfig table doesn't have other buses.
*/
printk(KERN_ERR PFX "%s: can't access PCI config space\n",
pci_name(hw->pdev));
return err;
} }
static u32 sky2_supported_modes(const struct sky2_hw *hw) static u32 sky2_supported_modes(const struct sky2_hw *hw)
...@@ -2852,11 +2886,11 @@ static int sky2_set_coalesce(struct net_device *dev, ...@@ -2852,11 +2886,11 @@ static int sky2_set_coalesce(struct net_device *dev,
(ecmd->rx_coalesce_usecs_irq < tmin || ecmd->rx_coalesce_usecs_irq > tmax)) (ecmd->rx_coalesce_usecs_irq < tmin || ecmd->rx_coalesce_usecs_irq > tmax))
return -EINVAL; return -EINVAL;
if (ecmd->tx_max_coalesced_frames > 0xffff) if (ecmd->tx_max_coalesced_frames >= TX_RING_SIZE-1)
return -EINVAL; return -EINVAL;
if (ecmd->rx_max_coalesced_frames > 0xff) if (ecmd->rx_max_coalesced_frames > RX_MAX_PENDING)
return -EINVAL; return -EINVAL;
if (ecmd->rx_max_coalesced_frames_irq > 0xff) if (ecmd->rx_max_coalesced_frames_irq >RX_MAX_PENDING)
return -EINVAL; return -EINVAL;
if (ecmd->tx_coalesce_usecs == 0) if (ecmd->tx_coalesce_usecs == 0)
...@@ -3198,17 +3232,6 @@ static int __devinit sky2_probe(struct pci_dev *pdev, ...@@ -3198,17 +3232,6 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
} }
} }
#ifdef __BIG_ENDIAN
/* byte swap descriptors in hardware */
{
u32 reg;
pci_read_config_dword(pdev, PCI_DEV_REG2, &reg);
reg |= PCI_REV_DESC;
pci_write_config_dword(pdev, PCI_DEV_REG2, reg);
}
#endif
err = -ENOMEM; err = -ENOMEM;
hw = kzalloc(sizeof(*hw), GFP_KERNEL); hw = kzalloc(sizeof(*hw), GFP_KERNEL);
if (!hw) { if (!hw) {
...@@ -3226,6 +3249,18 @@ static int __devinit sky2_probe(struct pci_dev *pdev, ...@@ -3226,6 +3249,18 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
goto err_out_free_hw; goto err_out_free_hw;
} }
hw->pm_cap = pm_cap; hw->pm_cap = pm_cap;
spin_lock_init(&hw->hw_lock);
#ifdef __BIG_ENDIAN
/* byte swap descriptors in hardware */
{
u32 reg;
reg = sky2_pci_read32(hw, PCI_DEV_REG2);
reg |= PCI_REV_DESC;
sky2_pci_write32(hw, PCI_DEV_REG2, reg);
}
#endif
/* ring for status responses */ /* ring for status responses */
hw->st_le = pci_alloc_consistent(hw->pdev, STATUS_LE_BYTES, hw->st_le = pci_alloc_consistent(hw->pdev, STATUS_LE_BYTES,
......
...@@ -5,14 +5,22 @@ ...@@ -5,14 +5,22 @@
#define _SKY2_H #define _SKY2_H
/* PCI config registers */ /* PCI config registers */
#define PCI_DEV_REG1 0x40 enum {
#define PCI_DEV_REG2 0x44 PCI_DEV_REG1 = 0x40,
#define PCI_DEV_STATUS 0x7c PCI_DEV_REG2 = 0x44,
#define PCI_OS_PCI_X (1<<26) PCI_DEV_STATUS = 0x7c,
PCI_DEV_REG3 = 0x80,
PCI_DEV_REG4 = 0x84,
PCI_DEV_REG5 = 0x88,
};
#define PEX_LNK_STAT 0xf2 enum {
#define PEX_UNC_ERR_STAT 0x104 PEX_DEV_CAP = 0xe4,
#define PEX_DEV_CTRL 0xe8 PEX_DEV_CTRL = 0xe8,
PEX_DEV_STA = 0xea,
PEX_LNK_STAT = 0xf2,
PEX_UNC_ERR_STAT= 0x104,
};
/* Yukon-2 */ /* Yukon-2 */
enum pci_dev_reg_1 { enum pci_dev_reg_1 {
...@@ -37,6 +45,25 @@ enum pci_dev_reg_2 { ...@@ -37,6 +45,25 @@ enum pci_dev_reg_2 {
PCI_USEDATA64 = 1<<0, /* Use 64Bit Data bus ext */ PCI_USEDATA64 = 1<<0, /* Use 64Bit Data bus ext */
}; };
/* PCI_OUR_REG_4 32 bit Our Register 4 (Yukon-ECU only) */
enum pci_dev_reg_4 {
/* (Link Training & Status State Machine) */
P_TIMER_VALUE_MSK = 0xffL<<16, /* Bit 23..16: Timer Value Mask */
/* (Active State Power Management) */
P_FORCE_ASPM_REQUEST = 1<<15, /* Force ASPM Request (A1 only) */
P_ASPM_GPHY_LINK_DOWN = 1<<14, /* GPHY Link Down (A1 only) */
P_ASPM_INT_FIFO_EMPTY = 1<<13, /* Internal FIFO Empty (A1 only) */
P_ASPM_CLKRUN_REQUEST = 1<<12, /* CLKRUN Request (A1 only) */
P_ASPM_FORCE_CLKREQ_ENA = 1<<4, /* Force CLKREQ Enable (A1b only) */
P_ASPM_CLKREQ_PAD_CTL = 1<<3, /* CLKREQ PAD Control (A1 only) */
P_ASPM_A1_MODE_SELECT = 1<<2, /* A1 Mode Select (A1 only) */
P_CLK_GATE_PEX_UNIT_ENA = 1<<1, /* Enable Gate PEX Unit Clock */
P_CLK_GATE_ROOT_COR_ENA = 1<<0, /* Enable Gate Root Core Clock */
P_ASPM_CONTROL_MSK = P_FORCE_ASPM_REQUEST | P_ASPM_GPHY_LINK_DOWN
| P_ASPM_CLKRUN_REQUEST | P_ASPM_INT_FIFO_EMPTY,
};
#define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \ #define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \
PCI_STATUS_SIG_SYSTEM_ERROR | \ PCI_STATUS_SIG_SYSTEM_ERROR | \
...@@ -507,6 +534,16 @@ enum { ...@@ -507,6 +534,16 @@ enum {
}; };
#define Q_ADDR(reg, offs) (B8_Q_REGS + (reg) + (offs)) #define Q_ADDR(reg, offs) (B8_Q_REGS + (reg) + (offs))
/* Q_F 32 bit Flag Register */
enum {
F_ALM_FULL = 1<<27, /* Rx FIFO: almost full */
F_EMPTY = 1<<27, /* Tx FIFO: empty flag */
F_FIFO_EOF = 1<<26, /* Tag (EOF Flag) bit in FIFO */
F_WM_REACHED = 1<<25, /* Watermark reached */
F_M_RX_RAM_DIS = 1<<24, /* MAC Rx RAM Read Port disable */
F_FIFO_LEVEL = 0x1fL<<16, /* Bit 23..16: # of Qwords in FIFO */
F_WATER_MARK = 0x0007ffL, /* Bit 10.. 0: Watermark */
};
/* Queue Prefetch Unit Offsets, use Y2_QADDR() to address (Yukon-2 only)*/ /* Queue Prefetch Unit Offsets, use Y2_QADDR() to address (Yukon-2 only)*/
enum { enum {
...@@ -909,10 +946,12 @@ enum { ...@@ -909,10 +946,12 @@ enum {
PHY_BCOM_ID1_C0 = 0x6044, PHY_BCOM_ID1_C0 = 0x6044,
PHY_BCOM_ID1_C5 = 0x6047, PHY_BCOM_ID1_C5 = 0x6047,
PHY_MARV_ID1_B0 = 0x0C23, /* Yukon (PHY 88E1011) */ PHY_MARV_ID1_B0 = 0x0C23, /* Yukon (PHY 88E1011) */
PHY_MARV_ID1_B2 = 0x0C25, /* Yukon-Plus (PHY 88E1011) */ PHY_MARV_ID1_B2 = 0x0C25, /* Yukon-Plus (PHY 88E1011) */
PHY_MARV_ID1_C2 = 0x0CC2, /* Yukon-EC (PHY 88E1111) */ PHY_MARV_ID1_C2 = 0x0CC2, /* Yukon-EC (PHY 88E1111) */
PHY_MARV_ID1_Y2 = 0x0C91, /* Yukon-2 (PHY 88E1112) */ PHY_MARV_ID1_Y2 = 0x0C91, /* Yukon-2 (PHY 88E1112) */
PHY_MARV_ID1_FE = 0x0C83, /* Yukon-FE (PHY 88E3082 Rev.A1) */
PHY_MARV_ID1_ECU= 0x0CB0, /* Yukon-ECU (PHY 88E1149 Rev.B2?) */
}; };
/* Advertisement register bits */ /* Advertisement register bits */
...@@ -1837,8 +1876,9 @@ struct sky2_port { ...@@ -1837,8 +1876,9 @@ struct sky2_port {
struct sky2_hw { struct sky2_hw {
void __iomem *regs; void __iomem *regs;
struct pci_dev *pdev; struct pci_dev *pdev;
u32 intr_mask;
struct net_device *dev[2]; struct net_device *dev[2];
spinlock_t hw_lock;
u32 intr_mask;
int pm_cap; int pm_cap;
int msi; int msi;
...@@ -1912,4 +1952,25 @@ static inline void gma_set_addr(struct sky2_hw *hw, unsigned port, unsigned reg, ...@@ -1912,4 +1952,25 @@ static inline void gma_set_addr(struct sky2_hw *hw, unsigned port, unsigned reg,
gma_write16(hw, port, reg+4,(u16) addr[2] | ((u16) addr[3] << 8)); gma_write16(hw, port, reg+4,(u16) addr[2] | ((u16) addr[3] << 8));
gma_write16(hw, port, reg+8,(u16) addr[4] | ((u16) addr[5] << 8)); gma_write16(hw, port, reg+8,(u16) addr[4] | ((u16) addr[5] << 8));
} }
/* PCI config space access */
static inline u32 sky2_pci_read32(const struct sky2_hw *hw, unsigned reg)
{
return sky2_read32(hw, Y2_CFG_SPC + reg);
}
static inline u16 sky2_pci_read16(const struct sky2_hw *hw, unsigned reg)
{
return sky2_read16(hw, Y2_CFG_SPC + reg);
}
static inline void sky2_pci_write32(struct sky2_hw *hw, unsigned reg, u32 val)
{
sky2_write32(hw, Y2_CFG_SPC + reg, val);
}
static inline void sky2_pci_write16(struct sky2_hw *hw, unsigned reg, u16 val)
{
sky2_write16(hw, Y2_CFG_SPC + reg, val);
}
#endif #endif
...@@ -536,6 +536,7 @@ static int __devinit TLan_probe1(struct pci_dev *pdev, ...@@ -536,6 +536,7 @@ static int __devinit TLan_probe1(struct pci_dev *pdev,
u16 device_id; u16 device_id;
int reg, rc = -ENODEV; int reg, rc = -ENODEV;
#ifdef CONFIG_PCI
if (pdev) { if (pdev) {
rc = pci_enable_device(pdev); rc = pci_enable_device(pdev);
if (rc) if (rc)
...@@ -547,6 +548,7 @@ static int __devinit TLan_probe1(struct pci_dev *pdev, ...@@ -547,6 +548,7 @@ static int __devinit TLan_probe1(struct pci_dev *pdev,
goto err_out; goto err_out;
} }
} }
#endif /* CONFIG_PCI */
dev = alloc_etherdev(sizeof(TLanPrivateInfo)); dev = alloc_etherdev(sizeof(TLanPrivateInfo));
if (dev == NULL) { if (dev == NULL) {
......
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