|
|
|
@ -136,7 +136,8 @@ |
|
|
|
|
#define AR2313_BUFSIZE (AR2313_MTU + ETH_HLEN + CRC_LEN + RX_OFFSET) |
|
|
|
|
|
|
|
|
|
#ifdef MODULE |
|
|
|
|
MODULE_AUTHOR("Sameer Dekate <sdekate@arubanetworks.com>, Imre Kaloz <kaloz@openwrt.org>, Felix Fietkau <nbd@openwrt.org>"); |
|
|
|
|
MODULE_AUTHOR |
|
|
|
|
("Sameer Dekate <sdekate@arubanetworks.com>, Imre Kaloz <kaloz@openwrt.org>, Felix Fietkau <nbd@openwrt.org>"); |
|
|
|
|
MODULE_DESCRIPTION("AR2313 Ethernet driver"); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
@ -144,7 +145,8 @@ MODULE_DESCRIPTION("AR2313 Ethernet driver"); |
|
|
|
|
|
|
|
|
|
// prototypes
|
|
|
|
|
static short armiiread(struct net_device *dev, short phy, short reg); |
|
|
|
|
static void armiiwrite(struct net_device *dev, short phy, short reg, short data); |
|
|
|
|
static void armiiwrite(struct net_device *dev, short phy, short reg, |
|
|
|
|
short data); |
|
|
|
|
#ifdef TX_TIMEOUT |
|
|
|
|
static void ar2313_tx_timeout(struct net_device *dev); |
|
|
|
|
#endif |
|
|
|
@ -168,7 +170,8 @@ int __init ar2313_probe(struct platform_device *pdev) |
|
|
|
|
dev = alloc_etherdev(sizeof(struct ar2313_private)); |
|
|
|
|
|
|
|
|
|
if (dev == NULL) { |
|
|
|
|
printk(KERN_ERR "ar2313: Unable to allocate net_device structure!\n"); |
|
|
|
|
printk(KERN_ERR |
|
|
|
|
"ar2313: Unable to allocate net_device structure!\n"); |
|
|
|
|
return -ENOMEM; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -212,7 +215,8 @@ int __init ar2313_probe(struct platform_device *pdev) |
|
|
|
|
tasklet_init(&sp->rx_tasklet, rx_tasklet_func, (unsigned long) dev); |
|
|
|
|
tasklet_disable(&sp->rx_tasklet); |
|
|
|
|
|
|
|
|
|
sp->eth_regs = ioremap_nocache(virt_to_phys(ar_eth_base), sizeof(*sp->eth_regs)); |
|
|
|
|
sp->eth_regs = |
|
|
|
|
ioremap_nocache(virt_to_phys(ar_eth_base), sizeof(*sp->eth_regs)); |
|
|
|
|
if (!sp->eth_regs) { |
|
|
|
|
printk("Can't remap eth registers\n"); |
|
|
|
|
return (-ENXIO); |
|
|
|
@ -226,14 +230,18 @@ int __init ar2313_probe(struct platform_device *pdev) |
|
|
|
|
if (virt_to_phys(ar_eth_base) == virt_to_phys(sp->phy_regs)) |
|
|
|
|
sp->phy_regs = sp->eth_regs; |
|
|
|
|
else { |
|
|
|
|
sp->phy_regs = ioremap_nocache(virt_to_phys(sp->cfg->phy_base), sizeof(*sp->phy_regs)); |
|
|
|
|
sp->phy_regs = |
|
|
|
|
ioremap_nocache(virt_to_phys(sp->cfg->phy_base), |
|
|
|
|
sizeof(*sp->phy_regs)); |
|
|
|
|
if (!sp->phy_regs) { |
|
|
|
|
printk("Can't remap phy registers\n"); |
|
|
|
|
return (-ENXIO); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
sp->dma_regs = ioremap_nocache(virt_to_phys(ar_eth_base + 0x1000), sizeof(*sp->dma_regs)); |
|
|
|
|
sp->dma_regs = |
|
|
|
|
ioremap_nocache(virt_to_phys(ar_eth_base + 0x1000), |
|
|
|
|
sizeof(*sp->dma_regs)); |
|
|
|
|
dev->base_addr = (unsigned int) sp->dma_regs; |
|
|
|
|
if (!sp->dma_regs) { |
|
|
|
|
printk("Can't remap DMA registers\n"); |
|
|
|
@ -267,8 +275,7 @@ int __init ar2313_probe(struct platform_device *pdev) |
|
|
|
|
printk("%s: %s: %02x:%02x:%02x:%02x:%02x:%02x, irq %d\n", |
|
|
|
|
dev->name, sp->name, |
|
|
|
|
dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], |
|
|
|
|
dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5], |
|
|
|
|
dev->irq); |
|
|
|
|
dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5], dev->irq); |
|
|
|
|
|
|
|
|
|
/* start link poll timer */ |
|
|
|
|
ar2313_setup_timer(dev); |
|
|
|
@ -283,7 +290,8 @@ static void ar2313_dump_regs(struct net_device *dev) |
|
|
|
|
struct ar2313_private *sp = (struct ar2313_private *) dev->priv; |
|
|
|
|
|
|
|
|
|
ptr = (unsigned int *) sp->eth_regs; |
|
|
|
|
for(i=0; i< (sizeof(ETHERNET_STRUCT)/ sizeof(unsigned int)); i++, ptr++) { |
|
|
|
|
for (i = 0; i < (sizeof(ETHERNET_STRUCT) / sizeof(unsigned int)); |
|
|
|
|
i++, ptr++) { |
|
|
|
|
printk("ENET: %08x = %08x\n", (int) ptr, *ptr); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -306,8 +314,7 @@ static void ar2313_dump_regs(struct net_device *dev) |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#ifdef TX_TIMEOUT |
|
|
|
|
static void |
|
|
|
|
ar2313_tx_timeout(struct net_device *dev) |
|
|
|
|
static void ar2313_tx_timeout(struct net_device *dev) |
|
|
|
|
{ |
|
|
|
|
struct ar2313_private *sp = (struct ar2313_private *) dev->priv; |
|
|
|
|
unsigned long flags; |
|
|
|
@ -322,8 +329,7 @@ ar2313_tx_timeout(struct net_device *dev) |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#if DEBUG_MC |
|
|
|
|
static void |
|
|
|
|
printMcList(struct net_device *dev) |
|
|
|
|
static void printMcList(struct net_device *dev) |
|
|
|
|
{ |
|
|
|
|
struct dev_mc_list *list = dev->mc_list; |
|
|
|
|
int num = 0, i; |
|
|
|
@ -342,8 +348,7 @@ printMcList(struct net_device *dev) |
|
|
|
|
* Set or clear the multicast filter for this adaptor. |
|
|
|
|
* THIS IS ABSOLUTE CRAP, disabled |
|
|
|
|
*/ |
|
|
|
|
static void |
|
|
|
|
ar2313_multicast_list(struct net_device *dev) |
|
|
|
|
static void ar2313_multicast_list(struct net_device *dev) |
|
|
|
|
{ |
|
|
|
|
/*
|
|
|
|
|
* Always listen to broadcasts and
|
|
|
|
@ -363,7 +368,8 @@ ar2313_multicast_list(struct net_device *dev) |
|
|
|
|
if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 15)) { |
|
|
|
|
#if DEBUG_MC |
|
|
|
|
printMcList(dev); |
|
|
|
|
printk("%s: all MULTICAST mc_count %d\n", __FUNCTION__, dev->mc_count); |
|
|
|
|
printk("%s: all MULTICAST mc_count %d\n", __FUNCTION__, |
|
|
|
|
dev->mc_count); |
|
|
|
|
#endif |
|
|
|
|
recognise |= MAC_CONTROL_PM; /* all multicast */ |
|
|
|
|
} else if (dev->mc_count > 0) { |
|
|
|
@ -374,7 +380,8 @@ ar2313_multicast_list(struct net_device *dev) |
|
|
|
|
recognise |= MAC_CONTROL_PM; /* for the time being */ |
|
|
|
|
} |
|
|
|
|
#if DEBUG_MC |
|
|
|
|
printk("%s: setting %08x to %08x\n", __FUNCTION__, (int)sp->eth_regs, recognise); |
|
|
|
|
printk("%s: setting %08x to %08x\n", __FUNCTION__, (int) sp->eth_regs, |
|
|
|
|
recognise); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
sp->eth_regs->mac_control = recognise; |
|
|
|
@ -468,7 +475,8 @@ static int ar2313_allocate_descriptors(struct net_device *dev) |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
size = (sizeof(ar2313_descr_t) * (AR2313_DESCR_ENTRIES * AR2313_QUEUES)); |
|
|
|
|
size = |
|
|
|
|
(sizeof(ar2313_descr_t) * (AR2313_DESCR_ENTRIES * AR2313_QUEUES)); |
|
|
|
|
space = kmalloc(size, GFP_KERNEL); |
|
|
|
|
if (space == NULL) |
|
|
|
|
return 1; |
|
|
|
@ -493,7 +501,9 @@ static int ar2313_allocate_descriptors(struct net_device *dev) |
|
|
|
|
td->status = 0; |
|
|
|
|
td->devcs = DMA_TX1_CHAINED; |
|
|
|
|
td->addr = 0; |
|
|
|
|
td->descr = virt_to_phys(&sp->tx_ring[(j+1) & (AR2313_DESCR_ENTRIES-1)]); |
|
|
|
|
td->descr = |
|
|
|
|
virt_to_phys(&sp-> |
|
|
|
|
tx_ring[(j + 1) & (AR2313_DESCR_ENTRIES - 1)]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
@ -512,8 +522,10 @@ static void ar2313_init_cleanup(struct net_device *dev) |
|
|
|
|
|
|
|
|
|
ar2313_free_descriptors(dev); |
|
|
|
|
|
|
|
|
|
if (sp->eth_regs) iounmap((void*)sp->eth_regs); |
|
|
|
|
if (sp->dma_regs) iounmap((void*)sp->dma_regs); |
|
|
|
|
if (sp->eth_regs) |
|
|
|
|
iounmap((void *) sp->eth_regs); |
|
|
|
|
if (sp->dma_regs) |
|
|
|
|
iounmap((void *) sp->dma_regs); |
|
|
|
|
|
|
|
|
|
if (sp->rx_skb) { |
|
|
|
|
for (j = 0; j < AR2313_DESCR_ENTRIES; j++) { |
|
|
|
@ -582,7 +594,8 @@ static void ar2313_check_link(struct net_device *dev) |
|
|
|
|
phyData = armiiread(dev, sp->phy, MII_BMSR); |
|
|
|
|
if (sp->phyData != phyData) { |
|
|
|
|
if (phyData & BMSR_LSTATUS) { |
|
|
|
|
/* link is present, ready link partner ability to deterine duplexity */ |
|
|
|
|
/* link is present, ready link partner ability to deterine
|
|
|
|
|
duplexity */ |
|
|
|
|
int duplex = 0; |
|
|
|
|
u16 reg; |
|
|
|
|
|
|
|
|
@ -597,17 +610,19 @@ static void ar2313_check_link(struct net_device *dev) |
|
|
|
|
duplex = (reg & BMCR_FULLDPLX) ? 1 : 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
printk(KERN_INFO "%s: Configuring MAC for %s duplex\n", dev->name, |
|
|
|
|
(duplex)? "full":"half"); |
|
|
|
|
printk(KERN_INFO "%s: Configuring MAC for %s duplex\n", |
|
|
|
|
dev->name, (duplex) ? "full" : "half"); |
|
|
|
|
|
|
|
|
|
if (duplex) { |
|
|
|
|
/* full duplex */ |
|
|
|
|
sp->eth_regs->mac_control = ((sp->eth_regs->mac_control | MAC_CONTROL_F) & |
|
|
|
|
~MAC_CONTROL_DRO); |
|
|
|
|
sp->eth_regs->mac_control = |
|
|
|
|
((sp->eth_regs-> |
|
|
|
|
mac_control | MAC_CONTROL_F) & ~MAC_CONTROL_DRO); |
|
|
|
|
} else { |
|
|
|
|
/* half duplex */ |
|
|
|
|
sp->eth_regs->mac_control = ((sp->eth_regs->mac_control | MAC_CONTROL_DRO) & |
|
|
|
|
~MAC_CONTROL_F); |
|
|
|
|
sp->eth_regs->mac_control = |
|
|
|
|
((sp->eth_regs-> |
|
|
|
|
mac_control | MAC_CONTROL_DRO) & ~MAC_CONTROL_F); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
/* no link */ |
|
|
|
@ -617,8 +632,7 @@ static void ar2313_check_link(struct net_device *dev) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int |
|
|
|
|
ar2313_reset_reg(struct net_device *dev) |
|
|
|
|
static int ar2313_reset_reg(struct net_device *dev) |
|
|
|
|
{ |
|
|
|
|
struct ar2313_private *sp = (struct ar2313_private *) dev->priv; |
|
|
|
|
unsigned int ethsal, ethsah; |
|
|
|
@ -635,17 +649,18 @@ ar2313_reset_reg(struct net_device *dev) |
|
|
|
|
|
|
|
|
|
sp->dma_regs->bus_mode = (DMA_BUS_MODE_SWR); |
|
|
|
|
mdelay(10); |
|
|
|
|
sp->dma_regs->bus_mode = ((32 << DMA_BUS_MODE_PBL_SHIFT) | DMA_BUS_MODE_BLE); |
|
|
|
|
sp->dma_regs->bus_mode = |
|
|
|
|
((32 << DMA_BUS_MODE_PBL_SHIFT) | DMA_BUS_MODE_BLE); |
|
|
|
|
|
|
|
|
|
/* enable interrupts */ |
|
|
|
|
sp->dma_regs->intr_ena = (DMA_STATUS_AIS | |
|
|
|
|
DMA_STATUS_NIS | |
|
|
|
|
DMA_STATUS_RI | |
|
|
|
|
DMA_STATUS_TI | |
|
|
|
|
DMA_STATUS_FBE); |
|
|
|
|
DMA_STATUS_TI | DMA_STATUS_FBE); |
|
|
|
|
sp->dma_regs->xmt_base = virt_to_phys(sp->tx_ring); |
|
|
|
|
sp->dma_regs->rcv_base = virt_to_phys(sp->rx_ring); |
|
|
|
|
sp->dma_regs->control = (DMA_CONTROL_SR | DMA_CONTROL_ST | DMA_CONTROL_SF); |
|
|
|
|
sp->dma_regs->control = |
|
|
|
|
(DMA_CONTROL_SR | DMA_CONTROL_ST | DMA_CONTROL_SF); |
|
|
|
|
|
|
|
|
|
sp->eth_regs->flow_control = (FLOW_CONTROL_FCE); |
|
|
|
|
sp->eth_regs->vlan_tag = (0x8100); |
|
|
|
@ -698,7 +713,9 @@ static int ar2313_init(struct net_device *dev) |
|
|
|
|
* Get the memory for the skb rings. |
|
|
|
|
*/ |
|
|
|
|
if (sp->rx_skb == NULL) { |
|
|
|
|
sp->rx_skb = kmalloc(sizeof(struct sk_buff *) * AR2313_DESCR_ENTRIES, GFP_KERNEL); |
|
|
|
|
sp->rx_skb = |
|
|
|
|
kmalloc(sizeof(struct sk_buff *) * AR2313_DESCR_ENTRIES, |
|
|
|
|
GFP_KERNEL); |
|
|
|
|
if (!(sp->rx_skb)) { |
|
|
|
|
printk("%s: %s: rx_skb kmalloc failed\n", |
|
|
|
|
dev->name, __FUNCTION__); |
|
|
|
@ -709,7 +726,9 @@ static int ar2313_init(struct net_device *dev) |
|
|
|
|
memset(sp->rx_skb, 0, sizeof(struct sk_buff *) * AR2313_DESCR_ENTRIES); |
|
|
|
|
|
|
|
|
|
if (sp->tx_skb == NULL) { |
|
|
|
|
sp->tx_skb = kmalloc(sizeof(struct sk_buff *) * AR2313_DESCR_ENTRIES, GFP_KERNEL); |
|
|
|
|
sp->tx_skb = |
|
|
|
|
kmalloc(sizeof(struct sk_buff *) * AR2313_DESCR_ENTRIES, |
|
|
|
|
GFP_KERNEL); |
|
|
|
|
if (!(sp->tx_skb)) { |
|
|
|
|
printk("%s: %s: tx_skb kmalloc failed\n", |
|
|
|
|
dev->name, __FUNCTION__); |
|
|
|
@ -749,7 +768,10 @@ static int ar2313_init(struct net_device *dev) |
|
|
|
|
/*
|
|
|
|
|
* Get the IRQ |
|
|
|
|
*/ |
|
|
|
|
ecode = request_irq(dev->irq, &ar2313_interrupt, IRQF_SHARED | IRQF_DISABLED | IRQF_SAMPLE_RANDOM, dev->name, dev); |
|
|
|
|
ecode = |
|
|
|
|
request_irq(dev->irq, &ar2313_interrupt, |
|
|
|
|
IRQF_SHARED | IRQF_DISABLED | IRQF_SAMPLE_RANDOM, |
|
|
|
|
dev->name, dev); |
|
|
|
|
if (ecode) { |
|
|
|
|
printk(KERN_WARNING "%s: %s: Requested IRQ %d is busy\n", |
|
|
|
|
dev->name, __FUNCTION__, dev->irq); |
|
|
|
@ -791,11 +813,11 @@ static void ar2313_load_rx_ring(struct net_device *dev, int nr_bufs) |
|
|
|
|
#endif /* DEBUG */ |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// partha: create additional room for the second GRE fragment
|
|
|
|
|
skb = alloc_skb(AR2313_BUFSIZE + 128, GFP_ATOMIC); |
|
|
|
|
if (!skb) { |
|
|
|
|
printk("\n\n\n\n %s: No memory in system\n\n\n\n", __FUNCTION__); |
|
|
|
|
printk("\n\n\n\n %s: No memory in system\n\n\n\n", |
|
|
|
|
__FUNCTION__); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
// partha: create additional room in the front for tx pkt capture
|
|
|
|
@ -814,7 +836,9 @@ static void ar2313_load_rx_ring(struct net_device *dev, int nr_bufs) |
|
|
|
|
rd->devcs = ((AR2313_BUFSIZE << DMA_RX1_BSIZE_SHIFT) | |
|
|
|
|
DMA_RX1_CHAINED); |
|
|
|
|
rd->addr = virt_to_phys(skb->data); |
|
|
|
|
rd->descr = virt_to_phys(&sp->rx_ring[(idx+1) & (AR2313_DESCR_ENTRIES-1)]); |
|
|
|
|
rd->descr = |
|
|
|
|
virt_to_phys(&sp-> |
|
|
|
|
rx_ring[(idx + 1) & (AR2313_DESCR_ENTRIES - 1)]); |
|
|
|
|
rd->status = DMA_RX_OWN; |
|
|
|
|
|
|
|
|
|
idx = DSC_NEXT(idx); |
|
|
|
@ -822,7 +846,8 @@ static void ar2313_load_rx_ring(struct net_device *dev, int nr_bufs) |
|
|
|
|
|
|
|
|
|
if (!i) { |
|
|
|
|
#if DEBUG_ERR |
|
|
|
|
printk(KERN_INFO "Out of memory when allocating standard receive buffers\n"); |
|
|
|
|
printk(KERN_INFO |
|
|
|
|
"Out of memory when allocating standard receive buffers\n"); |
|
|
|
|
#endif /* DEBUG */ |
|
|
|
|
} else { |
|
|
|
|
sp->rx_skbprd = idx; |
|
|
|
@ -845,7 +870,8 @@ static int ar2313_rx_int(struct net_device *dev) |
|
|
|
|
|
|
|
|
|
idx = sp->cur_rx; |
|
|
|
|
|
|
|
|
|
/* process at most the entire ring and then wait for another interrupt */ |
|
|
|
|
/* process at most the entire ring and then wait for another interrupt
|
|
|
|
|
*/ |
|
|
|
|
while (1) { |
|
|
|
|
|
|
|
|
|
rxdesc = &sp->rx_ring[idx]; |
|
|
|
@ -860,7 +886,6 @@ static int ar2313_rx_int(struct net_device *dev) |
|
|
|
|
rval = 1; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#if DEBUG_RX |
|
|
|
|
printk("index %d\n", idx); |
|
|
|
|
printk("RX status %08x\n", rxdesc->status); |
|
|
|
@ -878,12 +903,16 @@ static int ar2313_rx_int(struct net_device *dev) |
|
|
|
|
sp->stats.rx_dropped++; |
|
|
|
|
|
|
|
|
|
/* add statistics counters */ |
|
|
|
|
if (status & DMA_RX_ERR_CRC) sp->stats.rx_crc_errors++; |
|
|
|
|
if (status & DMA_RX_ERR_COL) sp->stats.rx_over_errors++; |
|
|
|
|
if (status & DMA_RX_ERR_CRC) |
|
|
|
|
sp->stats.rx_crc_errors++; |
|
|
|
|
if (status & DMA_RX_ERR_COL) |
|
|
|
|
sp->stats.rx_over_errors++; |
|
|
|
|
if (status & DMA_RX_ERR_LENGTH) |
|
|
|
|
sp->stats.rx_length_errors++; |
|
|
|
|
if (status & DMA_RX_ERR_RUNT) sp->stats.rx_over_errors++; |
|
|
|
|
if (status & DMA_RX_ERR_DESC) sp->stats.rx_over_errors++; |
|
|
|
|
if (status & DMA_RX_ERR_RUNT) |
|
|
|
|
sp->stats.rx_over_errors++; |
|
|
|
|
if (status & DMA_RX_ERR_DESC) |
|
|
|
|
sp->stats.rx_over_errors++; |
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
/* alloc new buffer. */ |
|
|
|
@ -892,7 +921,8 @@ static int ar2313_rx_int(struct net_device *dev) |
|
|
|
|
|
|
|
|
|
skb = sp->rx_skb[idx]; |
|
|
|
|
/* set skb */ |
|
|
|
|
skb_put(skb, ((status >> DMA_RX_LEN_SHIFT) & 0x3fff) - CRC_LEN); |
|
|
|
|
skb_put(skb, |
|
|
|
|
((status >> DMA_RX_LEN_SHIFT) & 0x3fff) - CRC_LEN); |
|
|
|
|
|
|
|
|
|
sp->stats.rx_bytes += skb->len; |
|
|
|
|
skb->protocol = eth_type_trans(skb, dev); |
|
|
|
@ -940,9 +970,10 @@ static void ar2313_tx_int(struct net_device *dev) |
|
|
|
|
txdesc = &sp->tx_ring[idx]; |
|
|
|
|
|
|
|
|
|
#if DEBUG_TX |
|
|
|
|
printk("%s: TXINT: csm=%d idx=%d prd=%d status=%x devcs=%x addr=%08x descr=%x\n",
|
|
|
|
|
dev->name, sp->tx_csm, idx, sp->tx_prd, |
|
|
|
|
txdesc->status, txdesc->devcs, txdesc->addr, txdesc->descr); |
|
|
|
|
printk |
|
|
|
|
("%s: TXINT: csm=%d idx=%d prd=%d status=%x devcs=%x addr=%08x descr=%x\n", |
|
|
|
|
dev->name, sp->tx_csm, idx, sp->tx_prd, txdesc->status, |
|
|
|
|
txdesc->devcs, txdesc->addr, txdesc->descr); |
|
|
|
|
#endif /* DEBUG */ |
|
|
|
|
|
|
|
|
|
if ((status = txdesc->status) & DMA_TX_OWN) { |
|
|
|
@ -950,7 +981,9 @@ static void ar2313_tx_int(struct net_device *dev) |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
/* done with this descriptor */ |
|
|
|
|
dma_unmap_single(NULL, txdesc->addr, txdesc->devcs & DMA_TX1_BSIZE_MASK, DMA_TO_DEVICE); |
|
|
|
|
dma_unmap_single(NULL, txdesc->addr, |
|
|
|
|
txdesc->devcs & DMA_TX1_BSIZE_MASK, |
|
|
|
|
DMA_TO_DEVICE); |
|
|
|
|
txdesc->status = 0; |
|
|
|
|
|
|
|
|
|
if (status & DMA_TX_ERROR) { |
|
|
|
@ -960,13 +993,11 @@ static void ar2313_tx_int(struct net_device *dev) |
|
|
|
|
sp->stats.tx_fifo_errors++; |
|
|
|
|
if (status & DMA_TX_ERR_HB) |
|
|
|
|
sp->stats.tx_heartbeat_errors++; |
|
|
|
|
if(status & (DMA_TX_ERR_LOSS | |
|
|
|
|
DMA_TX_ERR_LINK)) |
|
|
|
|
if (status & (DMA_TX_ERR_LOSS | DMA_TX_ERR_LINK)) |
|
|
|
|
sp->stats.tx_carrier_errors++; |
|
|
|
|
if (status & (DMA_TX_ERR_LATE | |
|
|
|
|
DMA_TX_ERR_COL | |
|
|
|
|
DMA_TX_ERR_JABBER | |
|
|
|
|
DMA_TX_ERR_DEFER)) |
|
|
|
|
DMA_TX_ERR_JABBER | DMA_TX_ERR_DEFER)) |
|
|
|
|
sp->stats.tx_aborted_errors++; |
|
|
|
|
} else { |
|
|
|
|
/* transmit OK */ |
|
|
|
@ -986,8 +1017,7 @@ static void ar2313_tx_int(struct net_device *dev) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
rx_tasklet_func(unsigned long data) |
|
|
|
|
static void rx_tasklet_func(unsigned long data) |
|
|
|
|
{ |
|
|
|
|
struct net_device *dev = (struct net_device *) data; |
|
|
|
|
struct ar2313_private *sp = dev->priv; |
|
|
|
@ -998,8 +1028,7 @@ rx_tasklet_func(unsigned long data) |
|
|
|
|
|
|
|
|
|
if (ar2313_rx_int(dev)) { |
|
|
|
|
tasklet_hi_schedule(&sp->rx_tasklet); |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
} else { |
|
|
|
|
unsigned long flags; |
|
|
|
|
spin_lock_irqsave(&sp->lock, flags); |
|
|
|
|
sp->dma_regs->intr_ena |= DMA_STATUS_RI; |
|
|
|
@ -1007,8 +1036,7 @@ rx_tasklet_func(unsigned long data) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
rx_schedule(struct net_device *dev) |
|
|
|
|
static void rx_schedule(struct net_device *dev) |
|
|
|
|
{ |
|
|
|
|
struct ar2313_private *sp = dev->priv; |
|
|
|
|
|
|
|
|
@ -1189,7 +1217,8 @@ static int ar2313_start_xmit(struct sk_buff *skb, struct net_device *dev) |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd) |
|
|
|
|
static int netdev_get_ecmd(struct net_device *dev, |
|
|
|
|
struct ethtool_cmd *ecmd) |
|
|
|
|
{ |
|
|
|
|
struct ar2313_private *np = dev->priv; |
|
|
|
|
u32 tmp; |
|
|
|
@ -1254,7 +1283,8 @@ static int netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd) |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd) |
|
|
|
|
static int netdev_set_ecmd(struct net_device *dev, |
|
|
|
|
struct ethtool_cmd *ecmd) |
|
|
|
|
{ |
|
|
|
|
struct ar2313_private *np = dev->priv; |
|
|
|
|
u32 tmp; |
|
|
|
@ -1267,7 +1297,8 @@ static int netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd) |
|
|
|
|
return -EINVAL; |
|
|
|
|
if (ecmd->transceiver != XCVR_INTERNAL) |
|
|
|
|
return -EINVAL; |
|
|
|
|
if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE) |
|
|
|
|
if (ecmd->autoneg != AUTONEG_DISABLE |
|
|
|
|
&& ecmd->autoneg != AUTONEG_ENABLE) |
|
|
|
|
return -EINVAL; |
|
|
|
|
/* ignore phy_address, maxtxpkt, maxrxpkt for now */ |
|
|
|
|
|
|
|
|
@ -1340,7 +1371,8 @@ static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr) |
|
|
|
|
/* get link status */ |
|
|
|
|
case ETHTOOL_GLINK:{ |
|
|
|
|
struct ethtool_value edata = { ETHTOOL_GLINK }; |
|
|
|
|
edata.data = (armiiread(dev, np->phy, MII_BMSR)&BMSR_LSTATUS) ? 1:0; |
|
|
|
|
edata.data = |
|
|
|
|
(armiiread(dev, np->phy, MII_BMSR) & BMSR_LSTATUS) ? 1 : 0; |
|
|
|
|
if (copy_to_user(useraddr, &edata, sizeof(edata))) |
|
|
|
|
return -EFAULT; |
|
|
|
|
return 0; |
|
|
|
@ -1375,12 +1407,14 @@ static int ar2313_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
case SIOCSIFHWADDR: |
|
|
|
|
if (copy_from_user(dev->dev_addr, ifr->ifr_data, sizeof(dev->dev_addr))) |
|
|
|
|
if (copy_from_user |
|
|
|
|
(dev->dev_addr, ifr->ifr_data, sizeof(dev->dev_addr))) |
|
|
|
|
return -EFAULT; |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
case SIOCGIFHWADDR: |
|
|
|
|
if (copy_to_user(ifr->ifr_data, dev->dev_addr, sizeof(dev->dev_addr))) |
|
|
|
|
if (copy_to_user |
|
|
|
|
(ifr->ifr_data, dev->dev_addr, sizeof(dev->dev_addr))) |
|
|
|
|
return -EFAULT; |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
@ -1401,8 +1435,7 @@ static struct net_device_stats *ar2313_get_stats(struct net_device *dev) |
|
|
|
|
#define MII_ADDR(phy, reg) \ |
|
|
|
|
((reg << MII_ADDR_REG_SHIFT) | (phy << MII_ADDR_PHY_SHIFT)) |
|
|
|
|
|
|
|
|
|
static short |
|
|
|
|
armiiread(struct net_device *dev, short phy, short reg) |
|
|
|
|
static short armiiread(struct net_device *dev, short phy, short reg) |
|
|
|
|
{ |
|
|
|
|
struct ar2313_private *sp = (struct ar2313_private *) dev->priv; |
|
|
|
|
volatile ETHERNET_STRUCT *ethernet = sp->phy_regs; |
|
|
|
@ -1422,4 +1455,3 @@ armiiwrite(struct net_device *dev, short phy, short reg, short data) |
|
|
|
|
ethernet->mii_data = data << MII_DATA_SHIFT; |
|
|
|
|
ethernet->mii_addr = MII_ADDR(phy, reg) | MII_ADDR_WRITE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|