patch-2.4.27 linux-2.4.27/drivers/net/8139cp.c
Next file: linux-2.4.27/drivers/net/8139too.c
Previous file: linux-2.4.27/drivers/mtd/mtdchar.c
Back to the patch index
Back to the overall index
- Lines: 634
- Date:
2004-08-07 16:26:04.938358447 -0700
- Orig file:
linux-2.4.26/drivers/net/8139cp.c
- Orig date:
2004-02-18 05:36:31.000000000 -0800
diff -urN linux-2.4.26/drivers/net/8139cp.c linux-2.4.27/drivers/net/8139cp.c
@@ -1,6 +1,6 @@
/* 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_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 @@
#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 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 @@
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 @@
/* 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 @@
/* TODO: reset hardware */
}
-out:
- spin_unlock(&cp->lock);
+
return IRQ_HANDLED;
}
@@ -736,7 +745,7 @@
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 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)
{
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 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();
- 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 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 @@
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 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_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();
free_irq(dev->irq, dev);
+
cp_free_rings(cp);
return 0;
}
@@ -1204,8 +1215,9 @@
#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 @@
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 @@
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 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 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 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_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 @@
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 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_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 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;
}
@@ -1637,7 +1657,9 @@
if (!dev)
return -ENOMEM;
SET_MODULE_OWNER(dev);
- cp = dev->priv;
+ SET_NETDEV_DEV(dev, &pdev->dev);
+
+ cp = netdev_priv(dev);
cp->pdev = pdev;
cp->dev = dev;
cp->msg_enable = (debug < 0 ? CP_DEF_MSG_ENABLE : debug);
@@ -1662,12 +1684,6 @@
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;
@@ -1687,19 +1703,20 @@
!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;
}
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",
@@ -1740,6 +1757,9 @@
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);
@@ -1774,14 +1794,14 @@
err_out_disable:
pci_disable_device(pdev);
err_out_free:
- kfree(dev);
+ free_netdev(dev);
return rc;
}
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();
@@ -1792,7 +1812,7 @@
pci_clear_mwi(pdev);
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
- kfree(dev);
+ free_netdev(dev);
}
#ifdef CONFIG_PM
@@ -1803,7 +1823,7 @@
unsigned long flags;
dev = pci_get_drvdata (pdev);
- cp = dev->priv;
+ cp = netdev_priv(dev);
if (!dev || !netif_running (dev)) return 0;
@@ -1832,7 +1852,7 @@
struct cp_private *cp;
dev = pci_get_drvdata (pdev);
- cp = dev->priv;
+ cp = netdev_priv(dev);
netif_device_attach (dev);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)