Commit 1e1af316 authored by Jes Sorensen's avatar Jes Sorensen Committed by Linus Torvalds

[PATCH] rrunner PCI DMA mappings

This makes drivers/net/rrunner.[ch] use the PCI DMA mapping API.  It
also fixes some potential SMP bugs where spin locks were taking outside
of interrupt context without disabling interrupts.
parent c5221eba
/* /*
* rrunner.c: Linux driver for the Essential RoadRunner HIPPI board. * rrunner.c: Linux driver for the Essential RoadRunner HIPPI board.
* *
* Copyright (C) 1998-2000 by Jes Sorensen, <Jes.Sorensen@cern.ch>. * Copyright (C) 1998-2002 by Jes Sorensen, <jes@wildopensource.com>.
* *
* Thanks to Essential Communication for providing us with hardware * Thanks to Essential Communication for providing us with hardware
* and very comprehensive documentation without which I would not have * and very comprehensive documentation without which I would not have
...@@ -19,9 +19,10 @@ ...@@ -19,9 +19,10 @@
* *
* Softnet support and various other patches from Val Henson of * Softnet support and various other patches from Val Henson of
* ODS/Essential. * ODS/Essential.
*
* PCI DMA mapping code partly based on work by Francois Romieu.
*/ */
#error Please convert me to Documentation/DMA-mapping.txt
#define DEBUG 1 #define DEBUG 1
#define RX_DMA_SKBUFF 1 #define RX_DMA_SKBUFF 1
...@@ -50,45 +51,20 @@ ...@@ -50,45 +51,20 @@
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#if (LINUX_VERSION_CODE < 0x02030e)
#define net_device device
#endif
#if (LINUX_VERSION_CODE >= 0x02031b)
#define NEW_NETINIT
#endif
#if (LINUX_VERSION_CODE < 0x02032b)
/*
* SoftNet changes
*/
#define dev_kfree_skb_irq(a) dev_kfree_skb(a)
#define netif_wake_queue(dev) clear_bit(0, &dev->tbusy)
#define netif_stop_queue(dev) set_bit(0, &dev->tbusy)
static inline void netif_start_queue(struct net_device *dev)
{
dev->tbusy = 0;
dev->start = 1;
}
#define rr_mark_net_bh(foo) mark_bh(foo)
#define rr_if_busy(dev) dev->tbusy
#define rr_if_running(dev) dev->start /* Currently unused. */
#define rr_if_down(dev) do { dev->start = 0; } while (0)
#else
#define NET_BH 0
#define rr_mark_net_bh(foo) do { } while(0)
#define rr_if_busy(dev) netif_queue_stopped(dev) #define rr_if_busy(dev) netif_queue_stopped(dev)
#define rr_if_running(dev) netif_running(dev) #define rr_if_running(dev) netif_running(dev)
#define rr_if_down(dev) do { } while(0)
#endif
#include "rrunner.h" #include "rrunner.h"
#define RUN_AT(x) (jiffies + (x)) #define RUN_AT(x) (jiffies + (x))
MODULE_AUTHOR("Jes Sorensen <jes@wildopensource.com>");
MODULE_DESCRIPTION("Essential RoadRunner HIPPI driver");
MODULE_LICENSE("GPL");
static char version[] __initdata = "rrunner.c: v0.50 11/11/2002 Jes Sorensen (jes@wildopensource.com)\n";
/* /*
* Implementation notes: * Implementation notes:
* *
...@@ -104,11 +80,6 @@ static inline void netif_start_queue(struct net_device *dev) ...@@ -104,11 +80,6 @@ static inline void netif_start_queue(struct net_device *dev)
* stack will need to know about I/O vectors or something similar. * stack will need to know about I/O vectors or something similar.
*/ */
static char version[] __initdata = "rrunner.c: v0.22 03/01/2000 Jes Sorensen (Jes.Sorensen@cern.ch)\n";
static struct net_device *root_dev;
/* /*
* These are checked at init time to see if they are at least 256KB * These are checked at init time to see if they are at least 256KB
* and increased to 256KB if they are not. This is done to avoid ending * and increased to 256KB if they are not. This is done to avoid ending
...@@ -117,200 +88,185 @@ static struct net_device *root_dev; ...@@ -117,200 +88,185 @@ static struct net_device *root_dev;
extern __u32 sysctl_wmem_max; extern __u32 sysctl_wmem_max;
extern __u32 sysctl_rmem_max; extern __u32 sysctl_rmem_max;
static int probed __initdata = 0; static int __devinit rr_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
#if LINUX_VERSION_CODE >= 0x20400
static struct pci_device_id rrunner_pci_tbl[] __initdata = {
{ PCI_VENDOR_ID_ESSENTIAL, PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER, PCI_ANY_ID, PCI_ANY_ID, },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(pci, rrunner_pci_tbl);
#endif /* LINUX_VERSION_CODE >= 0x20400 */
#ifdef NEW_NETINIT
int __init rr_hippi_probe (void)
#else
int __init rr_hippi_probe (struct net_device *dev)
#endif
{ {
#ifdef NEW_NETINIT
struct net_device *dev; struct net_device *dev;
#endif static int version_disp;
int boards_found = 0;
int version_disp; /* was version info already displayed? */
struct pci_dev *pdev = NULL;
struct pci_dev *opdev = NULL;
u8 pci_latency; u8 pci_latency;
struct rr_private *rrpriv; struct rr_private *rrpriv;
void *tmpptr;
dma_addr_t ring_dma;
int ret;
dev = init_hippi_dev(NULL, sizeof(struct rr_private));
if (!dev) {
ret = -ENOMEM;
goto out2;
}
if (probed) ret = pci_enable_device(pdev);
return -ENODEV; if (ret) {
probed++; ret = -ENODEV;
goto out2;
}
version_disp = 0; if (!dev->priv)
dev->priv = kmalloc(sizeof(*rrpriv), GFP_KERNEL);
while((pdev = pci_find_device(PCI_VENDOR_ID_ESSENTIAL, if (!dev->priv) {
PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER, ret = -ENOMEM;
pdev))) goto out2;
{ }
if (pci_enable_device(pdev))
continue;
if (pdev == opdev) rrpriv = (struct rr_private *)dev->priv;
return 0; memset(rrpriv, 0, sizeof(*rrpriv));
/* SET_MODULE_OWNER(dev);
* So we found our HIPPI ... time to tell the system.
*/
dev = init_hippi_dev(NULL, sizeof(struct rr_private)); if (pci_request_regions(pdev, "rrunner")) {
ret = -EIO;
goto out;
}
if (!dev) pci_set_drvdata(pdev, dev);
break;
if (!dev->priv) rrpriv->pci_dev = pdev;
dev->priv = kmalloc(sizeof(*rrpriv), GFP_KERNEL);
if (!dev->priv) spin_lock_init(&rrpriv->lock);
return -ENOMEM; sprintf(rrpriv->name, "RoadRunner serial HIPPI");
rrpriv = (struct rr_private *)dev->priv; dev->irq = pdev->irq;
memset(rrpriv, 0, sizeof(*rrpriv)); dev->open = &rr_open;
dev->hard_start_xmit = &rr_start_xmit;
dev->stop = &rr_close;
dev->get_stats = &rr_get_stats;
dev->do_ioctl = &rr_ioctl;
#ifdef CONFIG_SMP dev->base_addr = pci_resource_start(pdev, 0);
spin_lock_init(&rrpriv->lock);
#endif
sprintf(rrpriv->name, "RoadRunner serial HIPPI");
dev->irq = pdev->irq;
SET_MODULE_OWNER(dev);
dev->open = &rr_open;
dev->hard_start_xmit = &rr_start_xmit;
dev->stop = &rr_close;
dev->get_stats = &rr_get_stats;
dev->do_ioctl = &rr_ioctl;
#if (LINUX_VERSION_CODE < 0x02030d)
dev->base_addr = pdev->base_address[0];
#else
dev->base_addr = pdev->resource[0].start;
#endif
/* display version info if adapter is found */ /* display version info if adapter is found */
if (!version_disp) if (!version_disp) {
{ /* set display flag to TRUE so that */
/* set display flag to TRUE so that */ /* we only display this string ONCE */
/* we only display this string ONCE */ version_disp = 1;
version_disp = 1; printk(version);
printk(version); }
}
pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency); pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
if (pci_latency <= 0x58){ if (pci_latency <= 0x58){
pci_latency = 0x58; pci_latency = 0x58;
pci_write_config_byte(pdev, PCI_LATENCY_TIMER, pci_write_config_byte(pdev, PCI_LATENCY_TIMER, pci_latency);
pci_latency); }
}
pci_set_master(pdev); pci_set_master(pdev);
printk(KERN_INFO "%s: Essential RoadRunner serial HIPPI " printk(KERN_INFO "%s: Essential RoadRunner serial HIPPI "
"at 0x%08lx, irq %i, PCI latency %i\n", dev->name, "at 0x%08lx, irq %i, PCI latency %i\n", dev->name,
dev->base_addr, dev->irq, pci_latency); dev->base_addr, dev->irq, pci_latency);
/* /*
* Remap the regs into kernel space. * Remap the regs into kernel space.
*/ */
rrpriv->regs = (struct rr_regs *) rrpriv->regs = (struct rr_regs *)ioremap(dev->base_addr, 0x1000);
ioremap(dev->base_addr, 0x1000);
if (!rrpriv->regs){ if (!rrpriv->regs){
printk(KERN_ERR "%s: Unable to map I/O register, " printk(KERN_ERR "%s: Unable to map I/O register, "
"RoadRunner %i will be disabled.\n", "RoadRunner will be disabled.\n", dev->name);
dev->name, boards_found); ret = -EIO;
break; goto out;
} }
/* tmpptr = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
* Don't access any registes before this point! rrpriv->tx_ring = tmpptr;
*/ rrpriv->tx_ring_dma = ring_dma;
#ifdef __BIG_ENDIAN
writel(readl(&regs->HostCtrl) | NO_SWAP, &regs->HostCtrl);
#endif
/*
* Need to add a case for little-endian 64-bit hosts here.
*/
rr_init(dev); if (!tmpptr) {
ret = -ENOMEM;
goto out;
}
tmpptr = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);
rrpriv->rx_ring = tmpptr;
rrpriv->rx_ring_dma = ring_dma;
boards_found++; if (!tmpptr) {
dev->base_addr = 0; ret = -ENOMEM;
dev = NULL; goto out;
opdev = pdev; }
tmpptr = pci_alloc_consistent(pdev, EVT_RING_SIZE, &ring_dma);
rrpriv->evt_ring = tmpptr;
rrpriv->evt_ring_dma = ring_dma;
if (!tmpptr) {
ret = -ENOMEM;
goto out;
} }
/* /*
* If we're at this point we're going through rr_hippi_probe() * Don't access any register before this point!
* for the first time. Return success (0) if we've initialized
* 1 or more boards. Otherwise, return failure (-ENODEV).
*/ */
#ifdef __BIG_ENDIAN
#ifdef MODULE writel(readl(&regs->HostCtrl) | NO_SWAP, &regs->HostCtrl);
return boards_found;
#else
if (boards_found > 0)
return 0;
else
return -ENODEV;
#endif #endif
} /*
* Need to add a case for little-endian 64-bit hosts here.
*/
rr_init(dev);
#ifdef MODULE dev->base_addr = 0;
#if LINUX_VERSION_CODE > 0x20118 return 0;
MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@cern.ch>");
MODULE_DESCRIPTION("Essential RoadRunner HIPPI driver");
MODULE_LICENSE("GPL");
#endif
int init_module(void)
{
int cards;
root_dev = NULL; out:
if (rrpriv->rx_ring)
pci_free_consistent(pdev, RX_TOTAL_SIZE, rrpriv->rx_ring,
rrpriv->rx_ring_dma);
if (rrpriv->tx_ring)
pci_free_consistent(pdev, TX_TOTAL_SIZE, rrpriv->tx_ring,
rrpriv->tx_ring_dma);
if (rrpriv->regs)
iounmap(rrpriv->regs);
if (pdev) {
pci_release_regions(pdev);
pci_set_drvdata(pdev, NULL);
}
#ifdef NEW_NETINIT out2:
cards = rr_hippi_probe(); if (dev) {
#else unregister_hipdev(dev);
cards = rr_hippi_probe(NULL); kfree(dev);
#endif }
return cards ? 0 : -ENODEV; return ret;
} }
void cleanup_module(void) static void __devexit rr_remove_one (struct pci_dev *pdev)
{ {
struct rr_private *rr; struct net_device *dev = pci_get_drvdata(pdev);
struct net_device *next; struct rr_private *rr = (struct rr_private *)dev->priv;
while (root_dev) {
next = ((struct rr_private *)root_dev->priv)->next;
rr = (struct rr_private *)root_dev->priv;
if (dev) {
if (!(readl(&rr->regs->HostCtrl) & NIC_HALTED)){ if (!(readl(&rr->regs->HostCtrl) & NIC_HALTED)){
printk(KERN_ERR "%s: trying to unload running NIC\n", printk(KERN_ERR "%s: trying to unload running NIC\n",
root_dev->name); dev->name);
writel(HALT_NIC, &rr->regs->HostCtrl); writel(HALT_NIC, &rr->regs->HostCtrl);
} }
pci_free_consistent(pdev, EVT_RING_SIZE, rr->evt_ring,
rr->evt_ring_dma);
pci_free_consistent(pdev, RX_TOTAL_SIZE, rr->rx_ring,
rr->rx_ring_dma);
pci_free_consistent(pdev, TX_TOTAL_SIZE, rr->tx_ring,
rr->tx_ring_dma);
unregister_hipdev(dev);
iounmap(rr->regs); iounmap(rr->regs);
unregister_hipdev(root_dev); kfree(dev);
kfree(root_dev); pci_release_regions(pdev);
pci_set_drvdata(pdev, NULL);
root_dev = next;
} }
} }
#endif
/* /*
...@@ -634,9 +590,6 @@ static int __init rr_init(struct net_device *dev) ...@@ -634,9 +590,6 @@ static int __init rr_init(struct net_device *dev)
sysctl_wmem_max = 262144; sysctl_wmem_max = 262144;
} }
rrpriv->next = root_dev;
root_dev = dev;
return 0; return 0;
} }
...@@ -668,14 +621,14 @@ static int rr_init1(struct net_device *dev) ...@@ -668,14 +621,14 @@ static int rr_init1(struct net_device *dev)
goto error; goto error;
} }
set_rxaddr(regs, rrpriv->rx_ctrl); set_rxaddr(regs, rrpriv->rx_ctrl_dma);
set_infoaddr(regs, rrpriv->info); set_infoaddr(regs, rrpriv->info_dma);
rrpriv->info->evt_ctrl.entry_size = sizeof(struct event); rrpriv->info->evt_ctrl.entry_size = sizeof(struct event);
rrpriv->info->evt_ctrl.entries = EVT_RING_ENTRIES; rrpriv->info->evt_ctrl.entries = EVT_RING_ENTRIES;
rrpriv->info->evt_ctrl.mode = 0; rrpriv->info->evt_ctrl.mode = 0;
rrpriv->info->evt_ctrl.pi = 0; rrpriv->info->evt_ctrl.pi = 0;
set_rraddr(&rrpriv->info->evt_ctrl.rngptr, rrpriv->evt_ring); set_rraddr(&rrpriv->info->evt_ctrl.rngptr, rrpriv->evt_ring_dma);
rrpriv->info->cmd_ctrl.entry_size = sizeof(struct cmd); rrpriv->info->cmd_ctrl.entry_size = sizeof(struct cmd);
rrpriv->info->cmd_ctrl.entries = CMD_RING_ENTRIES; rrpriv->info->cmd_ctrl.entries = CMD_RING_ENTRIES;
...@@ -695,7 +648,7 @@ static int rr_init1(struct net_device *dev) ...@@ -695,7 +648,7 @@ static int rr_init1(struct net_device *dev)
rrpriv->info->tx_ctrl.entries = TX_RING_ENTRIES; rrpriv->info->tx_ctrl.entries = TX_RING_ENTRIES;
rrpriv->info->tx_ctrl.mode = 0; rrpriv->info->tx_ctrl.mode = 0;
rrpriv->info->tx_ctrl.pi = 0; rrpriv->info->tx_ctrl.pi = 0;
set_rraddr(&rrpriv->info->tx_ctrl.rngptr, rrpriv->tx_ring); set_rraddr(&rrpriv->info->tx_ctrl.rngptr, rrpriv->tx_ring_dma);
/* /*
* Set dirty_tx before we start receiving interrupts, otherwise * Set dirty_tx before we start receiving interrupts, otherwise
...@@ -730,6 +683,7 @@ static int rr_init1(struct net_device *dev) ...@@ -730,6 +683,7 @@ static int rr_init1(struct net_device *dev)
for (i = 0; i < RX_RING_ENTRIES; i++) { for (i = 0; i < RX_RING_ENTRIES; i++) {
struct sk_buff *skb; struct sk_buff *skb;
dma_addr_t addr;
rrpriv->rx_ring[i].mode = 0; rrpriv->rx_ring[i].mode = 0;
skb = alloc_skb(dev->mtu + HIPPI_HLEN, GFP_ATOMIC); skb = alloc_skb(dev->mtu + HIPPI_HLEN, GFP_ATOMIC);
...@@ -740,6 +694,8 @@ static int rr_init1(struct net_device *dev) ...@@ -740,6 +694,8 @@ static int rr_init1(struct net_device *dev)
goto error; goto error;
} }
rrpriv->rx_skbuff[i] = skb; rrpriv->rx_skbuff[i] = skb;
addr = pci_map_single(rrpriv->pci_dev, skb->data,
dev->mtu + HIPPI_HLEN, PCI_DMA_FROMDEVICE);
/* /*
* Sanity test to see if we conflict with the DMA * Sanity test to see if we conflict with the DMA
* limitations of the Roadrunner. * limitations of the Roadrunner.
...@@ -747,7 +703,7 @@ static int rr_init1(struct net_device *dev) ...@@ -747,7 +703,7 @@ static int rr_init1(struct net_device *dev)
if ((((unsigned long)skb->data) & 0xfff) > ~65320) if ((((unsigned long)skb->data) & 0xfff) > ~65320)
printk("skb alloc error\n"); printk("skb alloc error\n");
set_rraddr(&rrpriv->rx_ring[i].addr, skb->data); set_rraddr(&rrpriv->rx_ring[i].addr, addr);
rrpriv->rx_ring[i].size = dev->mtu + HIPPI_HLEN; rrpriv->rx_ring[i].size = dev->mtu + HIPPI_HLEN;
} }
...@@ -756,7 +712,7 @@ static int rr_init1(struct net_device *dev) ...@@ -756,7 +712,7 @@ static int rr_init1(struct net_device *dev)
rrpriv->rx_ctrl[4].mode = 8; rrpriv->rx_ctrl[4].mode = 8;
rrpriv->rx_ctrl[4].pi = 0; rrpriv->rx_ctrl[4].pi = 0;
wmb(); wmb();
set_rraddr(&rrpriv->rx_ctrl[4].rngptr, rrpriv->rx_ring); set_rraddr(&rrpriv->rx_ctrl[4].rngptr, rrpriv->rx_ring_dma);
udelay(1000); udelay(1000);
...@@ -785,10 +741,17 @@ static int rr_init1(struct net_device *dev) ...@@ -785,10 +741,17 @@ static int rr_init1(struct net_device *dev)
* make sure we release everything we allocated before failing * make sure we release everything we allocated before failing
*/ */
for (i = 0; i < RX_RING_ENTRIES; i++) { for (i = 0; i < RX_RING_ENTRIES; i++) {
if (rrpriv->rx_skbuff[i]) { struct sk_buff *skb = rrpriv->rx_skbuff[i];
if (skb) {
pci_unmap_single(rrpriv->pci_dev,
rrpriv->rx_ring[i].addr.addrlo,
dev->mtu + HIPPI_HLEN,
PCI_DMA_FROMDEVICE);
rrpriv->rx_ring[i].size = 0; rrpriv->rx_ring[i].size = 0;
set_rraddr(&rrpriv->rx_ring[i].addr, 0); set_rraddr(&rrpriv->rx_ring[i].addr, 0);
dev_kfree_skb(rrpriv->rx_skbuff[i]); dev_kfree_skb(skb);
rrpriv->rx_skbuff[i] = 0;
} }
} }
return ecode; return ecode;
...@@ -1009,12 +972,14 @@ static void rx_int(struct net_device *dev, u32 rxlimit, u32 index) ...@@ -1009,12 +972,14 @@ static void rx_int(struct net_device *dev, u32 rxlimit, u32 index)
struct rr_regs *regs = rrpriv->regs; struct rr_regs *regs = rrpriv->regs;
do { do {
struct rx_desc *desc;
u32 pkt_len; u32 pkt_len;
pkt_len = rrpriv->rx_ring[index].size;
desc = &(rrpriv->rx_ring[index]);
pkt_len = desc->size;
#if (DEBUG > 2) #if (DEBUG > 2)
printk("index %i, rxlimit %i\n", index, rxlimit); printk("index %i, rxlimit %i\n", index, rxlimit);
printk("len %x, mode %x\n", pkt_len, printk("len %x, mode %x\n", pkt_len, desc->mode);
rrpriv->rx_ring[index].mode);
#endif #endif
if ( (rrpriv->rx_ring[index].mode & PACKET_BAD) == PACKET_BAD){ if ( (rrpriv->rx_ring[index].mode & PACKET_BAD) == PACKET_BAD){
rrpriv->stats.rx_dropped++; rrpriv->stats.rx_dropped++;
...@@ -1022,7 +987,12 @@ static void rx_int(struct net_device *dev, u32 rxlimit, u32 index) ...@@ -1022,7 +987,12 @@ static void rx_int(struct net_device *dev, u32 rxlimit, u32 index)
} }
if (pkt_len > 0){ if (pkt_len > 0){
struct sk_buff *skb; struct sk_buff *skb, *rx_skb;
rx_skb = rrpriv->rx_skbuff[index];
pci_dma_sync_single(rrpriv->pci_dev, desc->addr.addrlo,
pkt_len, PCI_DMA_FROMDEVICE);
if (pkt_len < PKT_COPY_THRESHOLD) { if (pkt_len < PKT_COPY_THRESHOLD) {
skb = alloc_skb(pkt_len, GFP_ATOMIC); skb = alloc_skb(pkt_len, GFP_ATOMIC);
...@@ -1032,19 +1002,27 @@ static void rx_int(struct net_device *dev, u32 rxlimit, u32 index) ...@@ -1032,19 +1002,27 @@ static void rx_int(struct net_device *dev, u32 rxlimit, u32 index)
goto defer; goto defer;
}else }else
memcpy(skb_put(skb, pkt_len), memcpy(skb_put(skb, pkt_len),
rrpriv->rx_skbuff[index]->data, rx_skb->data, pkt_len);
pkt_len);
}else{ }else{
struct sk_buff *newskb; struct sk_buff *newskb;
newskb = alloc_skb(dev->mtu + HIPPI_HLEN, newskb = alloc_skb(dev->mtu + HIPPI_HLEN,
GFP_ATOMIC); GFP_ATOMIC);
if (newskb){ if (newskb){
skb = rrpriv->rx_skbuff[index]; dma_addr_t addr;
pci_unmap_single(rrpriv->pci_dev,
desc->addr.addrlo, dev->mtu +
HIPPI_HLEN, PCI_DMA_FROMDEVICE);
skb = rx_skb;
skb_put(skb, pkt_len); skb_put(skb, pkt_len);
rrpriv->rx_skbuff[index] = newskb; rrpriv->rx_skbuff[index] = newskb;
set_rraddr(&rrpriv->rx_ring[index].addr, newskb->data); addr = pci_map_single(rrpriv->pci_dev,
}else{ newskb->data,
dev->mtu + HIPPI_HLEN,
PCI_DMA_FROMDEVICE);
set_rraddr(&desc->addr, addr);
} else {
printk("%s: Out of memory, deferring " printk("%s: Out of memory, deferring "
"packet\n", dev->name); "packet\n", dev->name);
rrpriv->stats.rx_dropped++; rrpriv->stats.rx_dropped++;
...@@ -1061,8 +1039,8 @@ static void rx_int(struct net_device *dev, u32 rxlimit, u32 index) ...@@ -1061,8 +1039,8 @@ static void rx_int(struct net_device *dev, u32 rxlimit, u32 index)
rrpriv->stats.rx_bytes += pkt_len; rrpriv->stats.rx_bytes += pkt_len;
} }
defer: defer:
rrpriv->rx_ring[index].mode = 0; desc->mode = 0;
rrpriv->rx_ring[index].size = dev->mtu + HIPPI_HLEN; desc->size = dev->mtu + HIPPI_HLEN;
if ((index & 7) == 7) if ((index & 7) == 7)
writel(index, &regs->IpRxPi); writel(index, &regs->IpRxPi);
...@@ -1120,14 +1098,24 @@ static void rr_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) ...@@ -1120,14 +1098,24 @@ static void rr_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
* of sync. error need to check entry in ring -kbf * of sync. error need to check entry in ring -kbf
*/ */
if(rrpriv->tx_skbuff[txcon]){ if(rrpriv->tx_skbuff[txcon]){
struct tx_desc *desc;
struct sk_buff *skb;
desc = &(rrpriv->tx_ring[txcon]);
skb = rrpriv->tx_skbuff[txcon];
rrpriv->stats.tx_packets++; rrpriv->stats.tx_packets++;
rrpriv->stats.tx_bytes +=rrpriv->tx_skbuff[txcon]->len; rrpriv->stats.tx_bytes += skb->len;
dev_kfree_skb_irq(rrpriv->tx_skbuff[txcon]);
pci_unmap_single(rrpriv->pci_dev,
desc->addr.addrlo, skb->len,
PCI_DMA_TODEVICE);
dev_kfree_skb_irq(skb);
rrpriv->tx_skbuff[txcon] = NULL; rrpriv->tx_skbuff[txcon] = NULL;
rrpriv->tx_ring[txcon].size = 0; desc->size = 0;
set_rraddr(&rrpriv->tx_ring[txcon].addr, 0); set_rraddr(&rrpriv->tx_ring[txcon].addr, 0);
rrpriv->tx_ring[txcon].mode = 0; desc->mode = 0;
} }
txcon = (txcon + 1) % TX_RING_ENTRIES; txcon = (txcon + 1) % TX_RING_ENTRIES;
} while (txcsmr != txcon); } while (txcsmr != txcon);
...@@ -1139,7 +1127,6 @@ static void rr_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) ...@@ -1139,7 +1127,6 @@ static void rr_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
!= rrpriv->dirty_tx)){ != rrpriv->dirty_tx)){
rrpriv->tx_full = 0; rrpriv->tx_full = 0;
netif_wake_queue(dev); netif_wake_queue(dev);
rr_mark_net_bh(NET_BH);
} }
} }
...@@ -1164,6 +1151,7 @@ static void rr_timer(unsigned long data) ...@@ -1164,6 +1151,7 @@ static void rr_timer(unsigned long data)
memset(rrpriv->rx_ctrl, 0, 256 * sizeof(struct ring_ctrl)); memset(rrpriv->rx_ctrl, 0, 256 * sizeof(struct ring_ctrl));
memset(rrpriv->info, 0, sizeof(struct rr_info)); memset(rrpriv->info, 0, sizeof(struct rr_info));
wmb(); wmb();
for (i = 0; i < TX_RING_ENTRIES; i++) { for (i = 0; i < TX_RING_ENTRIES; i++) {
if (rrpriv->tx_skbuff[i]) { if (rrpriv->tx_skbuff[i]) {
rrpriv->tx_ring[i].size = 0; rrpriv->tx_ring[i].size = 0;
...@@ -1181,6 +1169,7 @@ static void rr_timer(unsigned long data) ...@@ -1181,6 +1169,7 @@ static void rr_timer(unsigned long data)
rrpriv->rx_skbuff[i] = NULL; rrpriv->rx_skbuff[i] = NULL;
} }
} }
if (rr_init1(dev)) { if (rr_init1(dev)) {
spin_lock_irqsave(&rrpriv->lock, flags); spin_lock_irqsave(&rrpriv->lock, flags);
writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT, writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT,
...@@ -1195,12 +1184,13 @@ static void rr_timer(unsigned long data) ...@@ -1195,12 +1184,13 @@ static void rr_timer(unsigned long data)
static int rr_open(struct net_device *dev) static int rr_open(struct net_device *dev)
{ {
struct rr_private *rrpriv; struct rr_private *rrpriv = (struct rr_private *)dev->priv;
struct pci_dev *pdev = rrpriv->pci_dev;
struct rr_regs *regs; struct rr_regs *regs;
int ecode = 0; int ecode = 0;
unsigned long flags; unsigned long flags;
dma_addr_t dma_addr;
rrpriv = (struct rr_private *)dev->priv;
regs = rrpriv->regs; regs = rrpriv->regs;
if (rrpriv->fw_rev < 0x00020000) { if (rrpriv->fw_rev < 0x00020000) {
...@@ -1210,24 +1200,29 @@ static int rr_open(struct net_device *dev) ...@@ -1210,24 +1200,29 @@ static int rr_open(struct net_device *dev)
goto error; goto error;
} }
rrpriv->rx_ctrl = kmalloc(256*sizeof(struct ring_ctrl), GFP_KERNEL); rrpriv->rx_ctrl = pci_alloc_consistent(pdev,
256 * sizeof(struct ring_ctrl),
&dma_addr);
if (!rrpriv->rx_ctrl) { if (!rrpriv->rx_ctrl) {
ecode = -ENOMEM; ecode = -ENOMEM;
goto error; goto error;
} }
rrpriv->rx_ctrl_dma = dma_addr;
memset(rrpriv->rx_ctrl, 0, 256*sizeof(struct ring_ctrl));
rrpriv->info = kmalloc(sizeof(struct rr_info), GFP_KERNEL); rrpriv->info = pci_alloc_consistent(pdev, sizeof(struct rr_info),
if (!rrpriv->info){ &dma_addr);
rrpriv->rx_ctrl = NULL; if (!rrpriv->info) {
ecode = -ENOMEM; ecode = -ENOMEM;
goto error; goto error;
} }
memset(rrpriv->rx_ctrl, 0, 256 * sizeof(struct ring_ctrl)); rrpriv->info_dma = dma_addr;
memset(rrpriv->info, 0, sizeof(struct rr_info)); memset(rrpriv->info, 0, sizeof(struct rr_info));
wmb(); wmb();
spin_lock_irqsave(&rrpriv->lock, flags); spin_lock_irqsave(&rrpriv->lock, flags);
writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT, &regs->HostCtrl); writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT, &regs->HostCtrl);
readl(&regs->HostCtrl);
spin_unlock_irqrestore(&rrpriv->lock, flags); spin_unlock_irqrestore(&rrpriv->lock, flags);
if (request_irq(dev->irq, rr_interrupt, SA_SHIRQ, rrpriv->name, dev)) if (request_irq(dev->irq, rr_interrupt, SA_SHIRQ, rrpriv->name, dev))
...@@ -1251,6 +1246,7 @@ static int rr_open(struct net_device *dev) ...@@ -1251,6 +1246,7 @@ static int rr_open(struct net_device *dev)
netif_start_queue(dev); netif_start_queue(dev);
MOD_INC_USE_COUNT;
return ecode; return ecode;
error: error:
...@@ -1268,12 +1264,54 @@ static int rr_open(struct net_device *dev) ...@@ -1268,12 +1264,54 @@ static int rr_open(struct net_device *dev)
} }
netif_stop_queue(dev); netif_stop_queue(dev);
rr_if_down(dev);
return ecode; return ecode;
} }
static inline void rr_raz_tx(struct rr_private *rrpriv,
struct net_device *dev)
{
int i;
for (i = 0; i < TX_RING_ENTRIES; i++) {
struct sk_buff *skb = rrpriv->tx_skbuff[i];
if (skb) {
struct tx_desc *desc = &(rrpriv->tx_ring[i]);
pci_unmap_single(rrpriv->pci_dev, desc->addr.addrlo,
skb->len, PCI_DMA_TODEVICE);
desc->size = 0;
set_rraddr(&desc->addr, 0);
dev_kfree_skb(skb);
rrpriv->tx_skbuff[i] = NULL;
}
}
}
static inline void rr_raz_rx(struct rr_private *rrpriv,
struct net_device *dev)
{
int i;
for (i = 0; i < RX_RING_ENTRIES; i++) {
struct sk_buff *skb = rrpriv->rx_skbuff[i];
if (skb) {
struct rx_desc *desc = &(rrpriv->rx_ring[i]);
pci_unmap_single(rrpriv->pci_dev, desc->addr.addrlo,
dev->mtu + HIPPI_HLEN, PCI_DMA_FROMDEVICE);
desc->size = 0;
set_rraddr(&desc->addr, 0);
dev_kfree_skb(skb);
rrpriv->rx_skbuff[i] = NULL;
}
}
}
static void rr_dump(struct net_device *dev) static void rr_dump(struct net_device *dev)
{ {
struct rr_private *rrpriv; struct rr_private *rrpriv;
...@@ -1313,11 +1351,10 @@ static void rr_dump(struct net_device *dev) ...@@ -1313,11 +1351,10 @@ static void rr_dump(struct net_device *dev)
if (rrpriv->tx_skbuff[cons]){ if (rrpriv->tx_skbuff[cons]){
len = min_t(int, 0x80, rrpriv->tx_skbuff[cons]->len); len = min_t(int, 0x80, rrpriv->tx_skbuff[cons]->len);
printk("skbuff for cons %i is valid - dumping data (0x%x bytes - skbuff len 0x%x)\n", cons, len, rrpriv->tx_skbuff[cons]->len); printk("skbuff for cons %i is valid - dumping data (0x%x bytes - skbuff len 0x%x)\n", cons, len, rrpriv->tx_skbuff[cons]->len);
printk("mode 0x%x, size 0x%x,\n phys %08x (virt %08lx), skbuff-addr %08lx, truesize 0x%x\n", printk("mode 0x%x, size 0x%x,\n phys %08x, skbuff-addr %08lx, truesize 0x%x\n",
rrpriv->tx_ring[cons].mode, rrpriv->tx_ring[cons].mode,
rrpriv->tx_ring[cons].size, rrpriv->tx_ring[cons].size,
rrpriv->tx_ring[cons].addr.addrlo, rrpriv->tx_ring[cons].addr.addrlo,
(unsigned long)bus_to_virt(rrpriv->tx_ring[cons].addr.addrlo),
(unsigned long)rrpriv->tx_skbuff[cons]->data, (unsigned long)rrpriv->tx_skbuff[cons]->data,
(unsigned int)rrpriv->tx_skbuff[cons]->truesize); (unsigned int)rrpriv->tx_skbuff[cons]->truesize);
for (i = 0; i < len; i++){ for (i = 0; i < len; i++){
...@@ -1342,20 +1379,20 @@ static int rr_close(struct net_device *dev) ...@@ -1342,20 +1379,20 @@ static int rr_close(struct net_device *dev)
{ {
struct rr_private *rrpriv; struct rr_private *rrpriv;
struct rr_regs *regs; struct rr_regs *regs;
unsigned long flags;
u32 tmp; u32 tmp;
short i; short i;
netif_stop_queue(dev); netif_stop_queue(dev);
rr_if_down(dev);
rrpriv = (struct rr_private *)dev->priv; rrpriv = (struct rr_private *)dev->priv;
regs = rrpriv->regs; regs = rrpriv->regs;
/* /*
* Lock to make sure we are not cleaning up while another CPU * Lock to make sure we are not cleaning up while another CPU
* handling interrupts. * is handling interrupts.
*/ */
spin_lock(&rrpriv->lock); spin_lock_irqsave(&rrpriv->lock, flags);
tmp = readl(&regs->HostCtrl); tmp = readl(&regs->HostCtrl);
if (tmp & NIC_HALTED){ if (tmp & NIC_HALTED){
...@@ -1364,12 +1401,12 @@ static int rr_close(struct net_device *dev) ...@@ -1364,12 +1401,12 @@ static int rr_close(struct net_device *dev)
}else{ }else{
tmp |= HALT_NIC | RR_CLEAR_INT; tmp |= HALT_NIC | RR_CLEAR_INT;
writel(tmp, &regs->HostCtrl); writel(tmp, &regs->HostCtrl);
wmb(); readl(&regs->HostCtrl);
} }
rrpriv->fw_running = 0; rrpriv->fw_running = 0;
del_timer(&rrpriv->timer); del_timer_sync(&rrpriv->timer);
writel(0, &regs->TxPi); writel(0, &regs->TxPi);
writel(0, &regs->IpRxPi); writel(0, &regs->IpRxPi);
...@@ -1403,18 +1440,18 @@ static int rr_close(struct net_device *dev) ...@@ -1403,18 +1440,18 @@ static int rr_close(struct net_device *dev)
} }
} }
if (rrpriv->rx_ctrl) { pci_free_consistent(rrpriv->pci_dev, 256 * sizeof(struct ring_ctrl),
kfree(rrpriv->rx_ctrl); rrpriv->rx_ctrl, rrpriv->rx_ctrl_dma);
rrpriv->rx_ctrl = NULL; rrpriv->rx_ctrl = NULL;
}
if (rrpriv->info) { pci_free_consistent(rrpriv->pci_dev, sizeof(struct rr_info),
kfree(rrpriv->info); rrpriv->info, rrpriv->info_dma);
rrpriv->info = NULL; rrpriv->info = NULL;
}
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
spin_unlock(&rrpriv->lock); spin_unlock_irqrestore(&rrpriv->lock, flags);
MOD_DEC_USE_COUNT;
return 0; return 0;
} }
...@@ -1467,7 +1504,8 @@ static int rr_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1467,7 +1504,8 @@ static int rr_start_xmit(struct sk_buff *skb, struct net_device *dev)
index = txctrl->pi; index = txctrl->pi;
rrpriv->tx_skbuff[index] = skb; rrpriv->tx_skbuff[index] = skb;
set_rraddr(&rrpriv->tx_ring[index].addr, skb->data); set_rraddr(&rrpriv->tx_ring[index].addr, pci_map_single(
rrpriv->pci_dev, skb->data, len + 8, PCI_DMA_TODEVICE));
rrpriv->tx_ring[index].size = len + 8; /* include IFIELD */ rrpriv->tx_ring[index].size = len + 8; /* include IFIELD */
rrpriv->tx_ring[index].mode = PACKET_START | PACKET_END; rrpriv->tx_ring[index].mode = PACKET_START | PACKET_END;
txctrl->pi = (index + 1) % TX_RING_ENTRIES; txctrl->pi = (index + 1) % TX_RING_ENTRIES;
...@@ -1612,6 +1650,7 @@ static int rr_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -1612,6 +1650,7 @@ static int rr_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{ {
struct rr_private *rrpriv; struct rr_private *rrpriv;
unsigned char *image, *oldimage; unsigned char *image, *oldimage;
unsigned long flags;
unsigned int i; unsigned int i;
int error = -EOPNOTSUPP; int error = -EOPNOTSUPP;
...@@ -1629,25 +1668,27 @@ static int rr_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -1629,25 +1668,27 @@ static int rr_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
"for EEPROM image\n", dev->name); "for EEPROM image\n", dev->name);
return -ENOMEM; return -ENOMEM;
} }
spin_lock(&rrpriv->lock);
if (rrpriv->fw_running){ if (rrpriv->fw_running){
printk("%s: Firmware already running\n", dev->name); printk("%s: Firmware already running\n", dev->name);
error = -EPERM; error = -EPERM;
goto out_spin; goto gf_out;
} }
spin_lock_irqsave(&rrpriv->lock, flags);
i = rr_read_eeprom(rrpriv, 0, image, EEPROM_BYTES); i = rr_read_eeprom(rrpriv, 0, image, EEPROM_BYTES);
if (i != EEPROM_BYTES){ if (i != EEPROM_BYTES){
printk(KERN_ERR "%s: Error reading EEPROM\n", dev->name); printk(KERN_ERR "%s: Error reading EEPROM\n",
dev->name);
error = -EFAULT; error = -EFAULT;
goto out_spin; goto gf_out;
} }
spin_unlock(&rrpriv->lock); spin_unlock_irqrestore(&rrpriv->lock, flags);
error = copy_to_user(rq->ifr_data, image, EEPROM_BYTES); error = copy_to_user(rq->ifr_data, image, EEPROM_BYTES);
if (error) if (error)
error = -EFAULT; error = -EFAULT;
gf_out:
kfree(image); kfree(image);
return error; return error;
...@@ -1657,56 +1698,52 @@ static int rr_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -1657,56 +1698,52 @@ static int rr_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
} }
image = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL); image = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL);
if (!image){
printk(KERN_ERR "%s: Unable to allocate memory "
"for EEPROM image\n", dev->name);
return -ENOMEM;
}
oldimage = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL); oldimage = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL);
if (!oldimage){ if (!image || !oldimage) {
kfree(image);
printk(KERN_ERR "%s: Unable to allocate memory " printk(KERN_ERR "%s: Unable to allocate memory "
"for old EEPROM image\n", dev->name); "for EEPROM image\n", dev->name);
return -ENOMEM; error = -ENOMEM;
goto wf_out;
} }
error = copy_from_user(image, rq->ifr_data, EEPROM_BYTES); error = copy_from_user(image, rq->ifr_data, EEPROM_BYTES);
if (error) { if (error) {
kfree(image); error = -EFAULT;
kfree(oldimage); goto wf_out;
return -EFAULT;
} }
spin_lock(&rrpriv->lock);
if (rrpriv->fw_running){ if (rrpriv->fw_running){
kfree(oldimage);
printk("%s: Firmware already running\n", dev->name); printk("%s: Firmware already running\n", dev->name);
error = -EPERM; error = -EPERM;
goto out_spin; goto wf_out;
} }
printk("%s: Updating EEPROM firmware\n", dev->name); printk("%s: Updating EEPROM firmware\n", dev->name);
spin_lock_irqsave(&rrpriv->lock, flags);
error = write_eeprom(rrpriv, 0, image, EEPROM_BYTES); error = write_eeprom(rrpriv, 0, image, EEPROM_BYTES);
if (error) if (error)
printk(KERN_ERR "%s: Error writing EEPROM\n", printk(KERN_ERR "%s: Error writing EEPROM\n",
dev->name); dev->name);
i = rr_read_eeprom(rrpriv, 0, oldimage, EEPROM_BYTES); i = rr_read_eeprom(rrpriv, 0, oldimage, EEPROM_BYTES);
spin_unlock_irqrestore(&rrpriv->lock, flags);
if (i != EEPROM_BYTES) if (i != EEPROM_BYTES)
printk(KERN_ERR "%s: Error reading back EEPROM " printk(KERN_ERR "%s: Error reading back EEPROM "
"image\n", dev->name); "image\n", dev->name);
spin_unlock(&rrpriv->lock);
error = memcmp(image, oldimage, EEPROM_BYTES); error = memcmp(image, oldimage, EEPROM_BYTES);
if (error){ if (error){
printk(KERN_ERR "%s: Error verifying EEPROM image\n", printk(KERN_ERR "%s: Error verifying EEPROM image\n",
dev->name); dev->name);
error = -EFAULT; error = -EFAULT;
} }
kfree(image); wf_out:
kfree(oldimage); if (oldimage)
kfree(oldimage);
if (image)
kfree(image);
return error; return error;
case SIOCRRID: case SIOCRRID:
...@@ -1714,13 +1751,34 @@ static int rr_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -1714,13 +1751,34 @@ static int rr_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
default: default:
return error; return error;
} }
}
out_spin: static struct pci_device_id rr_pci_tbl[] __devinitdata = {
kfree(image); { PCI_VENDOR_ID_ESSENTIAL, PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER,
spin_unlock(&rrpriv->lock); PCI_ANY_ID, PCI_ANY_ID, },
return error; { 0,}
};
MODULE_DEVICE_TABLE(pci, rr_pci_tbl);
static struct pci_driver rr_driver = {
name: "rrunner",
id_table: rr_pci_tbl,
probe: rr_init_one,
remove: rr_remove_one,
};
static int __init rr_init_module(void)
{
return pci_module_init(&rr_driver);
}
static void __exit rr_cleanup_module(void)
{
pci_unregister_driver(&rr_driver);
} }
module_init(rr_init_module);
module_exit(rr_cleanup_module);
/* /*
* Local variables: * Local variables:
......
...@@ -351,7 +351,7 @@ struct rr_regs { ...@@ -351,7 +351,7 @@ struct rr_regs {
*/ */
#define EVT_RING_ENTRIES 64 #define EVT_RING_ENTRIES 64
#define EVT_RING_SIZE (EVT_RING_ENTRIES * sizeof(struct event)) #define EVT_RING_SIZE (EVT_RING_ENTRIES * sizeof(struct event))
struct event { struct event {
#ifdef __LITTLE_ENDIAN #ifdef __LITTLE_ENDIAN
...@@ -496,9 +496,9 @@ typedef struct { ...@@ -496,9 +496,9 @@ typedef struct {
} rraddr; } rraddr;
static inline void set_rraddr(rraddr *ra, volatile void *addr) static inline void set_rraddr(rraddr *ra, dma_addr_t addr)
{ {
unsigned long baddr = virt_to_bus((void *)addr); unsigned long baddr = addr;
#if (BITS_PER_LONG == 64) #if (BITS_PER_LONG == 64)
ra->addrlo = baddr; ra->addrlo = baddr;
#else #else
...@@ -509,9 +509,9 @@ static inline void set_rraddr(rraddr *ra, volatile void *addr) ...@@ -509,9 +509,9 @@ static inline void set_rraddr(rraddr *ra, volatile void *addr)
} }
static inline void set_rxaddr(struct rr_regs *regs, volatile void *addr) static inline void set_rxaddr(struct rr_regs *regs, volatile dma_addr_t addr)
{ {
unsigned long baddr = virt_to_bus((void *)addr); unsigned long baddr = addr;
#if (BITS_PER_LONG == 64) && defined(__LITTLE_ENDIAN) #if (BITS_PER_LONG == 64) && defined(__LITTLE_ENDIAN)
writel(baddr & 0xffffffff, &regs->RxRingHi); writel(baddr & 0xffffffff, &regs->RxRingHi);
writel(baddr >> 32, &regs->RxRingLo); writel(baddr >> 32, &regs->RxRingLo);
...@@ -526,9 +526,9 @@ static inline void set_rxaddr(struct rr_regs *regs, volatile void *addr) ...@@ -526,9 +526,9 @@ static inline void set_rxaddr(struct rr_regs *regs, volatile void *addr)
} }
static inline void set_infoaddr(struct rr_regs *regs, volatile void *addr) static inline void set_infoaddr(struct rr_regs *regs, volatile dma_addr_t addr)
{ {
unsigned long baddr = virt_to_bus((void *)addr); unsigned long baddr = addr;
#if (BITS_PER_LONG == 64) && defined(__LITTLE_ENDIAN) #if (BITS_PER_LONG == 64) && defined(__LITTLE_ENDIAN)
writel(baddr & 0xffffffff, &regs->InfoPtrHi); writel(baddr & 0xffffffff, &regs->InfoPtrHi);
writel(baddr >> 32, &regs->InfoPtrLo); writel(baddr >> 32, &regs->InfoPtrLo);
...@@ -552,7 +552,7 @@ static inline void set_infoaddr(struct rr_regs *regs, volatile void *addr) ...@@ -552,7 +552,7 @@ static inline void set_infoaddr(struct rr_regs *regs, volatile void *addr)
#else #else
#define TX_RING_ENTRIES 16 #define TX_RING_ENTRIES 16
#endif #endif
#define TX_RING_SIZE (TX_RING_ENTRIES * sizeof(struct tx_desc)) #define TX_TOTAL_SIZE (TX_RING_ENTRIES * sizeof(struct tx_desc))
struct tx_desc{ struct tx_desc{
rraddr addr; rraddr addr;
...@@ -574,7 +574,7 @@ struct tx_desc{ ...@@ -574,7 +574,7 @@ struct tx_desc{
#else #else
#define RX_RING_ENTRIES 16 #define RX_RING_ENTRIES 16
#endif #endif
#define RX_RING_SIZE (RX_RING_ENTRIES * sizeof(struct rx_desc)) #define RX_TOTAL_SIZE (RX_RING_ENTRIES * sizeof(struct rx_desc))
struct rx_desc{ struct rx_desc{
rraddr addr; rraddr addr;
...@@ -798,24 +798,30 @@ struct rr_info { ...@@ -798,24 +798,30 @@ struct rr_info {
struct rr_private struct rr_private
{ {
struct rx_desc rx_ring[RX_RING_ENTRIES]; struct rx_desc *rx_ring;
struct tx_desc tx_ring[TX_RING_ENTRIES]; struct tx_desc *tx_ring;
struct event evt_ring[EVT_RING_ENTRIES]; struct event *evt_ring;
dma_addr_t tx_ring_dma;
dma_addr_t rx_ring_dma;
dma_addr_t evt_ring_dma;
/* Alignment ok ? */
struct sk_buff *rx_skbuff[RX_RING_ENTRIES]; struct sk_buff *rx_skbuff[RX_RING_ENTRIES];
struct sk_buff *tx_skbuff[TX_RING_ENTRIES]; struct sk_buff *tx_skbuff[TX_RING_ENTRIES];
struct rr_regs *regs; /* Register base */ struct rr_regs *regs; /* Register base */
struct ring_ctrl *rx_ctrl; /* Receive ring control */ struct ring_ctrl *rx_ctrl; /* Receive ring control */
struct rr_info *info; /* Shared info page */ struct rr_info *info; /* Shared info page */
struct net_device *next; dma_addr_t rx_ctrl_dma;
dma_addr_t info_dma;
spinlock_t lock; spinlock_t lock;
struct timer_list timer; struct timer_list timer;
u32 cur_rx, cur_cmd, cur_evt; u32 cur_rx, cur_cmd, cur_evt;
u32 dirty_rx, dirty_tx; u32 dirty_rx, dirty_tx;
u32 tx_full; u32 tx_full;
u32 fw_rev; u32 fw_rev;
short fw_running; volatile short fw_running;
char name[24]; /* The assigned name */ char name[24]; /* The assigned name */
struct net_device_stats stats; struct net_device_stats stats;
struct pci_dev *pci_dev;
}; };
...@@ -837,5 +843,6 @@ static unsigned int rr_read_eeprom(struct rr_private *rrpriv, ...@@ -837,5 +843,6 @@ static unsigned int rr_read_eeprom(struct rr_private *rrpriv,
unsigned long length); unsigned long length);
static u32 rr_read_eeprom_word(struct rr_private *rrpriv, void * offset); static u32 rr_read_eeprom_word(struct rr_private *rrpriv, void * offset);
static int rr_load_firmware(struct net_device *dev); static int rr_load_firmware(struct net_device *dev);
static inline void rr_raz_tx(struct rr_private *, struct net_device *);
static inline void rr_raz_rx(struct rr_private *, struct net_device *);
#endif /* _RRUNNER_H_ */ #endif /* _RRUNNER_H_ */
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