Commit 38171d07 authored by Jes Sorensen's avatar Jes Sorensen Committed by Jeff Garzik

acenic gige net driver fixes:

* fix Tigon I support
* fix memory leak
parent 6f005af3
...@@ -84,8 +84,10 @@ ...@@ -84,8 +84,10 @@
#ifdef CONFIG_ACENIC_OMIT_TIGON_I #ifdef CONFIG_ACENIC_OMIT_TIGON_I
#define ACE_IS_TIGON_I(ap) 0 #define ACE_IS_TIGON_I(ap) 0
#define ACE_TX_RING_ENTRIES(ap) MAX_TX_RING_ENTRIES
#else #else
#define ACE_IS_TIGON_I(ap) (ap->version == 1) #define ACE_IS_TIGON_I(ap) (ap->version == 1)
#define ACE_TX_RING_ENTRIES(ap) ap->tx_ring_entries
#endif #endif
#ifndef PCI_VENDOR_ID_ALTEON #ifndef PCI_VENDOR_ID_ALTEON
...@@ -554,7 +556,7 @@ static int tx_ratio[ACE_MAX_MOD_PARMS]; ...@@ -554,7 +556,7 @@ static int tx_ratio[ACE_MAX_MOD_PARMS];
static int dis_pci_mem_inval[ACE_MAX_MOD_PARMS] = {1, 1, 1, 1, 1, 1, 1, 1}; static int dis_pci_mem_inval[ACE_MAX_MOD_PARMS] = {1, 1, 1, 1, 1, 1, 1, 1};
static char version[] __initdata = static char version[] __initdata =
"acenic.c: v0.87 03/14/2002 Jes Sorensen, linux-acenic@SunSITE.dk\n" "acenic.c: v0.88 03/14/2002 Jes Sorensen, linux-acenic@SunSITE.dk\n"
" http://home.cern.ch/~jes/gige/acenic.html\n"; " http://home.cern.ch/~jes/gige/acenic.html\n";
static struct net_device *root_dev; static struct net_device *root_dev;
...@@ -960,6 +962,13 @@ static void ace_free_descriptors(struct net_device *dev) ...@@ -960,6 +962,13 @@ static void ace_free_descriptors(struct net_device *dev)
ap->evt_ring_dma); ap->evt_ring_dma);
ap->evt_ring = NULL; ap->evt_ring = NULL;
} }
if (ap->tx_ring != NULL && !ACE_IS_TIGON_I(ap)) {
size = (sizeof(struct tx_desc) * MAX_TX_RING_ENTRIES);
pci_free_consistent(ap->pdev, size, ap->tx_ring,
ap->tx_ring_dma);
}
ap->tx_ring = NULL;
if (ap->evt_prd != NULL) { if (ap->evt_prd != NULL) {
pci_free_consistent(ap->pdev, sizeof(u32), pci_free_consistent(ap->pdev, sizeof(u32),
(void *)ap->evt_prd, ap->evt_prd_dma); (void *)ap->evt_prd, ap->evt_prd_dma);
...@@ -1006,12 +1015,19 @@ static int ace_allocate_descriptors(struct net_device *dev) ...@@ -1006,12 +1015,19 @@ static int ace_allocate_descriptors(struct net_device *dev)
if (ap->evt_ring == NULL) if (ap->evt_ring == NULL)
goto fail; goto fail;
size = (sizeof(struct tx_desc) * TX_RING_ENTRIES); /*
* Only allocate a host TX ring for the Tigon II, the Tigon I
* has to use PCI registers for this ;-(
*/
if (!ACE_IS_TIGON_I(ap)) {
size = (sizeof(struct tx_desc) * MAX_TX_RING_ENTRIES);
ap->tx_ring = pci_alloc_consistent(ap->pdev, size, &ap->tx_ring_dma); ap->tx_ring = pci_alloc_consistent(ap->pdev, size,
&ap->tx_ring_dma);
if (ap->tx_ring == NULL) if (ap->tx_ring == NULL)
goto fail; goto fail;
}
ap->evt_prd = pci_alloc_consistent(ap->pdev, sizeof(u32), ap->evt_prd = pci_alloc_consistent(ap->pdev, sizeof(u32),
&ap->evt_prd_dma); &ap->evt_prd_dma);
...@@ -1145,6 +1161,7 @@ static int __init ace_init(struct net_device *dev) ...@@ -1145,6 +1161,7 @@ static int __init ace_init(struct net_device *dev)
tigonFwReleaseFix); tigonFwReleaseFix);
writel(0, &regs->LocalCtrl); writel(0, &regs->LocalCtrl);
ap->version = 1; ap->version = 1;
ap->tx_ring_entries = TIGON_I_TX_RING_ENTRIES;
break; break;
#endif #endif
case 6: case 6:
...@@ -1160,6 +1177,7 @@ static int __init ace_init(struct net_device *dev) ...@@ -1160,6 +1177,7 @@ static int __init ace_init(struct net_device *dev)
writel(SRAM_BANK_512K, &regs->LocalCtrl); writel(SRAM_BANK_512K, &regs->LocalCtrl);
writel(SYNC_SRAM_TIMING, &regs->MiscCfg); writel(SYNC_SRAM_TIMING, &regs->MiscCfg);
ap->version = 2; ap->version = 2;
ap->tx_ring_entries = MAX_TX_RING_ENTRIES;
break; break;
default: default:
printk(KERN_WARNING " Unsupported Tigon version detected " printk(KERN_WARNING " Unsupported Tigon version detected "
...@@ -1390,7 +1408,7 @@ static int __init ace_init(struct net_device *dev) ...@@ -1390,7 +1408,7 @@ static int __init ace_init(struct net_device *dev)
#ifdef INDEX_DEBUG #ifdef INDEX_DEBUG
spin_lock_init(&ap->debug_lock); spin_lock_init(&ap->debug_lock);
ap->last_tx = TX_RING_ENTRIES - 1; ap->last_tx = ACE_TX_RING_ENTRIES(ap) - 1;
ap->last_std_rx = 0; ap->last_std_rx = 0;
ap->last_mini_rx = 0; ap->last_mini_rx = 0;
#endif #endif
...@@ -1498,12 +1516,30 @@ static int __init ace_init(struct net_device *dev) ...@@ -1498,12 +1516,30 @@ static int __init ace_init(struct net_device *dev)
*(ap->rx_ret_prd) = 0; *(ap->rx_ret_prd) = 0;
writel(TX_RING_BASE, &regs->WinBase); writel(TX_RING_BASE, &regs->WinBase);
memset(ap->tx_ring, 0, TX_RING_ENTRIES * sizeof(struct tx_desc));
set_aceaddr(&info->tx_ctrl.rngptr, ap->tx_ring_dma); if (ACE_IS_TIGON_I(ap)) {
ap->tx_ring = (struct tx_desc *)regs->Window;
for (i = 0; i < (TIGON_I_TX_RING_ENTRIES *
sizeof(struct tx_desc) / 4); i++) {
writel(0, (unsigned long)ap->tx_ring + i * 4);
}
set_aceaddr(&info->tx_ctrl.rngptr, TX_RING_BASE);
} else {
memset(ap->tx_ring, 0,
MAX_TX_RING_ENTRIES * sizeof(struct tx_desc));
set_aceaddr(&info->tx_ctrl.rngptr, ap->tx_ring_dma);
}
info->tx_ctrl.max_len = ACE_TX_RING_ENTRIES(ap);
tmp = RCB_FLG_TCP_UDP_SUM|RCB_FLG_NO_PSEUDO_HDR;
info->tx_ctrl.max_len = TX_RING_ENTRIES; /*
tmp = RCB_FLG_TCP_UDP_SUM|RCB_FLG_NO_PSEUDO_HDR|RCB_FLG_TX_HOST_RING; * The Tigon I does not like having the TX ring in host memory ;-(
*/
if (!ACE_IS_TIGON_I(ap))
tmp |= RCB_FLG_TX_HOST_RING;
#if TX_COAL_INTS_ONLY #if TX_COAL_INTS_ONLY
tmp |= RCB_FLG_COAL_INT_ONLY; tmp |= RCB_FLG_COAL_INT_ONLY;
#endif #endif
...@@ -2264,7 +2300,7 @@ static inline void ace_tx_int(struct net_device *dev, ...@@ -2264,7 +2300,7 @@ static inline void ace_tx_int(struct net_device *dev,
info->skb = NULL; info->skb = NULL;
} }
idx = (idx + 1) % TX_RING_ENTRIES; idx = (idx + 1) % ACE_TX_RING_ENTRIES(ap);
} while (idx != txcsm); } while (idx != txcsm);
if (netif_queue_stopped(dev)) if (netif_queue_stopped(dev))
...@@ -2357,7 +2393,7 @@ static void ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) ...@@ -2357,7 +2393,7 @@ static void ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
* update releases enough of space, otherwise we just * update releases enough of space, otherwise we just
* wait for device to make more work. * wait for device to make more work.
*/ */
if (!tx_ring_full(txcsm, ap->tx_prd)) if (!tx_ring_full(ap, txcsm, ap->tx_prd))
ace_tx_int(dev, txcsm, idx); ace_tx_int(dev, txcsm, idx);
} }
...@@ -2531,7 +2567,7 @@ static int ace_close(struct net_device *dev) ...@@ -2531,7 +2567,7 @@ static int ace_close(struct net_device *dev)
save_flags(flags); save_flags(flags);
cli(); cli();
for (i = 0; i < TX_RING_ENTRIES; i++) { for (i = 0; i < ACE_TX_RING_ENTRIES(ap); i++) {
struct sk_buff *skb; struct sk_buff *skb;
dma_addr_t mapping; dma_addr_t mapping;
struct tx_ring_info *info; struct tx_ring_info *info;
...@@ -2541,7 +2577,13 @@ static int ace_close(struct net_device *dev) ...@@ -2541,7 +2577,13 @@ static int ace_close(struct net_device *dev)
mapping = pci_unmap_addr(info, mapping); mapping = pci_unmap_addr(info, mapping);
if (mapping) { if (mapping) {
memset(ap->tx_ring + i, 0, sizeof(struct tx_desc)); if (ACE_IS_TIGON_I(ap)) {
writel(0, &ap->tx_ring[i].addr.addrhi);
writel(0, &ap->tx_ring[i].addr.addrlo);
writel(0, &ap->tx_ring[i].flagsize);
} else
memset(ap->tx_ring + i, 0,
sizeof(struct tx_desc));
pci_unmap_page(ap->pdev, mapping, pci_unmap_page(ap->pdev, mapping,
pci_unmap_len(info, maplen), pci_unmap_len(info, maplen),
PCI_DMA_TODEVICE); PCI_DMA_TODEVICE);
...@@ -2587,15 +2629,21 @@ ace_map_tx_skb(struct ace_private *ap, struct sk_buff *skb, ...@@ -2587,15 +2629,21 @@ ace_map_tx_skb(struct ace_private *ap, struct sk_buff *skb,
static inline void static inline void
ace_load_tx_bd(struct tx_desc *desc, u64 addr, u32 flagsize) ace_load_tx_bd(struct ace_private *ap, struct tx_desc *desc,
u64 addr, u32 flagsize)
{ {
#if !USE_TX_COAL_NOW #if !USE_TX_COAL_NOW
flagsize &= ~BD_FLG_COAL_NOW; flagsize &= ~BD_FLG_COAL_NOW;
#endif #endif
if (!ACE_IS_TIGON_I(ap)) {
desc->addr.addrhi = addr >> 32; writel(addr >> 32, &desc->addr.addrhi);
desc->addr.addrlo = addr; writel(addr & 0xffffffff, &desc->addr.addrlo);
desc->flagsize = flagsize; writel(flagsize, &desc->flagsize);
} else {
desc->addr.addrhi = addr >> 32;
desc->addr.addrlo = addr;
desc->flagsize = flagsize;
}
} }
...@@ -2615,7 +2663,7 @@ static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -2615,7 +2663,7 @@ static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev)
restart: restart:
idx = ap->tx_prd; idx = ap->tx_prd;
if (tx_ring_full(ap->tx_ret_csm, idx)) if (tx_ring_full(ap, ap->tx_ret_csm, idx))
goto overflow; goto overflow;
#if MAX_SKB_FRAGS #if MAX_SKB_FRAGS
...@@ -2629,13 +2677,13 @@ static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -2629,13 +2677,13 @@ static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (skb->ip_summed == CHECKSUM_HW) if (skb->ip_summed == CHECKSUM_HW)
flagsize |= BD_FLG_TCP_UDP_SUM; flagsize |= BD_FLG_TCP_UDP_SUM;
desc = ap->tx_ring + idx; desc = ap->tx_ring + idx;
idx = (idx + 1) % TX_RING_ENTRIES; idx = (idx + 1) % ACE_TX_RING_ENTRIES(ap);
/* Look at ace_tx_int for explanations. */ /* Look at ace_tx_int for explanations. */
if (tx_ring_full(ap->tx_ret_csm, idx)) if (tx_ring_full(ap, ap->tx_ret_csm, idx))
flagsize |= BD_FLG_COAL_NOW; flagsize |= BD_FLG_COAL_NOW;
ace_load_tx_bd(desc, mapping, flagsize); ace_load_tx_bd(ap, desc, mapping, flagsize);
} }
#if MAX_SKB_FRAGS #if MAX_SKB_FRAGS
else { else {
...@@ -2647,9 +2695,9 @@ static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -2647,9 +2695,9 @@ static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (skb->ip_summed == CHECKSUM_HW) if (skb->ip_summed == CHECKSUM_HW)
flagsize |= BD_FLG_TCP_UDP_SUM; flagsize |= BD_FLG_TCP_UDP_SUM;
ace_load_tx_bd(ap->tx_ring + idx, mapping, flagsize); ace_load_tx_bd(ap, ap->tx_ring + idx, mapping, flagsize);
idx = (idx + 1) % TX_RING_ENTRIES; idx = (idx + 1) % ACE_TX_RING_ENTRIES(ap);
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
...@@ -2666,11 +2714,11 @@ static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -2666,11 +2714,11 @@ static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev)
flagsize = (frag->size << 16); flagsize = (frag->size << 16);
if (skb->ip_summed == CHECKSUM_HW) if (skb->ip_summed == CHECKSUM_HW)
flagsize |= BD_FLG_TCP_UDP_SUM; flagsize |= BD_FLG_TCP_UDP_SUM;
idx = (idx + 1) % TX_RING_ENTRIES; idx = (idx + 1) % ACE_TX_RING_ENTRIES(ap);
if (i == skb_shinfo(skb)->nr_frags - 1) { if (i == skb_shinfo(skb)->nr_frags - 1) {
flagsize |= BD_FLG_END; flagsize |= BD_FLG_END;
if (tx_ring_full(ap->tx_ret_csm, idx)) if (tx_ring_full(ap, ap->tx_ret_csm, idx))
flagsize |= BD_FLG_COAL_NOW; flagsize |= BD_FLG_COAL_NOW;
/* /*
...@@ -2683,7 +2731,7 @@ static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -2683,7 +2731,7 @@ static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev)
} }
pci_unmap_addr_set(info, mapping, mapping); pci_unmap_addr_set(info, mapping, mapping);
pci_unmap_len_set(info, maplen, frag->size); pci_unmap_len_set(info, maplen, frag->size);
ace_load_tx_bd(desc, mapping, flagsize); ace_load_tx_bd(ap, desc, mapping, flagsize);
} }
} }
#endif #endif
...@@ -2701,7 +2749,7 @@ static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -2701,7 +2749,7 @@ static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev)
* serialized, this is the only situation we have to * serialized, this is the only situation we have to
* re-test. * re-test.
*/ */
if (!tx_ring_full(ap->tx_ret_csm, idx)) if (!tx_ring_full(ap, ap->tx_ret_csm, idx))
netif_wake_queue(dev); netif_wake_queue(dev);
} }
...@@ -2781,7 +2829,7 @@ static int ace_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -2781,7 +2829,7 @@ static int ace_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
if (copy_from_user(&ecmd, ifr->ifr_data, sizeof(ecmd))) if (copy_from_user(&ecmd, ifr->ifr_data, sizeof(ecmd)))
return -EFAULT; return -EFAULT;
switch (ecmd.cmd) { switch (ecmd.cmd) {
case ETHTOOL_GSET: { case ETHTOOL_GSET:
ecmd.supported = ecmd.supported =
(SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
...@@ -2829,8 +2877,8 @@ static int ace_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -2829,8 +2877,8 @@ static int ace_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
if(copy_to_user(ifr->ifr_data, &ecmd, sizeof(ecmd))) if(copy_to_user(ifr->ifr_data, &ecmd, sizeof(ecmd)))
return -EFAULT; return -EFAULT;
return 0; return 0;
}
case ETHTOOL_SSET: { case ETHTOOL_SSET:
if(!capable(CAP_NET_ADMIN)) if(!capable(CAP_NET_ADMIN))
return -EPERM; return -EPERM;
...@@ -2887,7 +2935,7 @@ static int ace_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -2887,7 +2935,7 @@ static int ace_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
ace_issue_cmd(regs, &cmd); ace_issue_cmd(regs, &cmd);
} }
return 0; return 0;
}
case ETHTOOL_GDRVINFO: { case ETHTOOL_GDRVINFO: {
struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
strncpy(info.driver, "acenic", sizeof(info.driver) - 1); strncpy(info.driver, "acenic", sizeof(info.driver) - 1);
......
...@@ -437,11 +437,12 @@ struct cmd { ...@@ -437,11 +437,12 @@ struct cmd {
/* /*
* TX ring * TX ring - maximum TX ring entries for Tigon I's is 128
*/ */
#define TX_RING_ENTRIES 256 #define MAX_TX_RING_ENTRIES 256
#define TX_RING_SIZE (TX_RING_ENTRIES * sizeof(struct tx_desc)) #define TIGON_I_TX_RING_ENTRIES 128
#define TX_RING_BASE 0x3800 #define TX_RING_SIZE (MAX_TX_RING_ENTRIES * sizeof(struct tx_desc))
#define TX_RING_BASE 0x3800
struct tx_desc{ struct tx_desc{
aceaddr addr; aceaddr addr;
...@@ -608,7 +609,7 @@ struct tx_ring_info { ...@@ -608,7 +609,7 @@ struct tx_ring_info {
*/ */
struct ace_skb struct ace_skb
{ {
struct tx_ring_info tx_skbuff[TX_RING_ENTRIES]; struct tx_ring_info tx_skbuff[MAX_TX_RING_ENTRIES];
struct ring_info rx_std_skbuff[RX_STD_RING_ENTRIES]; struct ring_info rx_std_skbuff[RX_STD_RING_ENTRIES];
struct ring_info rx_mini_skbuff[RX_MINI_RING_ENTRIES]; struct ring_info rx_mini_skbuff[RX_MINI_RING_ENTRIES];
struct ring_info rx_jumbo_skbuff[RX_JUMBO_RING_ENTRIES]; struct ring_info rx_jumbo_skbuff[RX_JUMBO_RING_ENTRIES];
...@@ -642,6 +643,7 @@ struct ace_private ...@@ -642,6 +643,7 @@ struct ace_private
u32 tx_prd; u32 tx_prd;
volatile u32 tx_ret_csm; volatile u32 tx_ret_csm;
struct timer_list timer; struct timer_list timer;
int tx_ring_entries;
/* /*
* RX elements * RX elements
...@@ -692,17 +694,17 @@ struct ace_private ...@@ -692,17 +694,17 @@ struct ace_private
#define TX_RESERVED MAX_SKB_FRAGS #define TX_RESERVED MAX_SKB_FRAGS
static inline int tx_space (u32 csm, u32 prd) static inline int tx_space (struct ace_private *ap, u32 csm, u32 prd)
{ {
return (csm - prd - 1) & (TX_RING_ENTRIES - 1); return (csm - prd - 1) & (ACE_TX_RING_ENTRIES(ap) - 1);
} }
#define tx_free(ap) tx_space((ap)->tx_ret_csm, (ap)->tx_prd) #define tx_free(ap) tx_space((ap)->tx_ret_csm, (ap)->tx_prd, ap)
#if MAX_SKB_FRAGS #if MAX_SKB_FRAGS
#define tx_ring_full(csm, prd) (tx_space(csm, prd) <= TX_RESERVED) #define tx_ring_full(ap, csm, prd) (tx_space(ap, csm, prd) <= TX_RESERVED)
#else #else
#define tx_ring_full 0 #define tx_ring_full 0
#endif #endif
...@@ -711,7 +713,7 @@ static inline void set_aceaddr(aceaddr *aa, dma_addr_t addr) ...@@ -711,7 +713,7 @@ static inline void set_aceaddr(aceaddr *aa, dma_addr_t addr)
u64 baddr = (u64) addr; u64 baddr = (u64) addr;
aa->addrlo = baddr & 0xffffffff; aa->addrlo = baddr & 0xffffffff;
aa->addrhi = baddr >> 32; aa->addrhi = baddr >> 32;
mb(); wmb();
} }
......
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