Commit 86014f1b authored by Jeff Garzik's avatar Jeff Garzik

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

into redhat.com:/spare/repo/net-drivers-2.6
parents fbd532e3 ce99046f
No related merge requests found
......@@ -1061,23 +1061,33 @@ M: tigran@veritas.com
S: Maintained
INTEL PRO/100 ETHERNET SUPPORT
P: John Ronciak
M: john.ronciak@intel.com
P: Ganesh Venkatesan
M: ganesh.venkatesan@intel.com
P: Scott Feldman
M: scott.feldman@intel.com
W: http://sourceforge.net/projects/e1000/
S: Supported
INTEL PRO/1000 GIGABIT ETHERNET SUPPORT
P: Jeb Cramer
M: cramerj@intel.com
P: Scott Feldman
M: scott.feldman@intel.com
P: John Ronciak
M: john.ronciak@intel.com
P: Ganesh Venkatesan
M: ganesh.venkatesan@intel.com
W: http://sourceforge.net/projects/e1000/
S: Supported
INTEL PRO/10GbE SUPPORT
P: Ayyappan Veeraiyan
M: ayyappan.veeraiyan@intel.com
P: Ganesh Venkatesan
M: Ganesh.Venkatesan@intel.com
P: Scott Feldman
M: scott.feldman@intel.com
M: ganesh.venkatesan@intel.com
P: John Ronciak
M: john.ronciak@intel.com
W: http://sourceforge.net/projects/e1000/
S: Supported
INTERMEZZO FILE SYSTEM
......
......@@ -1084,7 +1084,7 @@ void NS8390_init(struct net_device *dev, int startp)
for(i = 0; i < 6; i++)
{
outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS_SHIFT(i));
if(inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i])
if (ei_debug > 1 && inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i])
printk(KERN_ERR "Hw. address read/write mismap %d\n",i);
}
......
......@@ -131,8 +131,19 @@ struct ei_device {
#define inb_p(port) in_8(port)
#define outb_p(val,port) out_8(port,val)
#elif defined(CONFIG_ARM_ETHERH) || defined(CONFIG_ARM_ETHERH_MODULE) || \
defined(CONFIG_NET_CBUS)
#elif defined(CONFIG_ARM_ETHERH) || defined(CONFIG_ARM_ETHERH_MODULE)
#define EI_SHIFT(x) (ei_local->reg_offset[x])
#undef inb
#undef inb_p
#undef outb
#undef outb_p
#define inb(_p) readb(_p)
#define outb(_v,_p) writeb(_v,_p)
#define inb_p(_p) inb(_p)
#define outb_p(_v,_p) outb(_v,_p)
#elif defined(CONFIG_NET_CBUS)
#define EI_SHIFT(x) (ei_local->reg_offset[x])
#else
#define EI_SHIFT(x) (x)
......
......@@ -1219,6 +1219,9 @@ config AMD8111_ETH
To compile this driver as a module, choose M here and read
<file:Documentation/networking/net-modules.txt>. The module
will be called amd8111e.
config AMD8111E_NAPI
bool "Enable NAPI support"
depends on AMD8111_ETH
config ADAPTEC_STARFIRE
tristate "Adaptec Starfire/DuraLAN support"
......
/* Advanced Micro Devices Inc. AMD8111E Linux Network Driver
* Copyright (C) 2003 Advanced Micro Devices
* Copyright (C) 2004 Advanced Micro Devices
*
*
* Copyright 2001,2002 Jeff Garzik <jgarzik@mandrakesoft.com> [ 8139cp.c,tg3.c ]
......@@ -55,6 +55,16 @@ Revision History:
4. Dynamic IPG support is disabled by default.
3.0.3 06/05/2003
1. Bug fix: Fixed failure to close the interface if SMP is enabled.
3.0.4 12/09/2003
1. Added set_mac_address routine for bonding driver support.
2. Tested the driver for bonding support
3. Bug fix: Fixed mismach in actual receive buffer lenth and lenth
indicated to the h/w.
4. Modified amd8111e_rx() routine to receive all the received packets
in the first interrupt.
5. Bug fix: Corrected rx_errors reported in get_stats() function.
3.0.5 03/22/2004
1. Added NAPI support
*/
......@@ -91,7 +101,7 @@ Revision History:
#include "amd8111e.h"
#define MODULE_NAME "amd8111e"
#define MODULE_VERS "3.0.3"
#define MODULE_VERS "3.0.5"
MODULE_AUTHOR("Advanced Micro Devices, Inc.");
MODULE_DESCRIPTION ("AMD8111 based 10/100 Ethernet Controller. Driver Version 3.0.3");
MODULE_LICENSE("GPL");
......@@ -276,8 +286,10 @@ static inline void amd8111e_set_rx_buff_len(struct net_device* dev)
unsigned int mtu = dev->mtu;
if (mtu > ETH_DATA_LEN){
/* MTU + ethernet header + FCS + optional VLAN tag */
lp->rx_buff_len = mtu + ETH_HLEN + 8;
/* MTU + ethernet header + FCS
+ optional VLAN tag + skb reserve space 2 */
lp->rx_buff_len = mtu + ETH_HLEN + 10;
lp->options |= OPTION_JUMBO_ENABLE;
} else{
lp->rx_buff_len = PKT_BUFF_SZ;
......@@ -337,7 +349,7 @@ static int amd8111e_init_ring(struct net_device *dev)
lp->rx_skbuff[i]->data,lp->rx_buff_len-2, PCI_DMA_FROMDEVICE);
lp->rx_ring[i].buff_phy_addr = cpu_to_le32(lp->rx_dma_addr[i]);
lp->rx_ring[i].buff_count = cpu_to_le16(lp->rx_buff_len);
lp->rx_ring[i].buff_count = cpu_to_le16(lp->rx_buff_len-2);
lp->rx_ring[i].rx_flags = cpu_to_le16(OWN_BIT);
}
......@@ -513,6 +525,9 @@ static void amd8111e_init_hw_default( struct amd8111e_priv* lp)
void * mmio = lp->mmio;
/* stop the chip */
writel(RUN, mmio + CMD0);
/* AUTOPOLL0 Register *//*TBD default value is 8100 in FPS */
writew( 0x8101, mmio + AUTOPOLL0);
......@@ -654,7 +669,11 @@ This is the receive indication function for packets with vlan tag.
*/
static int amd8111e_vlan_rx(struct amd8111e_priv *lp, struct sk_buff *skb, u16 vlan_tag)
{
#ifdef CONFIG_AMD8111E_NAPI
vlan_hwaccel_receive_skb(skb, lp->vlgrp,vlan_tag);
#else
return vlan_hwaccel_rx(skb, lp->vlgrp, vlan_tag);
#endif /* CONFIG_AMD8111E_NAPI */
}
#endif
......@@ -700,6 +719,142 @@ static int amd8111e_tx(struct net_device *dev)
return 0;
}
#if CONFIG_AMD8111E_NAPI
/* This function handles the driver receive operation in polling mode */
static int amd8111e_rx_poll(struct net_device *dev, int * budget)
{
struct amd8111e_priv *lp = dev->priv;
int rx_index = lp->rx_idx & RX_RING_DR_MOD_MASK;
void * mmio = lp->mmio;
struct sk_buff *skb,*new_skb;
int min_pkt_len, status;
unsigned int intr0;
int num_rx_pkt = 0;
/*int max_rx_pkt = NUM_RX_BUFFERS;*/
short pkt_len;
#if AMD8111E_VLAN_TAG_USED
short vtag;
#endif
int rx_pkt_limit = dev->quota;
do{
/* process receive packets until we use the quota*/
/* If we own the next entry, it's a new packet. Send it up. */
while(!(lp->rx_ring[rx_index].rx_flags & OWN_BIT)){
/* check if err summary bit is set */
if(le16_to_cpu(lp->rx_ring[rx_index].rx_flags)
& ERR_BIT){
/*
* There is a tricky error noted by John Murphy,
* <murf@perftech.com> to Russ Nelson: Even with
* full-sized * buffers it's possible for a
* jabber packet to use two buffers, with only
* the last correctly noting the error.
*/
/* reseting flags */
lp->rx_ring[rx_index].rx_flags &=RESET_RX_FLAGS;
goto err_next_pkt;
}
/* check for STP and ENP */
status = le16_to_cpu(lp->rx_ring[rx_index].rx_flags);
if(!((status & STP_BIT) && (status & ENP_BIT))){
/* reseting flags */
lp->rx_ring[rx_index].rx_flags &=RESET_RX_FLAGS;
goto err_next_pkt;
}
pkt_len = le16_to_cpu(lp->rx_ring[rx_index].msg_count) - 4;
#if AMD8111E_VLAN_TAG_USED
vtag = le16_to_cpu(lp->rx_ring[rx_index].rx_flags) & TT_MASK;
/*MAC will strip vlan tag*/
if(lp->vlgrp != NULL && vtag !=0)
min_pkt_len =MIN_PKT_LEN - 4;
else
#endif
min_pkt_len =MIN_PKT_LEN;
if (pkt_len < min_pkt_len) {
lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS;
lp->drv_rx_errors++;
goto err_next_pkt;
}
if(--rx_pkt_limit < 0)
goto rx_not_empty;
if(!(new_skb = dev_alloc_skb(lp->rx_buff_len))){
/* if allocation fail,
ignore that pkt and go to next one */
lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS;
lp->drv_rx_errors++;
goto err_next_pkt;
}
skb_reserve(new_skb, 2);
skb = lp->rx_skbuff[rx_index];
pci_unmap_single(lp->pci_dev,lp->rx_dma_addr[rx_index],
lp->rx_buff_len-2, PCI_DMA_FROMDEVICE);
skb_put(skb, pkt_len);
skb->dev = dev;
lp->rx_skbuff[rx_index] = new_skb;
new_skb->dev = dev;
lp->rx_dma_addr[rx_index] = pci_map_single(lp->pci_dev,
new_skb->data, lp->rx_buff_len-2,PCI_DMA_FROMDEVICE);
skb->protocol = eth_type_trans(skb, dev);
#if AMD8111E_VLAN_TAG_USED
vtag = lp->rx_ring[rx_index].rx_flags & TT_MASK;
if(lp->vlgrp != NULL && (vtag == TT_VLAN_TAGGED)){
amd8111e_vlan_rx(lp, skb,
lp->rx_ring[rx_index].tag_ctrl_info);
} else
#endif
netif_receive_skb(skb);
/*COAL update rx coalescing parameters*/
lp->coal_conf.rx_packets++;
lp->coal_conf.rx_bytes += pkt_len;
num_rx_pkt++;
dev->last_rx = jiffies;
err_next_pkt:
lp->rx_ring[rx_index].buff_phy_addr
= cpu_to_le32(lp->rx_dma_addr[rx_index]);
lp->rx_ring[rx_index].buff_count =
cpu_to_le16(lp->rx_buff_len-2);
lp->rx_ring[rx_index].rx_flags |= cpu_to_le16(OWN_BIT);
rx_index = (++lp->rx_idx) & RX_RING_DR_MOD_MASK;
}
/* Check the interrupt status register for more packets in the
mean time. Process them since we have not used up our quota.*/
intr0 = readl(mmio + INT0);
/*Ack receive packets */
writel(intr0 & RINT0,mmio + INT0);
}while(intr0 & RINT0);
/* Receive descriptor is empty now */
dev->quota -= num_rx_pkt;
*budget -= num_rx_pkt;
netif_rx_complete(dev);
/* enable receive interrupt */
writel(VAL0|RINTEN0, mmio + INTEN0);
writel(VAL2 | RDMD0, mmio + CMD0);
return 0;
rx_not_empty:
/* Do not call a netif_rx_complete */
dev->quota -= num_rx_pkt;
*budget -= num_rx_pkt;
return 1;
}
#else
/*
This function will check the ownership of receive buffers and descriptors. It will indicate to kernel up to half the number of maximum receive buffers in the descriptor ring, in a single receive interrupt. It will also replenish the descriptors with new skbs.
*/
......@@ -710,7 +865,7 @@ static int amd8111e_rx(struct net_device *dev)
int rx_index = lp->rx_idx & RX_RING_DR_MOD_MASK;
int min_pkt_len, status;
int num_rx_pkt = 0;
int max_rx_pkt = NUM_RX_BUFFERS/2;
int max_rx_pkt = NUM_RX_BUFFERS;
short pkt_len;
#if AMD8111E_VLAN_TAG_USED
short vtag;
......@@ -752,14 +907,14 @@ static int amd8111e_rx(struct net_device *dev)
if (pkt_len < min_pkt_len) {
lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS;
lp->stats.rx_errors++;
lp->drv_rx_errors++;
goto err_next_pkt;
}
if(!(new_skb = dev_alloc_skb(lp->rx_buff_len))){
/* if allocation fail,
ignore that pkt and go to next one */
lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS;
lp->stats.rx_errors++;
lp->drv_rx_errors++;
goto err_next_pkt;
}
......@@ -803,7 +958,7 @@ static int amd8111e_rx(struct net_device *dev)
return 0;
}
#endif /* CONFIG_AMD8111E_NAPI */
/*
This function will indicate the link status to the kernel.
*/
......@@ -896,12 +1051,14 @@ static struct net_device_stats *amd8111e_get_stats(struct net_device * dev)
new_stats->tx_bytes = amd8111e_read_mib(mmio, xmt_octets);
/* stats.rx_errors */
/* hw errors + errors driver reported */
new_stats->rx_errors = amd8111e_read_mib(mmio, rcv_undersize_pkts)+
amd8111e_read_mib(mmio, rcv_fragments)+
amd8111e_read_mib(mmio, rcv_jabbers)+
amd8111e_read_mib(mmio, rcv_alignment_errors)+
amd8111e_read_mib(mmio, rcv_fcs_errors)+
amd8111e_read_mib(mmio, rcv_miss_pkts);
amd8111e_read_mib(mmio, rcv_miss_pkts)+
lp->drv_rx_errors;
/* stats.tx_errors */
new_stats->tx_errors = amd8111e_read_mib(mmio, xmt_underrun_pkts);
......@@ -1119,20 +1276,36 @@ static irqreturn_t amd8111e_interrupt(int irq, void *dev_id, struct pt_regs *reg
/* Process all the INT event until INTR bit is clear. */
if (!(intr0 & INTR)) {
if (!(intr0 & INTR)){
handled = 0;
goto err_no_interrupt;
}
/* Current driver processes 3 interrupts : RINT,TINT,LCINT */
/* Current driver processes 4 interrupts : RINT,TINT,LCINT,STINT */
writel(intr0, mmio + INT0);
/* Check if Receive Interrupt has occurred. */
#if CONFIG_AMD8111E_NAPI
if(intr0 & RINT0){
if(netif_rx_schedule_prep(dev)){
/* Disable receive interupts */
writel(RINTEN0, mmio + INTEN0);
/* Schedule a polling routine */
__netif_rx_schedule(dev);
}
else {
printk("************Driver bug! \
interrupt while in poll\n");
/* Fix by disabling interrupts */
writel(RINT0, mmio + INT0);
}
}
#else
if(intr0 & RINT0){
amd8111e_rx(dev);
writel(VAL2 | RDMD0, mmio + CMD0);
}
#endif /* CONFIG_AMD8111E_NAPI */
/* Check if Transmit Interrupt has occurred. */
if(intr0 & TINT0)
amd8111e_tx(dev);
......@@ -1164,6 +1337,7 @@ static void amd8111e_poll(struct net_device *dev)
}
#endif
/*
This function closes the network interface and updates the statistics so that most recent statistics will be available after the interface is down.
*/
......@@ -1186,7 +1360,7 @@ static int amd8111e_close(struct net_device * dev)
spin_unlock_irq(&lp->lock);
free_irq(dev->irq, dev);
/* Update the statistics before closing */
amd8111e_get_stats(dev);
lp->opened = 0;
......@@ -1560,6 +1734,23 @@ static int amd8111e_ioctl(struct net_device * dev , struct ifreq *ifr, int cmd)
}
return -EOPNOTSUPP;
}
static int amd8111e_set_mac_address(struct net_device *dev, void *p)
{
struct amd8111e_priv *lp = dev->priv;
int i;
struct sockaddr *addr = p;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
spin_lock_irq(&lp->lock);
/* Setting the MAC address to the device */
for(i = 0; i < ETH_ADDR_LEN; i++)
writeb( dev->dev_addr[i], lp->mmio + PADR + i );
spin_unlock_irq(&lp->lock);
return 0;
}
/*
This function changes the mtu of the device. It restarts the device to initialize the descriptor with new receive buffers.
*/
......@@ -1890,11 +2081,16 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev,
dev->stop = amd8111e_close;
dev->get_stats = amd8111e_get_stats;
dev->set_multicast_list = amd8111e_set_multicast_list;
dev->set_mac_address = amd8111e_set_mac_address;
dev->do_ioctl = amd8111e_ioctl;
dev->change_mtu = amd8111e_change_mtu;
dev->irq =pdev->irq;
dev->tx_timeout = amd8111e_tx_timeout;
dev->watchdog_timeo = AMD8111E_TX_TIMEOUT;
#ifdef CONFIG_AMD8111E_NAPI
dev->poll = amd8111e_rx_poll;
dev->weight = 32;
#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = amd8111e_poll;
#endif
......@@ -1908,6 +2104,7 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev,
/* Set receive buffer length and set jumbo option*/
amd8111e_set_rx_buff_len(dev);
err = register_netdev(dev);
if (err) {
printk(KERN_ERR "amd8111e: Cannot register net device, "
......@@ -1954,7 +2151,7 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev,
}
static struct pci_driver amd8111e_driver = {
.name = MODULE_NAME,
.name = MODULE_NAME,
.id_table = amd8111e_pci_tbl,
.probe = amd8111e_probe_one,
.remove = __devexit_p(amd8111e_remove_one),
......
......@@ -606,7 +606,7 @@ typedef enum {
/* ipg parameters */
#define DEFAULT_IPG 0x60
#define IFS1_DELTA 36
#define IPG_CONVERGE_JIFFIES (HZ / 2)
#define IPG_CONVERGE_JIFFIES (HZ/2)
#define IPG_STABLE_TIME 5
#define MIN_IPG 96
#define MAX_IPG 255
......@@ -790,6 +790,7 @@ struct amd8111e_priv{
#endif
char opened;
struct net_device_stats stats;
unsigned int drv_rx_errors;
struct dev_mc_list* mc_list;
struct amd8111e_coalesce_conf coal_conf;
......
......@@ -185,8 +185,6 @@ static void __exit com20020_exit(void)
#ifndef MODULE
static int __init com20020isa_setup(char *s)
{
struct net_device *dev;
struct arcnet_local *lp;
int ints[8];
s = get_options(s, 8, ints);
......
......@@ -60,11 +60,28 @@ static unsigned int net_debug = NET_DEBUG;
struct etherh_priv {
struct ei_device eidev;
void *ioc_fast;
void *memc;
unsigned int id;
unsigned int ctrl_port;
void *ctrl_port;
unsigned int ctrl;
};
struct etherh_data {
unsigned long ns8390_offset;
unsigned long dataport_offset;
unsigned long ctrlport_offset;
int ctrl_ioc;
const char name[16];
/*
* netdev flags and port
*/
unsigned short flags;
unsigned char if_port;
unsigned char tx_start_page;
unsigned char stop_page;
};
MODULE_AUTHOR("Russell King");
MODULE_DESCRIPTION("EtherH/EtherM driver");
MODULE_LICENSE("GPL");
......@@ -72,13 +89,13 @@ MODULE_LICENSE("GPL");
static char version[] __initdata =
"EtherH/EtherM Driver (c) 2002 Russell King v1.09\n";
#define ETHERH500_DATAPORT 0x200 /* MEMC */
#define ETHERH500_DATAPORT 0x800 /* MEMC */
#define ETHERH500_NS8390 0x000 /* MEMC */
#define ETHERH500_CTRLPORT 0x200 /* IOC */
#define ETHERH500_CTRLPORT 0x800 /* IOC */
#define ETHERH600_DATAPORT 16 /* MEMC */
#define ETHERH600_NS8390 0x200 /* MEMC */
#define ETHERH600_CTRLPORT 0x080 /* MEMC */
#define ETHERH600_DATAPORT 0x040 /* MEMC */
#define ETHERH600_NS8390 0x800 /* MEMC */
#define ETHERH600_CTRLPORT 0x200 /* MEMC */
#define ETHERH_CP_IE 1
#define ETHERH_CP_IF 2
......@@ -90,9 +107,9 @@ static char version[] __initdata =
/*
* These came from CK/TEW
*/
#define ETHERM_DATAPORT 0x080 /* MEMC */
#define ETHERM_NS8390 0x200 /* MEMC */
#define ETHERM_CTRLPORT 0x08f /* MEMC */
#define ETHERM_DATAPORT 0x200 /* MEMC */
#define ETHERM_NS8390 0x800 /* MEMC */
#define ETHERM_CTRLPORT 0x23c /* MEMC */
#define ETHERM_TX_START_PAGE 64
#define ETHERM_STOP_PAGE 127
......@@ -102,18 +119,18 @@ static char version[] __initdata =
static inline void etherh_set_ctrl(struct etherh_priv *eh, unsigned int mask)
{
eh->ctrl |= mask;
outb(eh->ctrl, eh->ctrl_port);
writeb(eh->ctrl, eh->ctrl_port);
}
static inline void etherh_clr_ctrl(struct etherh_priv *eh, unsigned int mask)
{
eh->ctrl &= ~mask;
outb(eh->ctrl, eh->ctrl_port);
writeb(eh->ctrl, eh->ctrl_port);
}
static inline unsigned int etherh_get_stat(struct etherh_priv *eh)
{
return inb(eh->ctrl_port);
return readb(eh->ctrl_port);
}
......@@ -158,10 +175,10 @@ etherh_setif(struct net_device *dev)
switch (dev->if_port) {
case IF_PORT_10BASE2:
outb((inb(addr) & 0xf8) | 1, addr);
writeb((readb(addr) & 0xf8) | 1, addr);
break;
case IF_PORT_10BASET:
outb((inb(addr) & 0xf8), addr);
writeb((readb(addr) & 0xf8), addr);
break;
}
break;
......@@ -200,7 +217,7 @@ etherh_getifstat(struct net_device *dev)
stat = 1;
break;
case IF_PORT_10BASET:
stat = inb(dev->base_addr+EN0_RCNTHI) & 4;
stat = readb(dev->base_addr+EN0_RCNTHI) & 4;
break;
}
break;
......@@ -258,7 +275,7 @@ etherh_reset(struct net_device *dev)
{
struct ei_device *ei_local = netdev_priv(dev);
outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, dev->base_addr);
writeb(E8390_NODMA+E8390_PAGE0+E8390_STOP, dev->base_addr);
/*
* See if we need to change the interface type.
......@@ -306,31 +323,31 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf
dma_addr = dev->mem_start;
count = (count + 1) & ~1;
outb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
outb (0x42, addr + EN0_RCNTLO);
outb (0x00, addr + EN0_RCNTHI);
outb (0x42, addr + EN0_RSARLO);
outb (0x00, addr + EN0_RSARHI);
outb (E8390_RREAD | E8390_START, addr + E8390_CMD);
writeb (0x42, addr + EN0_RCNTLO);
writeb (0x00, addr + EN0_RCNTHI);
writeb (0x42, addr + EN0_RSARLO);
writeb (0x00, addr + EN0_RSARHI);
writeb (E8390_RREAD | E8390_START, addr + E8390_CMD);
udelay (1);
outb (ENISR_RDC, addr + EN0_ISR);
outb (count, addr + EN0_RCNTLO);
outb (count >> 8, addr + EN0_RCNTHI);
outb (0, addr + EN0_RSARLO);
outb (start_page, addr + EN0_RSARHI);
outb (E8390_RWRITE | E8390_START, addr + E8390_CMD);
writeb (ENISR_RDC, addr + EN0_ISR);
writeb (count, addr + EN0_RCNTLO);
writeb (count >> 8, addr + EN0_RCNTHI);
writeb (0, addr + EN0_RSARLO);
writeb (start_page, addr + EN0_RSARHI);
writeb (E8390_RWRITE | E8390_START, addr + E8390_CMD);
if (ei_local->word16)
outsw (dma_addr, buf, count >> 1);
writesw (dma_addr, buf, count >> 1);
else
outsb (dma_addr, buf, count);
writesb (dma_addr, buf, count);
dma_start = jiffies;
while ((inb (addr + EN0_ISR) & ENISR_RDC) == 0)
while ((readb (addr + EN0_ISR) & ENISR_RDC) == 0)
if (jiffies - dma_start > 2*HZ/100) { /* 20ms */
printk(KERN_ERR "%s: timeout waiting for TX RDC\n",
dev->name);
......@@ -339,7 +356,7 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf
break;
}
outb (ENISR_RDC, addr + EN0_ISR);
writeb (ENISR_RDC, addr + EN0_ISR);
ei_local->dmaing = 0;
}
......@@ -366,21 +383,21 @@ etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int
dma_addr = dev->mem_start;
buf = skb->data;
outb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
outb (count, addr + EN0_RCNTLO);
outb (count >> 8, addr + EN0_RCNTHI);
outb (ring_offset, addr + EN0_RSARLO);
outb (ring_offset >> 8, addr + EN0_RSARHI);
outb (E8390_RREAD | E8390_START, addr + E8390_CMD);
writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
writeb (count, addr + EN0_RCNTLO);
writeb (count >> 8, addr + EN0_RCNTHI);
writeb (ring_offset, addr + EN0_RSARLO);
writeb (ring_offset >> 8, addr + EN0_RSARHI);
writeb (E8390_RREAD | E8390_START, addr + E8390_CMD);
if (ei_local->word16) {
insw (dma_addr, buf, count >> 1);
readsw (dma_addr, buf, count >> 1);
if (count & 1)
buf[count - 1] = inb (dma_addr);
buf[count - 1] = readb (dma_addr);
} else
insb (dma_addr, buf, count);
readsb (dma_addr, buf, count);
outb (ENISR_RDC, addr + EN0_ISR);
writeb (ENISR_RDC, addr + EN0_ISR);
ei_local->dmaing = 0;
}
......@@ -405,19 +422,19 @@ etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_p
addr = dev->base_addr;
dma_addr = dev->mem_start;
outb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
outb (sizeof (*hdr), addr + EN0_RCNTLO);
outb (0, addr + EN0_RCNTHI);
outb (0, addr + EN0_RSARLO);
outb (ring_page, addr + EN0_RSARHI);
outb (E8390_RREAD | E8390_START, addr + E8390_CMD);
writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
writeb (sizeof (*hdr), addr + EN0_RCNTLO);
writeb (0, addr + EN0_RCNTHI);
writeb (0, addr + EN0_RSARLO);
writeb (ring_page, addr + EN0_RSARHI);
writeb (E8390_RREAD | E8390_START, addr + E8390_CMD);
if (ei_local->word16)
insw (dma_addr, hdr, sizeof (*hdr) >> 1);
readsw (dma_addr, hdr, sizeof (*hdr) >> 1);
else
insb (dma_addr, hdr, sizeof (*hdr));
readsb (dma_addr, hdr, sizeof (*hdr));
outb (ENISR_RDC, addr + EN0_ISR);
writeb (ENISR_RDC, addr + EN0_ISR);
ei_local->dmaing = 0;
}
......@@ -543,18 +560,22 @@ static u32 etherm_regoffsets[16];
static int __init
etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
{
const struct etherh_data *data = id->data;
struct ei_device *ei_local;
struct net_device *dev;
struct etherh_priv *eh;
const char *dev_type;
int i, size, ret;
int i, ret;
etherh_banner();
ret = ecard_request_resources(ec);
if (ret)
goto out;
dev = alloc_ei_netdev();
if (!dev) {
ret = -ENOMEM;
goto out;
goto release;
}
eh = netdev_priv(dev);
......@@ -562,111 +583,64 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
spin_lock_init(&eh->eidev.page_lock);
SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, &ec->dev);
dev->open = etherh_open;
dev->stop = etherh_close;
dev->set_config = etherh_set_config;
dev->irq = ec->irq;
dev->base_addr = ecard_address(ec, ECARD_MEMC, 0);
dev->if_port = data->if_port;
dev->flags |= data->flags;
/*
* IRQ and control port handling
*/
if (ec->irq != 11) {
ec->ops = &etherh_ops;
ec->irq_data = eh;
}
eh->ctrl = 0;
eh->id = ec->cid.product;
switch (ec->cid.product) {
case PROD_ANT_ETHERM:
etherm_addr(dev->dev_addr);
dev->base_addr += ETHERM_NS8390;
dev->mem_start = dev->base_addr + ETHERM_DATAPORT;
eh->ctrl_port = dev->base_addr + ETHERM_CTRLPORT;
break;
case PROD_I3_ETHERLAN500:
etherh_addr(dev->dev_addr, ec);
dev->base_addr += ETHERH500_NS8390;
dev->mem_start = dev->base_addr + ETHERH500_DATAPORT;
eh->ctrl_port = ecard_address (ec, ECARD_IOC, ECARD_FAST)
+ ETHERH500_CTRLPORT;
break;
case PROD_I3_ETHERLAN600:
case PROD_I3_ETHERLAN600A:
etherh_addr(dev->dev_addr, ec);
dev->base_addr += ETHERH600_NS8390;
dev->mem_start = dev->base_addr + ETHERH600_DATAPORT;
eh->ctrl_port = dev->base_addr + ETHERH600_CTRLPORT;
break;
default:
printk(KERN_ERR "%s: unknown card type %x\n",
dev->name, ec->cid.product);
ret = -ENODEV;
eh->memc = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC), PAGE_SIZE);
if (!eh->memc) {
ret = -ENOMEM;
goto free;
}
size = 16;
if (ec->cid.product == PROD_ANT_ETHERM)
size <<= 3;
if (!request_region(dev->base_addr, size, dev->name)) {
ret = -EBUSY;
goto free;
eh->ctrl_port = eh->memc;
if (data->ctrl_ioc) {
eh->ioc_fast = ioremap(ecard_resource_start(ec, ECARD_RES_IOCFAST), PAGE_SIZE);
if (!eh->ioc_fast) {
ret = -ENOMEM;
goto free;
}
eh->ctrl_port = eh->ioc_fast;
}
dev->base_addr = (unsigned long)eh->memc + data->ns8390_offset;
dev->mem_start = (unsigned long)eh->memc + data->dataport_offset;
eh->ctrl_port += data->ctrlport_offset;
/*
* If we're in the NIC slot, make sure the IRQ is enabled
* IRQ and control port handling - only for non-NIC slot cards.
*/
if (dev->irq == 11)
if (ec->slot_no != 8) {
ec->ops = &etherh_ops;
ec->irq_data = eh;
} else {
/*
* If we're in the NIC slot, make sure the IRQ is enabled
*/
etherh_set_ctrl(eh, ETHERH_CP_IE);
switch (ec->cid.product) {
case PROD_ANT_ETHERM:
dev_type = "ANT EtherM";
dev->if_port = IF_PORT_UNKNOWN;
break;
case PROD_I3_ETHERLAN500:
dev_type = "i3 EtherH 500";
dev->if_port = IF_PORT_UNKNOWN;
break;
case PROD_I3_ETHERLAN600:
dev_type = "i3 EtherH 600";
dev->flags |= IFF_PORTSEL | IFF_AUTOMEDIA;
dev->if_port = IF_PORT_10BASET;
break;
case PROD_I3_ETHERLAN600A:
dev_type = "i3 EtherH 600A";
dev->flags |= IFF_PORTSEL | IFF_AUTOMEDIA;
dev->if_port = IF_PORT_10BASET;
break;
default:
dev_type = "unknown";
break;
}
ei_local = netdev_priv(dev);
ei_local = &eh->eidev;
if (ec->cid.product == PROD_ANT_ETHERM) {
ei_local->tx_start_page = ETHERM_TX_START_PAGE;
ei_local->stop_page = ETHERM_STOP_PAGE;
ei_local->reg_offset = etherm_regoffsets;
etherm_addr(dev->dev_addr);
ei_local->reg_offset = etherm_regoffsets;
} else {
ei_local->tx_start_page = ETHERH_TX_START_PAGE;
ei_local->stop_page = ETHERH_STOP_PAGE;
ei_local->reg_offset = etherh_regoffsets;
etherh_addr(dev->dev_addr, ec);
ei_local->reg_offset = etherh_regoffsets;
}
ei_local->name = dev->name;
ei_local->word16 = 1;
ei_local->tx_start_page = data->tx_start_page;
ei_local->rx_start_page = ei_local->tx_start_page + TX_PAGES;
ei_local->stop_page = data->stop_page;
ei_local->reset_8390 = etherh_reset;
ei_local->block_input = etherh_block_input;
ei_local->block_output = etherh_block_output;
......@@ -678,10 +652,10 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
ret = register_netdev(dev);
if (ret)
goto release;
goto free;
printk(KERN_INFO "%s: %s in slot %d, ",
dev->name, dev_type, ec->slot_no);
dev->name, data->name, ec->slot_no);
for (i = 0; i < 6; i++)
printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':');
......@@ -690,10 +664,14 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
return 0;
release:
release_region(dev->base_addr, 16);
free:
if (eh->ioc_fast)
iounmap(eh->ioc_fast);
if (eh->memc)
iounmap(eh->memc);
free_netdev(dev);
release:
ecard_release_resources(ec);
out:
return ret;
}
......@@ -701,25 +679,69 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
static void __devexit etherh_remove(struct expansion_card *ec)
{
struct net_device *dev = ecard_get_drvdata(ec);
int size = 16;
struct etherh_priv *eh = netdev_priv(dev);
ecard_set_drvdata(ec, NULL);
unregister_netdev(dev);
if (ec->cid.product == PROD_ANT_ETHERM)
size <<= 3;
release_region(dev->base_addr, size);
if (eh->ioc_fast)
iounmap(eh->ioc_fast);
iounmap(eh->memc);
free_netdev(dev);
ec->ops = NULL;
kfree(ec->irq_data);
ecard_release_resources(ec);
}
static struct etherh_data etherm_data = {
.ns8390_offset = ETHERM_NS8390,
.dataport_offset = ETHERM_NS8390 + ETHERM_DATAPORT,
.ctrlport_offset = ETHERM_NS8390 + ETHERM_CTRLPORT,
.name = "ANT EtherM",
.if_port = IF_PORT_UNKNOWN,
.tx_start_page = ETHERM_TX_START_PAGE,
.stop_page = ETHERM_STOP_PAGE,
};
static struct etherh_data etherlan500_data = {
.ns8390_offset = ETHERH500_NS8390,
.dataport_offset = ETHERH500_NS8390 + ETHERH500_DATAPORT,
.ctrlport_offset = ETHERH500_CTRLPORT,
.ctrl_ioc = 1,
.name = "i3 EtherH 500",
.if_port = IF_PORT_UNKNOWN,
.tx_start_page = ETHERH_TX_START_PAGE,
.stop_page = ETHERH_STOP_PAGE,
};
static struct etherh_data etherlan600_data = {
.ns8390_offset = ETHERH600_NS8390,
.dataport_offset = ETHERH600_NS8390 + ETHERH600_DATAPORT,
.ctrlport_offset = ETHERH600_NS8390 + ETHERH600_CTRLPORT,
.name = "i3 EtherH 600",
.flags = IFF_PORTSEL | IFF_AUTOMEDIA,
.if_port = IF_PORT_10BASET,
.tx_start_page = ETHERH_TX_START_PAGE,
.stop_page = ETHERH_STOP_PAGE,
};
static struct etherh_data etherlan600a_data = {
.ns8390_offset = ETHERH600_NS8390,
.dataport_offset = ETHERH600_NS8390 + ETHERH600_DATAPORT,
.ctrlport_offset = ETHERH600_NS8390 + ETHERH600_CTRLPORT,
.name = "i3 EtherH 600A",
.flags = IFF_PORTSEL | IFF_AUTOMEDIA,
.if_port = IF_PORT_10BASET,
.tx_start_page = ETHERH_TX_START_PAGE,
.stop_page = ETHERH_STOP_PAGE,
};
static const struct ecard_id etherh_ids[] = {
{ MANU_ANT, PROD_ANT_ETHERM },
{ MANU_I3, PROD_I3_ETHERLAN500 },
{ MANU_I3, PROD_I3_ETHERLAN600 },
{ MANU_I3, PROD_I3_ETHERLAN600A },
{ MANU_ANT, PROD_ANT_ETHERM, &etherm_data },
{ MANU_I3, PROD_I3_ETHERLAN500, &etherlan500_data },
{ MANU_I3, PROD_I3_ETHERLAN600, &etherlan600_data },
{ MANU_I3, PROD_I3_ETHERLAN600A, &etherlan600a_data },
{ 0xffff, 0xffff }
};
......@@ -737,8 +759,8 @@ static int __init etherh_init(void)
int i;
for (i = 0; i < 16; i++) {
etherh_regoffsets[i] = i;
etherm_regoffsets[i] = i << 3;
etherh_regoffsets[i] = i << 2;
etherm_regoffsets[i] = i << 5;
}
return ecard_register_driver(&etherh_driver);
......
......@@ -2910,7 +2910,7 @@ static void iph5526_timeout(struct net_device *dev)
{
struct fc_info *fi = dev->priv;
printk(KERN_WARNING "%s: timed out on send.\n", dev->name);
fi->fc_stats.rx_dropped++;
fi->fc_stats.tx_dropped++;
dev->trans_start = jiffies;
netif_wake_queue(dev);
}
......@@ -2953,7 +2953,7 @@ static int iph5526_send_packet(struct sk_buff *skb, struct net_device *dev)
fi->fc_stats.tx_packets++;
}
else
fi->fc_stats.rx_dropped++;
fi->fc_stats.tx_dropped++;
dev->trans_start = jiffies;
/* We free up the IP buffers in the OCI_interrupt handler.
* status == 0 implies that the frame was not transmitted. So the
......
......@@ -387,7 +387,7 @@ enum register_offsets {
IntrStatus = 0x10,
IntrMask = 0x14,
IntrEnable = 0x18,
IntrHoldoff = 0x16, /* DP83816 only */
IntrHoldoff = 0x1C, /* DP83816 only */
TxRingPtr = 0x20,
TxConfig = 0x24,
RxRingPtr = 0x30,
......
......@@ -997,13 +997,13 @@ static void skmca_set_multicast_list(struct net_device *dev)
block.Mode &= ~LANCE_INIT_PROM;
if (dev->flags & IFF_ALLMULTI) { /* get all multicasts */
memset(block.LAdrF, 8, 0xff);
memset(block.LAdrF, 0xff, sizeof(block.LAdrF));
} else { /* get selected/no multicasts */
struct dev_mc_list *mptr;
int code;
memset(block.LAdrF, 8, 0x00);
memset(block.LAdrF, 0, sizeof(block.LAdrF));
for (mptr = dev->mc_list; mptr != NULL; mptr = mptr->next) {
code = GetHash(mptr->dmi_addr);
block.LAdrF[(code >> 3) & 7] |= 1 << (code & 7);
......
......@@ -42,13 +42,14 @@ struct divert_blk;
struct vlan_group;
struct ethtool_ops;
/* source back-compat hook */
/* source back-compat hooks */
#define SET_ETHTOOL_OPS(netdev,ops) \
( (netdev)->ethtool_ops = (ops) )
#define HAVE_ALLOC_NETDEV /* feature macro: alloc_xxxdev
functions are available. */
#define HAVE_FREE_NETDEV
#define HAVE_FREE_NETDEV /* free_netdev() */
#define HAVE_NETDEV_PRIV /* netdev_priv() */
#define NET_XMIT_SUCCESS 0
#define NET_XMIT_DROP 1 /* skb dropped */
......
......@@ -163,21 +163,15 @@ void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
spin_lock(&np->dev->xmit_lock);
np->dev->xmit_lock_owner = smp_processor_id();
if (netif_queue_stopped(np->dev)) {
np->dev->xmit_lock_owner = -1;
spin_unlock(&np->dev->xmit_lock);
netpoll_poll(np);
goto repeat;
}
status = np->dev->hard_start_xmit(skb, np->dev);
np->dev->xmit_lock_owner = -1;
spin_unlock(&np->dev->xmit_lock);
/* transmit busy */
if(status)
if(status) {
netpoll_poll(np);
goto repeat;
}
}
void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
......@@ -231,9 +225,8 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
static void arp_reply(struct sk_buff *skb)
{
struct in_device *in_dev = (struct in_device *) skb->dev->ip_ptr;
struct arphdr *arp;
unsigned char *arp_ptr, *sha, *tha;
unsigned char *arp_ptr;
int size, type = ARPOP_REPLY, ptype = ETH_P_ARP;
u32 sip, tip;
struct sk_buff *send_skb;
......@@ -253,7 +246,7 @@ static void arp_reply(struct sk_buff *skb)
if (!np) return;
/* No arp on this interface */
if (!in_dev || skb->dev->flags & IFF_NOARP)
if (skb->dev->flags & IFF_NOARP)
return;
if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
......@@ -270,21 +263,15 @@ static void arp_reply(struct sk_buff *skb)
arp->ar_op != htons(ARPOP_REQUEST))
return;
arp_ptr= (unsigned char *)(arp+1);
sha = arp_ptr;
arp_ptr += skb->dev->addr_len;
arp_ptr = (unsigned char *)(arp+1) + skb->dev->addr_len;
memcpy(&sip, arp_ptr, 4);
arp_ptr += 4;
tha = arp_ptr;
arp_ptr += skb->dev->addr_len;
arp_ptr += 4 + skb->dev->addr_len;
memcpy(&tip, arp_ptr, 4);
/* Should we ignore arp? */
if (tip != in_dev->ifa_list->ifa_address ||
LOOPBACK(tip) || MULTICAST(tip))
if (tip != htonl(np->local_ip) || LOOPBACK(tip) || MULTICAST(tip))
return;
size = sizeof(struct arphdr) + 2 * (skb->dev->addr_len + 4);
send_skb = find_skb(np, size + LL_RESERVED_SPACE(np->dev),
LL_RESERVED_SPACE(np->dev));
......@@ -325,7 +312,7 @@ static void arp_reply(struct sk_buff *skb)
arp_ptr += np->dev->addr_len;
memcpy(arp_ptr, &tip, 4);
arp_ptr += 4;
memcpy(arp_ptr, np->local_mac, np->dev->addr_len);
memcpy(arp_ptr, np->remote_mac, np->dev->addr_len);
arp_ptr += np->dev->addr_len;
memcpy(arp_ptr, &sip, 4);
......
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