X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fnet%2Fns83820.c;h=23397f994436fba66b86b3907ce27975b7d1dad2;hb=16c70f8c1b54b61c3b951b6fb220df250fe09b32;hp=0ff2d422383649d521fb83f27b0ad31731da891f;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c index 0ff2d4223..23397f994 100644 --- a/drivers/net/ns83820.c +++ b/drivers/net/ns83820.c @@ -1,4 +1,4 @@ -#define _VERSION "0.20" +#define VERSION "0.22" /* ns83820.c by Benjamin LaHaise with contributions. * * Questions/comments/discussion to linux-ns83820@kvack.org. @@ -63,7 +63,11 @@ * - fix missed txok introduced during performance * tuning * 0.20 - fix stupid RFEN thinko. i am such a smurf. - * + * 20040828 0.21 - add hardware vlan accleration + * by Neil Horman + * 20050406 0.22 - improved DAC ifdefs from Andi Kleen + * - removal of dead code from Adrian Bunk + * - fix half duplex collision behaviour * Driver Overview * =============== * @@ -93,8 +97,10 @@ #define dprintk(x...) do { } while (0) #include +#include #include #include +#include #include #include #include @@ -103,17 +109,21 @@ #include #include /* for iph */ #include /* for IPPROTO_... */ -#include #include #include #include #include +#include +#include +#include #include #include #include -/* Global parameters. See MODULE_PARM near the bottom. */ +#define DRV_NAME "ns83820" + +/* Global parameters. See module_param near the bottom. */ static int ihr = 2; static int reset_phy = 0; static int lnksts = 0; /* CFG_LNKSTS bit polarity */ @@ -122,20 +132,11 @@ static int lnksts = 0; /* CFG_LNKSTS bit polarity */ #undef Dprintk #define Dprintk dprintk -#if defined(CONFIG_HIGHMEM64G) || defined(__ia64__) -#define USE_64BIT_ADDR "+" -#endif - -#if defined(USE_64BIT_ADDR) -#define VERSION _VERSION USE_64BIT_ADDR -#define TRY_DAC 1 -#else -#define VERSION _VERSION -#define TRY_DAC 0 -#endif - /* tunables */ #define RX_BUF_SIZE 1500 /* 8192 */ +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) +#define NS83820_VLAN_ACCEL_SUPPORT +#endif /* Must not exceed ~65000. */ #define NR_RX_DESC 64 @@ -260,6 +261,8 @@ static int lnksts = 0; /* CFG_LNKSTS bit polarity */ #define EXTSTS_UDPPKT 0x00200000 #define EXTSTS_TCPPKT 0x00080000 #define EXTSTS_IPPKT 0x00020000 +#define EXTSTS_VPKT 0x00010000 +#define EXTSTS_VTG_MASK 0x0000ffff #define SPDSTS_POLARITY (CFG_SPDSTS1 | CFG_SPDSTS0 | CFG_DUPSTS | (lnksts ? CFG_LNKSTS : 0)) @@ -374,22 +377,16 @@ static int lnksts = 0; /* CFG_LNKSTS bit polarity */ #define LINK_DOWN 0x02 #define LINK_UP 0x04 -#ifdef USE_64BIT_ADDR -#define HW_ADDR_LEN 8 +#define HW_ADDR_LEN sizeof(dma_addr_t) #define desc_addr_set(desc, addr) \ do { \ - u64 __addr = (addr); \ - (desc)[0] = cpu_to_le32(__addr); \ - (desc)[1] = cpu_to_le32(__addr >> 32); \ + ((desc)[0] = cpu_to_le32(addr)); \ + if (HW_ADDR_LEN == 8) \ + (desc)[1] = cpu_to_le32(((u64)addr) >> 32); \ } while(0) #define desc_addr_get(desc) \ - (((u64)le32_to_cpu((desc)[1]) << 32) \ - | le32_to_cpu((desc)[0])) -#else -#define HW_ADDR_LEN 4 -#define desc_addr_set(desc, addr) ((desc)[0] = cpu_to_le32(addr)) -#define desc_addr_get(desc) (le32_to_cpu((desc)[0])) -#endif + (le32_to_cpu((desc)[0]) | \ + (HW_ADDR_LEN == 8 ? ((dma_addr_t)le32_to_cpu((desc)[1]))<<32 : 0)) #define DESC_LINK 0 #define DESC_BUFPTR (DESC_LINK + HW_ADDR_LEN/4) @@ -401,6 +398,7 @@ static int lnksts = 0; /* CFG_LNKSTS bit polarity */ #define CMDSTS_INTR 0x20000000 #define CMDSTS_ERR 0x10000000 #define CMDSTS_OK 0x08000000 +#define CMDSTS_RUNT 0x00200000 #define CMDSTS_LEN_MASK 0x0000ffff #define CMDSTS_DEST_MASK 0x01800000 @@ -426,10 +424,14 @@ struct rx_info { struct ns83820 { struct net_device_stats stats; - u8 *base; + u8 __iomem *base; struct pci_dev *pci_dev; +#ifdef NS83820_VLAN_ACCEL_SUPPORT + struct vlan_group *vlgrp; +#endif + struct rx_info rx_info; struct tasklet_struct rx_tasklet; @@ -443,7 +445,6 @@ struct ns83820 { u32 MEAR_cache; u32 IMR_cache; - struct eeprom ee; unsigned linkstate; @@ -492,6 +493,33 @@ static inline void kick_rx(struct net_device *ndev) (((NR_TX_DESC-2 + dev->tx_done_idx - dev->tx_free_idx) % NR_TX_DESC) > MIN_TX_DESC_FREE) +#ifdef NS83820_VLAN_ACCEL_SUPPORT +static void ns83820_vlan_rx_register(struct net_device *ndev, struct vlan_group *grp) +{ + struct ns83820 *dev = PRIV(ndev); + + spin_lock_irq(&dev->misc_lock); + spin_lock(&dev->tx_lock); + + dev->vlgrp = grp; + + spin_unlock(&dev->tx_lock); + spin_unlock_irq(&dev->misc_lock); +} + +static void ns83820_vlan_rx_kill_vid(struct net_device *ndev, unsigned short vid) +{ + struct ns83820 *dev = PRIV(ndev); + + spin_lock_irq(&dev->misc_lock); + spin_lock(&dev->tx_lock); + if (dev->vlgrp) + dev->vlgrp->vlan_devices[vid] = NULL; + spin_unlock(&dev->tx_lock); + spin_unlock_irq(&dev->misc_lock); +} +#endif + /* Packet Receiver * * The hardware supports linked lists of receive descriptors for @@ -539,13 +567,12 @@ static inline int ns83820_add_rx_skb(struct ns83820 *dev, struct sk_buff *skb) #endif sg = dev->rx_info.descs + (next_empty * DESC_SIZE); - if (unlikely(NULL != dev->rx_info.skbs[next_empty])) - BUG(); + BUG_ON(NULL != dev->rx_info.skbs[next_empty]); dev->rx_info.skbs[next_empty] = skb; dev->rx_info.next_empty = (next_empty + 1) % NR_RX_DESC; cmdsts = REAL_RX_BUF_SIZE | CMDSTS_INTR; - buf = pci_map_single(dev->pci_dev, skb->tail, + buf = pci_map_single(dev->pci_dev, skb->data, REAL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); build_rx_desc(dev, sg, 0, buf, cmdsts, 0); /* update link of previous rx */ @@ -555,7 +582,7 @@ static inline int ns83820_add_rx_skb(struct ns83820 *dev, struct sk_buff *skb) return 0; } -static inline int rx_refill(struct net_device *ndev, int gfp) +static inline int rx_refill(struct net_device *ndev, gfp_t gfp) { struct ns83820 *dev = PRIV(ndev); unsigned i; @@ -575,7 +602,7 @@ static inline int rx_refill(struct net_device *ndev, int gfp) if (unlikely(!skb)) break; - res = (long)skb->tail & 0xf; + res = (long)skb->data & 0xf; res = 0x10 - res; res &= 0xf; skb_reserve(skb, res); @@ -623,7 +650,7 @@ static void FASTCALL(phy_intr(struct net_device *ndev)); static void fastcall phy_intr(struct net_device *ndev) { struct ns83820 *dev = PRIV(ndev); - static char *speeds[] = { "10", "100", "1000", "1000(?)", "1000F" }; + static const char *speeds[] = { "10", "100", "1000", "1000(?)", "1000F" }; u32 cfg, new_cfg; u32 tbisr, tanar, tanlpar; int speed, fullduplex, newlinkstate; @@ -683,11 +710,23 @@ static void fastcall phy_intr(struct net_device *ndev) speed = ((cfg / CFG_SPDSTS0) & 3); fullduplex = (cfg & CFG_DUPSTS); - if (fullduplex) + if (fullduplex) { new_cfg |= CFG_SB; + writel(readl(dev->base + TXCFG) + | TXCFG_CSI | TXCFG_HBI, + dev->base + TXCFG); + writel(readl(dev->base + RXCFG) | RXCFG_RX_FD, + dev->base + RXCFG); + } else { + writel(readl(dev->base + TXCFG) + & ~(TXCFG_CSI | TXCFG_HBI), + dev->base + TXCFG); + writel(readl(dev->base + RXCFG) & ~(RXCFG_RX_FD), + dev->base + RXCFG); + } if ((cfg & CFG_LNKSTS) && - ((new_cfg ^ dev->CFG_cache) & CFG_MODE_1000)) { + ((new_cfg ^ dev->CFG_cache) != 0)) { writel(new_cfg, dev->base + CFG); dev->CFG_cache = new_cfg; } @@ -764,7 +803,7 @@ static int ns83820_setup_rx(struct net_device *ndev) writel(dev->IMR_cache, dev->base + IMR); writel(1, dev->base + IER); - spin_unlock_irq(&dev->misc_lock); + spin_unlock(&dev->misc_lock); kick_rx(ndev); @@ -834,6 +873,7 @@ static void fastcall rx_irq(struct net_device *ndev) struct ns83820 *dev = PRIV(ndev); struct rx_info *info = &dev->rx_info; unsigned next_rx; + int rx_rc, len; u32 cmdsts, *desc; unsigned long flags; int nr = 0; @@ -874,8 +914,24 @@ static void fastcall rx_irq(struct net_device *ndev) pci_unmap_single(dev->pci_dev, bufptr, RX_BUF_SIZE, PCI_DMA_FROMDEVICE); + len = cmdsts & CMDSTS_LEN_MASK; +#ifdef NS83820_VLAN_ACCEL_SUPPORT + /* NH: As was mentioned below, this chip is kinda + * brain dead about vlan tag stripping. Frames + * that are 64 bytes with a vlan header appended + * like arp frames, or pings, are flagged as Runts + * when the tag is stripped and hardware. This + * also means that the OK bit in the descriptor + * is cleared when the frame comes in so we have + * to do a specific length check here to make sure + * the frame would have been ok, had we not stripped + * the tag. + */ + if (likely((CMDSTS_OK & cmdsts) || + ((cmdsts & CMDSTS_RUNT) && len >= 56))) { +#else if (likely(CMDSTS_OK & cmdsts)) { - int len = cmdsts & 0xffff; +#endif skb_put(skb, len); if (unlikely(!skb)) goto netdev_mangle_me_harder_failed; @@ -889,7 +945,18 @@ static void fastcall rx_irq(struct net_device *ndev) skb->ip_summed = CHECKSUM_NONE; } skb->protocol = eth_type_trans(skb, ndev); - if (NET_RX_DROP == netif_rx(skb)) { +#ifdef NS83820_VLAN_ACCEL_SUPPORT + if(extsts & EXTSTS_VPKT) { + unsigned short tag; + tag = ntohs(extsts & EXTSTS_VTG_MASK); + rx_rc = vlan_hwaccel_rx(skb,dev->vlgrp,tag); + } else { + rx_rc = netif_rx(skb); + } +#else + rx_rc = netif_rx(skb); +#endif + if (NET_RX_DROP == rx_rc) { netdev_mangle_me_harder_failed: dev->stats.rx_dropped ++; } @@ -945,8 +1012,6 @@ static void do_tx_done(struct net_device *ndev) struct ns83820 *dev = PRIV(ndev); u32 cmdsts, tx_done_idx, *desc; - spin_lock_irq(&dev->tx_lock); - dprintk("do_tx_done(%p)\n", ndev); tx_done_idx = dev->tx_done_idx; desc = dev->tx_descs + (tx_done_idx * DESC_SIZE); @@ -1002,7 +1067,6 @@ static void do_tx_done(struct net_device *ndev) netif_start_queue(ndev); netif_wake_queue(ndev); } - spin_unlock_irq(&dev->tx_lock); } static void ns83820_cleanup_tx(struct ns83820 *dev) @@ -1087,7 +1151,7 @@ again: frag = skb_shinfo(skb)->frags; if (!nr_frags) - frag = 0; + frag = NULL; extsts = 0; if (skb->ip_summed == CHECKSUM_HW) { extsts |= EXTSTS_IPPKT; @@ -1097,6 +1161,17 @@ again: extsts |= EXTSTS_UDPPKT; } +#ifdef NS83820_VLAN_ACCEL_SUPPORT + if(vlan_tx_tag_present(skb)) { + /* fetch the vlan tag info out of the + * ancilliary data if the vlan code + * is using hw vlan acceleration + */ + short tag = vlan_tx_tag_get(skb); + extsts |= (EXTSTS_VPKT | htons(tag)); + } +#endif + len = skb->len; if (nr_frags) len -= skb->data_len; @@ -1106,7 +1181,6 @@ again: for (;;) { volatile u32 *desc = dev->tx_descs + (free_idx * DESC_SIZE); - u32 residue = 0; dprintk("frag[%3u]: %4u @ 0x%08Lx\n", free_idx, len, (unsigned long long)buf); @@ -1116,17 +1190,11 @@ again: desc_addr_set(desc + DESC_BUFPTR, buf); desc[DESC_EXTSTS] = cpu_to_le32(extsts); - cmdsts = ((nr_frags|residue) ? CMDSTS_MORE : do_intr ? CMDSTS_INTR : 0); + cmdsts = ((nr_frags) ? CMDSTS_MORE : do_intr ? CMDSTS_INTR : 0); cmdsts |= (desc == first_desc) ? 0 : CMDSTS_OWN; cmdsts |= len; desc[DESC_CMDSTS] = cpu_to_le32(cmdsts); - if (residue) { - buf += len; - len = residue; - continue; - } - if (!nr_frags) break; @@ -1162,7 +1230,7 @@ again: static void ns83820_update_stats(struct ns83820 *dev) { - u8 *base = dev->base; + u8 __iomem *base = dev->base; /* the DP83820 will freeze counters, so we need to read all of them */ dev->stats.rx_errors += readl(base + 0x60) & 0xffff; @@ -1190,64 +1258,33 @@ static struct net_device_stats *ns83820_get_stats(struct net_device *ndev) return &dev->stats; } -static int ns83820_ethtool_ioctl (struct ns83820 *dev, void __user *useraddr) +static void ns83820_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info) { - u32 ethcmd; - - if (copy_from_user(ðcmd, useraddr, sizeof (ethcmd))) - return -EFAULT; - - switch (ethcmd) { - case ETHTOOL_GDRVINFO: - { - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - strcpy(info.driver, "ns83820"); - strcpy(info.version, VERSION); - strcpy(info.bus_info, pci_name(dev->pci_dev)); - if (copy_to_user(useraddr, &info, sizeof (info))) - return -EFAULT; - return 0; - } - - /* get link status */ - case ETHTOOL_GLINK: { - struct ethtool_value edata = { ETHTOOL_GLINK }; - u32 cfg = readl(dev->base + CFG) ^ SPDSTS_POLARITY; - - if (cfg & CFG_LNKSTS) - edata.data = 1; - else - edata.data = 0; - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - - default: - break; - } - - return -EOPNOTSUPP; + struct ns83820 *dev = PRIV(ndev); + strcpy(info->driver, "ns83820"); + strcpy(info->version, VERSION); + strcpy(info->bus_info, pci_name(dev->pci_dev)); } -static int ns83820_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) +static u32 ns83820_get_link(struct net_device *ndev) { struct ns83820 *dev = PRIV(ndev); - - switch(cmd) { - case SIOCETHTOOL: - return ns83820_ethtool_ioctl(dev, rq->ifr_data); - - default: - return -EOPNOTSUPP; - } + u32 cfg = readl(dev->base + CFG) ^ SPDSTS_POLARITY; + return cfg & CFG_LNKSTS ? 1 : 0; } +static struct ethtool_ops ops = { + .get_drvinfo = ns83820_get_drvinfo, + .get_link = ns83820_get_link +}; + +/* this function is called in irq context from the ISR */ static void ns83820_mib_isr(struct ns83820 *dev) { - spin_lock(&dev->misc_lock); + unsigned long flags; + spin_lock_irqsave(&dev->misc_lock, flags); ns83820_update_stats(dev); - spin_unlock(&dev->misc_lock); + spin_unlock_irqrestore(&dev->misc_lock, flags); } static void ns83820_do_isr(struct net_device *ndev, u32 isr); @@ -1269,6 +1306,8 @@ static irqreturn_t ns83820_irq(int foo, void *data, struct pt_regs *regs) static void ns83820_do_isr(struct net_device *ndev, u32 isr) { struct ns83820 *dev = PRIV(ndev); + unsigned long flags; + #ifdef DEBUG if (isr & ~(ISR_PHY | ISR_RXDESC | ISR_RXEARLY | ISR_RXOK | ISR_RXERR | ISR_TXIDLE | ISR_TXOK | ISR_TXDESC)) Dprintk("odd isr? 0x%08x\n", isr); @@ -1283,10 +1322,10 @@ static void ns83820_do_isr(struct net_device *ndev, u32 isr) if ((ISR_RXDESC | ISR_RXOK) & isr) { prefetch(dev->rx_info.next_rx_desc); - spin_lock_irq(&dev->misc_lock); + spin_lock_irqsave(&dev->misc_lock, flags); dev->IMR_cache &= ~(ISR_RXDESC | ISR_RXOK); writel(dev->IMR_cache, dev->base + IMR); - spin_unlock_irq(&dev->misc_lock); + spin_unlock_irqrestore(&dev->misc_lock, flags); tasklet_schedule(&dev->rx_tasklet); //rx_irq(ndev); @@ -1332,16 +1371,18 @@ static void ns83820_do_isr(struct net_device *ndev, u32 isr) * work has accumulated */ if ((ISR_TXDESC | ISR_TXIDLE | ISR_TXOK | ISR_TXERR) & isr) { + spin_lock_irqsave(&dev->tx_lock, flags); do_tx_done(ndev); + spin_unlock_irqrestore(&dev->tx_lock, flags); /* Disable TxOk if there are no outstanding tx packets. */ if ((dev->tx_done_idx == dev->tx_free_idx) && (dev->IMR_cache & ISR_TXOK)) { - spin_lock_irq(&dev->misc_lock); + spin_lock_irqsave(&dev->misc_lock, flags); dev->IMR_cache &= ~ISR_TXOK; writel(dev->IMR_cache, dev->base + IMR); - spin_unlock_irq(&dev->misc_lock); + spin_unlock_irqrestore(&dev->misc_lock, flags); } } @@ -1352,10 +1393,10 @@ static void ns83820_do_isr(struct net_device *ndev, u32 isr) * nature are expected, we must enable TxOk. */ if ((ISR_TXIDLE & isr) && (dev->tx_done_idx != dev->tx_free_idx)) { - spin_lock_irq(&dev->misc_lock); + spin_lock_irqsave(&dev->misc_lock, flags); dev->IMR_cache |= ISR_TXOK; writel(dev->IMR_cache, dev->base + IMR); - spin_unlock_irq(&dev->misc_lock); + spin_unlock_irqrestore(&dev->misc_lock, flags); } /* MIB interrupt: one of the statistics counters is about to overflow */ @@ -1417,7 +1458,7 @@ static void ns83820_tx_timeout(struct net_device *ndev) u32 tx_done_idx, *desc; unsigned long flags; - local_irq_save(flags); + spin_lock_irqsave(&dev->tx_lock, flags); tx_done_idx = dev->tx_done_idx; desc = dev->tx_descs + (tx_done_idx * DESC_SIZE); @@ -1444,7 +1485,7 @@ static void ns83820_tx_timeout(struct net_device *ndev) ndev->name, tx_done_idx, dev->tx_free_idx, le32_to_cpu(desc[DESC_CMDSTS])); - local_irq_restore(flags); + spin_unlock_irqrestore(&dev->tx_lock, flags); } static void ns83820_tx_watch(unsigned long data) @@ -1518,15 +1559,13 @@ static void ns83820_getmac(struct ns83820 *dev, u8 *mac) unsigned i; for (i=0; i<3; i++) { u32 data; -#if 0 /* I've left this in as an example of how to use eeprom.h */ - data = eeprom_readw(&dev->ee, 0xa + 2 - i); -#else + /* Read from the perfect match memory: this is loaded by * the chip from the EEPROM via the EELOAD self test. */ writel(i*2, dev->base + RFCR); data = readl(dev->base + RFDR); -#endif + *mac++ = data; *mac++ = data >> 8; } @@ -1543,7 +1582,7 @@ static int ns83820_change_mtu(struct net_device *ndev, int new_mtu) static void ns83820_set_multicast(struct net_device *ndev) { struct ns83820 *dev = PRIV(ndev); - u8 *rfcr = dev->base + RFCR; + u8 __iomem *rfcr = dev->base + RFCR; u32 and_mask = 0xffffffff; u32 or_mask = 0; u32 val; @@ -1570,7 +1609,7 @@ static void ns83820_run_bist(struct net_device *ndev, const char *name, u32 enab { struct ns83820 *dev = PRIV(ndev); int timed_out = 0; - long start; + unsigned long start; u32 status; int loops = 0; @@ -1588,12 +1627,11 @@ static void ns83820_run_bist(struct net_device *ndev, const char *name, u32 enab break; if (status & fail) break; - if ((jiffies - start) >= HZ) { + if (time_after_eq(jiffies, start + HZ)) { timed_out = 1; break; } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } if (status & fail) @@ -1791,12 +1829,13 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ int using_dac = 0; /* See if we can set the dma mask early on; failure is fatal. */ - if (TRY_DAC && !pci_set_dma_mask(pci_dev, 0xffffffffffffffffULL)) { + if (sizeof(dma_addr_t) == 8 && + !pci_set_dma_mask(pci_dev, DMA_64BIT_MASK)) { using_dac = 1; - } else if (!pci_set_dma_mask(pci_dev, 0xffffffff)) { + } else if (!pci_set_dma_mask(pci_dev, DMA_32BIT_MASK)) { using_dac = 0; } else { - printk(KERN_WARNING "ns83820.c: pci_set_dma_mask failed!\n"); + dev_warn(&pci_dev->dev, "pci_set_dma_mask failed!\n"); return -ENODEV; } @@ -1811,8 +1850,6 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ spin_lock_init(&dev->misc_lock); dev->pci_dev = pci_dev; - dev->ee.cache = &dev->MEAR_cache; - dev->ee.lock = &dev->misc_lock; SET_MODULE_OWNER(ndev); SET_NETDEV_DEV(ndev, &pci_dev->dev); @@ -1821,7 +1858,7 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ err = pci_enable_device(pci_dev); if (err) { - printk(KERN_INFO "ns83820: pci_enable_dev failed: %d\n", err); + dev_info(&pci_dev->dev, "pci_enable_dev failed: %d\n", err); goto out_free; } @@ -1847,14 +1884,11 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ dev->IMR_cache = 0; - setup_ee_mem_bitbanger(&dev->ee, (long)dev->base + MEAR, 3, 2, 1, 0, - 0); - - err = request_irq(pci_dev->irq, ns83820_irq, SA_SHIRQ, - ndev->name, ndev); + err = request_irq(pci_dev->irq, ns83820_irq, IRQF_SHARED, + DRV_NAME, ndev); if (err) { - printk(KERN_INFO "ns83820: unable to register irq %d\n", - pci_dev->irq); + dev_info(&pci_dev->dev, "unable to register irq %d, err %d\n", + pci_dev->irq, err); goto out_disable; } @@ -1868,7 +1902,7 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ rtnl_lock(); err = dev_alloc_name(ndev, ndev->name); if (err < 0) { - printk(KERN_INFO "ns83820: unable to get netdev name: %d\n", err); + dev_info(&pci_dev->dev, "unable to get netdev name: %d\n", err); goto out_free_irq; } @@ -1882,10 +1916,9 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ ndev->get_stats = ns83820_get_stats; ndev->change_mtu = ns83820_change_mtu; ndev->set_multicast_list = ns83820_set_multicast; - ndev->do_ioctl = ns83820_ioctl; + SET_ETHTOOL_OPS(ndev, &ops); ndev->tx_timeout = ns83820_tx_timeout; ndev->watchdog_timeo = 5 * HZ; - pci_set_drvdata(pci_dev, ndev); ns83820_do_reset(dev, CR_RST); @@ -1923,9 +1956,8 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ /* When compiled with 64 bit addressing, we must always enable * the 64 bit descriptor format. */ -#ifdef USE_64BIT_ADDR - dev->CFG_cache |= CFG_M64ADDR; -#endif + if (sizeof(dma_addr_t) == 8) + dev->CFG_cache |= CFG_M64ADDR; if (using_dac) dev->CFG_cache |= CFG_T64ADDR; @@ -1958,8 +1990,7 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ if (reset_phy) { printk(KERN_INFO "%s: resetting phy\n", ndev->name); writel(dev->CFG_cache | CFG_PHY_RST, dev->base + CFG); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((HZ+99)/100); + msleep(10); writel(dev->CFG_cache, dev->base + CFG); } @@ -2011,11 +2042,25 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ * a ping with a VLAN header) then the card, strips the 4 byte VLAN * tag and then checks the packet size, so if RXCFG_ARP is not enabled, * it discrards it!. These guys...... + * also turn on tag stripping if hardware acceleration is enabled */ - writel(VRCR_IPEN | VRCR_VTDEN, dev->base + VRCR); +#ifdef NS83820_VLAN_ACCEL_SUPPORT +#define VRCR_INIT_VALUE (VRCR_IPEN|VRCR_VTDEN|VRCR_VTREN) +#else +#define VRCR_INIT_VALUE (VRCR_IPEN|VRCR_VTDEN) +#endif + writel(VRCR_INIT_VALUE, dev->base + VRCR); - /* Enable per-packet TCP/UDP/IP checksumming */ - writel(VTCR_PPCHK, dev->base + VTCR); + /* Enable per-packet TCP/UDP/IP checksumming + * and per packet vlan tag insertion if + * vlan hardware acceleration is enabled + */ +#ifdef NS83820_VLAN_ACCEL_SUPPORT +#define VTCR_INIT_VALUE (VTCR_PPCHK|VTCR_VPPTI) +#else +#define VTCR_INIT_VALUE VTCR_PPCHK +#endif + writel(VTCR_INIT_VALUE, dev->base + VTCR); /* Ramit : Enable async and sync pause frames */ /* writel(0, dev->base + PCR); */ @@ -2032,6 +2077,13 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ ndev->features |= NETIF_F_SG; ndev->features |= NETIF_F_IP_CSUM; +#ifdef NS83820_VLAN_ACCEL_SUPPORT + /* We also support hardware vlan acceleration */ + ndev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + ndev->vlan_rx_register = ns83820_vlan_rx_register; + ndev->vlan_rx_kill_vid = ns83820_vlan_rx_kill_vid; +#endif + if (using_dac) { printk(KERN_INFO "%s: using 64 bit addressing.\n", ndev->name); @@ -2134,19 +2186,20 @@ static void __exit ns83820_exit(void) pci_unregister_driver(&driver); } -MODULE_AUTHOR("Benjamin LaHaise "); +MODULE_AUTHOR("Benjamin LaHaise "); MODULE_DESCRIPTION("National Semiconductor DP83820 10/100/1000 driver"); MODULE_LICENSE("GPL"); +MODULE_VERSION(VERSION); MODULE_DEVICE_TABLE(pci, ns83820_pci_tbl); -MODULE_PARM(lnksts, "i"); +module_param(lnksts, int, 0); MODULE_PARM_DESC(lnksts, "Polarity of LNKSTS bit"); -MODULE_PARM(ihr, "i"); +module_param(ihr, int, 0); MODULE_PARM_DESC(ihr, "Time in 100 us increments to delay interrupts (range 0-127)"); -MODULE_PARM(reset_phy, "i"); +module_param(reset_phy, int, 0); MODULE_PARM_DESC(reset_phy, "Set to 1 to reset the PHY on startup"); module_init(ns83820_init);