Information and updates available at
http://www.scyld.com/network/epic100.html
+ [this link no longer provides anything useful -jgarzik]
---------------------------------------------------------------------
- Linux kernel-specific changes:
-
- LK1.1.2 (jgarzik):
- * Merge becker version 1.09 (4/08/2000)
-
- LK1.1.3:
- * Major bugfix to 1.09 driver (Francis Romieu)
-
- LK1.1.4 (jgarzik):
- * Merge becker test version 1.09 (5/29/2000)
-
- LK1.1.5:
- * Fix locking (jgarzik)
- * Limit 83c175 probe to ethernet-class PCI devices (rgooch)
-
- LK1.1.6:
- * Merge becker version 1.11
- * Move pci_enable_device before any PCI BAR len checks
-
- LK1.1.7:
- * { fill me in }
-
- LK1.1.8:
- * ethtool driver info support (jgarzik)
-
- LK1.1.9:
- * ethtool media get/set support (jgarzik)
-
- LK1.1.10:
- * revert MII transceiver init change (jgarzik)
-
- LK1.1.11:
- * implement ETHTOOL_[GS]SET, _NWAY_RST, _[GS]MSGLVL, _GLINK (jgarzik)
- * replace some MII-related magic numbers with constants
-
- LK1.1.12:
- * fix power-up sequence
-
- LK1.1.13:
- * revert version 1.1.12, power-up sequence "fix"
-
- LK1.1.14 (Kryzsztof Halasa):
- * fix spurious bad initializations
- * pound phy a la SMSC's app note on the subject
-
- AC1.1.14ac
- * fix power up/down for ethtool that broke in 1.11
-
*/
#define DRV_NAME "epic100"
-#define DRV_VERSION "1.11+LK1.1.14+AC1.1.14"
-#define DRV_RELDATE "June 2, 2004"
+#define DRV_VERSION "2.1"
+#define DRV_RELDATE "Sept 11, 2006"
/* The user-configurable values.
These may be modified when a driver module is loaded.*/
static char version[] __devinitdata =
DRV_NAME ".c:v1.11 1/7/2001 Written by Donald Becker <becker@scyld.com>\n";
static char version2[] __devinitdata =
-" http://www.scyld.com/network/epic100.html\n";
-static char version3[] __devinitdata =
" (unofficial 2.4.x kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n";
MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
struct epic_chip_info {
const char *name;
- int io_size; /* Needed for I/O region check or ioremap(). */
int drv_flags; /* Driver use, intended as capability flags. */
};
/* indexed by chip_t */
static const struct epic_chip_info pci_id_tbl[] = {
- { "SMSC EPIC/100 83c170",
- EPIC_TOTAL_SIZE, TYPE2_INTR | NO_MII | MII_PWRDWN },
- { "SMSC EPIC/100 83c170",
- EPIC_TOTAL_SIZE, TYPE2_INTR },
- { "SMSC EPIC/C 83c175",
- EPIC_TOTAL_SIZE, TYPE2_INTR | MII_PWRDWN },
+ { "SMSC EPIC/100 83c170", TYPE2_INTR | NO_MII | MII_PWRDWN },
+ { "SMSC EPIC/100 83c170", TYPE2_INTR },
+ { "SMSC EPIC/C 83c175", TYPE2_INTR | MII_PWRDWN },
};
/* Ring pointers. */
spinlock_t lock; /* Group with Tx control cache line. */
spinlock_t napi_lock;
+ struct napi_struct napi;
unsigned int reschedule_in_poll;
unsigned int cur_tx, dirty_tx;
static void epic_init_ring(struct net_device *dev);
static int epic_start_xmit(struct sk_buff *skb, struct net_device *dev);
static int epic_rx(struct net_device *dev, int budget);
-static int epic_poll(struct net_device *dev, int *budget);
-static irqreturn_t epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static int epic_poll(struct napi_struct *napi, int budget);
+static irqreturn_t epic_interrupt(int irq, void *dev_instance);
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static struct ethtool_ops netdev_ethtool_ops;
+static const struct ethtool_ops netdev_ethtool_ops;
static int epic_close(struct net_device *dev);
static struct net_device_stats *epic_get_stats(struct net_device *dev);
static void set_rx_mode(struct net_device *dev);
int i, ret, option = 0, duplex = 0;
void *ring_space;
dma_addr_t ring_dma;
+ DECLARE_MAC_BUF(mac);
/* when built into the kernel, we only print version if device is found */
#ifndef MODULE
static int printed_version;
if (!printed_version++)
- printk (KERN_INFO "%s" KERN_INFO "%s" KERN_INFO "%s",
- version, version2, version3);
+ printk (KERN_INFO "%s" KERN_INFO "%s",
+ version, version2);
#endif
card_idx++;
goto out;
irq = pdev->irq;
- if (pci_resource_len(pdev, 0) < pci_id_tbl[chip_idx].io_size) {
- printk (KERN_ERR "card %d: no PCI region space\n", card_idx);
+ if (pci_resource_len(pdev, 0) < EPIC_TOTAL_SIZE) {
+ dev_err(&pdev->dev, "no PCI region space\n");
ret = -ENODEV;
goto err_out_disable;
}
dev = alloc_etherdev(sizeof (*ep));
if (!dev) {
- printk (KERN_ERR "card %d: no memory for eth device\n", card_idx);
+ dev_err(&pdev->dev, "no memory for eth device\n");
goto err_out_free_res;
}
- SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, &pdev->dev);
#ifdef USE_IO_OPS
ioaddr = pci_resource_start (pdev, 1);
ioaddr = (long) ioremap (ioaddr, pci_resource_len (pdev, 1));
if (!ioaddr) {
- printk (KERN_ERR DRV_NAME " %d: ioremap failed\n", card_idx);
+ dev_err(&pdev->dev, "ioremap failed\n");
goto err_out_free_netdev;
}
#endif
((u16 *)dev->dev_addr)[i] = le16_to_cpu(inw(ioaddr + LAN0 + i*4));
if (debug > 2) {
- printk(KERN_DEBUG DRV_NAME "(%s): EEPROM contents\n",
- pci_name(pdev));
+ dev_printk(KERN_DEBUG, &pdev->dev, "EEPROM contents:\n");
for (i = 0; i < 64; i++)
printk(" %4.4x%s", read_eeprom(ioaddr, i),
i % 16 == 15 ? "\n" : "");
int mii_status = mdio_read(dev, phy, MII_BMSR);
if (mii_status != 0xffff && mii_status != 0x0000) {
ep->phys[phy_idx++] = phy;
- printk(KERN_INFO DRV_NAME "(%s): MII transceiver #%d control "
- "%4.4x status %4.4x.\n",
- pci_name(pdev), phy, mdio_read(dev, phy, 0), mii_status);
+ dev_info(&pdev->dev,
+ "MII transceiver #%d control "
+ "%4.4x status %4.4x.\n",
+ phy, mdio_read(dev, phy, 0), mii_status);
}
}
ep->mii_phy_cnt = phy_idx;
if (phy_idx != 0) {
phy = ep->phys[0];
ep->mii.advertising = mdio_read(dev, phy, MII_ADVERTISE);
- printk(KERN_INFO DRV_NAME "(%s): Autonegotiation advertising %4.4x link "
+ dev_info(&pdev->dev,
+ "Autonegotiation advertising %4.4x link "
"partner %4.4x.\n",
- pci_name(pdev), ep->mii.advertising, mdio_read(dev, phy, 5));
+ ep->mii.advertising, mdio_read(dev, phy, 5));
} else if ( ! (ep->chip_flags & NO_MII)) {
- printk(KERN_WARNING DRV_NAME "(%s): ***WARNING***: No MII transceiver found!\n",
- pci_name(pdev));
+ dev_warn(&pdev->dev,
+ "***WARNING***: No MII transceiver found!\n");
/* Use the known PHY address of the EPII. */
ep->phys[0] = 3;
}
/* The lower four bits are the media type. */
if (duplex) {
ep->mii.force_media = ep->mii.full_duplex = 1;
- printk(KERN_INFO DRV_NAME "(%s): Forced full duplex operation requested.\n",
- pci_name(pdev));
+ dev_info(&pdev->dev, "Forced full duplex requested.\n");
}
dev->if_port = ep->default_port = option;
dev->ethtool_ops = &netdev_ethtool_ops;
dev->watchdog_timeo = TX_TIMEOUT;
dev->tx_timeout = &epic_tx_timeout;
- dev->poll = epic_poll;
- dev->weight = 64;
+ netif_napi_add(dev, &ep->napi, epic_poll, 64);
ret = register_netdev(dev);
if (ret < 0)
goto err_out_unmap_rx;
- printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ",
- dev->name, pci_id_tbl[chip_idx].name, ioaddr, dev->irq);
- for (i = 0; i < 5; i++)
- printk("%2.2x:", dev->dev_addr[i]);
- printk("%2.2x.\n", dev->dev_addr[i]);
+ printk(KERN_INFO "%s: %s at %#lx, IRQ %d, %s\n",
+ dev->name, pci_id_tbl[chip_idx].name, ioaddr, dev->irq,
+ print_mac(mac, dev->dev_addr));
out:
return ret;
/* Soft reset the chip. */
outl(0x4001, ioaddr + GENCTL);
- if ((retval = request_irq(dev->irq, &epic_interrupt, IRQF_SHARED, dev->name, dev)))
+ napi_enable(&ep->napi);
+ if ((retval = request_irq(dev->irq, &epic_interrupt, IRQF_SHARED, dev->name, dev))) {
+ napi_disable(&ep->napi);
return retval;
+ }
epic_init_ring(dev);
ep->rx_skbuff[i] = skb;
if (skb == NULL)
break;
- skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* 16 byte align the IP header. */
ep->rx_ring[i].bufaddr = pci_map_single(ep->pci_dev,
skb->data, ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
/* The interrupt handler does all of the Rx thread work and cleans up
after the Tx thread. */
-static irqreturn_t epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t epic_interrupt(int irq, void *dev_instance)
{
struct net_device *dev = dev_instance;
struct epic_private *ep = dev->priv;
if ((status & EpicNapiEvent) && !ep->reschedule_in_poll) {
spin_lock(&ep->napi_lock);
- if (netif_rx_schedule_prep(dev)) {
+ if (netif_rx_schedule_prep(dev, &ep->napi)) {
epic_napi_irq_off(dev, ep);
- __netif_rx_schedule(dev);
+ __netif_rx_schedule(dev, &ep->napi);
} else
ep->reschedule_in_poll++;
spin_unlock(&ep->napi_lock);
to a minimally-sized skbuff. */
if (pkt_len < rx_copybreak
&& (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
- skb->dev = dev;
skb_reserve(skb, 2); /* 16 byte align the IP header */
pci_dma_sync_single_for_cpu(ep->pci_dev,
ep->rx_ring[entry].bufaddr,
ep->rx_buf_sz,
PCI_DMA_FROMDEVICE);
- eth_copy_and_sum(skb, ep->rx_skbuff[entry]->data, pkt_len, 0);
+ skb_copy_to_linear_data(skb, ep->rx_skbuff[entry]->data, pkt_len);
skb_put(skb, pkt_len);
pci_dma_sync_single_for_device(ep->pci_dev,
ep->rx_ring[entry].bufaddr,
skb = ep->rx_skbuff[entry] = dev_alloc_skb(ep->rx_buf_sz);
if (skb == NULL)
break;
- skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
ep->rx_ring[entry].bufaddr = pci_map_single(ep->pci_dev,
skb->data, ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
outw(RxQueued, ioaddr + COMMAND);
}
-static int epic_poll(struct net_device *dev, int *budget)
+static int epic_poll(struct napi_struct *napi, int budget)
{
- struct epic_private *ep = dev->priv;
- int work_done = 0, orig_budget;
+ struct epic_private *ep = container_of(napi, struct epic_private, napi);
+ struct net_device *dev = ep->mii.dev;
+ int work_done = 0;
long ioaddr = dev->base_addr;
- orig_budget = (*budget > dev->quota) ? dev->quota : *budget;
-
rx_action:
epic_tx(dev, ep);
- work_done += epic_rx(dev, *budget);
+ work_done += epic_rx(dev, budget);
epic_rx_err(dev, ep);
- *budget -= work_done;
- dev->quota -= work_done;
-
- if (netif_running(dev) && (work_done < orig_budget)) {
+ if (work_done < budget) {
unsigned long flags;
int more;
more = ep->reschedule_in_poll;
if (!more) {
- __netif_rx_complete(dev);
+ __netif_rx_complete(dev, napi);
outl(EpicNapiEvent, ioaddr + INTSTAT);
epic_napi_irq_on(dev, ep);
} else
goto rx_action;
}
- return (work_done >= orig_budget);
+ return work_done;
}
static int epic_close(struct net_device *dev)
int i;
netif_stop_queue(dev);
+ napi_disable(&ep->napi);
if (debug > 1)
printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */
outl(0x002C, ioaddr + RxCtrl);
/* Unconditionally log net taps. */
- printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name);
memset(mc_filter, 0xff, sizeof(mc_filter));
} else if ((dev->mc_count > 0) || (dev->flags & IFF_ALLMULTI)) {
/* There is apparently a chip bug, so the multicast filter
}
}
-static struct ethtool_ops netdev_ethtool_ops = {
+static const struct ethtool_ops netdev_ethtool_ops = {
.get_drvinfo = netdev_get_drvinfo,
.get_settings = netdev_get_settings,
.set_settings = netdev_set_settings,
.get_link = netdev_get_link,
.get_msglevel = netdev_get_msglevel,
.set_msglevel = netdev_set_msglevel,
- .get_sg = ethtool_op_get_sg,
- .get_tx_csum = ethtool_op_get_tx_csum,
.begin = ethtool_begin,
.complete = ethtool_complete
};
{
/* when a module, this is printed whether or not devices are found in probe */
#ifdef MODULE
- printk (KERN_INFO "%s" KERN_INFO "%s" KERN_INFO "%s",
- version, version2, version3);
+ printk (KERN_INFO "%s" KERN_INFO "%s",
+ version, version2);
#endif
- return pci_module_init (&epic_driver);
+ return pci_register_driver(&epic_driver);
}