Commit 388f7ef7 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6

parents d5eebf42 560c22fe
...@@ -812,7 +812,7 @@ config SMC91X ...@@ -812,7 +812,7 @@ config SMC91X
tristate "SMC 91C9x/91C1xxx support" tristate "SMC 91C9x/91C1xxx support"
select CRC32 select CRC32
select MII select MII
depends on NET_ETHERNET && (ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH) depends on NET_ETHERNET && (ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || SOC_AU1X00)
help help
This is a driver for SMC's 91x series of Ethernet chipsets, This is a driver for SMC's 91x series of Ethernet chipsets,
including the SMC91C94 and the SMC91C111. Say Y if you want it including the SMC91C94 and the SMC91C111. Say Y if you want it
......
...@@ -97,6 +97,9 @@ ...@@ -97,6 +97,9 @@
* in the second (and later) nv_open call * in the second (and later) nv_open call
* 0.43: 10 Aug 2005: Add support for tx checksum. * 0.43: 10 Aug 2005: Add support for tx checksum.
* 0.44: 20 Aug 2005: Add support for scatter gather and segmentation. * 0.44: 20 Aug 2005: Add support for scatter gather and segmentation.
* 0.45: 18 Sep 2005: Remove nv_stop/start_rx from every link check
* 0.46: 20 Oct 2005: Add irq optimization modes.
* 0.47: 26 Oct 2005: Add phyaddr 0 in phy scan.
* *
* Known bugs: * Known bugs:
* We suspect that on some hardware no TX done interrupts are generated. * We suspect that on some hardware no TX done interrupts are generated.
...@@ -108,7 +111,7 @@ ...@@ -108,7 +111,7 @@
* DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
* superfluous timer interrupts from the nic. * superfluous timer interrupts from the nic.
*/ */
#define FORCEDETH_VERSION "0.44" #define FORCEDETH_VERSION "0.47"
#define DRV_NAME "forcedeth" #define DRV_NAME "forcedeth"
#include <linux/module.h> #include <linux/module.h>
...@@ -163,7 +166,8 @@ enum { ...@@ -163,7 +166,8 @@ enum {
#define NVREG_IRQ_LINK 0x0040 #define NVREG_IRQ_LINK 0x0040
#define NVREG_IRQ_TX_ERROR 0x0080 #define NVREG_IRQ_TX_ERROR 0x0080
#define NVREG_IRQ_TX1 0x0100 #define NVREG_IRQ_TX1 0x0100
#define NVREG_IRQMASK_WANTED 0x00df #define NVREG_IRQMASK_THROUGHPUT 0x00df
#define NVREG_IRQMASK_CPU 0x0040
#define NVREG_IRQ_UNKNOWN (~(NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_TX_ERR| \ #define NVREG_IRQ_UNKNOWN (~(NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_TX_ERR| \
NVREG_IRQ_TX_OK|NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_TX_ERROR| \ NVREG_IRQ_TX_OK|NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_TX_ERROR| \
...@@ -177,7 +181,8 @@ enum { ...@@ -177,7 +181,8 @@ enum {
* NVREG_POLL_DEFAULT=97 would result in an interval length of 1 ms * NVREG_POLL_DEFAULT=97 would result in an interval length of 1 ms
*/ */
NvRegPollingInterval = 0x00c, NvRegPollingInterval = 0x00c,
#define NVREG_POLL_DEFAULT 970 #define NVREG_POLL_DEFAULT_THROUGHPUT 970
#define NVREG_POLL_DEFAULT_CPU 13
NvRegMisc1 = 0x080, NvRegMisc1 = 0x080,
#define NVREG_MISC1_HD 0x02 #define NVREG_MISC1_HD 0x02
#define NVREG_MISC1_FORCE 0x3b0f3c #define NVREG_MISC1_FORCE 0x3b0f3c
...@@ -538,6 +543,25 @@ struct fe_priv { ...@@ -538,6 +543,25 @@ struct fe_priv {
*/ */
static int max_interrupt_work = 5; static int max_interrupt_work = 5;
/*
* Optimization can be either throuput mode or cpu mode
*
* Throughput Mode: Every tx and rx packet will generate an interrupt.
* CPU Mode: Interrupts are controlled by a timer.
*/
#define NV_OPTIMIZATION_MODE_THROUGHPUT 0
#define NV_OPTIMIZATION_MODE_CPU 1
static int optimization_mode = NV_OPTIMIZATION_MODE_THROUGHPUT;
/*
* Poll interval for timer irq
*
* This interval determines how frequent an interrupt is generated.
* The is value is determined by [(time_in_micro_secs * 100) / (2^10)]
* Min = 0, and Max = 65535
*/
static int poll_interval = -1;
static inline struct fe_priv *get_nvpriv(struct net_device *dev) static inline struct fe_priv *get_nvpriv(struct net_device *dev)
{ {
return netdev_priv(dev); return netdev_priv(dev);
...@@ -1328,6 +1352,7 @@ static void nv_rx_process(struct net_device *dev) ...@@ -1328,6 +1352,7 @@ static void nv_rx_process(struct net_device *dev)
if (!(Flags & NV_RX_DESCRIPTORVALID)) if (!(Flags & NV_RX_DESCRIPTORVALID))
goto next_pkt; goto next_pkt;
if (Flags & NV_RX_ERROR) {
if (Flags & NV_RX_MISSEDFRAME) { if (Flags & NV_RX_MISSEDFRAME) {
np->stats.rx_missed_errors++; np->stats.rx_missed_errors++;
np->stats.rx_errors++; np->stats.rx_errors++;
...@@ -1360,10 +1385,12 @@ static void nv_rx_process(struct net_device *dev) ...@@ -1360,10 +1385,12 @@ static void nv_rx_process(struct net_device *dev)
len--; len--;
} }
} }
}
} else { } else {
if (!(Flags & NV_RX2_DESCRIPTORVALID)) if (!(Flags & NV_RX2_DESCRIPTORVALID))
goto next_pkt; goto next_pkt;
if (Flags & NV_RX2_ERROR) {
if (Flags & (NV_RX2_ERROR1|NV_RX2_ERROR2|NV_RX2_ERROR3)) { if (Flags & (NV_RX2_ERROR1|NV_RX2_ERROR2|NV_RX2_ERROR3)) {
np->stats.rx_errors++; np->stats.rx_errors++;
goto next_pkt; goto next_pkt;
...@@ -1391,6 +1418,7 @@ static void nv_rx_process(struct net_device *dev) ...@@ -1391,6 +1418,7 @@ static void nv_rx_process(struct net_device *dev)
len--; len--;
} }
} }
}
Flags &= NV_RX2_CHECKSUMMASK; Flags &= NV_RX2_CHECKSUMMASK;
if (Flags == NV_RX2_CHECKSUMOK1 || if (Flags == NV_RX2_CHECKSUMOK1 ||
Flags == NV_RX2_CHECKSUMOK2 || Flags == NV_RX2_CHECKSUMOK2 ||
...@@ -1612,6 +1640,17 @@ static void nv_set_multicast(struct net_device *dev) ...@@ -1612,6 +1640,17 @@ static void nv_set_multicast(struct net_device *dev)
spin_unlock_irq(&np->lock); spin_unlock_irq(&np->lock);
} }
/**
* nv_update_linkspeed: Setup the MAC according to the link partner
* @dev: Network device to be configured
*
* The function queries the PHY and checks if there is a link partner.
* If yes, then it sets up the MAC accordingly. Otherwise, the MAC is
* set to 10 MBit HD.
*
* The function returns 0 if there is no link partner and 1 if there is
* a good link partner.
*/
static int nv_update_linkspeed(struct net_device *dev) static int nv_update_linkspeed(struct net_device *dev)
{ {
struct fe_priv *np = netdev_priv(dev); struct fe_priv *np = netdev_priv(dev);
...@@ -1751,13 +1790,11 @@ static int nv_update_linkspeed(struct net_device *dev) ...@@ -1751,13 +1790,11 @@ static int nv_update_linkspeed(struct net_device *dev)
static void nv_linkchange(struct net_device *dev) static void nv_linkchange(struct net_device *dev)
{ {
if (nv_update_linkspeed(dev)) { if (nv_update_linkspeed(dev)) {
if (netif_carrier_ok(dev)) { if (!netif_carrier_ok(dev)) {
nv_stop_rx(dev);
} else {
netif_carrier_on(dev); netif_carrier_on(dev);
printk(KERN_INFO "%s: link up.\n", dev->name); printk(KERN_INFO "%s: link up.\n", dev->name);
}
nv_start_rx(dev); nv_start_rx(dev);
}
} else { } else {
if (netif_carrier_ok(dev)) { if (netif_carrier_ok(dev)) {
netif_carrier_off(dev); netif_carrier_off(dev);
...@@ -1799,13 +1836,10 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs) ...@@ -1799,13 +1836,10 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
if (!(events & np->irqmask)) if (!(events & np->irqmask))
break; break;
if (events & (NVREG_IRQ_TX1|NVREG_IRQ_TX_OK|NVREG_IRQ_TX_ERROR|NVREG_IRQ_TX_ERR)) {
spin_lock(&np->lock); spin_lock(&np->lock);
nv_tx_done(dev); nv_tx_done(dev);
spin_unlock(&np->lock); spin_unlock(&np->lock);
}
if (events & (NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF)) {
nv_rx_process(dev); nv_rx_process(dev);
if (nv_alloc_rx(dev)) { if (nv_alloc_rx(dev)) {
spin_lock(&np->lock); spin_lock(&np->lock);
...@@ -1813,7 +1847,6 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs) ...@@ -1813,7 +1847,6 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
mod_timer(&np->oom_kick, jiffies + OOM_REFILL); mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
spin_unlock(&np->lock); spin_unlock(&np->lock);
} }
}
if (events & NVREG_IRQ_LINK) { if (events & NVREG_IRQ_LINK) {
spin_lock(&np->lock); spin_lock(&np->lock);
...@@ -2216,7 +2249,14 @@ static int nv_open(struct net_device *dev) ...@@ -2216,7 +2249,14 @@ static int nv_open(struct net_device *dev)
writel(NVREG_RNDSEED_FORCE | (i&NVREG_RNDSEED_MASK), base + NvRegRandomSeed); writel(NVREG_RNDSEED_FORCE | (i&NVREG_RNDSEED_MASK), base + NvRegRandomSeed);
writel(NVREG_UNKSETUP1_VAL, base + NvRegUnknownSetupReg1); writel(NVREG_UNKSETUP1_VAL, base + NvRegUnknownSetupReg1);
writel(NVREG_UNKSETUP2_VAL, base + NvRegUnknownSetupReg2); writel(NVREG_UNKSETUP2_VAL, base + NvRegUnknownSetupReg2);
writel(NVREG_POLL_DEFAULT, base + NvRegPollingInterval); if (poll_interval == -1) {
if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT)
writel(NVREG_POLL_DEFAULT_THROUGHPUT, base + NvRegPollingInterval);
else
writel(NVREG_POLL_DEFAULT_CPU, base + NvRegPollingInterval);
}
else
writel(poll_interval & 0xFFFF, base + NvRegPollingInterval);
writel(NVREG_UNKSETUP6_VAL, base + NvRegUnknownSetupReg6); writel(NVREG_UNKSETUP6_VAL, base + NvRegUnknownSetupReg6);
writel((np->phyaddr << NVREG_ADAPTCTL_PHYSHIFT)|NVREG_ADAPTCTL_PHYVALID|NVREG_ADAPTCTL_RUNNING, writel((np->phyaddr << NVREG_ADAPTCTL_PHYSHIFT)|NVREG_ADAPTCTL_PHYVALID|NVREG_ADAPTCTL_RUNNING,
base + NvRegAdapterControl); base + NvRegAdapterControl);
...@@ -2501,7 +2541,11 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i ...@@ -2501,7 +2541,11 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
} else { } else {
np->tx_flags = NV_TX2_VALID; np->tx_flags = NV_TX2_VALID;
} }
np->irqmask = NVREG_IRQMASK_WANTED; if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT)
np->irqmask = NVREG_IRQMASK_THROUGHPUT;
else
np->irqmask = NVREG_IRQMASK_CPU;
if (id->driver_data & DEV_NEED_TIMERIRQ) if (id->driver_data & DEV_NEED_TIMERIRQ)
np->irqmask |= NVREG_IRQ_TIMER; np->irqmask |= NVREG_IRQ_TIMER;
if (id->driver_data & DEV_NEED_LINKTIMER) { if (id->driver_data & DEV_NEED_LINKTIMER) {
...@@ -2514,16 +2558,17 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i ...@@ -2514,16 +2558,17 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
} }
/* find a suitable phy */ /* find a suitable phy */
for (i = 1; i < 32; i++) { for (i = 1; i <= 32; i++) {
int id1, id2; int id1, id2;
int phyaddr = i & 0x1F;
spin_lock_irq(&np->lock); spin_lock_irq(&np->lock);
id1 = mii_rw(dev, i, MII_PHYSID1, MII_READ); id1 = mii_rw(dev, phyaddr, MII_PHYSID1, MII_READ);
spin_unlock_irq(&np->lock); spin_unlock_irq(&np->lock);
if (id1 < 0 || id1 == 0xffff) if (id1 < 0 || id1 == 0xffff)
continue; continue;
spin_lock_irq(&np->lock); spin_lock_irq(&np->lock);
id2 = mii_rw(dev, i, MII_PHYSID2, MII_READ); id2 = mii_rw(dev, phyaddr, MII_PHYSID2, MII_READ);
spin_unlock_irq(&np->lock); spin_unlock_irq(&np->lock);
if (id2 < 0 || id2 == 0xffff) if (id2 < 0 || id2 == 0xffff)
continue; continue;
...@@ -2531,23 +2576,19 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i ...@@ -2531,23 +2576,19 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
id1 = (id1 & PHYID1_OUI_MASK) << PHYID1_OUI_SHFT; id1 = (id1 & PHYID1_OUI_MASK) << PHYID1_OUI_SHFT;
id2 = (id2 & PHYID2_OUI_MASK) >> PHYID2_OUI_SHFT; id2 = (id2 & PHYID2_OUI_MASK) >> PHYID2_OUI_SHFT;
dprintk(KERN_DEBUG "%s: open: Found PHY %04x:%04x at address %d.\n", dprintk(KERN_DEBUG "%s: open: Found PHY %04x:%04x at address %d.\n",
pci_name(pci_dev), id1, id2, i); pci_name(pci_dev), id1, id2, phyaddr);
np->phyaddr = i; np->phyaddr = phyaddr;
np->phy_oui = id1 | id2; np->phy_oui = id1 | id2;
break; break;
} }
if (i == 32) { if (i == 33) {
/* PHY in isolate mode? No phy attached and user wants to
* test loopback? Very odd, but can be correct.
*/
printk(KERN_INFO "%s: open: Could not find a valid PHY.\n", printk(KERN_INFO "%s: open: Could not find a valid PHY.\n",
pci_name(pci_dev)); pci_name(pci_dev));
goto out_freering;
} }
if (i != 32) {
/* reset it */ /* reset it */
phy_init(dev); phy_init(dev);
}
/* set default link speed settings */ /* set default link speed settings */
np->linkspeed = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10; np->linkspeed = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
...@@ -2689,6 +2730,10 @@ static void __exit exit_nic(void) ...@@ -2689,6 +2730,10 @@ static void __exit exit_nic(void)
module_param(max_interrupt_work, int, 0); module_param(max_interrupt_work, int, 0);
MODULE_PARM_DESC(max_interrupt_work, "forcedeth maximum events handled per interrupt"); MODULE_PARM_DESC(max_interrupt_work, "forcedeth maximum events handled per interrupt");
module_param(optimization_mode, int, 0);
MODULE_PARM_DESC(optimization_mode, "In throughput mode (0), every tx & rx packet will generate an interrupt. In CPU mode (1), interrupts are controlled by a timer.");
module_param(poll_interval, int, 0);
MODULE_PARM_DESC(poll_interval, "Interval determines how frequent timer interrupt is generated by [(time_in_micro_secs * 100) / (2^10)]. Min is 0 and Max is 65535.");
MODULE_AUTHOR("Manfred Spraul <manfred@colorfullife.com>"); MODULE_AUTHOR("Manfred Spraul <manfred@colorfullife.com>");
MODULE_DESCRIPTION("Reverse Engineered nForce ethernet driver"); MODULE_DESCRIPTION("Reverse Engineered nForce ethernet driver");
......
...@@ -133,7 +133,7 @@ int gfar_mdio_probe(struct device *dev) ...@@ -133,7 +133,7 @@ int gfar_mdio_probe(struct device *dev)
if (NULL == dev) if (NULL == dev)
return -EINVAL; return -EINVAL;
new_bus = kmalloc(sizeof(struct mii_bus), GFP_KERNEL); new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
if (NULL == new_bus) if (NULL == new_bus)
return -ENOMEM; return -ENOMEM;
......
...@@ -72,8 +72,6 @@ static void dump_tx_desc(int dbg_lvl, struct net_device *dev, int i); ...@@ -72,8 +72,6 @@ static void dump_tx_desc(int dbg_lvl, struct net_device *dev, int i);
static void dump_rx_desc(int dbg_lvl, struct net_device *dev, int i); static void dump_rx_desc(int dbg_lvl, struct net_device *dev, int i);
static void dump_skb(int dbg_lvl, struct net_device *dev, static void dump_skb(int dbg_lvl, struct net_device *dev,
struct sk_buff *skb); struct sk_buff *skb);
static void dump_hw_addr(int dbg_lvl, struct net_device *dev,
const char* pfx, unsigned char* addr_str);
static void update_stats(struct gt96100_private *gp); static void update_stats(struct gt96100_private *gp);
static void abort(struct net_device *dev, u32 abort_bits); static void abort(struct net_device *dev, u32 abort_bits);
static void hard_stop(struct net_device *dev); static void hard_stop(struct net_device *dev);
...@@ -334,13 +332,13 @@ dump_MII(int dbg_lvl, struct net_device *dev) ...@@ -334,13 +332,13 @@ dump_MII(int dbg_lvl, struct net_device *dev)
static void static void
dump_hw_addr(int dbg_lvl, struct net_device *dev, const char* pfx, dump_hw_addr(int dbg_lvl, struct net_device *dev, const char* pfx,
unsigned char* addr_str) const char* func, unsigned char* addr_str)
{ {
int i; int i;
char buf[100], octet[5]; char buf[100], octet[5];
if (dbg_lvl <= GT96100_DEBUG) { if (dbg_lvl <= GT96100_DEBUG) {
strcpy(buf, pfx); sprintf(buf, pfx, func);
for (i = 0; i < 6; i++) { for (i = 0; i < 6; i++) {
sprintf(octet, "%2.2x%s", sprintf(octet, "%2.2x%s",
addr_str[i], i<5 ? ":" : "\n"); addr_str[i], i<5 ? ":" : "\n");
...@@ -708,7 +706,7 @@ static int __init gt96100_probe1(struct pci_dev *pci, int port_num) ...@@ -708,7 +706,7 @@ static int __init gt96100_probe1(struct pci_dev *pci, int port_num)
info("%s found at 0x%x, irq %d\n", info("%s found at 0x%x, irq %d\n",
chip_name(gp->chip_rev), gtif->iobase, gtif->irq); chip_name(gp->chip_rev), gtif->iobase, gtif->irq);
dump_hw_addr(0, dev, "HW Address ", dev->dev_addr); dump_hw_addr(0, dev, "%s: HW Address ", __FUNCTION__, dev->dev_addr);
info("%s chip revision=%d\n", chip_name(gp->chip_rev), gp->chip_rev); info("%s chip revision=%d\n", chip_name(gp->chip_rev), gp->chip_rev);
info("%s ethernet port %d\n", chip_name(gp->chip_rev), gp->port_num); info("%s ethernet port %d\n", chip_name(gp->chip_rev), gp->port_num);
info("external PHY ID1=0x%04x, ID2=0x%04x\n", phy_id1, phy_id2); info("external PHY ID1=0x%04x, ID2=0x%04x\n", phy_id1, phy_id2);
...@@ -1488,7 +1486,7 @@ gt96100_set_rx_mode(struct net_device *dev) ...@@ -1488,7 +1486,7 @@ gt96100_set_rx_mode(struct net_device *dev)
gt96100_add_hash_entry(dev, dev->dev_addr); gt96100_add_hash_entry(dev, dev->dev_addr);
for (mcptr = dev->mc_list; mcptr; mcptr = mcptr->next) { for (mcptr = dev->mc_list; mcptr; mcptr = mcptr->next) {
dump_hw_addr(2, dev, __FUNCTION__ ": addr=", dump_hw_addr(2, dev, "%s: addr=", __FUNCTION__,
mcptr->dmi_addr); mcptr->dmi_addr);
gt96100_add_hash_entry(dev, mcptr->dmi_addr); gt96100_add_hash_entry(dev, mcptr->dmi_addr);
} }
......
...@@ -58,7 +58,7 @@ ...@@ -58,7 +58,7 @@
#include "ibmveth.h" #include "ibmveth.h"
#define DEBUG 1 #undef DEBUG
#define ibmveth_printk(fmt, args...) \ #define ibmveth_printk(fmt, args...) \
printk(KERN_INFO "%s: " fmt, __FILE__, ## args) printk(KERN_INFO "%s: " fmt, __FILE__, ## args)
......
/* /*
* Carsten Langgaard, carstenl@mips.com * Copyright (C) 2000, 2005 MIPS Technologies, Inc. All rights reserved.
* Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. * Authors: Carsten Langgaard <carstenl@mips.com>
* * Maciej W. Rozycki <macro@mips.com>
* ######################################################################## * Copyright (C) 2004 Ralf Baechle <ralf@linux-mips.org>
* *
* This program is free software; you can distribute it and/or modify it * This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as * under the terms of the GNU General Public License (Version 2) as
...@@ -17,15 +17,13 @@ ...@@ -17,15 +17,13 @@
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
* *
* ########################################################################
*
* SAA9730 ethernet driver. * SAA9730 ethernet driver.
* *
* Changes: * Changes:
* Angelo Dell'Aera <buffer@antifork.org> : Conversion to the new PCI API (pci_driver). * Angelo Dell'Aera <buffer@antifork.org> : Conversion to the new PCI API
* (pci_driver).
* Conversion to spinlocks. * Conversion to spinlocks.
* Error handling fixes. * Error handling fixes.
*
*/ */
#include <linux/init.h> #include <linux/init.h>
...@@ -36,8 +34,11 @@ ...@@ -36,8 +34,11 @@
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/types.h>
#include <asm/addrspace.h> #include <asm/addrspace.h>
#include <asm/io.h>
#include <asm/mips-boards/prom.h> #include <asm/mips-boards/prom.h>
#include "saa9730.h" #include "saa9730.h"
...@@ -51,7 +52,7 @@ int lan_saa9730_debug; ...@@ -51,7 +52,7 @@ int lan_saa9730_debug;
#define DRV_MODULE_NAME "saa9730" #define DRV_MODULE_NAME "saa9730"
static struct pci_device_id saa9730_pci_tbl[] = { static struct pci_device_id saa9730_pci_tbl[] = {
{ PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA9370, { PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA9730,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ 0, } { 0, }
}; };
...@@ -61,50 +62,48 @@ MODULE_DEVICE_TABLE(pci, saa9730_pci_tbl); ...@@ -61,50 +62,48 @@ MODULE_DEVICE_TABLE(pci, saa9730_pci_tbl);
/* Non-zero only if the current card is a PCI with BIOS-set IRQ. */ /* Non-zero only if the current card is a PCI with BIOS-set IRQ. */
static unsigned int pci_irq_line; static unsigned int pci_irq_line;
#define INL(a) inl((unsigned long)a)
#define OUTL(x,a) outl(x,(unsigned long)a)
static void evm_saa9730_enable_lan_int(struct lan_saa9730_private *lp) static void evm_saa9730_enable_lan_int(struct lan_saa9730_private *lp)
{ {
OUTL(INL(&lp->evm_saa9730_regs->InterruptBlock1) | EVM_LAN_INT, outl(readl(&lp->evm_saa9730_regs->InterruptBlock1) | EVM_LAN_INT,
&lp->evm_saa9730_regs->InterruptBlock1); &lp->evm_saa9730_regs->InterruptBlock1);
OUTL(INL(&lp->evm_saa9730_regs->InterruptStatus1) | EVM_LAN_INT, outl(readl(&lp->evm_saa9730_regs->InterruptStatus1) | EVM_LAN_INT,
&lp->evm_saa9730_regs->InterruptStatus1); &lp->evm_saa9730_regs->InterruptStatus1);
OUTL(INL(&lp->evm_saa9730_regs->InterruptEnable1) | EVM_LAN_INT | outl(readl(&lp->evm_saa9730_regs->InterruptEnable1) | EVM_LAN_INT |
EVM_MASTER_EN, &lp->evm_saa9730_regs->InterruptEnable1); EVM_MASTER_EN, &lp->evm_saa9730_regs->InterruptEnable1);
} }
static void evm_saa9730_disable_lan_int(struct lan_saa9730_private *lp) static void evm_saa9730_disable_lan_int(struct lan_saa9730_private *lp)
{ {
OUTL(INL(&lp->evm_saa9730_regs->InterruptBlock1) & ~EVM_LAN_INT, outl(readl(&lp->evm_saa9730_regs->InterruptBlock1) & ~EVM_LAN_INT,
&lp->evm_saa9730_regs->InterruptBlock1); &lp->evm_saa9730_regs->InterruptBlock1);
OUTL(INL(&lp->evm_saa9730_regs->InterruptEnable1) & ~EVM_LAN_INT, outl(readl(&lp->evm_saa9730_regs->InterruptEnable1) & ~EVM_LAN_INT,
&lp->evm_saa9730_regs->InterruptEnable1); &lp->evm_saa9730_regs->InterruptEnable1);
} }
static void evm_saa9730_clear_lan_int(struct lan_saa9730_private *lp) static void evm_saa9730_clear_lan_int(struct lan_saa9730_private *lp)
{ {
OUTL(EVM_LAN_INT, &lp->evm_saa9730_regs->InterruptStatus1); outl(EVM_LAN_INT, &lp->evm_saa9730_regs->InterruptStatus1);
} }
static void evm_saa9730_block_lan_int(struct lan_saa9730_private *lp) static void evm_saa9730_block_lan_int(struct lan_saa9730_private *lp)
{ {
OUTL(INL(&lp->evm_saa9730_regs->InterruptBlock1) & ~EVM_LAN_INT, outl(readl(&lp->evm_saa9730_regs->InterruptBlock1) & ~EVM_LAN_INT,
&lp->evm_saa9730_regs->InterruptBlock1); &lp->evm_saa9730_regs->InterruptBlock1);
} }
static void evm_saa9730_unblock_lan_int(struct lan_saa9730_private *lp) static void evm_saa9730_unblock_lan_int(struct lan_saa9730_private *lp)
{ {
OUTL(INL(&lp->evm_saa9730_regs->InterruptBlock1) | EVM_LAN_INT, outl(readl(&lp->evm_saa9730_regs->InterruptBlock1) | EVM_LAN_INT,
&lp->evm_saa9730_regs->InterruptBlock1); &lp->evm_saa9730_regs->InterruptBlock1);
} }
static void show_saa9730_regs(struct lan_saa9730_private *lp) static void __attribute_used__ show_saa9730_regs(struct lan_saa9730_private *lp)
{ {
int i, j; int i, j;
printk("TxmBufferA = %x\n", lp->TxmBuffer[0][0]); printk("TxmBufferA = %p\n", lp->TxmBuffer[0][0]);
printk("TxmBufferB = %x\n", lp->TxmBuffer[1][0]); printk("TxmBufferB = %p\n", lp->TxmBuffer[1][0]);
printk("RcvBufferA = %x\n", lp->RcvBuffer[0][0]); printk("RcvBufferA = %p\n", lp->RcvBuffer[0][0]);
printk("RcvBufferB = %x\n", lp->RcvBuffer[1][0]); printk("RcvBufferB = %p\n", lp->RcvBuffer[1][0]);
for (i = 0; i < LAN_SAA9730_BUFFERS; i++) { for (i = 0; i < LAN_SAA9730_BUFFERS; i++) {
for (j = 0; j < LAN_SAA9730_TXM_Q_SIZE; j++) { for (j = 0; j < LAN_SAA9730_TXM_Q_SIZE; j++) {
printk("TxmBuffer[%d][%d] = %x\n", i, j, printk("TxmBuffer[%d][%d] = %x\n", i, j,
...@@ -120,13 +119,13 @@ static void show_saa9730_regs(struct lan_saa9730_private *lp) ...@@ -120,13 +119,13 @@ static void show_saa9730_regs(struct lan_saa9730_private *lp)
} }
} }
printk("lp->evm_saa9730_regs->InterruptBlock1 = %x\n", printk("lp->evm_saa9730_regs->InterruptBlock1 = %x\n",
INL(&lp->evm_saa9730_regs->InterruptBlock1)); readl(&lp->evm_saa9730_regs->InterruptBlock1));
printk("lp->evm_saa9730_regs->InterruptStatus1 = %x\n", printk("lp->evm_saa9730_regs->InterruptStatus1 = %x\n",
INL(&lp->evm_saa9730_regs->InterruptStatus1)); readl(&lp->evm_saa9730_regs->InterruptStatus1));
printk("lp->evm_saa9730_regs->InterruptEnable1 = %x\n", printk("lp->evm_saa9730_regs->InterruptEnable1 = %x\n",
INL(&lp->evm_saa9730_regs->InterruptEnable1)); readl(&lp->evm_saa9730_regs->InterruptEnable1));
printk("lp->lan_saa9730_regs->Ok2Use = %x\n", printk("lp->lan_saa9730_regs->Ok2Use = %x\n",
INL(&lp->lan_saa9730_regs->Ok2Use)); readl(&lp->lan_saa9730_regs->Ok2Use));
printk("lp->NextTxmBufferIndex = %x\n", lp->NextTxmBufferIndex); printk("lp->NextTxmBufferIndex = %x\n", lp->NextTxmBufferIndex);
printk("lp->NextTxmPacketIndex = %x\n", lp->NextTxmPacketIndex); printk("lp->NextTxmPacketIndex = %x\n", lp->NextTxmPacketIndex);
printk("lp->PendingTxmBufferIndex = %x\n", printk("lp->PendingTxmBufferIndex = %x\n",
...@@ -134,23 +133,23 @@ static void show_saa9730_regs(struct lan_saa9730_private *lp) ...@@ -134,23 +133,23 @@ static void show_saa9730_regs(struct lan_saa9730_private *lp)
printk("lp->PendingTxmPacketIndex = %x\n", printk("lp->PendingTxmPacketIndex = %x\n",
lp->PendingTxmPacketIndex); lp->PendingTxmPacketIndex);
printk("lp->lan_saa9730_regs->LanDmaCtl = %x\n", printk("lp->lan_saa9730_regs->LanDmaCtl = %x\n",
INL(&lp->lan_saa9730_regs->LanDmaCtl)); readl(&lp->lan_saa9730_regs->LanDmaCtl));
printk("lp->lan_saa9730_regs->DmaStatus = %x\n", printk("lp->lan_saa9730_regs->DmaStatus = %x\n",
INL(&lp->lan_saa9730_regs->DmaStatus)); readl(&lp->lan_saa9730_regs->DmaStatus));
printk("lp->lan_saa9730_regs->CamCtl = %x\n", printk("lp->lan_saa9730_regs->CamCtl = %x\n",
INL(&lp->lan_saa9730_regs->CamCtl)); readl(&lp->lan_saa9730_regs->CamCtl));
printk("lp->lan_saa9730_regs->TxCtl = %x\n", printk("lp->lan_saa9730_regs->TxCtl = %x\n",
INL(&lp->lan_saa9730_regs->TxCtl)); readl(&lp->lan_saa9730_regs->TxCtl));
printk("lp->lan_saa9730_regs->TxStatus = %x\n", printk("lp->lan_saa9730_regs->TxStatus = %x\n",
INL(&lp->lan_saa9730_regs->TxStatus)); readl(&lp->lan_saa9730_regs->TxStatus));
printk("lp->lan_saa9730_regs->RxCtl = %x\n", printk("lp->lan_saa9730_regs->RxCtl = %x\n",
INL(&lp->lan_saa9730_regs->RxCtl)); readl(&lp->lan_saa9730_regs->RxCtl));
printk("lp->lan_saa9730_regs->RxStatus = %x\n", printk("lp->lan_saa9730_regs->RxStatus = %x\n",
INL(&lp->lan_saa9730_regs->RxStatus)); readl(&lp->lan_saa9730_regs->RxStatus));
for (i = 0; i < LAN_SAA9730_CAM_DWORDS; i++) { for (i = 0; i < LAN_SAA9730_CAM_DWORDS; i++) {
OUTL(i, &lp->lan_saa9730_regs->CamAddress); outl(i, &lp->lan_saa9730_regs->CamAddress);
printk("lp->lan_saa9730_regs->CamData = %x\n", printk("lp->lan_saa9730_regs->CamData = %x\n",
INL(&lp->lan_saa9730_regs->CamData)); readl(&lp->lan_saa9730_regs->CamData));
} }
printk("lp->stats.tx_packets = %lx\n", lp->stats.tx_packets); printk("lp->stats.tx_packets = %lx\n", lp->stats.tx_packets);
printk("lp->stats.tx_errors = %lx\n", lp->stats.tx_errors); printk("lp->stats.tx_errors = %lx\n", lp->stats.tx_errors);
...@@ -178,17 +177,17 @@ static void show_saa9730_regs(struct lan_saa9730_private *lp) ...@@ -178,17 +177,17 @@ static void show_saa9730_regs(struct lan_saa9730_private *lp)
lp->stats.rx_length_errors); lp->stats.rx_length_errors);
printk("lp->lan_saa9730_regs->DebugPCIMasterAddr = %x\n", printk("lp->lan_saa9730_regs->DebugPCIMasterAddr = %x\n",
INL(&lp->lan_saa9730_regs->DebugPCIMasterAddr)); readl(&lp->lan_saa9730_regs->DebugPCIMasterAddr));
printk("lp->lan_saa9730_regs->DebugLanTxStateMachine = %x\n", printk("lp->lan_saa9730_regs->DebugLanTxStateMachine = %x\n",
INL(&lp->lan_saa9730_regs->DebugLanTxStateMachine)); readl(&lp->lan_saa9730_regs->DebugLanTxStateMachine));
printk("lp->lan_saa9730_regs->DebugLanRxStateMachine = %x\n", printk("lp->lan_saa9730_regs->DebugLanRxStateMachine = %x\n",
INL(&lp->lan_saa9730_regs->DebugLanRxStateMachine)); readl(&lp->lan_saa9730_regs->DebugLanRxStateMachine));
printk("lp->lan_saa9730_regs->DebugLanTxFifoPointers = %x\n", printk("lp->lan_saa9730_regs->DebugLanTxFifoPointers = %x\n",
INL(&lp->lan_saa9730_regs->DebugLanTxFifoPointers)); readl(&lp->lan_saa9730_regs->DebugLanTxFifoPointers));
printk("lp->lan_saa9730_regs->DebugLanRxFifoPointers = %x\n", printk("lp->lan_saa9730_regs->DebugLanRxFifoPointers = %x\n",
INL(&lp->lan_saa9730_regs->DebugLanRxFifoPointers)); readl(&lp->lan_saa9730_regs->DebugLanRxFifoPointers));
printk("lp->lan_saa9730_regs->DebugLanCtlStateMachine = %x\n", printk("lp->lan_saa9730_regs->DebugLanCtlStateMachine = %x\n",
INL(&lp->lan_saa9730_regs->DebugLanCtlStateMachine)); readl(&lp->lan_saa9730_regs->DebugLanCtlStateMachine));
} }
static void lan_saa9730_buffer_init(struct lan_saa9730_private *lp) static void lan_saa9730_buffer_init(struct lan_saa9730_private *lp)
...@@ -214,39 +213,52 @@ static void lan_saa9730_buffer_init(struct lan_saa9730_private *lp) ...@@ -214,39 +213,52 @@ static void lan_saa9730_buffer_init(struct lan_saa9730_private *lp)
} }
} }
static int lan_saa9730_allocate_buffers(struct lan_saa9730_private *lp) static void lan_saa9730_free_buffers(struct pci_dev *pdev,
struct lan_saa9730_private *lp)
{
pci_free_consistent(pdev, lp->buffer_size, lp->buffer_start,
lp->dma_addr);
}
static int lan_saa9730_allocate_buffers(struct pci_dev *pdev,
struct lan_saa9730_private *lp)
{ {
unsigned int mem_size;
void *Pa; void *Pa;
unsigned int i, j, RcvBufferSize, TxmBufferSize; unsigned int i, j, rxoffset, txoffset;
unsigned int buffer_start; int ret;
/* Initialize buffer space */
lp->DmaRcvPackets = LAN_SAA9730_RCV_Q_SIZE;
lp->DmaTxmPackets = LAN_SAA9730_TXM_Q_SIZE;
/* Initialize Rx Buffer Index */
lp->NextRcvPacketIndex = 0;
lp->NextRcvBufferIndex = 0;
/* Set current buffer index & next available packet index */
lp->NextTxmPacketIndex = 0;
lp->NextTxmBufferIndex = 0;
lp->PendingTxmPacketIndex = 0;
lp->PendingTxmBufferIndex = 0;
/* /*
* Allocate all RX and TX packets in one chunk. * Allocate all RX and TX packets in one chunk.
* The Rx and Tx packets must be PACKET_SIZE aligned. * The Rx and Tx packets must be PACKET_SIZE aligned.
*/ */
mem_size = ((LAN_SAA9730_RCV_Q_SIZE + LAN_SAA9730_TXM_Q_SIZE) * lp->buffer_size = ((LAN_SAA9730_RCV_Q_SIZE + LAN_SAA9730_TXM_Q_SIZE) *
LAN_SAA9730_PACKET_SIZE * LAN_SAA9730_BUFFERS) + LAN_SAA9730_PACKET_SIZE * LAN_SAA9730_BUFFERS) +
LAN_SAA9730_PACKET_SIZE; LAN_SAA9730_PACKET_SIZE;
buffer_start = lp->buffer_start = pci_alloc_consistent(pdev, lp->buffer_size,
(unsigned int) kmalloc(mem_size, GFP_DMA | GFP_KERNEL); &lp->dma_addr);
if (!lp->buffer_start) {
if (!buffer_start) ret = -ENOMEM;
return -ENOMEM; goto out;
}
/* Pa = (void *)ALIGN((unsigned long)lp->buffer_start,
* Set DMA buffer to kseg1 (uncached). LAN_SAA9730_PACKET_SIZE);
* Make sure to flush before using it uncached.
*/
Pa = (void *) KSEG1ADDR((buffer_start + LAN_SAA9730_PACKET_SIZE) &
~(LAN_SAA9730_PACKET_SIZE - 1));
dma_cache_wback_inv((unsigned long) Pa, mem_size);
/* Initialize buffer space */ rxoffset = Pa - lp->buffer_start;
RcvBufferSize = LAN_SAA9730_PACKET_SIZE;
TxmBufferSize = LAN_SAA9730_PACKET_SIZE;
lp->DmaRcvPackets = LAN_SAA9730_RCV_Q_SIZE;
lp->DmaTxmPackets = LAN_SAA9730_TXM_Q_SIZE;
/* Init RX buffers */ /* Init RX buffers */
for (i = 0; i < LAN_SAA9730_BUFFERS; i++) { for (i = 0; i < LAN_SAA9730_BUFFERS; i++) {
...@@ -254,19 +266,21 @@ static int lan_saa9730_allocate_buffers(struct lan_saa9730_private *lp) ...@@ -254,19 +266,21 @@ static int lan_saa9730_allocate_buffers(struct lan_saa9730_private *lp)
*(unsigned int *) Pa = *(unsigned int *) Pa =
cpu_to_le32(RXSF_READY << cpu_to_le32(RXSF_READY <<
RX_STAT_CTL_OWNER_SHF); RX_STAT_CTL_OWNER_SHF);
lp->RcvBuffer[i][j] = (unsigned int) Pa; lp->RcvBuffer[i][j] = Pa;
Pa += RcvBufferSize; Pa += LAN_SAA9730_PACKET_SIZE;
} }
} }
txoffset = Pa - lp->buffer_start;
/* Init TX buffers */ /* Init TX buffers */
for (i = 0; i < LAN_SAA9730_BUFFERS; i++) { for (i = 0; i < LAN_SAA9730_BUFFERS; i++) {
for (j = 0; j < LAN_SAA9730_TXM_Q_SIZE; j++) { for (j = 0; j < LAN_SAA9730_TXM_Q_SIZE; j++) {
*(unsigned int *) Pa = *(unsigned int *) Pa =
cpu_to_le32(TXSF_EMPTY << cpu_to_le32(TXSF_EMPTY <<
TX_STAT_CTL_OWNER_SHF); TX_STAT_CTL_OWNER_SHF);
lp->TxmBuffer[i][j] = (unsigned int) Pa; lp->TxmBuffer[i][j] = Pa;
Pa += TxmBufferSize; Pa += LAN_SAA9730_PACKET_SIZE;
} }
} }
...@@ -274,38 +288,33 @@ static int lan_saa9730_allocate_buffers(struct lan_saa9730_private *lp) ...@@ -274,38 +288,33 @@ static int lan_saa9730_allocate_buffers(struct lan_saa9730_private *lp)
* Set rx buffer A and rx buffer B to point to the first two buffer * Set rx buffer A and rx buffer B to point to the first two buffer
* spaces. * spaces.
*/ */
OUTL(PHYSADDR(lp->RcvBuffer[0][0]), outl(lp->dma_addr + rxoffset,
&lp->lan_saa9730_regs->RxBuffA); &lp->lan_saa9730_regs->RxBuffA);
OUTL(PHYSADDR(lp->RcvBuffer[1][0]), outl(lp->dma_addr + rxoffset +
LAN_SAA9730_PACKET_SIZE * LAN_SAA9730_RCV_Q_SIZE,
&lp->lan_saa9730_regs->RxBuffB); &lp->lan_saa9730_regs->RxBuffB);
/* Initialize Buffer Index */
lp->NextRcvPacketIndex = 0;
lp->NextRcvToUseIsA = 1;
/* Set current buffer index & next availble packet index */
lp->NextTxmPacketIndex = 0;
lp->NextTxmBufferIndex = 0;
lp->PendingTxmPacketIndex = 0;
lp->PendingTxmBufferIndex = 0;
/* /*
* Set txm_buf_a and txm_buf_b to point to the first two buffer * Set txm_buf_a and txm_buf_b to point to the first two buffer
* space * space
*/ */
OUTL(PHYSADDR(lp->TxmBuffer[0][0]), outl(lp->dma_addr + txoffset,
&lp->lan_saa9730_regs->TxBuffA); &lp->lan_saa9730_regs->TxBuffA);
OUTL(PHYSADDR(lp->TxmBuffer[1][0]), outl(lp->dma_addr + txoffset +
LAN_SAA9730_PACKET_SIZE * LAN_SAA9730_TXM_Q_SIZE,
&lp->lan_saa9730_regs->TxBuffB); &lp->lan_saa9730_regs->TxBuffB);
/* Set packet number */ /* Set packet number */
OUTL((lp->DmaRcvPackets << PK_COUNT_RX_A_SHF) | outl((lp->DmaRcvPackets << PK_COUNT_RX_A_SHF) |
(lp->DmaRcvPackets << PK_COUNT_RX_B_SHF) | (lp->DmaRcvPackets << PK_COUNT_RX_B_SHF) |
(lp->DmaTxmPackets << PK_COUNT_TX_A_SHF) | (lp->DmaTxmPackets << PK_COUNT_TX_A_SHF) |
(lp->DmaTxmPackets << PK_COUNT_TX_B_SHF), (lp->DmaTxmPackets << PK_COUNT_TX_B_SHF),
&lp->lan_saa9730_regs->PacketCount); &lp->lan_saa9730_regs->PacketCount);
return 0; return 0;
out:
return ret;
} }
static int lan_saa9730_cam_load(struct lan_saa9730_private *lp) static int lan_saa9730_cam_load(struct lan_saa9730_private *lp)
...@@ -317,8 +326,8 @@ static int lan_saa9730_cam_load(struct lan_saa9730_private *lp) ...@@ -317,8 +326,8 @@ static int lan_saa9730_cam_load(struct lan_saa9730_private *lp)
for (i = 0; i < LAN_SAA9730_CAM_DWORDS; i++) { for (i = 0; i < LAN_SAA9730_CAM_DWORDS; i++) {
/* First set address to where data is written */ /* First set address to where data is written */
OUTL(i, &lp->lan_saa9730_regs->CamAddress); outl(i, &lp->lan_saa9730_regs->CamAddress);
OUTL((NetworkAddress[0] << 24) | (NetworkAddress[1] << 16) outl((NetworkAddress[0] << 24) | (NetworkAddress[1] << 16)
| (NetworkAddress[2] << 8) | NetworkAddress[3], | (NetworkAddress[2] << 8) | NetworkAddress[3],
&lp->lan_saa9730_regs->CamData); &lp->lan_saa9730_regs->CamData);
NetworkAddress += 4; NetworkAddress += 4;
...@@ -328,8 +337,7 @@ static int lan_saa9730_cam_load(struct lan_saa9730_private *lp) ...@@ -328,8 +337,7 @@ static int lan_saa9730_cam_load(struct lan_saa9730_private *lp)
static int lan_saa9730_cam_init(struct net_device *dev) static int lan_saa9730_cam_init(struct net_device *dev)
{ {
struct lan_saa9730_private *lp = struct lan_saa9730_private *lp = netdev_priv(dev);
(struct lan_saa9730_private *) dev->priv;
unsigned int i; unsigned int i;
/* Copy MAC-address into all entries. */ /* Copy MAC-address into all entries. */
...@@ -347,7 +355,7 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp) ...@@ -347,7 +355,7 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp)
/* Check link status, spin here till station is not busy. */ /* Check link status, spin here till station is not busy. */
i = 0; i = 0;
while (INL(&lp->lan_saa9730_regs->StationMgmtCtl) & MD_CA_BUSY) { while (readl(&lp->lan_saa9730_regs->StationMgmtCtl) & MD_CA_BUSY) {
i++; i++;
if (i > 100) { if (i > 100) {
printk("Error: lan_saa9730_mii_init: timeout\n"); printk("Error: lan_saa9730_mii_init: timeout\n");
...@@ -357,12 +365,12 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp) ...@@ -357,12 +365,12 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp)
} }
/* Now set the control and address register. */ /* Now set the control and address register. */
OUTL(MD_CA_BUSY | PHY_STATUS | PHY_ADDRESS << MD_CA_PHY_SHF, outl(MD_CA_BUSY | PHY_STATUS | PHY_ADDRESS << MD_CA_PHY_SHF,
&lp->lan_saa9730_regs->StationMgmtCtl); &lp->lan_saa9730_regs->StationMgmtCtl);
/* check link status, spin here till station is not busy */ /* check link status, spin here till station is not busy */
i = 0; i = 0;
while (INL(&lp->lan_saa9730_regs->StationMgmtCtl) & MD_CA_BUSY) { while (readl(&lp->lan_saa9730_regs->StationMgmtCtl) & MD_CA_BUSY) {
i++; i++;
if (i > 100) { if (i > 100) {
printk("Error: lan_saa9730_mii_init: timeout\n"); printk("Error: lan_saa9730_mii_init: timeout\n");
...@@ -375,7 +383,7 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp) ...@@ -375,7 +383,7 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp)
mdelay(1); mdelay(1);
/* Check the link status. */ /* Check the link status. */
if (INL(&lp->lan_saa9730_regs->StationMgmtData) & if (readl(&lp->lan_saa9730_regs->StationMgmtData) &
PHY_STATUS_LINK_UP) { PHY_STATUS_LINK_UP) {
/* Link is up. */ /* Link is up. */
return 0; return 0;
...@@ -383,14 +391,14 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp) ...@@ -383,14 +391,14 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp)
/* Link is down, reset the PHY first. */ /* Link is down, reset the PHY first. */
/* set PHY address = 'CONTROL' */ /* set PHY address = 'CONTROL' */
OUTL(PHY_ADDRESS << MD_CA_PHY_SHF | MD_CA_WR | PHY_CONTROL, outl(PHY_ADDRESS << MD_CA_PHY_SHF | MD_CA_WR | PHY_CONTROL,
&lp->lan_saa9730_regs->StationMgmtCtl); &lp->lan_saa9730_regs->StationMgmtCtl);
/* Wait for 1 ms. */ /* Wait for 1 ms. */
mdelay(1); mdelay(1);
/* set 'CONTROL' = force reset and renegotiate */ /* set 'CONTROL' = force reset and renegotiate */
OUTL(PHY_CONTROL_RESET | PHY_CONTROL_AUTO_NEG | outl(PHY_CONTROL_RESET | PHY_CONTROL_AUTO_NEG |
PHY_CONTROL_RESTART_AUTO_NEG, PHY_CONTROL_RESTART_AUTO_NEG,
&lp->lan_saa9730_regs->StationMgmtData); &lp->lan_saa9730_regs->StationMgmtData);
...@@ -398,12 +406,12 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp) ...@@ -398,12 +406,12 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp)
mdelay(50); mdelay(50);
/* set 'BUSY' to start operation */ /* set 'BUSY' to start operation */
OUTL(MD_CA_BUSY | PHY_ADDRESS << MD_CA_PHY_SHF | MD_CA_WR | outl(MD_CA_BUSY | PHY_ADDRESS << MD_CA_PHY_SHF | MD_CA_WR |
PHY_CONTROL, &lp->lan_saa9730_regs->StationMgmtCtl); PHY_CONTROL, &lp->lan_saa9730_regs->StationMgmtCtl);
/* await completion */ /* await completion */
i = 0; i = 0;
while (INL(&lp->lan_saa9730_regs->StationMgmtCtl) & while (readl(&lp->lan_saa9730_regs->StationMgmtCtl) &
MD_CA_BUSY) { MD_CA_BUSY) {
i++; i++;
if (i > 100) { if (i > 100) {
...@@ -419,13 +427,13 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp) ...@@ -419,13 +427,13 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp)
for (l = 0; l < 2; l++) { for (l = 0; l < 2; l++) {
/* set PHY address = 'STATUS' */ /* set PHY address = 'STATUS' */
OUTL(MD_CA_BUSY | PHY_ADDRESS << MD_CA_PHY_SHF | outl(MD_CA_BUSY | PHY_ADDRESS << MD_CA_PHY_SHF |
PHY_STATUS, PHY_STATUS,
&lp->lan_saa9730_regs->StationMgmtCtl); &lp->lan_saa9730_regs->StationMgmtCtl);
/* await completion */ /* await completion */
i = 0; i = 0;
while (INL(&lp->lan_saa9730_regs->StationMgmtCtl) & while (readl(&lp->lan_saa9730_regs->StationMgmtCtl) &
MD_CA_BUSY) { MD_CA_BUSY) {
i++; i++;
if (i > 100) { if (i > 100) {
...@@ -440,7 +448,7 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp) ...@@ -440,7 +448,7 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp)
mdelay(3000); mdelay(3000);
/* check the link status */ /* check the link status */
if (INL(&lp->lan_saa9730_regs->StationMgmtData) & if (readl(&lp->lan_saa9730_regs->StationMgmtData) &
PHY_STATUS_LINK_UP) { PHY_STATUS_LINK_UP) {
/* link is up */ /* link is up */
break; break;
...@@ -454,7 +462,7 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp) ...@@ -454,7 +462,7 @@ static int lan_saa9730_mii_init(struct lan_saa9730_private *lp)
static int lan_saa9730_control_init(struct lan_saa9730_private *lp) static int lan_saa9730_control_init(struct lan_saa9730_private *lp)
{ {
/* Initialize DMA control register. */ /* Initialize DMA control register. */
OUTL((LANMB_ANY << DMA_CTL_MAX_XFER_SHF) | outl((LANMB_ANY << DMA_CTL_MAX_XFER_SHF) |
(LANEND_LITTLE << DMA_CTL_ENDIAN_SHF) | (LANEND_LITTLE << DMA_CTL_ENDIAN_SHF) |
(LAN_SAA9730_RCV_Q_INT_THRESHOLD << DMA_CTL_RX_INT_COUNT_SHF) (LAN_SAA9730_RCV_Q_INT_THRESHOLD << DMA_CTL_RX_INT_COUNT_SHF)
| DMA_CTL_RX_INT_TO_EN | DMA_CTL_RX_INT_EN | | DMA_CTL_RX_INT_TO_EN | DMA_CTL_RX_INT_EN |
...@@ -462,27 +470,27 @@ static int lan_saa9730_control_init(struct lan_saa9730_private *lp) ...@@ -462,27 +470,27 @@ static int lan_saa9730_control_init(struct lan_saa9730_private *lp)
&lp->lan_saa9730_regs->LanDmaCtl); &lp->lan_saa9730_regs->LanDmaCtl);
/* Initial MAC control register. */ /* Initial MAC control register. */
OUTL((MACCM_MII << MAC_CONTROL_CONN_SHF) | MAC_CONTROL_FULL_DUP, outl((MACCM_MII << MAC_CONTROL_CONN_SHF) | MAC_CONTROL_FULL_DUP,
&lp->lan_saa9730_regs->MacCtl); &lp->lan_saa9730_regs->MacCtl);
/* Initialize CAM control register. */ /* Initialize CAM control register. */
OUTL(CAM_CONTROL_COMP_EN | CAM_CONTROL_BROAD_ACC, outl(CAM_CONTROL_COMP_EN | CAM_CONTROL_BROAD_ACC,
&lp->lan_saa9730_regs->CamCtl); &lp->lan_saa9730_regs->CamCtl);
/* /*
* Initialize CAM enable register, only turn on first entry, should * Initialize CAM enable register, only turn on first entry, should
* contain own addr. * contain own addr.
*/ */
OUTL(0x0001, &lp->lan_saa9730_regs->CamEnable); outl(0x0001, &lp->lan_saa9730_regs->CamEnable);
/* Initialize Tx control register */ /* Initialize Tx control register */
OUTL(TX_CTL_EN_COMP, &lp->lan_saa9730_regs->TxCtl); outl(TX_CTL_EN_COMP, &lp->lan_saa9730_regs->TxCtl);
/* Initialize Rcv control register */ /* Initialize Rcv control register */
OUTL(RX_CTL_STRIP_CRC, &lp->lan_saa9730_regs->RxCtl); outl(RX_CTL_STRIP_CRC, &lp->lan_saa9730_regs->RxCtl);
/* Reset DMA engine */ /* Reset DMA engine */
OUTL(DMA_TEST_SW_RESET, &lp->lan_saa9730_regs->DmaTest); outl(DMA_TEST_SW_RESET, &lp->lan_saa9730_regs->DmaTest);
return 0; return 0;
} }
...@@ -492,13 +500,13 @@ static int lan_saa9730_stop(struct lan_saa9730_private *lp) ...@@ -492,13 +500,13 @@ static int lan_saa9730_stop(struct lan_saa9730_private *lp)
int i; int i;
/* Stop DMA first */ /* Stop DMA first */
OUTL(INL(&lp->lan_saa9730_regs->LanDmaCtl) & outl(readl(&lp->lan_saa9730_regs->LanDmaCtl) &
~(DMA_CTL_EN_TX_DMA | DMA_CTL_EN_RX_DMA), ~(DMA_CTL_EN_TX_DMA | DMA_CTL_EN_RX_DMA),
&lp->lan_saa9730_regs->LanDmaCtl); &lp->lan_saa9730_regs->LanDmaCtl);
/* Set the SW Reset bits in DMA and MAC control registers */ /* Set the SW Reset bits in DMA and MAC control registers */
OUTL(DMA_TEST_SW_RESET, &lp->lan_saa9730_regs->DmaTest); outl(DMA_TEST_SW_RESET, &lp->lan_saa9730_regs->DmaTest);
OUTL(INL(&lp->lan_saa9730_regs->MacCtl) | MAC_CONTROL_RESET, outl(readl(&lp->lan_saa9730_regs->MacCtl) | MAC_CONTROL_RESET,
&lp->lan_saa9730_regs->MacCtl); &lp->lan_saa9730_regs->MacCtl);
/* /*
...@@ -506,7 +514,7 @@ static int lan_saa9730_stop(struct lan_saa9730_private *lp) ...@@ -506,7 +514,7 @@ static int lan_saa9730_stop(struct lan_saa9730_private *lp)
* when the reset is done. * when the reset is done.
*/ */
i = 0; i = 0;
while (INL(&lp->lan_saa9730_regs->MacCtl) & MAC_CONTROL_RESET) { while (readl(&lp->lan_saa9730_regs->MacCtl) & MAC_CONTROL_RESET) {
i++; i++;
if (i > 100) { if (i > 100) {
printk printk
...@@ -524,7 +532,7 @@ static int lan_saa9730_dma_init(struct lan_saa9730_private *lp) ...@@ -524,7 +532,7 @@ static int lan_saa9730_dma_init(struct lan_saa9730_private *lp)
/* Stop lan controller. */ /* Stop lan controller. */
lan_saa9730_stop(lp); lan_saa9730_stop(lp);
OUTL(LAN_SAA9730_DEFAULT_TIME_OUT_CNT, outl(LAN_SAA9730_DEFAULT_TIME_OUT_CNT,
&lp->lan_saa9730_regs->Timeout); &lp->lan_saa9730_regs->Timeout);
return 0; return 0;
...@@ -536,28 +544,27 @@ static int lan_saa9730_start(struct lan_saa9730_private *lp) ...@@ -536,28 +544,27 @@ static int lan_saa9730_start(struct lan_saa9730_private *lp)
/* Initialize Rx Buffer Index */ /* Initialize Rx Buffer Index */
lp->NextRcvPacketIndex = 0; lp->NextRcvPacketIndex = 0;
lp->NextRcvToUseIsA = 1; lp->NextRcvBufferIndex = 0;
/* Set current buffer index & next availble packet index */ /* Set current buffer index & next available packet index */
lp->NextTxmPacketIndex = 0; lp->NextTxmPacketIndex = 0;
lp->NextTxmBufferIndex = 0; lp->NextTxmBufferIndex = 0;
lp->PendingTxmPacketIndex = 0; lp->PendingTxmPacketIndex = 0;
lp->PendingTxmBufferIndex = 0; lp->PendingTxmBufferIndex = 0;
OUTL(INL(&lp->lan_saa9730_regs->LanDmaCtl) | DMA_CTL_EN_TX_DMA | outl(readl(&lp->lan_saa9730_regs->LanDmaCtl) | DMA_CTL_EN_TX_DMA |
DMA_CTL_EN_RX_DMA, &lp->lan_saa9730_regs->LanDmaCtl); DMA_CTL_EN_RX_DMA, &lp->lan_saa9730_regs->LanDmaCtl);
/* For Tx, turn on MAC then DMA */ /* For Tx, turn on MAC then DMA */
OUTL(INL(&lp->lan_saa9730_regs->TxCtl) | TX_CTL_TX_EN, outl(readl(&lp->lan_saa9730_regs->TxCtl) | TX_CTL_TX_EN,
&lp->lan_saa9730_regs->TxCtl); &lp->lan_saa9730_regs->TxCtl);
/* For Rx, turn on DMA then MAC */ /* For Rx, turn on DMA then MAC */
OUTL(INL(&lp->lan_saa9730_regs->RxCtl) | RX_CTL_RX_EN, outl(readl(&lp->lan_saa9730_regs->RxCtl) | RX_CTL_RX_EN,
&lp->lan_saa9730_regs->RxCtl); &lp->lan_saa9730_regs->RxCtl);
/* Set Ok2Use to let hardware owns the buffers */ /* Set Ok2Use to let hardware own the buffers. */
OUTL(OK2USE_RX_A | OK2USE_RX_B | OK2USE_TX_A | OK2USE_TX_B, outl(OK2USE_RX_A | OK2USE_RX_B, &lp->lan_saa9730_regs->Ok2Use);
&lp->lan_saa9730_regs->Ok2Use);
return 0; return 0;
} }
...@@ -572,8 +579,7 @@ static int lan_saa9730_restart(struct lan_saa9730_private *lp) ...@@ -572,8 +579,7 @@ static int lan_saa9730_restart(struct lan_saa9730_private *lp)
static int lan_saa9730_tx(struct net_device *dev) static int lan_saa9730_tx(struct net_device *dev)
{ {
struct lan_saa9730_private *lp = struct lan_saa9730_private *lp = netdev_priv(dev);
(struct lan_saa9730_private *) dev->priv;
unsigned int *pPacket; unsigned int *pPacket;
unsigned int tx_status; unsigned int tx_status;
...@@ -581,12 +587,10 @@ static int lan_saa9730_tx(struct net_device *dev) ...@@ -581,12 +587,10 @@ static int lan_saa9730_tx(struct net_device *dev)
printk("lan_saa9730_tx interrupt\n"); printk("lan_saa9730_tx interrupt\n");
/* Clear interrupt. */ /* Clear interrupt. */
OUTL(DMA_STATUS_MAC_TX_INT, &lp->lan_saa9730_regs->DmaStatus); outl(DMA_STATUS_MAC_TX_INT, &lp->lan_saa9730_regs->DmaStatus);
while (1) { while (1) {
pPacket = pPacket = lp->TxmBuffer[lp->PendingTxmBufferIndex]
(unsigned int *) lp->TxmBuffer[lp->
PendingTxmBufferIndex]
[lp->PendingTxmPacketIndex]; [lp->PendingTxmPacketIndex];
/* Get status of first packet transmitted. */ /* Get status of first packet transmitted. */
...@@ -607,9 +611,8 @@ static int lan_saa9730_tx(struct net_device *dev) ...@@ -607,9 +611,8 @@ static int lan_saa9730_tx(struct net_device *dev)
(TX_STATUS_EX_COLL << TX_STAT_CTL_STATUS_SHF)) (TX_STATUS_EX_COLL << TX_STAT_CTL_STATUS_SHF))
lp->stats.tx_aborted_errors++; lp->stats.tx_aborted_errors++;
if (tx_status & if (tx_status &
(TX_STATUS_LATE_COLL << (TX_STATUS_LATE_COLL << TX_STAT_CTL_STATUS_SHF))
TX_STAT_CTL_STATUS_SHF)) lp->stats. lp->stats.tx_window_errors++;
tx_window_errors++;
if (tx_status & if (tx_status &
(TX_STATUS_L_CARR << TX_STAT_CTL_STATUS_SHF)) (TX_STATUS_L_CARR << TX_STAT_CTL_STATUS_SHF))
lp->stats.tx_carrier_errors++; lp->stats.tx_carrier_errors++;
...@@ -636,21 +639,15 @@ static int lan_saa9730_tx(struct net_device *dev) ...@@ -636,21 +639,15 @@ static int lan_saa9730_tx(struct net_device *dev)
} }
} }
/* Make sure A and B are available to hardware. */
OUTL(OK2USE_TX_A | OK2USE_TX_B, &lp->lan_saa9730_regs->Ok2Use);
if (netif_queue_stopped(dev)) {
/* The tx buffer is no longer full. */ /* The tx buffer is no longer full. */
netif_wake_queue(dev); netif_wake_queue(dev);
}
return 0; return 0;
} }
static int lan_saa9730_rx(struct net_device *dev) static int lan_saa9730_rx(struct net_device *dev)
{ {
struct lan_saa9730_private *lp = struct lan_saa9730_private *lp = netdev_priv(dev);
(struct lan_saa9730_private *) dev->priv;
int len = 0; int len = 0;
struct sk_buff *skb = 0; struct sk_buff *skb = 0;
unsigned int rx_status; unsigned int rx_status;
...@@ -663,16 +660,13 @@ static int lan_saa9730_rx(struct net_device *dev) ...@@ -663,16 +660,13 @@ static int lan_saa9730_rx(struct net_device *dev)
printk("lan_saa9730_rx interrupt\n"); printk("lan_saa9730_rx interrupt\n");
/* Clear receive interrupts. */ /* Clear receive interrupts. */
OUTL(DMA_STATUS_MAC_RX_INT | DMA_STATUS_RX_INT | outl(DMA_STATUS_MAC_RX_INT | DMA_STATUS_RX_INT |
DMA_STATUS_RX_TO_INT, &lp->lan_saa9730_regs->DmaStatus); DMA_STATUS_RX_TO_INT, &lp->lan_saa9730_regs->DmaStatus);
/* Address next packet */ /* Address next packet */
if (lp->NextRcvToUseIsA) BufferIndex = lp->NextRcvBufferIndex;
BufferIndex = 0;
else
BufferIndex = 1;
PacketIndex = lp->NextRcvPacketIndex; PacketIndex = lp->NextRcvPacketIndex;
pPacket = (unsigned int *) lp->RcvBuffer[BufferIndex][PacketIndex]; pPacket = lp->RcvBuffer[BufferIndex][PacketIndex];
rx_status = le32_to_cpu(*pPacket); rx_status = le32_to_cpu(*pPacket);
/* Process each packet. */ /* Process each packet. */
...@@ -717,9 +711,8 @@ static int lan_saa9730_rx(struct net_device *dev) ...@@ -717,9 +711,8 @@ static int lan_saa9730_rx(struct net_device *dev)
(RX_STATUS_CRC_ERR << RX_STAT_CTL_STATUS_SHF)) (RX_STATUS_CRC_ERR << RX_STAT_CTL_STATUS_SHF))
lp->stats.rx_crc_errors++; lp->stats.rx_crc_errors++;
if (rx_status & if (rx_status &
(RX_STATUS_ALIGN_ERR << (RX_STATUS_ALIGN_ERR << RX_STAT_CTL_STATUS_SHF))
RX_STAT_CTL_STATUS_SHF)) lp->stats. lp->stats.rx_frame_errors++;
rx_frame_errors++;
if (rx_status & if (rx_status &
(RX_STATUS_OVERFLOW << RX_STAT_CTL_STATUS_SHF)) (RX_STATUS_OVERFLOW << RX_STAT_CTL_STATUS_SHF))
lp->stats.rx_fifo_errors++; lp->stats.rx_fifo_errors++;
...@@ -729,37 +722,26 @@ static int lan_saa9730_rx(struct net_device *dev) ...@@ -729,37 +722,26 @@ static int lan_saa9730_rx(struct net_device *dev)
} }
/* Indicate we have processed the buffer. */ /* Indicate we have processed the buffer. */
*pPacket = *pPacket = cpu_to_le32(RXSF_READY << RX_STAT_CTL_OWNER_SHF);
cpu_to_le32(RXSF_READY << RX_STAT_CTL_OWNER_SHF);
/* Make sure A or B is available to hardware as appropriate. */
outl(BufferIndex ? OK2USE_RX_B : OK2USE_RX_A,
&lp->lan_saa9730_regs->Ok2Use);
/* Go to next packet in sequence. */ /* Go to next packet in sequence. */
lp->NextRcvPacketIndex++; lp->NextRcvPacketIndex++;
if (lp->NextRcvPacketIndex >= LAN_SAA9730_RCV_Q_SIZE) { if (lp->NextRcvPacketIndex >= LAN_SAA9730_RCV_Q_SIZE) {
lp->NextRcvPacketIndex = 0; lp->NextRcvPacketIndex = 0;
if (BufferIndex) { lp->NextRcvBufferIndex ^= 1;
lp->NextRcvToUseIsA = 1;
} else {
lp->NextRcvToUseIsA = 0;
}
} }
OUTL(OK2USE_RX_A | OK2USE_RX_B,
&lp->lan_saa9730_regs->Ok2Use);
/* Address next packet */ /* Address next packet */
if (lp->NextRcvToUseIsA) BufferIndex = lp->NextRcvBufferIndex;
BufferIndex = 0;
else
BufferIndex = 1;
PacketIndex = lp->NextRcvPacketIndex; PacketIndex = lp->NextRcvPacketIndex;
pPacket = pPacket = lp->RcvBuffer[BufferIndex][PacketIndex];
(unsigned int *) lp->
RcvBuffer[BufferIndex][PacketIndex];
rx_status = le32_to_cpu(*pPacket); rx_status = le32_to_cpu(*pPacket);
} }
/* Make sure A and B are available to hardware. */
OUTL(OK2USE_RX_A | OK2USE_RX_B, &lp->lan_saa9730_regs->Ok2Use);
return 0; return 0;
} }
...@@ -767,8 +749,7 @@ static irqreturn_t lan_saa9730_interrupt(const int irq, void *dev_id, ...@@ -767,8 +749,7 @@ static irqreturn_t lan_saa9730_interrupt(const int irq, void *dev_id,
struct pt_regs *regs) struct pt_regs *regs)
{ {
struct net_device *dev = (struct net_device *) dev_id; struct net_device *dev = (struct net_device *) dev_id;
struct lan_saa9730_private *lp = struct lan_saa9730_private *lp = netdev_priv(dev);
(struct lan_saa9730_private *) dev->priv;
if (lan_saa9730_debug > 5) if (lan_saa9730_debug > 5)
printk("lan_saa9730_interrupt\n"); printk("lan_saa9730_interrupt\n");
...@@ -780,11 +761,11 @@ static irqreturn_t lan_saa9730_interrupt(const int irq, void *dev_id, ...@@ -780,11 +761,11 @@ static irqreturn_t lan_saa9730_interrupt(const int irq, void *dev_id,
evm_saa9730_clear_lan_int(lp); evm_saa9730_clear_lan_int(lp);
/* Service pending transmit interrupts. */ /* Service pending transmit interrupts. */
if (INL(&lp->lan_saa9730_regs->DmaStatus) & DMA_STATUS_MAC_TX_INT) if (readl(&lp->lan_saa9730_regs->DmaStatus) & DMA_STATUS_MAC_TX_INT)
lan_saa9730_tx(dev); lan_saa9730_tx(dev);
/* Service pending receive interrupts. */ /* Service pending receive interrupts. */
if (INL(&lp->lan_saa9730_regs->DmaStatus) & if (readl(&lp->lan_saa9730_regs->DmaStatus) &
(DMA_STATUS_MAC_RX_INT | DMA_STATUS_RX_INT | (DMA_STATUS_MAC_RX_INT | DMA_STATUS_RX_INT |
DMA_STATUS_RX_TO_INT)) lan_saa9730_rx(dev); DMA_STATUS_RX_TO_INT)) lan_saa9730_rx(dev);
...@@ -794,15 +775,9 @@ static irqreturn_t lan_saa9730_interrupt(const int irq, void *dev_id, ...@@ -794,15 +775,9 @@ static irqreturn_t lan_saa9730_interrupt(const int irq, void *dev_id,
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int lan_saa9730_open_fail(struct net_device *dev)
{
return -ENODEV;
}
static int lan_saa9730_open(struct net_device *dev) static int lan_saa9730_open(struct net_device *dev)
{ {
struct lan_saa9730_private *lp = struct lan_saa9730_private *lp = netdev_priv(dev);
(struct lan_saa9730_private *) dev->priv;
/* Associate IRQ with lan_saa9730_interrupt */ /* Associate IRQ with lan_saa9730_interrupt */
if (request_irq(dev->irq, &lan_saa9730_interrupt, 0, "SAA9730 Eth", if (request_irq(dev->irq, &lan_saa9730_interrupt, 0, "SAA9730 Eth",
...@@ -834,15 +809,13 @@ static int lan_saa9730_write(struct lan_saa9730_private *lp, ...@@ -834,15 +809,13 @@ static int lan_saa9730_write(struct lan_saa9730_private *lp,
int PacketIndex; int PacketIndex;
if (lan_saa9730_debug > 5) if (lan_saa9730_debug > 5)
printk("lan_saa9730_write: skb=%08x\n", printk("lan_saa9730_write: skb=%p\n", skb);
(unsigned int) skb);
BufferIndex = lp->NextTxmBufferIndex; BufferIndex = lp->NextTxmBufferIndex;
PacketIndex = lp->NextTxmPacketIndex; PacketIndex = lp->NextTxmPacketIndex;
tx_status = tx_status = le32_to_cpu(*(unsigned int *)lp->TxmBuffer[BufferIndex]
le32_to_cpu(*(unsigned int *) lp-> [PacketIndex]);
TxmBuffer[BufferIndex][PacketIndex]);
if ((tx_status & TX_STAT_CTL_OWNER_MSK) != if ((tx_status & TX_STAT_CTL_OWNER_MSK) !=
(TXSF_EMPTY << TX_STAT_CTL_OWNER_SHF)) { (TXSF_EMPTY << TX_STAT_CTL_OWNER_SHF)) {
if (lan_saa9730_debug > 4) if (lan_saa9730_debug > 4)
...@@ -858,29 +831,29 @@ static int lan_saa9730_write(struct lan_saa9730_private *lp, ...@@ -858,29 +831,29 @@ static int lan_saa9730_write(struct lan_saa9730_private *lp,
lp->NextTxmBufferIndex ^= 1; lp->NextTxmBufferIndex ^= 1;
} }
pbPacketData = pbPacketData = lp->TxmBuffer[BufferIndex][PacketIndex];
(unsigned char *) lp->TxmBuffer[BufferIndex][PacketIndex];
pbPacketData += 4; pbPacketData += 4;
/* copy the bits */ /* copy the bits */
memcpy(pbPacketData, pbData, len); memcpy(pbPacketData, pbData, len);
/* Set transmit status for hardware */ /* Set transmit status for hardware */
*(unsigned int *) lp->TxmBuffer[BufferIndex][PacketIndex] = *(unsigned int *)lp->TxmBuffer[BufferIndex][PacketIndex] =
cpu_to_le32((TXSF_READY << TX_STAT_CTL_OWNER_SHF) | cpu_to_le32((TXSF_READY << TX_STAT_CTL_OWNER_SHF) |
(TX_STAT_CTL_INT_AFTER_TX << TX_STAT_CTL_FRAME_SHF) (TX_STAT_CTL_INT_AFTER_TX <<
| (len << TX_STAT_CTL_LENGTH_SHF)); TX_STAT_CTL_FRAME_SHF) |
(len << TX_STAT_CTL_LENGTH_SHF));
/* Set hardware tx buffer. */ /* Make sure A or B is available to hardware as appropriate. */
OUTL(OK2USE_TX_A | OK2USE_TX_B, &lp->lan_saa9730_regs->Ok2Use); outl(BufferIndex ? OK2USE_TX_B : OK2USE_TX_A,
&lp->lan_saa9730_regs->Ok2Use);
return 0; return 0;
} }
static void lan_saa9730_tx_timeout(struct net_device *dev) static void lan_saa9730_tx_timeout(struct net_device *dev)
{ {
struct lan_saa9730_private *lp = struct lan_saa9730_private *lp = netdev_priv(dev);
(struct lan_saa9730_private *) dev->priv;
/* Transmitter timeout, serious problems */ /* Transmitter timeout, serious problems */
lp->stats.tx_errors++; lp->stats.tx_errors++;
...@@ -889,20 +862,19 @@ static void lan_saa9730_tx_timeout(struct net_device *dev) ...@@ -889,20 +862,19 @@ static void lan_saa9730_tx_timeout(struct net_device *dev)
lan_saa9730_restart(lp); lan_saa9730_restart(lp);
dev->trans_start = jiffies; dev->trans_start = jiffies;
netif_start_queue(dev); netif_wake_queue(dev);
} }
static int lan_saa9730_start_xmit(struct sk_buff *skb, static int lan_saa9730_start_xmit(struct sk_buff *skb,
struct net_device *dev) struct net_device *dev)
{ {
struct lan_saa9730_private *lp = struct lan_saa9730_private *lp = netdev_priv(dev);
(struct lan_saa9730_private *) dev->priv;
unsigned long flags; unsigned long flags;
int skblen; int skblen;
int len; int len;
if (lan_saa9730_debug > 4) if (lan_saa9730_debug > 4)
printk("Send packet: skb=%08x\n", (unsigned int) skb); printk("Send packet: skb=%p\n", skb);
skblen = skb->len; skblen = skb->len;
...@@ -912,8 +884,7 @@ static int lan_saa9730_start_xmit(struct sk_buff *skb, ...@@ -912,8 +884,7 @@ static int lan_saa9730_start_xmit(struct sk_buff *skb,
if (lan_saa9730_write(lp, skb, skblen)) { if (lan_saa9730_write(lp, skb, skblen)) {
spin_unlock_irqrestore(&lp->lock, flags); spin_unlock_irqrestore(&lp->lock, flags);
printk("Error when writing packet to controller: skb=%08x\n", printk("Error when writing packet to controller: skb=%p\n", skb);
(unsigned int) skb);
netif_stop_queue(dev); netif_stop_queue(dev);
return -1; return -1;
} }
...@@ -922,7 +893,7 @@ static int lan_saa9730_start_xmit(struct sk_buff *skb, ...@@ -922,7 +893,7 @@ static int lan_saa9730_start_xmit(struct sk_buff *skb,
lp->stats.tx_packets++; lp->stats.tx_packets++;
dev->trans_start = jiffies; dev->trans_start = jiffies;
netif_start_queue(dev); netif_wake_queue(dev);
dev_kfree_skb(skb); dev_kfree_skb(skb);
spin_unlock_irqrestore(&lp->lock, flags); spin_unlock_irqrestore(&lp->lock, flags);
...@@ -932,8 +903,7 @@ static int lan_saa9730_start_xmit(struct sk_buff *skb, ...@@ -932,8 +903,7 @@ static int lan_saa9730_start_xmit(struct sk_buff *skb,
static int lan_saa9730_close(struct net_device *dev) static int lan_saa9730_close(struct net_device *dev)
{ {
struct lan_saa9730_private *lp = struct lan_saa9730_private *lp = netdev_priv(dev);
(struct lan_saa9730_private *) dev->priv;
if (lan_saa9730_debug > 1) if (lan_saa9730_debug > 1)
printk("lan_saa9730_close:\n"); printk("lan_saa9730_close:\n");
...@@ -955,29 +925,27 @@ static int lan_saa9730_close(struct net_device *dev) ...@@ -955,29 +925,27 @@ static int lan_saa9730_close(struct net_device *dev)
static struct net_device_stats *lan_saa9730_get_stats(struct net_device static struct net_device_stats *lan_saa9730_get_stats(struct net_device
*dev) *dev)
{ {
struct lan_saa9730_private *lp = struct lan_saa9730_private *lp = netdev_priv(dev);
(struct lan_saa9730_private *) dev->priv;
return &lp->stats; return &lp->stats;
} }
static void lan_saa9730_set_multicast(struct net_device *dev) static void lan_saa9730_set_multicast(struct net_device *dev)
{ {
struct lan_saa9730_private *lp = struct lan_saa9730_private *lp = netdev_priv(dev);
(struct lan_saa9730_private *) dev->priv;
/* Stop the controller */ /* Stop the controller */
lan_saa9730_stop(lp); lan_saa9730_stop(lp);
if (dev->flags & IFF_PROMISC) { if (dev->flags & IFF_PROMISC) {
/* accept all packets */ /* accept all packets */
OUTL(CAM_CONTROL_COMP_EN | CAM_CONTROL_STATION_ACC | outl(CAM_CONTROL_COMP_EN | CAM_CONTROL_STATION_ACC |
CAM_CONTROL_GROUP_ACC | CAM_CONTROL_BROAD_ACC, CAM_CONTROL_GROUP_ACC | CAM_CONTROL_BROAD_ACC,
&lp->lan_saa9730_regs->CamCtl); &lp->lan_saa9730_regs->CamCtl);
} else { } else {
if (dev->flags & IFF_ALLMULTI) { if (dev->flags & IFF_ALLMULTI) {
/* accept all multicast packets */ /* accept all multicast packets */
OUTL(CAM_CONTROL_COMP_EN | CAM_CONTROL_GROUP_ACC | outl(CAM_CONTROL_COMP_EN | CAM_CONTROL_GROUP_ACC |
CAM_CONTROL_BROAD_ACC, CAM_CONTROL_BROAD_ACC,
&lp->lan_saa9730_regs->CamCtl); &lp->lan_saa9730_regs->CamCtl);
} else { } else {
...@@ -994,10 +962,13 @@ static void lan_saa9730_set_multicast(struct net_device *dev) ...@@ -994,10 +962,13 @@ static void lan_saa9730_set_multicast(struct net_device *dev)
static void __devexit saa9730_remove_one(struct pci_dev *pdev) static void __devexit saa9730_remove_one(struct pci_dev *pdev)
{ {
struct net_device *dev = pci_get_drvdata(pdev); struct net_device *dev = pci_get_drvdata(pdev);
struct lan_saa9730_private *lp = netdev_priv(dev);
if (dev) { if (dev) {
unregister_netdev(dev); unregister_netdev(dev);
kfree(dev->priv); lan_saa9730_free_buffers(pdev, lp);
iounmap(lp->lan_saa9730_regs);
iounmap(lp->evm_saa9730_regs);
free_netdev(dev); free_netdev(dev);
pci_release_regions(pdev); pci_release_regions(pdev);
pci_disable_device(pdev); pci_disable_device(pdev);
...@@ -1006,75 +977,67 @@ static void __devexit saa9730_remove_one(struct pci_dev *pdev) ...@@ -1006,75 +977,67 @@ static void __devexit saa9730_remove_one(struct pci_dev *pdev)
} }
static int lan_saa9730_init(struct net_device *dev, int ioaddr, int irq) static int lan_saa9730_init(struct net_device *dev, struct pci_dev *pdev,
unsigned long ioaddr, int irq)
{ {
struct lan_saa9730_private *lp; struct lan_saa9730_private *lp = netdev_priv(dev);
unsigned char ethernet_addr[6]; unsigned char ethernet_addr[6];
int ret = 0; int ret;
dev->open = lan_saa9730_open_fail; if (get_ethernet_addr(ethernet_addr)) {
ret = -ENODEV;
if (get_ethernet_addr(ethernet_addr)) goto out;
return -ENODEV; }
memcpy(dev->dev_addr, ethernet_addr, 6); memcpy(dev->dev_addr, ethernet_addr, 6);
dev->base_addr = ioaddr; dev->base_addr = ioaddr;
dev->irq = irq; dev->irq = irq;
/* lp->pci_dev = pdev;
* Make certain the data structures used by the controller are aligned
* and DMAble.
*/
/*
* XXX: that is obviously broken - kfree() won't be happy with us.
*/
lp = (struct lan_saa9730_private *) (((unsigned long)
kmalloc(sizeof(*lp) + 7,
GFP_DMA | GFP_KERNEL)
+ 7) & ~7);
if (!lp)
return -ENOMEM;
dev->priv = lp;
memset(lp, 0, sizeof(*lp));
/* Set SAA9730 LAN base address. */ /* Set SAA9730 LAN base address. */
lp->lan_saa9730_regs = (t_lan_saa9730_regmap *) (ioaddr + lp->lan_saa9730_regs = ioremap(ioaddr + SAA9730_LAN_REGS_ADDR,
SAA9730_LAN_REGS_ADDR); SAA9730_LAN_REGS_SIZE);
if (!lp->lan_saa9730_regs) {
ret = -ENOMEM;
goto out;
}
/* Set SAA9730 EVM base address. */ /* Set SAA9730 EVM base address. */
lp->evm_saa9730_regs = (t_evm_saa9730_regmap *) (ioaddr + lp->evm_saa9730_regs = ioremap(ioaddr + SAA9730_EVM_REGS_ADDR,
SAA9730_EVM_REGS_ADDR); SAA9730_EVM_REGS_SIZE);
if (!lp->evm_saa9730_regs) {
ret = -ENOMEM;
goto out_iounmap_lan;
}
/* Allocate LAN RX/TX frame buffer space. */ /* Allocate LAN RX/TX frame buffer space. */
/* FIXME: a leak */ if ((ret = lan_saa9730_allocate_buffers(pdev, lp)))
if ((ret = lan_saa9730_allocate_buffers(lp))) goto out_iounmap;
goto out;
/* Stop LAN controller. */ /* Stop LAN controller. */
if ((ret = lan_saa9730_stop(lp))) if ((ret = lan_saa9730_stop(lp)))
goto out; goto out_free_consistent;
/* Initialize CAM registers. */ /* Initialize CAM registers. */
if ((ret = lan_saa9730_cam_init(dev))) if ((ret = lan_saa9730_cam_init(dev)))
goto out; goto out_free_consistent;
/* Initialize MII registers. */ /* Initialize MII registers. */
if ((ret = lan_saa9730_mii_init(lp))) if ((ret = lan_saa9730_mii_init(lp)))
goto out; goto out_free_consistent;
/* Initialize control registers. */ /* Initialize control registers. */
if ((ret = lan_saa9730_control_init(lp))) if ((ret = lan_saa9730_control_init(lp)))
goto out; goto out_free_consistent;
/* Load CAM registers. */ /* Load CAM registers. */
if ((ret = lan_saa9730_cam_load(lp))) if ((ret = lan_saa9730_cam_load(lp)))
goto out; goto out_free_consistent;
/* Initialize DMA context registers. */ /* Initialize DMA context registers. */
if ((ret = lan_saa9730_dma_init(lp))) if ((ret = lan_saa9730_dma_init(lp)))
goto out; goto out_free_consistent;
spin_lock_init(&lp->lock); spin_lock_init(&lp->lock);
...@@ -1087,43 +1050,42 @@ static int lan_saa9730_init(struct net_device *dev, int ioaddr, int irq) ...@@ -1087,43 +1050,42 @@ static int lan_saa9730_init(struct net_device *dev, int ioaddr, int irq)
dev->watchdog_timeo = (HZ >> 1); dev->watchdog_timeo = (HZ >> 1);
dev->dma = 0; dev->dma = 0;
ret = register_netdev(dev); ret = register_netdev (dev);
if (ret) if (ret)
goto out; goto out_free_consistent;
return 0; return 0;
out: out_free_consistent:
kfree(dev->priv); lan_saa9730_free_buffers(pdev, lp);
out_iounmap:
iounmap(lp->evm_saa9730_regs);
out_iounmap_lan:
iounmap(lp->lan_saa9730_regs);
out:
return ret; return ret;
} }
static int __devinit saa9730_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) static int __devinit saa9730_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{ {
struct net_device *dev; struct net_device *dev = NULL;
unsigned int pci_ioaddr; unsigned long pci_ioaddr;
int err; int err;
if (lan_saa9730_debug > 1) if (lan_saa9730_debug > 1)
printk("saa9730.c: PCI bios is present, checking for devices...\n"); printk("saa9730.c: PCI bios is present, checking for devices...\n");
err = -ENOMEM;
dev = alloc_etherdev(0);
if (!dev)
goto out;
SET_MODULE_OWNER(dev);
err = pci_enable_device(pdev); err = pci_enable_device(pdev);
if (err) { if (err) {
printk(KERN_ERR "Cannot enable PCI device, aborting.\n"); printk(KERN_ERR "Cannot enable PCI device, aborting.\n");
goto out1; goto out;
} }
err = pci_request_regions(pdev, DRV_MODULE_NAME); err = pci_request_regions(pdev, DRV_MODULE_NAME);
if (err) { if (err) {
printk(KERN_ERR "Cannot obtain PCI resources, aborting.\n"); printk(KERN_ERR "Cannot obtain PCI resources, aborting.\n");
goto out2; goto out_disable_pdev;
} }
pci_irq_line = pdev->irq; pci_irq_line = pdev->irq;
...@@ -1132,24 +1094,29 @@ static int __devinit saa9730_init_one(struct pci_dev *pdev, const struct pci_dev ...@@ -1132,24 +1094,29 @@ static int __devinit saa9730_init_one(struct pci_dev *pdev, const struct pci_dev
pci_ioaddr = pci_resource_start(pdev, 1); pci_ioaddr = pci_resource_start(pdev, 1);
pci_set_master(pdev); pci_set_master(pdev);
printk("Found SAA9730 (PCI) at %#x, irq %d.\n", printk("Found SAA9730 (PCI) at %lx, irq %d.\n",
pci_ioaddr, pci_irq_line); pci_ioaddr, pci_irq_line);
err = lan_saa9730_init(dev, pci_ioaddr, pci_irq_line); dev = alloc_etherdev(sizeof(struct lan_saa9730_private));
if (!dev)
goto out_disable_pdev;
err = lan_saa9730_init(dev, pdev, pci_ioaddr, pci_irq_line);
if (err) { if (err) {
printk("Lan init failed"); printk("LAN init failed");
goto out2; goto out_free_netdev;
} }
pci_set_drvdata(pdev, dev); pci_set_drvdata(pdev, dev);
SET_NETDEV_DEV(dev, &pdev->dev); SET_NETDEV_DEV(dev, &pdev->dev);
return 0; return 0;
out2: out_free_netdev:
pci_disable_device(pdev);
out1:
free_netdev(dev); free_netdev(dev);
out_disable_pdev:
pci_disable_device(pdev);
out: out:
pci_set_drvdata(pdev, NULL);
return err; return err;
} }
...@@ -1175,6 +1142,6 @@ static void __exit saa9730_cleanup(void) ...@@ -1175,6 +1142,6 @@ static void __exit saa9730_cleanup(void)
module_init(saa9730_init); module_init(saa9730_init);
module_exit(saa9730_cleanup); module_exit(saa9730_cleanup);
MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
MODULE_DESCRIPTION("Philips SAA9730 ethernet driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -289,6 +289,38 @@ static inline void SMC_outsw (unsigned long a, int r, unsigned char* p, int l) ...@@ -289,6 +289,38 @@ static inline void SMC_outsw (unsigned long a, int r, unsigned char* p, int l)
#define RPC_LSA_DEFAULT RPC_LED_TX_RX #define RPC_LSA_DEFAULT RPC_LED_TX_RX
#define RPC_LSB_DEFAULT RPC_LED_100_10 #define RPC_LSB_DEFAULT RPC_LED_100_10
#elif defined(CONFIG_SOC_AU1X00)
#include <au1xxx.h>
/* We can only do 16-bit reads and writes in the static memory space. */
#define SMC_CAN_USE_8BIT 0
#define SMC_CAN_USE_16BIT 1
#define SMC_CAN_USE_32BIT 0
#define SMC_IO_SHIFT 0
#define SMC_NOWAIT 1
#define SMC_inw(a, r) au_readw((unsigned long)((a) + (r)))
#define SMC_insw(a, r, p, l) \
do { \
unsigned long _a = (unsigned long)((a) + (r)); \
int _l = (l); \
u16 *_p = (u16 *)(p); \
while (_l-- > 0) \
*_p++ = au_readw(_a); \
} while(0)
#define SMC_outw(v, a, r) au_writew(v, (unsigned long)((a) + (r)))
#define SMC_outsw(a, r, p, l) \
do { \
unsigned long _a = (unsigned long)((a) + (r)); \
int _l = (l); \
const u16 *_p = (const u16 *)(p); \
while (_l-- > 0) \
au_writew(*_p++ , _a); \
} while(0)
#define set_irq_type(irq, type) do {} while (0)
#else #else
#define SMC_CAN_USE_8BIT 1 #define SMC_CAN_USE_8BIT 1
......
...@@ -330,7 +330,7 @@ config PCI_HERMES ...@@ -330,7 +330,7 @@ config PCI_HERMES
config ATMEL config ATMEL
tristate "Atmel at76c50x chipset 802.11b support" tristate "Atmel at76c50x chipset 802.11b support"
depends on NET_RADIO && EXPERIMENTAL depends on NET_RADIO
select FW_LOADER select FW_LOADER
select CRC32 select CRC32
---help--- ---help---
......
...@@ -72,7 +72,7 @@ ...@@ -72,7 +72,7 @@
#include "atmel.h" #include "atmel.h"
#define DRIVER_MAJOR 0 #define DRIVER_MAJOR 0
#define DRIVER_MINOR 96 #define DRIVER_MINOR 98
MODULE_AUTHOR("Simon Kelley"); MODULE_AUTHOR("Simon Kelley");
MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards."); MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards.");
...@@ -1504,7 +1504,7 @@ static int atmel_read_proc(char *page, char **start, off_t off, ...@@ -1504,7 +1504,7 @@ static int atmel_read_proc(char *page, char **start, off_t off,
return len; return len;
} }
struct net_device *init_atmel_card( unsigned short irq, int port, const AtmelFWType fw_type, struct net_device *init_atmel_card( unsigned short irq, unsigned long port, const AtmelFWType fw_type,
struct device *sys_dev, int (*card_present)(void *), void *card) struct device *sys_dev, int (*card_present)(void *), void *card)
{ {
struct net_device *dev; struct net_device *dev;
...@@ -1605,8 +1605,8 @@ struct net_device *init_atmel_card( unsigned short irq, int port, const AtmelFWT ...@@ -1605,8 +1605,8 @@ struct net_device *init_atmel_card( unsigned short irq, int port, const AtmelFWT
goto err_out_free; goto err_out_free;
} }
if (priv->bus_type == BUS_TYPE_PCI && if (!request_region(dev->base_addr, 32,
!request_region( dev->base_addr, 64, dev->name )) { priv->bus_type == BUS_TYPE_PCCARD ? "atmel_cs" : "atmel_pci")) {
goto err_out_irq; goto err_out_irq;
} }
...@@ -1622,15 +1622,16 @@ struct net_device *init_atmel_card( unsigned short irq, int port, const AtmelFWT ...@@ -1622,15 +1622,16 @@ struct net_device *init_atmel_card( unsigned short irq, int port, const AtmelFWT
create_proc_read_entry ("driver/atmel", 0, NULL, atmel_read_proc, priv); create_proc_read_entry ("driver/atmel", 0, NULL, atmel_read_proc, priv);
printk(KERN_INFO "%s: Atmel at76c50x wireless. Version %d.%d simon@thekelleys.org.uk\n", printk(KERN_INFO "%s: Atmel at76c50x. Version %d.%d. MAC %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
dev->name, DRIVER_MAJOR, DRIVER_MINOR); dev->name, DRIVER_MAJOR, DRIVER_MINOR,
dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5] );
SET_MODULE_OWNER(dev); SET_MODULE_OWNER(dev);
return dev; return dev;
err_out_res: err_out_res:
if (priv->bus_type == BUS_TYPE_PCI) release_region( dev->base_addr, 32);
release_region( dev->base_addr, 64 );
err_out_irq: err_out_irq:
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
err_out_free: err_out_free:
...@@ -1640,7 +1641,7 @@ struct net_device *init_atmel_card( unsigned short irq, int port, const AtmelFWT ...@@ -1640,7 +1641,7 @@ struct net_device *init_atmel_card( unsigned short irq, int port, const AtmelFWT
EXPORT_SYMBOL(init_atmel_card); EXPORT_SYMBOL(init_atmel_card);
void stop_atmel_card(struct net_device *dev, int freeres) void stop_atmel_card(struct net_device *dev)
{ {
struct atmel_private *priv = netdev_priv(dev); struct atmel_private *priv = netdev_priv(dev);
...@@ -1654,10 +1655,7 @@ void stop_atmel_card(struct net_device *dev, int freeres) ...@@ -1654,10 +1655,7 @@ void stop_atmel_card(struct net_device *dev, int freeres)
remove_proc_entry("driver/atmel", NULL); remove_proc_entry("driver/atmel", NULL);
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
kfree(priv->firmware); kfree(priv->firmware);
if (freeres) { release_region(dev->base_addr, 32);
/* PCMCIA frees this stuff, so only for PCI */
release_region(dev->base_addr, 64);
}
free_netdev(dev); free_netdev(dev);
} }
...@@ -1827,11 +1825,12 @@ static int atmel_get_encode(struct net_device *dev, ...@@ -1827,11 +1825,12 @@ static int atmel_get_encode(struct net_device *dev,
if (!priv->wep_is_on) if (!priv->wep_is_on)
dwrq->flags = IW_ENCODE_DISABLED; dwrq->flags = IW_ENCODE_DISABLED;
else if (priv->exclude_unencrypted) else {
if (priv->exclude_unencrypted)
dwrq->flags = IW_ENCODE_RESTRICTED; dwrq->flags = IW_ENCODE_RESTRICTED;
else else
dwrq->flags = IW_ENCODE_OPEN; dwrq->flags = IW_ENCODE_OPEN;
}
/* Which key do we want ? -1 -> tx index */ /* Which key do we want ? -1 -> tx index */
if (index < 0 || index >= 4) if (index < 0 || index >= 4)
index = priv->default_key; index = priv->default_key;
...@@ -2646,7 +2645,7 @@ static void handle_beacon_probe(struct atmel_private *priv, u16 capability, u8 c ...@@ -2646,7 +2645,7 @@ static void handle_beacon_probe(struct atmel_private *priv, u16 capability, u8 c
} }
static void send_authentication_request(struct atmel_private *priv, u8 *challenge, int challenge_len) static void send_authentication_request(struct atmel_private *priv, u16 system, u8 *challenge, int challenge_len)
{ {
struct ieee80211_hdr_4addr header; struct ieee80211_hdr_4addr header;
struct auth_body auth; struct auth_body auth;
...@@ -2658,14 +2657,11 @@ static void send_authentication_request(struct atmel_private *priv, u8 *challeng ...@@ -2658,14 +2657,11 @@ static void send_authentication_request(struct atmel_private *priv, u8 *challeng
memcpy(header.addr2, priv->dev->dev_addr, 6); memcpy(header.addr2, priv->dev->dev_addr, 6);
memcpy(header.addr3, priv->CurrentBSSID, 6); memcpy(header.addr3, priv->CurrentBSSID, 6);
if (priv->wep_is_on) { if (priv->wep_is_on && priv->CurrentAuthentTransactionSeqNum != 1)
auth.alg = cpu_to_le16(C80211_MGMT_AAN_SHAREDKEY);
/* no WEP for authentication frames with TrSeqNo 1 */ /* no WEP for authentication frames with TrSeqNo 1 */
if (priv->CurrentAuthentTransactionSeqNum != 1)
header.frame_ctl |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); header.frame_ctl |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
} else {
auth.alg = cpu_to_le16(C80211_MGMT_AAN_OPENSYSTEM); auth.alg = cpu_to_le16(system);
}
auth.status = 0; auth.status = 0;
auth.trans_seq = cpu_to_le16(priv->CurrentAuthentTransactionSeqNum); auth.trans_seq = cpu_to_le16(priv->CurrentAuthentTransactionSeqNum);
...@@ -2834,6 +2830,7 @@ static void authenticate(struct atmel_private *priv, u16 frame_len) ...@@ -2834,6 +2830,7 @@ static void authenticate(struct atmel_private *priv, u16 frame_len)
struct auth_body *auth = (struct auth_body *)priv->rx_buf; struct auth_body *auth = (struct auth_body *)priv->rx_buf;
u16 status = le16_to_cpu(auth->status); u16 status = le16_to_cpu(auth->status);
u16 trans_seq_no = le16_to_cpu(auth->trans_seq); u16 trans_seq_no = le16_to_cpu(auth->trans_seq);
u16 system = le16_to_cpu(auth->alg);
if (status == C80211_MGMT_SC_Success && !priv->wep_is_on) { if (status == C80211_MGMT_SC_Success && !priv->wep_is_on) {
/* no WEP */ /* no WEP */
...@@ -2855,7 +2852,7 @@ static void authenticate(struct atmel_private *priv, u16 frame_len) ...@@ -2855,7 +2852,7 @@ static void authenticate(struct atmel_private *priv, u16 frame_len)
if (trans_seq_no == 0x0002 && if (trans_seq_no == 0x0002 &&
auth->el_id == C80211_MGMT_ElementID_ChallengeText) { auth->el_id == C80211_MGMT_ElementID_ChallengeText) {
send_authentication_request(priv, auth->chall_text, auth->chall_text_len); send_authentication_request(priv, system, auth->chall_text, auth->chall_text_len);
return; return;
} }
...@@ -2872,7 +2869,12 @@ static void authenticate(struct atmel_private *priv, u16 frame_len) ...@@ -2872,7 +2869,12 @@ static void authenticate(struct atmel_private *priv, u16 frame_len)
} }
} }
if (status == C80211_MGMT_SC_AuthAlgNotSupported && priv->connect_to_any_BSS) { if (status == C80211_MGMT_SC_AuthAlgNotSupported) {
/* Do opensystem first, then try sharedkey */
if (system == C80211_MGMT_AAN_OPENSYSTEM) {
priv->CurrentAuthentTransactionSeqNum = 0x001;
send_authentication_request(priv, C80211_MGMT_AAN_SHAREDKEY, NULL, 0);
} else if (priv->connect_to_any_BSS) {
int bss_index; int bss_index;
priv->BSSinfo[(int)(priv->current_BSS)].channel |= 0x80; priv->BSSinfo[(int)(priv->current_BSS)].channel |= 0x80;
...@@ -2882,6 +2884,7 @@ static void authenticate(struct atmel_private *priv, u16 frame_len) ...@@ -2882,6 +2884,7 @@ static void authenticate(struct atmel_private *priv, u16 frame_len)
return; return;
} }
} }
}
priv->AuthenticationRequestRetryCnt = 0; priv->AuthenticationRequestRetryCnt = 0;
...@@ -3205,7 +3208,7 @@ static void atmel_management_timer(u_long a) ...@@ -3205,7 +3208,7 @@ static void atmel_management_timer(u_long a)
priv->AuthenticationRequestRetryCnt++; priv->AuthenticationRequestRetryCnt++;
priv->CurrentAuthentTransactionSeqNum = 0x0001; priv->CurrentAuthentTransactionSeqNum = 0x0001;
mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES); mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
send_authentication_request(priv, NULL, 0); send_authentication_request(priv, C80211_MGMT_AAN_OPENSYSTEM, NULL, 0);
} }
break; break;
...@@ -3312,7 +3315,7 @@ static void atmel_command_irq(struct atmel_private *priv) ...@@ -3312,7 +3315,7 @@ static void atmel_command_irq(struct atmel_private *priv)
mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES); mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
priv->CurrentAuthentTransactionSeqNum = 0x0001; priv->CurrentAuthentTransactionSeqNum = 0x0001;
send_authentication_request(priv, NULL, 0); send_authentication_request(priv, C80211_MGMT_AAN_SHAREDKEY, NULL, 0);
} }
return; return;
} }
...@@ -3482,11 +3485,6 @@ static int probe_atmel_card(struct net_device *dev) ...@@ -3482,11 +3485,6 @@ static int probe_atmel_card(struct net_device *dev)
printk(KERN_ALERT "%s: *** Invalid MAC address. UPGRADE Firmware ****\n", dev->name); printk(KERN_ALERT "%s: *** Invalid MAC address. UPGRADE Firmware ****\n", dev->name);
memcpy(dev->dev_addr, default_mac, 6); memcpy(dev->dev_addr, default_mac, 6);
} }
printk(KERN_INFO "%s: MAC address %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
dev->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] );
} }
return rc; return rc;
......
...@@ -35,9 +35,9 @@ typedef enum { ...@@ -35,9 +35,9 @@ typedef enum {
ATMEL_FW_TYPE_506 ATMEL_FW_TYPE_506
} AtmelFWType; } AtmelFWType;
struct net_device *init_atmel_card(unsigned short, int, const AtmelFWType, struct device *, struct net_device *init_atmel_card(unsigned short, unsigned long, const AtmelFWType, struct device *,
int (*present_func)(void *), void * ); int (*present_func)(void *), void * );
void stop_atmel_card( struct net_device *, int ); void stop_atmel_card( struct net_device *);
int atmel_open( struct net_device * ); int atmel_open( struct net_device * );
#endif #endif
...@@ -63,6 +63,7 @@ ...@@ -63,6 +63,7 @@
be present but disabled -- but it can then be enabled for specific be present but disabled -- but it can then be enabled for specific
modules at load time with a 'pc_debug=#' option to insmod. modules at load time with a 'pc_debug=#' option to insmod.
*/ */
#ifdef PCMCIA_DEBUG #ifdef PCMCIA_DEBUG
static int pc_debug = PCMCIA_DEBUG; static int pc_debug = PCMCIA_DEBUG;
module_param(pc_debug, int, 0); module_param(pc_debug, int, 0);
...@@ -285,41 +286,6 @@ static int card_present(void *arg) ...@@ -285,41 +286,6 @@ static int card_present(void *arg)
return 0; return 0;
} }
/* list of cards we know about and their firmware requirements.
Go either by Manfid or version strings.
Cards not in this list will need a firmware parameter to the module
in all probability. Note that the SMC 2632 V2 and V3 have the same
manfids, so we ignore those and use the version1 strings. */
static struct {
int manf, card;
char *ver1;
AtmelFWType firmware;
char *name;
} card_table[] = {
{ 0, 0, "WLAN/802.11b PC CARD", ATMEL_FW_TYPE_502D, "Actiontec 802CAT1" },
{ 0, 0, "ATMEL/AT76C502AR", ATMEL_FW_TYPE_502, "NoName-RFMD" },
{ 0, 0, "ATMEL/AT76C502AR_D", ATMEL_FW_TYPE_502D, "NoName-revD" },
{ 0, 0, "ATMEL/AT76C502AR_E", ATMEL_FW_TYPE_502E, "NoName-revE" },
{ 0, 0, "ATMEL/AT76C504", ATMEL_FW_TYPE_504, "NoName-504" },
{ 0, 0, "ATMEL/AT76C504A", ATMEL_FW_TYPE_504A_2958, "NoName-504a-2958" },
{ 0, 0, "ATMEL/AT76C504_R", ATMEL_FW_TYPE_504_2958, "NoName-504-2958" },
{ MANFID_3COM, 0x0620, NULL, ATMEL_FW_TYPE_502_3COM, "3com 3CRWE62092B" },
{ MANFID_3COM, 0x0696, NULL, ATMEL_FW_TYPE_502_3COM, "3com 3CRSHPW196" },
{ 0, 0, "SMC/2632W-V2", ATMEL_FW_TYPE_502, "SMC 2632W-V2" },
{ 0, 0, "SMC/2632W", ATMEL_FW_TYPE_502D, "SMC 2632W-V3" },
{ 0xd601, 0x0007, NULL, ATMEL_FW_TYPE_502, "Sitecom WLAN-011" },
{ 0x01bf, 0x3302, NULL, ATMEL_FW_TYPE_502E, "Belkin F5D6020-V2" },
{ 0, 0, "BT/Voyager 1020 Laptop Adapter", ATMEL_FW_TYPE_502, "BT Voyager 1020" },
{ 0, 0, "IEEE 802.11b/Wireless LAN PC Card", ATMEL_FW_TYPE_502, "Siemens Gigaset PC Card II" },
{ 0, 0, "IEEE 802.11b/Wireless LAN Card S", ATMEL_FW_TYPE_504_2958, "Siemens Gigaset PC Card II" },
{ 0, 0, "CNet/CNWLC 11Mbps Wireless PC Card V-5", ATMEL_FW_TYPE_502E, "CNet CNWLC-811ARL" },
{ 0, 0, "Wireless/PC_CARD", ATMEL_FW_TYPE_502D, "Planet WL-3552" },
{ 0, 0, "OEM/11Mbps Wireless LAN PC Card V-3", ATMEL_FW_TYPE_502, "OEM 11Mbps WLAN PCMCIA Card" },
{ 0, 0, "11WAVE/11WP611AL-E", ATMEL_FW_TYPE_502E, "11WAVE WaveBuddy" },
{ 0, 0, "LG/LW2100N", ATMEL_FW_TYPE_502E, "LG LW2100N 11Mbps WLAN PCMCIA Card" },
};
static void atmel_config(dev_link_t *link) static void atmel_config(dev_link_t *link)
{ {
client_handle_t handle; client_handle_t handle;
...@@ -328,10 +294,11 @@ static void atmel_config(dev_link_t *link) ...@@ -328,10 +294,11 @@ static void atmel_config(dev_link_t *link)
local_info_t *dev; local_info_t *dev;
int last_fn, last_ret; int last_fn, last_ret;
u_char buf[64]; u_char buf[64];
int card_index = -1, done = 0; struct pcmcia_device_id *did;
handle = link->handle; handle = link->handle;
dev = link->priv; dev = link->priv;
did = handle_to_dev(handle).driver_data;
DEBUG(0, "atmel_config(0x%p)\n", link); DEBUG(0, "atmel_config(0x%p)\n", link);
...@@ -340,59 +307,6 @@ static void atmel_config(dev_link_t *link) ...@@ -340,59 +307,6 @@ static void atmel_config(dev_link_t *link)
tuple.TupleDataMax = sizeof(buf); tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0; tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_MANFID;
if (pcmcia_get_first_tuple(handle, &tuple) == 0) {
int i;
cistpl_manfid_t *manfid;
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
manfid = &(parse.manfid);
for (i = 0; i < sizeof(card_table)/sizeof(card_table[0]); i++) {
if (!card_table[i].ver1 &&
manfid->manf == card_table[i].manf &&
manfid->card == card_table[i].card) {
card_index = i;
done = 1;
}
}
}
tuple.DesiredTuple = CISTPL_VERS_1;
if (!done && (pcmcia_get_first_tuple(handle, &tuple) == 0)) {
int i, j, k;
cistpl_vers_1_t *ver1;
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
ver1 = &(parse.version_1);
for (i = 0; i < sizeof(card_table)/sizeof(card_table[0]); i++) {
for (j = 0; j < ver1->ns; j++) {
char *p = card_table[i].ver1;
char *q = &ver1->str[ver1->ofs[j]];
if (!p)
goto mismatch;
for (k = 0; k < j; k++) {
while ((*p != '\0') && (*p != '/')) p++;
if (*p == '\0') {
if (*q != '\0')
goto mismatch;
} else {
p++;
}
}
while((*q != '\0') && (*p != '\0') &&
(*p != '/') && (*p == *q)) p++, q++;
if (((*p != '\0') && *p != '/') || *q != '\0')
goto mismatch;
}
card_index = i;
break; /* done */
mismatch:
j = 0; /* dummy stmt to shut up compiler */
}
}
/* /*
This reads the card's CONFIG tuple to find its configuration This reads the card's CONFIG tuple to find its configuration
registers. registers.
...@@ -509,13 +423,14 @@ static void atmel_config(dev_link_t *link) ...@@ -509,13 +423,14 @@ static void atmel_config(dev_link_t *link)
((local_info_t*)link->priv)->eth_dev = ((local_info_t*)link->priv)->eth_dev =
init_atmel_card(link->irq.AssignedIRQ, init_atmel_card(link->irq.AssignedIRQ,
link->io.BasePort1, link->io.BasePort1,
card_index == -1 ? ATMEL_FW_TYPE_NONE : card_table[card_index].firmware, did ? did->driver_info : ATMEL_FW_TYPE_NONE,
&handle_to_dev(handle), &handle_to_dev(handle),
card_present, card_present,
link); link);
if (!((local_info_t*)link->priv)->eth_dev) if (!((local_info_t*)link->priv)->eth_dev)
goto cs_failed; goto cs_failed;
/* /*
At this point, the dev_node_t structure(s) need to be At this point, the dev_node_t structure(s) need to be
initialized and arranged in a linked list at link->dev. initialized and arranged in a linked list at link->dev.
...@@ -524,25 +439,6 @@ static void atmel_config(dev_link_t *link) ...@@ -524,25 +439,6 @@ static void atmel_config(dev_link_t *link)
dev->node.major = dev->node.minor = 0; dev->node.major = dev->node.minor = 0;
link->dev = &dev->node; link->dev = &dev->node;
/* Finally, report what we've done */
printk(KERN_INFO "%s: %s%sindex 0x%02x: Vcc %d.%d",
dev->node.dev_name,
card_index == -1 ? "" : card_table[card_index].name,
card_index == -1 ? "" : " ",
link->conf.ConfigIndex,
link->conf.Vcc/10, link->conf.Vcc%10);
if (link->conf.Vpp1)
printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
if (link->conf.Attributes & CONF_ENABLE_IRQ)
printk(", irq %d", link->irq.AssignedIRQ);
if (link->io.NumPorts1)
printk(", io 0x%04x-0x%04x", link->io.BasePort1,
link->io.BasePort1+link->io.NumPorts1-1);
if (link->io.NumPorts2)
printk(" & 0x%04x-0x%04x", link->io.BasePort2,
link->io.BasePort2+link->io.NumPorts2-1);
printk("\n");
link->state &= ~DEV_CONFIG_PENDING; link->state &= ~DEV_CONFIG_PENDING;
return; return;
...@@ -569,7 +465,7 @@ static void atmel_release(dev_link_t *link) ...@@ -569,7 +465,7 @@ static void atmel_release(dev_link_t *link)
link->dev = NULL; link->dev = NULL;
if (dev) if (dev)
stop_atmel_card(dev, 0); stop_atmel_card(dev);
((local_info_t*)link->priv)->eth_dev = NULL; ((local_info_t*)link->priv)->eth_dev = NULL;
/* Don't bother checking to see if these succeed or not */ /* Don't bother checking to see if these succeed or not */
...@@ -637,25 +533,47 @@ static int atmel_event(event_t event, int priority, ...@@ -637,25 +533,47 @@ static int atmel_event(event_t event, int priority,
} /* atmel_event */ } /* atmel_event */
/*====================================================================*/ /*====================================================================*/
/* We use the driver_info field to store the correct firmware type for a card. */
#define PCMCIA_DEVICE_MANF_CARD_INFO(manf, card, info) { \
.match_flags = PCMCIA_DEV_ID_MATCH_MANF_ID| \
PCMCIA_DEV_ID_MATCH_CARD_ID, \
.manf_id = (manf), \
.card_id = (card), \
.driver_info = (kernel_ulong_t)(info), }
#define PCMCIA_DEVICE_PROD_ID12_INFO(v1, v2, vh1, vh2, info) { \
.match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \
PCMCIA_DEV_ID_MATCH_PROD_ID2, \
.prod_id = { (v1), (v2), NULL, NULL }, \
.prod_id_hash = { (vh1), (vh2), 0, 0 }, \
.driver_info = (kernel_ulong_t)(info), }
static struct pcmcia_device_id atmel_ids[] = { static struct pcmcia_device_id atmel_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0620), PCMCIA_DEVICE_MANF_CARD_INFO(0x0101, 0x0620, ATMEL_FW_TYPE_502_3COM),
PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0696), PCMCIA_DEVICE_MANF_CARD_INFO(0x0101, 0x0696, ATMEL_FW_TYPE_502_3COM),
PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x3302), PCMCIA_DEVICE_MANF_CARD_INFO(0x01bf, 0x3302, ATMEL_FW_TYPE_502E),
PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0007), PCMCIA_DEVICE_MANF_CARD_INFO(0xd601, 0x0007, ATMEL_FW_TYPE_502),
PCMCIA_DEVICE_PROD_ID12("11WAVE", "11WP611AL-E", 0x9eb2da1f, 0xc9a0d3f9), PCMCIA_DEVICE_PROD_ID12_INFO("11WAVE", "11WP611AL-E", 0x9eb2da1f, 0xc9a0d3f9, ATMEL_FW_TYPE_502E),
PCMCIA_DEVICE_PROD_ID12("ATMEL", "AT76C502AR", 0xabda4164, 0x41b37e1f), PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C502AR", 0xabda4164, 0x41b37e1f, ATMEL_FW_TYPE_502),
PCMCIA_DEVICE_PROD_ID12("ATMEL", "AT76C504", 0xabda4164, 0x5040670a), PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C502AR_D", 0xabda4164, 0x3675d704, ATMEL_FW_TYPE_502D),
PCMCIA_DEVICE_PROD_ID12("ATMEL", "AT76C504A", 0xabda4164, 0xe15ed87f), PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C502AR_E", 0xabda4164, 0x4172e792, ATMEL_FW_TYPE_502E),
PCMCIA_DEVICE_PROD_ID12("BT", "Voyager 1020 Laptop Adapter", 0xae49b86a, 0x1e957cd5), PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C504_R", 0xabda4164, 0x917f3d72, ATMEL_FW_TYPE_504_2958),
PCMCIA_DEVICE_PROD_ID12("CNet", "CNWLC 11Mbps Wireless PC Card V-5", 0xbc477dde, 0x502fae6b), PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C504", 0xabda4164, 0x5040670a, ATMEL_FW_TYPE_504),
PCMCIA_DEVICE_PROD_ID12("IEEE 802.11b", "Wireless LAN PC Card", 0x5b878724, 0x122f1df6), PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C504A", 0xabda4164, 0xe15ed87f, ATMEL_FW_TYPE_504A_2958),
PCMCIA_DEVICE_PROD_ID12("OEM", "11Mbps Wireless LAN PC Card V-3", 0xfea54c90, 0x1c5b0f68), PCMCIA_DEVICE_PROD_ID12_INFO("BT", "Voyager 1020 Laptop Adapter", 0xae49b86a, 0x1e957cd5, ATMEL_FW_TYPE_502),
PCMCIA_DEVICE_PROD_ID12("SMC", "2632W", 0xc4f8b18b, 0x30f38774), PCMCIA_DEVICE_PROD_ID12_INFO("CNet", "CNWLC 11Mbps Wireless PC Card V-5", 0xbc477dde, 0x502fae6b, ATMEL_FW_TYPE_502E),
PCMCIA_DEVICE_PROD_ID12("SMC", "2632W-V2", 0xc4f8b18b, 0x172d1377), PCMCIA_DEVICE_PROD_ID12_INFO("IEEE 802.11b", "Wireless LAN PC Card", 0x5b878724, 0x122f1df6, ATMEL_FW_TYPE_502),
PCMCIA_DEVICE_PROD_ID12("Wireless", "PC", 0xa407ecdd, 0x556e4d7e), PCMCIA_DEVICE_PROD_ID12_INFO("IEEE 802.11b", "Wireless LAN Card S", 0x5b878724, 0x5fba533a, ATMEL_FW_TYPE_504_2958),
PCMCIA_DEVICE_PROD_ID12("WLAN", "802.11b PC CARD", 0x575c516c, 0xb1f6dbc4), PCMCIA_DEVICE_PROD_ID12_INFO("OEM", "11Mbps Wireless LAN PC Card V-3", 0xfea54c90, 0x1c5b0f68, ATMEL_FW_TYPE_502),
PCMCIA_DEVICE_PROD_ID12_INFO("SMC", "2632W", 0xc4f8b18b, 0x30f38774, ATMEL_FW_TYPE_502D),
PCMCIA_DEVICE_PROD_ID12_INFO("SMC", "2632W-V2", 0xc4f8b18b, 0x172d1377, ATMEL_FW_TYPE_502),
PCMCIA_DEVICE_PROD_ID12_INFO("Wireless", "PC_CARD", 0xa407ecdd, 0x119f6314, ATMEL_FW_TYPE_502D),
PCMCIA_DEVICE_PROD_ID12_INFO("WLAN", "802.11b PC CARD", 0x575c516c, 0xb1f6dbc4, ATMEL_FW_TYPE_502D),
PCMCIA_DEVICE_PROD_ID12_INFO("LG", "LW2100N", 0xb474d43a, 0x6b1fec94, ATMEL_FW_TYPE_502E),
PCMCIA_DEVICE_NULL PCMCIA_DEVICE_NULL
}; };
MODULE_DEVICE_TABLE(pcmcia, atmel_ids); MODULE_DEVICE_TABLE(pcmcia, atmel_ids);
static struct pcmcia_driver atmel_driver = { static struct pcmcia_driver atmel_driver = {
......
...@@ -72,7 +72,7 @@ static int __devinit atmel_pci_probe(struct pci_dev *pdev, ...@@ -72,7 +72,7 @@ static int __devinit atmel_pci_probe(struct pci_dev *pdev,
static void __devexit atmel_pci_remove(struct pci_dev *pdev) static void __devexit atmel_pci_remove(struct pci_dev *pdev)
{ {
stop_atmel_card(pci_get_drvdata(pdev), 1); stop_atmel_card(pci_get_drvdata(pdev));
} }
static int __init atmel_init_module(void) static int __init atmel_init_module(void)
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Author(s): Original Code written by * Author(s): Original Code written by
* DJ Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) * DJ Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
* Rewritten by * Rewritten by
* Frank Pavlic (pavlic@de.ibm.com) and * Frank Pavlic (fpavlic@de.ibm.com) and
* Martin Schwidefsky <schwidefsky@de.ibm.com> * Martin Schwidefsky <schwidefsky@de.ibm.com>
* *
* $Revision: 1.99 $ $Date: 2005/05/11 08:10:17 $ * $Revision: 1.99 $ $Date: 2005/05/11 08:10:17 $
...@@ -2342,6 +2342,6 @@ __exit lcs_cleanup_module(void) ...@@ -2342,6 +2342,6 @@ __exit lcs_cleanup_module(void)
module_init(lcs_init_module); module_init(lcs_init_module);
module_exit(lcs_cleanup_module); module_exit(lcs_cleanup_module);
MODULE_AUTHOR("Frank Pavlic <pavlic@de.ibm.com>"); MODULE_AUTHOR("Frank Pavlic <fpavlic@de.ibm.com>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <linux/trdevice.h> #include <linux/trdevice.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
#include <linux/ctype.h>
#include <net/ipv6.h> #include <net/ipv6.h>
#include <linux/in6.h> #include <linux/in6.h>
...@@ -24,7 +25,7 @@ ...@@ -24,7 +25,7 @@
#include "qeth_mpc.h" #include "qeth_mpc.h"
#define VERSION_QETH_H "$Revision: 1.142 $" #define VERSION_QETH_H "$Revision: 1.152 $"
#ifdef CONFIG_QETH_IPV6 #ifdef CONFIG_QETH_IPV6
#define QETH_VERSION_IPV6 ":IPv6" #define QETH_VERSION_IPV6 ":IPv6"
...@@ -718,8 +719,6 @@ struct qeth_reply { ...@@ -718,8 +719,6 @@ struct qeth_reply {
atomic_t refcnt; atomic_t refcnt;
}; };
#define QETH_BROADCAST_WITH_ECHO 1
#define QETH_BROADCAST_WITHOUT_ECHO 2
struct qeth_card_blkt { struct qeth_card_blkt {
int time_total; int time_total;
...@@ -727,8 +726,10 @@ struct qeth_card_blkt { ...@@ -727,8 +726,10 @@ struct qeth_card_blkt {
int inter_packet_jumbo; int inter_packet_jumbo;
}; };
#define QETH_BROADCAST_WITH_ECHO 0x01
#define QETH_BROADCAST_WITHOUT_ECHO 0x02
#define QETH_LAYER2_MAC_READ 0x01
#define QETH_LAYER2_MAC_REGISTERED 0x02
struct qeth_card_info { struct qeth_card_info {
unsigned short unit_addr2; unsigned short unit_addr2;
unsigned short cula; unsigned short cula;
...@@ -736,7 +737,7 @@ struct qeth_card_info { ...@@ -736,7 +737,7 @@ struct qeth_card_info {
__u16 func_level; __u16 func_level;
char mcl_level[QETH_MCL_LENGTH + 1]; char mcl_level[QETH_MCL_LENGTH + 1];
int guestlan; int guestlan;
int layer2_mac_registered; int mac_bits;
int portname_required; int portname_required;
int portno; int portno;
char portname[9]; char portname[9];
...@@ -749,6 +750,7 @@ struct qeth_card_info { ...@@ -749,6 +750,7 @@ struct qeth_card_info {
int unique_id; int unique_id;
struct qeth_card_blkt blkt; struct qeth_card_blkt blkt;
__u32 csum_mask; __u32 csum_mask;
enum qeth_ipa_promisc_modes promisc_mode;
}; };
struct qeth_card_options { struct qeth_card_options {
...@@ -775,6 +777,7 @@ struct qeth_card_options { ...@@ -775,6 +777,7 @@ struct qeth_card_options {
enum qeth_threads { enum qeth_threads {
QETH_SET_IP_THREAD = 1, QETH_SET_IP_THREAD = 1,
QETH_RECOVER_THREAD = 2, QETH_RECOVER_THREAD = 2,
QETH_SET_PROMISC_MODE_THREAD = 4,
}; };
struct qeth_osn_info { struct qeth_osn_info {
...@@ -1074,6 +1077,26 @@ qeth_get_qdio_q_format(struct qeth_card *card) ...@@ -1074,6 +1077,26 @@ qeth_get_qdio_q_format(struct qeth_card *card)
} }
} }
static inline int
qeth_isdigit(char * buf)
{
while (*buf) {
if (!isdigit(*buf++))
return 0;
}
return 1;
}
static inline int
qeth_isxdigit(char * buf)
{
while (*buf) {
if (!isxdigit(*buf++))
return 0;
}
return 1;
}
static inline void static inline void
qeth_ipaddr4_to_string(const __u8 *addr, char *buf) qeth_ipaddr4_to_string(const __u8 *addr, char *buf)
{ {
...@@ -1090,18 +1113,27 @@ qeth_string_to_ipaddr4(const char *buf, __u8 *addr) ...@@ -1090,18 +1113,27 @@ qeth_string_to_ipaddr4(const char *buf, __u8 *addr)
int i; int i;
start = buf; start = buf;
for (i = 0; i < 3; i++) { for (i = 0; i < 4; i++) {
if (!(end = strchr(start, '.'))) if (i == 3) {
return -EINVAL; end = strchr(start,0xa);
if (end)
len = end - start;
else
len = strlen(start);
}
else {
end = strchr(start, '.');
len = end - start; len = end - start;
}
if ((len <= 0) || (len > 3))
return -EINVAL;
memset(abuf, 0, 4); memset(abuf, 0, 4);
strncpy(abuf, start, len); strncpy(abuf, start, len);
if (!qeth_isdigit(abuf))
return -EINVAL;
addr[i] = simple_strtoul(abuf, &tmp, 10); addr[i] = simple_strtoul(abuf, &tmp, 10);
start = end + 1; start = end + 1;
} }
memset(abuf, 0, 4);
strcpy(abuf, start);
addr[3] = simple_strtoul(abuf, &tmp, 10);
return 0; return 0;
} }
...@@ -1128,18 +1160,27 @@ qeth_string_to_ipaddr6(const char *buf, __u8 *addr) ...@@ -1128,18 +1160,27 @@ qeth_string_to_ipaddr6(const char *buf, __u8 *addr)
tmp_addr = (u16 *)addr; tmp_addr = (u16 *)addr;
start = buf; start = buf;
for (i = 0; i < 7; i++) { for (i = 0; i < 8; i++) {
if (!(end = strchr(start, ':'))) if (i == 7) {
return -EINVAL; end = strchr(start,0xa);
if (end)
len = end - start;
else
len = strlen(start);
}
else {
end = strchr(start, ':');
len = end - start; len = end - start;
}
if ((len <= 0) || (len > 4))
return -EINVAL;
memset(abuf, 0, 5); memset(abuf, 0, 5);
strncpy(abuf, start, len); strncpy(abuf, start, len);
if (!qeth_isxdigit(abuf))
return -EINVAL;
tmp_addr[i] = simple_strtoul(abuf, &tmp, 16); tmp_addr[i] = simple_strtoul(abuf, &tmp, 16);
start = end + 1; start = end + 1;
} }
memset(abuf, 0, 5);
strcpy(abuf, start);
tmp_addr[7] = simple_strtoul(abuf, &tmp, 16);
return 0; return 0;
} }
......
/* /*
* *
* linux/drivers/s390/net/qeth_main.c ($Revision: 1.224 $) * linux/drivers/s390/net/qeth_main.c ($Revision: 1.242 $)
* *
* Linux on zSeries OSA Express and HiperSockets support * Linux on zSeries OSA Express and HiperSockets support
* *
...@@ -9,10 +9,10 @@ ...@@ -9,10 +9,10 @@
* Author(s): Original Code written by * Author(s): Original Code written by
* Utz Bacher (utz.bacher@de.ibm.com) * Utz Bacher (utz.bacher@de.ibm.com)
* Rewritten by * Rewritten by
* Frank Pavlic (pavlic@de.ibm.com) and * Frank Pavlic (fpavlic@de.ibm.com) and
* Thomas Spatzier <tspat@de.ibm.com> * Thomas Spatzier <tspat@de.ibm.com>
* *
* $Revision: 1.224 $ $Date: 2005/05/04 20:19:18 $ * $Revision: 1.242 $ $Date: 2005/05/04 20:19:18 $
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -72,7 +72,7 @@ ...@@ -72,7 +72,7 @@
#include "qeth_eddp.h" #include "qeth_eddp.h"
#include "qeth_tso.h" #include "qeth_tso.h"
#define VERSION_QETH_C "$Revision: 1.224 $" #define VERSION_QETH_C "$Revision: 1.242 $"
static const char *version = "qeth S/390 OSA-Express driver"; static const char *version = "qeth S/390 OSA-Express driver";
/** /**
...@@ -159,6 +159,9 @@ qeth_get_addr_buffer(enum qeth_prot_versions); ...@@ -159,6 +159,9 @@ qeth_get_addr_buffer(enum qeth_prot_versions);
static void static void
qeth_set_multicast_list(struct net_device *); qeth_set_multicast_list(struct net_device *);
static void
qeth_setadp_promisc_mode(struct qeth_card *);
static void static void
qeth_notify_processes(void) qeth_notify_processes(void)
{ {
...@@ -602,11 +605,20 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo, ...@@ -602,11 +605,20 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo,
int found = 0; int found = 0;
list_for_each_entry(addr, &card->ip_list, entry) { list_for_each_entry(addr, &card->ip_list, entry) {
if (card->options.layer2) {
if ((addr->type == todo->type) &&
(memcmp(&addr->mac, &todo->mac,
OSA_ADDR_LEN) == 0)) {
found = 1;
break;
}
continue;
}
if ((addr->proto == QETH_PROT_IPV4) && if ((addr->proto == QETH_PROT_IPV4) &&
(todo->proto == QETH_PROT_IPV4) && (todo->proto == QETH_PROT_IPV4) &&
(addr->type == todo->type) && (addr->type == todo->type) &&
(addr->u.a4.addr == todo->u.a4.addr) && (addr->u.a4.addr == todo->u.a4.addr) &&
(addr->u.a4.mask == todo->u.a4.mask) ){ (addr->u.a4.mask == todo->u.a4.mask)) {
found = 1; found = 1;
break; break;
} }
...@@ -620,7 +632,7 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo, ...@@ -620,7 +632,7 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo,
break; break;
} }
} }
if (found){ if (found) {
addr->users += todo->users; addr->users += todo->users;
if (addr->users <= 0){ if (addr->users <= 0){
*__addr = addr; *__addr = addr;
...@@ -632,7 +644,7 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo, ...@@ -632,7 +644,7 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo,
return 0; return 0;
} }
} }
if (todo->users > 0){ if (todo->users > 0) {
/* for VIPA and RXIP limit refcount to 1 */ /* for VIPA and RXIP limit refcount to 1 */
if (todo->type != QETH_IP_TYPE_NORMAL) if (todo->type != QETH_IP_TYPE_NORMAL)
todo->users = 1; todo->users = 1;
...@@ -682,12 +694,22 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add) ...@@ -682,12 +694,22 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add)
if ((addr->type == QETH_IP_TYPE_DEL_ALL_MC) && if ((addr->type == QETH_IP_TYPE_DEL_ALL_MC) &&
(tmp->type == QETH_IP_TYPE_DEL_ALL_MC)) (tmp->type == QETH_IP_TYPE_DEL_ALL_MC))
return 0; return 0;
if (card->options.layer2) {
if ((tmp->type == addr->type) &&
(tmp->is_multicast == addr->is_multicast) &&
(memcmp(&tmp->mac, &addr->mac,
OSA_ADDR_LEN) == 0)) {
found = 1;
break;
}
continue;
}
if ((tmp->proto == QETH_PROT_IPV4) && if ((tmp->proto == QETH_PROT_IPV4) &&
(addr->proto == QETH_PROT_IPV4) && (addr->proto == QETH_PROT_IPV4) &&
(tmp->type == addr->type) && (tmp->type == addr->type) &&
(tmp->is_multicast == addr->is_multicast) && (tmp->is_multicast == addr->is_multicast) &&
(tmp->u.a4.addr == addr->u.a4.addr) && (tmp->u.a4.addr == addr->u.a4.addr) &&
(tmp->u.a4.mask == addr->u.a4.mask) ){ (tmp->u.a4.mask == addr->u.a4.mask)) {
found = 1; found = 1;
break; break;
} }
...@@ -697,7 +719,7 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add) ...@@ -697,7 +719,7 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add)
(tmp->is_multicast == addr->is_multicast) && (tmp->is_multicast == addr->is_multicast) &&
(tmp->u.a6.pfxlen == addr->u.a6.pfxlen) && (tmp->u.a6.pfxlen == addr->u.a6.pfxlen) &&
(memcmp(&tmp->u.a6.addr, &addr->u.a6.addr, (memcmp(&tmp->u.a6.addr, &addr->u.a6.addr,
sizeof(struct in6_addr)) == 0) ){ sizeof(struct in6_addr)) == 0)) {
found = 1; found = 1;
break; break;
} }
...@@ -707,7 +729,7 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add) ...@@ -707,7 +729,7 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add)
tmp->users += addr->users; tmp->users += addr->users;
else else
tmp->users += add? 1:-1; tmp->users += add? 1:-1;
if (tmp->users == 0){ if (tmp->users == 0) {
list_del(&tmp->entry); list_del(&tmp->entry);
kfree(tmp); kfree(tmp);
} }
...@@ -738,12 +760,15 @@ qeth_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr) ...@@ -738,12 +760,15 @@ qeth_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
unsigned long flags; unsigned long flags;
int rc = 0; int rc = 0;
QETH_DBF_TEXT(trace,4,"delip"); QETH_DBF_TEXT(trace, 4, "delip");
if (addr->proto == QETH_PROT_IPV4)
QETH_DBF_HEX(trace,4,&addr->u.a4.addr,4); if (card->options.layer2)
QETH_DBF_HEX(trace, 4, &addr->mac, 6);
else if (addr->proto == QETH_PROT_IPV4)
QETH_DBF_HEX(trace, 4, &addr->u.a4.addr, 4);
else { else {
QETH_DBF_HEX(trace,4,&addr->u.a6.addr,8); QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8);
QETH_DBF_HEX(trace,4,((char *)&addr->u.a6.addr)+8,8); QETH_DBF_HEX(trace, 4, ((char *)&addr->u.a6.addr) + 8, 8);
} }
spin_lock_irqsave(&card->ip_lock, flags); spin_lock_irqsave(&card->ip_lock, flags);
rc = __qeth_insert_ip_todo(card, addr, 0); rc = __qeth_insert_ip_todo(card, addr, 0);
...@@ -757,12 +782,14 @@ qeth_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr) ...@@ -757,12 +782,14 @@ qeth_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
unsigned long flags; unsigned long flags;
int rc = 0; int rc = 0;
QETH_DBF_TEXT(trace,4,"addip"); QETH_DBF_TEXT(trace, 4, "addip");
if (addr->proto == QETH_PROT_IPV4) if (card->options.layer2)
QETH_DBF_HEX(trace,4,&addr->u.a4.addr,4); QETH_DBF_HEX(trace, 4, &addr->mac, 6);
else if (addr->proto == QETH_PROT_IPV4)
QETH_DBF_HEX(trace, 4, &addr->u.a4.addr, 4);
else { else {
QETH_DBF_HEX(trace,4,&addr->u.a6.addr,8); QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8);
QETH_DBF_HEX(trace,4,((char *)&addr->u.a6.addr)+8,8); QETH_DBF_HEX(trace, 4, ((char *)&addr->u.a6.addr) + 8, 8);
} }
spin_lock_irqsave(&card->ip_lock, flags); spin_lock_irqsave(&card->ip_lock, flags);
rc = __qeth_insert_ip_todo(card, addr, 1); rc = __qeth_insert_ip_todo(card, addr, 1);
...@@ -775,7 +802,7 @@ __qeth_delete_all_mc(struct qeth_card *card, unsigned long *flags) ...@@ -775,7 +802,7 @@ __qeth_delete_all_mc(struct qeth_card *card, unsigned long *flags)
{ {
struct qeth_ipaddr *addr, *tmp; struct qeth_ipaddr *addr, *tmp;
int rc; int rc;
again:
list_for_each_entry_safe(addr, tmp, &card->ip_list, entry) { list_for_each_entry_safe(addr, tmp, &card->ip_list, entry) {
if (addr->is_multicast) { if (addr->is_multicast) {
spin_unlock_irqrestore(&card->ip_lock, *flags); spin_unlock_irqrestore(&card->ip_lock, *flags);
...@@ -784,6 +811,7 @@ __qeth_delete_all_mc(struct qeth_card *card, unsigned long *flags) ...@@ -784,6 +811,7 @@ __qeth_delete_all_mc(struct qeth_card *card, unsigned long *flags)
if (!rc) { if (!rc) {
list_del(&addr->entry); list_del(&addr->entry);
kfree(addr); kfree(addr);
goto again;
} }
} }
} }
...@@ -851,6 +879,7 @@ qeth_set_ip_addr_list(struct qeth_card *card) ...@@ -851,6 +879,7 @@ qeth_set_ip_addr_list(struct qeth_card *card)
static void qeth_delete_mc_addresses(struct qeth_card *); static void qeth_delete_mc_addresses(struct qeth_card *);
static void qeth_add_multicast_ipv4(struct qeth_card *); static void qeth_add_multicast_ipv4(struct qeth_card *);
static void qeth_layer2_add_multicast(struct qeth_card *);
#ifdef CONFIG_QETH_IPV6 #ifdef CONFIG_QETH_IPV6
static void qeth_add_multicast_ipv6(struct qeth_card *); static void qeth_add_multicast_ipv6(struct qeth_card *);
#endif #endif
...@@ -939,6 +968,24 @@ qeth_register_ip_addresses(void *ptr) ...@@ -939,6 +968,24 @@ qeth_register_ip_addresses(void *ptr)
return 0; return 0;
} }
/*
* Drive the SET_PROMISC_MODE thread
*/
static int
qeth_set_promisc_mode(void *ptr)
{
struct qeth_card *card = (struct qeth_card *) ptr;
daemonize("qeth_setprm");
QETH_DBF_TEXT(trace,4,"setprm1");
if (!qeth_do_run_thread(card, QETH_SET_PROMISC_MODE_THREAD))
return 0;
QETH_DBF_TEXT(trace,4,"setprm2");
qeth_setadp_promisc_mode(card);
qeth_clear_thread_running_bit(card, QETH_SET_PROMISC_MODE_THREAD);
return 0;
}
static int static int
qeth_recover(void *ptr) qeth_recover(void *ptr)
{ {
...@@ -1005,6 +1052,8 @@ qeth_start_kernel_thread(struct qeth_card *card) ...@@ -1005,6 +1052,8 @@ qeth_start_kernel_thread(struct qeth_card *card)
if (qeth_do_start_thread(card, QETH_SET_IP_THREAD)) if (qeth_do_start_thread(card, QETH_SET_IP_THREAD))
kernel_thread(qeth_register_ip_addresses, (void *)card,SIGCHLD); kernel_thread(qeth_register_ip_addresses, (void *)card,SIGCHLD);
if (qeth_do_start_thread(card, QETH_SET_PROMISC_MODE_THREAD))
kernel_thread(qeth_set_promisc_mode, (void *)card, SIGCHLD);
if (qeth_do_start_thread(card, QETH_RECOVER_THREAD)) if (qeth_do_start_thread(card, QETH_RECOVER_THREAD))
kernel_thread(qeth_recover, (void *) card, SIGCHLD); kernel_thread(qeth_recover, (void *) card, SIGCHLD);
} }
...@@ -3749,7 +3798,7 @@ qeth_open(struct net_device *dev) ...@@ -3749,7 +3798,7 @@ qeth_open(struct net_device *dev)
if ( (card->info.type != QETH_CARD_TYPE_OSN) && if ( (card->info.type != QETH_CARD_TYPE_OSN) &&
(card->options.layer2) && (card->options.layer2) &&
(!card->info.layer2_mac_registered)) { (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))) {
QETH_DBF_TEXT(trace,4,"nomacadr"); QETH_DBF_TEXT(trace,4,"nomacadr");
return -EPERM; return -EPERM;
} }
...@@ -4311,6 +4360,8 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, ...@@ -4311,6 +4360,8 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
out: out:
if (flush_count) if (flush_count)
qeth_flush_buffers(queue, 0, start_index, flush_count); qeth_flush_buffers(queue, 0, start_index, flush_count);
else if (!atomic_read(&queue->set_pci_flags_count))
atomic_swap(&queue->state, QETH_OUT_Q_LOCKED_FLUSH);
/* /*
* queue->state will go from LOCKED -> UNLOCKED or from * queue->state will go from LOCKED -> UNLOCKED or from
* LOCKED_FLUSH -> LOCKED if output_handler wanted to 'notify' us * LOCKED_FLUSH -> LOCKED if output_handler wanted to 'notify' us
...@@ -4975,6 +5026,10 @@ qeth_default_setassparms_cb(struct qeth_card *, struct qeth_reply *, ...@@ -4975,6 +5026,10 @@ qeth_default_setassparms_cb(struct qeth_card *, struct qeth_reply *,
unsigned long); unsigned long);
static int static int
qeth_default_setadapterparms_cb(struct qeth_card *card,
struct qeth_reply *reply,
unsigned long data);
static int
qeth_send_setassparms(struct qeth_card *, struct qeth_cmd_buffer *, qeth_send_setassparms(struct qeth_card *, struct qeth_cmd_buffer *,
__u16, long, __u16, long,
int (*reply_cb) int (*reply_cb)
...@@ -5301,8 +5356,7 @@ qeth_free_vlan_addresses4(struct qeth_card *card, unsigned short vid) ...@@ -5301,8 +5356,7 @@ qeth_free_vlan_addresses4(struct qeth_card *card, unsigned short vid)
struct qeth_ipaddr *addr; struct qeth_ipaddr *addr;
QETH_DBF_TEXT(trace, 4, "frvaddr4"); QETH_DBF_TEXT(trace, 4, "frvaddr4");
if (!card->vlangrp)
return;
rcu_read_lock(); rcu_read_lock();
in_dev = __in_dev_get_rcu(card->vlangrp->vlan_devices[vid]); in_dev = __in_dev_get_rcu(card->vlangrp->vlan_devices[vid]);
if (!in_dev) if (!in_dev)
...@@ -5330,8 +5384,7 @@ qeth_free_vlan_addresses6(struct qeth_card *card, unsigned short vid) ...@@ -5330,8 +5384,7 @@ qeth_free_vlan_addresses6(struct qeth_card *card, unsigned short vid)
struct qeth_ipaddr *addr; struct qeth_ipaddr *addr;
QETH_DBF_TEXT(trace, 4, "frvaddr6"); QETH_DBF_TEXT(trace, 4, "frvaddr6");
if (!card->vlangrp)
return;
in6_dev = in6_dev_get(card->vlangrp->vlan_devices[vid]); in6_dev = in6_dev_get(card->vlangrp->vlan_devices[vid]);
if (!in6_dev) if (!in6_dev)
return; return;
...@@ -5351,10 +5404,38 @@ qeth_free_vlan_addresses6(struct qeth_card *card, unsigned short vid) ...@@ -5351,10 +5404,38 @@ qeth_free_vlan_addresses6(struct qeth_card *card, unsigned short vid)
} }
static void static void
qeth_free_vlan_addresses(struct qeth_card *card, unsigned short vid)
{
if (card->options.layer2 || !card->vlangrp)
return;
qeth_free_vlan_addresses4(card, vid);
qeth_free_vlan_addresses6(card, vid);
}
static int
qeth_layer2_send_setdelvlan_cb(struct qeth_card *card,
struct qeth_reply *reply,
unsigned long data)
{
struct qeth_ipa_cmd *cmd;
QETH_DBF_TEXT(trace, 2, "L2sdvcb");
cmd = (struct qeth_ipa_cmd *) data;
if (cmd->hdr.return_code) {
PRINT_ERR("Error in processing VLAN %i on %s: 0x%x. "
"Continuing\n",cmd->data.setdelvlan.vlan_id,
QETH_CARD_IFNAME(card), cmd->hdr.return_code);
QETH_DBF_TEXT_(trace, 2, "L2VL%4x", cmd->hdr.command);
QETH_DBF_TEXT_(trace, 2, "L2%s", CARD_BUS_ID(card));
QETH_DBF_TEXT_(trace, 2, "err%d", cmd->hdr.return_code);
}
return 0;
}
static int
qeth_layer2_send_setdelvlan(struct qeth_card *card, __u16 i, qeth_layer2_send_setdelvlan(struct qeth_card *card, __u16 i,
enum qeth_ipa_cmds ipacmd) enum qeth_ipa_cmds ipacmd)
{ {
int rc;
struct qeth_ipa_cmd *cmd; struct qeth_ipa_cmd *cmd;
struct qeth_cmd_buffer *iob; struct qeth_cmd_buffer *iob;
...@@ -5362,15 +5443,8 @@ qeth_layer2_send_setdelvlan(struct qeth_card *card, __u16 i, ...@@ -5362,15 +5443,8 @@ qeth_layer2_send_setdelvlan(struct qeth_card *card, __u16 i,
iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4); iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
cmd->data.setdelvlan.vlan_id = i; cmd->data.setdelvlan.vlan_id = i;
return qeth_send_ipa_cmd(card, iob,
rc = qeth_send_ipa_cmd(card, iob, NULL, NULL); qeth_layer2_send_setdelvlan_cb, NULL);
if (rc) {
PRINT_ERR("Error in processing VLAN %i on %s: 0x%x. "
"Continuing\n",i, QETH_CARD_IFNAME(card), rc);
QETH_DBF_TEXT_(trace, 2, "L2VL%4x", ipacmd);
QETH_DBF_TEXT_(trace, 2, "L2%s", CARD_BUS_ID(card));
QETH_DBF_TEXT_(trace, 2, "err%d", rc);
}
} }
static void static void
...@@ -5420,8 +5494,7 @@ qeth_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) ...@@ -5420,8 +5494,7 @@ qeth_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
qeth_free_vlan_skbs(card, vid); qeth_free_vlan_skbs(card, vid);
spin_lock_irqsave(&card->vlanlock, flags); spin_lock_irqsave(&card->vlanlock, flags);
/* unregister IP addresses of vlan device */ /* unregister IP addresses of vlan device */
qeth_free_vlan_addresses4(card, vid); qeth_free_vlan_addresses(card, vid);
qeth_free_vlan_addresses6(card, vid);
if (card->vlangrp) if (card->vlangrp)
card->vlangrp->vlan_devices[vid] = NULL; card->vlangrp->vlan_devices[vid] = NULL;
spin_unlock_irqrestore(&card->vlanlock, flags); spin_unlock_irqrestore(&card->vlanlock, flags);
...@@ -5430,6 +5503,59 @@ qeth_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) ...@@ -5430,6 +5503,59 @@ qeth_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
qeth_set_multicast_list(card->dev); qeth_set_multicast_list(card->dev);
} }
#endif #endif
/**
* Examine hardware response to SET_PROMISC_MODE
*/
static int
qeth_setadp_promisc_mode_cb(struct qeth_card *card,
struct qeth_reply *reply,
unsigned long data)
{
struct qeth_ipa_cmd *cmd;
struct qeth_ipacmd_setadpparms *setparms;
QETH_DBF_TEXT(trace,4,"prmadpcb");
cmd = (struct qeth_ipa_cmd *) data;
setparms = &(cmd->data.setadapterparms);
qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd);
if (cmd->hdr.return_code) {
QETH_DBF_TEXT_(trace,4,"prmrc%2.2x",cmd->hdr.return_code);
setparms->data.mode = SET_PROMISC_MODE_OFF;
}
card->info.promisc_mode = setparms->data.mode;
return 0;
}
/*
* Set promiscuous mode (on or off) (SET_PROMISC_MODE command)
*/
static void
qeth_setadp_promisc_mode(struct qeth_card *card)
{
enum qeth_ipa_promisc_modes mode;
struct net_device *dev = card->dev;
struct qeth_cmd_buffer *iob;
struct qeth_ipa_cmd *cmd;
QETH_DBF_TEXT(trace, 4, "setprom");
if (((dev->flags & IFF_PROMISC) &&
(card->info.promisc_mode == SET_PROMISC_MODE_ON)) ||
(!(dev->flags & IFF_PROMISC) &&
(card->info.promisc_mode == SET_PROMISC_MODE_OFF)))
return;
mode = SET_PROMISC_MODE_OFF;
if (dev->flags & IFF_PROMISC)
mode = SET_PROMISC_MODE_ON;
QETH_DBF_TEXT_(trace, 4, "mode:%x", mode);
iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_PROMISC_MODE,
sizeof(struct qeth_ipacmd_setadpparms));
cmd = (struct qeth_ipa_cmd *)(iob->data + IPA_PDU_HEADER_SIZE);
cmd->data.setadapterparms.data.mode = mode;
qeth_send_ipa_cmd(card, iob, qeth_setadp_promisc_mode_cb, NULL);
}
/** /**
* set multicast address on card * set multicast address on card
...@@ -5444,12 +5570,22 @@ qeth_set_multicast_list(struct net_device *dev) ...@@ -5444,12 +5570,22 @@ qeth_set_multicast_list(struct net_device *dev)
QETH_DBF_TEXT(trace,3,"setmulti"); QETH_DBF_TEXT(trace,3,"setmulti");
qeth_delete_mc_addresses(card); qeth_delete_mc_addresses(card);
if (card->options.layer2) {
qeth_layer2_add_multicast(card);
goto out;
}
qeth_add_multicast_ipv4(card); qeth_add_multicast_ipv4(card);
#ifdef CONFIG_QETH_IPV6 #ifdef CONFIG_QETH_IPV6
qeth_add_multicast_ipv6(card); qeth_add_multicast_ipv6(card);
#endif #endif
out:
if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0) if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
schedule_work(&card->kernel_thread_starter); schedule_work(&card->kernel_thread_starter);
if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
return;
if (qeth_set_thread_start_bit(card, QETH_SET_PROMISC_MODE_THREAD)==0)
schedule_work(&card->kernel_thread_starter);
} }
static int static int
...@@ -5657,6 +5793,24 @@ qeth_add_multicast_ipv4(struct qeth_card *card) ...@@ -5657,6 +5793,24 @@ qeth_add_multicast_ipv4(struct qeth_card *card)
in_dev_put(in4_dev); in_dev_put(in4_dev);
} }
static void
qeth_layer2_add_multicast(struct qeth_card *card)
{
struct qeth_ipaddr *ipm;
struct dev_mc_list *dm;
QETH_DBF_TEXT(trace,4,"L2addmc");
for (dm = card->dev->mc_list; dm; dm = dm->next) {
ipm = qeth_get_addr_buffer(QETH_PROT_IPV4);
if (!ipm)
continue;
memcpy(ipm->mac,dm->dmi_addr,MAX_ADDR_LEN);
ipm->is_multicast = 1;
if (!qeth_add_ip(card, ipm))
kfree(ipm);
}
}
#ifdef CONFIG_QETH_IPV6 #ifdef CONFIG_QETH_IPV6
static inline void static inline void
qeth_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev) qeth_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev)
...@@ -5825,10 +5979,10 @@ qeth_layer2_send_setmac_cb(struct qeth_card *card, ...@@ -5825,10 +5979,10 @@ qeth_layer2_send_setmac_cb(struct qeth_card *card,
PRINT_WARN("Error in registering MAC address on " \ PRINT_WARN("Error in registering MAC address on " \
"device %s: x%x\n", CARD_BUS_ID(card), "device %s: x%x\n", CARD_BUS_ID(card),
cmd->hdr.return_code); cmd->hdr.return_code);
card->info.layer2_mac_registered = 0; card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
cmd->hdr.return_code = -EIO; cmd->hdr.return_code = -EIO;
} else { } else {
card->info.layer2_mac_registered = 1; card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED;
memcpy(card->dev->dev_addr,cmd->data.setdelmac.mac, memcpy(card->dev->dev_addr,cmd->data.setdelmac.mac,
OSA_ADDR_LEN); OSA_ADDR_LEN);
PRINT_INFO("MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x " PRINT_INFO("MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x "
...@@ -5866,7 +6020,7 @@ qeth_layer2_send_delmac_cb(struct qeth_card *card, ...@@ -5866,7 +6020,7 @@ qeth_layer2_send_delmac_cb(struct qeth_card *card,
cmd->hdr.return_code = -EIO; cmd->hdr.return_code = -EIO;
return 0; return 0;
} }
card->info.layer2_mac_registered = 0; card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
return 0; return 0;
} }
...@@ -5874,7 +6028,7 @@ static int ...@@ -5874,7 +6028,7 @@ static int
qeth_layer2_send_delmac(struct qeth_card *card, __u8 *mac) qeth_layer2_send_delmac(struct qeth_card *card, __u8 *mac)
{ {
QETH_DBF_TEXT(trace, 2, "L2Delmac"); QETH_DBF_TEXT(trace, 2, "L2Delmac");
if (!card->info.layer2_mac_registered) if (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))
return 0; return 0;
return qeth_layer2_send_setdelmac(card, mac, IPA_CMD_DELVMAC, return qeth_layer2_send_setdelmac(card, mac, IPA_CMD_DELVMAC,
qeth_layer2_send_delmac_cb); qeth_layer2_send_delmac_cb);
...@@ -5896,7 +6050,7 @@ qeth_layer2_set_mac_address(struct net_device *dev, void *p) ...@@ -5896,7 +6050,7 @@ qeth_layer2_set_mac_address(struct net_device *dev, void *p)
card = (struct qeth_card *) dev->priv; card = (struct qeth_card *) dev->priv;
if (!card->options.layer2) { if (!card->options.layer2) {
PRINT_WARN("Setting MAC address on %s is not supported" PRINT_WARN("Setting MAC address on %s is not supported "
"in Layer 3 mode.\n", dev->name); "in Layer 3 mode.\n", dev->name);
QETH_DBF_TEXT(trace, 3, "setmcLY3"); QETH_DBF_TEXT(trace, 3, "setmcLY3");
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -6441,6 +6595,8 @@ qeth_default_setadapterparms_cb(struct qeth_card *card, ...@@ -6441,6 +6595,8 @@ qeth_default_setadapterparms_cb(struct qeth_card *card,
return 0; return 0;
} }
static int static int
qeth_query_setadapterparms_cb(struct qeth_card *card, struct qeth_reply *reply, qeth_query_setadapterparms_cb(struct qeth_card *card, struct qeth_reply *reply,
unsigned long data) unsigned long data)
...@@ -6481,8 +6637,13 @@ qeth_setadpparms_change_macaddr_cb(struct qeth_card *card, ...@@ -6481,8 +6637,13 @@ qeth_setadpparms_change_macaddr_cb(struct qeth_card *card,
QETH_DBF_TEXT(trace,4,"chgmaccb"); QETH_DBF_TEXT(trace,4,"chgmaccb");
cmd = (struct qeth_ipa_cmd *) data; cmd = (struct qeth_ipa_cmd *) data;
if (!card->options.layer2 || card->info.guestlan ||
!(card->info.mac_bits & QETH_LAYER2_MAC_READ)) {
memcpy(card->dev->dev_addr, memcpy(card->dev->dev_addr,
&cmd->data.setadapterparms.data.change_addr.addr,OSA_ADDR_LEN); &cmd->data.setadapterparms.data.change_addr.addr,
OSA_ADDR_LEN);
card->info.mac_bits |= QETH_LAYER2_MAC_READ;
}
qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd); qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd);
return 0; return 0;
} }
...@@ -6602,6 +6763,12 @@ qeth_layer2_initialize(struct qeth_card *card) ...@@ -6602,6 +6763,12 @@ qeth_layer2_initialize(struct qeth_card *card)
QETH_DBF_TEXT(setup, 2, "doL2init"); QETH_DBF_TEXT(setup, 2, "doL2init");
QETH_DBF_TEXT_(setup, 2, "doL2%s", CARD_BUS_ID(card)); QETH_DBF_TEXT_(setup, 2, "doL2%s", CARD_BUS_ID(card));
rc = qeth_query_setadapterparms(card);
if (rc) {
PRINT_WARN("could not query adapter parameters on device %s: "
"x%x\n", CARD_BUS_ID(card), rc);
}
rc = qeth_setadpparms_change_macaddr(card); rc = qeth_setadpparms_change_macaddr(card);
if (rc) { if (rc) {
PRINT_WARN("couldn't get MAC address on " PRINT_WARN("couldn't get MAC address on "
...@@ -8548,7 +8715,7 @@ EXPORT_SYMBOL(qeth_osn_deregister); ...@@ -8548,7 +8715,7 @@ EXPORT_SYMBOL(qeth_osn_deregister);
EXPORT_SYMBOL(qeth_osn_assist); EXPORT_SYMBOL(qeth_osn_assist);
module_init(qeth_init); module_init(qeth_init);
module_exit(qeth_exit); module_exit(qeth_exit);
MODULE_AUTHOR("Frank Pavlic <pavlic@de.ibm.com>"); MODULE_AUTHOR("Frank Pavlic <fpavlic@de.ibm.com>");
MODULE_DESCRIPTION("Linux on zSeries OSA Express and HiperSockets support\n" \ MODULE_DESCRIPTION("Linux on zSeries OSA Express and HiperSockets support\n" \
"Copyright 2000,2003 IBM Corporation\n"); "Copyright 2000,2003 IBM Corporation\n");
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* Linux on zSeries OSA Express and HiperSockets support * Linux on zSeries OSA Express and HiperSockets support
* *
* Copyright 2000,2003 IBM Corporation * Copyright 2000,2003 IBM Corporation
* Author(s): Frank Pavlic <pavlic@de.ibm.com> * Author(s): Frank Pavlic <fpavlic@de.ibm.com>
* Thomas Spatzier <tspat@de.ibm.com> * Thomas Spatzier <tspat@de.ibm.com>
* *
*/ */
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Copyright 2000,2003 IBM Corporation * Copyright 2000,2003 IBM Corporation
* Author(s): Utz Bacher <utz.bacher@de.ibm.com> * Author(s): Utz Bacher <utz.bacher@de.ibm.com>
* Thomas Spatzier <tspat@de.ibm.com> * Thomas Spatzier <tspat@de.ibm.com>
* Frank Pavlic <pavlic@de.ibm.com> * Frank Pavlic <fpavlic@de.ibm.com>
* *
*/ */
#ifndef __QETH_MPC_H__ #ifndef __QETH_MPC_H__
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
#include <asm/qeth.h> #include <asm/qeth.h>
#define VERSION_QETH_MPC_H "$Revision: 1.43 $" #define VERSION_QETH_MPC_H "$Revision: 1.44 $"
extern const char *VERSION_QETH_MPC_C; extern const char *VERSION_QETH_MPC_C;
...@@ -217,7 +217,7 @@ enum qeth_ipa_setadp_cmd { ...@@ -217,7 +217,7 @@ enum qeth_ipa_setadp_cmd {
IPA_SETADP_SEND_OSA_MESSAGE = 0x0100, IPA_SETADP_SEND_OSA_MESSAGE = 0x0100,
IPA_SETADP_SET_SNMP_CONTROL = 0x0200, IPA_SETADP_SET_SNMP_CONTROL = 0x0200,
IPA_SETADP_READ_SNMP_PARMS = 0x0400, IPA_SETADP_READ_SNMP_PARMS = 0x0400,
IPA_SETADP_WRITE_SNMP_PARMS = 0x0800, IPA_SETADP_SET_PROMISC_MODE = 0x0800,
IPA_SETADP_QUERY_CARD_INFO = 0x1000, IPA_SETADP_QUERY_CARD_INFO = 0x1000,
}; };
enum qeth_ipa_mac_ops { enum qeth_ipa_mac_ops {
...@@ -232,9 +232,12 @@ enum qeth_ipa_addr_ops { ...@@ -232,9 +232,12 @@ enum qeth_ipa_addr_ops {
CHANGE_ADDR_ADD_ADDR = 1, CHANGE_ADDR_ADD_ADDR = 1,
CHANGE_ADDR_DEL_ADDR = 2, CHANGE_ADDR_DEL_ADDR = 2,
CHANGE_ADDR_FLUSH_ADDR_TABLE = 4, CHANGE_ADDR_FLUSH_ADDR_TABLE = 4,
}; };
enum qeth_ipa_promisc_modes {
SET_PROMISC_MODE_OFF = 0,
SET_PROMISC_MODE_ON = 1,
};
/* (SET)DELIP(M) IPA stuff ***************************************************/ /* (SET)DELIP(M) IPA stuff ***************************************************/
struct qeth_ipacmd_setdelip4 { struct qeth_ipacmd_setdelip4 {
__u8 ip_addr[4]; __u8 ip_addr[4];
......
/* /*
* *
* linux/drivers/s390/net/qeth_sys.c ($Revision: 1.55 $) * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.58 $)
* *
* Linux on zSeries OSA Express and HiperSockets support * Linux on zSeries OSA Express and HiperSockets support
* This file contains code related to sysfs. * This file contains code related to sysfs.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Copyright 2000,2003 IBM Corporation * Copyright 2000,2003 IBM Corporation
* *
* Author(s): Thomas Spatzier <tspat@de.ibm.com> * Author(s): Thomas Spatzier <tspat@de.ibm.com>
* Frank Pavlic <pavlic@de.ibm.com> * Frank Pavlic <fpavlic@de.ibm.com>
* *
*/ */
#include <linux/list.h> #include <linux/list.h>
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#include "qeth_mpc.h" #include "qeth_mpc.h"
#include "qeth_fs.h" #include "qeth_fs.h"
const char *VERSION_QETH_SYS_C = "$Revision: 1.55 $"; const char *VERSION_QETH_SYS_C = "$Revision: 1.58 $";
/*****************************************************************************/ /*****************************************************************************/
/* */ /* */
...@@ -1117,7 +1117,7 @@ qeth_parse_ipatoe(const char* buf, enum qeth_prot_versions proto, ...@@ -1117,7 +1117,7 @@ qeth_parse_ipatoe(const char* buf, enum qeth_prot_versions proto,
start = buf; start = buf;
/* get address string */ /* get address string */
end = strchr(start, '/'); end = strchr(start, '/');
if (!end){ if (!end || (end-start >= 49)){
PRINT_WARN("Invalid format for ipato_addx/delx. " PRINT_WARN("Invalid format for ipato_addx/delx. "
"Use <ip addr>/<mask bits>\n"); "Use <ip addr>/<mask bits>\n");
return -EINVAL; return -EINVAL;
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* Copyright 2004 IBM Corporation * Copyright 2004 IBM Corporation
* *
* Author(s): Frank Pavlic <pavlic@de.ibm.com> * Author(s): Frank Pavlic <fpavlic@de.ibm.com>
* *
* $Revision: 1.7 $ $Date: 2005/05/04 20:19:18 $ * $Revision: 1.7 $ $Date: 2005/05/04 20:19:18 $
* *
......
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