Commit 62c6cb13 authored by Jeff Garzik's avatar Jeff Garzik

Merge redhat.com:/spare/repo/netdev-2.6/pcnet32

into redhat.com:/spare/repo/net-drivers-2.6
parents 0f300cbf 3893fcd9
...@@ -22,8 +22,8 @@ ...@@ -22,8 +22,8 @@
*************************************************************************/ *************************************************************************/
#define DRV_NAME "pcnet32" #define DRV_NAME "pcnet32"
#define DRV_VERSION "1.28" #define DRV_VERSION "1.29"
#define DRV_RELDATE "02.20.2004" #define DRV_RELDATE "04.06.2004"
#define PFX DRV_NAME ": " #define PFX DRV_NAME ": "
static const char *version = static const char *version =
...@@ -102,6 +102,7 @@ static int rx_copybreak = 200; ...@@ -102,6 +102,7 @@ static int rx_copybreak = 200;
#define PCNET32_DMA_MASK 0xffffffff #define PCNET32_DMA_MASK 0xffffffff
#define PCNET32_WATCHDOG_TIMEOUT (jiffies + (2 * HZ)) #define PCNET32_WATCHDOG_TIMEOUT (jiffies + (2 * HZ))
#define PCNET32_BLINK_TIMEOUT (jiffies + (HZ/4))
/* /*
* table to translate option values from tulip * table to translate option values from tulip
...@@ -232,6 +233,8 @@ static int full_duplex[MAX_UNITS]; ...@@ -232,6 +233,8 @@ static int full_duplex[MAX_UNITS];
* length errors, and transmit hangs. Cleans up after errors in open. * length errors, and transmit hangs. Cleans up after errors in open.
* Jim Lewis <jklewis@us.ibm.com> added ethernet loopback test. * Jim Lewis <jklewis@us.ibm.com> added ethernet loopback test.
* Thomas Munck Steenholdt <tmus@tmus.dk> non-mii ioctl corrections. * Thomas Munck Steenholdt <tmus@tmus.dk> non-mii ioctl corrections.
* v1.29 6 Apr 2004 Jim Lewis <jklewis@us.ibm.com> added physical
* identification code (blink led's).
*/ */
...@@ -342,6 +345,7 @@ struct pcnet32_private { ...@@ -342,6 +345,7 @@ struct pcnet32_private {
struct net_device *next; struct net_device *next;
struct mii_if_info mii_if; struct mii_if_info mii_if;
struct timer_list watchdog_timer; struct timer_list watchdog_timer;
struct timer_list blink_timer;
u32 msg_enable; /* debug message level */ u32 msg_enable; /* debug message level */
}; };
...@@ -356,6 +360,7 @@ static void pcnet32_tx_timeout (struct net_device *dev); ...@@ -356,6 +360,7 @@ static void pcnet32_tx_timeout (struct net_device *dev);
static irqreturn_t pcnet32_interrupt(int, void *, struct pt_regs *); static irqreturn_t pcnet32_interrupt(int, void *, struct pt_regs *);
static int pcnet32_close(struct net_device *); static int pcnet32_close(struct net_device *);
static struct net_device_stats *pcnet32_get_stats(struct net_device *); static struct net_device_stats *pcnet32_get_stats(struct net_device *);
static void pcnet32_load_multicast(struct net_device *dev);
static void pcnet32_set_multicast_list(struct net_device *); static void pcnet32_set_multicast_list(struct net_device *);
static int pcnet32_ioctl(struct net_device *, struct ifreq *, int); static int pcnet32_ioctl(struct net_device *, struct ifreq *, int);
static void pcnet32_watchdog(struct net_device *); static void pcnet32_watchdog(struct net_device *);
...@@ -365,6 +370,8 @@ static void pcnet32_restart(struct net_device *dev, unsigned int csr0_bits); ...@@ -365,6 +370,8 @@ static void pcnet32_restart(struct net_device *dev, unsigned int csr0_bits);
static void pcnet32_ethtool_test(struct net_device *dev, static void pcnet32_ethtool_test(struct net_device *dev,
struct ethtool_test *eth_test, u64 *data); struct ethtool_test *eth_test, u64 *data);
static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1); static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1);
static int pcnet32_phys_id(struct net_device *dev, u32 data);
static void pcnet32_led_blink_callback(struct net_device *dev);
enum pci_flags_bit { enum pci_flags_bit {
PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4, PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
...@@ -611,7 +618,7 @@ static void pcnet32_ethtool_test(struct net_device *dev, ...@@ -611,7 +618,7 @@ static void pcnet32_ethtool_test(struct net_device *dev,
test->flags |= ETH_TEST_FL_FAILED; test->flags |= ETH_TEST_FL_FAILED;
} else if (netif_msg_hw(lp)) } else if (netif_msg_hw(lp))
printk(KERN_DEBUG "%s: Loopback test passed.\n", dev->name); printk(KERN_DEBUG "%s: Loopback test passed.\n", dev->name);
} else } else if (netif_msg_hw(lp))
printk(KERN_DEBUG "%s: No tests to run (specify 'Offline' on ethtool).", dev->name); printk(KERN_DEBUG "%s: No tests to run (specify 'Offline' on ethtool).", dev->name);
} /* end pcnet32_ethtool_test */ } /* end pcnet32_ethtool_test */
...@@ -621,34 +628,40 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1) ...@@ -621,34 +628,40 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1)
struct pcnet32_access *a = &lp->a; /* access to registers */ struct pcnet32_access *a = &lp->a; /* access to registers */
ulong ioaddr = dev->base_addr; /* card base I/O address */ ulong ioaddr = dev->base_addr; /* card base I/O address */
struct sk_buff *skb; /* sk buff */ struct sk_buff *skb; /* sk buff */
int x, y, i; /* counters */ int x, i; /* counters */
int numbuffs = 4; /* number of TX/RX buffers and descs */ int numbuffs = 4; /* number of TX/RX buffers and descs */
u16 status = 0x8300; /* TX ring status */ u16 status = 0x8300; /* TX ring status */
u16 teststatus; /* test of ring status */
int rc; /* return code */ int rc; /* return code */
int size; /* size of packets */ int size; /* size of packets */
unsigned char *packet; /* source packet data */ unsigned char *packet; /* source packet data */
static int data_len = 60; /* length of source packets */ static int data_len = 60; /* length of source packets */
unsigned long flags; unsigned long flags;
unsigned long ticks;
*data1 = 1; /* status of test, default to fail */ *data1 = 1; /* status of test, default to fail */
rc = 1; /* default to fail */ rc = 1; /* default to fail */
if (netif_running(dev))
pcnet32_close(dev);
spin_lock_irqsave(&lp->lock, flags); spin_lock_irqsave(&lp->lock, flags);
lp->a.write_csr(ioaddr, 0, 0x7904);
del_timer_sync(&lp->watchdog_timer); /* Reset the PCNET32 */
lp->a.reset (ioaddr);
netif_stop_queue(dev); /* switch pcnet32 to 32bit mode */
lp->a.write_bcr (ioaddr, 20, 2);
lp->init_block.mode = le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7);
lp->init_block.filter[0] = 0;
lp->init_block.filter[1] = 0;
/* purge & init rings but don't actually restart */ /* purge & init rings but don't actually restart */
pcnet32_restart(dev, 0x0000); pcnet32_restart(dev, 0x0000);
lp->a.write_csr(ioaddr, 0, 0x0004); /* Set STOP bit */ lp->a.write_csr(ioaddr, 0, 0x0004); /* Set STOP bit */
x = a->read_bcr(ioaddr, 32); /* set internal loopback in BSR32 */
x = x | 0x00000002;
a->write_bcr(ioaddr, 32, x);
/* Initialize Transmit buffers. */ /* Initialize Transmit buffers. */
size = data_len + 15; size = data_len + 15;
for (x=0; x<numbuffs; x++) { for (x=0; x<numbuffs; x++) {
...@@ -662,19 +675,21 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1) ...@@ -662,19 +675,21 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1)
skb_put(skb, size); /* create space for data */ skb_put(skb, size); /* create space for data */
lp->tx_skbuff[x] = skb; lp->tx_skbuff[x] = skb;
lp->tx_ring[x].length = le16_to_cpu(-skb->len); lp->tx_ring[x].length = le16_to_cpu(-skb->len);
lp->tx_ring[x].misc = 0x00000000; lp->tx_ring[x].misc = 0;
/* put DA and SA into the skb */ /* put DA and SA into the skb */
for (i=0; i<12; i++) for (i=0; i<6; i++)
*packet++ = 0xff; *packet++ = dev->dev_addr[i];
for (i=0; i<6; i++)
*packet++ = dev->dev_addr[i];
/* type */ /* type */
*packet++ = 0x08; *packet++ = 0x08;
*packet++ = 0x06; *packet++ = 0x06;
/* packet number */ /* packet number */
*packet++ = x; *packet++ = x;
/* fill packet with data */ /* fill packet with data */
for (y=0; y<data_len; y++) for (i=0; i<data_len; i++)
*packet++ = y; *packet++ = i;
lp->tx_dma_addr[x] = pci_map_single(lp->pci_dev, skb->data, lp->tx_dma_addr[x] = pci_map_single(lp->pci_dev, skb->data,
skb->len, PCI_DMA_TODEVICE); skb->len, PCI_DMA_TODEVICE);
...@@ -684,20 +699,41 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1) ...@@ -684,20 +699,41 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1)
} }
} }
lp->a.write_csr(ioaddr, 0, 0x0002); /* Set STRT bit */ x = a->read_bcr(ioaddr, 32); /* set internal loopback in BSR32 */
spin_unlock_irqrestore(&lp->lock, flags); x = x | 0x0002;
a->write_bcr(ioaddr, 32, x);
lp->a.write_csr (ioaddr, 15, 0x0044); /* set int loopback in CSR15 */
mdelay(50); /* wait a bit */ teststatus = le16_to_cpu(0x8000);
lp->a.write_csr(ioaddr, 0, 0x0002); /* Set STRT bit */
/* Check status of descriptors */
for (x=0; x<numbuffs; x++) {
ticks = 0;
rmb();
while ((lp->rx_ring[x].status & teststatus) && (ticks < 200)) {
spin_unlock_irqrestore(&lp->lock, flags);
mdelay(1);
spin_lock_irqsave(&lp->lock, flags); spin_lock_irqsave(&lp->lock, flags);
lp->a.write_csr(ioaddr, 0, 0x0004); /* Set STOP bit */ rmb();
ticks++;
}
if (ticks == 200) {
if (netif_msg_hw(lp))
printk("%s: Desc %d failed to reset!\n",dev->name,x);
break;
}
}
lp->a.write_csr(ioaddr, 0, 0x0004); /* Set STOP bit */
wmb();
if (netif_msg_hw(lp) && netif_msg_pktdata(lp)) { if (netif_msg_hw(lp) && netif_msg_pktdata(lp)) {
printk(KERN_DEBUG "%s: RX loopback packets:\n", dev->name); printk(KERN_DEBUG "%s: RX loopback packets:\n", dev->name);
for (x=0; x<numbuffs; x++) { for (x=0; x<numbuffs; x++) {
printk(KERN_DEBUG "%s: Packet %d:\n", dev->name, x); printk(KERN_DEBUG "%s: Packet %d:\n", dev->name, x);
skb=lp->rx_skbuff[x]; skb = lp->rx_skbuff[x];
for (i=0; i<size; i++) { for (i=0; i<size; i++) {
printk("%02x ", *(skb->data+i)); printk("%02x ", *(skb->data+i));
} }
...@@ -730,21 +766,76 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1) ...@@ -730,21 +766,76 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1)
a->write_csr(ioaddr, 15, (x & ~0x0044)); /* reset bits 6 and 2 */ a->write_csr(ioaddr, 15, (x & ~0x0044)); /* reset bits 6 and 2 */
x = a->read_bcr(ioaddr, 32); /* reset internal loopback */ x = a->read_bcr(ioaddr, 32); /* reset internal loopback */
x = x & ~0x00000002; x = x & ~0x0002;
a->write_bcr(ioaddr, 32, x); a->write_bcr(ioaddr, 32, x);
pcnet32_restart(dev, 0x0042); /* resume normal operation */ spin_unlock_irqrestore(&lp->lock, flags);
netif_wake_queue(dev); if (netif_running(dev)) {
pcnet32_open(dev);
} else {
lp->a.write_bcr (ioaddr, 20, 4); /* return to 16bit mode */
}
mod_timer(&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT); return(rc);
} /* end pcnet32_loopback_test */
/* Clear interrupts, and set interrupt enable. */ static void pcnet32_led_blink_callback(struct net_device *dev)
lp->a.write_csr(ioaddr, 0, 0x7940); {
struct pcnet32_private *lp = dev->priv;
struct pcnet32_access *a = &lp->a;
ulong ioaddr = dev->base_addr;
unsigned long flags;
int i;
spin_lock_irqsave(&lp->lock, flags);
for (i=4; i<8; i++) {
a->write_bcr(ioaddr, i, a->read_bcr(ioaddr, i) ^ 0x4000);
}
spin_unlock_irqrestore(&lp->lock, flags); spin_unlock_irqrestore(&lp->lock, flags);
return(rc); mod_timer(&lp->blink_timer, PCNET32_BLINK_TIMEOUT);
} /* end pcnet32_loopback_test */ }
static int pcnet32_phys_id(struct net_device *dev, u32 data)
{
struct pcnet32_private *lp = dev->priv;
struct pcnet32_access *a = &lp->a;
ulong ioaddr = dev->base_addr;
unsigned long flags;
int i, regs[4];
if (!lp->blink_timer.function) {
init_timer(&lp->blink_timer);
lp->blink_timer.function = (void *) pcnet32_led_blink_callback;
lp->blink_timer.data = (unsigned long) dev;
}
/* Save the current value of the bcrs */
spin_lock_irqsave(&lp->lock, flags);
for (i=4; i<8; i++) {
regs[i-4] = a->read_bcr(ioaddr, i);
}
spin_unlock_irqrestore(&lp->lock, flags);
mod_timer(&lp->blink_timer, jiffies);
set_current_state(TASK_INTERRUPTIBLE);
if ((!data) || (data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)))
data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
schedule_timeout(data * HZ);
del_timer_sync(&lp->blink_timer);
/* Restore the original value of the bcrs */
spin_lock_irqsave(&lp->lock, flags);
for (i=4; i<8; i++) {
a->write_bcr(ioaddr, i, regs[i-4]);
}
spin_unlock_irqrestore(&lp->lock, flags);
return 0;
}
static struct ethtool_ops pcnet32_ethtool_ops = { static struct ethtool_ops pcnet32_ethtool_ops = {
.get_settings = pcnet32_get_settings, .get_settings = pcnet32_get_settings,
...@@ -761,6 +852,7 @@ static struct ethtool_ops pcnet32_ethtool_ops = { ...@@ -761,6 +852,7 @@ static struct ethtool_ops pcnet32_ethtool_ops = {
.get_strings = pcnet32_get_strings, .get_strings = pcnet32_get_strings,
.self_test_count = pcnet32_self_test_count, .self_test_count = pcnet32_self_test_count,
.self_test = pcnet32_ethtool_test, .self_test = pcnet32_ethtool_test,
.phys_id = pcnet32_phys_id,
}; };
/* only probes for non-PCI devices, the rest are handled by /* only probes for non-PCI devices, the rest are handled by
...@@ -793,6 +885,7 @@ pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -793,6 +885,7 @@ pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent)
err = pci_enable_device(pdev); err = pci_enable_device(pdev);
if (err < 0) { if (err < 0) {
if (pcnet32_debug & NETIF_MSG_PROBE)
printk(KERN_ERR PFX "failed to enable device -- err=%d\n", err); printk(KERN_ERR PFX "failed to enable device -- err=%d\n", err);
return err; return err;
} }
...@@ -800,15 +893,18 @@ pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -800,15 +893,18 @@ pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent)
ioaddr = pci_resource_start (pdev, 0); ioaddr = pci_resource_start (pdev, 0);
if (!ioaddr) { if (!ioaddr) {
if (pcnet32_debug & NETIF_MSG_PROBE)
printk (KERN_ERR PFX "card has no PCI IO resources, aborting\n"); printk (KERN_ERR PFX "card has no PCI IO resources, aborting\n");
return -ENODEV; return -ENODEV;
} }
if (!pci_dma_supported(pdev, PCNET32_DMA_MASK)) { if (!pci_dma_supported(pdev, PCNET32_DMA_MASK)) {
if (pcnet32_debug & NETIF_MSG_PROBE)
printk(KERN_ERR PFX "architecture does not support 32bit PCI busmaster DMA\n"); printk(KERN_ERR PFX "architecture does not support 32bit PCI busmaster DMA\n");
return -ENODEV; return -ENODEV;
} }
if (request_region(ioaddr, PCNET32_TOTAL_SIZE, "pcnet32_probe_pci") == NULL) { if (request_region(ioaddr, PCNET32_TOTAL_SIZE, "pcnet32_probe_pci") == NULL) {
if (pcnet32_debug & NETIF_MSG_PROBE)
printk(KERN_ERR PFX "io address range already allocated\n"); printk(KERN_ERR PFX "io address range already allocated\n");
return -EBUSY; return -EBUSY;
} }
...@@ -851,9 +947,10 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, ...@@ -851,9 +947,10 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
} }
chip_version = a->read_csr(ioaddr, 88) | (a->read_csr(ioaddr,89) << 16); chip_version = a->read_csr(ioaddr, 88) | (a->read_csr(ioaddr,89) << 16);
if (pcnet32_debug & NETIF_MSG_PROBE) if ((pcnet32_debug & NETIF_MSG_PROBE) && (pcnet32_debug & NETIF_MSG_HW))
printk(KERN_INFO " PCnet chip version is %#x.\n", chip_version); printk(KERN_INFO " PCnet chip version is %#x.\n", chip_version);
if ((chip_version & 0xfff) != 0x003) { if ((chip_version & 0xfff) != 0x003) {
if (pcnet32_debug & NETIF_MSG_PROBE)
printk(KERN_INFO PFX "Unsupported chip version.\n"); printk(KERN_INFO PFX "Unsupported chip version.\n");
goto err_release_region; goto err_release_region;
} }
...@@ -909,7 +1006,12 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, ...@@ -909,7 +1006,12 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
chipname = "PCnet/FAST III 79C975"; /* PCI */ chipname = "PCnet/FAST III 79C975"; /* PCI */
fdx = 1; mii = 1; fdx = 1; mii = 1;
break; break;
case 0x2628:
chipname = "PCnet/FAST III 79C976";
fdx = 1; mii = 1;
break;
default: default:
if (pcnet32_debug & NETIF_MSG_PROBE)
printk(KERN_INFO PFX "PCnet version %#x, no PCnet32 chip.\n", printk(KERN_INFO PFX "PCnet version %#x, no PCnet32 chip.\n",
chip_version); chip_version);
goto err_release_region; goto err_release_region;
...@@ -931,12 +1033,14 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, ...@@ -931,12 +1033,14 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
dev = alloc_etherdev(0); dev = alloc_etherdev(0);
if (!dev) { if (!dev) {
if (pcnet32_debug & NETIF_MSG_PROBE)
printk(KERN_ERR PFX "Memory allocation failed.\n"); printk(KERN_ERR PFX "Memory allocation failed.\n");
ret = -ENOMEM; ret = -ENOMEM;
goto err_release_region; goto err_release_region;
} }
SET_NETDEV_DEV(dev, &pdev->dev); SET_NETDEV_DEV(dev, &pdev->dev);
if (pcnet32_debug & NETIF_MSG_PROBE)
printk(KERN_INFO PFX "%s at %#3lx,", chipname, ioaddr); printk(KERN_INFO PFX "%s at %#3lx,", chipname, ioaddr);
/* In most chips, after a chip reset, the ethernet address is read from the /* In most chips, after a chip reset, the ethernet address is read from the
...@@ -966,8 +1070,10 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, ...@@ -966,8 +1070,10 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
if (!is_valid_ether_addr(dev->dev_addr) if (!is_valid_ether_addr(dev->dev_addr)
&& is_valid_ether_addr(promaddr)) { && is_valid_ether_addr(promaddr)) {
#endif #endif
if (pcnet32_debug & NETIF_MSG_PROBE) {
printk(" warning: CSR address invalid,\n"); printk(" warning: CSR address invalid,\n");
printk(KERN_INFO " using instead PROM address of"); printk(KERN_INFO " using instead PROM address of");
}
memcpy(dev->dev_addr, promaddr, 6); memcpy(dev->dev_addr, promaddr, 6);
} }
} }
...@@ -976,10 +1082,12 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, ...@@ -976,10 +1082,12 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
if (!is_valid_ether_addr(dev->dev_addr)) if (!is_valid_ether_addr(dev->dev_addr))
memset(dev->dev_addr, 0, sizeof(dev->dev_addr)); memset(dev->dev_addr, 0, sizeof(dev->dev_addr));
if (pcnet32_debug & NETIF_MSG_PROBE) {
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
printk(" %2.2x", dev->dev_addr[i] ); printk(" %2.2x", dev->dev_addr[i]);
if (((chip_version + 1) & 0xfffe) == 0x2624) { /* Version 0x2623 - 0x2624 */ /* Version 0x2623 and 0x2624 */
if (((chip_version + 1) & 0xfffe) == 0x2624) {
i = a->read_csr(ioaddr, 80) & 0x0C00; /* Check tx_start_pt */ i = a->read_csr(ioaddr, 80) & 0x0C00; /* Check tx_start_pt */
printk("\n" KERN_INFO " tx_start_pt(0x%04x):",i); printk("\n" KERN_INFO " tx_start_pt(0x%04x):",i);
switch(i>>10) { switch(i>>10) {
...@@ -1001,10 +1109,12 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, ...@@ -1001,10 +1109,12 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
i = a->read_bcr(ioaddr, 27); i = a->read_bcr(ioaddr, 27);
if (i & (1<<14)) printk("LowLatRx"); if (i & (1<<14)) printk("LowLatRx");
} }
}
dev->base_addr = ioaddr; dev->base_addr = ioaddr;
/* pci_alloc_consistent returns page-aligned memory, so we do not have to check the alignment */ /* pci_alloc_consistent returns page-aligned memory, so we do not have to check the alignment */
if ((lp = pci_alloc_consistent(pdev, sizeof(*lp), &lp_dma_addr)) == NULL) { if ((lp = pci_alloc_consistent(pdev, sizeof(*lp), &lp_dma_addr)) == NULL) {
if (pcnet32_debug & NETIF_MSG_PROBE)
printk(KERN_ERR PFX "Consistent memory allocation failed.\n"); printk(KERN_ERR PFX "Consistent memory allocation failed.\n");
ret = -ENOMEM; ret = -ENOMEM;
goto err_free_netdev; goto err_free_netdev;
...@@ -1041,6 +1151,7 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, ...@@ -1041,6 +1151,7 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
lp->options |= PCNET32_PORT_FD; lp->options |= PCNET32_PORT_FD;
if (!a) { if (!a) {
if (pcnet32_debug & NETIF_MSG_PROBE)
printk(KERN_ERR PFX "No access methods\n"); printk(KERN_ERR PFX "No access methods\n");
ret = -ENODEV; ret = -ENODEV;
goto err_free_consistent; goto err_free_consistent;
...@@ -1075,9 +1186,10 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, ...@@ -1075,9 +1186,10 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
dev->irq = irq_line; dev->irq = irq_line;
} }
if (dev->irq >= 2) if (dev->irq >= 2) {
if (pcnet32_debug & NETIF_MSG_PROBE)
printk(" assigned IRQ %d.\n", dev->irq); printk(" assigned IRQ %d.\n", dev->irq);
else { } else {
unsigned long irq_mask = probe_irq_on(); unsigned long irq_mask = probe_irq_on();
/* /*
...@@ -1091,10 +1203,12 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, ...@@ -1091,10 +1203,12 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
dev->irq = probe_irq_off (irq_mask); dev->irq = probe_irq_off (irq_mask);
if (!dev->irq) { if (!dev->irq) {
if (pcnet32_debug & NETIF_MSG_PROBE)
printk(", failed to detect IRQ line.\n"); printk(", failed to detect IRQ line.\n");
ret = -ENODEV; ret = -ENODEV;
goto err_free_consistent; goto err_free_consistent;
} }
if (pcnet32_debug & NETIF_MSG_PROBE)
printk(", probed IRQ %d.\n", dev->irq); printk(", probed IRQ %d.\n", dev->irq);
} }
...@@ -1132,8 +1246,12 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, ...@@ -1132,8 +1246,12 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
pcnet32_dev = dev; pcnet32_dev = dev;
} }
printk(KERN_INFO "%s: registered as %s\n",dev->name, lp->name); if (pcnet32_debug & NETIF_MSG_PROBE)
printk(KERN_INFO "%s: registered as %s\n", dev->name, lp->name);
cards_found++; cards_found++;
a->write_bcr(ioaddr, 2, 0x1002); /* enable LED writes */
return 0; return 0;
err_free_consistent: err_free_consistent:
...@@ -1154,13 +1272,15 @@ pcnet32_open(struct net_device *dev) ...@@ -1154,13 +1272,15 @@ pcnet32_open(struct net_device *dev)
u16 val; u16 val;
int i; int i;
int rc; int rc;
unsigned long flags;
if (dev->irq == 0 || if (dev->irq == 0 ||
request_irq(dev->irq, &pcnet32_interrupt, request_irq(dev->irq, &pcnet32_interrupt,
lp->shared_irq ? SA_SHIRQ : 0, lp->name, (void *)dev)) { lp->shared_irq ? SA_SHIRQ : 0, dev->name, (void *)dev)) {
return -EAGAIN; return -EAGAIN;
} }
spin_lock_irqsave(&lp->lock, flags);
/* Check for a valid station address */ /* Check for a valid station address */
if (!is_valid_ether_addr(dev->dev_addr)) { if (!is_valid_ether_addr(dev->dev_addr)) {
rc = -EINVAL; rc = -EINVAL;
...@@ -1241,8 +1361,8 @@ pcnet32_open(struct net_device *dev) ...@@ -1241,8 +1361,8 @@ pcnet32_open(struct net_device *dev)
} }
lp->init_block.mode = le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7); lp->init_block.mode = le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7);
lp->init_block.filter[0] = 0x00000000; pcnet32_load_multicast(dev);
lp->init_block.filter[1] = 0x00000000;
if (pcnet32_init_ring(dev)) { if (pcnet32_init_ring(dev)) {
rc = -ENOMEM; rc = -ENOMEM;
goto err_free_ring; goto err_free_ring;
...@@ -1261,7 +1381,7 @@ pcnet32_open(struct net_device *dev) ...@@ -1261,7 +1381,7 @@ pcnet32_open(struct net_device *dev)
/* If we have mii, print the link status and start the watchdog */ /* If we have mii, print the link status and start the watchdog */
if (lp->mii) { if (lp->mii) {
mii_check_media (&lp->mii_if, 1, 1); mii_check_media (&lp->mii_if, netif_msg_link(lp), 1);
mod_timer (&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT); mod_timer (&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT);
} }
...@@ -1281,6 +1401,7 @@ pcnet32_open(struct net_device *dev) ...@@ -1281,6 +1401,7 @@ pcnet32_open(struct net_device *dev)
offsetof(struct pcnet32_private, init_block)), offsetof(struct pcnet32_private, init_block)),
lp->a.read_csr(ioaddr, 0)); lp->a.read_csr(ioaddr, 0));
spin_unlock_irqrestore(&lp->lock, flags);
return 0; /* Always succeed */ return 0; /* Always succeed */
...@@ -1303,6 +1424,7 @@ pcnet32_open(struct net_device *dev) ...@@ -1303,6 +1424,7 @@ pcnet32_open(struct net_device *dev)
lp->a.write_bcr (ioaddr, 20, 4); lp->a.write_bcr (ioaddr, 20, 4);
err_free_irq: err_free_irq:
spin_unlock_irqrestore(&lp->lock, flags);
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
return rc; return rc;
} }
...@@ -1354,6 +1476,7 @@ pcnet32_init_ring(struct net_device *dev) ...@@ -1354,6 +1476,7 @@ pcnet32_init_ring(struct net_device *dev)
if (rx_skbuff == NULL) { if (rx_skbuff == NULL) {
if (!(rx_skbuff = lp->rx_skbuff[i] = dev_alloc_skb (PKT_BUF_SZ))) { if (!(rx_skbuff = lp->rx_skbuff[i] = dev_alloc_skb (PKT_BUF_SZ))) {
/* there is not much, we can do at this point */ /* there is not much, we can do at this point */
if (pcnet32_debug & NETIF_MSG_DRV)
printk(KERN_ERR "%s: pcnet32_init_ring dev_alloc_skb failed.\n", printk(KERN_ERR "%s: pcnet32_init_ring dev_alloc_skb failed.\n",
dev->name); dev->name);
return -1; return -1;
...@@ -1417,6 +1540,7 @@ pcnet32_tx_timeout (struct net_device *dev) ...@@ -1417,6 +1540,7 @@ pcnet32_tx_timeout (struct net_device *dev)
spin_lock_irqsave(&lp->lock, flags); spin_lock_irqsave(&lp->lock, flags);
/* Transmitter timeout, serious problems. */ /* Transmitter timeout, serious problems. */
if (pcnet32_debug & NETIF_MSG_DRV)
printk(KERN_ERR "%s: transmit timed out, status %4.4x, resetting.\n", printk(KERN_ERR "%s: transmit timed out, status %4.4x, resetting.\n",
dev->name, lp->a.read_csr(ioaddr, 0)); dev->name, lp->a.read_csr(ioaddr, 0));
lp->a.write_csr (ioaddr, 0, 0x0004); lp->a.write_csr (ioaddr, 0, 0x0004);
...@@ -1526,6 +1650,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs) ...@@ -1526,6 +1650,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
int must_restart; int must_restart;
if (!dev) { if (!dev) {
if (pcnet32_debug & NETIF_MSG_INTR)
printk (KERN_DEBUG "%s(): irq %d for unknown device\n", printk (KERN_DEBUG "%s(): irq %d for unknown device\n",
__FUNCTION__, irq); __FUNCTION__, irq);
return IRQ_NONE; return IRQ_NONE;
...@@ -1578,6 +1703,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs) ...@@ -1578,6 +1703,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
lp->stats.tx_fifo_errors++; lp->stats.tx_fifo_errors++;
/* Ackk! On FIFO errors the Tx unit is turned off! */ /* Ackk! On FIFO errors the Tx unit is turned off! */
/* Remove this verbosity later! */ /* Remove this verbosity later! */
if (netif_msg_tx_err(lp))
printk(KERN_ERR "%s: Tx FIFO error! CSR0=%4.4x\n", printk(KERN_ERR "%s: Tx FIFO error! CSR0=%4.4x\n",
dev->name, csr0); dev->name, csr0);
must_restart = 1; must_restart = 1;
...@@ -1588,6 +1714,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs) ...@@ -1588,6 +1714,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
if (! lp->dxsuflo) { /* If controller doesn't recover ... */ if (! lp->dxsuflo) { /* If controller doesn't recover ... */
/* Ackk! On FIFO errors the Tx unit is turned off! */ /* Ackk! On FIFO errors the Tx unit is turned off! */
/* Remove this verbosity later! */ /* Remove this verbosity later! */
if (netif_msg_tx_err(lp))
printk(KERN_ERR "%s: Tx FIFO error! CSR0=%4.4x\n", printk(KERN_ERR "%s: Tx FIFO error! CSR0=%4.4x\n",
dev->name, csr0); dev->name, csr0);
must_restart = 1; must_restart = 1;
...@@ -1613,6 +1740,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs) ...@@ -1613,6 +1740,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
delta = (lp->cur_tx - dirty_tx) & (TX_RING_MOD_MASK + TX_RING_SIZE); delta = (lp->cur_tx - dirty_tx) & (TX_RING_MOD_MASK + TX_RING_SIZE);
if (delta >= TX_RING_SIZE) { if (delta >= TX_RING_SIZE) {
if (netif_msg_drv(lp))
printk(KERN_ERR "%s: out-of-sync dirty pointer, %d vs. %d, full=%d.\n", printk(KERN_ERR "%s: out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
dev->name, dirty_tx, lp->cur_tx, lp->tx_full); dev->name, dirty_tx, lp->cur_tx, lp->tx_full);
dirty_tx += TX_RING_SIZE; dirty_tx += TX_RING_SIZE;
...@@ -1646,6 +1774,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs) ...@@ -1646,6 +1774,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
lp->stats.rx_errors++; /* Missed a Rx frame. */ lp->stats.rx_errors++; /* Missed a Rx frame. */
} }
if (csr0 & 0x0800) { if (csr0 & 0x0800) {
if (netif_msg_drv(lp))
printk(KERN_ERR "%s: Bus master arbitration failure, status %4.4x.\n", printk(KERN_ERR "%s: Bus master arbitration failure, status %4.4x.\n",
dev->name, csr0); dev->name, csr0);
/* unlike for the lance, there is no restart needed */ /* unlike for the lance, there is no restart needed */
...@@ -1701,7 +1830,8 @@ pcnet32_rx(struct net_device *dev) ...@@ -1701,7 +1830,8 @@ pcnet32_rx(struct net_device *dev)
struct sk_buff *skb; struct sk_buff *skb;
if (pkt_len < 60) { if (pkt_len < 60) {
printk(KERN_ERR "%s: Runt packet!\n",dev->name); if (netif_msg_rx_err(lp))
printk(KERN_ERR "%s: Runt packet!\n", dev->name);
lp->stats.rx_errors++; lp->stats.rx_errors++;
} else { } else {
int rx_in_place = 0; int rx_in_place = 0;
...@@ -1730,6 +1860,7 @@ pcnet32_rx(struct net_device *dev) ...@@ -1730,6 +1860,7 @@ pcnet32_rx(struct net_device *dev)
if (skb == NULL) { if (skb == NULL) {
int i; int i;
if (netif_msg_drv(lp))
printk(KERN_ERR "%s: Memory squeeze, deferring packet.\n", printk(KERN_ERR "%s: Memory squeeze, deferring packet.\n",
dev->name); dev->name);
for (i = 0; i < RX_RING_SIZE; i++) for (i = 0; i < RX_RING_SIZE; i++)
...@@ -1786,11 +1917,14 @@ pcnet32_close(struct net_device *dev) ...@@ -1786,11 +1917,14 @@ pcnet32_close(struct net_device *dev)
unsigned long ioaddr = dev->base_addr; unsigned long ioaddr = dev->base_addr;
struct pcnet32_private *lp = dev->priv; struct pcnet32_private *lp = dev->priv;
int i; int i;
unsigned long flags;
del_timer_sync(&lp->watchdog_timer); del_timer_sync(&lp->watchdog_timer);
netif_stop_queue(dev); netif_stop_queue(dev);
spin_lock_irqsave(&lp->lock, flags);
lp->stats.rx_missed_errors = lp->a.read_csr (ioaddr, 112); lp->stats.rx_missed_errors = lp->a.read_csr (ioaddr, 112);
if (netif_msg_ifdown(lp)) if (netif_msg_ifdown(lp))
...@@ -1806,6 +1940,8 @@ pcnet32_close(struct net_device *dev) ...@@ -1806,6 +1940,8 @@ pcnet32_close(struct net_device *dev)
*/ */
lp->a.write_bcr (ioaddr, 20, 4); lp->a.write_bcr (ioaddr, 20, 4);
spin_unlock_irqrestore(&lp->lock, flags);
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
/* free all allocated skbuffs */ /* free all allocated skbuffs */
...@@ -1900,6 +2036,7 @@ static void pcnet32_set_multicast_list(struct net_device *dev) ...@@ -1900,6 +2036,7 @@ static void pcnet32_set_multicast_list(struct net_device *dev)
spin_lock_irqsave(&lp->lock, flags); spin_lock_irqsave(&lp->lock, flags);
if (dev->flags&IFF_PROMISC) { if (dev->flags&IFF_PROMISC) {
/* Log any net taps. */ /* Log any net taps. */
if (netif_msg_hw(lp))
printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name); printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name);
lp->init_block.mode = le16_to_cpu(0x8000 | (lp->options & PCNET32_PORT_PORTSEL) << 7); lp->init_block.mode = le16_to_cpu(0x8000 | (lp->options & PCNET32_PORT_PORTSEL) << 7);
} else { } else {
...@@ -1975,7 +2112,7 @@ static void pcnet32_watchdog(struct net_device *dev) ...@@ -1975,7 +2112,7 @@ static void pcnet32_watchdog(struct net_device *dev)
/* Print the link status if it has changed */ /* Print the link status if it has changed */
if (lp->mii) { if (lp->mii) {
spin_lock_irqsave(&lp->lock, flags); spin_lock_irqsave(&lp->lock, flags);
mii_check_media (&lp->mii_if, 1, 0); mii_check_media (&lp->mii_if, netif_msg_link(lp), 0);
spin_unlock_irqrestore(&lp->lock, flags); spin_unlock_irqrestore(&lp->lock, flags);
} }
...@@ -2023,6 +2160,8 @@ MODULE_AUTHOR("Thomas Bogendoerfer"); ...@@ -2023,6 +2160,8 @@ MODULE_AUTHOR("Thomas Bogendoerfer");
MODULE_DESCRIPTION("Driver for PCnet32 and PCnetPCI based ethercards"); MODULE_DESCRIPTION("Driver for PCnet32 and PCnetPCI based ethercards");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#define PCNET32_MSG_DEFAULT (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK)
/* An additional parameter that may be passed in... */ /* An additional parameter that may be passed in... */
static int debug = -1; static int debug = -1;
static int tx_start_pt = -1; static int tx_start_pt = -1;
...@@ -2032,8 +2171,7 @@ static int __init pcnet32_init_module(void) ...@@ -2032,8 +2171,7 @@ static int __init pcnet32_init_module(void)
{ {
printk(KERN_INFO "%s", version); printk(KERN_INFO "%s", version);
if (debug >= 0 && debug < (sizeof(int) - 1)) pcnet32_debug = netif_msg_init(debug, PCNET32_MSG_DEFAULT);
pcnet32_debug = 1 << debug;
if ((tx_start_pt >= 0) && (tx_start_pt <= 3)) if ((tx_start_pt >= 0) && (tx_start_pt <= 3))
tx_start = tx_start_pt; tx_start = tx_start_pt;
...@@ -2046,7 +2184,7 @@ static int __init pcnet32_init_module(void) ...@@ -2046,7 +2184,7 @@ static int __init pcnet32_init_module(void)
if (pcnet32vlb) if (pcnet32vlb)
pcnet32_probe_vlbus(); pcnet32_probe_vlbus();
if (cards_found) if (cards_found && (pcnet32_debug & NETIF_MSG_PROBE))
printk(KERN_INFO PFX "%d cards_found.\n", cards_found); printk(KERN_INFO PFX "%d cards_found.\n", cards_found);
return (pcnet32_have_pci + cards_found) ? 0 : -ENODEV; return (pcnet32_have_pci + cards_found) ? 0 : -ENODEV;
...@@ -2075,7 +2213,6 @@ module_exit(pcnet32_cleanup_module); ...@@ -2075,7 +2213,6 @@ module_exit(pcnet32_cleanup_module);
/* /*
* Local variables: * Local variables:
* compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c pcnet32.c"
* c-indent-level: 4 * c-indent-level: 4
* tab-width: 8 * tab-width: 8
* End: * End:
......
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