linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / drivers / net / wireless / ipw2100.c
index e955db4..6290c9f 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright(c) 2003 - 2006 Intel Corporation. All rights reserved.
+  Copyright(c) 2003 - 2005 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
@@ -134,6 +134,7 @@ that only one external action is invoked at a time.
 */
 
 #include <linux/compiler.h>
+#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/if_arp.h>
 #include <linux/in6.h>
@@ -166,12 +167,12 @@ that only one external action is invoked at a time.
 
 #include "ipw2100.h"
 
-#define IPW2100_VERSION "git-1.2.2"
+#define IPW2100_VERSION "1.1.3"
 
 #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-2006 Intel Corporation"
+#define DRV_COPYRIGHT  "Copyright(c) 2003-2005 Intel Corporation"
 
 /* Debugging stuff */
 #ifdef CONFIG_IPW2100_DEBUG
@@ -1417,7 +1418,7 @@ static int ipw2100_enable_adapter(struct ipw2100_priv *priv)
        if (priv->status & STATUS_ENABLED)
                return 0;
 
-       mutex_lock(&priv->adapter_mutex);
+       down(&priv->adapter_sem);
 
        if (rf_kill_active(priv)) {
                IPW_DEBUG_HC("Command aborted due to RF kill active.\n");
@@ -1443,7 +1444,7 @@ static int ipw2100_enable_adapter(struct ipw2100_priv *priv)
        }
 
       fail_up:
-       mutex_unlock(&priv->adapter_mutex);
+       up(&priv->adapter_sem);
        return err;
 }
 
@@ -1484,7 +1485,7 @@ static int ipw2100_hw_stop_adapter(struct ipw2100_priv *priv)
                 *
                 * Sending the PREPARE_FOR_POWER_DOWN will restrict the
                 * hardware from going into standby mode and will transition
-                * out of D0-standby if it is already in that state.
+                * out of D0-standy if it is already in that state.
                 *
                 * STATUS_PREPARE_POWER_DOWN_COMPLETE will be sent by the
                 * driver upon completion.  Once received, the driver can
@@ -1575,7 +1576,7 @@ static int ipw2100_disable_adapter(struct ipw2100_priv *priv)
                cancel_delayed_work(&priv->hang_check);
        }
 
-       mutex_lock(&priv->adapter_mutex);
+       down(&priv->adapter_sem);
 
        err = ipw2100_hw_send_command(priv, &cmd);
        if (err) {
@@ -1594,7 +1595,7 @@ static int ipw2100_disable_adapter(struct ipw2100_priv *priv)
        IPW_DEBUG_INFO("TODO: implement scan state machine\n");
 
       fail_up:
-       mutex_unlock(&priv->adapter_mutex);
+       up(&priv->adapter_sem);
        return err;
 }
 
@@ -1671,18 +1672,6 @@ 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;
@@ -1738,13 +1727,6 @@ 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
@@ -1887,7 +1869,7 @@ static void ipw2100_reset_adapter(struct ipw2100_priv *priv)
        priv->status |= STATUS_RESET_PENDING;
        spin_unlock_irqrestore(&priv->low_lock, flags);
 
-       mutex_lock(&priv->action_mutex);
+       down(&priv->action_sem);
        /* stop timed checks so that they don't interfere with reset */
        priv->stop_hang_check = 1;
        cancel_delayed_work(&priv->hang_check);
@@ -1897,7 +1879,7 @@ static void ipw2100_reset_adapter(struct ipw2100_priv *priv)
                wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL);
 
        ipw2100_up(priv, 0);
-       mutex_unlock(&priv->action_mutex);
+       up(&priv->action_sem);
 
 }
 
@@ -2389,6 +2371,15 @@ 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))) {
@@ -2436,89 +2427,6 @@ 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];
@@ -2650,7 +2558,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_monitor(priv, i, &stats);
+                               isr_rx(priv, i, &stats);
                                break;
                        }
 #endif
@@ -3842,7 +3750,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;
@@ -3955,7 +3863,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_RADIOTAP;
+               priv->net_dev->type = ARPHRD_IEEE80211;
                break;
 #endif                         /* CONFIG_IPW2100_MONITOR */
        }
@@ -4162,7 +4070,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");
 
@@ -4211,7 +4119,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");
 
-       mutex_lock(&priv->action_mutex);
+       down(&priv->action_sem);
 
        if (disable_radio) {
                priv->status |= STATUS_RF_KILL_SW;
@@ -4229,7 +4137,7 @@ static int ipw_radio_kill_sw(struct ipw2100_priv *priv, int disable_radio)
                        schedule_reset(priv);
        }
 
-       mutex_unlock(&priv->action_mutex);
+       up(&priv->action_sem);
        return 1;
 }
 
@@ -5199,13 +5107,12 @@ 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)
-               tmp = (tx_power - IPW_TX_POWER_MIN_DBM) * 16 /
-                     (IPW_TX_POWER_MAX_DBM - IPW_TX_POWER_MIN_DBM);
+               tx_power = (tx_power - IPW_TX_POWER_MIN_DBM) * 16 /
+                   (IPW_TX_POWER_MAX_DBM - IPW_TX_POWER_MIN_DBM);
 
-       cmd.host_command_parameters[0] = tmp;
+       cmd.host_command_parameters[0] = tx_power;
 
        if (priv->ieee->iw_mode == IW_MODE_ADHOC)
                err = ipw2100_hw_send_command(priv, &cmd);
@@ -5357,7 +5264,7 @@ static int ipw2100_set_key(struct ipw2100_priv *priv,
                     idx, keylen, len);
 
        /* NOTE: We don't check cached values in case the firmware was reset
-        * or some other problem is occurring.  If the user is setting the key,
+        * or some other problem is occuring.  If the user is setting the key,
         * then we push the change */
 
        wep_key->idx = idx;
@@ -5458,12 +5365,9 @@ 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) {
-                       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;
-               }
+               if ((priv->ieee->sec.flags & SEC_AUTH_MODE) &&
+                   (priv->ieee->sec.auth_mode == WLAN_AUTH_SHARED_KEY))
+                       auth_mode = IPW_AUTH_SHARED;
 
                sec_level = SEC_LEVEL_0;
                if (priv->ieee->sec.flags & SEC_LEVEL)
@@ -5533,7 +5437,7 @@ static void shim__set_security(struct net_device *dev,
        struct ipw2100_priv *priv = ieee80211_priv(dev);
        int i, force_update = 0;
 
-       mutex_lock(&priv->action_mutex);
+       down(&priv->action_sem);
        if (!(priv->status & STATUS_INITIALIZED))
                goto done;
 
@@ -5606,7 +5510,7 @@ static void shim__set_security(struct net_device *dev,
        if (!(priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)))
                ipw2100_configure_security(priv, 0);
       done:
-       mutex_unlock(&priv->action_mutex);
+       up(&priv->action_sem);
 }
 
 static int ipw2100_adapter_setup(struct ipw2100_priv *priv)
@@ -5730,7 +5634,7 @@ static int ipw2100_set_address(struct net_device *dev, void *p)
        if (!is_valid_ether_addr(addr->sa_data))
                return -EADDRNOTAVAIL;
 
-       mutex_lock(&priv->action_mutex);
+       down(&priv->action_sem);
 
        priv->config |= CFG_CUSTOM_MAC;
        memcpy(priv->mac_addr, addr->sa_data, ETH_ALEN);
@@ -5740,12 +5644,12 @@ static int ipw2100_set_address(struct net_device *dev, void *p)
                goto done;
 
        priv->reset_backoff = 0;
-       mutex_unlock(&priv->action_mutex);
+       up(&priv->action_sem);
        ipw2100_reset_adapter(priv);
        return 0;
 
       done:
-       mutex_unlock(&priv->action_mutex);
+       up(&priv->action_sem);
        return err;
 }
 
@@ -5856,9 +5760,6 @@ 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;
 
@@ -5870,8 +5771,8 @@ static int ipw2100_wpa_set_auth_algs(struct ipw2100_priv *priv, int value)
        return ret;
 }
 
-static void ipw2100_wpa_assoc_frame(struct ipw2100_priv *priv,
-                                   char *wpa_ie, int wpa_ie_len)
+void ipw2100_wpa_assoc_frame(struct ipw2100_priv *priv,
+                            char *wpa_ie, int wpa_ie_len)
 {
 
        struct ipw2100_wpa_assoc_frame frame;
@@ -6088,8 +5989,8 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev,
        strcpy(priv->nick, "ipw2100");
 
        spin_lock_init(&priv->low_lock);
-       mutex_init(&priv->action_mutex);
-       mutex_init(&priv->adapter_mutex);
+       sema_init(&priv->action_sem, 1);
+       sema_init(&priv->adapter_sem, 1);
 
        init_waitqueue_head(&priv->wait_command_queue);
 
@@ -6229,7 +6130,7 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
        ipw2100_queues_initialize(priv);
 
        err = request_irq(pci_dev->irq,
-                         ipw2100_interrupt, IRQF_SHARED, dev->name, priv);
+                         ipw2100_interrupt, SA_SHIRQ, dev->name, priv);
        if (err) {
                printk(KERN_WARNING DRV_NAME
                       "Error calling request_irq: %d.\n", pci_dev->irq);
@@ -6254,7 +6155,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 */
-       mutex_lock(&priv->action_mutex);
+       down(&priv->action_sem);
        err = register_netdev(dev);
        if (err) {
                printk(KERN_WARNING DRV_NAME
@@ -6290,12 +6191,12 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
 
        priv->status |= STATUS_INITIALIZED;
 
-       mutex_unlock(&priv->action_mutex);
+       up(&priv->action_sem);
 
        return 0;
 
       fail_unlock:
-       mutex_unlock(&priv->action_mutex);
+       up(&priv->action_sem);
 
       fail:
        if (dev) {
@@ -6335,7 +6236,7 @@ static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev)
        struct net_device *dev;
 
        if (priv) {
-               mutex_lock(&priv->action_mutex);
+               down(&priv->action_sem);
 
                priv->status &= ~STATUS_INITIALIZED;
 
@@ -6350,9 +6251,9 @@ static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev)
                /* Take down the hardware */
                ipw2100_down(priv);
 
-               /* Release the mutex so that the network subsystem can
+               /* Release the semaphore so that the network subsystem can
                 * complete any needed calls into the driver... */
-               mutex_unlock(&priv->action_mutex);
+               up(&priv->action_sem);
 
                /* Unregister the device first - this results in close()
                 * being called if the device is open.  If we free storage
@@ -6391,7 +6292,7 @@ static int ipw2100_suspend(struct pci_dev *pci_dev, pm_message_t state)
 
        IPW_DEBUG_INFO("%s: Going into suspend...\n", dev->name);
 
-       mutex_lock(&priv->action_mutex);
+       down(&priv->action_sem);
        if (priv->status & STATUS_INITIALIZED) {
                /* Take down the device; powers it off, etc. */
                ipw2100_down(priv);
@@ -6404,7 +6305,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);
 
-       mutex_unlock(&priv->action_mutex);
+       up(&priv->action_sem);
 
        return 0;
 }
@@ -6418,7 +6319,7 @@ static int ipw2100_resume(struct pci_dev *pci_dev)
        if (IPW2100_PM_DISABLED)
                return 0;
 
-       mutex_lock(&priv->action_mutex);
+       down(&priv->action_sem);
 
        IPW_DEBUG_INFO("%s: Coming out of suspend...\n", dev->name);
 
@@ -6444,7 +6345,7 @@ static int ipw2100_resume(struct pci_dev *pci_dev)
        if (!(priv->status & STATUS_RF_KILL_SW))
                ipw2100_up(priv, 0);
 
-       mutex_unlock(&priv->action_mutex);
+       up(&priv->action_sem);
 
        return 0;
 }
@@ -6608,7 +6509,7 @@ static int ipw2100_wx_set_freq(struct net_device *dev,
        if (priv->ieee->iw_mode == IW_MODE_INFRA)
                return -EOPNOTSUPP;
 
-       mutex_lock(&priv->action_mutex);
+       down(&priv->action_sem);
        if (!(priv->status & STATUS_INITIALIZED)) {
                err = -EIO;
                goto done;
@@ -6639,7 +6540,7 @@ static int ipw2100_wx_set_freq(struct net_device *dev,
        }
 
       done:
-       mutex_unlock(&priv->action_mutex);
+       up(&priv->action_sem);
        return err;
 }
 
@@ -6680,7 +6581,7 @@ static int ipw2100_wx_set_mode(struct net_device *dev,
        if (wrqu->mode == priv->ieee->iw_mode)
                return 0;
 
-       mutex_lock(&priv->action_mutex);
+       down(&priv->action_sem);
        if (!(priv->status & STATUS_INITIALIZED)) {
                err = -EIO;
                goto done;
@@ -6703,7 +6604,7 @@ static int ipw2100_wx_set_mode(struct net_device *dev,
        }
 
       done:
-       mutex_unlock(&priv->action_mutex);
+       up(&priv->action_sem);
        return err;
 }
 
@@ -6885,7 +6786,7 @@ static int ipw2100_wx_set_wap(struct net_device *dev,
        if (wrqu->ap_addr.sa_family != ARPHRD_ETHER)
                return -EINVAL;
 
-       mutex_lock(&priv->action_mutex);
+       down(&priv->action_sem);
        if (!(priv->status & STATUS_INITIALIZED)) {
                err = -EIO;
                goto done;
@@ -6914,7 +6815,7 @@ static int ipw2100_wx_set_wap(struct net_device *dev,
                     wrqu->ap_addr.sa_data[5] & 0xff);
 
       done:
-       mutex_unlock(&priv->action_mutex);
+       up(&priv->action_sem);
        return err;
 }
 
@@ -6950,7 +6851,7 @@ static int ipw2100_wx_set_essid(struct net_device *dev,
        int length = 0;
        int err = 0;
 
-       mutex_lock(&priv->action_mutex);
+       down(&priv->action_sem);
        if (!(priv->status & STATUS_INITIALIZED)) {
                err = -EIO;
                goto done;
@@ -6987,7 +6888,7 @@ static int ipw2100_wx_set_essid(struct net_device *dev,
        err = ipw2100_set_essid(priv, essid, length, 0);
 
       done:
-       mutex_unlock(&priv->action_mutex);
+       up(&priv->action_sem);
        return err;
 }
 
@@ -7068,7 +6969,7 @@ static int ipw2100_wx_set_rate(struct net_device *dev,
        u32 rate;
        int err = 0;
 
-       mutex_lock(&priv->action_mutex);
+       down(&priv->action_sem);
        if (!(priv->status & STATUS_INITIALIZED)) {
                err = -EIO;
                goto done;
@@ -7095,7 +6996,7 @@ static int ipw2100_wx_set_rate(struct net_device *dev,
 
        IPW_DEBUG_WX("SET Rate -> %04X \n", rate);
       done:
-       mutex_unlock(&priv->action_mutex);
+       up(&priv->action_sem);
        return err;
 }
 
@@ -7115,7 +7016,7 @@ static int ipw2100_wx_get_rate(struct net_device *dev,
                return 0;
        }
 
-       mutex_lock(&priv->action_mutex);
+       down(&priv->action_sem);
        if (!(priv->status & STATUS_INITIALIZED)) {
                err = -EIO;
                goto done;
@@ -7147,7 +7048,7 @@ static int ipw2100_wx_get_rate(struct net_device *dev,
        IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value);
 
       done:
-       mutex_unlock(&priv->action_mutex);
+       up(&priv->action_sem);
        return err;
 }
 
@@ -7162,7 +7063,7 @@ static int ipw2100_wx_set_rts(struct net_device *dev,
        if (wrqu->rts.fixed == 0)
                return -EINVAL;
 
-       mutex_lock(&priv->action_mutex);
+       down(&priv->action_sem);
        if (!(priv->status & STATUS_INITIALIZED)) {
                err = -EIO;
                goto done;
@@ -7182,7 +7083,7 @@ static int ipw2100_wx_set_rts(struct net_device *dev,
 
        IPW_DEBUG_WX("SET RTS Threshold -> 0x%08X \n", value);
       done:
-       mutex_unlock(&priv->action_mutex);
+       up(&priv->action_sem);
        return err;
 }
 
@@ -7233,7 +7134,7 @@ static int ipw2100_wx_set_txpow(struct net_device *dev,
                value = wrqu->txpower.value;
        }
 
-       mutex_lock(&priv->action_mutex);
+       down(&priv->action_sem);
        if (!(priv->status & STATUS_INITIALIZED)) {
                err = -EIO;
                goto done;
@@ -7244,7 +7145,7 @@ static int ipw2100_wx_set_txpow(struct net_device *dev,
        IPW_DEBUG_WX("SET TX Power -> %d \n", value);
 
       done:
-       mutex_unlock(&priv->action_mutex);
+       up(&priv->action_sem);
        return err;
 }
 
@@ -7336,7 +7237,7 @@ static int ipw2100_wx_set_retry(struct net_device *dev,
        if (!(wrqu->retry.flags & IW_RETRY_LIMIT))
                return 0;
 
-       mutex_lock(&priv->action_mutex);
+       down(&priv->action_sem);
        if (!(priv->status & STATUS_INITIALIZED)) {
                err = -EIO;
                goto done;
@@ -7363,7 +7264,7 @@ static int ipw2100_wx_set_retry(struct net_device *dev,
        IPW_DEBUG_WX("SET Both Retry Limits -> %d \n", wrqu->retry.value);
 
       done:
-       mutex_unlock(&priv->action_mutex);
+       up(&priv->action_sem);
        return err;
 }
 
@@ -7406,7 +7307,7 @@ static int ipw2100_wx_set_scan(struct net_device *dev,
        struct ipw2100_priv *priv = ieee80211_priv(dev);
        int err = 0;
 
-       mutex_lock(&priv->action_mutex);
+       down(&priv->action_sem);
        if (!(priv->status & STATUS_INITIALIZED)) {
                err = -EIO;
                goto done;
@@ -7421,7 +7322,7 @@ static int ipw2100_wx_set_scan(struct net_device *dev,
        }
 
       done:
-       mutex_unlock(&priv->action_mutex);
+       up(&priv->action_sem);
        return err;
 }
 
@@ -7471,7 +7372,7 @@ static int ipw2100_wx_set_power(struct net_device *dev,
        struct ipw2100_priv *priv = ieee80211_priv(dev);
        int err = 0;
 
-       mutex_lock(&priv->action_mutex);
+       down(&priv->action_sem);
        if (!(priv->status & STATUS_INITIALIZED)) {
                err = -EIO;
                goto done;
@@ -7504,7 +7405,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:
-       mutex_unlock(&priv->action_mutex);
+       up(&priv->action_sem);
        return err;
 
 }
@@ -7808,7 +7709,7 @@ static int ipw2100_wx_set_promisc(struct net_device *dev,
        int enable = (parms[0] > 0);
        int err = 0;
 
-       mutex_lock(&priv->action_mutex);
+       down(&priv->action_sem);
        if (!(priv->status & STATUS_INITIALIZED)) {
                err = -EIO;
                goto done;
@@ -7826,7 +7727,7 @@ static int ipw2100_wx_set_promisc(struct net_device *dev,
                        err = ipw2100_switch_mode(priv, priv->last_mode);
        }
       done:
-       mutex_unlock(&priv->action_mutex);
+       up(&priv->action_sem);
        return err;
 }
 
@@ -7849,7 +7750,7 @@ static int ipw2100_wx_set_powermode(struct net_device *dev,
        struct ipw2100_priv *priv = ieee80211_priv(dev);
        int err = 0, mode = *(int *)extra;
 
-       mutex_lock(&priv->action_mutex);
+       down(&priv->action_sem);
        if (!(priv->status & STATUS_INITIALIZED)) {
                err = -EIO;
                goto done;
@@ -7861,7 +7762,7 @@ static int ipw2100_wx_set_powermode(struct net_device *dev,
        if (priv->power_mode != mode)
                err = ipw2100_set_power_mode(priv, mode);
       done:
-       mutex_unlock(&priv->action_mutex);
+       up(&priv->action_sem);
        return err;
 }
 
@@ -7913,7 +7814,7 @@ static int ipw2100_wx_set_preamble(struct net_device *dev,
        struct ipw2100_priv *priv = ieee80211_priv(dev);
        int err, mode = *(int *)extra;
 
-       mutex_lock(&priv->action_mutex);
+       down(&priv->action_sem);
        if (!(priv->status & STATUS_INITIALIZED)) {
                err = -EIO;
                goto done;
@@ -7931,7 +7832,7 @@ static int ipw2100_wx_set_preamble(struct net_device *dev,
        err = ipw2100_system_config(priv, 0);
 
       done:
-       mutex_unlock(&priv->action_mutex);
+       up(&priv->action_sem);
        return err;
 }
 
@@ -7961,7 +7862,7 @@ static int ipw2100_wx_set_crc_check(struct net_device *dev,
        struct ipw2100_priv *priv = ieee80211_priv(dev);
        int err, mode = *(int *)extra;
 
-       mutex_lock(&priv->action_mutex);
+       down(&priv->action_sem);
        if (!(priv->status & STATUS_INITIALIZED)) {
                err = -EIO;
                goto done;
@@ -7978,7 +7879,7 @@ static int ipw2100_wx_set_crc_check(struct net_device *dev,
        err = 0;
 
       done:
-       mutex_unlock(&priv->action_mutex);
+       up(&priv->action_sem);
        return err;
 }
 
@@ -8283,11 +8184,11 @@ static void ipw2100_wx_event_work(struct ipw2100_priv *priv)
        if (priv->status & STATUS_STOPPING)
                return;
 
-       mutex_lock(&priv->action_mutex);
+       down(&priv->action_sem);
 
        IPW_DEBUG_WX("enter\n");
 
-       mutex_unlock(&priv->action_mutex);
+       up(&priv->action_sem);
 
        wrqu.ap_addr.sa_family = ARPHRD_ETHER;
 
@@ -8310,7 +8211,7 @@ static void ipw2100_wx_event_work(struct ipw2100_priv *priv)
 
        if (!(priv->status & STATUS_ASSOCIATED)) {
                IPW_DEBUG_WX("Configuring ESSID\n");
-               mutex_lock(&priv->action_mutex);
+               down(&priv->action_sem);
                /* This is a disassociation event, so kick the firmware to
                 * look for another AP */
                if (priv->config & CFG_STATIC_ESSID)
@@ -8318,7 +8219,7 @@ static void ipw2100_wx_event_work(struct ipw2100_priv *priv)
                                          0);
                else
                        ipw2100_set_essid(priv, NULL, 0, 0);
-               mutex_unlock(&priv->action_mutex);
+               up(&priv->action_sem);
        }
 
        wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL);