patch-2.4.11-dontuse linux/drivers/net/ns83820.c
Next file: linux/drivers/net/pcmcia/3c574_cs.c
Previous file: linux/drivers/net/ni65.c
Back to the patch index
Back to the overall index
- Lines: 301
- Date:
Tue Oct 9 15:13:03 2001
- Orig file:
v2.4.10/linux/drivers/net/ns83820.c
- Orig date:
Sun Sep 23 11:40:58 2001
diff -u --recursive --new-file v2.4.10/linux/drivers/net/ns83820.c linux/drivers/net/ns83820.c
@@ -1,7 +1,7 @@
-#define VERSION "0.11"
+#define VERSION "0.13"
/* ns83820.c by Benjamin LaHaise <bcrl@redhat.com>
*
- * $Revision: 1.34.2.2 $
+ * $Revision: 1.34.2.8 $
*
* Copyright 2001 Benjamin LaHaise.
* Copyright 2001 Red Hat.
@@ -41,7 +41,10 @@
* 20010827 0.10 - fix ia64 unaligned access.
* 20010906 0.11 - accept all packets with checksum errors as
* otherwise fragments get lost
- - fix >> 32 bugs
+ * - fix >> 32 bugs
+ * 0.12 - add statistics counters
+ * - add allmulti/promisc support
+ * 20011009 0.13 - hotplug support, other smaller pci api cleanups
*
* Driver Overview
* ===============
@@ -61,7 +64,9 @@
* Cameo SOHO-GA2000T SOHO-GA2500T
* D-Link DGE-500T
* PureData PDP8023Z-TG
- * SMC SMC9462TX
+ * SMC SMC9452TX SMC9462TX
+ *
+ * Special thanks to SMC for providing hardware to test this driver on.
*
* Reports of success or failure would be greatly appreciated.
*/
@@ -366,10 +371,10 @@
struct ns83820 {
struct net_device net_dev;
+ struct net_device_stats stats;
u8 *base;
struct pci_dev *pci_dev;
- struct ns83820 *next_dev;
struct rx_info rx_info;
@@ -405,8 +410,6 @@
#define start_tx_okay(dev) \
(((NR_TX_DESC-2 + dev->tx_done_idx - dev->tx_free_idx) % NR_TX_DESC) > NR_TX_DESC/2)
-static struct ns83820 *ns83820_chain;
-
/* Packet Receiver
*
@@ -732,39 +735,22 @@
kfree_skb(skb);
skb = tmp;
#endif
+ if (cmdsts & CMDSTS_DEST_MULTI)
+ dev->stats.multicast ++;
+ dev->stats.rx_packets ++;
+ dev->stats.rx_bytes += len;
if ((extsts & 0x002a0000) && !(extsts & 0x00540000)) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
} else {
skb->ip_summed = CHECKSUM_NONE;
}
skb->protocol = eth_type_trans(skb, &dev->net_dev);
- switch (netif_rx(skb)) {
- case NET_RX_SUCCESS:
- dev->ihr = 3;
- break;
- case NET_RX_CN_LOW:
- dev->ihr = 3;
- break;
- case NET_RX_CN_MOD:
- dev->ihr = dev->ihr + 1;
- break;
- case NET_RX_CN_HIGH:
- dev->ihr += dev->ihr/2 + 1;
- break;
- case NET_RX_DROP:
- dev->ihr = 255;
- break;
- }
- if (dev->ihr > 255)
- dev->ihr = 255;
+ if (NET_RX_DROP == netif_rx(skb))
+ dev->stats.rx_dropped ++;
#ifndef __i386__
done:;
#endif
} else {
- static int err;
- if (err++ < 20) {
- Dprintk("error packet: cmdsts: %08x extsts: %08x\n", cmdsts, extsts);
- }
kfree_skb(skb);
}
@@ -807,6 +793,13 @@
!(CMDSTS_OWN & (cmdsts = desc[CMDSTS])) ) {
struct sk_buff *skb;
+ if (cmdsts & CMDSTS_ERR)
+ dev->stats.tx_errors ++;
+ if (cmdsts & CMDSTS_OK)
+ dev->stats.tx_packets ++;
+ if (cmdsts & CMDSTS_OK)
+ dev->stats.tx_bytes += cmdsts & 0xffff;
+
dprintk("tx_done_idx=%d free_idx=%d cmdsts=%08x\n",
tx_done_idx, dev->tx_free_idx, desc[CMDSTS]);
skb = dev->tx_skbs[tx_done_idx];
@@ -985,6 +978,35 @@
return 0;
}
+static void ns83820_update_stats(struct ns83820 *dev)
+{
+ u8 *base = dev->base;
+
+ dev->stats.rx_errors += readl(base + 0x60) & 0xffff;
+ dev->stats.rx_crc_errors += readl(base + 0x64) & 0xffff;
+ dev->stats.rx_missed_errors += readl(base + 0x68) & 0xffff;
+ dev->stats.rx_frame_errors += readl(base + 0x6c) & 0xffff;
+ /*dev->stats.rx_symbol_errors +=*/ readl(base + 0x70);
+ dev->stats.rx_length_errors += readl(base + 0x74) & 0xffff;
+ dev->stats.rx_length_errors += readl(base + 0x78) & 0xffff;
+ /*dev->stats.rx_badopcode_errors += */ readl(base + 0x7c);
+ /*dev->stats.rx_pause_count += */ readl(base + 0x80);
+ /*dev->stats.tx_pause_count += */ readl(base + 0x84);
+ dev->stats.tx_carrier_errors += readl(base + 0x88) & 0xff;
+}
+
+static struct net_device_stats *ns83820_get_stats(struct net_device *_dev)
+{
+ struct ns83820 *dev = (void *)_dev;
+
+ /* somewhat overkill */
+ spin_lock_irq(&dev->misc_lock);
+ ns83820_update_stats(dev);
+ spin_unlock_irq(&dev->misc_lock);
+
+ return &dev->stats;
+}
+
static void ns83820_irq(int foo, void *data, struct pt_regs *regs)
{
struct ns83820 *dev = data;
@@ -1060,6 +1082,12 @@
if ((ISR_TXDESC | ISR_TXIDLE) & isr)
do_tx_done(dev);
+ if (ISR_MIB & isr) {
+ spin_lock(&dev->misc_lock);
+ ns83820_update_stats(dev);
+ spin_unlock(&dev->misc_lock);
+ }
+
if (ISR_PHY & isr)
phy_intr(dev);
}
@@ -1178,7 +1206,29 @@
return 0;
}
-static int ns83820_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
+static void ns83820_set_multicast(struct net_device *_dev)
+{
+ struct ns83820 *dev = (void *)_dev;
+ u8 *rfcr = dev->base + RFCR;
+ u32 and_mask = 0xffffffff;
+ u32 or_mask = 0;
+
+ if (dev->net_dev.flags & IFF_PROMISC)
+ or_mask |= RFCR_AAU | RFCR_AAM;
+ else
+ and_mask &= ~(RFCR_AAU | RFCR_AAM);
+
+ if (dev->net_dev.flags & IFF_ALLMULTI)
+ or_mask |= RFCR_AAM;
+ else
+ and_mask &= ~RFCR_AAM;
+
+ spin_lock_irq(&dev->misc_lock);
+ writel((readl(rfcr) & and_mask) | or_mask, rfcr);
+ spin_unlock_irq(&dev->misc_lock);
+}
+
+static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_device_id *id)
{
struct ns83820 *dev;
long addr;
@@ -1241,12 +1291,12 @@
dev->net_dev.stop = ns83820_stop;
dev->net_dev.hard_start_xmit = ns83820_hard_start_xmit;
dev->net_dev.change_mtu = ns83820_change_mtu;
+ dev->net_dev.get_stats = ns83820_get_stats;
+ dev->net_dev.change_mtu = ns83820_change_mtu;
+ dev->net_dev.set_multicast_list = ns83820_set_multicast;
//FIXME: dev->net_dev.tx_timeout = ns83820_tx_timeout;
- lock_kernel();
- dev->next_dev = ns83820_chain;
- ns83820_chain = dev;
- unlock_kernel();
+ pci_set_drvdata(pci_dev, dev);
ns83820_do_reset(dev, CR_RST);
@@ -1368,21 +1418,45 @@
pci_disable_device(pci_dev);
out_free:
kfree(dev);
+ pci_set_drvdata(pci_dev, NULL);
out:
return err;
}
-static struct pci_device_id pci_device_id[] __devinitdata = {
+static void __devexit ns83820_remove_one(struct pci_dev *pci_dev)
+{
+ struct ns83820 *dev = pci_get_drvdata(pci_dev);
+
+ if (!dev) /* paranoia */
+ return;
+
+ writel(0, dev->base + IMR); /* paranoia */
+ writel(0, dev->base + IER);
+ readl(dev->base + IER);
+
+ unregister_netdev(&dev->net_dev);
+ free_irq(dev->pci_dev->irq, dev);
+ iounmap(dev->base);
+ pci_free_consistent(dev->pci_dev, 4 * DESC_SIZE * NR_TX_DESC,
+ dev->tx_descs, dev->tx_phy_descs);
+ pci_free_consistent(dev->pci_dev, 4 * DESC_SIZE * NR_RX_DESC,
+ dev->rx_info.descs, dev->rx_info.phy_descs);
+ pci_disable_device(dev->pci_dev);
+ kfree(dev);
+ pci_set_drvdata(pci_dev, NULL);
+}
+
+static struct pci_device_id ns83820_pci_tbl[] __devinitdata = {
{ 0x100b, 0x0022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
{ 0, },
};
static struct pci_driver driver = {
name: "ns83820",
- id_table: pci_device_id,
- probe: ns83820_probe,
+ id_table: ns83820_pci_tbl,
+ probe: ns83820_init_one,
+ remove: ns83820_remove_one,
#if 0 /* FIXME: implement */
- remove: ,
suspend: ,
resume: ,
#endif
@@ -1395,34 +1469,16 @@
return pci_module_init(&driver);
}
-static void ns83820_exit(void)
+static void __exit ns83820_exit(void)
{
- struct ns83820 *dev;
-
- for (dev = ns83820_chain; dev; ) {
- struct ns83820 *next = dev->next_dev;
-
- writel(0, dev->base + IMR); /* paranoia */
- writel(0, dev->base + IER);
- readl(dev->base + IER);
-
- unregister_netdev(&dev->net_dev);
- free_irq(dev->pci_dev->irq, dev);
- iounmap(dev->base);
- pci_free_consistent(dev->pci_dev, 4 * DESC_SIZE * NR_TX_DESC,
- dev->tx_descs, dev->tx_phy_descs);
- pci_free_consistent(dev->pci_dev, 4 * DESC_SIZE * NR_RX_DESC,
- dev->rx_info.descs, dev->rx_info.phy_descs);
- pci_disable_device(dev->pci_dev);
- kfree(dev);
- dev = next;
- }
pci_unregister_driver(&driver);
- ns83820_chain = NULL;
}
MODULE_AUTHOR("Benjamin LaHaise <bcrl@redhat.com>");
MODULE_DESCRIPTION("National Semiconductor DP83820 10/100/1000 driver");
-MODULE_DEVICE_TABLE(pci, pci_device_id);
+MODULE_LICENSE("GPL");
+
+MODULE_DEVICE_TABLE(pci, ns83820_pci_tbl);
+
module_init(ns83820_init);
module_exit(ns83820_exit);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)