diff options
Diffstat (limited to 'drivers/net/wan/lmc/lmc_main.c')
| -rw-r--r-- | drivers/net/wan/lmc/lmc_main.c | 764 |
1 files changed, 342 insertions, 422 deletions
diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c index 6635ecef36e..b2fe9bb8963 100644 --- a/drivers/net/wan/lmc/lmc_main.c +++ b/drivers/net/wan/lmc/lmc_main.c @@ -1,6 +1,7 @@ /* * Copyright (c) 1997-2000 LAN Media Corporation (LMC) * All rights reserved. www.lanmedia.com + * Generic HDLC port Copyright (C) 2008 Krzysztof Halasa <khc@pm.waw.pl> * * This code is written by: * Andrew Stanley-Jones (asj@cban.com) @@ -23,7 +24,7 @@ * * Linux driver notes: * Linux uses the device struct lmc_private to pass private information - * arround. + * around. * * The initialization portion of this driver (the lmc_reset() and the * lmc_dec_reset() functions, as well as the led controls and the @@ -36,8 +37,6 @@ * */ -/* $Id: lmc_main.c,v 1.36 2000/04/11 05:25:25 asj Exp $ */ - #include <linux/kernel.h> #include <linux/module.h> #include <linux/string.h> @@ -49,7 +48,7 @@ #include <linux/interrupt.h> #include <linux/pci.h> #include <linux/delay.h> -#include <linux/init.h> +#include <linux/hdlc.h> #include <linux/in.h> #include <linux/if_arp.h> #include <linux/netdevice.h> @@ -57,9 +56,6 @@ #include <linux/skbuff.h> #include <linux/inet.h> #include <linux/bitops.h> - -#include <net/syncppp.h> - #include <asm/processor.h> /* Processor type for cache alignment. */ #include <asm/io.h> #include <asm/dma.h> @@ -78,11 +74,9 @@ #include "lmc_debug.h" #include "lmc_proto.h" -static int lmc_first_load = 0; - static int LMC_PKT_BUF_SZ = 1542; -static struct pci_device_id lmc_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(lmc_pci_tbl) = { { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST, PCI_VENDOR_ID_LMC, PCI_ANY_ID }, { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST, @@ -91,11 +85,11 @@ static struct pci_device_id lmc_pci_tbl[] = { }; MODULE_DEVICE_TABLE(pci, lmc_pci_tbl); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); -static int lmc_start_xmit(struct sk_buff *skb, struct net_device *dev); -static int lmc_start_xmit(struct sk_buff *skb, struct net_device *dev); +static netdev_tx_t lmc_start_xmit(struct sk_buff *skb, + struct net_device *dev); static int lmc_rx (struct net_device *dev); static int lmc_open(struct net_device *dev); static int lmc_close(struct net_device *dev); @@ -114,27 +108,20 @@ static void lmc_driver_timeout(struct net_device *dev); * linux reserves 16 device specific IOCTLs. We call them * LMCIOC* to control various bits of our world. */ -int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ +int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ { - lmc_softc_t *sc; + lmc_softc_t *sc = dev_to_sc(dev); lmc_ctl_t ctl; - int ret; - u_int16_t regVal; + int ret = -EOPNOTSUPP; + u16 regVal; unsigned long flags; - struct sppp *sp; - - ret = -EOPNOTSUPP; - - sc = dev->priv; - lmc_trace(dev, "lmc_ioctl in"); /* * Most functions mess with the structure * Disable interrupts while we do the polling */ - spin_lock_irqsave(&sc->lmc_lock, flags); switch (cmd) { /* @@ -149,7 +136,6 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ break; case LMCIOCSINFO: /*fold01*/ - sp = &((struct ppp_device *) dev)->sppp; if (!capable(CAP_NET_ADMIN)) { ret = -EPERM; break; @@ -165,6 +151,7 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ break; } + spin_lock_irqsave(&sc->lmc_lock, flags); sc->lmc_media->set_status (sc, &ctl); if(ctl.crc_length != sc->ictl.crc_length) { @@ -174,26 +161,22 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ else sc->TxDescriptControlInit &= ~LMC_TDES_ADD_CRC_DISABLE; } - - if (ctl.keepalive_onoff == LMC_CTL_OFF) - sp->pp_flags &= ~PP_KEEPALIVE; /* Turn off */ - else - sp->pp_flags |= PP_KEEPALIVE; /* Turn on */ + spin_unlock_irqrestore(&sc->lmc_lock, flags); ret = 0; break; case LMCIOCIFTYPE: /*fold01*/ { - u_int16_t old_type = sc->if_type; - u_int16_t new_type; + u16 old_type = sc->if_type; + u16 new_type; if (!capable(CAP_NET_ADMIN)) { ret = -EPERM; break; } - if (copy_from_user(&new_type, ifr->ifr_data, sizeof(u_int16_t))) { + if (copy_from_user(&new_type, ifr->ifr_data, sizeof(u16))) { ret = -EFAULT; break; } @@ -205,19 +188,18 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ break; /* no change */ } + spin_lock_irqsave(&sc->lmc_lock, flags); lmc_proto_close(sc); - lmc_proto_detach(sc); sc->if_type = new_type; -// lmc_proto_init(sc); lmc_proto_attach(sc); - lmc_proto_open(sc); - - ret = 0 ; - break ; + ret = lmc_proto_open(sc); + spin_unlock_irqrestore(&sc->lmc_lock, flags); + break; } case LMCIOCGETXINFO: /*fold01*/ + spin_lock_irqsave(&sc->lmc_lock, flags); sc->lmc_xinfo.Magic0 = 0xBEEFCAFE; sc->lmc_xinfo.PciCardType = sc->lmc_cardtype; @@ -230,6 +212,7 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ sc->lmc_xinfo.MaxFrameSize = LMC_PKT_BUF_SZ; sc->lmc_xinfo.link_status = sc->lmc_media->get_link_status (sc); sc->lmc_xinfo.mii_reg16 = lmc_mii_readreg (sc, 0, 16); + spin_unlock_irqrestore(&sc->lmc_lock, flags); sc->lmc_xinfo.Magic1 = 0xDEADBEEF; @@ -241,51 +224,57 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ break; - case LMCIOCGETLMCSTATS: /*fold01*/ - if (sc->lmc_cardtype == LMC_CARDTYPE_T1){ - lmc_mii_writereg (sc, 0, 17, T1FRAMER_FERR_LSB); - sc->stats.framingBitErrorCount += - lmc_mii_readreg (sc, 0, 18) & 0xff; - lmc_mii_writereg (sc, 0, 17, T1FRAMER_FERR_MSB); - sc->stats.framingBitErrorCount += - (lmc_mii_readreg (sc, 0, 18) & 0xff) << 8; - lmc_mii_writereg (sc, 0, 17, T1FRAMER_LCV_LSB); - sc->stats.lineCodeViolationCount += - lmc_mii_readreg (sc, 0, 18) & 0xff; - lmc_mii_writereg (sc, 0, 17, T1FRAMER_LCV_MSB); - sc->stats.lineCodeViolationCount += - (lmc_mii_readreg (sc, 0, 18) & 0xff) << 8; - lmc_mii_writereg (sc, 0, 17, T1FRAMER_AERR); - regVal = lmc_mii_readreg (sc, 0, 18) & 0xff; - - sc->stats.lossOfFrameCount += - (regVal & T1FRAMER_LOF_MASK) >> 4; - sc->stats.changeOfFrameAlignmentCount += - (regVal & T1FRAMER_COFA_MASK) >> 2; - sc->stats.severelyErroredFrameCount += - regVal & T1FRAMER_SEF_MASK; - } - - if (copy_to_user(ifr->ifr_data, &sc->stats, - sizeof (struct lmc_statistics))) - ret = -EFAULT; - else - ret = 0; - break; + case LMCIOCGETLMCSTATS: + spin_lock_irqsave(&sc->lmc_lock, flags); + if (sc->lmc_cardtype == LMC_CARDTYPE_T1) { + lmc_mii_writereg(sc, 0, 17, T1FRAMER_FERR_LSB); + sc->extra_stats.framingBitErrorCount += + lmc_mii_readreg(sc, 0, 18) & 0xff; + lmc_mii_writereg(sc, 0, 17, T1FRAMER_FERR_MSB); + sc->extra_stats.framingBitErrorCount += + (lmc_mii_readreg(sc, 0, 18) & 0xff) << 8; + lmc_mii_writereg(sc, 0, 17, T1FRAMER_LCV_LSB); + sc->extra_stats.lineCodeViolationCount += + lmc_mii_readreg(sc, 0, 18) & 0xff; + lmc_mii_writereg(sc, 0, 17, T1FRAMER_LCV_MSB); + sc->extra_stats.lineCodeViolationCount += + (lmc_mii_readreg(sc, 0, 18) & 0xff) << 8; + lmc_mii_writereg(sc, 0, 17, T1FRAMER_AERR); + regVal = lmc_mii_readreg(sc, 0, 18) & 0xff; + + sc->extra_stats.lossOfFrameCount += + (regVal & T1FRAMER_LOF_MASK) >> 4; + sc->extra_stats.changeOfFrameAlignmentCount += + (regVal & T1FRAMER_COFA_MASK) >> 2; + sc->extra_stats.severelyErroredFrameCount += + regVal & T1FRAMER_SEF_MASK; + } + spin_unlock_irqrestore(&sc->lmc_lock, flags); + if (copy_to_user(ifr->ifr_data, &sc->lmc_device->stats, + sizeof(sc->lmc_device->stats)) || + copy_to_user(ifr->ifr_data + sizeof(sc->lmc_device->stats), + &sc->extra_stats, sizeof(sc->extra_stats))) + ret = -EFAULT; + else + ret = 0; + break; - case LMCIOCCLEARLMCSTATS: /*fold01*/ - if (!capable(CAP_NET_ADMIN)){ - ret = -EPERM; - break; - } + case LMCIOCCLEARLMCSTATS: + if (!capable(CAP_NET_ADMIN)) { + ret = -EPERM; + break; + } - memset (&sc->stats, 0, sizeof (struct lmc_statistics)); - sc->stats.check = STATCHECK; - sc->stats.version_size = (DRIVER_VERSION << 16) + - sizeof (struct lmc_statistics); - sc->stats.lmc_cardtype = sc->lmc_cardtype; - ret = 0; - break; + spin_lock_irqsave(&sc->lmc_lock, flags); + memset(&sc->lmc_device->stats, 0, sizeof(sc->lmc_device->stats)); + memset(&sc->extra_stats, 0, sizeof(sc->extra_stats)); + sc->extra_stats.check = STATCHECK; + sc->extra_stats.version_size = (DRIVER_VERSION << 16) + + sizeof(sc->lmc_device->stats) + sizeof(sc->extra_stats); + sc->extra_stats.lmc_cardtype = sc->lmc_cardtype; + spin_unlock_irqrestore(&sc->lmc_lock, flags); + ret = 0; + break; case LMCIOCSETCIRCUIT: /*fold01*/ if (!capable(CAP_NET_ADMIN)){ @@ -302,8 +291,10 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ ret = -EFAULT; break; } + spin_lock_irqsave(&sc->lmc_lock, flags); sc->lmc_media->set_circuit_type(sc, ctl.circuit_type); sc->ictl.circuit_type = ctl.circuit_type; + spin_unlock_irqrestore(&sc->lmc_lock, flags); ret = 0; break; @@ -314,12 +305,14 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ break; } + spin_lock_irqsave(&sc->lmc_lock, flags); /* Reset driver and bring back to current state */ printk (" REG16 before reset +%04x\n", lmc_mii_readreg (sc, 0, 16)); lmc_running_reset (dev); printk (" REG16 after reset +%04x\n", lmc_mii_readreg (sc, 0, 16)); LMC_EVENT_LOG(LMC_EVENT_FORCEDRESET, LMC_CSR_READ (sc, csr_status), lmc_mii_readreg (sc, 0, 16)); + spin_unlock_irqrestore(&sc->lmc_lock, flags); ret = 0; break; @@ -330,7 +323,8 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ ret = -EFAULT; break; } - if (copy_to_user(ifr->ifr_data + sizeof (u32), lmcEventLogBuf, sizeof (lmcEventLogBuf))) + if (copy_to_user(ifr->ifr_data + sizeof(u32), lmcEventLogBuf, + sizeof(lmcEventLogBuf))) ret = -EFAULT; else ret = 0; @@ -357,14 +351,15 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ */ netif_stop_queue(dev); - if (copy_from_user(&xc, ifr->ifr_data, sizeof(struct lmc_xilinx_control))) { + if (copy_from_user(&xc, ifr->ifr_data, sizeof(struct lmc_xilinx_control))) { ret = -EFAULT; break; - } + } switch(xc.command){ case lmc_xilinx_reset: /*fold02*/ { u16 mii; + spin_lock_irqsave(&sc->lmc_lock, flags); mii = lmc_mii_readreg (sc, 0, 16); /* @@ -423,6 +418,7 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ lmc_led_off(sc, LMC_DS3_LED2); } } + spin_unlock_irqrestore(&sc->lmc_lock, flags); @@ -435,6 +431,7 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ { u16 mii; int timeout = 500000; + spin_lock_irqsave(&sc->lmc_lock, flags); mii = lmc_mii_readreg (sc, 0, 16); /* @@ -470,13 +467,14 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ */ while( (LMC_CSR_READ(sc, csr_gp) & LMC_GEP_INIT) == 0 && (timeout-- > 0)) - ; + cpu_relax(); /* * stop driving Xilinx-related signals */ lmc_gpio_mkinput(sc, 0xff); + spin_unlock_irqrestore(&sc->lmc_lock, flags); ret = 0x0; @@ -498,7 +496,6 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ data = kmalloc(xc.len, GFP_KERNEL); if (!data) { - printk(KERN_WARNING "%s: Failed to allocate memory for copy\n", dev->name); ret = -ENOMEM; break; } @@ -512,6 +509,7 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ printk("%s: Starting load of data Len: %d at 0x%p == 0x%p\n", dev->name, xc.len, xc.data, data); + spin_lock_irqsave(&sc->lmc_lock, flags); lmc_gpio_mkinput(sc, 0xff); /* @@ -564,7 +562,7 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ */ while( (LMC_CSR_READ(sc, csr_gp) & LMC_GEP_INIT) == 0 && (timeout-- > 0)) - ; + cpu_relax(); printk(KERN_DEBUG "%s: Waited %d for the Xilinx to clear it's memory\n", dev->name, 500000-timeout); @@ -607,6 +605,7 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ sc->lmc_miireg16 &= ~LMC_MII16_FIFO_RESET; lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16); + spin_unlock_irqrestore(&sc->lmc_lock, flags); kfree(data); @@ -630,8 +629,6 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ break; } - spin_unlock_irqrestore(&sc->lmc_lock, flags); /*fold01*/ - lmc_trace(dev, "lmc_ioctl out"); return ret; @@ -641,14 +638,12 @@ int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/ /* the watchdog process that cruises around */ static void lmc_watchdog (unsigned long data) /*fold00*/ { - struct net_device *dev = (struct net_device *) data; - lmc_softc_t *sc; + struct net_device *dev = (struct net_device *)data; + lmc_softc_t *sc = dev_to_sc(dev); int link_status; - u_int32_t ticks; + u32 ticks; unsigned long flags; - sc = dev->priv; - lmc_trace(dev, "lmc_watchdog in"); spin_lock_irqsave(&sc->lmc_lock, flags); @@ -677,22 +672,22 @@ static void lmc_watchdog (unsigned long data) /*fold00*/ * check for a transmit interrupt timeout * Has the packet xmt vs xmt serviced threshold been exceeded */ if (sc->lmc_taint_tx == sc->lastlmc_taint_tx && - sc->stats.tx_packets > sc->lasttx_packets && - sc->tx_TimeoutInd == 0) + sc->lmc_device->stats.tx_packets > sc->lasttx_packets && + sc->tx_TimeoutInd == 0) { /* wait for the watchdog to come around again */ sc->tx_TimeoutInd = 1; } else if (sc->lmc_taint_tx == sc->lastlmc_taint_tx && - sc->stats.tx_packets > sc->lasttx_packets && - sc->tx_TimeoutInd) + sc->lmc_device->stats.tx_packets > sc->lasttx_packets && + sc->tx_TimeoutInd) { LMC_EVENT_LOG(LMC_EVENT_XMTINTTMO, LMC_CSR_READ (sc, csr_status), 0); sc->tx_TimeoutDisplay = 1; - sc->stats.tx_TimeoutCnt++; + sc->extra_stats.tx_TimeoutCnt++; /* DEC chip is stuck, hit it with a RESET!!!! */ lmc_running_reset (dev); @@ -712,13 +707,11 @@ static void lmc_watchdog (unsigned long data) /*fold00*/ /* reset the transmit timeout detection flag */ sc->tx_TimeoutInd = 0; sc->lastlmc_taint_tx = sc->lmc_taint_tx; - sc->lasttx_packets = sc->stats.tx_packets; - } - else - { + sc->lasttx_packets = sc->lmc_device->stats.tx_packets; + } else { sc->tx_TimeoutInd = 0; sc->lastlmc_taint_tx = sc->lmc_taint_tx; - sc->lasttx_packets = sc->stats.tx_packets; + sc->lasttx_packets = sc->lmc_device->stats.tx_packets; } /* --- end time out check ----------------------------------- */ @@ -748,19 +741,7 @@ static void lmc_watchdog (unsigned long data) /*fold00*/ sc->last_link_status = 1; /* lmc_reset (sc); Again why reset??? */ - /* Inform the world that link protocol is back up. */ netif_carrier_on(dev); - - /* Now we have to tell the syncppp that we had an outage - * and that it should deal. Calling sppp_reopen here - * should do the trick, but we may have to call sppp_close - * when the link goes down, and call sppp_open here. - * Subject to more testing. - * --bbraun - */ - - lmc_proto_reopen(sc); - } /* Call media specific watchdog functions */ @@ -816,113 +797,98 @@ kick_timer: } -static void lmc_setup(struct net_device * const dev) /*fold00*/ +static int lmc_attach(struct net_device *dev, unsigned short encoding, + unsigned short parity) { - lmc_trace(dev, "lmc_setup in"); - - dev->type = ARPHRD_HDLC; - dev->hard_start_xmit = lmc_start_xmit; - dev->open = lmc_open; - dev->stop = lmc_close; - dev->get_stats = lmc_get_stats; - dev->do_ioctl = lmc_ioctl; - dev->tx_timeout = lmc_driver_timeout; - dev->watchdog_timeo = (HZ); /* 1 second */ - - lmc_trace(dev, "lmc_setup out"); + if (encoding == ENCODING_NRZ && parity == PARITY_CRC16_PR1_CCITT) + return 0; + return -EINVAL; } +static const struct net_device_ops lmc_ops = { + .ndo_open = lmc_open, + .ndo_stop = lmc_close, + .ndo_change_mtu = hdlc_change_mtu, + .ndo_start_xmit = hdlc_start_xmit, + .ndo_do_ioctl = lmc_ioctl, + .ndo_tx_timeout = lmc_driver_timeout, + .ndo_get_stats = lmc_get_stats, +}; -static int __devinit lmc_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int lmc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - struct net_device *dev; - lmc_softc_t *sc; - u16 subdevice; - u_int16_t AdapModelNum; - int err = -ENOMEM; - static int cards_found; -#ifndef GCOM - /* We name by type not by vendor */ - static const char lmcname[] = "hdlc%d"; -#else - /* - * GCOM uses LMC vendor name so that clients can know which card - * to attach to. - */ - static const char lmcname[] = "lmc%d"; -#endif - - - /* - * Allocate our own device structure - */ - dev = alloc_netdev(sizeof(lmc_softc_t), lmcname, lmc_setup); - if (!dev) { - printk (KERN_ERR "lmc:alloc_netdev for device failed\n"); - goto out1; - } - - lmc_trace(dev, "lmc_init_one in"); - - err = pci_enable_device(pdev); - if (err) { - printk(KERN_ERR "lmc: pci enable failed:%d\n", err); - goto out2; - } - - if (pci_request_regions(pdev, "lmc")) { - printk(KERN_ERR "lmc: pci_request_region failed\n"); - err = -EIO; - goto out3; - } - - pci_set_drvdata(pdev, dev); - - if(lmc_first_load == 0){ - printk(KERN_INFO "Lan Media Corporation WAN Driver Version %d.%d.%d\n", - DRIVER_MAJOR_VERSION, DRIVER_MINOR_VERSION,DRIVER_SUB_VERSION); - lmc_first_load = 1; - } - - sc = dev->priv; - sc->lmc_device = dev; - sc->name = dev->name; - - /* Initialize the sppp layer */ - /* An ioctl can cause a subsequent detach for raw frame interface */ - sc->if_type = LMC_PPP; - sc->check = 0xBEAFCAFE; - dev->base_addr = pci_resource_start(pdev, 0); - dev->irq = pdev->irq; - - SET_NETDEV_DEV(dev, &pdev->dev); - - /* - * This will get the protocol layer ready and do any 1 time init's - * Must have a valid sc and dev structure - */ - lmc_proto_init(sc); - - lmc_proto_attach(sc); + lmc_softc_t *sc; + struct net_device *dev; + u16 subdevice; + u16 AdapModelNum; + int err; + static int cards_found; + + /* lmc_trace(dev, "lmc_init_one in"); */ + + err = pci_enable_device(pdev); + if (err) { + printk(KERN_ERR "lmc: pci enable failed: %d\n", err); + return err; + } - /* - * Why were we changing this??? - dev->tx_queue_len = 100; - */ + err = pci_request_regions(pdev, "lmc"); + if (err) { + printk(KERN_ERR "lmc: pci_request_region failed\n"); + goto err_req_io; + } - /* Init the spin lock so can call it latter */ + /* + * Allocate our own device structure + */ + sc = kzalloc(sizeof(lmc_softc_t), GFP_KERNEL); + if (!sc) { + err = -ENOMEM; + goto err_kzalloc; + } - spin_lock_init(&sc->lmc_lock); - pci_set_master(pdev); + dev = alloc_hdlcdev(sc); + if (!dev) { + printk(KERN_ERR "lmc:alloc_netdev for device failed\n"); + goto err_hdlcdev; + } - printk ("%s: detected at %lx, irq %d\n", dev->name, - dev->base_addr, dev->irq); - if (register_netdev (dev) != 0) { - printk (KERN_ERR "%s: register_netdev failed.\n", dev->name); - goto out4; - } + dev->type = ARPHRD_HDLC; + dev_to_hdlc(dev)->xmit = lmc_start_xmit; + dev_to_hdlc(dev)->attach = lmc_attach; + dev->netdev_ops = &lmc_ops; + dev->watchdog_timeo = HZ; /* 1 second */ + dev->tx_queue_len = 100; + sc->lmc_device = dev; + sc->name = dev->name; + sc->if_type = LMC_PPP; + sc->check = 0xBEAFCAFE; + dev->base_addr = pci_resource_start(pdev, 0); + dev->irq = pdev->irq; + pci_set_drvdata(pdev, dev); + SET_NETDEV_DEV(dev, &pdev->dev); + + /* + * This will get the protocol layer ready and do any 1 time init's + * Must have a valid sc and dev structure + */ + lmc_proto_attach(sc); + + /* Init the spin lock so can call it latter */ + + spin_lock_init(&sc->lmc_lock); + pci_set_master(pdev); + + printk(KERN_INFO "%s: detected at %lx, irq %d\n", dev->name, + dev->base_addr, dev->irq); + + err = register_hdlc_device(dev); + if (err) { + printk(KERN_ERR "%s: register_netdev failed.\n", dev->name); + free_netdev(dev); + goto err_hdlcdev; + } sc->lmc_cardtype = LMC_CARDTYPE_UNKNOWN; sc->lmc_timing = LMC_CTL_CLOCK_SOURCE_EXT; @@ -938,27 +904,27 @@ static int __devinit lmc_init_one(struct pci_dev *pdev, switch (subdevice) { case PCI_DEVICE_ID_LMC_HSSI: - printk ("%s: LMC HSSI\n", dev->name); + printk(KERN_INFO "%s: LMC HSSI\n", dev->name); sc->lmc_cardtype = LMC_CARDTYPE_HSSI; sc->lmc_media = &lmc_hssi_media; break; case PCI_DEVICE_ID_LMC_DS3: - printk ("%s: LMC DS3\n", dev->name); + printk(KERN_INFO "%s: LMC DS3\n", dev->name); sc->lmc_cardtype = LMC_CARDTYPE_DS3; sc->lmc_media = &lmc_ds3_media; break; case PCI_DEVICE_ID_LMC_SSI: - printk ("%s: LMC SSI\n", dev->name); + printk(KERN_INFO "%s: LMC SSI\n", dev->name); sc->lmc_cardtype = LMC_CARDTYPE_SSI; sc->lmc_media = &lmc_ssi_media; break; case PCI_DEVICE_ID_LMC_T1: - printk ("%s: LMC T1\n", dev->name); + printk(KERN_INFO "%s: LMC T1\n", dev->name); sc->lmc_cardtype = LMC_CARDTYPE_T1; sc->lmc_media = &lmc_t1_media; break; default: - printk (KERN_WARNING "%s: LMC UNKOWN CARD!\n", dev->name); + printk(KERN_WARNING "%s: LMC UNKNOWN CARD!\n", dev->name); break; } @@ -976,32 +942,28 @@ static int __devinit lmc_init_one(struct pci_dev *pdev, */ AdapModelNum = (lmc_mii_readreg (sc, 0, 3) & 0x3f0) >> 4; - if ((AdapModelNum == LMC_ADAP_T1 - && subdevice == PCI_DEVICE_ID_LMC_T1) || /* detect LMC1200 */ - (AdapModelNum == LMC_ADAP_SSI - && subdevice == PCI_DEVICE_ID_LMC_SSI) || /* detect LMC1000 */ - (AdapModelNum == LMC_ADAP_DS3 - && subdevice == PCI_DEVICE_ID_LMC_DS3) || /* detect LMC5245 */ - (AdapModelNum == LMC_ADAP_HSSI - && subdevice == PCI_DEVICE_ID_LMC_HSSI)) - { /* detect LMC5200 */ + if ((AdapModelNum != LMC_ADAP_T1 || /* detect LMC1200 */ + subdevice != PCI_DEVICE_ID_LMC_T1) && + (AdapModelNum != LMC_ADAP_SSI || /* detect LMC1000 */ + subdevice != PCI_DEVICE_ID_LMC_SSI) && + (AdapModelNum != LMC_ADAP_DS3 || /* detect LMC5245 */ + subdevice != PCI_DEVICE_ID_LMC_DS3) && + (AdapModelNum != LMC_ADAP_HSSI || /* detect LMC5200 */ + subdevice != PCI_DEVICE_ID_LMC_HSSI)) + printk(KERN_WARNING "%s: Model number (%d) miscompare for PCI" + " Subsystem ID = 0x%04x\n", + dev->name, AdapModelNum, subdevice); - } - else { - printk ("%s: Model number (%d) miscompare for PCI Subsystem ID = 0x%04x\n", - dev->name, AdapModelNum, subdevice); -// return (NULL); - } /* * reset clock */ LMC_CSR_WRITE (sc, csr_gp_timer, 0xFFFFFFFFUL); sc->board_idx = cards_found++; - sc->stats.check = STATCHECK; - sc->stats.version_size = (DRIVER_VERSION << 16) + - sizeof (struct lmc_statistics); - sc->stats.lmc_cardtype = sc->lmc_cardtype; + sc->extra_stats.check = STATCHECK; + sc->extra_stats.version_size = (DRIVER_VERSION << 16) + + sizeof(sc->lmc_device->stats) + sizeof(sc->extra_stats); + sc->extra_stats.lmc_cardtype = sc->lmc_cardtype; sc->lmc_ok = 0; sc->last_link_status = 0; @@ -1009,68 +971,59 @@ static int __devinit lmc_init_one(struct pci_dev *pdev, lmc_trace(dev, "lmc_init_one out"); return 0; - out4: - lmc_proto_detach(sc); - out3: - if (pdev) { - pci_release_regions(pdev); - pci_set_drvdata(pdev, NULL); - } - out2: - free_netdev(dev); - out1: - return err; +err_hdlcdev: + kfree(sc); +err_kzalloc: + pci_release_regions(pdev); +err_req_io: + pci_disable_device(pdev); + return err; } /* * Called from pci when removing module. */ -static void __devexit lmc_remove_one (struct pci_dev *pdev) +static void lmc_remove_one(struct pci_dev *pdev) { - struct net_device *dev = pci_get_drvdata(pdev); - - if (dev) { - lmc_softc_t *sc = dev->priv; - - printk("%s: removing...\n", dev->name); - lmc_proto_detach(sc); - unregister_netdev(dev); - free_netdev(dev); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } + struct net_device *dev = pci_get_drvdata(pdev); + + if (dev) { + printk(KERN_DEBUG "%s: removing...\n", dev->name); + unregister_hdlc_device(dev); + free_netdev(dev); + pci_release_regions(pdev); + pci_disable_device(pdev); + } } /* After this is called, packets can be sent. * Does not initialize the addresses */ -static int lmc_open (struct net_device *dev) /*fold00*/ +static int lmc_open(struct net_device *dev) { - lmc_softc_t *sc = dev->priv; + lmc_softc_t *sc = dev_to_sc(dev); + int err; lmc_trace(dev, "lmc_open in"); lmc_led_on(sc, LMC_DS3_LED0); - lmc_dec_reset (sc); - lmc_reset (sc); - - LMC_EVENT_LOG(LMC_EVENT_RESET1, LMC_CSR_READ (sc, csr_status), 0); - LMC_EVENT_LOG(LMC_EVENT_RESET2, - lmc_mii_readreg (sc, 0, 16), - lmc_mii_readreg (sc, 0, 17)); + lmc_dec_reset(sc); + lmc_reset(sc); + LMC_EVENT_LOG(LMC_EVENT_RESET1, LMC_CSR_READ(sc, csr_status), 0); + LMC_EVENT_LOG(LMC_EVENT_RESET2, lmc_mii_readreg(sc, 0, 16), + lmc_mii_readreg(sc, 0, 17)); if (sc->lmc_ok){ lmc_trace(dev, "lmc_open lmc_ok out"); - return (0); + return 0; } lmc_softreset (sc); /* Since we have to use PCI bus, this should work on x86,alpha,ppc */ - if (request_irq (dev->irq, &lmc_interrupt, IRQF_SHARED, dev->name, dev)){ + if (request_irq (dev->irq, lmc_interrupt, IRQF_SHARED, dev->name, dev)){ printk(KERN_WARNING "%s: could not get irq: %d\n", dev->name, dev->irq); lmc_trace(dev, "lmc_open irq failed out"); return -EAGAIN; @@ -1105,14 +1058,11 @@ static int lmc_open (struct net_device *dev) /*fold00*/ /* dev->flags |= IFF_UP; */ - lmc_proto_open(sc); - - dev->do_ioctl = lmc_ioctl; - + if ((err = lmc_proto_open(sc)) != 0) + return err; netif_start_queue(dev); - - sc->stats.tx_tbusy0++ ; + sc->extra_stats.tx_tbusy0++; /* * select what interrupts we want to get @@ -1150,12 +1100,12 @@ static int lmc_open (struct net_device *dev) /*fold00*/ init_timer (&sc->timer); sc->timer.expires = jiffies + HZ; sc->timer.data = (unsigned long) dev; - sc->timer.function = &lmc_watchdog; + sc->timer.function = lmc_watchdog; add_timer (&sc->timer); lmc_trace(dev, "lmc_open out"); - return (0); + return 0; } /* Total reset to compensate for the AdTran DSU doing bad things @@ -1164,10 +1114,9 @@ static int lmc_open (struct net_device *dev) /*fold00*/ static void lmc_running_reset (struct net_device *dev) /*fold00*/ { + lmc_softc_t *sc = dev_to_sc(dev); - lmc_softc_t *sc = (lmc_softc_t *) dev->priv; - - lmc_trace(dev, "lmc_runnig_reset in"); + lmc_trace(dev, "lmc_running_reset in"); /* stop interrupts */ /* Clear the interrupt mask */ @@ -1183,7 +1132,7 @@ static void lmc_running_reset (struct net_device *dev) /*fold00*/ netif_wake_queue(dev); sc->lmc_txfull = 0; - sc->stats.tx_tbusy0++ ; + sc->extra_stats.tx_tbusy0++; sc->lmc_intrmask = TULIP_DEFAULT_INTR_MASK; LMC_CSR_WRITE (sc, csr_intr, sc->lmc_intrmask); @@ -1199,14 +1148,13 @@ static void lmc_running_reset (struct net_device *dev) /*fold00*/ * This disables the timer for the watchdog and keepalives, * and disables the irq for dev. */ -static int lmc_close (struct net_device *dev) /*fold00*/ +static int lmc_close(struct net_device *dev) { /* not calling release_region() as we should */ - lmc_softc_t *sc; + lmc_softc_t *sc = dev_to_sc(dev); lmc_trace(dev, "lmc_close in"); - - sc = dev->priv; + sc->lmc_ok = 0; sc->lmc_media->set_link_status (sc, 0); del_timer (&sc->timer); @@ -1214,7 +1162,7 @@ static int lmc_close (struct net_device *dev) /*fold00*/ lmc_ifdown (dev); lmc_trace(dev, "lmc_close out"); - + return 0; } @@ -1222,16 +1170,16 @@ static int lmc_close (struct net_device *dev) /*fold00*/ /* When the interface goes down, this is called */ static int lmc_ifdown (struct net_device *dev) /*fold00*/ { - lmc_softc_t *sc = dev->priv; + lmc_softc_t *sc = dev_to_sc(dev); u32 csr6; int i; lmc_trace(dev, "lmc_ifdown in"); - + /* Don't let anything else go on right now */ // dev->start = 0; netif_stop_queue(dev); - sc->stats.tx_tbusy1++ ; + sc->extra_stats.tx_tbusy1++; /* stop interrupts */ /* Clear the interrupt mask */ @@ -1243,8 +1191,8 @@ static int lmc_ifdown (struct net_device *dev) /*fold00*/ csr6 &= ~LMC_DEC_SR; /* Turn off the Receive bit */ LMC_CSR_WRITE (sc, csr_command, csr6); - sc->stats.rx_missed_errors += - LMC_CSR_READ (sc, csr_missed_frames) & 0xffff; + sc->lmc_device->stats.rx_missed_errors += + LMC_CSR_READ(sc, csr_missed_frames) & 0xffff; /* release the interrupt */ if(sc->got_irq == 1){ @@ -1275,7 +1223,7 @@ static int lmc_ifdown (struct net_device *dev) /*fold00*/ lmc_led_off (sc, LMC_MII16_LED_ALL); netif_wake_queue(dev); - sc->stats.tx_tbusy0++ ; + sc->extra_stats.tx_tbusy0++; lmc_trace(dev, "lmc_ifdown out"); @@ -1288,7 +1236,7 @@ static int lmc_ifdown (struct net_device *dev) /*fold00*/ static irqreturn_t lmc_interrupt (int irq, void *dev_instance) /*fold00*/ { struct net_device *dev = (struct net_device *) dev_instance; - lmc_softc_t *sc; + lmc_softc_t *sc = dev_to_sc(dev); u32 csr; int i; s32 stat; @@ -1299,8 +1247,6 @@ static irqreturn_t lmc_interrupt (int irq, void *dev_instance) /*fold00*/ lmc_trace(dev, "lmc_interrupt in"); - sc = dev->priv; - spin_lock(&sc->lmc_lock); /* @@ -1353,7 +1299,7 @@ static irqreturn_t lmc_interrupt (int irq, void *dev_instance) /*fold00*/ int n_compl = 0 ; /* reset the transmit timeout detection flag -baz */ - sc->stats.tx_NoCompleteCnt = 0; + sc->extra_stats.tx_NoCompleteCnt = 0; badtx = sc->lmc_taint_tx; i = badtx % LMC_TXDESCS; @@ -1377,27 +1323,25 @@ static irqreturn_t lmc_interrupt (int irq, void *dev_instance) /*fold00*/ if (sc->lmc_txq[i] == NULL) continue; - /* - * Check the total error summary to look for any errors - */ - if (stat & 0x8000) { - sc->stats.tx_errors++; - if (stat & 0x4104) - sc->stats.tx_aborted_errors++; - if (stat & 0x0C00) - sc->stats.tx_carrier_errors++; - if (stat & 0x0200) - sc->stats.tx_window_errors++; - if (stat & 0x0002) - sc->stats.tx_fifo_errors++; + /* + * Check the total error summary to look for any errors + */ + if (stat & 0x8000) { + sc->lmc_device->stats.tx_errors++; + if (stat & 0x4104) + sc->lmc_device->stats.tx_aborted_errors++; + if (stat & 0x0C00) + sc->lmc_device->stats.tx_carrier_errors++; + if (stat & 0x0200) + sc->lmc_device->stats.tx_window_errors++; + if (stat & 0x0002) + sc->lmc_device->stats.tx_fifo_errors++; + } else { + sc->lmc_device->stats.tx_bytes += sc->lmc_txring[i].length & 0x7ff; + + sc->lmc_device->stats.tx_packets++; } - else { - - sc->stats.tx_bytes += sc->lmc_txring[i].length & 0x7ff; - - sc->stats.tx_packets++; - } - + // dev_kfree_skb(sc->lmc_txq[i]); dev_kfree_skb_irq(sc->lmc_txq[i]); sc->lmc_txq[i] = NULL; @@ -1414,13 +1358,13 @@ static irqreturn_t lmc_interrupt (int irq, void *dev_instance) /*fold00*/ LMC_EVENT_LOG(LMC_EVENT_TBUSY0, n_compl, 0); sc->lmc_txfull = 0; netif_wake_queue(dev); - sc->stats.tx_tbusy0++ ; + sc->extra_stats.tx_tbusy0++; #ifdef DEBUG - sc->stats.dirtyTx = badtx; - sc->stats.lmc_next_tx = sc->lmc_next_tx; - sc->stats.lmc_txfull = sc->lmc_txfull; + sc->extra_stats.dirtyTx = badtx; + sc->extra_stats.lmc_next_tx = sc->lmc_next_tx; + sc->extra_stats.lmc_txfull = sc->lmc_txfull; #endif sc->lmc_taint_tx = badtx; @@ -1475,18 +1419,16 @@ lmc_int_fail_out: return IRQ_RETVAL(handled); } -static int lmc_start_xmit (struct sk_buff *skb, struct net_device *dev) /*fold00*/ +static netdev_tx_t lmc_start_xmit(struct sk_buff *skb, + struct net_device *dev) { - lmc_softc_t *sc; + lmc_softc_t *sc = dev_to_sc(dev); u32 flag; int entry; - int ret = 0; unsigned long flags; lmc_trace(dev, "lmc_start_xmit in"); - sc = dev->priv; - spin_lock_irqsave(&sc->lmc_lock, flags); /* normal path, tbusy known to be zero */ @@ -1531,8 +1473,8 @@ static int lmc_start_xmit (struct sk_buff *skb, struct net_device *dev) /*fold00 if (sc->lmc_next_tx - sc->lmc_taint_tx >= LMC_TXDESCS - 1) { /* ring full, go busy */ sc->lmc_txfull = 1; - netif_stop_queue(dev); - sc->stats.tx_tbusy1++ ; + netif_stop_queue(dev); + sc->extra_stats.tx_tbusy1++; LMC_EVENT_LOG(LMC_EVENT_TBUSY1, entry, 0); } #endif @@ -1549,7 +1491,7 @@ static int lmc_start_xmit (struct sk_buff *skb, struct net_device *dev) /*fold00 * the watchdog timer handler. -baz */ - sc->stats.tx_NoCompleteCnt++; + sc->extra_stats.tx_NoCompleteCnt++; sc->lmc_next_tx++; /* give ownership to the chip */ @@ -1559,18 +1501,16 @@ static int lmc_start_xmit (struct sk_buff *skb, struct net_device *dev) /*fold00 /* send now! */ LMC_CSR_WRITE (sc, csr_txpoll, 0); - dev->trans_start = jiffies; - spin_unlock_irqrestore(&sc->lmc_lock, flags); lmc_trace(dev, "lmc_start_xmit_out"); - return ret; + return NETDEV_TX_OK; } -static int lmc_rx (struct net_device *dev) /*fold00*/ +static int lmc_rx(struct net_device *dev) { - lmc_softc_t *sc; + lmc_softc_t *sc = dev_to_sc(dev); int i; int rx_work_limit = LMC_RXDESCS; unsigned int next_rx; @@ -1582,8 +1522,6 @@ static int lmc_rx (struct net_device *dev) /*fold00*/ lmc_trace(dev, "lmc_rx in"); - sc = dev->priv; - lmc_led_on(sc, LMC_DS3_LED3); rxIntLoopCnt = 0; /* debug -baz */ @@ -1596,39 +1534,38 @@ static int lmc_rx (struct net_device *dev) /*fold00*/ rxIntLoopCnt++; /* debug -baz */ len = ((stat & LMC_RDES_FRAME_LENGTH) >> RDES_FRAME_LENGTH_BIT_NUMBER); if ((stat & 0x0300) != 0x0300) { /* Check first segment and last segment */ - if ((stat & 0x0000ffff) != 0x7fff) { - /* Oversized frame */ - sc->stats.rx_length_errors++; - goto skip_packet; - } - } - - if(stat & 0x00000008){ /* Catch a dribbling bit error */ - sc->stats.rx_errors++; - sc->stats.rx_frame_errors++; - goto skip_packet; - } + if ((stat & 0x0000ffff) != 0x7fff) { + /* Oversized frame */ + sc->lmc_device->stats.rx_length_errors++; + goto skip_packet; + } + } + if (stat & 0x00000008) { /* Catch a dribbling bit error */ + sc->lmc_device->stats.rx_errors++; + sc->lmc_device->stats.rx_frame_errors++; + goto skip_packet; + } - if(stat & 0x00000004){ /* Catch a CRC error by the Xilinx */ - sc->stats.rx_errors++; - sc->stats.rx_crc_errors++; - goto skip_packet; - } + if (stat & 0x00000004) { /* Catch a CRC error by the Xilinx */ + sc->lmc_device->stats.rx_errors++; + sc->lmc_device->stats.rx_crc_errors++; + goto skip_packet; + } - if (len > LMC_PKT_BUF_SZ){ - sc->stats.rx_length_errors++; - localLengthErrCnt++; - goto skip_packet; - } + if (len > LMC_PKT_BUF_SZ) { + sc->lmc_device->stats.rx_length_errors++; + localLengthErrCnt++; + goto skip_packet; + } - if (len < sc->lmc_crcSize + 2) { - sc->stats.rx_length_errors++; - sc->stats.rx_SmallPktCnt++; - localLengthErrCnt++; - goto skip_packet; - } + if (len < sc->lmc_crcSize + 2) { + sc->lmc_device->stats.rx_length_errors++; + sc->extra_stats.rx_SmallPktCnt++; + localLengthErrCnt++; + goto skip_packet; + } if(stat & 0x00004000){ printk(KERN_WARNING "%s: Receiver descriptor error, receiver out of sync?\n", dev->name); @@ -1654,9 +1591,8 @@ static int lmc_rx (struct net_device *dev) /*fold00*/ goto skip_packet; } - dev->last_rx = jiffies; - sc->stats.rx_packets++; - sc->stats.rx_bytes += len; + sc->lmc_device->stats.rx_packets++; + sc->lmc_device->stats.rx_bytes += len; LMC_CONSOLE_LOG("recv", skb->data, len); @@ -1678,7 +1614,6 @@ static int lmc_rx (struct net_device *dev) /*fold00*/ skb_put (skb, len); skb->protocol = lmc_proto_type(sc, skb); - skb->protocol = htons(ETH_P_WAN_PPP); skb_reset_mac_header(skb); /* skb_reset_network_header(skb); */ skb->dev = dev; @@ -1703,7 +1638,7 @@ static int lmc_rx (struct net_device *dev) /*fold00*/ * in which care we'll try to allocate the buffer * again. (once a second) */ - sc->stats.rx_BuffAllocErr++; + sc->extra_stats.rx_BuffAllocErr++; LMC_EVENT_LOG(LMC_EVENT_RCVINT, stat, len); sc->failed_recv_alloc = 1; goto skip_out_of_mem; @@ -1716,7 +1651,7 @@ static int lmc_rx (struct net_device *dev) /*fold00*/ } skb_copy_from_linear_data(skb, skb_put(nsb, len), len); - nsb->protocol = lmc_proto_type(sc, skb); + nsb->protocol = lmc_proto_type(sc, nsb); skb_reset_mac_header(nsb); /* skb_reset_network_header(nsb); */ nsb->dev = dev; @@ -1738,16 +1673,14 @@ static int lmc_rx (struct net_device *dev) /*fold00*/ * descriptors with bogus packets * if (localLengthErrCnt > LMC_RXDESCS - 3) { - sc->stats.rx_BadPktSurgeCnt++; - LMC_EVENT_LOG(LMC_EVENT_BADPKTSURGE, - localLengthErrCnt, - sc->stats.rx_BadPktSurgeCnt); + sc->extra_stats.rx_BadPktSurgeCnt++; + LMC_EVENT_LOG(LMC_EVENT_BADPKTSURGE, localLengthErrCnt, + sc->extra_stats.rx_BadPktSurgeCnt); } */ /* save max count of receive descriptors serviced */ - if (rxIntLoopCnt > sc->stats.rxIntLoopCnt) { - sc->stats.rxIntLoopCnt = rxIntLoopCnt; /* debug -baz */ - } + if (rxIntLoopCnt > sc->extra_stats.rxIntLoopCnt) + sc->extra_stats.rxIntLoopCnt = rxIntLoopCnt; /* debug -baz */ #ifdef DEBUG if (rxIntLoopCnt == 0) @@ -1774,44 +1707,32 @@ skip_out_of_mem: return 0; } -static struct net_device_stats *lmc_get_stats (struct net_device *dev) /*fold00*/ +static struct net_device_stats *lmc_get_stats(struct net_device *dev) { - lmc_softc_t *sc = dev->priv; + lmc_softc_t *sc = dev_to_sc(dev); unsigned long flags; lmc_trace(dev, "lmc_get_stats in"); - spin_lock_irqsave(&sc->lmc_lock, flags); - sc->stats.rx_missed_errors += LMC_CSR_READ (sc, csr_missed_frames) & 0xffff; + sc->lmc_device->stats.rx_missed_errors += LMC_CSR_READ(sc, csr_missed_frames) & 0xffff; spin_unlock_irqrestore(&sc->lmc_lock, flags); lmc_trace(dev, "lmc_get_stats out"); - return (struct net_device_stats *) &sc->stats; + return &sc->lmc_device->stats; } static struct pci_driver lmc_driver = { .name = "lmc", .id_table = lmc_pci_tbl, .probe = lmc_init_one, - .remove = __devexit_p(lmc_remove_one), + .remove = lmc_remove_one, }; -static int __init init_lmc(void) -{ - return pci_register_driver(&lmc_driver); -} - -static void __exit exit_lmc(void) -{ - pci_unregister_driver(&lmc_driver); -} - -module_init(init_lmc); -module_exit(exit_lmc); +module_pci_driver(lmc_driver); unsigned lmc_mii_readreg (lmc_softc_t * const sc, unsigned devaddr, unsigned regno) /*fold00*/ { @@ -1959,17 +1880,18 @@ static void lmc_softreset (lmc_softc_t * const sc) /*fold00*/ /* * Sets end of ring */ - sc->lmc_rxring[i - 1].length |= 0x02000000; /* Set end of buffers flag */ - sc->lmc_rxring[i - 1].buffer2 = virt_to_bus (&sc->lmc_rxring[0]); /* Point back to the start */ + if (i != 0) { + sc->lmc_rxring[i - 1].length |= 0x02000000; /* Set end of buffers flag */ + sc->lmc_rxring[i - 1].buffer2 = virt_to_bus(&sc->lmc_rxring[0]); /* Point back to the start */ + } LMC_CSR_WRITE (sc, csr_rxlist, virt_to_bus (sc->lmc_rxring)); /* write base address */ - /* Initialize the transmit rings and buffers */ for (i = 0; i < LMC_TXDESCS; i++) { if (sc->lmc_txq[i] != NULL){ /* have buffer */ dev_kfree_skb(sc->lmc_txq[i]); /* free it */ - sc->stats.tx_dropped++; /* We just dropped a packet */ + sc->lmc_device->stats.tx_dropped++; /* We just dropped a packet */ } sc->lmc_txq[i] = NULL; sc->lmc_txring[i].status = 0x00000000; @@ -1981,7 +1903,7 @@ static void lmc_softreset (lmc_softc_t * const sc) /*fold00*/ lmc_trace(sc->lmc_device, "lmc_softreset out"); } -void lmc_gpio_mkinput(lmc_softc_t * const sc, u_int32_t bits) /*fold00*/ +void lmc_gpio_mkinput(lmc_softc_t * const sc, u32 bits) /*fold00*/ { lmc_trace(sc->lmc_device, "lmc_gpio_mkinput in"); sc->lmc_gpio_io &= ~bits; @@ -1989,7 +1911,7 @@ void lmc_gpio_mkinput(lmc_softc_t * const sc, u_int32_t bits) /*fold00*/ lmc_trace(sc->lmc_device, "lmc_gpio_mkinput out"); } -void lmc_gpio_mkoutput(lmc_softc_t * const sc, u_int32_t bits) /*fold00*/ +void lmc_gpio_mkoutput(lmc_softc_t * const sc, u32 bits) /*fold00*/ { lmc_trace(sc->lmc_device, "lmc_gpio_mkoutput in"); sc->lmc_gpio_io |= bits; @@ -1997,7 +1919,7 @@ void lmc_gpio_mkoutput(lmc_softc_t * const sc, u_int32_t bits) /*fold00*/ lmc_trace(sc->lmc_device, "lmc_gpio_mkoutput out"); } -void lmc_led_on(lmc_softc_t * const sc, u_int32_t led) /*fold00*/ +void lmc_led_on(lmc_softc_t * const sc, u32 led) /*fold00*/ { lmc_trace(sc->lmc_device, "lmc_led_on in"); if((~sc->lmc_miireg16) & led){ /* Already on! */ @@ -2010,7 +1932,7 @@ void lmc_led_on(lmc_softc_t * const sc, u_int32_t led) /*fold00*/ lmc_trace(sc->lmc_device, "lmc_led_on out"); } -void lmc_led_off(lmc_softc_t * const sc, u_int32_t led) /*fold00*/ +void lmc_led_off(lmc_softc_t * const sc, u32 led) /*fold00*/ { lmc_trace(sc->lmc_device, "lmc_led_off in"); if(sc->lmc_miireg16 & led){ /* Already set don't do anything */ @@ -2060,13 +1982,13 @@ static void lmc_reset(lmc_softc_t * const sc) /*fold00*/ */ sc->lmc_media->init(sc); - sc->stats.resetCount++; + sc->extra_stats.resetCount++; lmc_trace(sc->lmc_device, "lmc_reset out"); } static void lmc_dec_reset(lmc_softc_t * const sc) /*fold00*/ { - u_int32_t val; + u32 val; lmc_trace(sc->lmc_device, "lmc_dec_reset in"); /* @@ -2150,23 +2072,21 @@ static void lmc_initcsrs(lmc_softc_t * const sc, lmc_csrptr_t csr_base, /*fold00 lmc_trace(sc->lmc_device, "lmc_initcsrs out"); } -static void lmc_driver_timeout(struct net_device *dev) { /*fold00*/ - lmc_softc_t *sc; +static void lmc_driver_timeout(struct net_device *dev) +{ + lmc_softc_t *sc = dev_to_sc(dev); u32 csr6; unsigned long flags; lmc_trace(dev, "lmc_driver_timeout in"); - sc = dev->priv; - spin_lock_irqsave(&sc->lmc_lock, flags); printk("%s: Xmitter busy|\n", dev->name); - sc->stats.tx_tbusy_calls++ ; - if (jiffies - dev->trans_start < TX_TIMEOUT) { - goto bug_out; - } + sc->extra_stats.tx_tbusy_calls++; + if (jiffies - dev_trans_start(dev) < TX_TIMEOUT) + goto bug_out; /* * Chip seems to have locked up @@ -2177,7 +2097,7 @@ static void lmc_driver_timeout(struct net_device *dev) { /*fold00*/ LMC_EVENT_LOG(LMC_EVENT_XMTPRCTMO, LMC_CSR_READ (sc, csr_status), - sc->stats.tx_ProcTimeout); + sc->extra_stats.tx_ProcTimeout); lmc_running_reset (dev); @@ -2194,16 +2114,16 @@ static void lmc_driver_timeout(struct net_device *dev) { /*fold00*/ /* immediate transmit */ LMC_CSR_WRITE (sc, csr_txpoll, 0); - sc->stats.tx_errors++; - sc->stats.tx_ProcTimeout++; /* -baz */ + sc->lmc_device->stats.tx_errors++; + sc->extra_stats.tx_ProcTimeout++; /* -baz */ - dev->trans_start = jiffies; + dev->trans_start = jiffies; /* prevent tx timeout */ bug_out: spin_unlock_irqrestore(&sc->lmc_lock, flags); - lmc_trace(dev, "lmc_driver_timout out"); + lmc_trace(dev, "lmc_driver_timeout out"); } |
