Commit 84ce7c18 authored by Benjamin LaHaise's avatar Benjamin LaHaise

[PATCH] ns83820.c update to 0.18

This patch fixes a highmem issue with ns83820.c when used with the
pci dma fix for x86.  The patch was successfully tested on a highmem
machine with 5GB of ram and a file in high memory.  Cruft from the
pre-64 bit pci dma era is also removed.
parent 726f11b1
#define _VERSION "0.17" #define _VERSION "0.18"
/* ns83820.c by Benjamin LaHaise <bcrl@redhat.com> with contributions. /* ns83820.c by Benjamin LaHaise with contributions.
* *
* $Revision: 1.34.2.14 $ * Questions/comments/discussion to linux-ns83820@kvack.org.
*
* $Revision: 1.34.2.16 $
* *
* Copyright 2001 Benjamin LaHaise. * Copyright 2001 Benjamin LaHaise.
* Copyright 2001 Red Hat. * Copyright 2001, 2002 Red Hat.
* *
* Mmmm, chocolate vanilla mocha... * Mmmm, chocolate vanilla mocha...
* *
...@@ -49,10 +51,12 @@ ...@@ -49,10 +51,12 @@
* by Michael Clark <michael@metaparadigm.com> * by Michael Clark <michael@metaparadigm.com>
* 20011205 0.13b - call register_netdev earlier in initialization * 20011205 0.13b - call register_netdev earlier in initialization
* suppress duplicate link status messages * suppress duplicate link status messages
* 20011117 0.14 - ethtool GDRVINFO, GLINK support * 20011117 0.14 - ethtool GDRVINFO, GLINK support from jgarzik
* 20011204 0.15 get ppc (big endian) working * 20011204 0.15 get ppc (big endian) working
* 20011218 0.16 various cleanups * 20011218 0.16 various cleanups
* 20020310 0.17 speedups * 20020310 0.17 speedups
* 20020610 0.18 - actually use the pci dma api for highmem
* - remove pci latency register fiddling
* *
* Driver Overview * Driver Overview
* =============== * ===============
...@@ -105,54 +109,16 @@ ...@@ -105,54 +109,16 @@
#undef Dprintk #undef Dprintk
#define Dprintk dprintk #define Dprintk dprintk
#ifdef CONFIG_HIGHMEM64G #if defined(CONFIG_HIGHMEM64G) || defined(__ia64__)
#define USE_64BIT_ADDR "+"
#elif defined(__ia64__)
#define USE_64BIT_ADDR "+" #define USE_64BIT_ADDR "+"
#endif #endif
/* Tell davem to fix the pci dma api. Grrr. */
/* stolen from acenic.c */
#if 0 //def CONFIG_HIGHMEM
#if defined(CONFIG_X86)
#define DMAADDR_OFFSET 0
#if defined(CONFIG_HIGHMEM64G)
typedef u64 dmaaddr_high_t;
#else
typedef u32 dmaaddr_high_t;
#endif
#elif defined(CONFIG_PPC)
#define DMAADDR_OFFSET PCI_DRAM_OFFSET
typedef unsigned long dmaaddr_high_t;
#endif
static inline dmaaddr_high_t
pci_map_single_high(struct pci_dev *hwdev, struct page *page,
int offset, size_t size, int dir)
{
u64 phys;
phys = page - mem_map;
phys <<= PAGE_SHIFT;
phys += offset;
phys += DMAADDR_OFFSET;
return phys;
}
#else
typedef unsigned long dmaaddr_high_t;
static inline dmaaddr_high_t
pci_map_single_high(struct pci_dev *hwdev, struct page *page,
int offset, size_t size, int dir)
{
return pci_map_single(hwdev, page_address(page) + offset, size, dir);
}
#endif
#if defined(USE_64BIT_ADDR) #if defined(USE_64BIT_ADDR)
#define VERSION _VERSION USE_64BIT_ADDR #define VERSION _VERSION USE_64BIT_ADDR
#define TRY_DAC 1
#else #else
#define VERSION _VERSION #define VERSION _VERSION
#define TRY_DAC 0
#endif #endif
/* tunables */ /* tunables */
...@@ -384,13 +350,22 @@ pci_map_single_high(struct pci_dev *hwdev, struct page *page, ...@@ -384,13 +350,22 @@ pci_map_single_high(struct pci_dev *hwdev, struct page *page,
} while(0) } while(0)
#ifdef USE_64BIT_ADDR #ifdef USE_64BIT_ADDR
typedef u64 hw_addr_t; #define HW_ADDR_LEN 8
#define desc_addr_set(desc, addr) \
do { \
u64 __addr = (addr); \
desc[BUFPTR] = cpu_to_le32(__addr); \
desc[BUFPTR+1] = cpu_to_le32(__addr >> 32); \
} while(0)
#define desc_addr_get(desc) \
(((u64)le32_to_cpu(desc[BUFPTR+1]) << 32) \
| le32_to_cpu(desc[BUFPTR]))
#else #else
typedef u32 hw_addr_t; #define HW_ADDR_LEN 4
#define desc_addr_set(desc, addr) (desc[BUFPTR] = cpu_to_le32(addr))
#define desc_addr_get(desc) (le32_to_cpu(desc[BUFPTR]))
#endif #endif
#define HW_ADDR_LEN (sizeof(hw_addr_t))
#define LINK 0 #define LINK 0
#define BUFPTR (LINK + HW_ADDR_LEN/4) #define BUFPTR (LINK + HW_ADDR_LEN/4)
#define CMDSTS (BUFPTR + HW_ADDR_LEN/4) #define CMDSTS (BUFPTR + HW_ADDR_LEN/4)
...@@ -402,6 +377,7 @@ typedef u32 hw_addr_t; ...@@ -402,6 +377,7 @@ typedef u32 hw_addr_t;
#define CMDSTS_INTR 0x20000000 #define CMDSTS_INTR 0x20000000
#define CMDSTS_ERR 0x10000000 #define CMDSTS_ERR 0x10000000
#define CMDSTS_OK 0x08000000 #define CMDSTS_OK 0x08000000
#define CMDSTS_LEN_MASK 0x0000ffff
#define CMDSTS_DEST_MASK 0x01800000 #define CMDSTS_DEST_MASK 0x01800000
#define CMDSTS_DEST_SELF 0x00800000 #define CMDSTS_DEST_SELF 0x00800000
...@@ -515,7 +491,7 @@ static inline int ns83820_add_rx_skb(struct ns83820 *dev, struct sk_buff *skb) ...@@ -515,7 +491,7 @@ static inline int ns83820_add_rx_skb(struct ns83820 *dev, struct sk_buff *skb)
unsigned next_empty; unsigned next_empty;
u32 cmdsts; u32 cmdsts;
u32 *sg; u32 *sg;
hw_addr_t buf; dma_addr_t buf;
next_empty = dev->rx_info.next_empty; next_empty = dev->rx_info.next_empty;
...@@ -848,7 +824,7 @@ static void rx_irq(struct ns83820 *dev) ...@@ -848,7 +824,7 @@ static void rx_irq(struct ns83820 *dev)
(cmdsts != CMDSTS_OWN)) { (cmdsts != CMDSTS_OWN)) {
struct sk_buff *skb; struct sk_buff *skb;
u32 extsts = le32_to_cpu(desc[EXTSTS]); u32 extsts = le32_to_cpu(desc[EXTSTS]);
dmaaddr_high_t bufptr = le32_to_cpu(desc[BUFPTR]); dma_addr_t bufptr = desc_addr_get(desc);
dprintk("cmdsts: %08x\n", cmdsts); dprintk("cmdsts: %08x\n", cmdsts);
dprintk("link: %08x\n", cpu_to_le32(desc[LINK])); dprintk("link: %08x\n", cpu_to_le32(desc[LINK]));
...@@ -936,6 +912,8 @@ static void do_tx_done(struct ns83820 *dev) ...@@ -936,6 +912,8 @@ static void do_tx_done(struct ns83820 *dev)
while ((tx_done_idx != dev->tx_free_idx) && while ((tx_done_idx != dev->tx_free_idx) &&
!(CMDSTS_OWN & (cmdsts = le32_to_cpu(desc[CMDSTS]))) ) { !(CMDSTS_OWN & (cmdsts = le32_to_cpu(desc[CMDSTS]))) ) {
struct sk_buff *skb; struct sk_buff *skb;
unsigned len;
dma_addr_t addr;
if (cmdsts & CMDSTS_ERR) if (cmdsts & CMDSTS_ERR)
dev->stats.tx_errors ++; dev->stats.tx_errors ++;
...@@ -949,13 +927,20 @@ static void do_tx_done(struct ns83820 *dev) ...@@ -949,13 +927,20 @@ static void do_tx_done(struct ns83820 *dev)
skb = dev->tx_skbs[tx_done_idx]; skb = dev->tx_skbs[tx_done_idx];
dev->tx_skbs[tx_done_idx] = NULL; dev->tx_skbs[tx_done_idx] = NULL;
dprintk("done(%p)\n", skb); dprintk("done(%p)\n", skb);
len = cmdsts & CMDSTS_LEN_MASK;
addr = desc_addr_get(desc);
if (skb) { if (skb) {
pci_unmap_single(dev->pci_dev, pci_unmap_single(dev->pci_dev,
le32_to_cpu(desc[BUFPTR]), addr,
skb->len, len,
PCI_DMA_TODEVICE); PCI_DMA_TODEVICE);
dev_kfree_skb_irq(skb); dev_kfree_skb_irq(skb);
} } else
pci_unmap_page(dev->pci_dev,
addr,
len,
PCI_DMA_TODEVICE);
tx_done_idx = (tx_done_idx + 1) % NR_TX_DESC; tx_done_idx = (tx_done_idx + 1) % NR_TX_DESC;
dev->tx_done_idx = tx_done_idx; dev->tx_done_idx = tx_done_idx;
...@@ -1001,7 +986,7 @@ static int ns83820_hard_start_xmit(struct sk_buff *skb, struct net_device *_dev) ...@@ -1001,7 +986,7 @@ static int ns83820_hard_start_xmit(struct sk_buff *skb, struct net_device *_dev)
u32 free_idx, cmdsts, extsts; u32 free_idx, cmdsts, extsts;
int nr_free, nr_frags; int nr_free, nr_frags;
unsigned tx_done_idx; unsigned tx_done_idx;
dmaaddr_high_t buf; dma_addr_t buf;
unsigned len; unsigned len;
skb_frag_t *frag; skb_frag_t *frag;
int stopped = 0; int stopped = 0;
...@@ -1075,7 +1060,7 @@ static int ns83820_hard_start_xmit(struct sk_buff *skb, struct net_device *_dev) ...@@ -1075,7 +1060,7 @@ static int ns83820_hard_start_xmit(struct sk_buff *skb, struct net_device *_dev)
(unsigned long long)buf); (unsigned long long)buf);
free_idx = (free_idx + 1) % NR_TX_DESC; free_idx = (free_idx + 1) % NR_TX_DESC;
desc[LINK] = cpu_to_le32(dev->tx_phy_descs + (free_idx * DESC_SIZE * 4)); desc[LINK] = cpu_to_le32(dev->tx_phy_descs + (free_idx * DESC_SIZE * 4));
desc[BUFPTR] = cpu_to_le32(buf); desc_addr_set(desc, buf);
desc[EXTSTS] = cpu_to_le32(extsts); desc[EXTSTS] = cpu_to_le32(extsts);
cmdsts = ((nr_frags|residue) ? CMDSTS_MORE : do_intr ? CMDSTS_INTR : 0); cmdsts = ((nr_frags|residue) ? CMDSTS_MORE : do_intr ? CMDSTS_INTR : 0);
...@@ -1092,11 +1077,12 @@ static int ns83820_hard_start_xmit(struct sk_buff *skb, struct net_device *_dev) ...@@ -1092,11 +1077,12 @@ static int ns83820_hard_start_xmit(struct sk_buff *skb, struct net_device *_dev)
if (!nr_frags) if (!nr_frags)
break; break;
buf = pci_map_single_high(dev->pci_dev, frag->page, buf = pci_map_page(dev->pci_dev, frag->page,
frag->page_offset, frag->page_offset,
frag->size, PCI_DMA_TODEVICE); frag->size, PCI_DMA_TODEVICE);
dprintk("frag: buf=%08Lx page=%08lx\n", dprintk("frag: buf=%08Lx page=%08lx offset=%08lx\n",
(long long)buf, (long)(frag->page - mem_map)); (long long)buf, (long)(frag->page - mem_map),
frag->page_offset);
len = frag->size; len = frag->size;
frag++; frag++;
nr_frags--; nr_frags--;
...@@ -1427,6 +1413,16 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ ...@@ -1427,6 +1413,16 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_
struct ns83820 *dev; struct ns83820 *dev;
long addr; long addr;
int err; int err;
int using_dac = 0;
if (TRY_DAC && !pci_set_dma_mask(pci_dev, 0xffffffffffffffff)) {
using_dac = 1;
} else if (!pci_set_dma_mask(pci_dev, 0xffffffff)) {
using_dac = 0;
} else {
printk(KERN_WARNING "ns83820.c: pci_set_dma_mask failed!\n");
return -ENODEV;
}
dev = (struct ns83820 *)alloc_etherdev((sizeof *dev) - (sizeof dev->net_dev)); dev = (struct ns83820 *)alloc_etherdev((sizeof *dev) - (sizeof dev->net_dev));
err = -ENOMEM; err = -ENOMEM;
...@@ -1536,6 +1532,9 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ ...@@ -1536,6 +1532,9 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_
#ifdef USE_64BIT_ADDR #ifdef USE_64BIT_ADDR
dev->CFG_cache |= CFG_M64ADDR; dev->CFG_cache |= CFG_M64ADDR;
#endif #endif
if (using_dac)
dev->CFG_cache |= CFG_T64ADDR;
/* Big endian mode does not seem to do what the docs suggest */ /* Big endian mode does not seem to do what the docs suggest */
dev->CFG_cache &= ~CFG_BEM; dev->CFG_cache &= ~CFG_BEM;
...@@ -1561,7 +1560,7 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ ...@@ -1561,7 +1560,7 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_
writel(dev->CFG_cache, dev->base + CFG); writel(dev->CFG_cache, dev->base + CFG);
dprintk("CFG: %08x\n", dev->CFG_cache); dprintk("CFG: %08x\n", dev->CFG_cache);
#if 1 /* Huh? This sets the PCI latency register. Should be done via #if 0 /* Huh? This sets the PCI latency register. Should be done via
* the PCI layer. FIXME. * the PCI layer. FIXME.
*/ */
if (readl(dev->base + SRR)) if (readl(dev->base + SRR))
...@@ -1614,13 +1613,12 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ ...@@ -1614,13 +1613,12 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_
/* Yes, we support dumb IP checksum on transmit */ /* Yes, we support dumb IP checksum on transmit */
dev->net_dev.features |= NETIF_F_SG; dev->net_dev.features |= NETIF_F_SG;
dev->net_dev.features |= NETIF_F_IP_CSUM; dev->net_dev.features |= NETIF_F_IP_CSUM;
#if defined(USE_64BIT_ADDR) || defined(CONFIG_HIGHMEM4G)
if ((dev->CFG_cache & CFG_T64ADDR)) { if (using_dac) {
printk(KERN_INFO "%s: using 64 bit addressing.\n", printk(KERN_INFO "%s: using 64 bit addressing.\n",
dev->net_dev.name); dev->net_dev.name);
dev->net_dev.features |= NETIF_F_HIGHDMA; dev->net_dev.features |= NETIF_F_HIGHDMA;
} }
#endif
printk(KERN_INFO "%s: ns83820 v" VERSION ": DP83820 v%u.%u: %02x:%02x:%02x:%02x:%02x:%02x io=0x%08lx irq=%d f=%s\n", printk(KERN_INFO "%s: ns83820 v" VERSION ": DP83820 v%u.%u: %02x:%02x:%02x:%02x:%02x:%02x io=0x%08lx irq=%d f=%s\n",
dev->net_dev.name, dev->net_dev.name,
......
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