aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/Kconfig42
-rw-r--r--drivers/net/wireless/airo.c791
-rw-r--r--drivers/net/wireless/atmel.c110
-rw-r--r--drivers/net/wireless/hostap/hostap_ap.c2
-rw-r--r--drivers/net/wireless/hostap/hostap_cs.c2
-rw-r--r--drivers/net/wireless/hostap/hostap_hw.c8
-rw-r--r--drivers/net/wireless/hostap/hostap_ioctl.c4
-rw-r--r--drivers/net/wireless/hostap/hostap_pci.c4
-rw-r--r--drivers/net/wireless/hostap/hostap_plx.c13
-rw-r--r--drivers/net/wireless/ipw2100.c266
-rw-r--r--drivers/net/wireless/ipw2100.h17
-rw-r--r--drivers/net/wireless/ipw2200.c1239
-rw-r--r--drivers/net/wireless/ipw2200.h103
-rw-r--r--drivers/net/wireless/netwave_cs.c2
-rw-r--r--drivers/net/wireless/prism54/oid_mgt.c4
-rw-r--r--drivers/net/wireless/spectrum_cs.c2
-rw-r--r--drivers/net/wireless/strip.c4
-rw-r--r--drivers/net/wireless/wavelan.p.h6
-rw-r--r--drivers/net/wireless/wavelan_cs.p.h9
19 files changed, 1505 insertions, 1123 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index ef85d76575a2..fd17aa8491b6 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -6,7 +6,8 @@ menu "Wireless LAN (non-hamradio)"
depends on NETDEVICES
config NET_RADIO
- bool "Wireless LAN drivers (non-hamradio) & Wireless Extensions"
+ bool "Wireless LAN drivers (non-hamradio)"
+ select WIRELESS_EXT
---help---
Support for wireless LANs and everything having to do with radio,
but not with amateur radio or FM broadcasting.
@@ -24,6 +25,16 @@ config NET_RADIO
the tools from
<http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
+config NET_WIRELESS_RTNETLINK
+ bool "Wireless Extension API over RtNetlink"
+ depends on NET_RADIO
+ ---help---
+ Support the Wireless Extension API over the RtNetlink socket
+ in addition to the traditional ioctl interface (selected above).
+
+ For now, few tools use this facility, but it might grow in the
+ future. The only downside is that it adds 4.5 kB to your kernel.
+
# Note : the cards are obsolete (can't buy them anymore), but the drivers
# are not, as people are still using them...
comment "Obsolete Wireless cards support (pre-802.11)"
@@ -135,8 +146,9 @@ comment "Wireless 802.11b ISA/PCI cards support"
config IPW2100
tristate "Intel PRO/Wireless 2100 Network Connection"
- depends on NET_RADIO && PCI && IEEE80211
+ depends on NET_RADIO && PCI
select FW_LOADER
+ select IEEE80211
---help---
A driver for the Intel PRO/Wireless 2100 Network
Connection 802.11b wireless network adapter.
@@ -188,8 +200,9 @@ config IPW2100_DEBUG
config IPW2200
tristate "Intel PRO/Wireless 2200BG and 2915ABG Network Connection"
- depends on NET_RADIO && IEEE80211 && PCI
+ depends on NET_RADIO && PCI
select FW_LOADER
+ select IEEE80211
---help---
A driver for the Intel PRO/Wireless 2200BG and 2915ABG Network
Connection adapters.
@@ -201,7 +214,7 @@ config IPW2200
In order to use this driver, you will need a firmware image for it.
You can obtain the firmware from
<http://ipw2200.sf.net/>. See the above referenced README.ipw2200
- for information on where to install the firmare images.
+ for information on where to install the firmware images.
You will also very likely need the Wireless Tools in order to
configure your card:
@@ -213,6 +226,19 @@ config IPW2200
say M here and read <file:Documentation/modules.txt>. The module
will be called ipw2200.ko.
+config IPW2200_MONITOR
+ bool "Enable promiscuous mode"
+ depends on IPW2200
+ ---help---
+ Enables promiscuous/monitor mode support for the ipw2200 driver.
+ With this feature compiled into the driver, you can switch to
+ promiscuous mode via the Wireless Tool's Monitor mode. While in this
+ mode, no packets can be sent.
+
+config IPW_QOS
+ bool "Enable QoS support"
+ depends on IPW2200 && EXPERIMENTAL
+
config IPW2200_DEBUG
bool "Enable full debugging output in IPW2200 module."
depends on IPW2200
@@ -239,13 +265,14 @@ config IPW2200_DEBUG
config AIRO
tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards"
- depends on NET_RADIO && ISA_DMA_API && CRYPTO && (PCI || BROKEN)
+ depends on NET_RADIO && ISA_DMA_API && (PCI || BROKEN)
+ select CRYPTO
---help---
This is the standard Linux driver to support Cisco/Aironet ISA and
PCI 802.11 wireless cards.
It supports the new 802.11b cards from Cisco (Cisco 34X, Cisco 35X
- with or without encryption) as well as card before the Cisco
- aquisition (Aironet 4500, Aironet 4800, Aironet 4800B).
+ acquisition (Aironet 4500, Aironet 4800, Aironet 4800B).
This driver support both the standard Linux Wireless Extensions
and Cisco proprietary API, so both the Linux Wireless Tools and the
@@ -387,13 +414,14 @@ config PCMCIA_SPECTRUM
config AIRO_CS
tristate "Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards"
depends on NET_RADIO && PCMCIA && (BROKEN || !M32R)
+ select CRYPTO
---help---
This is the standard Linux driver to support Cisco/Aironet PCMCIA
802.11 wireless cards. This driver is the same as the Aironet
driver part of the Linux Pcmcia package.
It supports the new 802.11b cards from Cisco (Cisco 34X, Cisco 35X
- with or without encryption) as well as card before the Cisco
- aquisition (Aironet 4500, Aironet 4800, Aironet 4800B). It also
+ acquisition (Aironet 4500, Aironet 4800, Aironet 4800B). It also
supports OEM of Cisco such as the DELL TrueMobile 4800 and Xircom
802.11b cards.
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index a4c7ae94614d..108d9fed8f07 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -36,6 +36,7 @@
#include <linux/in.h>
#include <linux/bitops.h>
#include <linux/scatterlist.h>
+#include <linux/crypto.h>
#include <asm/io.h>
#include <asm/system.h>
@@ -87,14 +88,6 @@ static struct pci_driver airo_driver = {
#include <linux/delay.h>
#endif
-/* Support Cisco MIC feature */
-#define MICSUPPORT
-
-#if defined(MICSUPPORT) && !defined(CONFIG_CRYPTO)
-#warning MIC support requires Crypto API
-#undef MICSUPPORT
-#endif
-
/* Hack to do some power saving */
#define POWER_ON_DOWN
@@ -777,6 +770,11 @@ typedef struct {
} BSSListRid;
typedef struct {
+ BSSListRid bss;
+ struct list_head list;
+} BSSListElement;
+
+typedef struct {
u8 rssipct;
u8 rssidBm;
} tdsRssiEntry;
@@ -909,6 +907,7 @@ static char swversion[] = "2.1";
#define NUM_MODULES 2
#define MIC_MSGLEN_MAX 2400
#define EMMH32_MSGLEN_MAX MIC_MSGLEN_MAX
+#define AIRO_DEF_MTU 2312
typedef struct {
u32 size; // size
@@ -1118,7 +1117,6 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp);
static int writerids(struct net_device *dev, aironet_ioctl *comp);
static int flashcard(struct net_device *dev, aironet_ioctl *comp);
#endif /* CISCO_EXT */
-#ifdef MICSUPPORT
static void micinit(struct airo_info *ai);
static int micsetup(struct airo_info *ai);
static int encapsulate(struct airo_info *ai, etherHead *pPacket, MICBuffer *buffer, int len);
@@ -1127,8 +1125,7 @@ static int decapsulate(struct airo_info *ai, MICBuffer *mic, etherHead *pPacket,
static u8 airo_rssi_to_dbm (tdsRssiEntry *rssi_rid, u8 rssi);
static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm);
-#include <linux/crypto.h>
-#endif
+static void airo_networks_free(struct airo_info *ai);
struct airo_info {
struct net_device_stats stats;
@@ -1161,7 +1158,7 @@ struct airo_info {
#define FLAG_COMMIT 13
#define FLAG_RESET 14
#define FLAG_FLASHING 15
-#define JOB_MASK 0x1ff0000
+#define JOB_MASK 0x2ff0000
#define JOB_DIE 16
#define JOB_XMIT 17
#define JOB_XMIT11 18
@@ -1171,6 +1168,7 @@ struct airo_info {
#define JOB_EVENT 22
#define JOB_AUTOWEP 23
#define JOB_WSTATS 24
+#define JOB_SCAN_RESULTS 25
int (*bap_read)(struct airo_info*, u16 *pu16Dst, int bytelen,
int whichbap);
unsigned short *flash;
@@ -1187,15 +1185,13 @@ struct airo_info {
} xmit, xmit11;
struct net_device *wifidev;
struct iw_statistics wstats; // wireless stats
- unsigned long scan_timestamp; /* Time started to scan */
+ unsigned long scan_timeout; /* Time scan should be read */
struct iw_spy_data spy_data;
struct iw_public_data wireless_data;
-#ifdef MICSUPPORT
/* MIC stuff */
struct crypto_tfm *tfm;
mic_module mod[2];
mic_statistics micstats;
-#endif
HostRxDesc rxfids[MPI_MAX_FIDS]; // rx/tx/config MPI350 descriptors
HostTxDesc txfids[MPI_MAX_FIDS];
HostRidDesc config_desc;
@@ -1211,6 +1207,10 @@ struct airo_info {
APListRid *APList;
#define PCI_SHARED_LEN 2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE
char proc_name[IFNAMSIZ];
+
+ struct list_head network_list;
+ struct list_head network_free_list;
+ BSSListElement *networks;
};
static inline int bap_read(struct airo_info *ai, u16 *pu16Dst, int bytelen,
@@ -1229,7 +1229,22 @@ static int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime);
static int flashputbuf(struct airo_info *ai);
static int flashrestart(struct airo_info *ai,struct net_device *dev);
-#ifdef MICSUPPORT
+#define airo_print(type, name, fmt, args...) \
+ { printk(type "airo(%s): " fmt "\n", name, ##args); }
+
+#define airo_print_info(name, fmt, args...) \
+ airo_print(KERN_INFO, name, fmt, ##args)
+
+#define airo_print_dbg(name, fmt, args...) \
+ airo_print(KERN_DEBUG, name, fmt, ##args)
+
+#define airo_print_warn(name, fmt, args...) \
+ airo_print(KERN_WARNING, name, fmt, ##args)
+
+#define airo_print_err(name, fmt, args...) \
+ airo_print(KERN_ERR, name, fmt, ##args)
+
+
/***********************************************************************
* MIC ROUTINES *
***********************************************************************
@@ -1308,7 +1323,7 @@ static int micsetup(struct airo_info *ai) {
ai->tfm = crypto_alloc_tfm("aes", CRYPTO_TFM_REQ_MAY_SLEEP);
if (ai->tfm == NULL) {
- printk(KERN_ERR "airo: failed to load transform for AES\n");
+ airo_print_err(ai->dev->name, "failed to load transform for AES");
return ERROR;
}
@@ -1686,7 +1701,6 @@ static void emmh32_final(emmh32_context *context, u8 digest[4])
digest[2] = (val>>8) & 0xFF;
digest[3] = val & 0xFF;
}
-#endif
static int readBSSListRid(struct airo_info *ai, int first,
BSSListRid *list) {
@@ -1741,11 +1755,11 @@ static int writeWepKeyRid(struct airo_info*ai, WepKeyRid *pwkr, int perm, int lo
wkr.kindex = cpu_to_le16(wkr.kindex);
wkr.klen = cpu_to_le16(wkr.klen);
rc = PC4500_writerid(ai, RID_WEP_TEMP, &wkr, sizeof(wkr), lock);
- if (rc!=SUCCESS) printk(KERN_ERR "airo: WEP_TEMP set %x\n", rc);
+ if (rc!=SUCCESS) airo_print_err(ai->dev->name, "WEP_TEMP set %x", rc);
if (perm) {
rc = PC4500_writerid(ai, RID_WEP_PERM, &wkr, sizeof(wkr), lock);
if (rc!=SUCCESS) {
- printk(KERN_ERR "airo: WEP_PERM set %x\n", rc);
+ airo_print_err(ai->dev->name, "WEP_PERM set %x", rc);
}
}
return rc;
@@ -1924,7 +1938,7 @@ static int mpi_start_xmit(struct sk_buff *skb, struct net_device *dev) {
struct airo_info *ai = dev->priv;
if (!skb) {
- printk(KERN_ERR "airo: %s: skb==NULL\n",__FUNCTION__);
+ airo_print_err(dev->name, "%s: skb == NULL!",__FUNCTION__);
return 0;
}
npacks = skb_queue_len (&ai->txq);
@@ -1970,8 +1984,8 @@ static int mpi_send_packet (struct net_device *dev)
/* get a packet to send */
if ((skb = skb_dequeue(&ai->txq)) == 0) {
- printk (KERN_ERR
- "airo: %s: Dequeue'd zero in send_packet()\n",
+ airo_print_err(dev->name,
+ "%s: Dequeue'd zero in send_packet()",
__FUNCTION__);
return 0;
}
@@ -2005,7 +2019,6 @@ static int mpi_send_packet (struct net_device *dev)
* Firmware automaticly puts 802 header on so
* we don't need to account for it in the length
*/
-#ifdef MICSUPPORT
if (test_bit(FLAG_MIC_CAPABLE, &ai->flags) && ai->micstats.enabled &&
(ntohs(((u16 *)buffer)[6]) != 0x888E)) {
MICBuffer pMic;
@@ -2022,9 +2035,7 @@ static int mpi_send_packet (struct net_device *dev)
memcpy (sendbuf, &pMic, sizeof(pMic));
sendbuf += sizeof(pMic);
memcpy (sendbuf, buffer, len - sizeof(etherHead));
- } else
-#endif
- {
+ } else {
*payloadLen = cpu_to_le16(len - sizeof(etherHead));
dev->trans_start = jiffies;
@@ -2126,7 +2137,7 @@ static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) {
u32 *fids = priv->fids;
if ( skb == NULL ) {
- printk( KERN_ERR "airo: skb == NULL!!!\n" );
+ airo_print_err(dev->name, "%s: skb == NULL!", __FUNCTION__);
return 0;
}
@@ -2197,7 +2208,7 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {
}
if ( skb == NULL ) {
- printk( KERN_ERR "airo: skb == NULL!!!\n" );
+ airo_print_err(dev->name, "%s: skb == NULL!", __FUNCTION__);
return 0;
}
@@ -2382,6 +2393,8 @@ void stop_airo_card( struct net_device *dev, int freeres )
dev_kfree_skb(skb);
}
+ airo_networks_free (ai);
+
kfree(ai->flash);
kfree(ai->rssi);
kfree(ai->APList);
@@ -2400,9 +2413,7 @@ void stop_airo_card( struct net_device *dev, int freeres )
ai->shared, ai->shared_dma);
}
}
-#ifdef MICSUPPORT
crypto_free_tfm(ai->tfm);
-#endif
del_airo_dev( dev );
free_netdev( dev );
}
@@ -2454,7 +2465,7 @@ static int mpi_init_descriptors (struct airo_info *ai)
cmd.parm2 = MPI_MAX_FIDS;
rc=issuecommand(ai, &cmd, &rsp);
if (rc != SUCCESS) {
- printk(KERN_ERR "airo: Couldn't allocate RX FID\n");
+ airo_print_err(ai->dev->name, "Couldn't allocate RX FID");
return rc;
}
@@ -2482,7 +2493,7 @@ static int mpi_init_descriptors (struct airo_info *ai)
rc=issuecommand(ai, &cmd, &rsp);
if (rc != SUCCESS) {
- printk(KERN_ERR "airo: Couldn't allocate TX FID\n");
+ airo_print_err(ai->dev->name, "Couldn't allocate TX FID");
return rc;
}
@@ -2496,7 +2507,7 @@ static int mpi_init_descriptors (struct airo_info *ai)
cmd.parm2 = 1; /* Magic number... */
rc=issuecommand(ai, &cmd, &rsp);
if (rc != SUCCESS) {
- printk(KERN_ERR "airo: Couldn't allocate RID\n");
+ airo_print_err(ai->dev->name, "Couldn't allocate RID");
return rc;
}
@@ -2528,25 +2539,25 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
aux_len = AUXMEMSIZE;
if (!request_mem_region(mem_start, mem_len, name)) {
- printk(KERN_ERR "airo: Couldn't get region %x[%x] for %s\n",
+ airo_print_err(ai->dev->name, "Couldn't get region %x[%x] for %s",
(int)mem_start, (int)mem_len, name);
goto out;
}
if (!request_mem_region(aux_start, aux_len, name)) {
- printk(KERN_ERR "airo: Couldn't get region %x[%x] for %s\n",
+ airo_print_err(ai->dev->name, "Couldn't get region %x[%x] for %s",
(int)aux_start, (int)aux_len, name);
goto free_region1;
}
ai->pcimem = ioremap(mem_start, mem_len);
if (!ai->pcimem) {
- printk(KERN_ERR "airo: Couldn't map region %x[%x] for %s\n",
+ airo_print_err(ai->dev->name, "Couldn't map region %x[%x] for %s",
(int)mem_start, (int)mem_len, name);
goto free_region2;
}
ai->pciaux = ioremap(aux_start, aux_len);
if (!ai->pciaux) {
- printk(KERN_ERR "airo: Couldn't map region %x[%x] for %s\n",
+ airo_print_err(ai->dev->name, "Couldn't map region %x[%x] for %s",
(int)aux_start, (int)aux_len, name);
goto free_memmap;
}
@@ -2554,7 +2565,7 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
/* Reserve PKTSIZE for each fid and 2K for the Rids */
ai->shared = pci_alloc_consistent(pci, PCI_SHARED_LEN, &ai->shared_dma);
if (!ai->shared) {
- printk(KERN_ERR "airo: Couldn't alloc_consistent %d\n",
+ airo_print_err(ai->dev->name, "Couldn't alloc_consistent %d",
PCI_SHARED_LEN);
goto free_auxmap;
}
@@ -2646,7 +2657,7 @@ static void wifi_setup(struct net_device *dev)
dev->type = ARPHRD_IEEE80211;
dev->hard_header_len = ETH_HLEN;
- dev->mtu = 2312;
+ dev->mtu = AIRO_DEF_MTU;
dev->addr_len = ETH_ALEN;
dev->tx_queue_len = 100;
@@ -2690,6 +2701,42 @@ static int reset_card( struct net_device *dev , int lock) {
return 0;
}
+#define MAX_NETWORK_COUNT 64
+static int airo_networks_allocate(struct airo_info *ai)
+{
+ if (ai->networks)
+ return 0;
+
+ ai->networks =
+ kzalloc(MAX_NETWORK_COUNT * sizeof(BSSListElement),
+ GFP_KERNEL);
+ if (!ai->networks) {
+ airo_print_warn(ai->dev->name, "Out of memory allocating beacons");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void airo_networks_free(struct airo_info *ai)
+{
+ if (!ai->networks)
+ return;
+ kfree(ai->networks);
+ ai->networks = NULL;
+}
+
+static void airo_networks_initialize(struct airo_info *ai)
+{
+ int i;
+
+ INIT_LIST_HEAD(&ai->network_free_list);
+ INIT_LIST_HEAD(&ai->network_list);
+ for (i = 0; i < MAX_NETWORK_COUNT; i++)
+ list_add_tail(&ai->networks[i].list,
+ &ai->network_free_list);
+}
+
static struct net_device *_init_airo_card( unsigned short irq, int port,
int is_pcmcia, struct pci_dev *pci,
struct device *dmdev )
@@ -2701,22 +2748,22 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
/* Create the network device object. */
dev = alloc_etherdev(sizeof(*ai));
if (!dev) {
- printk(KERN_ERR "airo: Couldn't alloc_etherdev\n");
+ airo_print_err("", "Couldn't alloc_etherdev");
return NULL;
}
if (dev_alloc_name(dev, dev->name) < 0) {
- printk(KERN_ERR "airo: Couldn't get name!\n");
+ airo_print_err("", "Couldn't get name!");
goto err_out_free;
}
ai = dev->priv;
ai->wifidev = NULL;
ai->flags = 0;
+ ai->dev = dev;
if (pci && (pci->device == 0x5000 || pci->device == 0xa504)) {
- printk(KERN_DEBUG "airo: Found an MPI350 card\n");
+ airo_print_dbg(dev->name, "Found an MPI350 card");
set_bit(FLAG_MPI, &ai->flags);
}
- ai->dev = dev;
spin_lock_init(&ai->aux_lock);
sema_init(&ai->sem, 1);
ai->config.len = 0;
@@ -2726,13 +2773,15 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
ai->thr_pid = kernel_thread(airo_thread, dev, CLONE_FS | CLONE_FILES);
if (ai->thr_pid < 0)
goto err_out_free;
-#ifdef MICSUPPORT
ai->tfm = NULL;
-#endif
rc = add_airo_dev( dev );
if (rc)
goto err_out_thr;
+ if (airo_networks_allocate (ai))
+ goto err_out_unlink;
+ airo_networks_initialize (ai);
+
/* The Airo-specific entries in the device structure. */
if (test_bit(FLAG_MPI,&ai->flags)) {
skb_queue_head_init (&ai->txq);
@@ -2754,33 +2803,33 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
SET_NETDEV_DEV(dev, dmdev);
-
reset_card (dev, 1);
msleep(400);
rc = request_irq( dev->irq, airo_interrupt, SA_SHIRQ, dev->name, dev );
if (rc) {
- printk(KERN_ERR "airo: register interrupt %d failed, rc %d\n", irq, rc );
+ airo_print_err(dev->name, "register interrupt %d failed, rc %d",
+ irq, rc);
goto err_out_unlink;
}
if (!is_pcmcia) {
if (!request_region( dev->base_addr, 64, dev->name )) {
rc = -EBUSY;
- printk(KERN_ERR "airo: Couldn't request region\n");
+ airo_print_err(dev->name, "Couldn't request region");
goto err_out_irq;
}
}
if (test_bit(FLAG_MPI,&ai->flags)) {
if (mpi_map_card(ai, pci, dev->name)) {
- printk(KERN_ERR "airo: Could not map memory\n");
+ airo_print_err(dev->name, "Could not map memory");
goto err_out_res;
}
}
if (probe) {
if ( setup_card( ai, dev->dev_addr, 1 ) != SUCCESS ) {
- printk( KERN_ERR "airo: MAC could not be enabled\n" );
+ airo_print_err(dev->name, "MAC could not be enabled" );
rc = -EIO;
goto err_out_map;
}
@@ -2791,21 +2840,20 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
rc = register_netdev(dev);
if (rc) {
- printk(KERN_ERR "airo: Couldn't register_netdev\n");
+ airo_print_err(dev->name, "Couldn't register_netdev");
goto err_out_map;
}
ai->wifidev = init_wifidev(ai, dev);
set_bit(FLAG_REGISTERED,&ai->flags);
- printk( KERN_INFO "airo: MAC enabled %s %x:%x:%x:%x:%x:%x\n",
- dev->name,
+ airo_print_info(dev->name, "MAC enabled %x:%x:%x:%x:%x:%x",
dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5] );
/* Allocate the transmit buffers */
if (probe && !test_bit(FLAG_MPI,&ai->flags))
for( i = 0; i < MAX_FIDS; i++ )
- ai->fids[i] = transmit_allocate(ai,2312,i>=MAX_FIDS/2);
+ ai->fids[i] = transmit_allocate(ai,AIRO_DEF_MTU,i>=MAX_FIDS/2);
setup_proc_entry( dev, dev->priv ); /* XXX check for failure */
netif_start_queue(dev);
@@ -2862,16 +2910,16 @@ int reset_airo_card( struct net_device *dev )
return -1;
if ( setup_card(ai, dev->dev_addr, 1 ) != SUCCESS ) {
- printk( KERN_ERR "airo: MAC could not be enabled\n" );
+ airo_print_err(dev->name, "MAC could not be enabled");
return -1;
}
- printk( KERN_INFO "airo: MAC enabled %s %x:%x:%x:%x:%x:%x\n", dev->name,
+ airo_print_info(dev->name, "MAC enabled %x:%x:%x:%x:%x:%x",
dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
/* Allocate the transmit buffers if needed */
if (!test_bit(FLAG_MPI,&ai->flags))
for( i = 0; i < MAX_FIDS; i++ )
- ai->fids[i] = transmit_allocate (ai,2312,i>=MAX_FIDS/2);
+ ai->fids[i] = transmit_allocate (ai,AIRO_DEF_MTU,i>=MAX_FIDS/2);
enable_interrupts( ai );
netif_wake_queue(dev);
@@ -2897,6 +2945,65 @@ static void airo_send_event(struct net_device *dev) {
wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
}
+static void airo_process_scan_results (struct airo_info *ai) {
+ union iwreq_data wrqu;
+ BSSListRid BSSList;
+ int rc;
+ BSSListElement * loop_net;
+ BSSListElement * tmp_net;
+
+ /* Blow away current list of scan results */
+ list_for_each_entry_safe (loop_net, tmp_net, &ai->network_list, list) {
+ list_move_tail (&loop_net->list, &ai->network_free_list);
+ /* Don't blow away ->list, just BSS data */
+ memset (loop_net, 0, sizeof (loop_net->bss));
+ }
+
+ /* Try to read the first entry of the scan result */
+ rc = PC4500_readrid(ai, RID_BSSLISTFIRST, &BSSList, sizeof(BSSList), 0);
+ if((rc) || (BSSList.index == 0xffff)) {
+ /* No scan results */
+ goto out;
+ }
+
+ /* Read and parse all entries */
+ tmp_net = NULL;
+ while((!rc) && (BSSList.index != 0xffff)) {
+ /* Grab a network off the free list */
+ if (!list_empty(&ai->network_free_list)) {
+ tmp_net = list_entry(ai->network_free_list.next,
+ BSSListElement, list);
+ list_del(ai->network_free_list.next);
+ }
+
+ if (tmp_net != NULL) {
+ memcpy(tmp_net, &BSSList, sizeof(tmp_net->bss));
+ list_add_tail(&tmp_net->list, &ai->network_list);
+ tmp_net = NULL;
+ }
+
+ /* Read next entry */
+ rc = PC4500_readrid(ai, RID_BSSLISTNEXT,
+ &BSSList, sizeof(BSSList), 0);
+ }
+
+out:
+ ai->scan_timeout = 0;
+ clear_bit(JOB_SCAN_RESULTS, &ai->flags);
+ up(&ai->sem);
+
+ /* Send an empty event to user space.
+ * We don't send the received data on
+ * the event because it would require
+ * us to do complex transcoding, and
+ * we want to minimise the work done in
+ * the irq handler. Use a request to
+ * extract the data - Jean II */
+ wrqu.data.length = 0;
+ wrqu.data.flags = 0;
+ wireless_send_event(ai->dev, SIOCGIWSCAN, &wrqu, NULL);
+}
+
static int airo_thread(void *data) {
struct net_device *dev = data;
struct airo_info *ai = dev->priv;
@@ -2926,13 +3033,26 @@ static int airo_thread(void *data) {
set_current_state(TASK_INTERRUPTIBLE);
if (ai->flags & JOB_MASK)
break;
- if (ai->expires) {
- if (time_after_eq(jiffies,ai->expires)){
+ if (ai->expires || ai->scan_timeout) {
+ if (ai->scan_timeout &&
+ time_after_eq(jiffies,ai->scan_timeout)){
+ set_bit(JOB_SCAN_RESULTS,&ai->flags);
+ break;
+ } else if (ai->expires &&
+ time_after_eq(jiffies,ai->expires)){
set_bit(JOB_AUTOWEP,&ai->flags);
break;
}
if (!signal_pending(current)) {
- schedule_timeout(ai->expires - jiffies);
+ unsigned long wake_at;
+ if (!ai->expires || !ai->scan_timeout) {
+ wake_at = max(ai->expires,
+ ai->scan_timeout);
+ } else {
+ wake_at = min(ai->expires,
+ ai->scan_timeout);
+ }
+ schedule_timeout(wake_at - jiffies);
continue;
}
} else if (!signal_pending(current)) {
@@ -2969,14 +3089,16 @@ static int airo_thread(void *data) {
airo_read_wireless_stats(ai);
else if (test_bit(JOB_PROMISC, &ai->flags))
airo_set_promisc(ai);
-#ifdef MICSUPPORT
else if (test_bit(JOB_MIC, &ai->flags))
micinit(ai);
-#endif
else if (test_bit(JOB_EVENT, &ai->flags))
airo_send_event(dev);
else if (test_bit(JOB_AUTOWEP, &ai->flags))
timer_func(dev);
+ else if (test_bit(JOB_SCAN_RESULTS, &ai->flags))
+ airo_process_scan_results(ai);
+ else /* Shouldn't get here, but we make sure to unlock */
+ up(&ai->sem);
}
complete_and_exit (&ai->thr_exited, 0);
}
@@ -3010,12 +3132,10 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
if ( status & EV_MIC ) {
OUT4500( apriv, EVACK, EV_MIC );
-#ifdef MICSUPPORT
if (test_bit(FLAG_MIC_CAPABLE, &apriv->flags)) {
set_bit(JOB_MIC, &apriv->flags);
wake_up_interruptible(&apriv->thr_wait);
}
-#endif
}
if ( status & EV_LINK ) {
union iwreq_data wrqu;
@@ -3073,19 +3193,15 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
* and reassociations as valid status
* Jean II */
if(newStatus == ASSOCIATED) {
- if (apriv->scan_timestamp) {
- /* Send an empty event to user space.
- * We don't send the received data on
- * the event because it would require
- * us to do complex transcoding, and
- * we want to minimise the work done in
- * the irq handler. Use a request to
- * extract the data - Jean II */
- wrqu.data.length = 0;
- wrqu.data.flags = 0;
- wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
- apriv->scan_timestamp = 0;
+#if 0
+ /* FIXME: Grabbing scan results here
+ * seems to be too early??? Just wait for
+ * timeout instead. */
+ if (apriv->scan_timeout > 0) {
+ set_bit(JOB_SCAN_RESULTS, &apriv->flags);
+ wake_up_interruptible(&apriv->thr_wait);
}
+#endif
if (down_trylock(&apriv->sem) != 0) {
set_bit(JOB_EVENT, &apriv->flags);
wake_up_interruptible(&apriv->thr_wait);
@@ -3143,8 +3259,8 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
}
len = le16_to_cpu(hdr.len);
- if (len > 2312) {
- printk( KERN_ERR "airo: Bad size %d\n", len );
+ if (len > AIRO_DEF_MTU) {
+ airo_print_err(apriv->dev->name, "Bad size %d", len);
goto badrx;
}
if (len == 0)
@@ -3187,18 +3303,17 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
bap_read (apriv, &gap, sizeof(gap), BAP0);
gap = le16_to_cpu(gap);
if (gap) {
- if (gap <= 8)
+ if (gap <= 8) {
bap_read (apriv, tmpbuf, gap, BAP0);
- else
- printk(KERN_ERR "airo: gaplen too big. Problems will follow...\n");
+ } else {
+ airo_print_err(apriv->dev->name, "gaplen too "
+ "big. Problems will follow...");
+ }
}
bap_read (apriv, buffer + hdrlen/2, len, BAP0);
} else {
-#ifdef MICSUPPORT
MICBuffer micbuf;
-#endif
bap_read (apriv, buffer, ETH_ALEN*2, BAP0);
-#ifdef MICSUPPORT
if (apriv->micstats.enabled) {
bap_read (apriv,(u16*)&micbuf,sizeof(micbuf),BAP0);
if (ntohs(micbuf.typelen) > 0x05DC)
@@ -3211,15 +3326,10 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
skb_trim (skb, len + hdrlen);
}
}
-#endif
bap_read(apriv,buffer+ETH_ALEN,len,BAP0);
-#ifdef MICSUPPORT
if (decapsulate(apriv,&micbuf,(etherHead*)buffer,len)) {
badmic:
dev_kfree_skb_irq (skb);
-#else
- if (0) {
-#endif
badrx:
OUT4500( apriv, EVACK, EV_RX);
goto exitrx;
@@ -3315,12 +3425,13 @@ exitrx:
}
} else {
OUT4500( apriv, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC));
- printk( KERN_ERR "airo: Unallocated FID was used to xmit\n" );
+ airo_print_err(apriv->dev->name, "Unallocated FID was "
+ "used to xmit" );
}
}
exittx:
if ( status & ~STATUS_INTS & ~IGNORE_INTS )
- printk( KERN_WARNING "airo: Got weird status %x\n",
+ airo_print_warn(apriv->dev->name, "Got weird status %x",
status & ~STATUS_INTS & ~IGNORE_INTS );
}
@@ -3393,8 +3504,8 @@ static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock ) {
up(&ai->sem);
if (rc)
- printk(KERN_ERR "%s: Cannot enable MAC, err=%d\n",
- __FUNCTION__,rc);
+ airo_print_err(ai->dev->name, "%s: Cannot enable MAC, err=%d",
+ __FUNCTION__, rc);
return rc;
}
@@ -3430,10 +3541,8 @@ static void mpi_receive_802_3(struct airo_info *ai)
int len = 0;
struct sk_buff *skb;
char *buffer;
-#ifdef MICSUPPORT
int off = 0;
MICBuffer micbuf;
-#endif
memcpy_fromio(&rxd, ai->rxfids[0].card_ram_off, sizeof(rxd));
/* Make sure we got something */
@@ -3448,7 +3557,6 @@ static void mpi_receive_802_3(struct airo_info *ai)
goto badrx;
}
buffer = skb_put(skb,len);
-#ifdef MICSUPPORT
memcpy(buffer, ai->rxfids[0].virtual_host_addr, ETH_ALEN * 2);
if (ai->micstats.enabled) {
memcpy(&micbuf,
@@ -3470,9 +3578,6 @@ badmic:
dev_kfree_skb_irq (skb);
goto badrx;
}
-#else
- memcpy(buffer, ai->rxfids[0].virtual_host_addr, len);
-#endif
#ifdef WIRELESS_SPY
if (ai->spy_data.spy_number > 0) {
char *sa;
@@ -3529,8 +3634,8 @@ void mpi_receive_802_11 (struct airo_info *ai)
if (ai->wifidev == NULL)
hdr.len = 0;
len = le16_to_cpu(hdr.len);
- if (len > 2312) {
- printk( KERN_ERR "airo: Bad size %d\n", len );
+ if (len > AIRO_DEF_MTU) {
+ airo_print_err(ai->dev->name, "Bad size %d", len);
goto badrx;
}
if (len == 0)
@@ -3571,8 +3676,8 @@ void mpi_receive_802_11 (struct airo_info *ai)
if (gap <= 8)
ptr += gap;
else
- printk(KERN_ERR
- "airo: gaplen too big. Problems will follow...\n");
+ airo_print_err(ai->dev->name,
+ "gaplen too big. Problems will follow...");
}
memcpy ((char *)buffer + hdrlen, ptr, len);
ptr += len;
@@ -3644,15 +3749,15 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
if (issuecommand(ai, &cmd, &rsp) != SUCCESS) {
if (lock)
up(&ai->sem);
- printk(KERN_ERR "airo: Error checking for AUX port\n");
+ airo_print_err(ai->dev->name, "Error checking for AUX port");
return ERROR;
}
if (!aux_bap || rsp.status & 0xff00) {
ai->bap_read = fast_bap_read;
- printk(KERN_DEBUG "airo: Doing fast bap_reads\n");
+ airo_print_dbg(ai->dev->name, "Doing fast bap_reads");
} else {
ai->bap_read = aux_bap_read;
- printk(KERN_DEBUG "airo: Doing AUX bap_reads\n");
+ airo_print_dbg(ai->dev->name, "Doing AUX bap_reads");
}
}
if (lock)
@@ -3683,19 +3788,18 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
if (cap_rid.softCap & 8)
ai->config.rmode |= RXMODE_NORMALIZED_RSSI;
else
- printk(KERN_WARNING "airo: unknown received signal level scale\n");
+ airo_print_warn(ai->dev->name, "unknown received signal "
+ "level scale");
}
ai->config.opmode = adhoc ? MODE_STA_IBSS : MODE_STA_ESS;
ai->config.authType = AUTH_OPEN;
ai->config.modulation = MOD_CCK;
-#ifdef MICSUPPORT
if ((cap_rid.len>=sizeof(cap_rid)) && (cap_rid.extSoftCap&1) &&
(micsetup(ai) == SUCCESS)) {
ai->config.opmode |= MODE_MIC;
set_bit(FLAG_MIC_CAPABLE, &ai->flags);
}
-#endif
/* Save off the MAC */
for( i = 0; i < ETH_ALEN; i++ ) {
@@ -3748,7 +3852,8 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
status = enable_MAC(ai, &rsp, lock);
if ( status != SUCCESS || (rsp.status & 0xFF00) != 0) {
- printk( KERN_ERR "airo: Bad MAC enable reason = %x, rid = %x, offset = %d\n", rsp.rsp0, rsp.rsp1, rsp.rsp2 );
+ airo_print_err(ai->dev->name, "Bad MAC enable reason = %x, rid = %x,"
+ " offset = %d", rsp.rsp0, rsp.rsp1, rsp.rsp2 );
return ERROR;
}
@@ -3791,8 +3896,8 @@ static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) {
}
if ( max_tries == -1 ) {
- printk( KERN_ERR
- "airo: Max tries exceeded when issueing command\n" );
+ airo_print_err(ai->dev->name,
+ "Max tries exceeded when issueing command");
if (IN4500(ai, COMMAND) & COMMAND_BUSY)
OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY);
return ERROR;
@@ -3804,11 +3909,11 @@ static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) {
pRsp->rsp1 = IN4500(ai, RESP1);
pRsp->rsp2 = IN4500(ai, RESP2);
if ((pRsp->status & 0xff00)!=0 && pCmd->cmd != CMD_SOFTRESET) {
- printk (KERN_ERR "airo: cmd= %x\n", pCmd->cmd);
- printk (KERN_ERR "airo: status= %x\n", pRsp->status);
- printk (KERN_ERR "airo: Rsp0= %x\n", pRsp->rsp0);
- printk (KERN_ERR "airo: Rsp1= %x\n", pRsp->rsp1);
- printk (KERN_ERR "airo: Rsp2= %x\n", pRsp->rsp2);
+ airo_print_err(ai->dev->name, "cmd= %x\n", pCmd->cmd);
+ airo_print_err(ai->dev->name, "status= %x\n", pRsp->status);
+ airo_print_err(ai->dev->name, "Rsp0= %x\n", pRsp->rsp0);
+ airo_print_err(ai->dev->name, "Rsp1= %x\n", pRsp->rsp1);
+ airo_print_err(ai->dev->name, "Rsp2= %x\n", pRsp->rsp2);
}
// clear stuck command busy if necessary
@@ -3841,15 +3946,15 @@ static int bap_setup(struct airo_info *ai, u16 rid, u16 offset, int whichbap )
}
} else if ( status & BAP_ERR ) {
/* invalid rid or offset */
- printk( KERN_ERR "airo: BAP error %x %d\n",
+ airo_print_err(ai->dev->name, "BAP error %x %d",
status, whichbap );
return ERROR;
} else if (status & BAP_DONE) { // success
return SUCCESS;
}
if ( !(max_tries--) ) {
- printk( KERN_ERR
- "airo: BAP setup error too many retries\n" );
+ airo_print_err(ai->dev->name,
+ "airo: BAP setup error too many retries\n");
return ERROR;
}
// -- PC4500 missed it, try again
@@ -4004,8 +4109,8 @@ static int PC4500_readrid(struct airo_info *ai, u16 rid, void *pBuf, int len, in
len = min(len, (int)le16_to_cpu(*(u16*)pBuf)) - 2;
if ( len <= 2 ) {
- printk( KERN_ERR
- "airo: Rid %x has a length of %d which is too short\n",
+ airo_print_err(ai->dev->name,
+ "Rid %x has a length of %d which is too short",
(int)rid, (int)len );
rc = ERROR;
goto done;
@@ -4038,8 +4143,8 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid,
Resp rsp;
if (test_bit(FLAG_ENABLED, &ai->flags) && (RID_WEP_TEMP != rid))
- printk(KERN_ERR
- "%s: MAC should be disabled (rid=%04x)\n",
+ airo_print_err(ai->dev->name,
+ "%s: MAC should be disabled (rid=%04x)",
__FUNCTION__, rid);
memset(&cmd, 0, sizeof(cmd));
memset(&rsp, 0, sizeof(rsp));
@@ -4055,7 +4160,7 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid,
&ai->config_desc.rid_desc, sizeof(Rid));
if (len < 4 || len > 2047) {
- printk(KERN_ERR "%s: len=%d\n",__FUNCTION__,len);
+ airo_print_err(ai->dev->name, "%s: len=%d", __FUNCTION__, len);
rc = -1;
} else {
memcpy((char *)ai->config_desc.virtual_host_addr,
@@ -4063,10 +4168,10 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid,
rc = issuecommand(ai, &cmd, &rsp);
if ((rc & 0xff00) != 0) {
- printk(KERN_ERR "%s: Write rid Error %d\n",
- __FUNCTION__,rc);
- printk(KERN_ERR "%s: Cmd=%04x\n",
- __FUNCTION__,cmd.cmd);
+ airo_print_err(ai->dev->name, "%s: Write rid Error %d",
+ __FUNCTION__, rc);
+ airo_print_err(ai->dev->name, "%s: Cmd=%04x",
+ __FUNCTION__, cmd.cmd);
}
if ((rsp.status & 0x7f00))
@@ -4165,20 +4270,17 @@ static int transmit_802_3_packet(struct airo_info *ai, int len, char *pPacket)
len >>= 16;
if (len <= ETH_ALEN * 2) {
- printk( KERN_WARNING "Short packet %d\n", len );
+ airo_print_warn(ai->dev->name, "Short packet %d", len);
return ERROR;
}
len -= ETH_ALEN * 2;
-#ifdef MICSUPPORT
if (test_bit(FLAG_MIC_CAPABLE, &ai->flags) && ai->micstats.enabled &&
(ntohs(((u16 *)pPacket)[6]) != 0x888E)) {
if (encapsulate(ai,(etherHead *)pPacket,&pMic,len) != SUCCESS)
return ERROR;
miclen = sizeof(pMic);
}
-#endif
-
// packet is destination[6], source[6], payload[len-12]
// write the payload length and dst/src/payload
if (bap_setup(ai, txFid, 0x0036, BAP1) != SUCCESS) return ERROR;
@@ -4232,7 +4334,7 @@ static int transmit_802_11_packet(struct airo_info *ai, int len, char *pPacket)
}
if (len < hdrlen) {
- printk( KERN_WARNING "Short packet %d\n", len );
+ airo_print_warn(ai->dev->name, "Short packet %d", len);
return ERROR;
}
@@ -4629,15 +4731,14 @@ static int proc_stats_rid_open( struct inode *inode,
i*4<stats.len; i++){
if (!statsLabels[i]) continue;
if (j+strlen(statsLabels[i])+16>4096) {
- printk(KERN_WARNING
- "airo: Potentially disasterous buffer overflow averted!\n");
+ airo_print_warn(apriv->dev->name,
+ "Potentially disasterous buffer overflow averted!");
break;
}
j+=sprintf(data->rbuffer+j, "%s: %u\n", statsLabels[i], vals[i]);
}
if (i*4>=stats.len){
- printk(KERN_WARNING
- "airo: Got a short rid\n");
+ airo_print_warn(apriv->dev->name, "Got a short rid");
}
data->readlen = j;
return 0;
@@ -4799,7 +4900,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
line += 14;
v = get_dec_u16(line, &i, 4);
- v = (v<0) ? 0 : ((v>2312) ? 2312 : v);
+ v = (v<0) ? 0 : ((v>AIRO_DEF_MTU) ? AIRO_DEF_MTU : v);
ai->config.rtsThres = (u16)v;
set_bit (FLAG_COMMIT, &ai->flags);
} else if ( !strncmp( line, "TXMSDULifetime: ", 16 ) ) {
@@ -4833,7 +4934,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
line += 15;
v = get_dec_u16(line, &i, 4);
- v = (v<256) ? 256 : ((v>2312) ? 2312 : v);
+ v = (v<256) ? 256 : ((v>AIRO_DEF_MTU) ? AIRO_DEF_MTU : v);
v = v & 0xfffe; /* Make sure its even */
ai->config.fragThresh = (u16)v;
set_bit (FLAG_COMMIT, &ai->flags);
@@ -4843,8 +4944,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
case 'd': ai->config.modulation=MOD_DEFAULT; set_bit(FLAG_COMMIT, &ai->flags); break;
case 'c': ai->config.modulation=MOD_CCK; set_bit(FLAG_COMMIT, &ai->flags); break;
case 'm': ai->config.modulation=MOD_MOK; set_bit(FLAG_COMMIT, &ai->flags); break;
- default:
- printk( KERN_WARNING "airo: Unknown modulation\n" );
+ default: airo_print_warn(ai->dev->name, "Unknown modulation");
}
} else if (!strncmp(line, "Preamble: ", 10)) {
line += 10;
@@ -4852,10 +4952,10 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
case 'a': ai->config.preamble=PREAMBLE_AUTO; set_bit(FLAG_COMMIT, &ai->flags); break;
case 'l': ai->config.preamble=PREAMBLE_LONG; set_bit(FLAG_COMMIT, &ai->flags); break;
case 's': ai->config.preamble=PREAMBLE_SHORT; set_bit(FLAG_COMMIT, &ai->flags); break;
- default: printk(KERN_WARNING "airo: Unknown preamble\n");
+ default: airo_print_warn(ai->dev->name, "Unknown preamble");
}
} else {
- printk( KERN_WARNING "Couldn't figure out %s\n", line );
+ airo_print_warn(ai->dev->name, "Couldn't figure out %s", line);
}
while( line[0] && line[0] != '\n' ) line++;
if ( line[0] ) line++;
@@ -5081,7 +5181,6 @@ static int set_wep_key(struct airo_info *ai, u16 index,
wkr.len = sizeof(wkr);
wkr.kindex = 0xffff;
wkr.mac[0] = (char)index;
- if (perm) printk(KERN_INFO "Setting transmit key to %d\n", index);
if (perm) ai->defindex = (char)index;
} else {
// We are actually setting the key
@@ -5090,7 +5189,6 @@ static int set_wep_key(struct airo_info *ai, u16 index,
wkr.klen = keylen;
memcpy( wkr.key, key, keylen );
memcpy( wkr.mac, macaddr, ETH_ALEN );
- printk(KERN_INFO "Setting key %d\n", index);
}
if (perm) disable_MAC(ai, lock);
@@ -5123,7 +5221,7 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
}
j = 2;
} else {
- printk(KERN_ERR "airo: WepKey passed invalid key index\n");
+ airo_print_err(ai->dev->name, "WepKey passed invalid key index");
return;
}
@@ -5536,17 +5634,16 @@ static int __init airo_init_module( void )
airo_entry->gid = proc_gid;
for( i = 0; i < 4 && io[i] && irq[i]; i++ ) {
- printk( KERN_INFO
- "airo: Trying to configure ISA adapter at irq=%d io=0x%x\n",
- irq[i], io[i] );
+ airo_print_info("", "Trying to configure ISA adapter at irq=%d "
+ "io=0x%x", irq[i], io[i] );
if (init_airo_card( irq[i], io[i], 0, NULL ))
have_isa_dev = 1;
}
#ifdef CONFIG_PCI
- printk( KERN_INFO "airo: Probing for PCI adapters\n" );
+ airo_print_info("", "Probing for PCI adapters");
pci_register_driver(&airo_driver);
- printk( KERN_INFO "airo: Finished probing for PCI adapters\n" );
+ airo_print_info("", "Finished probing for PCI adapters");
#endif
/* Always exit with success, as we are a library module
@@ -5558,7 +5655,7 @@ static int __init airo_init_module( void )
static void __exit airo_cleanup_module( void )
{
while( airo_devices ) {
- printk( KERN_INFO "airo: Unregistering %s\n", airo_devices->dev->name );
+ airo_print_info(airo_devices->dev->name, "Unregistering...\n");
stop_airo_card( airo_devices->dev, 1 );
}
#ifdef CONFIG_PCI
@@ -5669,7 +5766,8 @@ static int airo_set_freq(struct net_device *dev,
/* We should do a better check than that,
* based on the card capability !!! */
if((channel < 1) || (channel > 14)) {
- printk(KERN_DEBUG "%s: New channel value of %d is invalid!\n", dev->name, fwrq->m);
+ airo_print_dbg(dev->name, "New channel value of %d is invalid!",
+ fwrq->m);
rc = -EINVAL;
} else {
readConfigRid(local, 1);
@@ -5801,11 +5899,13 @@ static int airo_set_wap(struct net_device *dev,
Cmd cmd;
Resp rsp;
APListRid APList_rid;
- static const unsigned char bcast[ETH_ALEN] = { 255, 255, 255, 255, 255, 255 };
+ static const u8 any[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+ static const u8 off[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
if (awrq->sa_family != ARPHRD_ETHER)
return -EINVAL;
- else if (!memcmp(bcast, awrq->sa_data, ETH_ALEN)) {
+ else if (!memcmp(any, awrq->sa_data, ETH_ALEN) ||
+ !memcmp(off, awrq->sa_data, ETH_ALEN)) {
memset(&cmd, 0, sizeof(cmd));
cmd.cmd=CMD_LOSE_SYNC;
if (down_interruptible(&local->sem))
@@ -5991,8 +6091,8 @@ static int airo_set_rts(struct net_device *dev,
int rthr = vwrq->value;
if(vwrq->disabled)
- rthr = 2312;
- if((rthr < 0) || (rthr > 2312)) {
+ rthr = AIRO_DEF_MTU;
+ if((rthr < 0) || (rthr > AIRO_DEF_MTU)) {
return -EINVAL;
}
readConfigRid(local, 1);
@@ -6015,7 +6115,7 @@ static int airo_get_rts(struct net_device *dev,
readConfigRid(local, 1);
vwrq->value = local->config.rtsThres;
- vwrq->disabled = (vwrq->value >= 2312);
+ vwrq->disabled = (vwrq->value >= AIRO_DEF_MTU);
vwrq->fixed = 1;
return 0;
@@ -6034,8 +6134,8 @@ static int airo_set_frag(struct net_device *dev,
int fthr = vwrq->value;
if(vwrq->disabled)
- fthr = 2312;
- if((fthr < 256) || (fthr > 2312)) {
+ fthr = AIRO_DEF_MTU;
+ if((fthr < 256) || (fthr > AIRO_DEF_MTU)) {
return -EINVAL;
}
fthr &= ~0x1; /* Get an even value - is it really needed ??? */
@@ -6059,7 +6159,7 @@ static int airo_get_frag(struct net_device *dev,
readConfigRid(local, 1);
vwrq->value = local->config.fragThresh;
- vwrq->disabled = (vwrq->value >= 2312);
+ vwrq->disabled = (vwrq->value >= AIRO_DEF_MTU);
vwrq->fixed = 1;
return 0;
@@ -6296,6 +6396,272 @@ static int airo_get_encode(struct net_device *dev,
/*------------------------------------------------------------------*/
/*
+ * Wireless Handler : set extended Encryption parameters
+ */
+static int airo_set_encodeext(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ struct airo_info *local = dev->priv;
+ struct iw_point *encoding = &wrqu->encoding;
+ struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+ CapabilityRid cap_rid; /* Card capability info */
+ int perm = ( encoding->flags & IW_ENCODE_TEMP ? 0 : 1 );
+ u16 currentAuthType = local->config.authType;
+ int idx, key_len, alg = ext->alg, set_key = 1;
+ wep_key_t key;
+
+ /* Is WEP supported ? */
+ readCapabilityRid(local, &cap_rid, 1);
+ /* Older firmware doesn't support this...
+ if(!(cap_rid.softCap & 2)) {
+ return -EOPNOTSUPP;
+ } */
+ readConfigRid(local, 1);
+
+ /* Determine and validate the key index */
+ idx = encoding->flags & IW_ENCODE_INDEX;
+ if (idx) {
+ if (idx < 1 || idx > ((cap_rid.softCap & 0x80) ? 4:1))
+ return -EINVAL;
+ idx--;
+ } else
+ idx = get_wep_key(local, 0xffff);
+
+ if (encoding->flags & IW_ENCODE_DISABLED)
+ alg = IW_ENCODE_ALG_NONE;
+
+ if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
+ /* Only set transmit key index here, actual
+ * key is set below if needed.
+ */
+ set_wep_key(local, idx, NULL, 0, perm, 1);
+ set_key = ext->key_len > 0 ? 1 : 0;
+ }
+
+ if (set_key) {
+ /* Set the requested key first */
+ memset(key.key, 0, MAX_KEY_SIZE);
+ switch (alg) {
+ case IW_ENCODE_ALG_NONE:
+ key.len = 0;
+ break;
+ case IW_ENCODE_ALG_WEP:
+ if (ext->key_len > MIN_KEY_SIZE) {
+ key.len = MAX_KEY_SIZE;
+ } else if (ext->key_len > 0) {
+ key.len = MIN_KEY_SIZE;
+ } else {
+ return -EINVAL;
+ }
+ key_len = min (ext->key_len, key.len);
+ memcpy(key.key, ext->key, key_len);
+ break;
+ default:
+ return -EINVAL;
+ }
+ /* Send the key to the card */
+ set_wep_key(local, idx, key.key, key.len, perm, 1);
+ }
+
+ /* Read the flags */
+ if(encoding->flags & IW_ENCODE_DISABLED)
+ local->config.authType = AUTH_OPEN; // disable encryption
+ if(encoding->flags & IW_ENCODE_RESTRICTED)
+ local->config.authType = AUTH_SHAREDKEY; // Only Both
+ if(encoding->flags & IW_ENCODE_OPEN)
+ local->config.authType = AUTH_ENCRYPT; // Only Wep
+ /* Commit the changes to flags if needed */
+ if (local->config.authType != currentAuthType)
+ set_bit (FLAG_COMMIT, &local->flags);
+
+ return -EINPROGRESS;
+}
+
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get extended Encryption parameters
+ */
+static int airo_get_encodeext(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ struct airo_info *local = dev->priv;
+ struct iw_point *encoding = &wrqu->encoding;
+ struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+ CapabilityRid cap_rid; /* Card capability info */
+ int idx, max_key_len;
+
+ /* Is it supported ? */
+ readCapabilityRid(local, &cap_rid, 1);
+ if(!(cap_rid.softCap & 2)) {
+ return -EOPNOTSUPP;
+ }
+ readConfigRid(local, 1);
+
+ max_key_len = encoding->length - sizeof(*ext);
+ if (max_key_len < 0)
+ return -EINVAL;
+
+ idx = encoding->flags & IW_ENCODE_INDEX;
+ if (idx) {
+ if (idx < 1 || idx > ((cap_rid.softCap & 0x80) ? 4:1))
+ return -EINVAL;
+ idx--;
+ } else
+ idx = get_wep_key(local, 0xffff);
+
+ encoding->flags = idx + 1;
+ memset(ext, 0, sizeof(*ext));
+
+ /* Check encryption mode */
+ switch(local->config.authType) {
+ case AUTH_ENCRYPT:
+ encoding->flags = IW_ENCODE_ALG_WEP | IW_ENCODE_ENABLED;
+ break;
+ case AUTH_SHAREDKEY:
+ encoding->flags = IW_ENCODE_ALG_WEP | IW_ENCODE_ENABLED;
+ break;
+ default:
+ case AUTH_OPEN:
+ encoding->flags = IW_ENCODE_ALG_NONE | IW_ENCODE_DISABLED;
+ break;
+ }
+ /* We can't return the key, so set the proper flag and return zero */
+ encoding->flags |= IW_ENCODE_NOKEY;
+ memset(extra, 0, 16);
+
+ /* Copy the key to the user buffer */
+ ext->key_len = get_wep_key(local, idx);
+ if (ext->key_len > 16) {
+ ext->key_len=0;
+ }
+
+ return 0;
+}
+
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set extended authentication parameters
+ */
+static int airo_set_auth(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct airo_info *local = dev->priv;
+ struct iw_param *param = &wrqu->param;
+ u16 currentAuthType = local->config.authType;
+
+ switch (param->flags & IW_AUTH_INDEX) {
+ case IW_AUTH_WPA_VERSION:
+ case IW_AUTH_CIPHER_PAIRWISE:
+ case IW_AUTH_CIPHER_GROUP:
+ case IW_AUTH_KEY_MGMT:
+ case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+ case IW_AUTH_PRIVACY_INVOKED:
+ /*
+ * airo does not use these parameters
+ */
+ break;
+
+ case IW_AUTH_DROP_UNENCRYPTED:
+ if (param->value) {
+ /* Only change auth type if unencrypted */
+ if (currentAuthType == AUTH_OPEN)
+ local->config.authType = AUTH_ENCRYPT;
+ } else {
+ local->config.authType = AUTH_OPEN;
+ }
+
+ /* Commit the changes to flags if needed */
+ if (local->config.authType != currentAuthType)
+ set_bit (FLAG_COMMIT, &local->flags);
+ break;
+
+ case IW_AUTH_80211_AUTH_ALG: {
+ /* FIXME: What about AUTH_OPEN? This API seems to
+ * disallow setting our auth to AUTH_OPEN.
+ */
+ if (param->value & IW_AUTH_ALG_SHARED_KEY) {
+ local->config.authType = AUTH_SHAREDKEY;
+ } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) {
+ local->config.authType = AUTH_ENCRYPT;
+ } else
+ return -EINVAL;
+ break;
+
+ /* Commit the changes to flags if needed */
+ if (local->config.authType != currentAuthType)
+ set_bit (FLAG_COMMIT, &local->flags);
+ }
+
+ case IW_AUTH_WPA_ENABLED:
+ /* Silently accept disable of WPA */
+ if (param->value > 0)
+ return -EOPNOTSUPP;
+ break;
+
+ default:
+ return -EOPNOTSUPP;
+ }
+ return -EINPROGRESS;
+}
+
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get extended authentication parameters
+ */
+static int airo_get_auth(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct airo_info *local = dev->priv;
+ struct iw_param *param = &wrqu->param;
+ u16 currentAuthType = local->config.authType;
+
+ switch (param->flags & IW_AUTH_INDEX) {
+ case IW_AUTH_DROP_UNENCRYPTED:
+ switch (currentAuthType) {
+ case AUTH_SHAREDKEY:
+ case AUTH_ENCRYPT:
+ param->value = 1;
+ break;
+ default:
+ param->value = 0;
+ break;
+ }
+ break;
+
+ case IW_AUTH_80211_AUTH_ALG:
+ switch (currentAuthType) {
+ case AUTH_SHAREDKEY:
+ param->value = IW_AUTH_ALG_SHARED_KEY;
+ break;
+ case AUTH_ENCRYPT:
+ default:
+ param->value = IW_AUTH_ALG_OPEN_SYSTEM;
+ break;
+ }
+ break;
+
+ case IW_AUTH_WPA_ENABLED:
+ param->value = 0;
+ break;
+
+ default:
+ return -EOPNOTSUPP;
+ }
+ return 0;
+}
+
+
+/*------------------------------------------------------------------*/
+/*
* Wireless Handler : set Tx-Power
*/
static int airo_set_txpow(struct net_device *dev,
@@ -6488,9 +6854,9 @@ static int airo_get_range(struct net_device *dev,
range->throughput = 1500 * 1000;
range->min_rts = 0;
- range->max_rts = 2312;
+ range->max_rts = AIRO_DEF_MTU;
range->min_frag = 256;
- range->max_frag = 2312;
+ range->max_frag = AIRO_DEF_MTU;
if(cap_rid.softCap & 2) {
// WEP: RC4 40 bits
@@ -6751,6 +7117,7 @@ static int airo_set_scan(struct net_device *dev,
struct airo_info *ai = dev->priv;
Cmd cmd;
Resp rsp;
+ int wake = 0;
/* Note : you may have realised that, as this is a SET operation,
* this is privileged and therefore a normal user can't
@@ -6760,17 +7127,25 @@ static int airo_set_scan(struct net_device *dev,
* Jean II */
if (ai->flags & FLAG_RADIO_MASK) return -ENETDOWN;
+ if (down_interruptible(&ai->sem))
+ return -ERESTARTSYS;
+
+ /* If there's already a scan in progress, don't
+ * trigger another one. */
+ if (ai->scan_timeout > 0)
+ goto out;
+
/* Initiate a scan command */
memset(&cmd, 0, sizeof(cmd));
cmd.cmd=CMD_LISTBSS;
- if (down_interruptible(&ai->sem))
- return -ERESTARTSYS;
issuecommand(ai, &cmd, &rsp);
- ai->scan_timestamp = jiffies;
- up(&ai->sem);
-
- /* At this point, just return to the user. */
+ ai->scan_timeout = RUN_AT(3*HZ);
+ wake = 1;
+out:
+ up(&ai->sem);
+ if (wake)
+ wake_up_interruptible(&ai->thr_wait);
return 0;
}
@@ -6890,59 +7265,38 @@ static int airo_get_scan(struct net_device *dev,
char *extra)
{
struct airo_info *ai = dev->priv;
- BSSListRid BSSList;
- int rc;
+ BSSListElement *net;
+ int err = 0;
char *current_ev = extra;
- /* When we are associated again, the scan has surely finished.
- * Just in case, let's make sure enough time has elapsed since
- * we started the scan. - Javier */
- if(ai->scan_timestamp && time_before(jiffies,ai->scan_timestamp+3*HZ)) {
- /* Important note : we don't want to block the caller
- * until results are ready for various reasons.
- * First, managing wait queues is complex and racy
- * (there may be multiple simultaneous callers).
- * Second, we grab some rtnetlink lock before comming
- * here (in dev_ioctl()).
- * Third, the caller can wait on the Wireless Event
- * - Jean II */
+ /* If a scan is in-progress, return -EAGAIN */
+ if (ai->scan_timeout > 0)
return -EAGAIN;
- }
- ai->scan_timestamp = 0;
- /* There's only a race with proc_BSSList_open(), but its
- * consequences are begnign. So I don't bother fixing it - Javier */
-
- /* Try to read the first entry of the scan result */
- rc = PC4500_readrid(ai, RID_BSSLISTFIRST, &BSSList, sizeof(BSSList), 1);
- if((rc) || (BSSList.index == 0xffff)) {
- /* Client error, no scan results...
- * The caller need to restart the scan. */
- return -ENODATA;
- }
+ if (down_interruptible(&ai->sem))
+ return -EAGAIN;
- /* Read and parse all entries */
- while((!rc) && (BSSList.index != 0xffff)) {
+ list_for_each_entry (net, &ai->network_list, list) {
/* Translate to WE format this entry */
current_ev = airo_translate_scan(dev, current_ev,
extra + dwrq->length,
- &BSSList);
+ &net->bss);
/* Check if there is space for one more entry */
if((extra + dwrq->length - current_ev) <= IW_EV_ADDR_LEN) {
/* Ask user space to try again with a bigger buffer */
- return -E2BIG;
+ err = -E2BIG;
+ goto out;
}
-
- /* Read next entry */
- rc = PC4500_readrid(ai, RID_BSSLISTNEXT,
- &BSSList, sizeof(BSSList), 1);
}
+
/* Length of data */
dwrq->length = (current_ev - extra);
dwrq->flags = 0; /* todo */
- return 0;
+out:
+ up(&ai->sem);
+ return err;
}
/*------------------------------------------------------------------*/
@@ -7050,6 +7404,15 @@ static const iw_handler airo_handler[] =
(iw_handler) airo_get_encode, /* SIOCGIWENCODE */
(iw_handler) airo_set_power, /* SIOCSIWPOWER */
(iw_handler) airo_get_power, /* SIOCGIWPOWER */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* SIOCSIWGENIE */
+ (iw_handler) NULL, /* SIOCGIWGENIE */
+ (iw_handler) airo_set_auth, /* SIOCSIWAUTH */
+ (iw_handler) airo_get_auth, /* SIOCGIWAUTH */
+ (iw_handler) airo_set_encodeext, /* SIOCSIWENCODEEXT */
+ (iw_handler) airo_get_encodeext, /* SIOCGIWENCODEEXT */
+ (iw_handler) NULL, /* SIOCSIWPMKSA */
};
/* Note : don't describe AIROIDIFC and AIROOLDIDIFC in here.
@@ -7270,13 +7633,11 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) {
case AIROGSTAT: ridcode = RID_STATUS; break;
case AIROGSTATSD32: ridcode = RID_STATSDELTA; break;
case AIROGSTATSC32: ridcode = RID_STATS; break;
-#ifdef MICSUPPORT
case AIROGMICSTATS:
if (copy_to_user(comp->data, &ai->micstats,
min((int)comp->len,(int)sizeof(ai->micstats))))
return -EFAULT;
return 0;
-#endif
case AIRORRID: ridcode = comp->ridnum; break;
default:
return -EINVAL;
@@ -7308,9 +7669,7 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) {
static int writerids(struct net_device *dev, aironet_ioctl *comp) {
struct airo_info *ai = dev->priv;
int ridcode;
-#ifdef MICSUPPORT
int enabled;
-#endif
Resp rsp;
static int (* writer)(struct airo_info *, u16 rid, const void *, int, int);
unsigned char *iobuf;
@@ -7367,11 +7726,9 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) {
PC4500_readrid(ai,RID_STATSDELTACLEAR,iobuf,RIDSIZE, 1);
-#ifdef MICSUPPORT
enabled = ai->micstats.enabled;
memset(&ai->micstats,0,sizeof(ai->micstats));
ai->micstats.enabled = enabled;
-#endif
if (copy_to_user(comp->data, iobuf,
min((int)comp->len, (int)RIDSIZE))) {
@@ -7487,7 +7844,7 @@ static int cmdreset(struct airo_info *ai) {
disable_MAC(ai, 1);
if(!waitbusy (ai)){
- printk(KERN_INFO "Waitbusy hang before RESET\n");
+ airo_print_info(ai->dev->name, "Waitbusy hang before RESET");
return -EBUSY;
}
@@ -7496,7 +7853,7 @@ static int cmdreset(struct airo_info *ai) {
ssleep(1); /* WAS 600 12/7/00 */
if(!waitbusy (ai)){
- printk(KERN_INFO "Waitbusy hang AFTER RESET\n");
+ airo_print_info(ai->dev->name, "Waitbusy hang AFTER RESET");
return -EBUSY;
}
return 0;
@@ -7524,7 +7881,7 @@ static int setflashmode (struct airo_info *ai) {
if(!waitbusy(ai)) {
clear_bit (FLAG_FLASHING, &ai->flags);
- printk(KERN_INFO "Waitbusy hang after setflash mode\n");
+ airo_print_info(ai->dev->name, "Waitbusy hang after setflash mode");
return -EIO;
}
return 0;
@@ -7553,7 +7910,7 @@ static int flashpchar(struct airo_info *ai,int byte,int dwelltime) {
/* timeout for busy clear wait */
if(waittime <= 0 ){
- printk(KERN_INFO "flash putchar busywait timeout! \n");
+ airo_print_info(ai->dev->name, "flash putchar busywait timeout!");
return -EBUSY;
}
@@ -7642,7 +7999,7 @@ static int flashrestart(struct airo_info *ai,struct net_device *dev){
if (!test_bit(FLAG_MPI,&ai->flags))
for( i = 0; i < MAX_FIDS; i++ ) {
ai->fids[i] = transmit_allocate
- ( ai, 2312, i >= MAX_FIDS / 2 );
+ ( ai, AIRO_DEF_MTU, i >= MAX_FIDS / 2 );
}
ssleep(1); /* Added 12/7/00 */
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index dfc24016ba81..87afa6878f26 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -137,44 +137,6 @@ static struct {
#define MAC_BOOT_COMPLETE 0x0010 // MAC boot has been completed
#define MAC_INIT_OK 0x0002 // MAC boot has been completed
-#define C80211_SUBTYPE_MGMT_ASS_REQUEST 0x00
-#define C80211_SUBTYPE_MGMT_ASS_RESPONSE 0x10
-#define C80211_SUBTYPE_MGMT_REASS_REQUEST 0x20
-#define C80211_SUBTYPE_MGMT_REASS_RESPONSE 0x30
-#define C80211_SUBTYPE_MGMT_ProbeRequest 0x40
-#define C80211_SUBTYPE_MGMT_ProbeResponse 0x50
-#define C80211_SUBTYPE_MGMT_BEACON 0x80
-#define C80211_SUBTYPE_MGMT_ATIM 0x90
-#define C80211_SUBTYPE_MGMT_DISASSOSIATION 0xA0
-#define C80211_SUBTYPE_MGMT_Authentication 0xB0
-#define C80211_SUBTYPE_MGMT_Deauthentication 0xC0
-
-#define C80211_MGMT_AAN_OPENSYSTEM 0x0000
-#define C80211_MGMT_AAN_SHAREDKEY 0x0001
-
-#define C80211_MGMT_CAPABILITY_ESS 0x0001 // see 802.11 p.58
-#define C80211_MGMT_CAPABILITY_IBSS 0x0002 // - " -
-#define C80211_MGMT_CAPABILITY_CFPollable 0x0004 // - " -
-#define C80211_MGMT_CAPABILITY_CFPollRequest 0x0008 // - " -
-#define C80211_MGMT_CAPABILITY_Privacy 0x0010 // - " -
-
-#define C80211_MGMT_SC_Success 0
-#define C80211_MGMT_SC_Unspecified 1
-#define C80211_MGMT_SC_SupportCapabilities 10
-#define C80211_MGMT_SC_ReassDenied 11
-#define C80211_MGMT_SC_AssDenied 12
-#define C80211_MGMT_SC_AuthAlgNotSupported 13
-#define C80211_MGMT_SC_AuthTransSeqNumError 14
-#define C80211_MGMT_SC_AuthRejectChallenge 15
-#define C80211_MGMT_SC_AuthRejectTimeout 16
-#define C80211_MGMT_SC_AssDeniedHandleAP 17
-#define C80211_MGMT_SC_AssDeniedBSSRate 18
-
-#define C80211_MGMT_ElementID_SSID 0
-#define C80211_MGMT_ElementID_SupportedRates 1
-#define C80211_MGMT_ElementID_ChallengeText 16
-#define C80211_MGMT_CAPABILITY_ShortPreamble 0x0020
-
#define MIB_MAX_DATA_BYTES 212
#define MIB_HEADER_SIZE 4 /* first four fields */
@@ -2835,7 +2797,7 @@ static void handle_beacon_probe(struct atmel_private *priv, u16 capability,
u8 channel)
{
int rejoin = 0;
- int new = capability & C80211_MGMT_CAPABILITY_ShortPreamble ?
+ int new = capability & MFIE_TYPE_POWER_CONSTRAINT ?
SHORT_PREAMBLE : LONG_PREAMBLE;
if (priv->preamble != new) {
@@ -2921,11 +2883,11 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
memcpy(header.addr2, priv->dev->dev_addr, 6);
memcpy(header.addr3, priv->CurrentBSSID, 6);
- body.capability = cpu_to_le16(C80211_MGMT_CAPABILITY_ESS);
+ body.capability = cpu_to_le16(WLAN_CAPABILITY_ESS);
if (priv->wep_is_on)
- body.capability |= cpu_to_le16(C80211_MGMT_CAPABILITY_Privacy);
+ body.capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
if (priv->preamble == SHORT_PREAMBLE)
- body.capability |= cpu_to_le16(C80211_MGMT_CAPABILITY_ShortPreamble);
+ body.capability |= cpu_to_le16(MFIE_TYPE_POWER_CONSTRAINT);
body.listen_interval = cpu_to_le16(priv->listen_interval * priv->beacon_period);
@@ -2939,10 +2901,10 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
bodysize = 12 + priv->SSID_size;
}
- ssid_el_p[0] = C80211_MGMT_ElementID_SSID;
+ ssid_el_p[0] = MFIE_TYPE_SSID;
ssid_el_p[1] = priv->SSID_size;
memcpy(ssid_el_p + 2, priv->SSID, priv->SSID_size);
- ssid_el_p[2 + priv->SSID_size] = C80211_MGMT_ElementID_SupportedRates;
+ ssid_el_p[2 + priv->SSID_size] = MFIE_TYPE_RATES;
ssid_el_p[3 + priv->SSID_size] = 4; /* len of suported rates */
memcpy(ssid_el_p + 4 + priv->SSID_size, atmel_basic_rates, 4);
@@ -3004,7 +2966,7 @@ static void store_bss_info(struct atmel_private *priv,
u16 beacon_period, u8 channel, u8 rssi, u8 ssid_len,
u8 *ssid, int is_beacon)
{
- u8 *bss = capability & C80211_MGMT_CAPABILITY_ESS ? header->addr2 : header->addr3;
+ u8 *bss = capability & WLAN_CAPABILITY_ESS ? header->addr2 : header->addr3;
int i, index;
for (index = -1, i = 0; i < priv->BSS_list_entries; i++)
@@ -3030,16 +2992,16 @@ static void store_bss_info(struct atmel_private *priv,
priv->BSSinfo[index].channel = channel;
priv->BSSinfo[index].beacon_period = beacon_period;
- priv->BSSinfo[index].UsingWEP = capability & C80211_MGMT_CAPABILITY_Privacy;
+ priv->BSSinfo[index].UsingWEP = capability & WLAN_CAPABILITY_PRIVACY;
memcpy(priv->BSSinfo[index].SSID, ssid, ssid_len);
priv->BSSinfo[index].SSIDsize = ssid_len;
- if (capability & C80211_MGMT_CAPABILITY_IBSS)
+ if (capability & WLAN_CAPABILITY_IBSS)
priv->BSSinfo[index].BSStype = IW_MODE_ADHOC;
- else if (capability & C80211_MGMT_CAPABILITY_ESS)
+ else if (capability & WLAN_CAPABILITY_ESS)
priv->BSSinfo[index].BSStype =IW_MODE_INFRA;
- priv->BSSinfo[index].preamble = capability & C80211_MGMT_CAPABILITY_ShortPreamble ?
+ priv->BSSinfo[index].preamble = capability & MFIE_TYPE_POWER_CONSTRAINT ?
SHORT_PREAMBLE : LONG_PREAMBLE;
}
@@ -3050,7 +3012,7 @@ static void authenticate(struct atmel_private *priv, u16 frame_len)
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 == WLAN_STATUS_SUCCESS && !priv->wep_is_on) {
/* no WEP */
if (priv->station_was_associated) {
atmel_enter_state(priv, STATION_STATE_REASSOCIATING);
@@ -3063,19 +3025,19 @@ static void authenticate(struct atmel_private *priv, u16 frame_len)
}
}
- if (status == C80211_MGMT_SC_Success && priv->wep_is_on) {
+ if (status == WLAN_STATUS_SUCCESS && priv->wep_is_on) {
int should_associate = 0;
/* WEP */
if (trans_seq_no != priv->ExpectedAuthentTransactionSeqNum)
return;
- if (system == C80211_MGMT_AAN_OPENSYSTEM) {
+ if (system == WLAN_AUTH_OPEN) {
if (trans_seq_no == 0x0002) {
should_associate = 1;
}
- } else if (system == C80211_MGMT_AAN_SHAREDKEY) {
+ } else if (system == WLAN_AUTH_SHARED_KEY) {
if (trans_seq_no == 0x0002 &&
- auth->el_id == C80211_MGMT_ElementID_ChallengeText) {
+ auth->el_id == MFIE_TYPE_CHALLENGE) {
send_authentication_request(priv, system, auth->chall_text, auth->chall_text_len);
return;
} else if (trans_seq_no == 0x0004) {
@@ -3140,8 +3102,8 @@ static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype)
if (frame_len < 8 + rates_len)
return;
- if (status == C80211_MGMT_SC_Success) {
- if (subtype == C80211_SUBTYPE_MGMT_ASS_RESPONSE)
+ if (status == WLAN_STATUS_SUCCESS) {
+ if (subtype == IEEE80211_STYPE_ASSOC_RESP)
priv->AssociationRequestRetryCnt = 0;
else
priv->ReAssociationRequestRetryCnt = 0;
@@ -3178,9 +3140,9 @@ static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype)
return;
}
- if (subtype == C80211_SUBTYPE_MGMT_ASS_RESPONSE &&
- status != C80211_MGMT_SC_AssDeniedBSSRate &&
- status != C80211_MGMT_SC_SupportCapabilities &&
+ if (subtype == IEEE80211_STYPE_ASSOC_RESP &&
+ status != WLAN_STATUS_ASSOC_DENIED_RATES &&
+ status != WLAN_STATUS_CAPS_UNSUPPORTED &&
priv->AssociationRequestRetryCnt < MAX_ASSOCIATION_RETRIES) {
mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
priv->AssociationRequestRetryCnt++;
@@ -3188,9 +3150,9 @@ static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype)
return;
}
- if (subtype == C80211_SUBTYPE_MGMT_REASS_RESPONSE &&
- status != C80211_MGMT_SC_AssDeniedBSSRate &&
- status != C80211_MGMT_SC_SupportCapabilities &&
+ if (subtype == IEEE80211_STYPE_REASSOC_RESP &&
+ status != WLAN_STATUS_ASSOC_DENIED_RATES &&
+ status != WLAN_STATUS_CAPS_UNSUPPORTED &&
priv->AssociationRequestRetryCnt < MAX_ASSOCIATION_RETRIES) {
mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
priv->ReAssociationRequestRetryCnt++;
@@ -3325,8 +3287,8 @@ static void atmel_management_frame(struct atmel_private *priv,
subtype = le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_STYPE;
switch (subtype) {
- case C80211_SUBTYPE_MGMT_BEACON:
- case C80211_SUBTYPE_MGMT_ProbeResponse:
+ case IEEE80211_STYPE_BEACON:
+ case IEEE80211_STYPE_PROBE_RESP:
/* beacon frame has multiple variable-length fields -
never let an engineer loose with a data structure design. */
@@ -3384,19 +3346,19 @@ static void atmel_management_frame(struct atmel_private *priv,
beacon_interval, channel, rssi,
ssid_length,
&beacon->rates_el_id,
- subtype == C80211_SUBTYPE_MGMT_BEACON);
+ subtype == IEEE80211_STYPE_BEACON);
}
break;
- case C80211_SUBTYPE_MGMT_Authentication:
+ case IEEE80211_STYPE_AUTH:
if (priv->station_state == STATION_STATE_AUTHENTICATING)
authenticate(priv, frame_len);
break;
- case C80211_SUBTYPE_MGMT_ASS_RESPONSE:
- case C80211_SUBTYPE_MGMT_REASS_RESPONSE:
+ case IEEE80211_STYPE_ASSOC_RESP:
+ case IEEE80211_STYPE_REASSOC_RESP:
if (priv->station_state == STATION_STATE_ASSOCIATING ||
priv->station_state == STATION_STATE_REASSOCIATING)
@@ -3404,7 +3366,7 @@ static void atmel_management_frame(struct atmel_private *priv,
break;
- case C80211_SUBTYPE_MGMT_DISASSOSIATION:
+ case IEEE80211_STYPE_DISASSOC:
if (priv->station_is_associated &&
priv->operating_mode == IW_MODE_INFRA &&
is_frame_from_current_bss(priv, header)) {
@@ -3417,7 +3379,7 @@ static void atmel_management_frame(struct atmel_private *priv,
break;
- case C80211_SUBTYPE_MGMT_Deauthentication:
+ case IEEE80211_STYPE_DEAUTH:
if (priv->operating_mode == IW_MODE_INFRA &&
is_frame_from_current_bss(priv, header)) {
priv->station_was_associated = 0;
@@ -3453,12 +3415,12 @@ static void atmel_management_timer(u_long a)
priv->AuthenticationRequestRetryCnt = 0;
restart_search(priv);
} else {
- int auth = C80211_MGMT_AAN_OPENSYSTEM;
+ int auth = WLAN_AUTH_OPEN;
priv->AuthenticationRequestRetryCnt++;
priv->CurrentAuthentTransactionSeqNum = 0x0001;
mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
if (priv->wep_is_on && priv->exclude_unencrypted)
- auth = C80211_MGMT_AAN_SHAREDKEY;
+ auth = WLAN_AUTH_SHARED_KEY;
send_authentication_request(priv, auth, NULL, 0);
}
break;
@@ -3558,14 +3520,14 @@ static void atmel_command_irq(struct atmel_private *priv)
priv->station_was_associated = priv->station_is_associated;
atmel_enter_state(priv, STATION_STATE_READY);
} else {
- int auth = C80211_MGMT_AAN_OPENSYSTEM;
+ int auth = WLAN_AUTH_OPEN;
priv->AuthenticationRequestRetryCnt = 0;
atmel_enter_state(priv, STATION_STATE_AUTHENTICATING);
mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
priv->CurrentAuthentTransactionSeqNum = 0x0001;
if (priv->wep_is_on && priv->exclude_unencrypted)
- auth = C80211_MGMT_AAN_SHAREDKEY;
+ auth = WLAN_AUTH_SHARED_KEY;
send_authentication_request(priv, auth, NULL, 0);
}
return;
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
index 753a1de6664b..06c3fa32b310 100644
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -3141,7 +3141,7 @@ int hostap_add_sta(struct ap_data *ap, u8 *sta_addr)
if (ret == 1) {
sta = ap_add_sta(ap, sta_addr);
if (!sta)
- ret = -1;
+ return -1;
sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC;
sta->ap = 1;
memset(sta->supported_rates, 0, sizeof(sta->supported_rates));
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index f8f4503475f9..d335b250923a 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -585,8 +585,6 @@ static int prism2_config(dev_link_t *link)
parse = kmalloc(sizeof(cisparse_t), GFP_KERNEL);
hw_priv = kmalloc(sizeof(*hw_priv), GFP_KERNEL);
if (parse == NULL || hw_priv == NULL) {
- kfree(parse);
- kfree(hw_priv);
ret = -ENOMEM;
goto failed;
}
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
index b1f142d9e232..328e9a1d13b5 100644
--- a/drivers/net/wireless/hostap/hostap_hw.c
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -928,15 +928,15 @@ static int hfa384x_set_rid(struct net_device *dev, u16 rid, void *buf, int len)
res = hfa384x_cmd(dev, HFA384X_CMDCODE_ACCESS_WRITE, rid, NULL, NULL);
up(&local->rid_bap_sem);
+
if (res) {
printk(KERN_DEBUG "%s: hfa384x_set_rid: CMDCODE_ACCESS_WRITE "
"failed (res=%d, rid=%04x, len=%d)\n",
dev->name, res, rid, len);
- return res;
- }
- if (res == -ETIMEDOUT)
- prism2_hw_reset(dev);
+ if (res == -ETIMEDOUT)
+ prism2_hw_reset(dev);
+ }
return res;
}
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
index f3e0ce1ee037..8b37e824dfcb 100644
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -3358,10 +3358,6 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev,
if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
if (!sta_ptr)
local->tx_keyidx = i;
- else if (i) {
- ret = -EINVAL;
- goto done;
- }
}
diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c
index 2e85bdced2dd..194f07097581 100644
--- a/drivers/net/wireless/hostap/hostap_pci.c
+++ b/drivers/net/wireless/hostap/hostap_pci.c
@@ -307,7 +307,7 @@ static int prism2_pci_probe(struct pci_dev *pdev,
memset(hw_priv, 0, sizeof(*hw_priv));
if (pci_enable_device(pdev))
- return -EIO;
+ goto err_out_free;
phymem = pci_resource_start(pdev, 0);
@@ -368,6 +368,8 @@ static int prism2_pci_probe(struct pci_dev *pdev,
err_out_disable:
pci_disable_device(pdev);
prism2_free_local_data(dev);
+
+ err_out_free:
kfree(hw_priv);
return -ENODEV;
diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c
index 94fe2449f099..edaaa943eb8f 100644
--- a/drivers/net/wireless/hostap/hostap_plx.c
+++ b/drivers/net/wireless/hostap/hostap_plx.c
@@ -368,7 +368,7 @@ static int prism2_plx_check_cis(void __iomem *attr_mem, int attr_len,
switch (cis[pos]) {
case CISTPL_CONFIG:
- if (cis[pos + 1] < 1)
+ if (cis[pos + 1] < 2)
goto cis_error;
rmsz = (cis[pos + 2] & 0x3c) >> 2;
rasz = cis[pos + 2] & 0x03;
@@ -390,7 +390,7 @@ static int prism2_plx_check_cis(void __iomem *attr_mem, int attr_len,
break;
case CISTPL_MANFID:
- if (cis[pos + 1] < 4)
+ if (cis[pos + 1] < 5)
goto cis_error;
manfid1 = cis[pos + 2] + (cis[pos + 3] << 8);
manfid2 = cis[pos + 4] + (cis[pos + 5] << 8);
@@ -452,7 +452,7 @@ static int prism2_plx_probe(struct pci_dev *pdev,
memset(hw_priv, 0, sizeof(*hw_priv));
if (pci_enable_device(pdev))
- return -EIO;
+ goto err_out_free;
/* National Datacomm NCP130 based on TMD7160, not PLX9052. */
tmd7160 = (pdev->vendor == 0x15e8) && (pdev->device == 0x0131);
@@ -567,9 +567,6 @@ static int prism2_plx_probe(struct pci_dev *pdev,
return hostap_hw_ready(dev);
fail:
- prism2_free_local_data(dev);
- kfree(hw_priv);
-
if (irq_registered && dev)
free_irq(dev->irq, dev);
@@ -577,6 +574,10 @@ static int prism2_plx_probe(struct pci_dev *pdev,
iounmap(attr_mem);
pci_disable_device(pdev);
+ prism2_free_local_data(dev);
+
+ err_out_free:
+ kfree(hw_priv);
return -ENODEV;
}
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index 6290c9f7e939..72335c8eb97f 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved.
+ Copyright(c) 2003 - 2006 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the terms of version 2 of the GNU General Public License as
@@ -167,12 +167,12 @@ that only one external action is invoked at a time.
#include "ipw2100.h"
-#define IPW2100_VERSION "1.1.3"
+#define IPW2100_VERSION "git-1.2.2"
#define DRV_NAME "ipw2100"
#define DRV_VERSION IPW2100_VERSION
#define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2100 Network Driver"
-#define DRV_COPYRIGHT "Copyright(c) 2003-2005 Intel Corporation"
+#define DRV_COPYRIGHT "Copyright(c) 2003-2006 Intel Corporation"
/* Debugging stuff */
#ifdef CONFIG_IPW2100_DEBUG
@@ -1418,7 +1418,7 @@ static int ipw2100_enable_adapter(struct ipw2100_priv *priv)
if (priv->status & STATUS_ENABLED)
return 0;
- down(&priv->adapter_sem);
+ mutex_lock(&priv->adapter_mutex);
if (rf_kill_active(priv)) {
IPW_DEBUG_HC("Command aborted due to RF kill active.\n");
@@ -1444,7 +1444,7 @@ static int ipw2100_enable_adapter(struct ipw2100_priv *priv)
}
fail_up:
- up(&priv->adapter_sem);
+ mutex_unlock(&priv->adapter_mutex);
return err;
}
@@ -1576,7 +1576,7 @@ static int ipw2100_disable_adapter(struct ipw2100_priv *priv)
cancel_delayed_work(&priv->hang_check);
}
- down(&priv->adapter_sem);
+ mutex_lock(&priv->adapter_mutex);
err = ipw2100_hw_send_command(priv, &cmd);
if (err) {
@@ -1595,7 +1595,7 @@ static int ipw2100_disable_adapter(struct ipw2100_priv *priv)
IPW_DEBUG_INFO("TODO: implement scan state machine\n");
fail_up:
- up(&priv->adapter_sem);
+ mutex_unlock(&priv->adapter_mutex);
return err;
}
@@ -1672,6 +1672,18 @@ static int ipw2100_start_scan(struct ipw2100_priv *priv)
return err;
}
+static const struct ieee80211_geo ipw_geos[] = {
+ { /* Restricted */
+ "---",
+ .bg_channels = 14,
+ .bg = {{2412, 1}, {2417, 2}, {2422, 3},
+ {2427, 4}, {2432, 5}, {2437, 6},
+ {2442, 7}, {2447, 8}, {2452, 9},
+ {2457, 10}, {2462, 11}, {2467, 12},
+ {2472, 13}, {2484, 14}},
+ },
+};
+
static int ipw2100_up(struct ipw2100_priv *priv, int deferred)
{
unsigned long flags;
@@ -1727,6 +1739,13 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred)
goto exit;
}
+ /* Initialize the geo */
+ if (ieee80211_set_geo(priv->ieee, &ipw_geos[0])) {
+ printk(KERN_WARNING DRV_NAME "Could not set geo\n");
+ return 0;
+ }
+ priv->ieee->freq_band = IEEE80211_24GHZ_BAND;
+
lock = LOCK_NONE;
if (ipw2100_set_ordinal(priv, IPW_ORD_PERS_DB_LOCK, &lock, &ord_len)) {
printk(KERN_ERR DRV_NAME
@@ -1869,7 +1888,7 @@ static void ipw2100_reset_adapter(struct ipw2100_priv *priv)
priv->status |= STATUS_RESET_PENDING;
spin_unlock_irqrestore(&priv->low_lock, flags);
- down(&priv->action_sem);
+ mutex_lock(&priv->action_mutex);
/* stop timed checks so that they don't interfere with reset */
priv->stop_hang_check = 1;
cancel_delayed_work(&priv->hang_check);
@@ -1879,7 +1898,7 @@ static void ipw2100_reset_adapter(struct ipw2100_priv *priv)
wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL);
ipw2100_up(priv, 0);
- up(&priv->action_sem);
+ mutex_unlock(&priv->action_mutex);
}
@@ -2371,15 +2390,6 @@ static void isr_rx(struct ipw2100_priv *priv, int i,
IPW_DEBUG_DROP("Dropping packet while interface is not up.\n");
return;
}
-#ifdef CONFIG_IPW2100_MONITOR
- if (unlikely(priv->ieee->iw_mode == IW_MODE_MONITOR &&
- priv->config & CFG_CRC_CHECK &&
- status->flags & IPW_STATUS_FLAG_CRC_ERROR)) {
- IPW_DEBUG_RX("CRC error in packet. Dropping.\n");
- priv->ieee->stats.rx_errors++;
- return;
- }
-#endif
if (unlikely(priv->ieee->iw_mode != IW_MODE_MONITOR &&
!(priv->status & STATUS_ASSOCIATED))) {
@@ -2427,6 +2437,89 @@ static void isr_rx(struct ipw2100_priv *priv, int i,
priv->rx_queue.drv[i].host_addr = packet->dma_addr;
}
+#ifdef CONFIG_IPW2100_MONITOR
+
+static void isr_rx_monitor(struct ipw2100_priv *priv, int i,
+ struct ieee80211_rx_stats *stats)
+{
+ struct ipw2100_status *status = &priv->status_queue.drv[i];
+ struct ipw2100_rx_packet *packet = &priv->rx_buffers[i];
+
+ /* Magic struct that slots into the radiotap header -- no reason
+ * to build this manually element by element, we can write it much
+ * more efficiently than we can parse it. ORDER MATTERS HERE */
+ struct ipw_rt_hdr {
+ struct ieee80211_radiotap_header rt_hdr;
+ s8 rt_dbmsignal; /* signal in dbM, kluged to signed */
+ } *ipw_rt;
+
+ IPW_DEBUG_RX("Handler...\n");
+
+ if (unlikely(status->frame_size > skb_tailroom(packet->skb) -
+ sizeof(struct ipw_rt_hdr))) {
+ IPW_DEBUG_INFO("%s: frame_size (%u) > skb_tailroom (%u)!"
+ " Dropping.\n",
+ priv->net_dev->name,
+ status->frame_size,
+ skb_tailroom(packet->skb));
+ priv->ieee->stats.rx_errors++;
+ return;
+ }
+
+ if (unlikely(!netif_running(priv->net_dev))) {
+ priv->ieee->stats.rx_errors++;
+ priv->wstats.discard.misc++;
+ IPW_DEBUG_DROP("Dropping packet while interface is not up.\n");
+ return;
+ }
+
+ if (unlikely(priv->config & CFG_CRC_CHECK &&
+ status->flags & IPW_STATUS_FLAG_CRC_ERROR)) {
+ IPW_DEBUG_RX("CRC error in packet. Dropping.\n");
+ priv->ieee->stats.rx_errors++;
+ return;
+ }
+
+ pci_unmap_single(priv->pci_dev, packet->dma_addr,
+ sizeof(struct ipw2100_rx), PCI_DMA_FROMDEVICE);
+ memmove(packet->skb->data + sizeof(struct ipw_rt_hdr),
+ packet->skb->data, status->frame_size);
+
+ ipw_rt = (struct ipw_rt_hdr *) packet->skb->data;
+
+ ipw_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
+ ipw_rt->rt_hdr.it_pad = 0; /* always good to zero */
+ ipw_rt->rt_hdr.it_len = sizeof(struct ipw_rt_hdr); /* total hdr+data */
+
+ ipw_rt->rt_hdr.it_present = 1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL;
+
+ ipw_rt->rt_dbmsignal = status->rssi + IPW2100_RSSI_TO_DBM;
+
+ skb_put(packet->skb, status->frame_size + sizeof(struct ipw_rt_hdr));
+
+ if (!ieee80211_rx(priv->ieee, packet->skb, stats)) {
+ priv->ieee->stats.rx_errors++;
+
+ /* ieee80211_rx failed, so it didn't free the SKB */
+ dev_kfree_skb_any(packet->skb);
+ packet->skb = NULL;
+ }
+
+ /* We need to allocate a new SKB and attach it to the RDB. */
+ if (unlikely(ipw2100_alloc_skb(priv, packet))) {
+ IPW_DEBUG_WARNING(
+ "%s: Unable to allocate SKB onto RBD ring - disabling "
+ "adapter.\n", priv->net_dev->name);
+ /* TODO: schedule adapter shutdown */
+ IPW_DEBUG_INFO("TODO: Shutdown adapter...\n");
+ }
+
+ /* Update the RDB entry */
+ priv->rx_queue.drv[i].host_addr = packet->dma_addr;
+}
+
+#endif
+
static int ipw2100_corruption_check(struct ipw2100_priv *priv, int i)
{
struct ipw2100_status *status = &priv->status_queue.drv[i];
@@ -2558,7 +2651,7 @@ static void __ipw2100_rx_process(struct ipw2100_priv *priv)
case P8023_DATA_VAL:
#ifdef CONFIG_IPW2100_MONITOR
if (priv->ieee->iw_mode == IW_MODE_MONITOR) {
- isr_rx(priv, i, &stats);
+ isr_rx_monitor(priv, i, &stats);
break;
}
#endif
@@ -3750,7 +3843,7 @@ static ssize_t store_memory(struct device *d, struct device_attribute *attr,
struct net_device *dev = priv->net_dev;
const char *p = buf;
- (void) dev; /* kill unused-var warning for debug-only code */
+ (void)dev; /* kill unused-var warning for debug-only code */
if (count < 1)
return count;
@@ -3863,7 +3956,7 @@ static int ipw2100_switch_mode(struct ipw2100_priv *priv, u32 mode)
#ifdef CONFIG_IPW2100_MONITOR
case IW_MODE_MONITOR:
priv->last_mode = priv->ieee->iw_mode;
- priv->net_dev->type = ARPHRD_IEEE80211;
+ priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP;
break;
#endif /* CONFIG_IPW2100_MONITOR */
}
@@ -4070,7 +4163,7 @@ static ssize_t store_scan_age(struct device *d, struct device_attribute *attr,
unsigned long val;
char *p = buffer;
- (void) dev; /* kill unused-var warning for debug-only code */
+ (void)dev; /* kill unused-var warning for debug-only code */
IPW_DEBUG_INFO("enter\n");
@@ -4119,7 +4212,7 @@ static int ipw_radio_kill_sw(struct ipw2100_priv *priv, int disable_radio)
IPW_DEBUG_RF_KILL("Manual SW RF Kill set to: RADIO %s\n",
disable_radio ? "OFF" : "ON");
- down(&priv->action_sem);
+ mutex_lock(&priv->action_mutex);
if (disable_radio) {
priv->status |= STATUS_RF_KILL_SW;
@@ -4137,7 +4230,7 @@ static int ipw_radio_kill_sw(struct ipw2100_priv *priv, int disable_radio)
schedule_reset(priv);
}
- up(&priv->action_sem);
+ mutex_unlock(&priv->action_mutex);
return 1;
}
@@ -5107,12 +5200,13 @@ static int ipw2100_set_tx_power(struct ipw2100_priv *priv, u32 tx_power)
.host_command_length = 4
};
int err = 0;
+ u32 tmp = tx_power;
if (tx_power != IPW_TX_POWER_DEFAULT)
- tx_power = (tx_power - IPW_TX_POWER_MIN_DBM) * 16 /
- (IPW_TX_POWER_MAX_DBM - IPW_TX_POWER_MIN_DBM);
+ tmp = (tx_power - IPW_TX_POWER_MIN_DBM) * 16 /
+ (IPW_TX_POWER_MAX_DBM - IPW_TX_POWER_MIN_DBM);
- cmd.host_command_parameters[0] = tx_power;
+ cmd.host_command_parameters[0] = tmp;
if (priv->ieee->iw_mode == IW_MODE_ADHOC)
err = ipw2100_hw_send_command(priv, &cmd);
@@ -5365,9 +5459,12 @@ static int ipw2100_configure_security(struct ipw2100_priv *priv, int batch_mode)
SEC_LEVEL_0, 0, 1);
} else {
auth_mode = IPW_AUTH_OPEN;
- if ((priv->ieee->sec.flags & SEC_AUTH_MODE) &&
- (priv->ieee->sec.auth_mode == WLAN_AUTH_SHARED_KEY))
- auth_mode = IPW_AUTH_SHARED;
+ if (priv->ieee->sec.flags & SEC_AUTH_MODE) {
+ if (priv->ieee->sec.auth_mode == WLAN_AUTH_SHARED_KEY)
+ auth_mode = IPW_AUTH_SHARED;
+ else if (priv->ieee->sec.auth_mode == WLAN_AUTH_LEAP)
+ auth_mode = IPW_AUTH_LEAP_CISCO_ID;
+ }
sec_level = SEC_LEVEL_0;
if (priv->ieee->sec.flags & SEC_LEVEL)
@@ -5437,7 +5534,7 @@ static void shim__set_security(struct net_device *dev,
struct ipw2100_priv *priv = ieee80211_priv(dev);
int i, force_update = 0;
- down(&priv->action_sem);
+ mutex_lock(&priv->action_mutex);
if (!(priv->status & STATUS_INITIALIZED))
goto done;
@@ -5510,7 +5607,7 @@ static void shim__set_security(struct net_device *dev,
if (!(priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)))
ipw2100_configure_security(priv, 0);
done:
- up(&priv->action_sem);
+ mutex_unlock(&priv->action_mutex);
}
static int ipw2100_adapter_setup(struct ipw2100_priv *priv)
@@ -5634,7 +5731,7 @@ static int ipw2100_set_address(struct net_device *dev, void *p)
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
- down(&priv->action_sem);
+ mutex_lock(&priv->action_mutex);
priv->config |= CFG_CUSTOM_MAC;
memcpy(priv->mac_addr, addr->sa_data, ETH_ALEN);
@@ -5644,12 +5741,12 @@ static int ipw2100_set_address(struct net_device *dev, void *p)
goto done;
priv->reset_backoff = 0;
- up(&priv->action_sem);
+ mutex_unlock(&priv->action_mutex);
ipw2100_reset_adapter(priv);
return 0;
done:
- up(&priv->action_sem);
+ mutex_unlock(&priv->action_mutex);
return err;
}
@@ -5760,6 +5857,9 @@ static int ipw2100_wpa_set_auth_algs(struct ipw2100_priv *priv, int value)
} else if (value & IW_AUTH_ALG_OPEN_SYSTEM) {
sec.auth_mode = WLAN_AUTH_OPEN;
ieee->open_wep = 1;
+ } else if (value & IW_AUTH_ALG_LEAP) {
+ sec.auth_mode = WLAN_AUTH_LEAP;
+ ieee->open_wep = 1;
} else
return -EINVAL;
@@ -5771,8 +5871,8 @@ static int ipw2100_wpa_set_auth_algs(struct ipw2100_priv *priv, int value)
return ret;
}
-void ipw2100_wpa_assoc_frame(struct ipw2100_priv *priv,
- char *wpa_ie, int wpa_ie_len)
+static void ipw2100_wpa_assoc_frame(struct ipw2100_priv *priv,
+ char *wpa_ie, int wpa_ie_len)
{
struct ipw2100_wpa_assoc_frame frame;
@@ -5989,8 +6089,8 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev,
strcpy(priv->nick, "ipw2100");
spin_lock_init(&priv->low_lock);
- sema_init(&priv->action_sem, 1);
- sema_init(&priv->adapter_sem, 1);
+ mutex_init(&priv->action_mutex);
+ mutex_init(&priv->adapter_mutex);
init_waitqueue_head(&priv->wait_command_queue);
@@ -6155,7 +6255,7 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
* member to call a function that then just turns and calls ipw2100_up.
* net_dev->init is called after name allocation but before the
* notifier chain is called */
- down(&priv->action_sem);
+ mutex_lock(&priv->action_mutex);
err = register_netdev(dev);
if (err) {
printk(KERN_WARNING DRV_NAME
@@ -6191,12 +6291,12 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
priv->status |= STATUS_INITIALIZED;
- up(&priv->action_sem);
+ mutex_unlock(&priv->action_mutex);
return 0;
fail_unlock:
- up(&priv->action_sem);
+ mutex_unlock(&priv->action_mutex);
fail:
if (dev) {
@@ -6236,7 +6336,7 @@ static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev)
struct net_device *dev;
if (priv) {
- down(&priv->action_sem);
+ mutex_lock(&priv->action_mutex);
priv->status &= ~STATUS_INITIALIZED;
@@ -6251,9 +6351,9 @@ static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev)
/* Take down the hardware */
ipw2100_down(priv);
- /* Release the semaphore so that the network subsystem can
+ /* Release the mutex so that the network subsystem can
* complete any needed calls into the driver... */
- up(&priv->action_sem);
+ mutex_unlock(&priv->action_mutex);
/* Unregister the device first - this results in close()
* being called if the device is open. If we free storage
@@ -6292,7 +6392,7 @@ static int ipw2100_suspend(struct pci_dev *pci_dev, pm_message_t state)
IPW_DEBUG_INFO("%s: Going into suspend...\n", dev->name);
- down(&priv->action_sem);
+ mutex_lock(&priv->action_mutex);
if (priv->status & STATUS_INITIALIZED) {
/* Take down the device; powers it off, etc. */
ipw2100_down(priv);
@@ -6305,7 +6405,7 @@ static int ipw2100_suspend(struct pci_dev *pci_dev, pm_message_t state)
pci_disable_device(pci_dev);
pci_set_power_state(pci_dev, PCI_D3hot);
- up(&priv->action_sem);
+ mutex_unlock(&priv->action_mutex);
return 0;
}
@@ -6319,7 +6419,7 @@ static int ipw2100_resume(struct pci_dev *pci_dev)
if (IPW2100_PM_DISABLED)
return 0;
- down(&priv->action_sem);
+ mutex_lock(&priv->action_mutex);
IPW_DEBUG_INFO("%s: Coming out of suspend...\n", dev->name);
@@ -6345,7 +6445,7 @@ static int ipw2100_resume(struct pci_dev *pci_dev)
if (!(priv->status & STATUS_RF_KILL_SW))
ipw2100_up(priv, 0);
- up(&priv->action_sem);
+ mutex_unlock(&priv->action_mutex);
return 0;
}
@@ -6509,7 +6609,7 @@ static int ipw2100_wx_set_freq(struct net_device *dev,
if (priv->ieee->iw_mode == IW_MODE_INFRA)
return -EOPNOTSUPP;
- down(&priv->action_sem);
+ mutex_lock(&priv->action_mutex);
if (!(priv->status & STATUS_INITIALIZED)) {
err = -EIO;
goto done;
@@ -6540,7 +6640,7 @@ static int ipw2100_wx_set_freq(struct net_device *dev,
}
done:
- up(&priv->action_sem);
+ mutex_unlock(&priv->action_mutex);
return err;
}
@@ -6581,7 +6681,7 @@ static int ipw2100_wx_set_mode(struct net_device *dev,
if (wrqu->mode == priv->ieee->iw_mode)
return 0;
- down(&priv->action_sem);
+ mutex_lock(&priv->action_mutex);
if (!(priv->status & STATUS_INITIALIZED)) {
err = -EIO;
goto done;
@@ -6604,7 +6704,7 @@ static int ipw2100_wx_set_mode(struct net_device *dev,
}
done:
- up(&priv->action_sem);
+ mutex_unlock(&priv->action_mutex);
return err;
}
@@ -6786,7 +6886,7 @@ static int ipw2100_wx_set_wap(struct net_device *dev,
if (wrqu->ap_addr.sa_family != ARPHRD_ETHER)
return -EINVAL;
- down(&priv->action_sem);
+ mutex_lock(&priv->action_mutex);
if (!(priv->status & STATUS_INITIALIZED)) {
err = -EIO;
goto done;
@@ -6815,7 +6915,7 @@ static int ipw2100_wx_set_wap(struct net_device *dev,
wrqu->ap_addr.sa_data[5] & 0xff);
done:
- up(&priv->action_sem);
+ mutex_unlock(&priv->action_mutex);
return err;
}
@@ -6851,7 +6951,7 @@ static int ipw2100_wx_set_essid(struct net_device *dev,
int length = 0;
int err = 0;
- down(&priv->action_sem);
+ mutex_lock(&priv->action_mutex);
if (!(priv->status & STATUS_INITIALIZED)) {
err = -EIO;
goto done;
@@ -6888,7 +6988,7 @@ static int ipw2100_wx_set_essid(struct net_device *dev,
err = ipw2100_set_essid(priv, essid, length, 0);
done:
- up(&priv->action_sem);
+ mutex_unlock(&priv->action_mutex);
return err;
}
@@ -6969,7 +7069,7 @@ static int ipw2100_wx_set_rate(struct net_device *dev,
u32 rate;
int err = 0;
- down(&priv->action_sem);
+ mutex_lock(&priv->action_mutex);
if (!(priv->status & STATUS_INITIALIZED)) {
err = -EIO;
goto done;
@@ -6996,7 +7096,7 @@ static int ipw2100_wx_set_rate(struct net_device *dev,
IPW_DEBUG_WX("SET Rate -> %04X \n", rate);
done:
- up(&priv->action_sem);
+ mutex_unlock(&priv->action_mutex);
return err;
}
@@ -7016,7 +7116,7 @@ static int ipw2100_wx_get_rate(struct net_device *dev,
return 0;
}
- down(&priv->action_sem);
+ mutex_lock(&priv->action_mutex);
if (!(priv->status & STATUS_INITIALIZED)) {
err = -EIO;
goto done;
@@ -7048,7 +7148,7 @@ static int ipw2100_wx_get_rate(struct net_device *dev,
IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value);
done:
- up(&priv->action_sem);
+ mutex_unlock(&priv->action_mutex);
return err;
}
@@ -7063,7 +7163,7 @@ static int ipw2100_wx_set_rts(struct net_device *dev,
if (wrqu->rts.fixed == 0)
return -EINVAL;
- down(&priv->action_sem);
+ mutex_lock(&priv->action_mutex);
if (!(priv->status & STATUS_INITIALIZED)) {
err = -EIO;
goto done;
@@ -7083,7 +7183,7 @@ static int ipw2100_wx_set_rts(struct net_device *dev,
IPW_DEBUG_WX("SET RTS Threshold -> 0x%08X \n", value);
done:
- up(&priv->action_sem);
+ mutex_unlock(&priv->action_mutex);
return err;
}
@@ -7134,7 +7234,7 @@ static int ipw2100_wx_set_txpow(struct net_device *dev,
value = wrqu->txpower.value;
}
- down(&priv->action_sem);
+ mutex_lock(&priv->action_mutex);
if (!(priv->status & STATUS_INITIALIZED)) {
err = -EIO;
goto done;
@@ -7145,7 +7245,7 @@ static int ipw2100_wx_set_txpow(struct net_device *dev,
IPW_DEBUG_WX("SET TX Power -> %d \n", value);
done:
- up(&priv->action_sem);
+ mutex_unlock(&priv->action_mutex);
return err;
}
@@ -7237,7 +7337,7 @@ static int ipw2100_wx_set_retry(struct net_device *dev,
if (!(wrqu->retry.flags & IW_RETRY_LIMIT))
return 0;
- down(&priv->action_sem);
+ mutex_lock(&priv->action_mutex);
if (!(priv->status & STATUS_INITIALIZED)) {
err = -EIO;
goto done;
@@ -7264,7 +7364,7 @@ static int ipw2100_wx_set_retry(struct net_device *dev,
IPW_DEBUG_WX("SET Both Retry Limits -> %d \n", wrqu->retry.value);
done:
- up(&priv->action_sem);
+ mutex_unlock(&priv->action_mutex);
return err;
}
@@ -7307,7 +7407,7 @@ static int ipw2100_wx_set_scan(struct net_device *dev,
struct ipw2100_priv *priv = ieee80211_priv(dev);
int err = 0;
- down(&priv->action_sem);
+ mutex_lock(&priv->action_mutex);
if (!(priv->status & STATUS_INITIALIZED)) {
err = -EIO;
goto done;
@@ -7322,7 +7422,7 @@ static int ipw2100_wx_set_scan(struct net_device *dev,
}
done:
- up(&priv->action_sem);
+ mutex_unlock(&priv->action_mutex);
return err;
}
@@ -7372,7 +7472,7 @@ static int ipw2100_wx_set_power(struct net_device *dev,
struct ipw2100_priv *priv = ieee80211_priv(dev);
int err = 0;
- down(&priv->action_sem);
+ mutex_lock(&priv->action_mutex);
if (!(priv->status & STATUS_INITIALIZED)) {
err = -EIO;
goto done;
@@ -7405,7 +7505,7 @@ static int ipw2100_wx_set_power(struct net_device *dev,
IPW_DEBUG_WX("SET Power Management Mode -> 0x%02X\n", priv->power_mode);
done:
- up(&priv->action_sem);
+ mutex_unlock(&priv->action_mutex);
return err;
}
@@ -7709,7 +7809,7 @@ static int ipw2100_wx_set_promisc(struct net_device *dev,
int enable = (parms[0] > 0);
int err = 0;
- down(&priv->action_sem);
+ mutex_lock(&priv->action_mutex);
if (!(priv->status & STATUS_INITIALIZED)) {
err = -EIO;
goto done;
@@ -7727,7 +7827,7 @@ static int ipw2100_wx_set_promisc(struct net_device *dev,
err = ipw2100_switch_mode(priv, priv->last_mode);
}
done:
- up(&priv->action_sem);
+ mutex_unlock(&priv->action_mutex);
return err;
}
@@ -7750,7 +7850,7 @@ static int ipw2100_wx_set_powermode(struct net_device *dev,
struct ipw2100_priv *priv = ieee80211_priv(dev);
int err = 0, mode = *(int *)extra;
- down(&priv->action_sem);
+ mutex_lock(&priv->action_mutex);
if (!(priv->status & STATUS_INITIALIZED)) {
err = -EIO;
goto done;
@@ -7762,7 +7862,7 @@ static int ipw2100_wx_set_powermode(struct net_device *dev,
if (priv->power_mode != mode)
err = ipw2100_set_power_mode(priv, mode);
done:
- up(&priv->action_sem);
+ mutex_unlock(&priv->action_mutex);
return err;
}
@@ -7814,7 +7914,7 @@ static int ipw2100_wx_set_preamble(struct net_device *dev,
struct ipw2100_priv *priv = ieee80211_priv(dev);
int err, mode = *(int *)extra;
- down(&priv->action_sem);
+ mutex_lock(&priv->action_mutex);
if (!(priv->status & STATUS_INITIALIZED)) {
err = -EIO;
goto done;
@@ -7832,7 +7932,7 @@ static int ipw2100_wx_set_preamble(struct net_device *dev,
err = ipw2100_system_config(priv, 0);
done:
- up(&priv->action_sem);
+ mutex_unlock(&priv->action_mutex);
return err;
}
@@ -7862,7 +7962,7 @@ static int ipw2100_wx_set_crc_check(struct net_device *dev,
struct ipw2100_priv *priv = ieee80211_priv(dev);
int err, mode = *(int *)extra;
- down(&priv->action_sem);
+ mutex_lock(&priv->action_mutex);
if (!(priv->status & STATUS_INITIALIZED)) {
err = -EIO;
goto done;
@@ -7879,7 +7979,7 @@ static int ipw2100_wx_set_crc_check(struct net_device *dev,
err = 0;
done:
- up(&priv->action_sem);
+ mutex_unlock(&priv->action_mutex);
return err;
}
@@ -8184,11 +8284,11 @@ static void ipw2100_wx_event_work(struct ipw2100_priv *priv)
if (priv->status & STATUS_STOPPING)
return;
- down(&priv->action_sem);
+ mutex_lock(&priv->action_mutex);
IPW_DEBUG_WX("enter\n");
- up(&priv->action_sem);
+ mutex_unlock(&priv->action_mutex);
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
@@ -8211,7 +8311,7 @@ static void ipw2100_wx_event_work(struct ipw2100_priv *priv)
if (!(priv->status & STATUS_ASSOCIATED)) {
IPW_DEBUG_WX("Configuring ESSID\n");
- down(&priv->action_sem);
+ mutex_lock(&priv->action_mutex);
/* This is a disassociation event, so kick the firmware to
* look for another AP */
if (priv->config & CFG_STATIC_ESSID)
@@ -8219,7 +8319,7 @@ static void ipw2100_wx_event_work(struct ipw2100_priv *priv)
0);
else
ipw2100_set_essid(priv, NULL, 0, 0);
- up(&priv->action_sem);
+ mutex_unlock(&priv->action_mutex);
}
wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL);
diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2100.h
index f6c51441fa87..55b7227198df 100644
--- a/drivers/net/wireless/ipw2100.h
+++ b/drivers/net/wireless/ipw2100.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved.
+ Copyright(c) 2003 - 2006 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the terms of version 2 of the GNU General Public License as
@@ -41,7 +41,12 @@
#include <net/ieee80211.h>
+#ifdef CONFIG_IPW2100_MONITOR
+#include <net/ieee80211_radiotap.h>
+#endif
+
#include <linux/workqueue.h>
+#include <linux/mutex.h>
struct ipw2100_priv;
struct ipw2100_tx_packet;
@@ -392,8 +397,10 @@ struct ipw2100_notification {
#define IPW_WEP104_CIPHER (1<<5)
#define IPW_CKIP_CIPHER (1<<6)
-#define IPW_AUTH_OPEN 0
-#define IPW_AUTH_SHARED 1
+#define IPW_AUTH_OPEN 0
+#define IPW_AUTH_SHARED 1
+#define IPW_AUTH_LEAP 2
+#define IPW_AUTH_LEAP_CISCO_ID 0x80
struct statistic {
int value;
@@ -588,8 +595,8 @@ struct ipw2100_priv {
int inta_other;
spinlock_t low_lock;
- struct semaphore action_sem;
- struct semaphore adapter_sem;
+ struct mutex action_mutex;
+ struct mutex adapter_mutex;
wait_queue_head_t wait_command_queue;
};
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index 287676ad80df..9dce522526c5 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved.
+ Copyright(c) 2003 - 2006 Intel Corporation. All rights reserved.
802.11 status code portion of this file from ethereal-0.10.6:
Copyright 2000, Axis Communications AB
@@ -33,9 +33,9 @@
#include "ipw2200.h"
#include <linux/version.h>
-#define IPW2200_VERSION "git-1.0.8"
+#define IPW2200_VERSION "git-1.1.1"
#define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver"
-#define DRV_COPYRIGHT "Copyright(c) 2003-2005 Intel Corporation"
+#define DRV_COPYRIGHT "Copyright(c) 2003-2006 Intel Corporation"
#define DRV_VERSION IPW2200_VERSION
#define ETH_P_80211_STATS (ETH_P_80211_RAW + 1)
@@ -55,7 +55,9 @@ static int associate = 1;
static int auto_create = 1;
static int led = 0;
static int disable = 0;
-static int hwcrypto = 1;
+static int bt_coexist = 0;
+static int hwcrypto = 0;
+static int roaming = 1;
static const char ipw_modes[] = {
'a', 'b', 'g', '?'
};
@@ -151,12 +153,6 @@ static int init_supported_rates(struct ipw_priv *priv,
static void ipw_set_hwcrypto_keys(struct ipw_priv *);
static void ipw_send_wep_keys(struct ipw_priv *, int);
-static int ipw_is_valid_channel(struct ieee80211_device *, u8);
-static int ipw_channel_to_index(struct ieee80211_device *, u8);
-static u8 ipw_freq_to_channel(struct ieee80211_device *, u32);
-static int ipw_set_geo(struct ieee80211_device *, const struct ieee80211_geo *);
-static const struct ieee80211_geo *ipw_get_geo(struct ieee80211_device *);
-
static int snprint_line(char *buf, size_t count,
const u8 * data, u32 len, u32 ofs)
{
@@ -227,12 +223,15 @@ static int snprintk_buf(u8 * output, size_t size, const u8 * data, size_t len)
return total;
}
+/* alias for 32-bit indirect read (for SRAM/reg above 4K), with debug wrapper */
static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg);
#define ipw_read_reg32(a, b) _ipw_read_reg32(a, b)
+/* alias for 8-bit indirect read (for SRAM/reg above 4K), with debug wrapper */
static u8 _ipw_read_reg8(struct ipw_priv *ipw, u32 reg);
#define ipw_read_reg8(a, b) _ipw_read_reg8(a, b)
+/* 8-bit indirect write (for SRAM/reg above 4K), with debug wrapper */
static void _ipw_write_reg8(struct ipw_priv *priv, u32 reg, u8 value);
static inline void ipw_write_reg8(struct ipw_priv *a, u32 b, u8 c)
{
@@ -241,6 +240,7 @@ static inline void ipw_write_reg8(struct ipw_priv *a, u32 b, u8 c)
_ipw_write_reg8(a, b, c);
}
+/* 16-bit indirect write (for SRAM/reg above 4K), with debug wrapper */
static void _ipw_write_reg16(struct ipw_priv *priv, u32 reg, u16 value);
static inline void ipw_write_reg16(struct ipw_priv *a, u32 b, u16 c)
{
@@ -249,6 +249,7 @@ static inline void ipw_write_reg16(struct ipw_priv *a, u32 b, u16 c)
_ipw_write_reg16(a, b, c);
}
+/* 32-bit indirect write (for SRAM/reg above 4K), with debug wrapper */
static void _ipw_write_reg32(struct ipw_priv *priv, u32 reg, u32 value);
static inline void ipw_write_reg32(struct ipw_priv *a, u32 b, u32 c)
{
@@ -257,48 +258,70 @@ static inline void ipw_write_reg32(struct ipw_priv *a, u32 b, u32 c)
_ipw_write_reg32(a, b, c);
}
+/* 8-bit direct write (low 4K) */
#define _ipw_write8(ipw, ofs, val) writeb((val), (ipw)->hw_base + (ofs))
+
+/* 8-bit direct write (for low 4K of SRAM/regs), with debug wrapper */
#define ipw_write8(ipw, ofs, val) \
IPW_DEBUG_IO("%s %d: write_direct8(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \
_ipw_write8(ipw, ofs, val)
+/* 16-bit direct write (low 4K) */
#define _ipw_write16(ipw, ofs, val) writew((val), (ipw)->hw_base + (ofs))
+
+/* 16-bit direct write (for low 4K of SRAM/regs), with debug wrapper */
#define ipw_write16(ipw, ofs, val) \
IPW_DEBUG_IO("%s %d: write_direct16(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \
_ipw_write16(ipw, ofs, val)
+/* 32-bit direct write (low 4K) */
#define _ipw_write32(ipw, ofs, val) writel((val), (ipw)->hw_base + (ofs))
+
+/* 32-bit direct write (for low 4K of SRAM/regs), with debug wrapper */
#define ipw_write32(ipw, ofs, val) \
IPW_DEBUG_IO("%s %d: write_direct32(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \
_ipw_write32(ipw, ofs, val)
+/* 8-bit direct read (low 4K) */
#define _ipw_read8(ipw, ofs) readb((ipw)->hw_base + (ofs))
+
+/* 8-bit direct read (low 4K), with debug wrapper */
static inline u8 __ipw_read8(char *f, u32 l, struct ipw_priv *ipw, u32 ofs)
{
IPW_DEBUG_IO("%s %d: read_direct8(0x%08X)\n", f, l, (u32) (ofs));
return _ipw_read8(ipw, ofs);
}
+/* alias to 8-bit direct read (low 4K of SRAM/regs), with debug wrapper */
#define ipw_read8(ipw, ofs) __ipw_read8(__FILE__, __LINE__, ipw, ofs)
+/* 16-bit direct read (low 4K) */
#define _ipw_read16(ipw, ofs) readw((ipw)->hw_base + (ofs))
+
+/* 16-bit direct read (low 4K), with debug wrapper */
static inline u16 __ipw_read16(char *f, u32 l, struct ipw_priv *ipw, u32 ofs)
{
IPW_DEBUG_IO("%s %d: read_direct16(0x%08X)\n", f, l, (u32) (ofs));
return _ipw_read16(ipw, ofs);
}
+/* alias to 16-bit direct read (low 4K of SRAM/regs), with debug wrapper */
#define ipw_read16(ipw, ofs) __ipw_read16(__FILE__, __LINE__, ipw, ofs)
+/* 32-bit direct read (low 4K) */
#define _ipw_read32(ipw, ofs) readl((ipw)->hw_base + (ofs))
+
+/* 32-bit direct read (low 4K), with debug wrapper */
static inline u32 __ipw_read32(char *f, u32 l, struct ipw_priv *ipw, u32 ofs)
{
IPW_DEBUG_IO("%s %d: read_direct32(0x%08X)\n", f, l, (u32) (ofs));
return _ipw_read32(ipw, ofs);
}
+/* alias to 32-bit direct read (low 4K of SRAM/regs), with debug wrapper */
#define ipw_read32(ipw, ofs) __ipw_read32(__FILE__, __LINE__, ipw, ofs)
+/* multi-byte read (above 4K), with debug wrapper */
static void _ipw_read_indirect(struct ipw_priv *, u32, u8 *, int);
static inline void __ipw_read_indirect(const char *f, int l,
struct ipw_priv *a, u32 b, u8 * c, int d)
@@ -308,15 +331,17 @@ static inline void __ipw_read_indirect(const char *f, int l,
_ipw_read_indirect(a, b, c, d);
}
+/* alias to multi-byte read (SRAM/regs above 4K), with debug wrapper */
#define ipw_read_indirect(a, b, c, d) __ipw_read_indirect(__FILE__, __LINE__, a, b, c, d)
+/* alias to multi-byte read (SRAM/regs above 4K), with debug wrapper */
static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * data,
int num);
#define ipw_write_indirect(a, b, c, d) \
IPW_DEBUG_IO("%s %d: write_indirect(0x%08X) %d bytes\n", __FILE__, __LINE__, (u32)(b), d); \
_ipw_write_indirect(a, b, c, d)
-/* indirect write s */
+/* 32-bit indirect write (above 4K) */
static void _ipw_write_reg32(struct ipw_priv *priv, u32 reg, u32 value)
{
IPW_DEBUG_IO(" %p : reg = 0x%8X : value = 0x%8X\n", priv, reg, value);
@@ -324,22 +349,29 @@ static void _ipw_write_reg32(struct ipw_priv *priv, u32 reg, u32 value)
_ipw_write32(priv, IPW_INDIRECT_DATA, value);
}
+/* 8-bit indirect write (above 4K) */
static void _ipw_write_reg8(struct ipw_priv *priv, u32 reg, u8 value)
{
+ u32 aligned_addr = reg & IPW_INDIRECT_ADDR_MASK; /* dword align */
+ u32 dif_len = reg - aligned_addr;
+
IPW_DEBUG_IO(" reg = 0x%8X : value = 0x%8X\n", reg, value);
- _ipw_write32(priv, IPW_INDIRECT_ADDR, reg & IPW_INDIRECT_ADDR_MASK);
- _ipw_write8(priv, IPW_INDIRECT_DATA, value);
+ _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr);
+ _ipw_write8(priv, IPW_INDIRECT_DATA + dif_len, value);
}
+/* 16-bit indirect write (above 4K) */
static void _ipw_write_reg16(struct ipw_priv *priv, u32 reg, u16 value)
{
+ u32 aligned_addr = reg & IPW_INDIRECT_ADDR_MASK; /* dword align */
+ u32 dif_len = (reg - aligned_addr) & (~0x1ul);
+
IPW_DEBUG_IO(" reg = 0x%8X : value = 0x%8X\n", reg, value);
- _ipw_write32(priv, IPW_INDIRECT_ADDR, reg & IPW_INDIRECT_ADDR_MASK);
- _ipw_write16(priv, IPW_INDIRECT_DATA, value);
+ _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr);
+ _ipw_write16(priv, IPW_INDIRECT_DATA + dif_len, value);
}
-/* indirect read s */
-
+/* 8-bit indirect read (above 4K) */
static u8 _ipw_read_reg8(struct ipw_priv *priv, u32 reg)
{
u32 word;
@@ -349,6 +381,7 @@ static u8 _ipw_read_reg8(struct ipw_priv *priv, u32 reg)
return (word >> ((reg & 0x3) * 8)) & 0xff;
}
+/* 32-bit indirect read (above 4K) */
static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg)
{
u32 value;
@@ -361,11 +394,12 @@ static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg)
return value;
}
-/* iterative/auto-increment 32 bit reads and writes */
+/* General purpose, no alignment requirement, iterative (multi-byte) read, */
+/* for area above 1st 4K of SRAM/reg space */
static void _ipw_read_indirect(struct ipw_priv *priv, u32 addr, u8 * buf,
int num)
{
- u32 aligned_addr = addr & IPW_INDIRECT_ADDR_MASK;
+ u32 aligned_addr = addr & IPW_INDIRECT_ADDR_MASK; /* dword align */
u32 dif_len = addr - aligned_addr;
u32 i;
@@ -375,7 +409,7 @@ static void _ipw_read_indirect(struct ipw_priv *priv, u32 addr, u8 * buf,
return;
}
- /* Read the first nibble byte by byte */
+ /* Read the first dword (or portion) byte by byte */
if (unlikely(dif_len)) {
_ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr);
/* Start reading at aligned_addr + dif_len */
@@ -384,11 +418,12 @@ static void _ipw_read_indirect(struct ipw_priv *priv, u32 addr, u8 * buf,
aligned_addr += 4;
}
+ /* Read all of the middle dwords as dwords, with auto-increment */
_ipw_write32(priv, IPW_AUTOINC_ADDR, aligned_addr);
for (; num >= 4; buf += 4, aligned_addr += 4, num -= 4)
*(u32 *) buf = _ipw_read32(priv, IPW_AUTOINC_DATA);
- /* Copy the last nibble */
+ /* Read the last dword (or portion) byte by byte */
if (unlikely(num)) {
_ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr);
for (i = 0; num > 0; i++, num--)
@@ -396,10 +431,12 @@ static void _ipw_read_indirect(struct ipw_priv *priv, u32 addr, u8 * buf,
}
}
+/* General purpose, no alignment requirement, iterative (multi-byte) write, */
+/* for area above 1st 4K of SRAM/reg space */
static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * buf,
int num)
{
- u32 aligned_addr = addr & IPW_INDIRECT_ADDR_MASK;
+ u32 aligned_addr = addr & IPW_INDIRECT_ADDR_MASK; /* dword align */
u32 dif_len = addr - aligned_addr;
u32 i;
@@ -409,20 +446,21 @@ static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * buf,
return;
}
- /* Write the first nibble byte by byte */
+ /* Write the first dword (or portion) byte by byte */
if (unlikely(dif_len)) {
_ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr);
- /* Start reading at aligned_addr + dif_len */
+ /* Start writing at aligned_addr + dif_len */
for (i = dif_len; ((i < 4) && (num > 0)); i++, num--, buf++)
_ipw_write8(priv, IPW_INDIRECT_DATA + i, *buf);
aligned_addr += 4;
}
+ /* Write all of the middle dwords as dwords, with auto-increment */
_ipw_write32(priv, IPW_AUTOINC_ADDR, aligned_addr);
for (; num >= 4; buf += 4, aligned_addr += 4, num -= 4)
_ipw_write32(priv, IPW_AUTOINC_DATA, *(u32 *) buf);
- /* Copy the last nibble */
+ /* Write the last dword (or portion) byte by byte */
if (unlikely(num)) {
_ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr);
for (i = 0; num > 0; i++, num--, buf++)
@@ -430,17 +468,21 @@ static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * buf,
}
}
+/* General purpose, no alignment requirement, iterative (multi-byte) write, */
+/* for 1st 4K of SRAM/regs space */
static void ipw_write_direct(struct ipw_priv *priv, u32 addr, void *buf,
int num)
{
memcpy_toio((priv->hw_base + addr), buf, num);
}
+/* Set bit(s) in low 4K of SRAM/regs */
static inline void ipw_set_bit(struct ipw_priv *priv, u32 reg, u32 mask)
{
ipw_write32(priv, reg, ipw_read32(priv, reg) | mask);
}
+/* Clear bit(s) in low 4K of SRAM/regs */
static inline void ipw_clear_bit(struct ipw_priv *priv, u32 reg, u32 mask)
{
ipw_write32(priv, reg, ipw_read32(priv, reg) & ~mask);
@@ -701,7 +743,7 @@ static void ipw_init_ordinals(struct ipw_priv *priv)
}
-u32 ipw_register_toggle(u32 reg)
+static u32 ipw_register_toggle(u32 reg)
{
reg &= ~IPW_START_STANDBY;
if (reg & IPW_GATE_ODMA)
@@ -722,11 +764,11 @@ u32 ipw_register_toggle(u32 reg)
* - On radio OFF, turn off any LEDs started during radio on
*
*/
-#define LD_TIME_LINK_ON 300
-#define LD_TIME_LINK_OFF 2700
-#define LD_TIME_ACT_ON 250
+#define LD_TIME_LINK_ON msecs_to_jiffies(300)
+#define LD_TIME_LINK_OFF msecs_to_jiffies(2700)
+#define LD_TIME_ACT_ON msecs_to_jiffies(250)
-void ipw_led_link_on(struct ipw_priv *priv)
+static void ipw_led_link_on(struct ipw_priv *priv)
{
unsigned long flags;
u32 led;
@@ -764,12 +806,12 @@ void ipw_led_link_on(struct ipw_priv *priv)
static void ipw_bg_led_link_on(void *data)
{
struct ipw_priv *priv = data;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
ipw_led_link_on(data);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
}
-void ipw_led_link_off(struct ipw_priv *priv)
+static void ipw_led_link_off(struct ipw_priv *priv)
{
unsigned long flags;
u32 led;
@@ -808,9 +850,9 @@ void ipw_led_link_off(struct ipw_priv *priv)
static void ipw_bg_led_link_off(void *data)
{
struct ipw_priv *priv = data;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
ipw_led_link_off(data);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
}
static void __ipw_led_activity_on(struct ipw_priv *priv)
@@ -847,6 +889,7 @@ static void __ipw_led_activity_on(struct ipw_priv *priv)
}
}
+#if 0
void ipw_led_activity_on(struct ipw_priv *priv)
{
unsigned long flags;
@@ -854,8 +897,9 @@ void ipw_led_activity_on(struct ipw_priv *priv)
__ipw_led_activity_on(priv);
spin_unlock_irqrestore(&priv->lock, flags);
}
+#endif /* 0 */
-void ipw_led_activity_off(struct ipw_priv *priv)
+static void ipw_led_activity_off(struct ipw_priv *priv)
{
unsigned long flags;
u32 led;
@@ -885,12 +929,12 @@ void ipw_led_activity_off(struct ipw_priv *priv)
static void ipw_bg_led_activity_off(void *data)
{
struct ipw_priv *priv = data;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
ipw_led_activity_off(data);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
}
-void ipw_led_band_on(struct ipw_priv *priv)
+static void ipw_led_band_on(struct ipw_priv *priv)
{
unsigned long flags;
u32 led;
@@ -925,7 +969,7 @@ void ipw_led_band_on(struct ipw_priv *priv)
spin_unlock_irqrestore(&priv->lock, flags);
}
-void ipw_led_band_off(struct ipw_priv *priv)
+static void ipw_led_band_off(struct ipw_priv *priv)
{
unsigned long flags;
u32 led;
@@ -948,24 +992,24 @@ void ipw_led_band_off(struct ipw_priv *priv)
spin_unlock_irqrestore(&priv->lock, flags);
}
-void ipw_led_radio_on(struct ipw_priv *priv)
+static void ipw_led_radio_on(struct ipw_priv *priv)
{
ipw_led_link_on(priv);
}
-void ipw_led_radio_off(struct ipw_priv *priv)
+static void ipw_led_radio_off(struct ipw_priv *priv)
{
ipw_led_activity_off(priv);
ipw_led_link_off(priv);
}
-void ipw_led_link_up(struct ipw_priv *priv)
+static void ipw_led_link_up(struct ipw_priv *priv)
{
/* Set the Link Led on for all nic types */
ipw_led_link_on(priv);
}
-void ipw_led_link_down(struct ipw_priv *priv)
+static void ipw_led_link_down(struct ipw_priv *priv)
{
ipw_led_activity_off(priv);
ipw_led_link_off(priv);
@@ -974,7 +1018,7 @@ void ipw_led_link_down(struct ipw_priv *priv)
ipw_led_radio_off(priv);
}
-void ipw_led_init(struct ipw_priv *priv)
+static void ipw_led_init(struct ipw_priv *priv)
{
priv->nic_type = priv->eeprom[EEPROM_NIC_TYPE];
@@ -1025,7 +1069,7 @@ void ipw_led_init(struct ipw_priv *priv)
}
}
-void ipw_led_shutdown(struct ipw_priv *priv)
+static void ipw_led_shutdown(struct ipw_priv *priv)
{
ipw_led_activity_off(priv);
ipw_led_link_off(priv);
@@ -1074,6 +1118,7 @@ static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO,
static inline u32 ipw_get_event_log_len(struct ipw_priv *priv)
{
+ /* length = 1st dword in log */
return ipw_read_reg32(priv, ipw_read32(priv, IPW_EVENT_LOG));
}
@@ -1603,7 +1648,7 @@ static ssize_t store_speed_scan(struct device *d, struct device_attribute *attr,
break;
}
- if (ipw_is_valid_channel(priv->ieee, channel))
+ if (ieee80211_is_valid_channel(priv->ieee, channel))
priv->speed_scan[pos++] = channel;
else
IPW_WARNING("Skipping invalid channel request: %d\n",
@@ -1751,9 +1796,9 @@ static void ipw_irq_tasklet(struct ipw_priv *priv)
}
if (inta & IPW_INTA_BIT_FATAL_ERROR) {
- IPW_ERROR("Firmware error detected. Restarting.\n");
+ IPW_WARNING("Firmware error detected. Restarting.\n");
if (priv->error) {
- IPW_ERROR("Sysfs 'error' log already exists.\n");
+ IPW_DEBUG_FW("Sysfs 'error' log already exists.\n");
#ifdef CONFIG_IPW2200_DEBUG
if (ipw_debug_level & IPW_DL_FW_ERRORS) {
struct ipw_fw_error *error =
@@ -1766,10 +1811,10 @@ static void ipw_irq_tasklet(struct ipw_priv *priv)
} else {
priv->error = ipw_alloc_error_log(priv);
if (priv->error)
- IPW_ERROR("Sysfs 'error' log captured.\n");
+ IPW_DEBUG_FW("Sysfs 'error' log captured.\n");
else
- IPW_ERROR("Error allocating sysfs 'error' "
- "log.\n");
+ IPW_DEBUG_FW("Error allocating sysfs 'error' "
+ "log.\n");
#ifdef CONFIG_IPW2200_DEBUG
if (ipw_debug_level & IPW_DL_FW_ERRORS)
ipw_dump_error_log(priv, priv->error);
@@ -1870,7 +1915,8 @@ static char *get_cmd_string(u8 cmd)
}
#define HOST_COMPLETE_TIMEOUT HZ
-static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd)
+
+static int __ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd)
{
int rc = 0;
unsigned long flags;
@@ -1897,9 +1943,15 @@ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd)
IPW_DEBUG_HC("%s command (#%d) %d bytes: 0x%08X\n",
get_cmd_string(cmd->cmd), cmd->cmd, cmd->len,
priv->status);
- printk_buf(IPW_DL_HOST_COMMAND, (u8 *) cmd->param, cmd->len);
- rc = ipw_queue_tx_hcmd(priv, cmd->cmd, &cmd->param, cmd->len, 0);
+#ifndef DEBUG_CMD_WEP_KEY
+ if (cmd->cmd == IPW_CMD_WEP_KEY)
+ IPW_DEBUG_HC("WEP_KEY command masked out for secure.\n");
+ else
+#endif
+ printk_buf(IPW_DL_HOST_COMMAND, (u8 *) cmd->param, cmd->len);
+
+ rc = ipw_queue_tx_hcmd(priv, cmd->cmd, cmd->param, cmd->len, 0);
if (rc) {
priv->status &= ~STATUS_HCMD_ACTIVE;
IPW_ERROR("Failed to send %s: Reason %d\n",
@@ -1942,61 +1994,62 @@ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd)
return rc;
}
-static int ipw_send_host_complete(struct ipw_priv *priv)
+static int ipw_send_cmd_simple(struct ipw_priv *priv, u8 command)
+{
+ struct host_cmd cmd = {
+ .cmd = command,
+ };
+
+ return __ipw_send_cmd(priv, &cmd);
+}
+
+static int ipw_send_cmd_pdu(struct ipw_priv *priv, u8 command, u8 len,
+ void *data)
{
struct host_cmd cmd = {
- .cmd = IPW_CMD_HOST_COMPLETE,
- .len = 0
+ .cmd = command,
+ .len = len,
+ .param = data,
};
+ return __ipw_send_cmd(priv, &cmd);
+}
+
+static int ipw_send_host_complete(struct ipw_priv *priv)
+{
if (!priv) {
IPW_ERROR("Invalid args\n");
return -1;
}
- return ipw_send_cmd(priv, &cmd);
+ return ipw_send_cmd_simple(priv, IPW_CMD_HOST_COMPLETE);
}
static int ipw_send_system_config(struct ipw_priv *priv,
struct ipw_sys_config *config)
{
- struct host_cmd cmd = {
- .cmd = IPW_CMD_SYSTEM_CONFIG,
- .len = sizeof(*config)
- };
-
if (!priv || !config) {
IPW_ERROR("Invalid args\n");
return -1;
}
- memcpy(cmd.param, config, sizeof(*config));
- return ipw_send_cmd(priv, &cmd);
+ return ipw_send_cmd_pdu(priv, IPW_CMD_SYSTEM_CONFIG, sizeof(*config),
+ config);
}
static int ipw_send_ssid(struct ipw_priv *priv, u8 * ssid, int len)
{
- struct host_cmd cmd = {
- .cmd = IPW_CMD_SSID,
- .len = min(len, IW_ESSID_MAX_SIZE)
- };
-
if (!priv || !ssid) {
IPW_ERROR("Invalid args\n");
return -1;
}
- memcpy(cmd.param, ssid, cmd.len);
- return ipw_send_cmd(priv, &cmd);
+ return ipw_send_cmd_pdu(priv, IPW_CMD_SSID, min(len, IW_ESSID_MAX_SIZE),
+ ssid);
}
static int ipw_send_adapter_address(struct ipw_priv *priv, u8 * mac)
{
- struct host_cmd cmd = {
- .cmd = IPW_CMD_ADAPTER_ADDRESS,
- .len = ETH_ALEN
- };
-
if (!priv || !mac) {
IPW_ERROR("Invalid args\n");
return -1;
@@ -2005,8 +2058,7 @@ static int ipw_send_adapter_address(struct ipw_priv *priv, u8 * mac)
IPW_DEBUG_INFO("%s: Setting MAC to " MAC_FMT "\n",
priv->net_dev->name, MAC_ARG(mac));
- memcpy(cmd.param, mac, ETH_ALEN);
- return ipw_send_cmd(priv, &cmd);
+ return ipw_send_cmd_pdu(priv, IPW_CMD_ADAPTER_ADDRESS, ETH_ALEN, mac);
}
/*
@@ -2036,9 +2088,9 @@ static void ipw_adapter_restart(void *adapter)
static void ipw_bg_adapter_restart(void *data)
{
struct ipw_priv *priv = data;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
ipw_adapter_restart(data);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
}
#define IPW_SCAN_CHECK_WATCHDOG (5 * HZ)
@@ -2048,8 +2100,8 @@ static void ipw_scan_check(void *data)
struct ipw_priv *priv = data;
if (priv->status & (STATUS_SCANNING | STATUS_SCAN_ABORTING)) {
IPW_DEBUG_SCAN("Scan completion watchdog resetting "
- "adapter (%dms).\n",
- IPW_SCAN_CHECK_WATCHDOG / 100);
+ "adapter after (%dms).\n",
+ jiffies_to_msecs(IPW_SCAN_CHECK_WATCHDOG));
queue_work(priv->workqueue, &priv->adapter_restart);
}
}
@@ -2057,59 +2109,48 @@ static void ipw_scan_check(void *data)
static void ipw_bg_scan_check(void *data)
{
struct ipw_priv *priv = data;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
ipw_scan_check(data);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
}
static int ipw_send_scan_request_ext(struct ipw_priv *priv,
struct ipw_scan_request_ext *request)
{
- struct host_cmd cmd = {
- .cmd = IPW_CMD_SCAN_REQUEST_EXT,
- .len = sizeof(*request)
- };
-
- memcpy(cmd.param, request, sizeof(*request));
- return ipw_send_cmd(priv, &cmd);
+ return ipw_send_cmd_pdu(priv, IPW_CMD_SCAN_REQUEST_EXT,
+ sizeof(*request), request);
}
static int ipw_send_scan_abort(struct ipw_priv *priv)
{
- struct host_cmd cmd = {
- .cmd = IPW_CMD_SCAN_ABORT,
- .len = 0
- };
-
if (!priv) {
IPW_ERROR("Invalid args\n");
return -1;
}
- return ipw_send_cmd(priv, &cmd);
+ return ipw_send_cmd_simple(priv, IPW_CMD_SCAN_ABORT);
}
static int ipw_set_sensitivity(struct ipw_priv *priv, u16 sens)
{
- struct host_cmd cmd = {
- .cmd = IPW_CMD_SENSITIVITY_CALIB,
- .len = sizeof(struct ipw_sensitivity_calib)
+ struct ipw_sensitivity_calib calib = {
+ .beacon_rssi_raw = sens,
};
- struct ipw_sensitivity_calib *calib = (struct ipw_sensitivity_calib *)
- &cmd.param;
- calib->beacon_rssi_raw = sens;
- return ipw_send_cmd(priv, &cmd);
+
+ return ipw_send_cmd_pdu(priv, IPW_CMD_SENSITIVITY_CALIB, sizeof(calib),
+ &calib);
}
static int ipw_send_associate(struct ipw_priv *priv,
struct ipw_associate *associate)
{
- struct host_cmd cmd = {
- .cmd = IPW_CMD_ASSOCIATE,
- .len = sizeof(*associate)
- };
-
struct ipw_associate tmp_associate;
+
+ if (!priv || !associate) {
+ IPW_ERROR("Invalid args\n");
+ return -1;
+ }
+
memcpy(&tmp_associate, associate, sizeof(*associate));
tmp_associate.policy_support =
cpu_to_le16(tmp_associate.policy_support);
@@ -2122,85 +2163,60 @@ static int ipw_send_associate(struct ipw_priv *priv,
cpu_to_le16(tmp_associate.beacon_interval);
tmp_associate.atim_window = cpu_to_le16(tmp_associate.atim_window);
- if (!priv || !associate) {
- IPW_ERROR("Invalid args\n");
- return -1;
- }
-
- memcpy(cmd.param, &tmp_associate, sizeof(*associate));
- return ipw_send_cmd(priv, &cmd);
+ return ipw_send_cmd_pdu(priv, IPW_CMD_ASSOCIATE, sizeof(tmp_associate),
+ &tmp_associate);
}
static int ipw_send_supported_rates(struct ipw_priv *priv,
struct ipw_supported_rates *rates)
{
- struct host_cmd cmd = {
- .cmd = IPW_CMD_SUPPORTED_RATES,
- .len = sizeof(*rates)
- };
-
if (!priv || !rates) {
IPW_ERROR("Invalid args\n");
return -1;
}
- memcpy(cmd.param, rates, sizeof(*rates));
- return ipw_send_cmd(priv, &cmd);
+ return ipw_send_cmd_pdu(priv, IPW_CMD_SUPPORTED_RATES, sizeof(*rates),
+ rates);
}
static int ipw_set_random_seed(struct ipw_priv *priv)
{
- struct host_cmd cmd = {
- .cmd = IPW_CMD_SEED_NUMBER,
- .len = sizeof(u32)
- };
+ u32 val;
if (!priv) {
IPW_ERROR("Invalid args\n");
return -1;
}
- get_random_bytes(&cmd.param, sizeof(u32));
+ get_random_bytes(&val, sizeof(val));
- return ipw_send_cmd(priv, &cmd);
+ return ipw_send_cmd_pdu(priv, IPW_CMD_SEED_NUMBER, sizeof(val), &val);
}
static int ipw_send_card_disable(struct ipw_priv *priv, u32 phy_off)
{
- struct host_cmd cmd = {
- .cmd = IPW_CMD_CARD_DISABLE,
- .len = sizeof(u32)
- };
-
if (!priv) {
IPW_ERROR("Invalid args\n");
return -1;
}
- *((u32 *) & cmd.param) = phy_off;
-
- return ipw_send_cmd(priv, &cmd);
+ return ipw_send_cmd_pdu(priv, IPW_CMD_CARD_DISABLE, sizeof(phy_off),
+ &phy_off);
}
static int ipw_send_tx_power(struct ipw_priv *priv, struct ipw_tx_power *power)
{
- struct host_cmd cmd = {
- .cmd = IPW_CMD_TX_POWER,
- .len = sizeof(*power)
- };
-
if (!priv || !power) {
IPW_ERROR("Invalid args\n");
return -1;
}
- memcpy(cmd.param, power, sizeof(*power));
- return ipw_send_cmd(priv, &cmd);
+ return ipw_send_cmd_pdu(priv, IPW_CMD_TX_POWER, sizeof(*power), power);
}
static int ipw_set_tx_power(struct ipw_priv *priv)
{
- const struct ieee80211_geo *geo = ipw_get_geo(priv->ieee);
+ const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee);
struct ipw_tx_power tx_power;
s8 max_power;
int i;
@@ -2247,18 +2263,14 @@ static int ipw_send_rts_threshold(struct ipw_priv *priv, u16 rts)
struct ipw_rts_threshold rts_threshold = {
.rts_threshold = rts,
};
- struct host_cmd cmd = {
- .cmd = IPW_CMD_RTS_THRESHOLD,
- .len = sizeof(rts_threshold)
- };
if (!priv) {
IPW_ERROR("Invalid args\n");
return -1;
}
- memcpy(cmd.param, &rts_threshold, sizeof(rts_threshold));
- return ipw_send_cmd(priv, &cmd);
+ return ipw_send_cmd_pdu(priv, IPW_CMD_RTS_THRESHOLD,
+ sizeof(rts_threshold), &rts_threshold);
}
static int ipw_send_frag_threshold(struct ipw_priv *priv, u16 frag)
@@ -2266,27 +2278,19 @@ static int ipw_send_frag_threshold(struct ipw_priv *priv, u16 frag)
struct ipw_frag_threshold frag_threshold = {
.frag_threshold = frag,
};
- struct host_cmd cmd = {
- .cmd = IPW_CMD_FRAG_THRESHOLD,
- .len = sizeof(frag_threshold)
- };
if (!priv) {
IPW_ERROR("Invalid args\n");
return -1;
}
- memcpy(cmd.param, &frag_threshold, sizeof(frag_threshold));
- return ipw_send_cmd(priv, &cmd);
+ return ipw_send_cmd_pdu(priv, IPW_CMD_FRAG_THRESHOLD,
+ sizeof(frag_threshold), &frag_threshold);
}
static int ipw_send_power_mode(struct ipw_priv *priv, u32 mode)
{
- struct host_cmd cmd = {
- .cmd = IPW_CMD_POWER_MODE,
- .len = sizeof(u32)
- };
- u32 *param = (u32 *) (&cmd.param);
+ u32 param;
if (!priv) {
IPW_ERROR("Invalid args\n");
@@ -2297,17 +2301,18 @@ static int ipw_send_power_mode(struct ipw_priv *priv, u32 mode)
* level */
switch (mode) {
case IPW_POWER_BATTERY:
- *param = IPW_POWER_INDEX_3;
+ param = IPW_POWER_INDEX_3;
break;
case IPW_POWER_AC:
- *param = IPW_POWER_MODE_CAM;
+ param = IPW_POWER_MODE_CAM;
break;
default:
- *param = mode;
+ param = mode;
break;
}
- return ipw_send_cmd(priv, &cmd);
+ return ipw_send_cmd_pdu(priv, IPW_CMD_POWER_MODE, sizeof(param),
+ &param);
}
static int ipw_send_retry_limit(struct ipw_priv *priv, u8 slimit, u8 llimit)
@@ -2316,18 +2321,14 @@ static int ipw_send_retry_limit(struct ipw_priv *priv, u8 slimit, u8 llimit)
.short_retry_limit = slimit,
.long_retry_limit = llimit
};
- struct host_cmd cmd = {
- .cmd = IPW_CMD_RETRY_LIMIT,
- .len = sizeof(retry_limit)
- };
if (!priv) {
IPW_ERROR("Invalid args\n");
return -1;
}
- memcpy(cmd.param, &retry_limit, sizeof(retry_limit));
- return ipw_send_cmd(priv, &cmd);
+ return ipw_send_cmd_pdu(priv, IPW_CMD_RETRY_LIMIT, sizeof(retry_limit),
+ &retry_limit);
}
/*
@@ -2454,7 +2455,7 @@ static void ipw_eeprom_init_sram(struct ipw_priv *priv)
/*
If the data looks correct, then copy it to our private
copy. Otherwise let the firmware know to perform the operation
- on it's own
+ on its own.
*/
if (priv->eeprom[EEPROM_VERSION] != 0) {
IPW_DEBUG_INFO("Writing EEPROM data into SRAM\n");
@@ -2707,22 +2708,25 @@ static int ipw_fw_dma_add_buffer(struct ipw_priv *priv,
static int ipw_fw_dma_wait(struct ipw_priv *priv)
{
- u32 current_index = 0;
+ u32 current_index = 0, previous_index;
u32 watchdog = 0;
IPW_DEBUG_FW(">> : \n");
current_index = ipw_fw_dma_command_block_index(priv);
- IPW_DEBUG_FW_INFO("sram_desc.last_cb_index:0x%8X\n",
+ IPW_DEBUG_FW_INFO("sram_desc.last_cb_index:0x%08X\n",
(int)priv->sram_desc.last_cb_index);
while (current_index < priv->sram_desc.last_cb_index) {
udelay(50);
+ previous_index = current_index;
current_index = ipw_fw_dma_command_block_index(priv);
- watchdog++;
-
- if (watchdog > 400) {
+ if (previous_index < current_index) {
+ watchdog = 0;
+ continue;
+ }
+ if (++watchdog > 400) {
IPW_DEBUG_FW_INFO("Timeout\n");
ipw_fw_dma_dump_command_block(priv);
ipw_fw_dma_abort(priv);
@@ -2772,6 +2776,7 @@ static inline int ipw_alive(struct ipw_priv *priv)
return ipw_read32(priv, 0x90) == 0xd55555d5;
}
+/* timeout in msec, attempted in 10-msec quanta */
static int ipw_poll_bit(struct ipw_priv *priv, u32 addr, u32 mask,
int timeout)
{
@@ -2800,10 +2805,11 @@ static int ipw_stop_master(struct ipw_priv *priv)
/* stop master. typical delay - 0 */
ipw_set_bit(priv, IPW_RESET_REG, IPW_RESET_REG_STOP_MASTER);
+ /* timeout is in msec, polled in 10-msec quanta */
rc = ipw_poll_bit(priv, IPW_RESET_REG,
IPW_RESET_REG_MASTER_DISABLED, 100);
if (rc < 0) {
- IPW_ERROR("stop master failed in 10ms\n");
+ IPW_ERROR("wait for stop master failed after 100ms\n");
return -1;
}
@@ -2823,33 +2829,11 @@ static void ipw_arc_release(struct ipw_priv *priv)
mdelay(5);
}
-struct fw_header {
- u32 version;
- u32 mode;
-};
-
struct fw_chunk {
u32 address;
u32 length;
};
-#define IPW_FW_MAJOR_VERSION 2
-#define IPW_FW_MINOR_VERSION 4
-
-#define IPW_FW_MINOR(x) ((x & 0xff) >> 8)
-#define IPW_FW_MAJOR(x) (x & 0xff)
-
-#define IPW_FW_VERSION ((IPW_FW_MINOR_VERSION << 8) | IPW_FW_MAJOR_VERSION)
-
-#define IPW_FW_PREFIX "ipw-" __stringify(IPW_FW_MAJOR_VERSION) \
-"." __stringify(IPW_FW_MINOR_VERSION) "-"
-
-#if IPW_FW_MAJOR_VERSION >= 2 && IPW_FW_MINOR_VERSION > 0
-#define IPW_FW_NAME(x) IPW_FW_PREFIX "" x ".fw"
-#else
-#define IPW_FW_NAME(x) "ipw2200_" x ".fw"
-#endif
-
static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len)
{
int rc = 0, i, addr;
@@ -2890,8 +2874,8 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len)
mdelay(1);
/* enable ucode store */
- ipw_write_reg8(priv, DINO_CONTROL_REG, 0x0);
- ipw_write_reg8(priv, DINO_CONTROL_REG, DINO_ENABLE_CS);
+ ipw_write_reg8(priv, IPW_BASEBAND_CONTROL_STATUS, 0x0);
+ ipw_write_reg8(priv, IPW_BASEBAND_CONTROL_STATUS, DINO_ENABLE_CS);
mdelay(1);
/* write ucode */
@@ -3036,7 +3020,7 @@ static int ipw_stop_nic(struct ipw_priv *priv)
rc = ipw_poll_bit(priv, IPW_RESET_REG,
IPW_RESET_REG_MASTER_DISABLED, 500);
if (rc < 0) {
- IPW_ERROR("wait for reg master disabled failed\n");
+ IPW_ERROR("wait for reg master disabled failed after 500ms\n");
return rc;
}
@@ -3118,33 +3102,47 @@ static int ipw_reset_nic(struct ipw_priv *priv)
return rc;
}
+
+struct ipw_fw {
+ u32 ver;
+ u32 boot_size;
+ u32 ucode_size;
+ u32 fw_size;
+ u8 data[0];
+};
+
static int ipw_get_fw(struct ipw_priv *priv,
- const struct firmware **fw, const char *name)
+ const struct firmware **raw, const char *name)
{
- struct fw_header *header;
+ struct ipw_fw *fw;
int rc;
/* ask firmware_class module to get the boot firmware off disk */
- rc = request_firmware(fw, name, &priv->pci_dev->dev);
+ rc = request_firmware(raw, name, &priv->pci_dev->dev);
if (rc < 0) {
- IPW_ERROR("%s load failed: Reason %d\n", name, rc);
+ IPW_ERROR("%s request_firmware failed: Reason %d\n", name, rc);
return rc;
}
- header = (struct fw_header *)(*fw)->data;
- if (IPW_FW_MAJOR(le32_to_cpu(header->version)) != IPW_FW_MAJOR_VERSION) {
- IPW_ERROR("'%s' firmware version not compatible (%d != %d)\n",
- name,
- IPW_FW_MAJOR(le32_to_cpu(header->version)),
- IPW_FW_MAJOR_VERSION);
+ if ((*raw)->size < sizeof(*fw)) {
+ IPW_ERROR("%s is too small (%zd)\n", name, (*raw)->size);
+ return -EINVAL;
+ }
+
+ fw = (void *)(*raw)->data;
+
+ if ((*raw)->size < sizeof(*fw) +
+ fw->boot_size + fw->ucode_size + fw->fw_size) {
+ IPW_ERROR("%s is too small or corrupt (%zd)\n",
+ name, (*raw)->size);
return -EINVAL;
}
- IPW_DEBUG_INFO("Loading firmware '%s' file v%d.%d (%zd bytes)\n",
+ IPW_DEBUG_INFO("Read firmware '%s' image v%d.%d (%zd bytes)\n",
name,
- IPW_FW_MAJOR(le32_to_cpu(header->version)),
- IPW_FW_MINOR(le32_to_cpu(header->version)),
- (*fw)->size - sizeof(struct fw_header));
+ le32_to_cpu(fw->ver) >> 16,
+ le32_to_cpu(fw->ver) & 0xff,
+ (*raw)->size - sizeof(*fw));
return 0;
}
@@ -3184,17 +3182,13 @@ static void ipw_rx_queue_reset(struct ipw_priv *priv,
#ifdef CONFIG_PM
static int fw_loaded = 0;
-static const struct firmware *bootfw = NULL;
-static const struct firmware *firmware = NULL;
-static const struct firmware *ucode = NULL;
+static const struct firmware *raw = NULL;
static void free_firmware(void)
{
if (fw_loaded) {
- release_firmware(bootfw);
- release_firmware(ucode);
- release_firmware(firmware);
- bootfw = ucode = firmware = NULL;
+ release_firmware(raw);
+ raw = NULL;
fw_loaded = 0;
}
}
@@ -3205,60 +3199,50 @@ static void free_firmware(void)
static int ipw_load(struct ipw_priv *priv)
{
#ifndef CONFIG_PM
- const struct firmware *bootfw = NULL;
- const struct firmware *firmware = NULL;
- const struct firmware *ucode = NULL;
+ const struct firmware *raw = NULL;
#endif
+ struct ipw_fw *fw;
+ u8 *boot_img, *ucode_img, *fw_img;
+ u8 *name = NULL;
int rc = 0, retries = 3;
-#ifdef CONFIG_PM
- if (!fw_loaded) {
-#endif
- rc = ipw_get_fw(priv, &bootfw, IPW_FW_NAME("boot"));
- if (rc)
- goto error;
-
- switch (priv->ieee->iw_mode) {
- case IW_MODE_ADHOC:
- rc = ipw_get_fw(priv, &ucode,
- IPW_FW_NAME("ibss_ucode"));
- if (rc)
- goto error;
-
- rc = ipw_get_fw(priv, &firmware, IPW_FW_NAME("ibss"));
- break;
-
+ switch (priv->ieee->iw_mode) {
+ case IW_MODE_ADHOC:
+ name = "ipw2200-ibss.fw";
+ break;
#ifdef CONFIG_IPW2200_MONITOR
- case IW_MODE_MONITOR:
- rc = ipw_get_fw(priv, &ucode,
- IPW_FW_NAME("sniffer_ucode"));
- if (rc)
- goto error;
-
- rc = ipw_get_fw(priv, &firmware,
- IPW_FW_NAME("sniffer"));
- break;
+ case IW_MODE_MONITOR:
+ name = "ipw2200-sniffer.fw";
+ break;
#endif
- case IW_MODE_INFRA:
- rc = ipw_get_fw(priv, &ucode, IPW_FW_NAME("bss_ucode"));
- if (rc)
- goto error;
-
- rc = ipw_get_fw(priv, &firmware, IPW_FW_NAME("bss"));
- break;
+ case IW_MODE_INFRA:
+ name = "ipw2200-bss.fw";
+ break;
+ }
- default:
- rc = -EINVAL;
- }
+ if (!name) {
+ rc = -EINVAL;
+ goto error;
+ }
- if (rc)
+#ifdef CONFIG_PM
+ if (!fw_loaded) {
+#endif
+ rc = ipw_get_fw(priv, &raw, name);
+ if (rc < 0)
goto error;
-
#ifdef CONFIG_PM
- fw_loaded = 1;
}
#endif
+ fw = (void *)raw->data;
+ boot_img = &fw->data[0];
+ ucode_img = &fw->data[fw->boot_size];
+ fw_img = &fw->data[fw->boot_size + fw->ucode_size];
+
+ if (rc < 0)
+ goto error;
+
if (!priv->rxq)
priv->rxq = ipw_rx_queue_alloc(priv);
else
@@ -3279,7 +3263,7 @@ static int ipw_load(struct ipw_priv *priv)
ipw_stop_nic(priv);
rc = ipw_reset_nic(priv);
- if (rc) {
+ if (rc < 0) {
IPW_ERROR("Unable to reset NIC\n");
goto error;
}
@@ -3288,8 +3272,7 @@ static int ipw_load(struct ipw_priv *priv)
IPW_NIC_SRAM_UPPER_BOUND - IPW_NIC_SRAM_LOWER_BOUND);
/* DMA the initial boot firmware into the device */
- rc = ipw_load_firmware(priv, bootfw->data + sizeof(struct fw_header),
- bootfw->size - sizeof(struct fw_header));
+ rc = ipw_load_firmware(priv, boot_img, fw->boot_size);
if (rc < 0) {
IPW_ERROR("Unable to load boot firmware: %d\n", rc);
goto error;
@@ -3298,7 +3281,7 @@ static int ipw_load(struct ipw_priv *priv)
/* kick start the device */
ipw_start_nic(priv);
- /* wait for the device to finish it's initial startup sequence */
+ /* wait for the device to finish its initial startup sequence */
rc = ipw_poll_bit(priv, IPW_INTA_RW,
IPW_INTA_BIT_FW_INITIALIZATION_DONE, 500);
if (rc < 0) {
@@ -3311,8 +3294,7 @@ static int ipw_load(struct ipw_priv *priv)
ipw_write32(priv, IPW_INTA_RW, IPW_INTA_BIT_FW_INITIALIZATION_DONE);
/* DMA the ucode into the device */
- rc = ipw_load_ucode(priv, ucode->data + sizeof(struct fw_header),
- ucode->size - sizeof(struct fw_header));
+ rc = ipw_load_ucode(priv, ucode_img, fw->ucode_size);
if (rc < 0) {
IPW_ERROR("Unable to load ucode: %d\n", rc);
goto error;
@@ -3322,18 +3304,19 @@ static int ipw_load(struct ipw_priv *priv)
ipw_stop_nic(priv);
/* DMA bss firmware into the device */
- rc = ipw_load_firmware(priv, firmware->data +
- sizeof(struct fw_header),
- firmware->size - sizeof(struct fw_header));
+ rc = ipw_load_firmware(priv, fw_img, fw->fw_size);
if (rc < 0) {
IPW_ERROR("Unable to load firmware: %d\n", rc);
goto error;
}
+#ifdef CONFIG_PM
+ fw_loaded = 1;
+#endif
ipw_write32(priv, IPW_EEPROM_LOAD_DISABLE, 0);
rc = ipw_queue_reset(priv);
- if (rc) {
+ if (rc < 0) {
IPW_ERROR("Unable to initialize queues\n");
goto error;
}
@@ -3362,7 +3345,7 @@ static int ipw_load(struct ipw_priv *priv)
rc = ipw_poll_bit(priv, IPW_INTA_RW,
IPW_INTA_BIT_FW_INITIALIZATION_DONE, 500);
if (rc < 0) {
- IPW_ERROR("device failed to start after 500ms\n");
+ IPW_ERROR("device failed to start within 500ms\n");
goto error;
}
IPW_DEBUG_INFO("device response after %dms\n", rc);
@@ -3386,9 +3369,7 @@ static int ipw_load(struct ipw_priv *priv)
ipw_write32(priv, IPW_INTA_RW, IPW_INTA_MASK_ALL);
#ifndef CONFIG_PM
- release_firmware(bootfw);
- release_firmware(ucode);
- release_firmware(firmware);
+ release_firmware(raw);
#endif
return 0;
@@ -3398,15 +3379,11 @@ static int ipw_load(struct ipw_priv *priv)
priv->rxq = NULL;
}
ipw_tx_queue_free(priv);
- if (bootfw)
- release_firmware(bootfw);
- if (ucode)
- release_firmware(ucode);
- if (firmware)
- release_firmware(firmware);
+ if (raw)
+ release_firmware(raw);
#ifdef CONFIG_PM
fw_loaded = 0;
- bootfw = ucode = firmware = NULL;
+ raw = NULL;
#endif
return rc;
@@ -3715,9 +3692,9 @@ static int ipw_disassociate(void *data)
static void ipw_bg_disassociate(void *data)
{
struct ipw_priv *priv = data;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
ipw_disassociate(data);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
}
static void ipw_system_config(void *data)
@@ -4077,9 +4054,9 @@ static void ipw_gather_stats(struct ipw_priv *priv)
static void ipw_bg_gather_stats(void *data)
{
struct ipw_priv *priv = data;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
ipw_gather_stats(data);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
}
/* Missed beacon behavior:
@@ -4121,8 +4098,9 @@ static void ipw_handle_missed_beacon(struct ipw_priv *priv,
return;
}
- if (missed_count > priv->roaming_threshold &&
- missed_count <= priv->disassociate_threshold) {
+ if (roaming &&
+ (missed_count > priv->roaming_threshold &&
+ missed_count <= priv->disassociate_threshold)) {
/* If we are not already roaming, set the ROAM
* bit in the status and kick off a scan.
* This can happen several times before we reach
@@ -4150,7 +4128,6 @@ static void ipw_handle_missed_beacon(struct ipw_priv *priv,
}
IPW_DEBUG_NOTIF("Missed beacon: %d\n", missed_count);
-
}
/**
@@ -4527,10 +4504,9 @@ static void ipw_rx_notification(struct ipw_priv *priv,
if (notif->size == sizeof(*x)) {
IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE,
- "link deterioration: '%s' " MAC_FMT
- " \n", escape_essid(priv->essid,
- priv->essid_len),
- MAC_ARG(priv->bssid));
+ "link deterioration: type %d, cnt %d\n",
+ x->silence_notification_type,
+ x->silence_count);
memcpy(&priv->last_link_deterioration, x,
sizeof(*x));
} else {
@@ -4911,13 +4887,13 @@ static void ipw_rx_queue_replenish(void *data)
static void ipw_bg_rx_queue_replenish(void *data)
{
struct ipw_priv *priv = data;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
ipw_rx_queue_replenish(data);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
}
/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
- * If an SKB has been detached, the POOL needs to have it's SKB set to NULL
+ * If an SKB has been detached, the POOL needs to have its SKB set to NULL
* This free routine walks the list of POOL entries and if SKB is set to
* non NULL it is unmapped and freed
*/
@@ -5257,10 +5233,11 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
if (priv->ieee->scan_age != 0 &&
time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) {
IPW_DEBUG_MERGE("Network '%s (" MAC_FMT ")' excluded "
- "because of age: %lums.\n",
+ "because of age: %ums.\n",
escape_essid(network->ssid, network->ssid_len),
MAC_ARG(network->bssid),
- 1000 * (jiffies - network->last_scanned) / HZ);
+ jiffies_to_msecs(jiffies -
+ network->last_scanned));
return 0;
}
@@ -5369,7 +5346,7 @@ static void ipw_merge_adhoc_network(void *data)
return;
}
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
if ((priv->ieee->iw_mode == IW_MODE_ADHOC)) {
IPW_DEBUG_MERGE("remove network %s\n",
escape_essid(priv->essid,
@@ -5379,7 +5356,7 @@ static void ipw_merge_adhoc_network(void *data)
ipw_disassociate(priv);
priv->assoc_network = match.network;
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return;
}
}
@@ -5467,11 +5444,12 @@ static int ipw_best_network(struct ipw_priv *priv,
if (network->last_associate &&
time_after(network->last_associate + (HZ * 3UL), jiffies)) {
IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
- "because of storming (%lus since last "
+ "because of storming (%ums since last "
"assoc attempt).\n",
escape_essid(network->ssid, network->ssid_len),
MAC_ARG(network->bssid),
- (jiffies - network->last_associate) / HZ);
+ jiffies_to_msecs(jiffies -
+ network->last_associate));
return 0;
}
@@ -5479,10 +5457,11 @@ static int ipw_best_network(struct ipw_priv *priv,
if (priv->ieee->scan_age != 0 &&
time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) {
IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
- "because of age: %lums.\n",
+ "because of age: %ums.\n",
escape_essid(network->ssid, network->ssid_len),
MAC_ARG(network->bssid),
- 1000 * (jiffies - network->last_scanned) / HZ);
+ jiffies_to_msecs(jiffies -
+ network->last_scanned));
return 0;
}
@@ -5510,15 +5489,6 @@ static int ipw_best_network(struct ipw_priv *priv,
return 0;
}
- if (!priv->ieee->wpa_enabled && (network->wpa_ie_len > 0 ||
- network->rsn_ie_len > 0)) {
- IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
- "because of WPA capability mismatch.\n",
- escape_essid(network->ssid, network->ssid_len),
- MAC_ARG(network->bssid));
- return 0;
- }
-
if ((priv->config & CFG_STATIC_BSSID) &&
memcmp(network->bssid, priv->bssid, ETH_ALEN)) {
IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
@@ -5539,7 +5509,7 @@ static int ipw_best_network(struct ipw_priv *priv,
}
/* Filter out invalid channel in current GEO */
- if (!ipw_is_valid_channel(priv->ieee, network->channel)) {
+ if (!ieee80211_is_valid_channel(priv->ieee, network->channel)) {
IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
"because of invalid channel in current GEO\n",
escape_essid(network->ssid, network->ssid_len),
@@ -5584,7 +5554,7 @@ static int ipw_best_network(struct ipw_priv *priv,
static void ipw_adhoc_create(struct ipw_priv *priv,
struct ieee80211_network *network)
{
- const struct ieee80211_geo *geo = ipw_get_geo(priv->ieee);
+ const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee);
int i;
/*
@@ -5599,10 +5569,10 @@ static void ipw_adhoc_create(struct ipw_priv *priv,
* FW fatal error.
*
*/
- switch (ipw_is_valid_channel(priv->ieee, priv->channel)) {
+ switch (ieee80211_is_valid_channel(priv->ieee, priv->channel)) {
case IEEE80211_52GHZ_BAND:
network->mode = IEEE_A;
- i = ipw_channel_to_index(priv->ieee, priv->channel);
+ i = ieee80211_channel_to_index(priv->ieee, priv->channel);
if (i == -1)
BUG();
if (geo->a[i].flags & IEEE80211_CH_PASSIVE_ONLY) {
@@ -5616,7 +5586,7 @@ static void ipw_adhoc_create(struct ipw_priv *priv,
network->mode = IEEE_G;
else
network->mode = IEEE_B;
- i = ipw_channel_to_index(priv->ieee, priv->channel);
+ i = ieee80211_channel_to_index(priv->ieee, priv->channel);
if (i == -1)
BUG();
if (geo->bg[i].flags & IEEE80211_CH_PASSIVE_ONLY) {
@@ -5671,54 +5641,44 @@ static void ipw_adhoc_create(struct ipw_priv *priv,
static void ipw_send_tgi_tx_key(struct ipw_priv *priv, int type, int index)
{
- struct ipw_tgi_tx_key *key;
- struct host_cmd cmd = {
- .cmd = IPW_CMD_TGI_TX_KEY,
- .len = sizeof(*key)
- };
+ struct ipw_tgi_tx_key key;
if (!(priv->ieee->sec.flags & (1 << index)))
return;
- key = (struct ipw_tgi_tx_key *)&cmd.param;
- key->key_id = index;
- memcpy(key->key, priv->ieee->sec.keys[index], SCM_TEMPORAL_KEY_LENGTH);
- key->security_type = type;
- key->station_index = 0; /* always 0 for BSS */
- key->flags = 0;
+ key.key_id = index;
+ memcpy(key.key, priv->ieee->sec.keys[index], SCM_TEMPORAL_KEY_LENGTH);
+ key.security_type = type;
+ key.station_index = 0; /* always 0 for BSS */
+ key.flags = 0;
/* 0 for new key; previous value of counter (after fatal error) */
- key->tx_counter[0] = 0;
- key->tx_counter[1] = 0;
+ key.tx_counter[0] = 0;
+ key.tx_counter[1] = 0;
- ipw_send_cmd(priv, &cmd);
+ ipw_send_cmd_pdu(priv, IPW_CMD_TGI_TX_KEY, sizeof(key), &key);
}
static void ipw_send_wep_keys(struct ipw_priv *priv, int type)
{
- struct ipw_wep_key *key;
+ struct ipw_wep_key key;
int i;
- struct host_cmd cmd = {
- .cmd = IPW_CMD_WEP_KEY,
- .len = sizeof(*key)
- };
- key = (struct ipw_wep_key *)&cmd.param;
- key->cmd_id = DINO_CMD_WEP_KEY;
- key->seq_num = 0;
+ key.cmd_id = DINO_CMD_WEP_KEY;
+ key.seq_num = 0;
/* Note: AES keys cannot be set for multiple times.
* Only set it at the first time. */
for (i = 0; i < 4; i++) {
- key->key_index = i | type;
+ key.key_index = i | type;
if (!(priv->ieee->sec.flags & (1 << i))) {
- key->key_size = 0;
+ key.key_size = 0;
continue;
}
- key->key_size = priv->ieee->sec.key_sizes[i];
- memcpy(key->key, priv->ieee->sec.keys[i], key->key_size);
+ key.key_size = priv->ieee->sec.key_sizes[i];
+ memcpy(key.key, priv->ieee->sec.keys[i], key.key_size);
- ipw_send_cmd(priv, &cmd);
+ ipw_send_cmd_pdu(priv, IPW_CMD_WEP_KEY, sizeof(key), &key);
}
}
@@ -5822,9 +5782,9 @@ static void ipw_adhoc_check(void *data)
static void ipw_bg_adhoc_check(void *data)
{
struct ipw_priv *priv = data;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
ipw_adhoc_check(data);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
}
#ifdef CONFIG_IPW2200_DEBUG
@@ -5950,7 +5910,7 @@ static void ipw_add_scan_channels(struct ipw_priv *priv,
const struct ieee80211_geo *geo;
int i;
- geo = ipw_get_geo(priv->ieee);
+ geo = ieee80211_get_geo(priv->ieee);
if (priv->ieee->freq_band & IEEE80211_52GHZ_BAND) {
int start = channel_index;
@@ -6010,7 +5970,7 @@ static void ipw_add_scan_channels(struct ipw_priv *priv,
channel_index++;
scan->channels_list[channel_index] = channel;
index =
- ipw_channel_to_index(priv->ieee, channel);
+ ieee80211_channel_to_index(priv->ieee, channel);
ipw_set_scan_type(scan, channel_index,
geo->bg[index].
flags &
@@ -6051,7 +6011,7 @@ static int ipw_request_scan(struct ipw_priv *priv)
(priv->status & STATUS_EXIT_PENDING))
return 0;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
if (priv->status & STATUS_SCANNING) {
IPW_DEBUG_HC("Concurrent scan requested. Ignoring.\n");
@@ -6092,7 +6052,7 @@ static int ipw_request_scan(struct ipw_priv *priv)
u8 channel;
u8 band = 0;
- switch (ipw_is_valid_channel(priv->ieee, priv->channel)) {
+ switch (ieee80211_is_valid_channel(priv->ieee, priv->channel)) {
case IEEE80211_52GHZ_BAND:
band = (u8) (IPW_A_MODE << 6) | 1;
channel = priv->channel;
@@ -6159,16 +6119,16 @@ static int ipw_request_scan(struct ipw_priv *priv)
queue_delayed_work(priv->workqueue, &priv->scan_check,
IPW_SCAN_CHECK_WATCHDOG);
done:
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return err;
}
static void ipw_bg_abort_scan(void *data)
{
struct ipw_priv *priv = data;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
ipw_abort_scan(data);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
}
static int ipw_wpa_enable(struct ipw_priv *priv, int value)
@@ -6193,6 +6153,9 @@ static int ipw_wpa_set_auth_algs(struct ipw_priv *priv, int value)
} else if (value & IW_AUTH_ALG_OPEN_SYSTEM) {
sec.auth_mode = WLAN_AUTH_OPEN;
ieee->open_wep = 1;
+ } else if (value & IW_AUTH_ALG_LEAP) {
+ sec.auth_mode = WLAN_AUTH_LEAP;
+ ieee->open_wep = 1;
} else
return -EINVAL;
@@ -6204,7 +6167,8 @@ static int ipw_wpa_set_auth_algs(struct ipw_priv *priv, int value)
return ret;
}
-void ipw_wpa_assoc_frame(struct ipw_priv *priv, char *wpa_ie, int wpa_ie_len)
+static void ipw_wpa_assoc_frame(struct ipw_priv *priv, char *wpa_ie,
+ int wpa_ie_len)
{
/* make sure WPA is enabled */
ipw_wpa_enable(priv, 1);
@@ -6215,15 +6179,10 @@ void ipw_wpa_assoc_frame(struct ipw_priv *priv, char *wpa_ie, int wpa_ie_len)
static int ipw_set_rsn_capa(struct ipw_priv *priv,
char *capabilities, int length)
{
- struct host_cmd cmd = {
- .cmd = IPW_CMD_RSN_CAPABILITIES,
- .len = length,
- };
-
IPW_DEBUG_HC("HOST_CMD_RSN_CAPABILITIES\n");
- memcpy(cmd.param, capabilities, length);
- return ipw_send_cmd(priv, &cmd);
+ return ipw_send_cmd_pdu(priv, IPW_CMD_RSN_CAPABILITIES, length,
+ capabilities);
}
/*
@@ -6244,7 +6203,7 @@ static int ipw_wx_set_genie(struct net_device *dev,
(wrqu->data.length && extra == NULL))
return -EINVAL;
- //down(&priv->sem);
+ //mutex_lock(&priv->mutex);
//if (!ieee->wpa_enabled) {
// err = -EOPNOTSUPP;
@@ -6270,7 +6229,7 @@ static int ipw_wx_set_genie(struct net_device *dev,
ipw_wpa_assoc_frame(priv, ieee->wpa_ie, ieee->wpa_ie_len);
out:
- //up(&priv->sem);
+ //mutex_unlock(&priv->mutex);
return err;
}
@@ -6283,7 +6242,7 @@ static int ipw_wx_get_genie(struct net_device *dev,
struct ieee80211_device *ieee = priv->ieee;
int err = 0;
- //down(&priv->sem);
+ //mutex_lock(&priv->mutex);
//if (!ieee->wpa_enabled) {
// err = -EOPNOTSUPP;
@@ -6304,7 +6263,7 @@ static int ipw_wx_get_genie(struct net_device *dev,
memcpy(extra, ieee->wpa_ie, ieee->wpa_ie_len);
out:
- //up(&priv->sem);
+ //mutex_unlock(&priv->mutex);
return err;
}
@@ -6556,7 +6515,7 @@ static int ipw_wx_set_mlme(struct net_device *dev,
* get the modulation type of the current network or
* the card current mode
*/
-u8 ipw_qos_current_mode(struct ipw_priv * priv)
+static u8 ipw_qos_current_mode(struct ipw_priv * priv)
{
u8 mode = 0;
@@ -6964,12 +6923,12 @@ static void ipw_bg_qos_activate(void *data)
if (priv == NULL)
return;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
if (priv->status & STATUS_ASSOCIATED)
ipw_qos_activate(priv, &(priv->assoc_network->qos_data));
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
}
static int ipw_handle_probe_response(struct net_device *dev,
@@ -7010,25 +6969,15 @@ static int ipw_handle_assoc_response(struct net_device *dev,
static int ipw_send_qos_params_command(struct ipw_priv *priv, struct ieee80211_qos_parameters
*qos_param)
{
- struct host_cmd cmd = {
- .cmd = IPW_CMD_QOS_PARAMETERS,
- .len = (sizeof(struct ieee80211_qos_parameters) * 3)
- };
-
- memcpy(cmd.param, qos_param, sizeof(*qos_param) * 3);
- return ipw_send_cmd(priv, &cmd);
+ return ipw_send_cmd_pdu(priv, IPW_CMD_QOS_PARAMETERS,
+ sizeof(*qos_param) * 3, qos_param);
}
static int ipw_send_qos_info_command(struct ipw_priv *priv, struct ieee80211_qos_information_element
*qos_param)
{
- struct host_cmd cmd = {
- .cmd = IPW_CMD_WME_INFO,
- .len = sizeof(*qos_param)
- };
-
- memcpy(cmd.param, qos_param, sizeof(*qos_param));
- return ipw_send_cmd(priv, &cmd);
+ return ipw_send_cmd_pdu(priv, IPW_CMD_WME_INFO, sizeof(*qos_param),
+ qos_param);
}
#endif /* CONFIG_IPW_QOS */
@@ -7052,19 +7001,21 @@ static int ipw_associate_network(struct ipw_priv *priv,
memset(&priv->assoc_request, 0, sizeof(priv->assoc_request));
priv->assoc_request.channel = network->channel;
+ priv->assoc_request.auth_key = 0;
+
if ((priv->capability & CAP_PRIVACY_ON) &&
- (priv->capability & CAP_SHARED_KEY)) {
+ (priv->ieee->sec.auth_mode == WLAN_AUTH_SHARED_KEY)) {
priv->assoc_request.auth_type = AUTH_SHARED_KEY;
priv->assoc_request.auth_key = priv->ieee->sec.active_key;
- if ((priv->capability & CAP_PRIVACY_ON) &&
- (priv->ieee->sec.level == SEC_LEVEL_1) &&
- !(priv->ieee->host_encrypt || priv->ieee->host_decrypt))
+ if (priv->ieee->sec.level == SEC_LEVEL_1)
ipw_send_wep_keys(priv, DCW_WEP_KEY_SEC_TYPE_WEP);
- } else {
+
+ } else if ((priv->capability & CAP_PRIVACY_ON) &&
+ (priv->ieee->sec.auth_mode == WLAN_AUTH_LEAP))
+ priv->assoc_request.auth_type = AUTH_LEAP;
+ else
priv->assoc_request.auth_type = AUTH_OPEN;
- priv->assoc_request.auth_key = 0;
- }
if (priv->ieee->wpa_ie_len) {
priv->assoc_request.policy_support = 0x02; /* RSN active */
@@ -7278,9 +7229,9 @@ static void ipw_roam(void *data)
static void ipw_bg_roam(void *data)
{
struct ipw_priv *priv = data;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
ipw_roam(data);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
}
static int ipw_associate(void *data)
@@ -7375,9 +7326,9 @@ static int ipw_associate(void *data)
static void ipw_bg_associate(void *data)
{
struct ipw_priv *priv = data;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
ipw_associate(data);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
}
static void ipw_rebuild_decrypted_skb(struct ipw_priv *priv,
@@ -7811,12 +7762,10 @@ static void ipw_rx(struct ipw_priv *priv)
while (i != r) {
rxb = priv->rxq->queue[i];
-#ifdef CONFIG_IPW2200_DEBUG
if (unlikely(rxb == NULL)) {
printk(KERN_CRIT "Queue not allocated!\n");
break;
}
-#endif
priv->rxq->queue[i] = NULL;
pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr,
@@ -7835,7 +7784,8 @@ static void ipw_rx(struct ipw_priv *priv)
le16_to_cpu(pkt->u.frame.rssi_dbm) -
IPW_RSSI_TO_DBM,
.signal =
- le16_to_cpu(pkt->u.frame.signal),
+ le16_to_cpu(pkt->u.frame.rssi_dbm) -
+ IPW_RSSI_TO_DBM + 0x100,
.noise =
le16_to_cpu(pkt->u.frame.noise),
.rate = pkt->u.frame.rate,
@@ -7899,7 +7849,8 @@ static void ipw_rx(struct ipw_priv *priv)
le16_to_cpu(pkt->u.frame.length));
if (le16_to_cpu(pkt->u.frame.length) <
- frame_hdr_len(header)) {
+ ieee80211_get_hdrlen(le16_to_cpu(
+ header->frame_ctl))) {
IPW_DEBUG_DROP
("Received packet is too small. "
"Dropping.\n");
@@ -7989,7 +7940,14 @@ static void ipw_rx(struct ipw_priv *priv)
#define DEFAULT_SHORT_RETRY_LIMIT 7U
#define DEFAULT_LONG_RETRY_LIMIT 4U
-static int ipw_sw_reset(struct ipw_priv *priv, int init)
+/**
+ * ipw_sw_reset
+ * @option: options to control different reset behaviour
+ * 0 = reset everything except the 'disable' module_param
+ * 1 = reset everything and print out driver info (for probe only)
+ * 2 = reset everything
+ */
+static int ipw_sw_reset(struct ipw_priv *priv, int option)
{
int band, modulation;
int old_mode = priv->ieee->iw_mode;
@@ -8016,7 +7974,7 @@ static int ipw_sw_reset(struct ipw_priv *priv, int init)
priv->essid_len = 0;
memset(priv->essid, 0, IW_ESSID_MAX_SIZE);
- if (disable) {
+ if (disable && option) {
priv->status |= STATUS_RF_KILL_SW;
IPW_DEBUG_INFO("Radio disabled.\n");
}
@@ -8068,7 +8026,7 @@ static int ipw_sw_reset(struct ipw_priv *priv, int init)
if ((priv->pci_dev->device == 0x4223) ||
(priv->pci_dev->device == 0x4224)) {
- if (init)
+ if (option == 1)
printk(KERN_INFO DRV_NAME
": Detected Intel PRO/Wireless 2915ABG Network "
"Connection\n");
@@ -8079,7 +8037,7 @@ static int ipw_sw_reset(struct ipw_priv *priv, int init)
priv->adapter = IPW_2915ABG;
priv->ieee->mode = IEEE_A | IEEE_G | IEEE_B;
} else {
- if (init)
+ if (option == 1)
printk(KERN_INFO DRV_NAME
": Detected Intel PRO/Wireless 2200BG Network "
"Connection\n");
@@ -8126,7 +8084,7 @@ static int ipw_wx_get_name(struct net_device *dev,
union iwreq_data *wrqu, char *extra)
{
struct ipw_priv *priv = ieee80211_priv(dev);
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
if (priv->status & STATUS_RF_KILL_MASK)
strcpy(wrqu->name, "radio off");
else if (!(priv->status & STATUS_ASSOCIATED))
@@ -8135,7 +8093,7 @@ static int ipw_wx_get_name(struct net_device *dev,
snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11%c",
ipw_modes[priv->assoc_request.ieee_mode]);
IPW_DEBUG_WX("Name: %s\n", wrqu->name);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return 0;
}
@@ -8196,7 +8154,7 @@ static int ipw_wx_set_freq(struct net_device *dev,
union iwreq_data *wrqu, char *extra)
{
struct ipw_priv *priv = ieee80211_priv(dev);
- const struct ieee80211_geo *geo = ipw_get_geo(priv->ieee);
+ const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee);
struct iw_freq *fwrq = &wrqu->freq;
int ret = 0, i;
u8 channel, flags;
@@ -8204,24 +8162,24 @@ static int ipw_wx_set_freq(struct net_device *dev,
if (fwrq->m == 0) {
IPW_DEBUG_WX("SET Freq/Channel -> any\n");
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
ret = ipw_set_channel(priv, 0);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return ret;
}
/* if setting by freq convert to channel */
if (fwrq->e == 1) {
- channel = ipw_freq_to_channel(priv->ieee, fwrq->m);
+ channel = ieee80211_freq_to_channel(priv->ieee, fwrq->m);
if (channel == 0)
return -EINVAL;
} else
channel = fwrq->m;
- if (!(band = ipw_is_valid_channel(priv->ieee, channel)))
+ if (!(band = ieee80211_is_valid_channel(priv->ieee, channel)))
return -EINVAL;
if (priv->ieee->iw_mode == IW_MODE_ADHOC) {
- i = ipw_channel_to_index(priv->ieee, channel);
+ i = ieee80211_channel_to_index(priv->ieee, channel);
if (i == -1)
return -EINVAL;
@@ -8234,9 +8192,9 @@ static int ipw_wx_set_freq(struct net_device *dev,
}
IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m);
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
ret = ipw_set_channel(priv, channel);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return ret;
}
@@ -8250,14 +8208,14 @@ static int ipw_wx_get_freq(struct net_device *dev,
/* If we are associated, trying to associate, or have a statically
* configured CHANNEL then return that; otherwise return ANY */
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
if (priv->config & CFG_STATIC_CHANNEL ||
priv->status & (STATUS_ASSOCIATING | STATUS_ASSOCIATED))
wrqu->freq.m = priv->channel;
else
wrqu->freq.m = 0;
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
IPW_DEBUG_WX("GET Freq/Channel -> %d \n", priv->channel);
return 0;
}
@@ -8287,7 +8245,7 @@ static int ipw_wx_set_mode(struct net_device *dev,
if (wrqu->mode == priv->ieee->iw_mode)
return 0;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
ipw_sw_reset(priv, 0);
@@ -8310,7 +8268,7 @@ static int ipw_wx_set_mode(struct net_device *dev,
priv->ieee->iw_mode = wrqu->mode;
queue_work(priv->workqueue, &priv->adapter_restart);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return err;
}
@@ -8319,10 +8277,10 @@ static int ipw_wx_get_mode(struct net_device *dev,
union iwreq_data *wrqu, char *extra)
{
struct ipw_priv *priv = ieee80211_priv(dev);
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
wrqu->mode = priv->ieee->iw_mode;
IPW_DEBUG_WX("Get MODE -> %d\n", wrqu->mode);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return 0;
}
@@ -8349,7 +8307,7 @@ static int ipw_wx_get_range(struct net_device *dev,
{
struct ipw_priv *priv = ieee80211_priv(dev);
struct iw_range *range = (struct iw_range *)extra;
- const struct ieee80211_geo *geo = ipw_get_geo(priv->ieee);
+ const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee);
int i = 0, j;
wrqu->data.length = sizeof(*range);
@@ -8361,7 +8319,7 @@ static int ipw_wx_get_range(struct net_device *dev,
range->max_qual.qual = 100;
/* TODO: Find real max RSSI and stick here */
range->max_qual.level = 0;
- range->max_qual.noise = priv->ieee->worst_rssi + 0x100;
+ range->max_qual.noise = 0;
range->max_qual.updated = 7; /* Updated all three */
range->avg_qual.qual = 70;
@@ -8369,7 +8327,7 @@ static int ipw_wx_get_range(struct net_device *dev,
range->avg_qual.level = 0; /* FIXME to real average level */
range->avg_qual.noise = 0;
range->avg_qual.updated = 7; /* Updated all three */
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
range->num_bitrates = min(priv->rates.num_rates, (u8) IW_MAX_BITRATES);
for (i = 0; i < range->num_bitrates; i++)
@@ -8387,31 +8345,39 @@ static int ipw_wx_get_range(struct net_device *dev,
/* Set the Wireless Extension versions */
range->we_version_compiled = WIRELESS_EXT;
- range->we_version_source = 16;
+ range->we_version_source = 18;
i = 0;
if (priv->ieee->mode & (IEEE_B | IEEE_G)) {
- for (j = 0; j < geo->bg_channels && i < IW_MAX_FREQUENCIES;
- i++, j++) {
+ for (j = 0; j < geo->bg_channels && i < IW_MAX_FREQUENCIES; j++) {
+ if ((priv->ieee->iw_mode == IW_MODE_ADHOC) &&
+ (geo->bg[j].flags & IEEE80211_CH_PASSIVE_ONLY))
+ continue;
+
range->freq[i].i = geo->bg[j].channel;
range->freq[i].m = geo->bg[j].freq * 100000;
range->freq[i].e = 1;
+ i++;
}
}
if (priv->ieee->mode & IEEE_A) {
- for (j = 0; j < geo->a_channels && i < IW_MAX_FREQUENCIES;
- i++, j++) {
+ for (j = 0; j < geo->a_channels && i < IW_MAX_FREQUENCIES; j++) {
+ if ((priv->ieee->iw_mode == IW_MODE_ADHOC) &&
+ (geo->a[j].flags & IEEE80211_CH_PASSIVE_ONLY))
+ continue;
+
range->freq[i].i = geo->a[j].channel;
range->freq[i].m = geo->a[j].freq * 100000;
range->freq[i].e = 1;
+ i++;
}
}
range->num_channels = i;
range->num_frequency = i;
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
/* Event capability (kernel + driver) */
range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
@@ -8419,6 +8385,9 @@ static int ipw_wx_get_range(struct net_device *dev,
IW_EVENT_CAPA_MASK(SIOCGIWAP));
range->event_capa[1] = IW_EVENT_CAPA_K_1;
+ range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
+ IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
+
IPW_DEBUG_WX("GET Range\n");
return 0;
}
@@ -8438,7 +8407,7 @@ static int ipw_wx_set_wap(struct net_device *dev,
if (wrqu->ap_addr.sa_family != ARPHRD_ETHER)
return -EINVAL;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
if (!memcmp(any, wrqu->ap_addr.sa_data, ETH_ALEN) ||
!memcmp(off, wrqu->ap_addr.sa_data, ETH_ALEN)) {
/* we disable mandatory BSSID association */
@@ -8447,14 +8416,14 @@ static int ipw_wx_set_wap(struct net_device *dev,
IPW_DEBUG_ASSOC("Attempting to associate with new "
"parameters.\n");
ipw_associate(priv);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return 0;
}
priv->config |= CFG_STATIC_BSSID;
if (!memcmp(priv->bssid, wrqu->ap_addr.sa_data, ETH_ALEN)) {
IPW_DEBUG_WX("BSSID set to current BSSID.\n");
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return 0;
}
@@ -8468,7 +8437,7 @@ static int ipw_wx_set_wap(struct net_device *dev,
if (!ipw_disassociate(priv))
ipw_associate(priv);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return 0;
}
@@ -8479,7 +8448,7 @@ static int ipw_wx_get_wap(struct net_device *dev,
struct ipw_priv *priv = ieee80211_priv(dev);
/* If we are associated, trying to associate, or have a statically
* configured BSSID then return that; otherwise return ANY */
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
if (priv->config & CFG_STATIC_BSSID ||
priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) {
wrqu->ap_addr.sa_family = ARPHRD_ETHER;
@@ -8489,7 +8458,7 @@ static int ipw_wx_get_wap(struct net_device *dev,
IPW_DEBUG_WX("Getting WAP BSSID: " MAC_FMT "\n",
MAC_ARG(wrqu->ap_addr.sa_data));
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return 0;
}
@@ -8500,7 +8469,7 @@ static int ipw_wx_set_essid(struct net_device *dev,
struct ipw_priv *priv = ieee80211_priv(dev);
char *essid = ""; /* ANY */
int length = 0;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
if (wrqu->essid.flags && wrqu->essid.length) {
length = wrqu->essid.length - 1;
essid = extra;
@@ -8515,7 +8484,7 @@ static int ipw_wx_set_essid(struct net_device *dev,
priv->config &= ~CFG_STATIC_ESSID;
ipw_associate(priv);
}
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return 0;
}
@@ -8525,7 +8494,7 @@ static int ipw_wx_set_essid(struct net_device *dev,
if (priv->essid_len == length && !memcmp(priv->essid, extra, length)) {
IPW_DEBUG_WX("ESSID set to current ESSID.\n");
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return 0;
}
@@ -8540,7 +8509,7 @@ static int ipw_wx_set_essid(struct net_device *dev,
if (!ipw_disassociate(priv))
ipw_associate(priv);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return 0;
}
@@ -8552,7 +8521,7 @@ static int ipw_wx_get_essid(struct net_device *dev,
/* If we are associated, trying to associate, or have a statically
* configured ESSID then return that; otherwise return ANY */
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
if (priv->config & CFG_STATIC_ESSID ||
priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) {
IPW_DEBUG_WX("Getting essid: '%s'\n",
@@ -8565,7 +8534,7 @@ static int ipw_wx_get_essid(struct net_device *dev,
wrqu->essid.length = 0;
wrqu->essid.flags = 0; /* active */
}
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return 0;
}
@@ -8578,12 +8547,12 @@ static int ipw_wx_set_nick(struct net_device *dev,
IPW_DEBUG_WX("Setting nick to '%s'\n", extra);
if (wrqu->data.length > IW_ESSID_MAX_SIZE)
return -E2BIG;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
wrqu->data.length = min((size_t) wrqu->data.length, sizeof(priv->nick));
memset(priv->nick, 0, sizeof(priv->nick));
memcpy(priv->nick, extra, wrqu->data.length);
IPW_DEBUG_TRACE("<<\n");
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return 0;
}
@@ -8594,11 +8563,57 @@ static int ipw_wx_get_nick(struct net_device *dev,
{
struct ipw_priv *priv = ieee80211_priv(dev);
IPW_DEBUG_WX("Getting nick\n");
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
wrqu->data.length = strlen(priv->nick) + 1;
memcpy(extra, priv->nick, wrqu->data.length);
wrqu->data.flags = 1; /* active */
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
+ return 0;
+}
+
+static int ipw_wx_set_sens(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ int err = 0;
+
+ IPW_DEBUG_WX("Setting roaming threshold to %d\n", wrqu->sens.value);
+ IPW_DEBUG_WX("Setting disassociate threshold to %d\n", 3*wrqu->sens.value);
+ mutex_lock(&priv->mutex);
+
+ if (wrqu->sens.fixed == 0)
+ {
+ priv->roaming_threshold = IPW_MB_ROAMING_THRESHOLD_DEFAULT;
+ priv->disassociate_threshold = IPW_MB_DISASSOCIATE_THRESHOLD_DEFAULT;
+ goto out;
+ }
+ if ((wrqu->sens.value > IPW_MB_ROAMING_THRESHOLD_MAX) ||
+ (wrqu->sens.value < IPW_MB_ROAMING_THRESHOLD_MIN)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ priv->roaming_threshold = wrqu->sens.value;
+ priv->disassociate_threshold = 3*wrqu->sens.value;
+ out:
+ mutex_unlock(&priv->mutex);
+ return err;
+}
+
+static int ipw_wx_get_sens(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ipw_priv *priv = ieee80211_priv(dev);
+ mutex_lock(&priv->mutex);
+ wrqu->sens.fixed = 1;
+ wrqu->sens.value = priv->roaming_threshold;
+ mutex_unlock(&priv->mutex);
+
+ IPW_DEBUG_WX("GET roaming threshold -> %s %d \n",
+ wrqu->power.disabled ? "OFF" : "ON", wrqu->power.value);
+
return 0;
}
@@ -8691,7 +8706,7 @@ static int ipw_wx_set_rate(struct net_device *dev,
apply:
IPW_DEBUG_WX("Setting rate mask to 0x%08X [%s]\n",
mask, fixed ? "fixed" : "sub-rates");
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
if (mask == IEEE80211_DEFAULT_RATES_MASK) {
priv->config &= ~CFG_FIXED_RATE;
ipw_set_fixed_rate(priv, priv->ieee->mode);
@@ -8700,7 +8715,7 @@ static int ipw_wx_set_rate(struct net_device *dev,
if (priv->rates_mask == mask) {
IPW_DEBUG_WX("Mask set to current mask.\n");
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return 0;
}
@@ -8711,7 +8726,7 @@ static int ipw_wx_set_rate(struct net_device *dev,
if (!ipw_disassociate(priv))
ipw_associate(priv);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return 0;
}
@@ -8720,9 +8735,9 @@ static int ipw_wx_get_rate(struct net_device *dev,
union iwreq_data *wrqu, char *extra)
{
struct ipw_priv *priv = ieee80211_priv(dev);
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
wrqu->bitrate.value = priv->last_rate;
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value);
return 0;
}
@@ -8732,20 +8747,20 @@ static int ipw_wx_set_rts(struct net_device *dev,
union iwreq_data *wrqu, char *extra)
{
struct ipw_priv *priv = ieee80211_priv(dev);
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
if (wrqu->rts.disabled)
priv->rts_threshold = DEFAULT_RTS_THRESHOLD;
else {
if (wrqu->rts.value < MIN_RTS_THRESHOLD ||
wrqu->rts.value > MAX_RTS_THRESHOLD) {
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return -EINVAL;
}
priv->rts_threshold = wrqu->rts.value;
}
ipw_send_rts_threshold(priv, priv->rts_threshold);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
IPW_DEBUG_WX("SET RTS Threshold -> %d \n", priv->rts_threshold);
return 0;
}
@@ -8755,11 +8770,11 @@ static int ipw_wx_get_rts(struct net_device *dev,
union iwreq_data *wrqu, char *extra)
{
struct ipw_priv *priv = ieee80211_priv(dev);
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
wrqu->rts.value = priv->rts_threshold;
wrqu->rts.fixed = 0; /* no auto select */
wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
IPW_DEBUG_WX("GET RTS Threshold -> %d \n", wrqu->rts.value);
return 0;
}
@@ -8771,7 +8786,7 @@ static int ipw_wx_set_txpow(struct net_device *dev,
struct ipw_priv *priv = ieee80211_priv(dev);
int err = 0;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
if (ipw_radio_kill_sw(priv, wrqu->power.disabled)) {
err = -EINPROGRESS;
goto out;
@@ -8794,7 +8809,7 @@ static int ipw_wx_set_txpow(struct net_device *dev,
priv->tx_power = wrqu->power.value;
err = ipw_set_tx_power(priv);
out:
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return err;
}
@@ -8803,12 +8818,12 @@ static int ipw_wx_get_txpow(struct net_device *dev,
union iwreq_data *wrqu, char *extra)
{
struct ipw_priv *priv = ieee80211_priv(dev);
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
wrqu->power.value = priv->tx_power;
wrqu->power.fixed = 1;
wrqu->power.flags = IW_TXPOW_DBM;
wrqu->power.disabled = (priv->status & STATUS_RF_KILL_MASK) ? 1 : 0;
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
IPW_DEBUG_WX("GET TX Power -> %s %d \n",
wrqu->power.disabled ? "OFF" : "ON", wrqu->power.value);
@@ -8821,13 +8836,13 @@ static int ipw_wx_set_frag(struct net_device *dev,
union iwreq_data *wrqu, char *extra)
{
struct ipw_priv *priv = ieee80211_priv(dev);
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
if (wrqu->frag.disabled)
priv->ieee->fts = DEFAULT_FTS;
else {
if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
wrqu->frag.value > MAX_FRAG_THRESHOLD) {
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return -EINVAL;
}
@@ -8835,7 +8850,7 @@ static int ipw_wx_set_frag(struct net_device *dev,
}
ipw_send_frag_threshold(priv, wrqu->frag.value);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
IPW_DEBUG_WX("SET Frag Threshold -> %d \n", wrqu->frag.value);
return 0;
}
@@ -8845,11 +8860,11 @@ static int ipw_wx_get_frag(struct net_device *dev,
union iwreq_data *wrqu, char *extra)
{
struct ipw_priv *priv = ieee80211_priv(dev);
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
wrqu->frag.value = priv->ieee->fts;
wrqu->frag.fixed = 0; /* no auto select */
wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FTS);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
IPW_DEBUG_WX("GET Frag Threshold -> %d \n", wrqu->frag.value);
return 0;
@@ -8870,7 +8885,7 @@ static int ipw_wx_set_retry(struct net_device *dev,
if (wrqu->retry.value < 0 || wrqu->retry.value > 255)
return -EINVAL;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
if (wrqu->retry.flags & IW_RETRY_MIN)
priv->short_retry_limit = (u8) wrqu->retry.value;
else if (wrqu->retry.flags & IW_RETRY_MAX)
@@ -8882,7 +8897,7 @@ static int ipw_wx_set_retry(struct net_device *dev,
ipw_send_retry_limit(priv, priv->short_retry_limit,
priv->long_retry_limit);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
IPW_DEBUG_WX("SET retry limit -> short:%d long:%d\n",
priv->short_retry_limit, priv->long_retry_limit);
return 0;
@@ -8894,11 +8909,11 @@ static int ipw_wx_get_retry(struct net_device *dev,
{
struct ipw_priv *priv = ieee80211_priv(dev);
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
wrqu->retry.disabled = 0;
if ((wrqu->retry.flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return -EINVAL;
}
@@ -8912,7 +8927,7 @@ static int ipw_wx_get_retry(struct net_device *dev,
wrqu->retry.flags = IW_RETRY_LIMIT;
wrqu->retry.value = priv->short_retry_limit;
}
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
IPW_DEBUG_WX("GET retry -> %d \n", wrqu->retry.value);
@@ -8929,7 +8944,7 @@ static int ipw_request_direct_scan(struct ipw_priv *priv, char *essid,
(priv->status & STATUS_EXIT_PENDING))
return 0;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
if (priv->status & STATUS_RF_KILL_MASK) {
IPW_DEBUG_HC("Aborting scan due to RF kill activation\n");
@@ -8981,7 +8996,7 @@ static int ipw_request_direct_scan(struct ipw_priv *priv, char *essid,
priv->status |= STATUS_SCANNING;
done:
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return err;
}
@@ -9024,7 +9039,7 @@ static int ipw_wx_set_encode(struct net_device *dev,
int ret;
u32 cap = priv->capability;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
ret = ieee80211_wx_set_encode(priv->ieee, info, wrqu, key);
/* In IBSS mode, we need to notify the firmware to update
@@ -9034,7 +9049,7 @@ static int ipw_wx_set_encode(struct net_device *dev,
priv->status & STATUS_ASSOCIATED)
ipw_disassociate(priv);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return ret;
}
@@ -9052,17 +9067,17 @@ static int ipw_wx_set_power(struct net_device *dev,
{
struct ipw_priv *priv = ieee80211_priv(dev);
int err;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
if (wrqu->power.disabled) {
priv->power_mode = IPW_POWER_LEVEL(priv->power_mode);
err = ipw_send_power_mode(priv, IPW_POWER_MODE_CAM);
if (err) {
IPW_DEBUG_WX("failed setting power mode.\n");
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return err;
}
IPW_DEBUG_WX("SET Power Management Mode -> off\n");
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return 0;
}
@@ -9074,7 +9089,7 @@ static int ipw_wx_set_power(struct net_device *dev,
default: /* Otherwise we don't support it */
IPW_DEBUG_WX("SET PM Mode: %X not supported.\n",
wrqu->power.flags);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return -EOPNOTSUPP;
}
@@ -9087,12 +9102,12 @@ static int ipw_wx_set_power(struct net_device *dev,
err = ipw_send_power_mode(priv, IPW_POWER_LEVEL(priv->power_mode));
if (err) {
IPW_DEBUG_WX("failed setting power mode.\n");
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return err;
}
IPW_DEBUG_WX("SET Power Management Mode -> 0x%02X\n", priv->power_mode);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return 0;
}
@@ -9101,13 +9116,13 @@ static int ipw_wx_get_power(struct net_device *dev,
union iwreq_data *wrqu, char *extra)
{
struct ipw_priv *priv = ieee80211_priv(dev);
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
if (!(priv->power_mode & IPW_POWER_ENABLED))
wrqu->power.disabled = 1;
else
wrqu->power.disabled = 0;
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
IPW_DEBUG_WX("GET Power Management Mode -> %02X\n", priv->power_mode);
return 0;
@@ -9120,7 +9135,7 @@ static int ipw_wx_set_powermode(struct net_device *dev,
struct ipw_priv *priv = ieee80211_priv(dev);
int mode = *(int *)extra;
int err;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
if ((mode < 1) || (mode > IPW_POWER_LIMIT)) {
mode = IPW_POWER_AC;
priv->power_mode = mode;
@@ -9133,11 +9148,11 @@ static int ipw_wx_set_powermode(struct net_device *dev,
if (err) {
IPW_DEBUG_WX("failed setting power mode.\n");
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return err;
}
}
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return 0;
}
@@ -9186,7 +9201,7 @@ static int ipw_wx_set_wireless_mode(struct net_device *dev,
IPW_WARNING("Attempt to set invalid wireless mode: %d\n", mode);
return -EINVAL;
}
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
if (priv->adapter == IPW_2915ABG) {
priv->ieee->abg_true = 1;
if (mode & IEEE_A) {
@@ -9198,7 +9213,7 @@ static int ipw_wx_set_wireless_mode(struct net_device *dev,
if (mode & IEEE_A) {
IPW_WARNING("Attempt to set 2200BG into "
"802.11a mode\n");
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return -EINVAL;
}
@@ -9235,7 +9250,7 @@ static int ipw_wx_set_wireless_mode(struct net_device *dev,
IPW_DEBUG_WX("PRIV SET MODE: %c%c%c\n",
mode & IEEE_A ? 'a' : '.',
mode & IEEE_B ? 'b' : '.', mode & IEEE_G ? 'g' : '.');
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return 0;
}
@@ -9244,7 +9259,7 @@ static int ipw_wx_get_wireless_mode(struct net_device *dev,
union iwreq_data *wrqu, char *extra)
{
struct ipw_priv *priv = ieee80211_priv(dev);
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
switch (priv->ieee->mode) {
case IEEE_A:
strncpy(extra, "802.11a (1)", MAX_WX_STRING);
@@ -9275,7 +9290,7 @@ static int ipw_wx_get_wireless_mode(struct net_device *dev,
IPW_DEBUG_WX("PRIV GET MODE: %s\n", extra);
wrqu->data.length = strlen(extra) + 1;
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return 0;
}
@@ -9286,7 +9301,7 @@ static int ipw_wx_set_preamble(struct net_device *dev,
{
struct ipw_priv *priv = ieee80211_priv(dev);
int mode = *(int *)extra;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
/* Switching from SHORT -> LONG requires a disassociation */
if (mode == 1) {
if (!(priv->config & CFG_PREAMBLE_LONG)) {
@@ -9305,11 +9320,11 @@ static int ipw_wx_set_preamble(struct net_device *dev,
priv->config &= ~CFG_PREAMBLE_LONG;
goto done;
}
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return -EINVAL;
done:
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return 0;
}
@@ -9318,12 +9333,12 @@ static int ipw_wx_get_preamble(struct net_device *dev,
union iwreq_data *wrqu, char *extra)
{
struct ipw_priv *priv = ieee80211_priv(dev);
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
if (priv->config & CFG_PREAMBLE_LONG)
snprintf(wrqu->name, IFNAMSIZ, "long (1)");
else
snprintf(wrqu->name, IFNAMSIZ, "auto (0)");
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return 0;
}
@@ -9335,7 +9350,7 @@ static int ipw_wx_set_monitor(struct net_device *dev,
struct ipw_priv *priv = ieee80211_priv(dev);
int *parms = (int *)extra;
int enable = (parms[0] > 0);
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
IPW_DEBUG_WX("SET MONITOR: %d %d\n", enable, parms[1]);
if (enable) {
if (priv->ieee->iw_mode != IW_MODE_MONITOR) {
@@ -9350,13 +9365,13 @@ static int ipw_wx_set_monitor(struct net_device *dev,
ipw_set_channel(priv, parms[1]);
} else {
if (priv->ieee->iw_mode != IW_MODE_MONITOR) {
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return 0;
}
priv->net_dev->type = ARPHRD_ETHER;
queue_work(priv->workqueue, &priv->adapter_restart);
}
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return 0;
}
@@ -9386,9 +9401,9 @@ static int ipw_wx_sw_reset(struct net_device *dev,
IPW_DEBUG_WX("SW_RESET\n");
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
- ret = ipw_sw_reset(priv, 0);
+ ret = ipw_sw_reset(priv, 2);
if (!ret) {
free_firmware();
ipw_adapter_restart(priv);
@@ -9398,9 +9413,9 @@ static int ipw_wx_sw_reset(struct net_device *dev,
* module parameter, so take appropriate action */
ipw_radio_kill_sw(priv, priv->status & STATUS_RF_KILL_SW);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
ieee80211_wx_set_encode(priv->ieee, info, &wrqu_sec, NULL);
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
if (!(priv->status & STATUS_RF_KILL_MASK)) {
/* Configuration likely changed -- force [re]association */
@@ -9410,7 +9425,7 @@ static int ipw_wx_sw_reset(struct net_device *dev,
ipw_associate(priv);
}
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return 0;
}
@@ -9423,6 +9438,8 @@ static iw_handler ipw_wx_handlers[] = {
IW_IOCTL(SIOCGIWFREQ) = ipw_wx_get_freq,
IW_IOCTL(SIOCSIWMODE) = ipw_wx_set_mode,
IW_IOCTL(SIOCGIWMODE) = ipw_wx_get_mode,
+ IW_IOCTL(SIOCSIWSENS) = ipw_wx_set_sens,
+ IW_IOCTL(SIOCGIWSENS) = ipw_wx_get_sens,
IW_IOCTL(SIOCGIWRANGE) = ipw_wx_get_range,
IW_IOCTL(SIOCSIWAP) = ipw_wx_set_wap,
IW_IOCTL(SIOCGIWAP) = ipw_wx_get_wap,
@@ -9568,7 +9585,7 @@ static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev)
wstats->qual.level = average_value(&priv->average_rssi);
wstats->qual.noise = average_value(&priv->average_noise);
wstats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED |
- IW_QUAL_NOISE_UPDATED;
+ IW_QUAL_NOISE_UPDATED | IW_QUAL_DBM;
wstats->miss.beacon = average_value(&priv->average_missed_beacons);
wstats->discard.retries = priv->last_tx_failures;
@@ -9586,7 +9603,7 @@ static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev)
static void init_sys_config(struct ipw_sys_config *sys_config)
{
memset(sys_config, 0, sizeof(struct ipw_sys_config));
- sys_config->bt_coexistence = 1; /* We may need to look into prvStaBtConfig */
+ sys_config->bt_coexistence = 0;
sys_config->answer_broadcast_ssid_probe = 0;
sys_config->accept_all_data_frames = 0;
sys_config->accept_non_directed_frames = 1;
@@ -9594,12 +9611,13 @@ static void init_sys_config(struct ipw_sys_config *sys_config)
sys_config->disable_unicast_decryption = 1;
sys_config->exclude_multicast_unencrypted = 0;
sys_config->disable_multicast_decryption = 1;
- sys_config->antenna_diversity = CFG_SYS_ANTENNA_BOTH;
+ sys_config->antenna_diversity = CFG_SYS_ANTENNA_SLOW_DIV;
sys_config->pass_crc_to_host = 0; /* TODO: See if 1 gives us FCS */
sys_config->dot11g_auto_detection = 0;
sys_config->enable_cts_to_self = 0;
sys_config->bt_coexist_collision_thr = 0;
sys_config->pass_noise_stats_to_host = 1; //1 -- fix for 256
+ sys_config->silence_threshold = 0x1e;
}
static int ipw_net_open(struct net_device *dev)
@@ -9607,11 +9625,11 @@ static int ipw_net_open(struct net_device *dev)
struct ipw_priv *priv = ieee80211_priv(dev);
IPW_DEBUG_INFO("dev->open\n");
/* we should be verifying the device is ready to be opened */
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
if (!(priv->status & STATUS_RF_KILL_MASK) &&
(priv->status & STATUS_ASSOCIATED))
netif_start_queue(dev);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return 0;
}
@@ -9647,11 +9665,6 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
u16 remaining_bytes;
int fc;
- /* If there isn't room in the queue, we return busy and let the
- * network stack requeue the packet for us */
- if (ipw_queue_space(q) < q->high_mark)
- return NETDEV_TX_BUSY;
-
switch (priv->ieee->iw_mode) {
case IW_MODE_ADHOC:
hdr_len = IEEE80211_3ADDR_LEN;
@@ -9817,6 +9830,9 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
q->first_empty = ipw_queue_inc_wrap(q->first_empty, q->n_bd);
ipw_write32(priv, q->reg_w, q->first_empty);
+ if (ipw_queue_space(q) < q->high_mark)
+ netif_stop_queue(priv->net_dev);
+
return NETDEV_TX_OK;
drop:
@@ -9890,13 +9906,13 @@ static int ipw_net_set_mac_address(struct net_device *dev, void *p)
struct sockaddr *addr = p;
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
priv->config |= CFG_CUSTOM_MAC;
memcpy(priv->mac_addr, addr->sa_data, ETH_ALEN);
printk(KERN_INFO "%s: Setting MAC to " MAC_FMT "\n",
priv->net_dev->name, MAC_ARG(priv->mac_addr));
queue_work(priv->workqueue, &priv->adapter_restart);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return 0;
}
@@ -9940,9 +9956,9 @@ static int ipw_ethtool_get_eeprom(struct net_device *dev,
if (eeprom->offset + eeprom->len > IPW_EEPROM_IMAGE_SIZE)
return -EINVAL;
- down(&p->sem);
+ mutex_lock(&p->mutex);
memcpy(bytes, &p->eeprom[eeprom->offset], eeprom->len);
- up(&p->sem);
+ mutex_unlock(&p->mutex);
return 0;
}
@@ -9954,12 +9970,11 @@ static int ipw_ethtool_set_eeprom(struct net_device *dev,
if (eeprom->offset + eeprom->len > IPW_EEPROM_IMAGE_SIZE)
return -EINVAL;
- down(&p->sem);
+ mutex_lock(&p->mutex);
memcpy(&p->eeprom[eeprom->offset], bytes, eeprom->len);
- for (i = IPW_EEPROM_DATA;
- i < IPW_EEPROM_DATA + IPW_EEPROM_IMAGE_SIZE; i++)
- ipw_write8(p, i, p->eeprom[i]);
- up(&p->sem);
+ for (i = 0; i < IPW_EEPROM_IMAGE_SIZE; i++)
+ ipw_write8(p, i + IPW_EEPROM_DATA, p->eeprom[i]);
+ mutex_unlock(&p->mutex);
return 0;
}
@@ -10054,12 +10069,12 @@ static void ipw_rf_kill(void *adapter)
static void ipw_bg_rf_kill(void *data)
{
struct ipw_priv *priv = data;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
ipw_rf_kill(data);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
}
-void ipw_link_up(struct ipw_priv *priv)
+static void ipw_link_up(struct ipw_priv *priv)
{
priv->last_seq_num = -1;
priv->last_frag_num = -1;
@@ -10089,12 +10104,12 @@ void ipw_link_up(struct ipw_priv *priv)
static void ipw_bg_link_up(void *data)
{
struct ipw_priv *priv = data;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
ipw_link_up(data);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
}
-void ipw_link_down(struct ipw_priv *priv)
+static void ipw_link_down(struct ipw_priv *priv)
{
ipw_led_link_down(priv);
netif_carrier_off(priv->net_dev);
@@ -10117,9 +10132,9 @@ void ipw_link_down(struct ipw_priv *priv)
static void ipw_bg_link_down(void *data)
{
struct ipw_priv *priv = data;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
ipw_link_down(data);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
}
static int ipw_setup_deferred_work(struct ipw_priv *priv)
@@ -10292,6 +10307,20 @@ static int ipw_config(struct ipw_priv *priv)
/* set basic system config settings */
init_sys_config(&priv->sys_config);
+
+ /* Support Bluetooth if we have BT h/w on board, and user wants to.
+ * Does not support BT priority yet (don't abort or defer our Tx) */
+ if (bt_coexist) {
+ unsigned char bt_caps = priv->eeprom[EEPROM_SKU_CAPABILITY];
+
+ if (bt_caps & EEPROM_SKU_CAP_BT_CHANNEL_SIG)
+ priv->sys_config.bt_coexistence
+ |= CFG_BT_COEXISTENCE_SIGNAL_CHNL;
+ if (bt_caps & EEPROM_SKU_CAP_BT_OOB)
+ priv->sys_config.bt_coexistence
+ |= CFG_BT_COEXISTENCE_OOB;
+ }
+
if (priv->ieee->iw_mode == IW_MODE_ADHOC)
priv->sys_config.answer_broadcast_ssid_probe = 1;
else
@@ -10349,6 +10378,9 @@ static int ipw_config(struct ipw_priv *priv)
* not intended for resale of the above mentioned Intel adapters has
* not been tested.
*
+ * Remember to update the table in README.ipw2200 when changing this
+ * table.
+ *
*/
static const struct ieee80211_geo ipw_geos[] = {
{ /* Restricted */
@@ -10596,96 +10628,6 @@ static const struct ieee80211_geo ipw_geos[] = {
}
};
-/* GEO code borrowed from ieee80211_geo.c */
-static int ipw_is_valid_channel(struct ieee80211_device *ieee, u8 channel)
-{
- int i;
-
- /* Driver needs to initialize the geography map before using
- * these helper functions */
- BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0);
-
- if (ieee->freq_band & IEEE80211_24GHZ_BAND)
- for (i = 0; i < ieee->geo.bg_channels; i++)
- /* NOTE: If G mode is currently supported but
- * this is a B only channel, we don't see it
- * as valid. */
- if ((ieee->geo.bg[i].channel == channel) &&
- (!(ieee->mode & IEEE_G) ||
- !(ieee->geo.bg[i].flags & IEEE80211_CH_B_ONLY)))
- return IEEE80211_24GHZ_BAND;
-
- if (ieee->freq_band & IEEE80211_52GHZ_BAND)
- for (i = 0; i < ieee->geo.a_channels; i++)
- if (ieee->geo.a[i].channel == channel)
- return IEEE80211_52GHZ_BAND;
-
- return 0;
-}
-
-static int ipw_channel_to_index(struct ieee80211_device *ieee, u8 channel)
-{
- int i;
-
- /* Driver needs to initialize the geography map before using
- * these helper functions */
- BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0);
-
- if (ieee->freq_band & IEEE80211_24GHZ_BAND)
- for (i = 0; i < ieee->geo.bg_channels; i++)
- if (ieee->geo.bg[i].channel == channel)
- return i;
-
- if (ieee->freq_band & IEEE80211_52GHZ_BAND)
- for (i = 0; i < ieee->geo.a_channels; i++)
- if (ieee->geo.a[i].channel == channel)
- return i;
-
- return -1;
-}
-
-static u8 ipw_freq_to_channel(struct ieee80211_device *ieee, u32 freq)
-{
- int i;
-
- /* Driver needs to initialize the geography map before using
- * these helper functions */
- BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0);
-
- freq /= 100000;
-
- if (ieee->freq_band & IEEE80211_24GHZ_BAND)
- for (i = 0; i < ieee->geo.bg_channels; i++)
- if (ieee->geo.bg[i].freq == freq)
- return ieee->geo.bg[i].channel;
-
- if (ieee->freq_band & IEEE80211_52GHZ_BAND)
- for (i = 0; i < ieee->geo.a_channels; i++)
- if (ieee->geo.a[i].freq == freq)
- return ieee->geo.a[i].channel;
-
- return 0;
-}
-
-static int ipw_set_geo(struct ieee80211_device *ieee,
- const struct ieee80211_geo *geo)
-{
- memcpy(ieee->geo.name, geo->name, 3);
- ieee->geo.name[3] = '\0';
- ieee->geo.bg_channels = geo->bg_channels;
- ieee->geo.a_channels = geo->a_channels;
- memcpy(ieee->geo.bg, geo->bg, geo->bg_channels *
- sizeof(struct ieee80211_channel));
- memcpy(ieee->geo.a, geo->a, ieee->geo.a_channels *
- sizeof(struct ieee80211_channel));
- return 0;
-}
-
-static const struct ieee80211_geo *ipw_get_geo(struct ieee80211_device *ieee)
-{
- return &ieee->geo;
-}
-
#define MAX_HW_RESTARTS 5
static int ipw_up(struct ipw_priv *priv)
{
@@ -10732,14 +10674,11 @@ static int ipw_up(struct ipw_priv *priv)
priv->eeprom[EEPROM_COUNTRY_CODE + 2]);
j = 0;
}
- if (ipw_set_geo(priv->ieee, &ipw_geos[j])) {
+ if (ieee80211_set_geo(priv->ieee, &ipw_geos[j])) {
IPW_WARNING("Could not set geography.");
return 0;
}
- IPW_DEBUG_INFO("Geography %03d [%s] detected.\n",
- j, priv->ieee->geo.name);
-
if (priv->status & STATUS_RF_KILL_SW) {
IPW_WARNING("Radio disabled by module parameter.\n");
return 0;
@@ -10782,9 +10721,9 @@ static int ipw_up(struct ipw_priv *priv)
static void ipw_bg_up(void *data)
{
struct ipw_priv *priv = data;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
ipw_up(data);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
}
static void ipw_deinit(struct ipw_priv *priv)
@@ -10853,23 +10792,23 @@ static void ipw_down(struct ipw_priv *priv)
static void ipw_bg_down(void *data)
{
struct ipw_priv *priv = data;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
ipw_down(data);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
}
/* Called by register_netdev() */
static int ipw_net_init(struct net_device *dev)
{
struct ipw_priv *priv = ieee80211_priv(dev);
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
if (ipw_up(priv)) {
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return -EIO;
}
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
return 0;
}
@@ -10959,7 +10898,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
for (i = 0; i < IPW_IBSS_MAC_HASH_SIZE; i++)
INIT_LIST_HEAD(&priv->ibss_mac_hash[i]);
- init_MUTEX(&priv->sem);
+ mutex_init(&priv->mutex);
if (pci_enable_device(pdev)) {
err = -ENODEV;
goto out_free_ieee80211;
@@ -11017,7 +10956,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
SET_MODULE_OWNER(net_dev);
SET_NETDEV_DEV(net_dev, &pdev->dev);
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
priv->ieee->hard_start_xmit = ipw_net_hard_start_xmit;
priv->ieee->set_security = shim__set_security;
@@ -11050,16 +10989,22 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err = sysfs_create_group(&pdev->dev.kobj, &ipw_attribute_group);
if (err) {
IPW_ERROR("failed to create sysfs device attributes\n");
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
goto out_release_irq;
}
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
err = register_netdev(net_dev);
if (err) {
IPW_ERROR("failed to register network device\n");
goto out_remove_sysfs;
}
+
+ printk(KERN_INFO DRV_NAME ": Detected geography %s (%d 802.11bg "
+ "channels, %d 802.11a channels)\n",
+ priv->ieee->geo.name, priv->ieee->geo.bg_channels,
+ priv->ieee->geo.a_channels);
+
return 0;
out_remove_sysfs:
@@ -11091,13 +11036,13 @@ static void ipw_pci_remove(struct pci_dev *pdev)
if (!priv)
return;
- down(&priv->sem);
+ mutex_lock(&priv->mutex);
priv->status |= STATUS_EXIT_PENDING;
ipw_down(priv);
sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group);
- up(&priv->sem);
+ mutex_unlock(&priv->mutex);
unregister_netdev(priv->net_dev);
@@ -11250,8 +11195,10 @@ MODULE_PARM_DESC(auto_create, "auto create adhoc network (default on)");
module_param(led, int, 0444);
MODULE_PARM_DESC(led, "enable led control on some systems (default 0 off)\n");
+#ifdef CONFIG_IPW2200_DEBUG
module_param(debug, int, 0444);
MODULE_PARM_DESC(debug, "debug output mask");
+#endif
module_param(channel, int, 0444);
MODULE_PARM_DESC(channel, "channel to limit associate to (default 0 [ANY])");
@@ -11281,12 +11228,18 @@ module_param(mode, int, 0444);
MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS)");
#endif
+module_param(bt_coexist, int, 0444);
+MODULE_PARM_DESC(bt_coexist, "enable bluetooth coexistence (default off)");
+
module_param(hwcrypto, int, 0444);
-MODULE_PARM_DESC(hwcrypto, "enable hardware crypto (default on)");
+MODULE_PARM_DESC(hwcrypto, "enable hardware crypto (default off)");
module_param(cmdlog, int, 0444);
MODULE_PARM_DESC(cmdlog,
"allocate a ring buffer for logging firmware commands");
+module_param(roaming, int, 0444);
+MODULE_PARM_DESC(roaming, "enable roaming support (default on)");
+
module_exit(ipw_exit);
module_init(ipw_init);
diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h
index e65620a4d79e..4b9804900702 100644
--- a/drivers/net/wireless/ipw2200.h
+++ b/drivers/net/wireless/ipw2200.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved.
+ Copyright(c) 2003 - 2006 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the terms of version 2 of the GNU General Public License as
@@ -33,6 +33,7 @@
#include <linux/moduleparam.h>
#include <linux/config.h>
#include <linux/init.h>
+#include <linux/mutex.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
@@ -46,6 +47,7 @@
#include <linux/firmware.h>
#include <linux/wireless.h>
#include <linux/dma-mapping.h>
+#include <linux/jiffies.h>
#include <asm/io.h>
#include <net/ieee80211.h>
@@ -244,8 +246,10 @@ enum connection_manager_assoc_states {
#define HOST_NOTIFICATION_S36_MEASUREMENT_REFUSED 31
#define HOST_NOTIFICATION_STATUS_BEACON_MISSING 1
-#define IPW_MB_DISASSOCIATE_THRESHOLD_DEFAULT 24
+#define IPW_MB_ROAMING_THRESHOLD_MIN 1
#define IPW_MB_ROAMING_THRESHOLD_DEFAULT 8
+#define IPW_MB_ROAMING_THRESHOLD_MAX 30
+#define IPW_MB_DISASSOCIATE_THRESHOLD_DEFAULT 3*IPW_MB_ROAMING_THRESHOLD_DEFAULT
#define IPW_REAL_RATE_RX_PACKET_THRESHOLD 300
#define MACADRR_BYTE_LEN 6
@@ -616,13 +620,16 @@ struct notif_tgi_tx_key {
u8 reserved;
} __attribute__ ((packed));
+#define SILENCE_OVER_THRESH (1)
+#define SILENCE_UNDER_THRESH (2)
+
struct notif_link_deterioration {
struct ipw_cmd_stats stats;
u8 rate;
u8 modulation;
struct rate_histogram histogram;
- u8 reserved1;
- u16 reserved2;
+ u8 silence_notification_type; /* SILENCE_OVER/UNDER_THRESH */
+ u16 silence_count;
} __attribute__ ((packed));
struct notif_association {
@@ -780,7 +787,7 @@ struct ipw_sys_config {
u8 enable_cts_to_self;
u8 enable_multicast_filtering;
u8 bt_coexist_collision_thr;
- u8 reserved2;
+ u8 silence_threshold;
u8 accept_all_mgmt_bcpr;
u8 accept_all_mgtm_frames;
u8 pass_noise_stats_to_host;
@@ -852,7 +859,7 @@ struct ipw_scan_request_ext {
u16 dwell_time[IPW_SCAN_TYPES];
} __attribute__ ((packed));
-extern inline u8 ipw_get_scan_type(struct ipw_scan_request_ext *scan, u8 index)
+static inline u8 ipw_get_scan_type(struct ipw_scan_request_ext *scan, u8 index)
{
if (index % 2)
return scan->scan_type[index / 2] & 0x0F;
@@ -860,7 +867,7 @@ extern inline u8 ipw_get_scan_type(struct ipw_scan_request_ext *scan, u8 index)
return (scan->scan_type[index / 2] & 0xF0) >> 4;
}
-extern inline void ipw_set_scan_type(struct ipw_scan_request_ext *scan,
+static inline void ipw_set_scan_type(struct ipw_scan_request_ext *scan,
u8 index, u8 scan_type)
{
if (index % 2)
@@ -1120,7 +1127,7 @@ struct ipw_priv {
struct ieee80211_device *ieee;
spinlock_t lock;
- struct semaphore sem;
+ struct mutex mutex;
/* basic pci-network driver stuff */
struct pci_dev *pci_dev;
@@ -1406,13 +1413,6 @@ do { if (ipw_debug_level & (level)) \
* Register bit definitions
*/
-/* Dino control registers bits */
-
-#define DINO_ENABLE_SYSTEM 0x80
-#define DINO_ENABLE_CS 0x40
-#define DINO_RXFIFO_DATA 0x01
-#define DINO_CONTROL_REG 0x00200000
-
#define IPW_INTA_RW 0x00000008
#define IPW_INTA_MASK_R 0x0000000C
#define IPW_INDIRECT_ADDR 0x00000010
@@ -1459,6 +1459,11 @@ do { if (ipw_debug_level & (level)) \
#define IPW_DOMAIN_0_END 0x1000
#define CLX_MEM_BAR_SIZE 0x1000
+/* Dino/baseband control registers bits */
+
+#define DINO_ENABLE_SYSTEM 0x80 /* 1 = baseband processor on, 0 = reset */
+#define DINO_ENABLE_CS 0x40 /* 1 = enable ucode load */
+#define DINO_RXFIFO_DATA 0x01 /* 1 = data available */
#define IPW_BASEBAND_CONTROL_STATUS 0X00200000
#define IPW_BASEBAND_TX_FIFO_WRITE 0X00200004
#define IPW_BASEBAND_RX_FIFO_READ 0X00200004
@@ -1567,13 +1572,18 @@ do { if (ipw_debug_level & (level)) \
#define EEPROM_BSS_CHANNELS_BG (GET_EEPROM_ADDR(0x2c,LSB)) /* 2 bytes */
#define EEPROM_HW_VERSION (GET_EEPROM_ADDR(0x72,LSB)) /* 2 bytes */
-/* NIC type as found in the one byte EEPROM_NIC_TYPE offset*/
+/* NIC type as found in the one byte EEPROM_NIC_TYPE offset */
#define EEPROM_NIC_TYPE_0 0
#define EEPROM_NIC_TYPE_1 1
#define EEPROM_NIC_TYPE_2 2
#define EEPROM_NIC_TYPE_3 3
#define EEPROM_NIC_TYPE_4 4
+/* Bluetooth Coexistence capabilities as found in EEPROM_SKU_CAPABILITY */
+#define EEPROM_SKU_CAP_BT_CHANNEL_SIG 0x01 /* we can tell BT our channel # */
+#define EEPROM_SKU_CAP_BT_PRIORITY 0x02 /* BT can take priority over us */
+#define EEPROM_SKU_CAP_BT_OOB 0x04 /* we can signal BT out-of-band */
+
#define FW_MEM_REG_LOWER_BOUND 0x00300000
#define FW_MEM_REG_EEPROM_ACCESS (FW_MEM_REG_LOWER_BOUND + 0x40)
#define IPW_EVENT_REG (FW_MEM_REG_LOWER_BOUND + 0x04)
@@ -1658,9 +1668,10 @@ enum {
IPW_FW_ERROR_FATAL_ERROR
};
-#define AUTH_OPEN 0
-#define AUTH_SHARED_KEY 1
-#define AUTH_IGNORE 3
+#define AUTH_OPEN 0
+#define AUTH_SHARED_KEY 1
+#define AUTH_LEAP 2
+#define AUTH_IGNORE 3
#define HC_ASSOCIATE 0
#define HC_REASSOCIATE 1
@@ -1860,7 +1871,7 @@ struct host_cmd {
u8 cmd;
u8 len;
u16 reserved;
- u32 param[TFD_CMD_IMMEDIATE_PAYLOAD_LENGTH];
+ u32 *param;
} __attribute__ ((packed));
struct ipw_cmd_log {
@@ -1869,21 +1880,24 @@ struct ipw_cmd_log {
struct host_cmd cmd;
};
-#define CFG_BT_COEXISTENCE_MIN 0x00
-#define CFG_BT_COEXISTENCE_DEFER 0x02
-#define CFG_BT_COEXISTENCE_KILL 0x04
-#define CFG_BT_COEXISTENCE_WME_OVER_BT 0x08
-#define CFG_BT_COEXISTENCE_OOB 0x10
-#define CFG_BT_COEXISTENCE_MAX 0xFF
-#define CFG_BT_COEXISTENCE_DEF 0x80 /* read Bt from EEPROM */
-
-#define CFG_CTS_TO_ITSELF_ENABLED_MIN 0x0
-#define CFG_CTS_TO_ITSELF_ENABLED_MAX 0x1
+/* SysConfig command parameters ... */
+/* bt_coexistence param */
+#define CFG_BT_COEXISTENCE_SIGNAL_CHNL 0x01 /* tell BT our chnl # */
+#define CFG_BT_COEXISTENCE_DEFER 0x02 /* defer our Tx if BT traffic */
+#define CFG_BT_COEXISTENCE_KILL 0x04 /* kill our Tx if BT traffic */
+#define CFG_BT_COEXISTENCE_WME_OVER_BT 0x08 /* multimedia extensions */
+#define CFG_BT_COEXISTENCE_OOB 0x10 /* signal BT via out-of-band */
+
+/* clear-to-send to self param */
+#define CFG_CTS_TO_ITSELF_ENABLED_MIN 0x00
+#define CFG_CTS_TO_ITSELF_ENABLED_MAX 0x01
#define CFG_CTS_TO_ITSELF_ENABLED_DEF CFG_CTS_TO_ITSELF_ENABLED_MIN
-#define CFG_SYS_ANTENNA_BOTH 0x000
-#define CFG_SYS_ANTENNA_A 0x001
-#define CFG_SYS_ANTENNA_B 0x003
+/* Antenna diversity param (h/w can select best antenna, based on signal) */
+#define CFG_SYS_ANTENNA_BOTH 0x00 /* NIC selects best antenna */
+#define CFG_SYS_ANTENNA_A 0x01 /* force antenna A */
+#define CFG_SYS_ANTENNA_B 0x03 /* force antenna B */
+#define CFG_SYS_ANTENNA_SLOW_DIV 0x02 /* consider background noise */
/*
* The definitions below were lifted off the ipw2100 driver, which only
@@ -1899,27 +1913,4 @@ struct ipw_cmd_log {
#define IPW_MAX_CONFIG_RETRIES 10
-static inline u32 frame_hdr_len(struct ieee80211_hdr_4addr *hdr)
-{
- u32 retval;
- u16 fc;
-
- retval = sizeof(struct ieee80211_hdr_3addr);
- fc = le16_to_cpu(hdr->frame_ctl);
-
- /*
- * Function ToDS FromDS
- * IBSS 0 0
- * To AP 1 0
- * From AP 0 1
- * WDS (bridge) 1 1
- *
- * Only WDS frames use Address4 among them. --YZ
- */
- if (!(fc & IEEE80211_FCTL_TODS) || !(fc & IEEE80211_FCTL_FROMDS))
- retval -= ETH_ALEN;
-
- return retval;
-}
-
#endif /* __ipw2200_h__ */
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
index bf6271ee387a..75ce6ddb0cf5 100644
--- a/drivers/net/wireless/netwave_cs.c
+++ b/drivers/net/wireless/netwave_cs.c
@@ -55,10 +55,8 @@
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/bitops.h>
-#ifdef CONFIG_NET_RADIO
#include <linux/wireless.h>
#include <net/iw_handler.h>
-#endif
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
diff --git a/drivers/net/wireless/prism54/oid_mgt.c b/drivers/net/wireless/prism54/oid_mgt.c
index eea2f04c8c6d..ebb238785839 100644
--- a/drivers/net/wireless/prism54/oid_mgt.c
+++ b/drivers/net/wireless/prism54/oid_mgt.c
@@ -332,7 +332,7 @@ mgt_le_to_cpu(int type, void *data)
case OID_TYPE_ATTACH:{
struct obj_attachment *attach = data;
attach->id = le16_to_cpu(attach->id);
- attach->size = le16_to_cpu(attach->size);;
+ attach->size = le16_to_cpu(attach->size);
break;
}
case OID_TYPE_SSID:
@@ -401,7 +401,7 @@ mgt_cpu_to_le(int type, void *data)
case OID_TYPE_ATTACH:{
struct obj_attachment *attach = data;
attach->id = cpu_to_le16(attach->id);
- attach->size = cpu_to_le16(attach->size);;
+ attach->size = cpu_to_le16(attach->size);
break;
}
case OID_TYPE_SSID:
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c
index fee4be1ce810..5fa6fbe35bb9 100644
--- a/drivers/net/wireless/spectrum_cs.c
+++ b/drivers/net/wireless/spectrum_cs.c
@@ -147,7 +147,7 @@ struct pdi {
__le16 _len; /* length of ID and data, in words */
__le16 _id; /* record ID */
char data[0]; /* plug data */
-} __attribute__ ((packed));;
+} __attribute__ ((packed));
/* Functions for access to little-endian data */
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
index 18baacfc5a2c..18a44580b53b 100644
--- a/drivers/net/wireless/strip.c
+++ b/drivers/net/wireless/strip.c
@@ -112,7 +112,7 @@ static const char StripVersion[] = "1.3A-STUART.CHESHIRE";
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/time.h>
-
+#include <linux/jiffies.h>
/************************************************************************/
/* Useful structures and definitions */
@@ -1569,7 +1569,7 @@ static int strip_xmit(struct sk_buff *skb, struct net_device *dev)
del_timer(&strip_info->idle_timer);
- if (jiffies - strip_info->pps_timer > HZ) {
+ if (time_after(jiffies, strip_info->pps_timer + HZ)) {
unsigned long t = jiffies - strip_info->pps_timer;
unsigned long rx_pps_count = (strip_info->rx_pps_count * HZ * 8 + t / 2) / t;
unsigned long tx_pps_count = (strip_info->tx_pps_count * HZ * 8 + t / 2) / t;
diff --git a/drivers/net/wireless/wavelan.p.h b/drivers/net/wireless/wavelan.p.h
index 166e28b9a4f7..5cb0bc8bb128 100644
--- a/drivers/net/wireless/wavelan.p.h
+++ b/drivers/net/wireless/wavelan.p.h
@@ -98,11 +98,7 @@
* characteristics of the hardware. Applications such as mobile IP may
* take advantage of it.
*
- * You will need to enable the CONFIG_NET_RADIO define in the kernel
- * configuration to enable the wireless extensions (this is the one
- * giving access to the radio network device choice).
- *
- * It might also be a good idea as well to fetch the wireless tools to
+ * It might be a good idea as well to fetch the wireless tools to
* configure the device and play a bit.
*/
diff --git a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h
index f2d597568151..451f6271dcbc 100644
--- a/drivers/net/wireless/wavelan_cs.p.h
+++ b/drivers/net/wireless/wavelan_cs.p.h
@@ -99,11 +99,7 @@
* caracteristics of the hardware in a standard way and support for
* applications for taking advantage of it (like Mobile IP).
*
- * You will need to enable the CONFIG_NET_RADIO define in the kernel
- * configuration to enable the wireless extensions (this is the one
- * giving access to the radio network device choice).
- *
- * It might also be a good idea as well to fetch the wireless tools to
+ * It might be a good idea as well to fetch the wireless tools to
* configure the device and play a bit.
*/
@@ -440,11 +436,8 @@
#include <linux/ioport.h>
#include <linux/fcntl.h>
#include <linux/ethtool.h>
-
-#ifdef CONFIG_NET_RADIO
#include <linux/wireless.h> /* Wireless extensions */
#include <net/iw_handler.h> /* New driver API */
-#endif
/* Pcmcia headers that we need */
#include <pcmcia/cs_types.h>