Commit e0d3e322 authored by Jeff Garzik's avatar Jeff Garzik

Merge redhat.com:/spare/repo/netdev-2.6/8139cp

into redhat.com:/spare/repo/net-drivers-2.6
parents 4d72de23 93eb7437
/* 8139cp.c: A Linux PCI Ethernet driver for the RealTek 8139C+ chips. */
/*
Copyright 2001,2002 Jeff Garzik <jgarzik@pobox.com>
Copyright 2001-2004 Jeff Garzik <jgarzik@pobox.com>
Copyright (C) 2001, 2002 David S. Miller (davem@redhat.com) [tg3.c]
Copyright (C) 2000, 2001 David S. Miller (davem@redhat.com) [sungem.c]
......@@ -48,8 +48,8 @@
*/
#define DRV_NAME "8139cp"
#define DRV_VERSION "1.1"
#define DRV_RELDATE "Aug 30, 2003"
#define DRV_VERSION "1.2"
#define DRV_RELDATE "Mar 22, 2004"
#include <linux/config.h>
......@@ -69,6 +69,7 @@
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/cache.h>
#include <asm/io.h>
#include <asm/uaccess.h>
......@@ -334,36 +335,36 @@ struct cp_extra_stats {
};
struct cp_private {
unsigned tx_head;
unsigned tx_tail;
unsigned rx_tail;
void *regs;
struct net_device *dev;
spinlock_t lock;
u32 msg_enable;
struct pci_dev *pdev;
u32 rx_config;
u16 cpcmd;
struct net_device_stats net_stats;
struct cp_extra_stats cp_stats;
struct cp_dma_stats *nic_stats;
dma_addr_t nic_stats_dma;
unsigned rx_tail ____cacheline_aligned;
struct cp_desc *rx_ring;
struct cp_desc *tx_ring;
struct ring_info tx_skb[CP_TX_RING_SIZE];
struct ring_info rx_skb[CP_RX_RING_SIZE];
unsigned rx_buf_sz;
unsigned tx_head ____cacheline_aligned;
unsigned tx_tail;
struct cp_desc *tx_ring;
struct ring_info tx_skb[CP_TX_RING_SIZE];
dma_addr_t ring_dma;
#if CP_VLAN_TAG_USED
struct vlan_group *vlgrp;
#endif
u32 msg_enable;
struct net_device_stats net_stats;
struct cp_extra_stats cp_stats;
struct cp_dma_stats *nic_stats;
dma_addr_t nic_stats_dma;
struct pci_dev *pdev;
u32 rx_config;
u16 cpcmd;
unsigned int wol_enabled : 1; /* Is Wake-on-LAN enabled? */
u32 power_state[16];
......@@ -424,25 +425,27 @@ static struct {
#if CP_VLAN_TAG_USED
static void cp_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
{
struct cp_private *cp = dev->priv;
struct cp_private *cp = netdev_priv(dev);
unsigned long flags;
spin_lock_irq(&cp->lock);
spin_lock_irqsave(&cp->lock, flags);
cp->vlgrp = grp;
cp->cpcmd |= RxVlanOn;
cpw16(CpCmd, cp->cpcmd);
spin_unlock_irq(&cp->lock);
spin_unlock_irqrestore(&cp->lock, flags);
}
static void cp_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
{
struct cp_private *cp = dev->priv;
struct cp_private *cp = netdev_priv(dev);
unsigned long flags;
spin_lock_irq(&cp->lock);
spin_lock_irqsave(&cp->lock, flags);
cp->cpcmd &= ~RxVlanOn;
cpw16(CpCmd, cp->cpcmd);
if (cp->vlgrp)
cp->vlgrp->vlan_devices[vid] = NULL;
spin_unlock_irq(&cp->lock);
spin_unlock_irqrestore(&cp->lock, flags);
}
#endif /* CP_VLAN_TAG_USED */
......@@ -510,7 +513,7 @@ static inline unsigned int cp_rx_csum_ok (u32 status)
static int cp_rx_poll (struct net_device *dev, int *budget)
{
struct cp_private *cp = dev->priv;
struct cp_private *cp = netdev_priv(dev);
unsigned rx_tail = cp->rx_tail;
unsigned rx_work = dev->quota;
unsigned rx;
......@@ -630,9 +633,13 @@ static irqreturn_t
cp_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
{
struct net_device *dev = dev_instance;
struct cp_private *cp = dev->priv;
struct cp_private *cp;
u16 status;
if (unlikely(dev == NULL))
return IRQ_NONE;
cp = netdev_priv(dev);
status = cpr16(IntrStatus);
if (!status || (status == 0xFFFF))
return IRQ_NONE;
......@@ -648,20 +655,23 @@ cp_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
/* close possible race's with dev_close */
if (unlikely(!netif_running(dev))) {
cpw16(IntrMask, 0);
goto out;
spin_unlock(&cp->lock);
return IRQ_HANDLED;
}
if (status & (RxOK | RxErr | RxEmpty | RxFIFOOvr)) {
if (status & (RxOK | RxErr | RxEmpty | RxFIFOOvr))
if (netif_rx_schedule_prep(dev)) {
cpw16_f(IntrMask, cp_norx_intr_mask);
__netif_rx_schedule(dev);
}
}
if (status & (TxOK | TxErr | TxEmpty | SWInt))
cp_tx(cp);
if (status & LinkChg)
mii_check_media(&cp->mii_if, netif_msg_link(cp), FALSE);
spin_unlock(&cp->lock);
if (status & PciErr) {
u16 pci_status;
......@@ -672,8 +682,7 @@ cp_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
/* TODO: reset hardware */
}
out:
spin_unlock(&cp->lock);
return IRQ_HANDLED;
}
......@@ -736,7 +745,7 @@ static void cp_tx (struct cp_private *cp)
static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
{
struct cp_private *cp = dev->priv;
struct cp_private *cp = netdev_priv(dev);
unsigned entry;
u32 eor;
#if CP_VLAN_TAG_USED
......@@ -894,7 +903,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
static void __cp_set_rx_mode (struct net_device *dev)
{
struct cp_private *cp = dev->priv;
struct cp_private *cp = netdev_priv(dev);
u32 mc_filter[2]; /* Multicast hash filter */
int i, rx_mode;
u32 tmp;
......@@ -939,7 +948,7 @@ static void __cp_set_rx_mode (struct net_device *dev)
static void cp_set_rx_mode (struct net_device *dev)
{
unsigned long flags;
struct cp_private *cp = dev->priv;
struct cp_private *cp = netdev_priv(dev);
spin_lock_irqsave (&cp->lock, flags);
__cp_set_rx_mode(dev);
......@@ -955,35 +964,28 @@ static void __cp_get_stats(struct cp_private *cp)
static struct net_device_stats *cp_get_stats(struct net_device *dev)
{
struct cp_private *cp = dev->priv;
struct cp_private *cp = netdev_priv(dev);
unsigned long flags;
/* The chip only need report frame silently dropped. */
spin_lock_irq(&cp->lock);
spin_lock_irqsave(&cp->lock, flags);
if (netif_running(dev) && netif_device_present(dev))
__cp_get_stats(cp);
spin_unlock_irq(&cp->lock);
spin_unlock_irqrestore(&cp->lock, flags);
return &cp->net_stats;
}
static void cp_stop_hw (struct cp_private *cp)
{
struct net_device *dev = cp->dev;
cpw16(IntrStatus, ~(cpr16(IntrStatus)));
cpw16_f(IntrMask, 0);
cpw8(Cmd, 0);
cpw16_f(CpCmd, 0);
cpw16(IntrStatus, ~(cpr16(IntrStatus)));
synchronize_irq(dev->irq);
udelay(10);
cpw16_f(IntrStatus, ~(cpr16(IntrStatus)));
cp->rx_tail = 0;
cp->tx_head = cp->tx_tail = 0;
(void) dev; /* avoid compiler warning when synchronize_irq()
* disappears during !CONFIG_SMP
*/
}
static void cp_reset_hw (struct cp_private *cp)
......@@ -1012,6 +1014,7 @@ static inline void cp_start_hw (struct cp_private *cp)
static void cp_init_hw (struct cp_private *cp)
{
struct net_device *dev = cp->dev;
dma_addr_t ring_dma;
cp_reset_hw(cp);
......@@ -1037,10 +1040,13 @@ static void cp_init_hw (struct cp_private *cp)
cpw32_f(HiTxRingAddr, 0);
cpw32_f(HiTxRingAddr + 4, 0);
cpw32_f(RxRingAddr, cp->ring_dma);
cpw32_f(RxRingAddr + 4, 0); /* FIXME: 64-bit PCI */
cpw32_f(TxRingAddr, cp->ring_dma + (sizeof(struct cp_desc) * CP_RX_RING_SIZE));
cpw32_f(TxRingAddr + 4, 0); /* FIXME: 64-bit PCI */
ring_dma = cp->ring_dma;
cpw32_f(RxRingAddr, ring_dma & 0xffffffff);
cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16);
ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE;
cpw32_f(TxRingAddr, ring_dma & 0xffffffff);
cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16);
cpw16(MultiIntr, 0);
......@@ -1154,7 +1160,7 @@ static void cp_free_rings (struct cp_private *cp)
static int cp_open (struct net_device *dev)
{
struct cp_private *cp = dev->priv;
struct cp_private *cp = netdev_priv(dev);
int rc;
if (netif_msg_ifup(cp))
......@@ -1184,19 +1190,24 @@ static int cp_open (struct net_device *dev)
static int cp_close (struct net_device *dev)
{
struct cp_private *cp = dev->priv;
struct cp_private *cp = netdev_priv(dev);
unsigned long flags;
if (netif_msg_ifdown(cp))
printk(KERN_DEBUG "%s: disabling interface\n", dev->name);
spin_lock_irqsave(&cp->lock, flags);
netif_stop_queue(dev);
netif_carrier_off(dev);
spin_lock_irq(&cp->lock);
cp_stop_hw(cp);
spin_unlock_irq(&cp->lock);
spin_unlock_irqrestore(&cp->lock, flags);
synchronize_irq(dev->irq);
free_irq(dev->irq, dev);
cp_free_rings(cp);
return 0;
}
......@@ -1204,8 +1215,9 @@ static int cp_close (struct net_device *dev)
#ifdef BROKEN
static int cp_change_mtu(struct net_device *dev, int new_mtu)
{
struct cp_private *cp = dev->priv;
struct cp_private *cp = netdev_priv(dev);
int rc;
unsigned long flags;
/* check for invalid MTU, according to hardware limits */
if (new_mtu < CP_MIN_MTU || new_mtu > CP_MAX_MTU)
......@@ -1218,7 +1230,7 @@ static int cp_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
spin_lock_irq(&cp->lock);
spin_lock_irqsave(&cp->lock, flags);
cp_stop_hw(cp); /* stop h/w and free rings */
cp_clean_rings(cp);
......@@ -1229,7 +1241,7 @@ static int cp_change_mtu(struct net_device *dev, int new_mtu)
rc = cp_init_rings(cp); /* realloc and restart h/w */
cp_start_hw(cp);
spin_unlock_irq(&cp->lock);
spin_unlock_irqrestore(&cp->lock, flags);
return rc;
}
......@@ -1248,7 +1260,7 @@ static char mii_2_8139_map[8] = {
static int mdio_read(struct net_device *dev, int phy_id, int location)
{
struct cp_private *cp = dev->priv;
struct cp_private *cp = netdev_priv(dev);
return location < 8 && mii_2_8139_map[location] ?
readw(cp->regs + mii_2_8139_map[location]) : 0;
......@@ -1258,7 +1270,7 @@ static int mdio_read(struct net_device *dev, int phy_id, int location)
static void mdio_write(struct net_device *dev, int phy_id, int location,
int value)
{
struct cp_private *cp = dev->priv;
struct cp_private *cp = netdev_priv(dev);
if (location == 0) {
cpw8(Cfg9346, Cfg9346_Unlock);
......@@ -1326,7 +1338,7 @@ static void netdev_get_wol (struct cp_private *cp,
static void cp_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *info)
{
struct cp_private *cp = dev->priv;
struct cp_private *cp = netdev_priv(dev);
strcpy (info->driver, DRV_NAME);
strcpy (info->version, DRV_VERSION);
......@@ -1345,55 +1357,57 @@ static int cp_get_stats_count (struct net_device *dev)
static int cp_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct cp_private *cp = dev->priv;
struct cp_private *cp = netdev_priv(dev);
int rc;
unsigned long flags;
spin_lock_irq(&cp->lock);
spin_lock_irqsave(&cp->lock, flags);
rc = mii_ethtool_gset(&cp->mii_if, cmd);
spin_unlock_irq(&cp->lock);
spin_unlock_irqrestore(&cp->lock, flags);
return rc;
}
static int cp_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct cp_private *cp = dev->priv;
struct cp_private *cp = netdev_priv(dev);
int rc;
unsigned long flags;
spin_lock_irq(&cp->lock);
spin_lock_irqsave(&cp->lock, flags);
rc = mii_ethtool_sset(&cp->mii_if, cmd);
spin_unlock_irq(&cp->lock);
spin_unlock_irqrestore(&cp->lock, flags);
return rc;
}
static int cp_nway_reset(struct net_device *dev)
{
struct cp_private *cp = dev->priv;
struct cp_private *cp = netdev_priv(dev);
return mii_nway_restart(&cp->mii_if);
}
static u32 cp_get_msglevel(struct net_device *dev)
{
struct cp_private *cp = dev->priv;
struct cp_private *cp = netdev_priv(dev);
return cp->msg_enable;
}
static void cp_set_msglevel(struct net_device *dev, u32 value)
{
struct cp_private *cp = dev->priv;
struct cp_private *cp = netdev_priv(dev);
cp->msg_enable = value;
}
static u32 cp_get_rx_csum(struct net_device *dev)
{
struct cp_private *cp = dev->priv;
struct cp_private *cp = netdev_priv(dev);
return (cpr16(CpCmd) & RxChkSum) ? 1 : 0;
}
static int cp_set_rx_csum(struct net_device *dev, u32 data)
{
struct cp_private *cp = dev->priv;
struct cp_private *cp = netdev_priv(dev);
u16 cmd = cp->cpcmd, newcmd;
newcmd = cmd;
......@@ -1404,10 +1418,12 @@ static int cp_set_rx_csum(struct net_device *dev, u32 data)
newcmd &= ~RxChkSum;
if (newcmd != cmd) {
spin_lock_irq(&cp->lock);
unsigned long flags;
spin_lock_irqsave(&cp->lock, flags);
cp->cpcmd = newcmd;
cpw16_f(CpCmd, newcmd);
spin_unlock_irq(&cp->lock);
spin_unlock_irqrestore(&cp->lock, flags);
}
return 0;
......@@ -1416,35 +1432,38 @@ static int cp_set_rx_csum(struct net_device *dev, u32 data)
static void cp_get_regs(struct net_device *dev, struct ethtool_regs *regs,
void *p)
{
struct cp_private *cp = dev->priv;
struct cp_private *cp = netdev_priv(dev);
unsigned long flags;
if (regs->len < CP_REGS_SIZE)
return /* -EINVAL */;
regs->version = CP_REGS_VER;
spin_lock_irq(&cp->lock);
spin_lock_irqsave(&cp->lock, flags);
memcpy_fromio(p, cp->regs, CP_REGS_SIZE);
spin_unlock_irq(&cp->lock);
spin_unlock_irqrestore(&cp->lock, flags);
}
static void cp_get_wol (struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct cp_private *cp = dev->priv;
struct cp_private *cp = netdev_priv(dev);
unsigned long flags;
spin_lock_irq (&cp->lock);
spin_lock_irqsave (&cp->lock, flags);
netdev_get_wol (cp, wol);
spin_unlock_irq (&cp->lock);
spin_unlock_irqrestore (&cp->lock, flags);
}
static int cp_set_wol (struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct cp_private *cp = dev->priv;
struct cp_private *cp = netdev_priv(dev);
unsigned long flags;
int rc;
spin_lock_irq (&cp->lock);
spin_lock_irqsave (&cp->lock, flags);
rc = netdev_set_wol (cp, wol);
spin_unlock_irq (&cp->lock);
spin_unlock_irqrestore (&cp->lock, flags);
return rc;
}
......@@ -1464,13 +1483,13 @@ static void cp_get_strings (struct net_device *dev, u32 stringset, u8 *buf)
static void cp_get_ethtool_stats (struct net_device *dev,
struct ethtool_stats *estats, u64 *tmp_stats)
{
struct cp_private *cp = dev->priv;
struct cp_private *cp = netdev_priv(dev);
unsigned int work = 100;
int i;
/* begin NIC statistics dump */
cpw32(StatsAddr + 4, 0); /* FIXME: 64-bit PCI */
cpw32(StatsAddr, cp->nic_stats_dma | DumpStats);
cpw32(StatsAddr + 4, (cp->nic_stats_dma >> 16) >> 16);
cpw32(StatsAddr, (cp->nic_stats_dma & 0xffffffff) | DumpStats);
cpr32(StatsAddr);
while (work-- > 0) {
......@@ -1526,16 +1545,17 @@ static struct ethtool_ops cp_ethtool_ops = {
static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
{
struct cp_private *cp = dev->priv;
struct cp_private *cp = netdev_priv(dev);
struct mii_ioctl_data *mii = (struct mii_ioctl_data *) &rq->ifr_data;
int rc;
unsigned long flags;
if (!netif_running(dev))
return -EINVAL;
spin_lock_irq(&cp->lock);
spin_lock_irqsave(&cp->lock, flags);
rc = generic_mii_ioctl(&cp->mii_if, mii, cmd, NULL);
spin_unlock_irq(&cp->lock);
spin_unlock_irqrestore(&cp->lock, flags);
return rc;
}
......@@ -1639,7 +1659,7 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, &pdev->dev);
cp = dev->priv;
cp = netdev_priv(dev);
cp->pdev = pdev;
cp->dev = dev;
cp->msg_enable = (debug < 0 ? CP_DEF_MSG_ENABLE : debug);
......@@ -1664,12 +1684,6 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc)
goto err_out_mwi;
if (pdev->irq < 2) {
rc = -EIO;
printk(KERN_ERR PFX "invalid irq (%d) for pci dev %s\n",
pdev->irq, pci_name(pdev));
goto err_out_res;
}
pciaddr = pci_resource_start(pdev, 1);
if (!pciaddr) {
rc = -EIO;
......@@ -1686,22 +1700,30 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
/* Configure DMA attributes. */
if ((sizeof(dma_addr_t) > 32) &&
!pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL) &&
!pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) {
pci_using_dac = 1;
} else {
pci_using_dac = 0;
rc = pci_set_dma_mask(pdev, 0xffffffffULL);
if (rc) {
printk(KERN_ERR PFX "No usable DMA configuration, "
"aborting.\n");
goto err_out_res;
}
pci_using_dac = 0;
rc = pci_set_consistent_dma_mask(pdev, 0xffffffffULL);
if (rc) {
printk(KERN_ERR PFX "No usable consistent DMA configuration, "
"aborting.\n");
goto err_out_res;
}
}
cp->cpcmd = (pci_using_dac ? PCIDAC : 0) |
PCIMulRW | RxChkSum | CpRxOn | CpTxOn;
regs = ioremap_nocache(pciaddr, CP_REGS_SIZE);
regs = ioremap(pciaddr, CP_REGS_SIZE);
if (!regs) {
rc = -EIO;
printk(KERN_ERR PFX "Cannot map PCI MMIO (%lx@%lx) on pci dev %s\n",
......@@ -1742,6 +1764,9 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
dev->vlan_rx_kill_vid = cp_vlan_rx_kill_vid;
#endif
if (pci_using_dac)
dev->features |= NETIF_F_HIGHDMA;
dev->irq = pdev->irq;
rc = register_netdev(dev);
......@@ -1783,7 +1808,7 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
static void cp_remove_one (struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct cp_private *cp = dev->priv;
struct cp_private *cp = netdev_priv(dev);
if (!dev)
BUG();
......@@ -1805,7 +1830,7 @@ static int cp_suspend (struct pci_dev *pdev, u32 state)
unsigned long flags;
dev = pci_get_drvdata (pdev);
cp = dev->priv;
cp = netdev_priv(dev);
if (!dev || !netif_running (dev)) return 0;
......@@ -1834,7 +1859,7 @@ static int cp_resume (struct pci_dev *pdev)
struct cp_private *cp;
dev = pci_get_drvdata (pdev);
cp = dev->priv;
cp = netdev_priv(dev);
netif_device_attach (dev);
......
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