summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@redhat.com>2004-04-25 14:27:09 -0400
committerJeff Garzik <jgarzik@redhat.com>2004-04-25 14:27:09 -0400
commit63d5381ed20e9e6a5723cfaf5a2ddce018c0a39e (patch)
tree31efdbc4b7433ab69765a4ef0ffceb36c4b722e8
parentfc3b6177b5008c5708079a3afbfdac177dea88c8 (diff)
parent2210dfec14407ea8604873fe071e084899efafef (diff)
Merge redhat.com:/spare/repo/netdev-2.6/misc
into redhat.com:/spare/repo/net-drivers-2.6
-rw-r--r--drivers/net/pcmcia/3c574_cs.c42
-rw-r--r--drivers/net/pcmcia/3c589_cs.c26
-rw-r--r--drivers/net/pcmcia/axnet_cs.c30
-rw-r--r--drivers/net/pcmcia/com20020_cs.c13
-rw-r--r--drivers/net/pcmcia/fmvj18x_cs.c18
-rw-r--r--drivers/net/pcmcia/ibmtr_cs.c13
-rw-r--r--drivers/net/pcmcia/nmclan_cs.c15
-rw-r--r--drivers/net/pcmcia/smc91c92_cs.c63
-rw-r--r--drivers/net/pcmcia/xirc2ps_cs.c13
-rw-r--r--drivers/net/tulip/tulip_core.c2
-rw-r--r--drivers/net/wireless/atmel.c477
-rw-r--r--drivers/net/wireless/atmel_cs.c7
12 files changed, 401 insertions, 318 deletions
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index aed8eee7ccaa..47a102fd67a9 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -384,6 +384,8 @@ static void tc574_detach(dev_link_t *link)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
+static char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
+
static void tc574_config(dev_link_t *link)
{
client_handle_t handle = link->handle;
@@ -396,6 +398,7 @@ static void tc574_config(dev_link_t *link)
ioaddr_t ioaddr;
u16 *phys_addr;
char *cardname;
+ union wn3_config config;
phys_addr = (u16 *)dev->dev_addr;
@@ -431,15 +434,7 @@ static void tc574_config(dev_link_t *link)
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
- if (register_netdev(dev) != 0) {
- printk(KERN_NOTICE "3c574_cs: register_netdev() failed\n");
- goto failed;
- }
-
ioaddr = dev->base_addr;
- strcpy(lp->node.dev_name, dev->name);
- link->dev = &lp->node;
- link->state &= ~DEV_CONFIG_PENDING;
/* The 3c574 normally uses an EEPROM for configuration info, including
the hardware address. The future products may include a modem chip
@@ -467,24 +462,14 @@ static void tc574_config(dev_link_t *link)
} else
cardname = "3Com 3c574";
- printk(KERN_INFO "%s: %s at io %#3lx, irq %d, hw_addr ",
- dev->name, cardname, dev->base_addr, dev->irq);
-
- for (i = 0; i < 6; i++)
- printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : ".\n"));
-
{
- u_char mcr, *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
- union wn3_config config;
+ u_char mcr;
outw(2<<11, ioaddr + RunnerRdCtrl);
mcr = inb(ioaddr + 2);
outw(0<<11, ioaddr + RunnerRdCtrl);
printk(KERN_INFO " ASIC rev %d,", mcr>>3);
EL3WINDOW(3);
config.i = inl(ioaddr + Wn3_Config);
- printk(" %dK FIFO split %s Rx:Tx, %sMII interface.\n",
- 8 << config.u.ram_size, ram_split[config.u.ram_split],
- config.u.autoselect ? "autoselect " : "");
lp->default_media = config.u.xcvr;
lp->autoselect = config.u.autoselect;
}
@@ -531,6 +516,25 @@ static void tc574_config(dev_link_t *link)
}
}
+ link->state &= ~DEV_CONFIG_PENDING;
+ link->dev = &lp->node;
+
+ if (register_netdev(dev) != 0) {
+ printk(KERN_NOTICE "3c574_cs: register_netdev() failed\n");
+ link->dev = NULL;
+ goto failed;
+ }
+
+ strcpy(lp->node.dev_name, dev->name);
+
+ printk(KERN_INFO "%s: %s at io %#3lx, irq %d, hw_addr ",
+ dev->name, cardname, dev->base_addr, dev->irq);
+ for (i = 0; i < 6; i++)
+ printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : ".\n"));
+ printk(" %dK FIFO split %s Rx:Tx, %sMII interface.\n",
+ 8 << config.u.ram_size, ram_split[config.u.ram_split],
+ config.u.autoselect ? "autoselect " : "");
+
return;
cs_failed:
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index 7ce948fce66c..be997bd296e7 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -308,7 +308,7 @@ static void tc589_config(dev_link_t *link)
tuple_t tuple;
cisparse_t parse;
u16 buf[32], *phys_addr;
- int last_fn, last_ret, i, j, multi = 0;
+ int last_fn, last_ret, i, j, multi = 0, fifo;
ioaddr_t ioaddr;
char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
@@ -357,11 +357,6 @@ static void tc589_config(dev_link_t *link)
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
- if (register_netdev(dev) != 0) {
- printk(KERN_ERR "3c589_cs: register_netdev() failed\n");
- goto failed;
- }
-
ioaddr = dev->base_addr;
EL3WINDOW(0);
@@ -382,13 +377,10 @@ static void tc589_config(dev_link_t *link)
}
}
- strcpy(lp->node.dev_name, dev->name);
- link->dev = &lp->node;
- link->state &= ~DEV_CONFIG_PENDING;
-
/* The address and resource configuration register aren't loaded from
the EEPROM and *must* be set to 0 and IRQ3 for the PCMCIA version. */
outw(0x3f00, ioaddr + 8);
+ fifo = inl(ioaddr);
/* The if_port symbol can be set when the module is loaded */
if ((if_port >= 0) && (if_port <= 3))
@@ -396,14 +388,24 @@ static void tc589_config(dev_link_t *link)
else
printk(KERN_ERR "3c589_cs: invalid if_port requested\n");
+ link->dev = &lp->node;
+ link->state &= ~DEV_CONFIG_PENDING;
+
+ if (register_netdev(dev) != 0) {
+ printk(KERN_ERR "3c589_cs: register_netdev() failed\n");
+ link->dev = NULL;
+ goto failed;
+ }
+
+ strcpy(lp->node.dev_name, dev->name);
+
printk(KERN_INFO "%s: 3Com 3c%s, io %#3lx, irq %d, hw_addr ",
dev->name, (multi ? "562" : "589"), dev->base_addr,
dev->irq);
for (i = 0; i < 6; i++)
printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
- i = inl(ioaddr);
printk(KERN_INFO " %dK FIFO split %s Rx:Tx, %s xcvr\n",
- (i & 7) ? 32 : 8, ram_split[(i >> 16) & 3],
+ (fifo & 7) ? 32 : 8, ram_split[(fifo >> 16) & 3],
if_names[dev->if_port]);
return;
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index 8ef57bdd7776..67e1526df0ec 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -430,19 +430,11 @@ static void axnet_config(dev_link_t *link)
ei_status.block_input = &block_input;
ei_status.block_output = &block_output;
- strcpy(info->node.dev_name, dev->name);
-
if (inb(dev->base_addr + AXNET_TEST) != 0)
info->flags |= IS_AX88790;
else
info->flags |= IS_AX88190;
- printk(KERN_INFO "%s: Asix AX88%d90: io %#3lx, irq %d, hw_addr ",
- dev->name, ((info->flags & IS_AX88790) ? 7 : 1),
- dev->base_addr, dev->irq);
- for (i = 0; i < 6; i++)
- printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
-
if (info->flags & IS_AX88790)
outb(0x10, dev->base_addr + AXNET_GPIO); /* select Internal PHY */
@@ -463,19 +455,27 @@ static void axnet_config(dev_link_t *link)
}
info->phy_id = (i < 32) ? i : -1;
- if (i < 32) {
- DEBUG(0, " MII transceiver at index %d, status %x.\n", i, j);
- } else {
- printk(KERN_NOTICE " No MII transceivers found!\n");
- }
+ link->dev = &info->node;
+ link->state &= ~DEV_CONFIG_PENDING;
if (register_netdev(dev) != 0) {
printk(KERN_NOTICE "axnet_cs: register_netdev() failed\n");
+ link->dev = NULL;
goto failed;
}
- link->dev = &info->node;
- link->state &= ~DEV_CONFIG_PENDING;
+ strcpy(info->node.dev_name, dev->name);
+
+ printk(KERN_INFO "%s: Asix AX88%d90: io %#3lx, irq %d, hw_addr ",
+ dev->name, ((info->flags & IS_AX88790) ? 7 : 1),
+ dev->base_addr, dev->irq);
+ for (i = 0; i < 6; i++)
+ printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
+ if (info->phy_id != -1) {
+ DEBUG(0, " MII transceiver at index %d, status %x.\n", info->phy_id, j);
+ } else {
+ printk(KERN_NOTICE " No MII transceivers found!\n");
+ }
return;
cs_failed:
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c
index d5037cd18def..9ce8df6f2bcf 100644
--- a/drivers/net/pcmcia/com20020_cs.c
+++ b/drivers/net/pcmcia/com20020_cs.c
@@ -141,7 +141,6 @@ static dev_link_t *dev_list;
typedef struct com20020_dev_t {
struct net_device *dev;
- int dev_configured;
dev_node_t node;
} com20020_dev_t;
@@ -277,13 +276,10 @@ static void com20020_detach(dev_link_t *link)
dev = info->dev;
if (dev)
{
- if (info->dev_configured)
+ if (link->dev)
{
DEBUG(1,"unregister...\n");
- if (netif_running(dev))
- dev->stop(dev);
-
unregister_netdev(dev);
/*
@@ -398,17 +394,18 @@ static void com20020_config(dev_link_t *link)
lp->card_name = "PCMCIA COM20020";
lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */
+ link->dev = &info->node;
+ link->state &= ~DEV_CONFIG_PENDING;
+
i = com20020_found(dev, 0); /* calls register_netdev */
if (i != 0) {
DEBUG(1,KERN_NOTICE "com20020_cs: com20020_found() failed\n");
+ link->dev = NULL;
goto failed;
}
- info->dev_configured = 1;
strcpy(info->node.dev_name, dev->name);
- link->dev = &info->node;
- link->state &= ~DEV_CONFIG_PENDING;
DEBUG(1,KERN_INFO "%s: port %#3lx, irq %d\n",
dev->name, dev->base_addr, dev->irq);
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index ba59cd976451..580af370930b 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -510,10 +510,6 @@ static void fmvj18x_config(dev_link_t *link)
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
- if (register_netdev(dev) != 0) {
- printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n");
- goto failed;
- }
if (link->io.BasePort2 != 0)
fmvj18x_setup_mfc(link);
@@ -575,7 +571,6 @@ static void fmvj18x_config(dev_link_t *link)
/* Read MACID from Buggy CIS */
if (fmvj18x_get_hwinfo(link, tuple.TupleData) == -1) {
printk(KERN_NOTICE "fmvj18x_cs: unable to read hardware net address.\n");
- unregister_netdev(dev);
goto failed;
}
for (i = 0 ; i < 6; i++) {
@@ -592,10 +587,18 @@ static void fmvj18x_config(dev_link_t *link)
break;
}
- strcpy(lp->node.dev_name, dev->name);
+ lp->cardtype = cardtype;
link->dev = &lp->node;
+ link->state &= ~DEV_CONFIG_PENDING;
+
+ if (register_netdev(dev) != 0) {
+ printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n");
+ link->dev = NULL;
+ goto failed;
+ }
+
+ strcpy(lp->node.dev_name, dev->name);
- lp->cardtype = cardtype;
/* print current configuration */
printk(KERN_INFO "%s: %s, sram %s, port %#3lx, irq %d, hw_addr ",
dev->name, card_name, sram_config == 0 ? "4K TX*2" : "8K TX*2",
@@ -603,7 +606,6 @@ static void fmvj18x_config(dev_link_t *link)
for (i = 0; i < 6; i++)
printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
- link->state &= ~DEV_CONFIG_PENDING;
return;
cs_failed:
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c
index cf2a3497d2de..beccf9e9535d 100644
--- a/drivers/net/pcmcia/ibmtr_cs.c
+++ b/drivers/net/pcmcia/ibmtr_cs.c
@@ -317,13 +317,10 @@ static void ibmtr_config(dev_link_t *link)
/* Try PRIMARY card at 0xA20-0xA23 */
link->io.BasePort1 = 0xA20;
i = pcmcia_request_io(link->handle, &link->io);
- if (i == CS_SUCCESS) {
- memcpy(info->node.dev_name, "tr0\0", 4);
- } else {
+ if (i != CS_SUCCESS) {
/* Couldn't get 0xA20-0xA23. Try ALTERNATE at 0xA24-0xA27. */
link->io.BasePort1 = 0xA24;
CS_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io));
- memcpy(info->node.dev_name, "tr1\0", 4);
}
dev->base_addr = link->io.BasePort1;
@@ -367,15 +364,17 @@ static void ibmtr_config(dev_link_t *link)
Adapters Technical Reference" SC30-3585 for this info. */
ibmtr_hw_setup(dev, mmiobase);
+ link->dev = &info->node;
+ link->state &= ~DEV_CONFIG_PENDING;
+
i = ibmtr_probe_card(dev);
-
if (i != 0) {
printk(KERN_NOTICE "ibmtr_cs: register_netdev() failed\n");
+ link->dev = NULL;
goto failed;
}
- link->dev = &info->node;
- link->state &= ~DEV_CONFIG_PENDING;
+ strcpy(info->node.dev_name, dev->name);
printk(KERN_INFO "%s: port %#3lx, irq %d,",
dev->name, dev->base_addr, dev->irq);
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c
index 07cac888ba3d..bcf284bbb453 100644
--- a/drivers/net/pcmcia/nmclan_cs.c
+++ b/drivers/net/pcmcia/nmclan_cs.c
@@ -734,11 +734,6 @@ static void nmclan_config(dev_link_t *link)
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
- i = register_netdev(dev);
- if (i != 0) {
- printk(KERN_NOTICE "nmclan_cs: register_netdev() failed\n");
- goto failed;
- }
ioaddr = dev->base_addr;
@@ -777,10 +772,18 @@ static void nmclan_config(dev_link_t *link)
else
printk(KERN_NOTICE "nmclan_cs: invalid if_port requested\n");
- strcpy(lp->node.dev_name, dev->name);
link->dev = &lp->node;
link->state &= ~DEV_CONFIG_PENDING;
+ i = register_netdev(dev);
+ if (i != 0) {
+ printk(KERN_NOTICE "nmclan_cs: register_netdev() failed\n");
+ link->dev = NULL;
+ goto failed;
+ }
+
+ strcpy(lp->node.dev_name, dev->name);
+
printk(KERN_INFO "%s: nmclan: port %#3lx, irq %d, %s port, hw_addr ",
dev->name, dev->base_addr, dev->irq, if_names[dev->if_port]);
for (i = 0; i < 6; i++)
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 6b3cb0ec6975..13ed04f1b89c 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -901,6 +901,7 @@ static void smc91c92_config(dev_link_t *link)
char *name;
int i, j, rev;
ioaddr_t ioaddr;
+ u_long mir;
DEBUG(0, "smc91c92_config(0x%p)\n", link);
@@ -952,11 +953,6 @@ static void smc91c92_config(dev_link_t *link)
else
printk(KERN_NOTICE "smc91c92_cs: invalid if_port requested\n");
- if (register_netdev(dev) != 0) {
- printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n");
- goto config_undo;
- }
-
switch (smc->manfid) {
case MANFID_OSITECH:
case MANFID_PSION:
@@ -977,8 +973,6 @@ static void smc91c92_config(dev_link_t *link)
goto config_undo;
}
- strcpy(smc->node.dev_name, dev->name);
- link->dev = &smc->node;
smc->duplex = 0;
smc->rx_ovrn = 0;
@@ -993,25 +987,16 @@ static void smc91c92_config(dev_link_t *link)
case 8: name = "100-FD"; break;
case 9: name = "110"; break;
}
- printk(KERN_INFO "%s: smc91c%s rev %d: io %#3lx, irq %d, "
- "hw_addr ", dev->name, name, (rev & 0x0f), dev->base_addr,
- dev->irq);
- for (i = 0; i < 6; i++)
- printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
ioaddr = dev->base_addr;
if (rev > 0) {
- u_long mir, mcr;
+ u_long mcr;
SMC_SELECT_BANK(0);
mir = inw(ioaddr + MEMINFO) & 0xff;
if (mir == 0xff) mir++;
/* Get scale factor for memory size */
mcr = ((rev >> 4) > 3) ? inw(ioaddr + MEMCFG) : 0x0200;
mir *= 128 * (1<<((mcr >> 9) & 7));
- if (mir & 0x3ff)
- printk(KERN_INFO " %lu byte", mir);
- else
- printk(KERN_INFO " %lu kb", mir>>10);
SMC_SELECT_BANK(1);
smc->cfg = inw(ioaddr + CONFIG) & ~CFG_AUI_SELECT;
smc->cfg |= CFG_NO_WAIT | CFG_16BIT | CFG_STATIC;
@@ -1019,9 +1004,8 @@ static void smc91c92_config(dev_link_t *link)
smc->cfg |= CFG_IRQ_SEL_1 | CFG_IRQ_SEL_0;
if ((rev >> 4) >= 7)
smc->cfg |= CFG_MII_SELECT;
- printk(" buffer, %s xcvr\n", (smc->cfg & CFG_MII_SELECT) ?
- "MII" : if_names[dev->if_port]);
- }
+ } else
+ mir = 0;
if (smc->cfg & CFG_MII_SELECT) {
SMC_SELECT_BANK(3);
@@ -1031,16 +1015,45 @@ static void smc91c92_config(dev_link_t *link)
if ((j != 0) && (j != 0xffff)) break;
}
smc->mii_if.phy_id = (i < 32) ? i : -1;
- if (i < 32) {
- DEBUG(0, " MII transceiver at index %d, status %x.\n", i, j);
- } else {
- printk(KERN_NOTICE " No MII transceivers found!\n");
- }
SMC_SELECT_BANK(0);
}
+ link->dev = &smc->node;
link->state &= ~DEV_CONFIG_PENDING;
+
+ if (register_netdev(dev) != 0) {
+ printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n");
+ link->dev = NULL;
+ goto config_undo;
+ }
+
+ strcpy(smc->node.dev_name, dev->name);
+
+ printk(KERN_INFO "%s: smc91c%s rev %d: io %#3lx, irq %d, "
+ "hw_addr ", dev->name, name, (rev & 0x0f), dev->base_addr,
+ dev->irq);
+ for (i = 0; i < 6; i++)
+ printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
+
+ if (rev > 0) {
+ if (mir & 0x3ff)
+ printk(KERN_INFO " %lu byte", mir);
+ else
+ printk(KERN_INFO " %lu kb", mir>>10);
+ printk(" buffer, %s xcvr\n", (smc->cfg & CFG_MII_SELECT) ?
+ "MII" : if_names[dev->if_port]);
+ }
+
+ if (smc->cfg & CFG_MII_SELECT) {
+ if (smc->mii_if.phy_id != -1) {
+ DEBUG(0, " MII transceiver at index %d, status %x.\n",
+ smc->mii_if.phy_id, j);
+ } else {
+ printk(KERN_NOTICE " No MII transceivers found!\n");
+ }
+ }
+
return;
config_undo:
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index f6e47d77ea82..5671f1234ade 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -1114,17 +1114,20 @@ xirc2ps_config(dev_link_t * link)
/* we can now register the device with the net subsystem */
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
+
+ if (local->dingo)
+ do_reset(dev, 1); /* a kludge to make the cem56 work */
+
+ link->dev = &local->node;
+ link->state &= ~DEV_CONFIG_PENDING;
+
if ((err=register_netdev(dev))) {
printk(KNOT_XIRC "register_netdev() failed\n");
+ link->dev = NULL;
goto config_error;
}
strcpy(local->node.dev_name, dev->name);
- link->dev = &local->node;
- link->state &= ~DEV_CONFIG_PENDING;
-
- if (local->dingo)
- do_reset(dev, 1); /* a kludge to make the cem56 work */
/* give some infos about the hardware */
printk(KERN_INFO "%s: %s: port %#3lx, irq %d, hwaddr",
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index 9ae70d7200c4..c3b4d91bcf8e 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -1761,11 +1761,11 @@ static void __devexit tulip_remove_one (struct pci_dev *pdev)
return;
tp = netdev_priv(dev);
+ unregister_netdev(dev);
pci_free_consistent (pdev,
sizeof (struct tulip_rx_desc) * RX_RING_SIZE +
sizeof (struct tulip_tx_desc) * TX_RING_SIZE,
tp->rx_ring, tp->rx_ring_dma);
- unregister_netdev (dev);
if (tp->mtable)
kfree (tp->mtable);
#ifndef USE_IO_OPS
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index 8062c074a302..67cbbb71a9c1 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -3,7 +3,7 @@
Driver for Atmel at76c502 at76c504 and at76c506 wireless cards.
Copyright 2000-2001 ATMEL Corporation.
- Copyright 2003 Simon Kelley.
+ Copyright 2003-2004 Simon Kelley.
This code was developed from version 2.1.1 of the Atmel drivers,
released by Atmel corp. under the GPL in December 2002. It also
@@ -47,6 +47,7 @@
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/ctype.h>
#include <linux/timer.h>
#include <asm/io.h>
#include <asm/system.h>
@@ -70,7 +71,7 @@
#include "ieee802_11.h"
#define DRIVER_MAJOR 0
-#define DRIVER_MINOR 91
+#define DRIVER_MINOR 96
MODULE_AUTHOR("Simon Kelley");
MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards.");
@@ -519,7 +520,6 @@ struct atmel_private {
} host_info;
enum {
- STATION_STATE_INITIALIZING,
STATION_STATE_SCANNING,
STATION_STATE_JOINNING,
STATION_STATE_AUTHENTICATING,
@@ -527,15 +527,14 @@ struct atmel_private {
STATION_STATE_READY,
STATION_STATE_REASSOCIATING,
STATION_STATE_DOWN,
- STATION_STATE_NO_CARD,
- STATION_STATE_MGMT_ERROR
+ STATION_STATE_MGMT_ERROR
} station_state;
int operating_mode, power_mode;
time_t last_qual;
int beacons_this_sec;
int channel;
- int reg_domain;
+ int reg_domain, config_reg_domain;
int tx_rate;
int auto_tx_rate;
int rts_threshold;
@@ -578,6 +577,19 @@ struct atmel_private {
static u8 atmel_basic_rates[4] = {0x82,0x84,0x0b,0x16};
+static const struct {
+ int reg_domain;
+ int min, max;
+ char *name;
+} channel_table[] = { { REG_DOMAIN_FCC, 1, 11, "USA" },
+ { REG_DOMAIN_DOC, 1, 11, "Canada" },
+ { REG_DOMAIN_ETSI, 1, 13, "Europe" },
+ { REG_DOMAIN_SPAIN, 10, 11, "Spain" },
+ { REG_DOMAIN_FRANCE, 10, 13, "France" },
+ { REG_DOMAIN_MKK, 14, 14, "MKK" },
+ { REG_DOMAIN_MKK1, 1, 14, "MKK1" },
+ { REG_DOMAIN_ISRAEL, 3, 9, "Israel"} };
+
static void build_wpa_mib(struct atmel_private *priv);
static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static void atmel_copy_to_card(struct net_device *dev, u16 dest, unsigned char *src, u16 len);
@@ -606,8 +618,9 @@ static void atmel_join_bss(struct atmel_private *priv, int bss_index);
static void atmel_smooth_qual(struct atmel_private *priv);
static void atmel_writeAR(struct net_device *dev, u16 data);
static int probe_atmel_card(struct net_device *dev);
-int reset_atmel_card(struct net_device *dev );
+static int reset_atmel_card(struct net_device *dev );
static void atmel_enter_state(struct atmel_private *priv, int new_state);
+int atmel_open (struct net_device *dev);
static inline u16 atmel_hi(struct atmel_private *priv, u16 offset)
{
@@ -649,7 +662,6 @@ static inline void atmel_write16(struct net_device *dev, u16 offset, u16 data)
outw(data, dev->base_addr + offset);
}
-
static inline u8 atmel_rmem8(struct atmel_private *priv, u16 pos)
{
atmel_writeAR(priv->dev, pos);
@@ -802,14 +814,14 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
u16 buff, frame_ctl, len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
u8 SNAP_RFC1024[6] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
- if (priv->station_state != STATION_STATE_READY) {
+ if (priv->card && priv->present_callback &&
+ !(*priv->present_callback)(priv->card)) {
priv->stats.tx_errors++;
dev_kfree_skb(skb);
return 0;
}
- if (priv->card && priv->present_callback &&
- !(*priv->present_callback)(priv->card)) {
+ if (priv->station_state != STATION_STATE_READY) {
priv->stats.tx_errors++;
dev_kfree_skb(skb);
return 0;
@@ -872,8 +884,8 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
}
static void atmel_transmit_management_frame(struct atmel_private *priv,
- struct ieee802_11_hdr *header,
- u8 *body, int body_len)
+ struct ieee802_11_hdr *header,
+ u8 *body, int body_len)
{
u16 buff;
int len = MGMT_FRAME_BODY_OFFSET + body_len;
@@ -1153,82 +1165,112 @@ static void rx_done_irq(struct atmel_private *priv)
}
}
-static void reset_irq_status(struct atmel_private *priv, u8 mask)
-{
- u8 isr;
-
- atmel_lock_mac(priv);
- isr = atmel_rmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET));
- isr ^= mask;
- atmel_wmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET), isr);
- atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0);
-}
-
static irqreturn_t service_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *) dev_id;
struct atmel_private *priv = netdev_priv(dev);
u8 isr;
-
+ int i = -1;
+ static u8 irq_order[] = {
+ ISR_OUT_OF_RANGE,
+ ISR_RxCOMPLETE,
+ ISR_TxCOMPLETE,
+ ISR_RxFRAMELOST,
+ ISR_FATAL_ERROR,
+ ISR_COMMAND_COMPLETE,
+ ISR_IBSS_MERGE,
+ ISR_GENERIC_IRQ
+ };
+
+
if (priv->card && priv->present_callback &&
!(*priv->present_callback)(priv->card))
return IRQ_HANDLED;
+
+ /* In this state upper-level code assumes it can mess with
+ the card unhampered by interrupts which may change register state.
+ Note that even though the card shouldn't generate interrupts
+ the inturrupt line may be shared. This allows card setup
+ to go on without disabling interrupts for a long time. */
+ if (priv->station_state == STATION_STATE_DOWN)
+ return IRQ_NONE;
atmel_clear_gcr(dev, GCR_ENINT); /* disable interrupts */
-
+
while (1) {
if (!atmel_lock_mac(priv)) {
- printk(KERN_ALERT "%s: MAC gone away in ISR.\n", dev->name);
- /* bad things - don't re-enable interrupts */
+ /* failed to contact card */
+ printk(KERN_ALERT "%s: failed to contact MAC.\n", dev->name);
return IRQ_HANDLED;
}
-
+
isr = atmel_rmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET));
atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0);
- if (isr)
- atmel_set_gcr(dev, GCR_ACKINT); /* acknowledge interrupt */
- else
- break; /* no pending irqs */
-
- if (isr & ISR_OUT_OF_RANGE) {
- reset_irq_status(priv, ISR_OUT_OF_RANGE);
- if(priv->operating_mode == IW_MODE_INFRA &&
- priv->station_state == STATION_STATE_READY) {
+
+ if (!isr) {
+ atmel_set_gcr(dev, GCR_ENINT); /* enable interrupts */
+ return i == -1 ? IRQ_NONE : IRQ_HANDLED;
+ }
+
+ atmel_set_gcr(dev, GCR_ACKINT); /* acknowledge interrupt */
+
+ for (i = 0; i < sizeof(irq_order)/sizeof(u8); i++)
+ if (isr & irq_order[i])
+ break;
+
+ if (!atmel_lock_mac(priv)) {
+ /* failed to contact card */
+ printk(KERN_ALERT "%s: failed to contact MAC.\n", dev->name);
+ return IRQ_HANDLED;
+ }
+
+ isr = atmel_rmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET));
+ isr ^= irq_order[i];
+ atmel_wmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET), isr);
+ atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0);
+
+ switch (irq_order[i]) {
+
+ case ISR_OUT_OF_RANGE:
+ if (priv->operating_mode == IW_MODE_INFRA &&
+ priv->station_state == STATION_STATE_READY) {
priv->station_is_associated = 0;
atmel_scan(priv, 1);
}
- } else if (isr & ISR_RxCOMPLETE) {
- reset_irq_status(priv, ISR_RxCOMPLETE);
+ break;
+
+ case ISR_RxFRAMELOST:
+ priv->wstats.discard.misc++;
+ /* fall through */
+ case ISR_RxCOMPLETE:
rx_done_irq(priv);
- } else if (isr & ISR_TxCOMPLETE) {
- reset_irq_status(priv, ISR_TxCOMPLETE);
+ break;
+
+ case ISR_TxCOMPLETE:
tx_done_irq(priv);
- } else if (isr & ISR_RxFRAMELOST) {
- reset_irq_status(priv, ISR_RxFRAMELOST);
- priv->wstats.discard.misc++;
- rx_done_irq(priv);
- } else if (isr & ISR_FATAL_ERROR) {
- reset_irq_status(priv, ISR_FATAL_ERROR);
+ break;
+
+ case ISR_FATAL_ERROR:
printk(KERN_ALERT "%s: *** FATAL error interrupt ***\n", dev->name);
atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
- } else if (isr & ISR_COMMAND_COMPLETE) {
- reset_irq_status(priv, ISR_COMMAND_COMPLETE);
- atmel_command_irq(priv);
- } else if (isr & ISR_IBSS_MERGE) {
- reset_irq_status(priv, ISR_IBSS_MERGE);
+ break;
+
+ case ISR_COMMAND_COMPLETE:
+ atmel_command_irq(priv);
+ break;
+
+ case ISR_IBSS_MERGE:
atmel_get_mib(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_BSSID_POS,
priv->CurrentBSSID, 6);
/* The WPA stuff cares about the current AP address */
if (priv->use_wpa)
build_wpa_mib(priv);
- } else if (isr & ISR_GENERIC_IRQ) {
- reset_irq_status(priv, ISR_GENERIC_IRQ);
+ break;
+ case ISR_GENERIC_IRQ:
printk(KERN_INFO "%s: Generic_irq recieved.\n", dev->name);
+ break;
}
}
-
- atmel_set_gcr(dev, GCR_ENINT); /* enable interrupts */
- return IRQ_HANDLED;
}
@@ -1256,8 +1298,8 @@ static struct iw_statistics *atmel_get_wireless_stats (struct net_device *dev)
priv->wstats.qual.noise = 0;
priv->wstats.qual.updated = 7;
} else {
- // Quality levels cannot be determined in ad-hoc mode,
- // because we can 'hear' more that one remote station.
+ /* Quality levels cannot be determined in ad-hoc mode,
+ because we can 'hear' more that one remote station. */
priv->wstats.qual.qual = 0;
priv->wstats.qual.level = 0;
priv->wstats.qual.noise = 0;
@@ -1281,18 +1323,62 @@ static int atmel_set_mac_address(struct net_device *dev, void *p)
struct sockaddr *addr = p;
memcpy (dev->dev_addr, addr->sa_data, dev->addr_len);
- reset_atmel_card(dev);
- return 0;
+ return atmel_open(dev);
}
-static int atmel_open (struct net_device *dev)
+EXPORT_SYMBOL(atmel_open);
+
+int atmel_open (struct net_device *dev)
{
struct atmel_private *priv = netdev_priv(dev);
- priv->station_state = STATION_STATE_INITIALIZING;
- if (!reset_atmel_card(dev)) {
- priv->station_state = STATION_STATE_DOWN;
+ int i, channel;
+
+ /* any scheduled timer is no longer needed and might screw things up.. */
+ del_timer_sync(&priv->management_timer);
+
+ /* Interrupts will not touch the card once in this state... */
+ priv->station_state = STATION_STATE_DOWN;
+
+ if (priv->new_SSID_size) {
+ memcpy(priv->SSID, priv->new_SSID, priv->new_SSID_size);
+ priv->SSID_size = priv->new_SSID_size;
+ priv->new_SSID_size = 0;
+ }
+ priv->BSS_list_entries = 0;
+
+ priv->AuthenticationRequestRetryCnt = 0;
+ priv->AssociationRequestRetryCnt = 0;
+ priv->ReAssociationRequestRetryCnt = 0;
+ priv->CurrentAuthentTransactionSeqNum = 0x0001;
+ priv->ExpectedAuthentTransactionSeqNum = 0x0002;
+
+ priv->site_survey_state = SITE_SURVEY_IDLE;
+ priv->station_is_associated = 0;
+
+ if (!reset_atmel_card(dev))
return -EAGAIN;
+
+ if (priv->config_reg_domain) {
+ priv->reg_domain = priv->config_reg_domain;
+ atmel_set_mib8(priv, Phy_Mib_Type, PHY_MIB_REG_DOMAIN_POS, priv->reg_domain);
+ } else {
+ priv->reg_domain = atmel_get_mib8(priv, Phy_Mib_Type, PHY_MIB_REG_DOMAIN_POS);
+ for (i = 0; i < sizeof(channel_table)/sizeof(channel_table[0]); i++)
+ if (priv->reg_domain == channel_table[i].reg_domain)
+ break;
+ if (i == sizeof(channel_table)/sizeof(channel_table[0])) {
+ priv->reg_domain = REG_DOMAIN_MKK1;
+ printk(KERN_ALERT "%s: failed to get regulatory domain: assuming MKK1.\n", dev->name);
+ }
}
+
+ if ((channel = atmel_validate_channel(priv, priv->channel)))
+ priv->channel = channel;
+
+ /* this moves station_state on.... */
+ atmel_scan(priv, 1);
+
+ atmel_set_gcr(priv->dev, GCR_ENINT); /* enable interrupts */
return 0;
}
@@ -1300,19 +1386,34 @@ static int atmel_close (struct net_device *dev)
{
struct atmel_private *priv = netdev_priv(dev);
- netif_carrier_off(dev);
- if (netif_running(dev))
- netif_stop_queue(dev);
+ atmel_enter_state(priv, STATION_STATE_DOWN);
- priv->station_state = STATION_STATE_DOWN;
if (priv->bus_type == BUS_TYPE_PCCARD)
atmel_write16(dev, GCR, 0x0060);
atmel_write16(dev, GCR, 0x0040);
return 0;
}
+static int atmel_validate_channel(struct atmel_private *priv, int channel)
+{
+ /* check that channel is OK, if so return zero,
+ else return suitable default channel */
+ int i;
+
+ for (i = 0; i < sizeof(channel_table)/sizeof(channel_table[0]); i++)
+ if (priv->reg_domain == channel_table[i].reg_domain) {
+ if (channel >= channel_table[i].min &&
+ channel <= channel_table[i].max)
+ return 0;
+ else
+ return channel_table[i].min;
+ }
+ return 0;
+}
+
static int atmel_proc_output (char *buf, struct atmel_private *priv)
{
+ int i;
char *p = buf;
char *s, *r, *c;
@@ -1338,17 +1439,12 @@ static int atmel_proc_output (char *buf, struct atmel_private *priv)
default: c = "<unknown>";
}
- switch (priv->reg_domain) {
- case REG_DOMAIN_FCC: r = "USA"; break;
- case REG_DOMAIN_DOC: r = "Canada"; break;
- case REG_DOMAIN_ETSI: r = "Europe"; break;
- case REG_DOMAIN_SPAIN: r = "Spain"; break;
- case REG_DOMAIN_FRANCE: r = "France"; break;
- case REG_DOMAIN_MKK: r = "Japan (MKK)"; break;
- case REG_DOMAIN_MKK1: r = "Japan (MKK1)"; break;
- case REG_DOMAIN_ISRAEL: r = "Israel"; break;
- default: r = "<unknown>";
- }
+
+ r = "<unknown>";
+ for (i = 0; i < sizeof(channel_table)/sizeof(channel_table[0]); i++)
+ if (priv->reg_domain == channel_table[i].reg_domain)
+ r = channel_table[i].name;
+
p += sprintf(p, "MAC memory type:\t%s\n", c);
p += sprintf(p, "Regulatory domain:\t%s\n", r);
p += sprintf(p, "Host CRC checking:\t%s\n",
@@ -1358,14 +1454,12 @@ static int atmel_proc_output (char *buf, struct atmel_private *priv)
}
switch(priv->station_state) {
- case STATION_STATE_INITIALIZING: s = "Initialising"; break;
case STATION_STATE_SCANNING: s = "Scanning"; break;
case STATION_STATE_JOINNING: s = "Joining"; break;
case STATION_STATE_AUTHENTICATING: s = "Authenticating"; break;
case STATION_STATE_ASSOCIATING: s = "Associating"; break;
case STATION_STATE_READY: s = "Ready"; break;
case STATION_STATE_REASSOCIATING: s = "Reassociating"; break;
- case STATION_STATE_NO_CARD: s = "No card"; break;
case STATION_STATE_MGMT_ERROR: s = "Management error"; break;
case STATION_STATE_DOWN: s = "Down"; break;
default: s = "<unknown>";
@@ -1441,6 +1535,8 @@ struct net_device *init_atmel_card( unsigned short irq, int port, char *firmware
priv->preamble = LONG_PREAMBLE;
priv->operating_mode = IW_MODE_INFRA;
priv->connect_to_any_BSS = 0;
+ priv->config_reg_domain = 0;
+ priv->reg_domain = 0;
priv->tx_rate = 3;
priv->auto_tx_rate = 1;
priv->channel = 4;
@@ -1547,36 +1643,6 @@ void stop_atmel_card(struct net_device *dev, int freeres)
EXPORT_SYMBOL(stop_atmel_card);
-static const struct {
- int reg_domain;
- int min, max;
-} channel_table[] = { { REG_DOMAIN_FCC, 1, 11},
- { REG_DOMAIN_DOC, 1, 11},
- { REG_DOMAIN_ETSI, 1, 13},
- { REG_DOMAIN_SPAIN, 10, 11},
- { REG_DOMAIN_FRANCE, 10, 13},
- { REG_DOMAIN_MKK, 14, 14},
- { REG_DOMAIN_MKK1, 1, 14},
- { REG_DOMAIN_ISRAEL, 9} };
-
-
-static int atmel_validate_channel(struct atmel_private *priv, int channel)
-{
- /* check that channel is OK, if so return zero,
- else return suitable default channel */
- int i;
-
- for (i = 0; i < sizeof(channel_table)/sizeof(channel_table[0]); i++)
- if (priv->reg_domain == channel_table[i].reg_domain) {
- if (channel >= channel_table[i].min &&
- channel <= channel_table[i].max)
- return 0;
- else
- return channel_table[i].min;
- }
- return 1;
-}
-
static int atmel_set_essid(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *dwrq,
@@ -1613,7 +1679,7 @@ static int atmel_get_essid(struct net_device *dev,
struct atmel_private *priv = netdev_priv(dev);
/* Get the current SSID */
- if (priv->SSID_size == 0) {
+ if (priv->new_SSID_size != 0) {
memcpy(extra, priv->new_SSID, priv->new_SSID_size);
extra[priv->new_SSID_size] = '\0';
dwrq->length = priv->new_SSID_size + 1;
@@ -2037,6 +2103,7 @@ static int atmel_set_scan(struct net_device *dev,
char *extra)
{
struct atmel_private *priv = netdev_priv(dev);
+ unsigned long flags;
/* Note : you may have realised that, as this is a SET operation,
* this is privileged and therefore a normal user can't
@@ -2045,8 +2112,7 @@ static int atmel_set_scan(struct net_device *dev,
* traffic doesn't flow, so it's a perfect DoS...
* Jean II */
- if (priv->station_state == STATION_STATE_DOWN ||
- priv->station_state == STATION_STATE_NO_CARD)
+ if (priv->station_state == STATION_STATE_DOWN)
return -EAGAIN;
/* Timeout old surveys. */
@@ -2057,14 +2123,14 @@ static int atmel_set_scan(struct net_device *dev,
/* Initiate a scan command */
if (priv->site_survey_state == SITE_SURVEY_IN_PROGRESS)
return -EBUSY;
+
+ del_timer_sync(&priv->management_timer);
+ spin_lock_irqsave(&priv->irqlock, flags);
priv->site_survey_state = SITE_SURVEY_IN_PROGRESS;
-
- atmel_clear_gcr(dev, GCR_ENINT); /* disable interrupts */
- del_timer_sync(&priv->management_timer);
priv->fast_scan = 0;
atmel_scan(priv, 0);
- atmel_set_gcr(dev, GCR_ENINT); /* enable interrupts */
+ spin_unlock_irqrestore(&priv->irqlock, flags);
return 0;
}
@@ -2116,7 +2182,7 @@ static int atmel_get_scan(struct net_device *dev,
/* Length of data */
dwrq->length = (current_ev - extra);
- dwrq->flags = 0; /* todo */
+ dwrq->flags = 0;
return 0;
}
@@ -2196,15 +2262,16 @@ static int atmel_set_wap(struct net_device *dev,
struct atmel_private *priv = netdev_priv(dev);
int i;
static const u8 bcast[] = { 255, 255, 255, 255, 255, 255 };
-
+ unsigned long flags;
+
if (awrq->sa_family != ARPHRD_ETHER)
return -EINVAL;
if (memcmp(bcast, awrq->sa_data, 6) == 0) {
- atmel_clear_gcr(dev, GCR_ENINT); /* disable interrupts */
del_timer_sync(&priv->management_timer);
+ spin_lock_irqsave(&priv->irqlock, flags);
atmel_scan(priv, 1);
- atmel_set_gcr(dev, GCR_ENINT); /* enable interrupts */
+ spin_unlock_irqrestore(&priv->irqlock, flags);
return 0;
}
@@ -2214,9 +2281,13 @@ static int atmel_set_wap(struct net_device *dev,
return -EINVAL;
} else if (priv->wep_is_on && !priv->BSSinfo[i].UsingWEP) {
return -EINVAL;
- } else
- atmel_join_bss(priv, i);
- return 0;
+ } else {
+ del_timer_sync(&priv->management_timer);
+ spin_lock_irqsave(&priv->irqlock, flags);
+ atmel_join_bss(priv, i);
+ spin_unlock_irqrestore(&priv->irqlock, flags);
+ return 0;
+ }
}
}
@@ -2228,8 +2299,7 @@ static int atmel_config_commit(struct net_device *dev,
void *zwrq, /* NULL */
char *extra) /* NULL */
{
- reset_atmel_card(dev);
- return 0;
+ return atmel_open(dev);
}
static const iw_handler atmel_handler[] =
@@ -2297,12 +2367,15 @@ typedef struct atmel_priv_ioctl {
#define ATMELFWL SIOCIWFIRSTPRIV
#define ATMELIDIFC ATMELFWL + 1
+#define ATMELRD ATMELFWL + 2
#define ATMELMAGIC 0x51807
+#define REGDOMAINSZ 20
static const struct iw_priv_args atmel_private_args[] = {
/*{ cmd, set_args, get_args, name } */
{ ATMELFWL, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof (atmel_priv_ioctl), IW_PRIV_TYPE_NONE, "atmelfwl" },
{ ATMELIDIFC, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "atmelidifc" },
+ { ATMELRD, IW_PRIV_TYPE_CHAR | REGDOMAINSZ, IW_PRIV_TYPE_NONE, "regdomain" },
};
static const struct iw_handler_def atmel_handler_def =
@@ -2317,11 +2390,12 @@ static const struct iw_handler_def atmel_handler_def =
static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
- int rc = 0;
+ int i, rc = 0;
struct atmel_private *priv = netdev_priv(dev);
atmel_priv_ioctl com;
struct iwreq *wrq = (struct iwreq *) rq;
unsigned char *new_firmware;
+ char domain[REGDOMAINSZ+1];
switch (cmd) {
case SIOCGIWPRIV:
@@ -2371,6 +2445,39 @@ static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
priv->firmware_id[31] = '\0';
break;
+ case ATMELRD:
+ if (copy_from_user(domain, rq->ifr_data, REGDOMAINSZ)) {
+ rc = -EFAULT;
+ break;
+ }
+
+ if (!capable(CAP_NET_ADMIN)) {
+ rc = -EPERM;
+ break;
+ }
+
+ domain[REGDOMAINSZ] = 0;
+ rc = -EINVAL;
+ for (i = 0; i < sizeof(channel_table)/sizeof(channel_table[0]); i++) {
+ /* strcasecmp doesn't exist in the library */
+ char *a = channel_table[i].name;
+ char *b = domain;
+ while (*a) {
+ char c1 = *a++;
+ char c2 = *b++;
+ if (tolower(c1) != tolower(c2))
+ break;
+ }
+ if (!*a && !*b) {
+ priv->config_reg_domain = channel_table[i].reg_domain;
+ rc = 0;
+ }
+ }
+
+ if (rc == 0 && priv->station_state != STATION_STATE_DOWN)
+ rc = atmel_open(dev);
+ break;
+
default:
rc = -EOPNOTSUPP;
}
@@ -2390,10 +2497,12 @@ struct auth_body {
static void atmel_enter_state(struct atmel_private *priv, int new_state)
{
int old_state = priv->station_state;
-
+
if (new_state == old_state)
return;
-
+
+ priv->station_state = new_state;
+
if (new_state == STATION_STATE_READY) {
netif_start_queue(priv->dev);
netif_carrier_on(priv->dev);
@@ -2401,12 +2510,10 @@ static void atmel_enter_state(struct atmel_private *priv, int new_state)
if (old_state == STATION_STATE_READY) {
netif_carrier_off(priv->dev);
- netif_stop_queue(priv->dev);
+ if (netif_running(priv->dev))
+ netif_stop_queue(priv->dev);
priv->last_beacon_timestamp = 0;
}
-
- priv->station_state = new_state;
-
}
static void atmel_scan(struct atmel_private *priv, int specific_ssid)
@@ -2423,8 +2530,6 @@ static void atmel_scan(struct atmel_private *priv, int specific_ssid)
u8 SSID_size;
} cmd;
- atmel_enter_state(priv, STATION_STATE_SCANNING);
-
memset(cmd.BSSID, 0xff, 6);
if (priv->fast_scan) {
@@ -2450,6 +2555,10 @@ static void atmel_scan(struct atmel_private *priv, int specific_ssid)
BSS_TYPE_AD_HOC : BSS_TYPE_INFRASTRUCTURE);
atmel_send_command(priv, CMD_Scan, &cmd, sizeof(cmd));
+
+ /* This must come after all hardware access to avoid being messed up
+ by stuff happening in interrupt context after we leave STATE_DOWN */
+ atmel_enter_state(priv, STATION_STATE_SCANNING);
}
static void join(struct atmel_private *priv, int type)
@@ -3060,16 +3169,12 @@ static void atmel_management_timer(u_long a)
if (priv->card && priv->present_callback &&
!(*priv->present_callback)(priv->card))
return;
-
- if (priv->station_state == STATION_STATE_NO_CARD)
- return;
-
+
spin_lock_irqsave(&priv->irqlock, flags);
switch (priv->station_state) {
case STATION_STATE_AUTHENTICATING:
-
if (priv->AuthenticationRequestRetryCnt >= MAX_AUTHENTICATION_RETRIES) {
atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
priv->station_is_associated = 0;
@@ -3085,7 +3190,6 @@ static void atmel_management_timer(u_long a)
break;
case STATION_STATE_ASSOCIATING:
-
if (priv->AssociationRequestRetryCnt == MAX_ASSOCIATION_RETRIES) {
atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
priv->station_is_associated = 0;
@@ -3100,7 +3204,6 @@ static void atmel_management_timer(u_long a)
break;
case STATION_STATE_REASSOCIATING:
-
if (priv->ReAssociationRequestRetryCnt == MAX_ASSOCIATION_RETRIES) {
atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
priv->station_is_associated = 0;
@@ -3113,7 +3216,7 @@ static void atmel_management_timer(u_long a)
}
break;
-
+
default:
break;
}
@@ -3203,7 +3306,7 @@ static int atmel_wakeup_firmware(struct atmel_private *priv)
struct host_info_struct *iface = &priv->host_info;
u16 mr1, mr3;
int i;
-
+
if (priv->card_type == CARD_TYPE_SPI_FLASH)
atmel_set_gcr(priv->dev, GCR_REMAP);
@@ -3233,7 +3336,6 @@ static int atmel_wakeup_firmware(struct atmel_private *priv)
if ((priv->host_info_base = atmel_read16(priv->dev, MR2)) == 0xffff) {
printk(KERN_ALERT "%s: card missing.\n", priv->dev->name);
- priv->station_state = STATION_STATE_NO_CARD;
return 0;
}
@@ -3271,10 +3373,10 @@ static int atmel_wakeup_firmware(struct atmel_private *priv)
printk(KERN_ALERT "%s: MAC failed MR1 self-test.\n", priv->dev->name);
return 0;
}
-
+
atmel_copy_to_host(priv->dev, (unsigned char *)iface,
priv->host_info_base, sizeof(*iface));
-
+
iface->tx_buff_pos = le16_to_cpu(iface->tx_buff_pos);
iface->tx_buff_size = le16_to_cpu(iface->tx_buff_size);
iface->tx_desc_pos = le16_to_cpu(iface->tx_desc_pos);
@@ -3323,7 +3425,6 @@ static int probe_atmel_card(struct net_device *dev)
printk(KERN_ALERT "%s: MAC failed to boot MAC address reader.\n", dev->name);
} else {
atmel_copy_to_host(dev, dev->dev_addr, atmel_read16(dev, MR2), 6);
-
/* got address, now squash it again until the network
interface is opened */
if (priv->bus_type == BUS_TYPE_PCCARD)
@@ -3469,7 +3570,7 @@ static void build_wpa_mib(struct atmel_private *priv)
atmel_set_mib(priv, Mac_Wep_Mib_Type, 0, (u8 *)&mib, sizeof(mib));
}
-int reset_atmel_card(struct net_device *dev)
+static int reset_atmel_card(struct net_device *dev)
{
/* do everything necessary to wake up the hardware, including
waiting for the lightning strike and throwing the knife switch....
@@ -3485,7 +3586,6 @@ int reset_atmel_card(struct net_device *dev)
including a copy of the firmware's hostinfo stucture
which is the route into the rest of the firmare datastructures. */
- int channel;
struct atmel_private *priv = netdev_priv(dev);
u8 configuration;
@@ -3497,37 +3597,14 @@ int reset_atmel_card(struct net_device *dev)
"",
NULL
};
-
- if (priv->station_state == STATION_STATE_NO_CARD ||
- priv->station_state == STATION_STATE_DOWN)
- return 0;
-
+
/* reset pccard */
if (priv->bus_type == BUS_TYPE_PCCARD)
atmel_write16(priv->dev, GCR, 0x0060);
/* stop card , disable interrupts */
atmel_write16(priv->dev, GCR, 0x0040);
-
- /* any scheduled timer is no longer needed and might screw things up.. */
- del_timer_sync(&priv->management_timer);
- if (priv->new_SSID_size) {
- memcpy(priv->SSID, priv->new_SSID, priv->new_SSID_size);
- priv->SSID_size = priv->new_SSID_size;
- priv->new_SSID_size = 0;
- }
- priv->BSS_list_entries = 0;
-
- priv->AuthenticationRequestRetryCnt = 0;
- priv->AssociationRequestRetryCnt = 0;
- priv->ReAssociationRequestRetryCnt = 0;
- priv->CurrentAuthentTransactionSeqNum = 0x0001;
- priv->ExpectedAuthentTransactionSeqNum = 0x0002;
-
- priv->station_state = STATION_STATE_INITIALIZING;
- priv->site_survey_state = SITE_SURVEY_IDLE;
- priv->station_is_associated = 0;
-
+
if (priv->card_type == CARD_TYPE_EEPROM) {
/* copy in firmware if needed */
const struct firmware *fw_entry = NULL;
@@ -3573,7 +3650,7 @@ int reset_atmel_card(struct net_device *dev)
len = fw_entry->size;
}
- if (len <= 0x6000) {
+ if (len <= 0x6000) {
atmel_write16(priv->dev, BSR, BSS_IRAM);
atmel_copy_to_card(priv->dev, 0, fw, len);
atmel_set_gcr(priv->dev, GCR_REMAP);
@@ -3628,29 +3705,14 @@ int reset_atmel_card(struct net_device *dev)
configuration = atmel_rmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET));
atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET),
configuration | FUNC_CTRL_RxENABLE);
-
- priv->reg_domain = atmel_get_mib8(priv, Phy_Mib_Type, PHY_MIB_REG_DOMAIN_POS);
- if (priv->reg_domain != REG_DOMAIN_FCC &&
- priv->reg_domain != REG_DOMAIN_DOC &&
- priv->reg_domain != REG_DOMAIN_ETSI &&
- priv->reg_domain != REG_DOMAIN_SPAIN &&
- priv->reg_domain != REG_DOMAIN_FRANCE &&
- priv->reg_domain != REG_DOMAIN_MKK &&
- priv->reg_domain != REG_DOMAIN_MKK1 &&
- priv->reg_domain != REG_DOMAIN_ISRAEL) {
- priv->reg_domain = REG_DOMAIN_MKK1;
- printk(KERN_ALERT "%s: failed to get regulatory domain: assuming MKK1.\n", dev->name);
- }
- if ((channel = atmel_validate_channel(priv, priv->channel)))
- priv->channel = channel;
-
+
if (!priv->radio_on_broken) {
if (atmel_send_command_wait(priv, CMD_EnableRadio, NULL, 0) ==
CMD_STATUS_REJECTED_RADIO_OFF) {
printk(KERN_INFO
"%s: cannot turn the radio on. (Hey radio, you're beautiful!)\n",
dev->name);
- return 0;
+ return 0;
}
}
@@ -3674,15 +3736,9 @@ int reset_atmel_card(struct net_device *dev)
else
build_wep_mib(priv);
- atmel_scan(priv, 1);
-
- atmel_set_gcr(priv->dev, GCR_ENINT); /* enable interrupts */
-
return 1;
}
-EXPORT_SYMBOL(reset_atmel_card);
-
static void atmel_send_command(struct atmel_private *priv, int command, void *cmd, int cmd_size)
{
if (cmd)
@@ -3698,16 +3754,17 @@ static int atmel_send_command_wait(struct atmel_private *priv, int command, void
int i, status;
atmel_send_command(priv, command, cmd, cmd_size);
-
- for (i = LOOP_RETRY_LIMIT; i; i--) {
+
+ for (i = 5000; i; i--) {
status = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET));
if (status != CMD_STATUS_IDLE &&
status != CMD_STATUS_IN_PROGRESS)
break;
+ udelay(20);
}
-
+
if (i == 0) {
- printk(KERN_ALERT "%s: command %d failed to complete.\n", priv->dev->name, command);
+ printk(KERN_ALERT "%s: failed to contact MAC.\n", priv->dev->name);
status = CMD_STATUS_HOST_ERROR;
} else {
if (command != CMD_EnableRadio)
@@ -3835,9 +3892,13 @@ static void atmel_clear_gcr(struct net_device *dev, u16 mask)
static int atmel_lock_mac(struct atmel_private *priv)
{
- int i, j = 100;
+ int i, j = 20;
retry:
- for (i = LOOP_RETRY_LIMIT ; atmel_rmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_HOST_OFFSET)) && i ; i--);
+ for (i = 5000; i; i--) {
+ if (!atmel_rmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_HOST_OFFSET)))
+ break;
+ udelay(20);
+ }
if (!i) return 0; /* timed out */
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index 71b19e358c28..06b09a0327c2 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -54,7 +54,6 @@
#include <asm/io.h>
#include <asm/system.h>
#include <linux/wireless.h>
-#include <linux/802_11.h>
/*
@@ -104,7 +103,7 @@ MODULE_PARM(irq_list, "1-4i");
struct net_device *init_atmel_card(int, int, char *, struct device *,
int (*present_func)(void *), void * );
void stop_atmel_card( struct net_device *, int );
-int reset_atmel_card( struct net_device * );
+int atmel_open( struct net_device * );
static void atmel_config(dev_link_t *link);
static void atmel_release(dev_link_t *link);
@@ -335,7 +334,7 @@ static struct {
{ 0, 0, "ATMEL/AT76C504A", "atmel_at76c504a_2958%s.bin", "NoName-504a-2958" },
{ 0, 0, "ATMEL/AT76C504_R", "atmel_at76c504_2958%s.bin", "NoName-504-2958" },
{ MANFID_3COM, 0x0620, NULL, "atmel_at76c502_3com%s.bin", "3com 3CRWE62092B" },
- { MANFID_3COM, 0x0696, NULL, "atmel_at76c502_3com%s.bin", "3com 3CRSHPW_96" },
+ { MANFID_3COM, 0x0696, NULL, "atmel_at76c502_3com%s.bin", "3com 3CRSHPW196" },
{ 0, 0, "SMC/2632W-V2", "atmel_at76c502%s.bin", "SMC 2632W-V2" },
{ 0, 0, "SMC/2632W", "atmel_at76c502d%s.bin", "SMC 2632W-V3" },
{ 0xd601, 0x0007, NULL, "atmel_at76c502%s.bin", "Sitecom WLAN-011" },
@@ -661,7 +660,7 @@ static int atmel_event(event_t event, int priority,
case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG) {
pcmcia_request_configuration(link->handle, &link->conf);
- reset_atmel_card(local->eth_dev);
+ atmel_open(local->eth_dev);
netif_device_attach(local->eth_dev);
}
break;