aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Ketrenos <jketreno@linux.intel.com>2005-08-24 22:56:24 -0400
committerJames Ketrenos <jketreno@linux.intel.com>2005-11-07 18:49:56 -0500
commitc848d0af404f00835f038e370005733d90a186fd (patch)
treee9d3e4b02fa9404f7a9633d98e3a35468eb516be
parenta613bffd3aac89bb0a8c9b7afa72af9b0ae30f0a (diff)
Catch ipw2200 up to equivelancy with v1.0.3
* Fix #616 problem with OOPS on module load (thanks to Yi Zhu) * Fixed problem with led module parameter being described as 'auto_create' * Added support to merge between adhoc networks (thanks to Mohamed Abbas) * Added semaphore lock at the driver's entry points to protect against re-entry (thanks to Mohamed Abbas) * Added semaphore lock to background scheduled driver actions (thanks to Mohamed Abbas) * Changed how signal quality is reported for scan output (thanks to Peter Jones) * Fixed how high/low clamp values of signal quality are reported so a more consistent ramp is provided (thanks to Bill Moss) * Fix #624 problem with duplicate addresses (again) (thanks to Bernard Blackham) * Fix #385 problem with fragmentation and certain sized packets (thanks to Mohamed Abbas) * Modified iwconfig network name if RF kill is enabled to say 'radio off' * Fix #382 problem with driver not responding to probe requests in Ad-Hoc mode (thanks to Mohamed Abbas) Signed-off-by: James Ketrenos <jketreno@linux.intel.com>
-rw-r--r--drivers/net/wireless/ipw2200.c841
-rw-r--r--drivers/net/wireless/ipw2200.h5
2 files changed, 668 insertions, 178 deletions
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index ea7a3dcf1daa..0bf1931ac5f3 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -32,7 +32,7 @@
32 32
33#include "ipw2200.h" 33#include "ipw2200.h"
34 34
35#define IPW2200_VERSION "1.0.2" 35#define IPW2200_VERSION "1.0.3"
36#define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver" 36#define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver"
37#define DRV_COPYRIGHT "Copyright(c) 2003-2004 Intel Corporation" 37#define DRV_COPYRIGHT "Copyright(c) 2003-2004 Intel Corporation"
38#define DRV_VERSION IPW2200_VERSION 38#define DRV_VERSION IPW2200_VERSION
@@ -68,9 +68,10 @@ static void ipw_tx_queue_free(struct ipw_priv *);
68static struct ipw_rx_queue *ipw_rx_queue_alloc(struct ipw_priv *); 68static struct ipw_rx_queue *ipw_rx_queue_alloc(struct ipw_priv *);
69static void ipw_rx_queue_free(struct ipw_priv *, struct ipw_rx_queue *); 69static void ipw_rx_queue_free(struct ipw_priv *, struct ipw_rx_queue *);
70static void ipw_rx_queue_replenish(void *); 70static void ipw_rx_queue_replenish(void *);
71
72static int ipw_up(struct ipw_priv *); 71static int ipw_up(struct ipw_priv *);
72static void ipw_bg_up(void *);
73static void ipw_down(struct ipw_priv *); 73static void ipw_down(struct ipw_priv *);
74static void ipw_bg_down(void *);
74static int ipw_config(struct ipw_priv *); 75static int ipw_config(struct ipw_priv *);
75static int init_supported_rates(struct ipw_priv *priv, 76static int init_supported_rates(struct ipw_priv *priv,
76 struct ipw_supported_rates *prates); 77 struct ipw_supported_rates *prates);
@@ -473,6 +474,11 @@ static void ipw_dump_nic_event_log(struct ipw_priv *priv)
473 } 474 }
474} 475}
475 476
477static inline int ipw_is_init(struct ipw_priv *priv)
478{
479 return (priv->status & STATUS_INIT) ? 1 : 0;
480}
481
476static int ipw_get_ordinal(struct ipw_priv *priv, u32 ord, void *val, u32 * len) 482static int ipw_get_ordinal(struct ipw_priv *priv, u32 ord, void *val, u32 * len)
477{ 483{
478 u32 addr, field_info, field_len, field_count, total_len; 484 u32 addr, field_info, field_len, field_count, total_len;
@@ -698,6 +704,14 @@ void ipw_led_link_on(struct ipw_priv *priv)
698 spin_unlock_irqrestore(&priv->lock, flags); 704 spin_unlock_irqrestore(&priv->lock, flags);
699} 705}
700 706
707static void ipw_bg_led_link_on(void *data)
708{
709 struct ipw_priv *priv = data;
710 down(&priv->sem);
711 ipw_led_link_on(data);
712 up(&priv->sem);
713}
714
701void ipw_led_link_off(struct ipw_priv *priv) 715void ipw_led_link_off(struct ipw_priv *priv)
702{ 716{
703 unsigned long flags; 717 unsigned long flags;
@@ -734,6 +748,14 @@ void ipw_led_link_off(struct ipw_priv *priv)
734 spin_unlock_irqrestore(&priv->lock, flags); 748 spin_unlock_irqrestore(&priv->lock, flags);
735} 749}
736 750
751static void ipw_bg_led_link_off(void *data)
752{
753 struct ipw_priv *priv = data;
754 down(&priv->sem);
755 ipw_led_link_off(data);
756 up(&priv->sem);
757}
758
737void ipw_led_activity_on(struct ipw_priv *priv) 759void ipw_led_activity_on(struct ipw_priv *priv)
738{ 760{
739 unsigned long flags; 761 unsigned long flags;
@@ -762,6 +784,7 @@ void ipw_led_activity_on(struct ipw_priv *priv)
762 784
763 priv->status |= STATUS_LED_ACT_ON; 785 priv->status |= STATUS_LED_ACT_ON;
764 786
787 cancel_delayed_work(&priv->led_act_off);
765 queue_delayed_work(priv->workqueue, &priv->led_act_off, 788 queue_delayed_work(priv->workqueue, &priv->led_act_off,
766 LD_TIME_ACT_ON); 789 LD_TIME_ACT_ON);
767 } else { 790 } else {
@@ -801,13 +824,22 @@ void ipw_led_activity_off(struct ipw_priv *priv)
801 spin_unlock_irqrestore(&priv->lock, flags); 824 spin_unlock_irqrestore(&priv->lock, flags);
802} 825}
803 826
827static void ipw_bg_led_activity_off(void *data)
828{
829 struct ipw_priv *priv = data;
830 down(&priv->sem);
831 ipw_led_activity_off(data);
832 up(&priv->sem);
833}
834
804void ipw_led_band_on(struct ipw_priv *priv) 835void ipw_led_band_on(struct ipw_priv *priv)
805{ 836{
806 unsigned long flags; 837 unsigned long flags;
807 u32 led; 838 u32 led;
808 839
809 /* Only nic type 1 supports mode LEDs */ 840 /* Only nic type 1 supports mode LEDs */
810 if (priv->config & CFG_NO_LED || priv->nic_type != EEPROM_NIC_TYPE_1) 841 if (priv->config & CFG_NO_LED ||
842 priv->nic_type != EEPROM_NIC_TYPE_1 || !priv->assoc_network)
811 return; 843 return;
812 844
813 spin_lock_irqsave(&priv->lock, flags); 845 spin_lock_irqsave(&priv->lock, flags);
@@ -993,7 +1025,9 @@ static ssize_t store_scan_age(struct device *d, struct device_attribute *attr,
993 const char *buf, size_t count) 1025 const char *buf, size_t count)
994{ 1026{
995 struct ipw_priv *priv = dev_get_drvdata(d); 1027 struct ipw_priv *priv = dev_get_drvdata(d);
1028#ifdef CONFIG_IPW_DEBUG
996 struct net_device *dev = priv->net_dev; 1029 struct net_device *dev = priv->net_dev;
1030#endif
997 char buffer[] = "00000000"; 1031 char buffer[] = "00000000";
998 unsigned long len = 1032 unsigned long len =
999 (sizeof(buffer) - 1) > count ? count : sizeof(buffer) - 1; 1033 (sizeof(buffer) - 1) > count ? count : sizeof(buffer) - 1;
@@ -1704,6 +1738,14 @@ static void ipw_adapter_restart(void *adapter)
1704 } 1738 }
1705} 1739}
1706 1740
1741static void ipw_bg_adapter_restart(void *data)
1742{
1743 struct ipw_priv *priv = data;
1744 down(&priv->sem);
1745 ipw_adapter_restart(data);
1746 up(&priv->sem);
1747}
1748
1707#define IPW_SCAN_CHECK_WATCHDOG (5 * HZ) 1749#define IPW_SCAN_CHECK_WATCHDOG (5 * HZ)
1708 1750
1709static void ipw_scan_check(void *data) 1751static void ipw_scan_check(void *data)
@@ -1717,6 +1759,14 @@ static void ipw_scan_check(void *data)
1717 } 1759 }
1718} 1760}
1719 1761
1762static void ipw_bg_scan_check(void *data)
1763{
1764 struct ipw_priv *priv = data;
1765 down(&priv->sem);
1766 ipw_scan_check(data);
1767 up(&priv->sem);
1768}
1769
1720static int ipw_send_scan_request_ext(struct ipw_priv *priv, 1770static int ipw_send_scan_request_ext(struct ipw_priv *priv,
1721 struct ipw_scan_request_ext *request) 1771 struct ipw_scan_request_ext *request)
1722{ 1772{
@@ -2982,6 +3032,8 @@ static int ipw_load(struct ipw_priv *priv)
2982 3032
2983 /* Ensure interrupts are disabled */ 3033 /* Ensure interrupts are disabled */
2984 ipw_write32(priv, CX2_INTA_MASK_R, ~CX2_INTA_MASK_ALL); 3034 ipw_write32(priv, CX2_INTA_MASK_R, ~CX2_INTA_MASK_ALL);
3035 /* ack pending interrupts */
3036 ipw_write32(priv, CX2_INTA_RW, CX2_INTA_MASK_ALL);
2985 3037
2986 /* kick start the device */ 3038 /* kick start the device */
2987 ipw_start_nic(priv); 3039 ipw_start_nic(priv);
@@ -3350,9 +3402,21 @@ static void ipw_send_disassociate(struct ipw_priv *priv, int quiet)
3350 3402
3351} 3403}
3352 3404
3353static void ipw_disassociate(void *data) 3405static int ipw_disassociate(void *data)
3354{ 3406{
3407 struct ipw_priv *priv = data;
3408 if (!(priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)))
3409 return 0;
3355 ipw_send_disassociate(data, 0); 3410 ipw_send_disassociate(data, 0);
3411 return 1;
3412}
3413
3414static void ipw_bg_disassociate(void *data)
3415{
3416 struct ipw_priv *priv = data;
3417 down(&priv->sem);
3418 ipw_disassociate(data);
3419 up(&priv->sem);
3356} 3420}
3357 3421
3358struct ipw_status_code { 3422struct ipw_status_code {
@@ -3571,8 +3635,6 @@ static u32 ipw_get_current_rate(struct ipw_priv *priv)
3571 return 0; 3635 return 0;
3572} 3636}
3573 3637
3574#define PERFECT_RSSI (-20)
3575#define WORST_RSSI (-85)
3576#define IPW_STATS_INTERVAL (2 * HZ) 3638#define IPW_STATS_INTERVAL (2 * HZ)
3577static void ipw_gather_stats(struct ipw_priv *priv) 3639static void ipw_gather_stats(struct ipw_priv *priv)
3578{ 3640{
@@ -3663,19 +3725,19 @@ static void ipw_gather_stats(struct ipw_priv *priv)
3663 tx_quality, tx_failures_delta, tx_packets_delta); 3725 tx_quality, tx_failures_delta, tx_packets_delta);
3664 3726
3665 rssi = average_value(&priv->average_rssi); 3727 rssi = average_value(&priv->average_rssi);
3666 if (rssi > PERFECT_RSSI) 3728 signal_quality =
3729 (100 *
3730 (priv->ieee->perfect_rssi - priv->ieee->worst_rssi) *
3731 (priv->ieee->perfect_rssi - priv->ieee->worst_rssi) -
3732 (priv->ieee->perfect_rssi - rssi) *
3733 (15 * (priv->ieee->perfect_rssi - priv->ieee->worst_rssi) +
3734 62 * (priv->ieee->perfect_rssi - rssi))) /
3735 ((priv->ieee->perfect_rssi - priv->ieee->worst_rssi) *
3736 (priv->ieee->perfect_rssi - priv->ieee->worst_rssi));
3737 if (signal_quality > 100)
3667 signal_quality = 100; 3738 signal_quality = 100;
3668 else if (rssi < WORST_RSSI) 3739 else if (signal_quality < 1)
3669 signal_quality = 0; 3740 signal_quality = 0;
3670 else /* qual = 100a^2 - 15ab + 62b^2 / a^2 */
3671 signal_quality =
3672 (100 *
3673 (PERFECT_RSSI - WORST_RSSI) *
3674 (PERFECT_RSSI - WORST_RSSI) -
3675 (PERFECT_RSSI - rssi) *
3676 (15 * (PERFECT_RSSI - WORST_RSSI) +
3677 62 * (PERFECT_RSSI - rssi))) /
3678 ((PERFECT_RSSI - WORST_RSSI) * (PERFECT_RSSI - WORST_RSSI));
3679 3741
3680 IPW_DEBUG_STATS("Signal level : %3d%% (%d dBm)\n", 3742 IPW_DEBUG_STATS("Signal level : %3d%% (%d dBm)\n",
3681 signal_quality, rssi); 3743 signal_quality, rssi);
@@ -3705,6 +3767,14 @@ static void ipw_gather_stats(struct ipw_priv *priv)
3705 IPW_STATS_INTERVAL); 3767 IPW_STATS_INTERVAL);
3706} 3768}
3707 3769
3770static void ipw_bg_gather_stats(void *data)
3771{
3772 struct ipw_priv *priv = data;
3773 down(&priv->sem);
3774 ipw_gather_stats(data);
3775 up(&priv->sem);
3776}
3777
3708static inline void ipw_handle_missed_beacon(struct ipw_priv *priv, 3778static inline void ipw_handle_missed_beacon(struct ipw_priv *priv,
3709 int missed_count) 3779 int missed_count)
3710{ 3780{
@@ -4456,6 +4526,14 @@ static void ipw_rx_queue_replenish(void *data)
4456 ipw_rx_queue_restock(priv); 4526 ipw_rx_queue_restock(priv);
4457} 4527}
4458 4528
4529static void ipw_bg_rx_queue_replenish(void *data)
4530{
4531 struct ipw_priv *priv = data;
4532 down(&priv->sem);
4533 ipw_rx_queue_replenish(data);
4534 up(&priv->sem);
4535}
4536
4459/* Assumes that the skb field of the buffers in 'pool' is kept accurate. 4537/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
4460 * If an SKB has been detached, the POOL needs to have it's SKB set to NULL 4538 * If an SKB has been detached, the POOL needs to have it's SKB set to NULL
4461 * This free routine walks the list of POOL entries and if SKB is set to 4539 * This free routine walks the list of POOL entries and if SKB is set to
@@ -4715,6 +4793,215 @@ struct ipw_network_match {
4715 struct ipw_supported_rates rates; 4793 struct ipw_supported_rates rates;
4716}; 4794};
4717 4795
4796static int ipw_find_adhoc_network(struct ipw_priv *priv,
4797 struct ipw_network_match *match,
4798 struct ieee80211_network *network,
4799 int roaming)
4800{
4801 struct ipw_supported_rates rates;
4802
4803 /* Verify that this network's capability is compatible with the
4804 * current mode (AdHoc or Infrastructure) */
4805 if ((priv->ieee->iw_mode == IW_MODE_ADHOC &&
4806 !(network->capability & WLAN_CAPABILITY_IBSS))) {
4807 IPW_DEBUG_MERGE("Network '%s (" MAC_FMT ")' excluded due to "
4808 "capability mismatch.\n",
4809 escape_essid(network->ssid, network->ssid_len),
4810 MAC_ARG(network->bssid));
4811 return 0;
4812 }
4813
4814 /* If we do not have an ESSID for this AP, we can not associate with
4815 * it */
4816 if (network->flags & NETWORK_EMPTY_ESSID) {
4817 IPW_DEBUG_MERGE("Network '%s (" MAC_FMT ")' excluded "
4818 "because of hidden ESSID.\n",
4819 escape_essid(network->ssid, network->ssid_len),
4820 MAC_ARG(network->bssid));
4821 return 0;
4822 }
4823
4824 if (unlikely(roaming)) {
4825 /* If we are roaming, then ensure check if this is a valid
4826 * network to try and roam to */
4827 if ((network->ssid_len != match->network->ssid_len) ||
4828 memcmp(network->ssid, match->network->ssid,
4829 network->ssid_len)) {
4830 IPW_DEBUG_MERGE("Netowrk '%s (" MAC_FMT ")' excluded "
4831 "because of non-network ESSID.\n",
4832 escape_essid(network->ssid,
4833 network->ssid_len),
4834 MAC_ARG(network->bssid));
4835 return 0;
4836 }
4837 } else {
4838 /* If an ESSID has been configured then compare the broadcast
4839 * ESSID to ours */
4840 if ((priv->config & CFG_STATIC_ESSID) &&
4841 ((network->ssid_len != priv->essid_len) ||
4842 memcmp(network->ssid, priv->essid,
4843 min(network->ssid_len, priv->essid_len)))) {
4844 char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
4845 strncpy(escaped,
4846 escape_essid(network->ssid, network->ssid_len),
4847 sizeof(escaped));
4848 IPW_DEBUG_MERGE("Network '%s (" MAC_FMT ")' excluded "
4849 "because of ESSID mismatch: '%s'.\n",
4850 escaped, MAC_ARG(network->bssid),
4851 escape_essid(priv->essid,
4852 priv->essid_len));
4853 return 0;
4854 }
4855 }
4856
4857 /* If the old network rate is better than this one, don't bother
4858 * testing everything else. */
4859
4860 if (network->time_stamp[0] < match->network->time_stamp[0]) {
4861 IPW_DEBUG_MERGE
4862 ("Network '%s excluded because newer than current network.\n",
4863 escape_essid(match->network->ssid,
4864 match->network->ssid_len));
4865 return 0;
4866 } else if (network->time_stamp[1] < match->network->time_stamp[1]) {
4867 IPW_DEBUG_MERGE
4868 ("Network '%s excluded because newer than current network.\n",
4869 escape_essid(match->network->ssid,
4870 match->network->ssid_len));
4871 return 0;
4872 }
4873
4874 /* Now go through and see if the requested network is valid... */
4875 if (priv->ieee->scan_age != 0 &&
4876 time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) {
4877 IPW_DEBUG_MERGE("Network '%s (" MAC_FMT ")' excluded "
4878 "because of age: %lums.\n",
4879 escape_essid(network->ssid, network->ssid_len),
4880 MAC_ARG(network->bssid),
4881 (jiffies - network->last_scanned) / (HZ / 100));
4882 return 0;
4883 }
4884
4885 if ((priv->config & CFG_STATIC_CHANNEL) &&
4886 (network->channel != priv->channel)) {
4887 IPW_DEBUG_MERGE("Network '%s (" MAC_FMT ")' excluded "
4888 "because of channel mismatch: %d != %d.\n",
4889 escape_essid(network->ssid, network->ssid_len),
4890 MAC_ARG(network->bssid),
4891 network->channel, priv->channel);
4892 return 0;
4893 }
4894
4895 /* Verify privacy compatability */
4896 if (((priv->capability & CAP_PRIVACY_ON) ? 1 : 0) !=
4897 ((network->capability & WLAN_CAPABILITY_PRIVACY) ? 1 : 0)) {
4898 IPW_DEBUG_MERGE("Network '%s (" MAC_FMT ")' excluded "
4899 "because of privacy mismatch: %s != %s.\n",
4900 escape_essid(network->ssid, network->ssid_len),
4901 MAC_ARG(network->bssid),
4902 priv->capability & CAP_PRIVACY_ON ? "on" :
4903 "off",
4904 network->capability &
4905 WLAN_CAPABILITY_PRIVACY ? "on" : "off");
4906 return 0;
4907 }
4908
4909 if (!memcmp(network->bssid, priv->bssid, ETH_ALEN)) {
4910 IPW_DEBUG_MERGE("Network '%s (" MAC_FMT ")' excluded "
4911 "because of the same BSSID match: " MAC_FMT
4912 ".\n", escape_essid(network->ssid,
4913 network->ssid_len),
4914 MAC_ARG(network->bssid), MAC_ARG(priv->bssid));
4915 return 0;
4916 }
4917
4918 /* Filter out any incompatible freq / mode combinations */
4919 if (!ieee80211_is_valid_mode(priv->ieee, network->mode)) {
4920 IPW_DEBUG_MERGE("Network '%s (" MAC_FMT ")' excluded "
4921 "because of invalid frequency/mode "
4922 "combination.\n",
4923 escape_essid(network->ssid, network->ssid_len),
4924 MAC_ARG(network->bssid));
4925 return 0;
4926 }
4927
4928 /* Ensure that the rates supported by the driver are compatible with
4929 * this AP, including verification of basic rates (mandatory) */
4930 if (!ipw_compatible_rates(priv, network, &rates)) {
4931 IPW_DEBUG_MERGE("Network '%s (" MAC_FMT ")' excluded "
4932 "because configured rate mask excludes "
4933 "AP mandatory rate.\n",
4934 escape_essid(network->ssid, network->ssid_len),
4935 MAC_ARG(network->bssid));
4936 return 0;
4937 }
4938
4939 if (rates.num_rates == 0) {
4940 IPW_DEBUG_MERGE("Network '%s (" MAC_FMT ")' excluded "
4941 "because of no compatible rates.\n",
4942 escape_essid(network->ssid, network->ssid_len),
4943 MAC_ARG(network->bssid));
4944 return 0;
4945 }
4946
4947 /* TODO: Perform any further minimal comparititive tests. We do not
4948 * want to put too much policy logic here; intelligent scan selection
4949 * should occur within a generic IEEE 802.11 user space tool. */
4950
4951 /* Set up 'new' AP to this network */
4952 ipw_copy_rates(&match->rates, &rates);
4953 match->network = network;
4954 IPW_DEBUG_MERGE("Network '%s (" MAC_FMT ")' is a viable match.\n",
4955 escape_essid(network->ssid, network->ssid_len),
4956 MAC_ARG(network->bssid));
4957
4958 return 1;
4959}
4960
4961static void ipw_merge_adhoc_network(void *data)
4962{
4963 struct ipw_priv *priv = data;
4964 struct ieee80211_network *network = NULL;
4965 struct ipw_network_match match = {
4966 .network = priv->assoc_network
4967 };
4968
4969 if ((priv->status & STATUS_ASSOCIATED)
4970 && (priv->ieee->iw_mode == IW_MODE_ADHOC)) {
4971 /* First pass through ROAM process -- look for a better
4972 * network */
4973 unsigned long flags;
4974
4975 spin_lock_irqsave(&priv->ieee->lock, flags);
4976 list_for_each_entry(network, &priv->ieee->network_list, list) {
4977 if (network != priv->assoc_network)
4978 ipw_find_adhoc_network(priv, &match, network,
4979 1);
4980 }
4981 spin_unlock_irqrestore(&priv->ieee->lock, flags);
4982
4983 if (match.network == priv->assoc_network) {
4984 IPW_DEBUG_MERGE("No better ADHOC in this network to "
4985 "merge to.\n");
4986 return;
4987 }
4988
4989 down(&priv->sem);
4990 if ((priv->ieee->iw_mode == IW_MODE_ADHOC)) {
4991 IPW_DEBUG_MERGE("remove network %s\n",
4992 escape_essid(priv->essid,
4993 priv->essid_len));
4994 ipw_remove_current_network(priv);
4995 }
4996
4997 ipw_disassociate(priv);
4998 priv->assoc_network = match.network;
4999 up(&priv->sem);
5000 return;
5001 }
5002
5003}
5004
4718static int ipw_best_network(struct ipw_priv *priv, 5005static int ipw_best_network(struct ipw_priv *priv,
4719 struct ipw_network_match *match, 5006 struct ipw_network_match *match,
4720 struct ieee80211_network *network, int roaming) 5007 struct ieee80211_network *network, int roaming)
@@ -4997,6 +5284,14 @@ static void ipw_adhoc_check(void *data)
4997 priv->assoc_request.beacon_interval); 5284 priv->assoc_request.beacon_interval);
4998} 5285}
4999 5286
5287static void ipw_bg_adhoc_check(void *data)
5288{
5289 struct ipw_priv *priv = data;
5290 down(&priv->sem);
5291 ipw_adhoc_check(data);
5292 up(&priv->sem);
5293}
5294
5000#ifdef CONFIG_IPW_DEBUG 5295#ifdef CONFIG_IPW_DEBUG
5001static void ipw_debug_config(struct ipw_priv *priv) 5296static void ipw_debug_config(struct ipw_priv *priv)
5002{ 5297{
@@ -5181,10 +5476,9 @@ static int ipw_request_scan(struct ipw_priv *priv)
5181 /* If we are roaming, then make this a directed scan for the current 5476 /* If we are roaming, then make this a directed scan for the current
5182 * network. Otherwise, ensure that every other scan is a fast 5477 * network. Otherwise, ensure that every other scan is a fast
5183 * channel hop scan */ 5478 * channel hop scan */
5184 if ((priv->status & STATUS_ROAMING) 5479 if ((priv->status & STATUS_ROAMING) || (!(priv->status & STATUS_ASSOCIATED) && (priv->config & CFG_STATIC_ESSID) && (le32_to_cpu(scan.full_scan_index) % 2))) { /* || (
5185 || (!(priv->status & STATUS_ASSOCIATED) 5480 (priv->status & STATUS_ASSOCIATED) &&
5186 && (priv->config & CFG_STATIC_ESSID) 5481 (priv->ieee->iw_mode == IW_MODE_ADHOC))) { */
5187 && (le32_to_cpu(scan.full_scan_index) % 2))) {
5188 err = ipw_send_ssid(priv, priv->essid, priv->essid_len); 5482 err = ipw_send_ssid(priv, priv->essid, priv->essid_len);
5189 if (err) { 5483 if (err) {
5190 IPW_DEBUG_HC 5484 IPW_DEBUG_HC
@@ -5257,6 +5551,22 @@ static int ipw_request_scan(struct ipw_priv *priv)
5257 return 0; 5551 return 0;
5258} 5552}
5259 5553
5554static void ipw_bg_request_scan(void *data)
5555{
5556 struct ipw_priv *priv = data;
5557 down(&priv->sem);
5558 ipw_request_scan(data);
5559 up(&priv->sem);
5560}
5561
5562static void ipw_bg_abort_scan(void *data)
5563{
5564 struct ipw_priv *priv = data;
5565 down(&priv->sem);
5566 ipw_abort_scan(data);
5567 up(&priv->sem);
5568}
5569
5260/* Support for wpa_supplicant. Will be replaced with WEXT once 5570/* Support for wpa_supplicant. Will be replaced with WEXT once
5261 * they get WPA support. */ 5571 * they get WPA support. */
5262 5572
@@ -5473,8 +5783,7 @@ void ipw_wpa_assoc_frame(struct ipw_priv *priv, char *wpa_ie, int wpa_ie_len)
5473 /* make sure WPA is enabled */ 5783 /* make sure WPA is enabled */
5474 ipw_wpa_enable(priv, 1); 5784 ipw_wpa_enable(priv, 1);
5475 5785
5476 if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) 5786 ipw_disassociate(priv);
5477 ipw_disassociate(priv);
5478} 5787}
5479 5788
5480static int ipw_wpa_set_wpa_ie(struct net_device *dev, 5789static int ipw_wpa_set_wpa_ie(struct net_device *dev,
@@ -5830,6 +6139,12 @@ static int ipw_associate_network(struct ipw_priv *priv,
5830 priv->sys_config.dot11g_auto_detection = 1; 6139 priv->sys_config.dot11g_auto_detection = 1;
5831 else 6140 else
5832 priv->sys_config.dot11g_auto_detection = 0; 6141 priv->sys_config.dot11g_auto_detection = 0;
6142
6143 if (priv->ieee->iw_mode == IW_MODE_ADHOC)
6144 priv->sys_config.answer_broadcast_ssid_probe = 1;
6145 else
6146 priv->sys_config.answer_broadcast_ssid_probe = 0;
6147
5833 err = ipw_send_system_config(priv, &priv->sys_config); 6148 err = ipw_send_system_config(priv, &priv->sys_config);
5834 if (err) { 6149 if (err) {
5835 IPW_DEBUG_HC("Attempt to send sys config command failed.\n"); 6150 IPW_DEBUG_HC("Attempt to send sys config command failed.\n");
@@ -5933,7 +6248,15 @@ static void ipw_roam(void *data)
5933 priv->status &= ~STATUS_ROAMING; 6248 priv->status &= ~STATUS_ROAMING;
5934} 6249}
5935 6250
5936static void ipw_associate(void *data) 6251static void ipw_bg_roam(void *data)
6252{
6253 struct ipw_priv *priv = data;
6254 down(&priv->sem);
6255 ipw_roam(data);
6256 up(&priv->sem);
6257}
6258
6259static int ipw_associate(void *data)
5937{ 6260{
5938 struct ipw_priv *priv = data; 6261 struct ipw_priv *priv = data;
5939 6262
@@ -5945,11 +6268,23 @@ static void ipw_associate(void *data)
5945 struct list_head *element; 6268 struct list_head *element;
5946 unsigned long flags; 6269 unsigned long flags;
5947 6270
6271 if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) {
6272 IPW_DEBUG_ASSOC
6273 ("Not attempting association (already in progress)\n");
6274 return 0;
6275 }
6276
6277 if (!ipw_is_init(priv) || (priv->status & STATUS_SCANNING)) {
6278 IPW_DEBUG_ASSOC
6279 ("Not attempting association (scanning or not initialized)\n");
6280 return 0;
6281 }
6282
5948 if (!(priv->config & CFG_ASSOCIATE) && 6283 if (!(priv->config & CFG_ASSOCIATE) &&
5949 !(priv->config & (CFG_STATIC_ESSID | 6284 !(priv->config & (CFG_STATIC_ESSID |
5950 CFG_STATIC_CHANNEL | CFG_STATIC_BSSID))) { 6285 CFG_STATIC_CHANNEL | CFG_STATIC_BSSID))) {
5951 IPW_DEBUG_ASSOC("Not attempting association (associate=0)\n"); 6286 IPW_DEBUG_ASSOC("Not attempting association (associate=0)\n");
5952 return; 6287 return 0;
5953 } 6288 }
5954 6289
5955 /* Protect our use of the network_list */ 6290 /* Protect our use of the network_list */
@@ -5984,10 +6319,20 @@ static void ipw_associate(void *data)
5984 queue_delayed_work(priv->workqueue, &priv->request_scan, 6319 queue_delayed_work(priv->workqueue, &priv->request_scan,
5985 SCAN_INTERVAL); 6320 SCAN_INTERVAL);
5986 6321
5987 return; 6322 return 0;
5988 } 6323 }
5989 6324
5990 ipw_associate_network(priv, network, rates, 0); 6325 ipw_associate_network(priv, network, rates, 0);
6326
6327 return 1;
6328}
6329
6330static void ipw_bg_associate(void *data)
6331{
6332 struct ipw_priv *priv = data;
6333 down(&priv->sem);
6334 ipw_associate(data);
6335 up(&priv->sem);
5991} 6336}
5992 6337
5993static inline void ipw_handle_data_packet(struct ipw_priv *priv, 6338static inline void ipw_handle_data_packet(struct ipw_priv *priv,
@@ -6037,6 +6382,10 @@ static inline int is_network_packet(struct ipw_priv *priv,
6037 * this network, discarding packets coming from ourselves */ 6382 * this network, discarding packets coming from ourselves */
6038 switch (priv->ieee->iw_mode) { 6383 switch (priv->ieee->iw_mode) {
6039 case IW_MODE_ADHOC: /* Header: Dest. | Source | BSSID */ 6384 case IW_MODE_ADHOC: /* Header: Dest. | Source | BSSID */
6385 /* packets from our adapter are dropped (echo) */
6386 if (!memcmp(header->addr2, priv->net_dev->dev_addr, ETH_ALEN))
6387 return 0;
6388
6040 /* {broad,multi}cast packets to our IBSS go through */ 6389 /* {broad,multi}cast packets to our IBSS go through */
6041 if (is_broadcast_ether_addr(header->addr1) || 6390 if (is_broadcast_ether_addr(header->addr1) ||
6042 is_multicast_ether_addr(header->addr1)) 6391 is_multicast_ether_addr(header->addr1))
@@ -6045,9 +6394,12 @@ static inline int is_network_packet(struct ipw_priv *priv,
6045 /* packets to our adapter go through */ 6394 /* packets to our adapter go through */
6046 return !memcmp(header->addr1, priv->net_dev->dev_addr, 6395 return !memcmp(header->addr1, priv->net_dev->dev_addr,
6047 ETH_ALEN); 6396 ETH_ALEN);
6048 break;
6049 6397
6050 case IW_MODE_INFRA: /* Header: Dest. | AP{BSSID} | Source */ 6398 case IW_MODE_INFRA: /* Header: Dest. | AP{BSSID} | Source */
6399 /* packets from our adapter are dropped (echo) */
6400 if (!memcmp(header->addr3, priv->net_dev->dev_addr, ETH_ALEN))
6401 return 0;
6402
6051 /* {broad,multi}cast packets to our IBSS go through */ 6403 /* {broad,multi}cast packets to our IBSS go through */
6052 if (is_broadcast_ether_addr(header->addr1) || 6404 if (is_broadcast_ether_addr(header->addr1) ||
6053 is_multicast_ether_addr(header->addr1)) 6405 is_multicast_ether_addr(header->addr1))
@@ -6056,7 +6408,6 @@ static inline int is_network_packet(struct ipw_priv *priv,
6056 /* packets to our adapter go through */ 6408 /* packets to our adapter go through */
6057 return !memcmp(header->addr1, priv->net_dev->dev_addr, 6409 return !memcmp(header->addr1, priv->net_dev->dev_addr,
6058 ETH_ALEN); 6410 ETH_ALEN);
6059 break;
6060 } 6411 }
6061 6412
6062 return 1; 6413 return 1;
@@ -6101,9 +6452,13 @@ static void ipw_rx(struct ipw_priv *priv)
6101 switch (pkt->header.message_type) { 6452 switch (pkt->header.message_type) {
6102 case RX_FRAME_TYPE: /* 802.11 frame */ { 6453 case RX_FRAME_TYPE: /* 802.11 frame */ {
6103 struct ieee80211_rx_stats stats = { 6454 struct ieee80211_rx_stats stats = {
6104 .rssi = pkt->u.frame.rssi_dbm - 6455 .rssi =
6456 le16_to_cpu(pkt->u.frame.rssi_dbm) -
6105 IPW_RSSI_TO_DBM, 6457 IPW_RSSI_TO_DBM,
6106 /* .signal = le16_to_cpu(pkt->u.frame.signal), */ 6458 .signal =
6459 le16_to_cpu(pkt->u.frame.signal),
6460 .noise =
6461 le16_to_cpu(pkt->u.frame.noise),
6107 .rate = pkt->u.frame.rate, 6462 .rate = pkt->u.frame.rate,
6108 .mac_time = jiffies, 6463 .mac_time = jiffies,
6109 .received_channel = 6464 .received_channel =
@@ -6120,6 +6475,8 @@ static void ipw_rx(struct ipw_priv *priv)
6120 stats.mask |= IEEE80211_STATMASK_RSSI; 6475 stats.mask |= IEEE80211_STATMASK_RSSI;
6121 if (stats.signal != 0) 6476 if (stats.signal != 0)
6122 stats.mask |= IEEE80211_STATMASK_SIGNAL; 6477 stats.mask |= IEEE80211_STATMASK_SIGNAL;
6478 if (stats.noise != 0)
6479 stats.mask |= IEEE80211_STATMASK_NOISE;
6123 if (stats.rate != 0) 6480 if (stats.rate != 0)
6124 stats.mask |= IEEE80211_STATMASK_RATE; 6481 stats.mask |= IEEE80211_STATMASK_RATE;
6125 6482
@@ -6179,11 +6536,34 @@ static void ipw_rx(struct ipw_priv *priv)
6179 || 6536 ||
6180 (WLAN_FC_GET_STYPE 6537 (WLAN_FC_GET_STYPE
6181 (le16_to_cpu(header->frame_ctl)) 6538 (le16_to_cpu(header->frame_ctl))
6182 == IEEE80211_STYPE_BEACON)) 6539 == IEEE80211_STYPE_BEACON))) {
6183 && !memcmp(header->addr3, 6540 if (!memcmp
6184 priv->bssid, ETH_ALEN)) 6541 (header->addr3, priv->bssid,
6185 ipw_add_station(priv, 6542 ETH_ALEN))
6186 header->addr2); 6543 ipw_add_station(priv,
6544 header->
6545 addr2);
6546 else {
6547 struct
6548 ieee80211_probe_response
6549 *beacon;
6550 beacon =
6551 (struct
6552 ieee80211_probe_response
6553 *)header;
6554 if (le16_to_cpu
6555 (beacon->
6556 capability) &
6557 WLAN_CAPABILITY_IBSS)
6558 {
6559 queue_work
6560 (priv->
6561 workqueue,
6562 &priv->
6563 merge_networks);
6564 }
6565 }
6566 }
6187 break; 6567 break;
6188 6568
6189 case IEEE80211_FTYPE_CTL: 6569 case IEEE80211_FTYPE_CTL:
@@ -6262,14 +6642,16 @@ static int ipw_wx_get_name(struct net_device *dev,
6262 union iwreq_data *wrqu, char *extra) 6642 union iwreq_data *wrqu, char *extra)
6263{ 6643{
6264 struct ipw_priv *priv = ieee80211_priv(dev); 6644 struct ipw_priv *priv = ieee80211_priv(dev);
6265 if (priv->status & STATUS_RF_KILL_MASK) { 6645 down(&priv->sem);
6646 if (priv->status & STATUS_RF_KILL_MASK)
6266 strcpy(wrqu->name, "radio off"); 6647 strcpy(wrqu->name, "radio off");
6267 } else if (!(priv->status & STATUS_ASSOCIATED)) 6648 else if (!(priv->status & STATUS_ASSOCIATED))
6268 strcpy(wrqu->name, "unassociated"); 6649 strcpy(wrqu->name, "unassociated");
6269 else 6650 else
6270 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11%c", 6651 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11%c",
6271 ipw_modes[priv->assoc_request.ieee_mode]); 6652 ipw_modes[priv->assoc_request.ieee_mode]);
6272 IPW_DEBUG_WX("Name: %s\n", wrqu->name); 6653 IPW_DEBUG_WX("Name: %s\n", wrqu->name);
6654 up(&priv->sem);
6273 return 0; 6655 return 0;
6274} 6656}
6275 6657
@@ -6278,13 +6660,9 @@ static int ipw_set_channel(struct ipw_priv *priv, u8 channel)
6278 if (channel == 0) { 6660 if (channel == 0) {
6279 IPW_DEBUG_INFO("Setting channel to ANY (0)\n"); 6661 IPW_DEBUG_INFO("Setting channel to ANY (0)\n");
6280 priv->config &= ~CFG_STATIC_CHANNEL; 6662 priv->config &= ~CFG_STATIC_CHANNEL;
6281 if (!(priv->status & (STATUS_SCANNING | STATUS_ASSOCIATED | 6663 IPW_DEBUG_ASSOC("Attempting to associate with new "
6282 STATUS_ASSOCIATING))) { 6664 "parameters.\n");
6283 IPW_DEBUG_ASSOC("Attempting to associate with new " 6665 ipw_associate(priv);
6284 "parameters.\n");
6285 ipw_associate(priv);
6286 }
6287
6288 return 0; 6666 return 0;
6289 } 6667 }
6290 6668
@@ -6299,12 +6677,9 @@ static int ipw_set_channel(struct ipw_priv *priv, u8 channel)
6299 IPW_DEBUG_INFO("Setting channel to %i\n", (int)channel); 6677 IPW_DEBUG_INFO("Setting channel to %i\n", (int)channel);
6300 priv->channel = channel; 6678 priv->channel = channel;
6301 6679
6302 /* If we are currently associated, or trying to associate 6680 /* Network configuration changed -- force [re]association */
6303 * then see if this is a new channel (causing us to disassociate) */ 6681 IPW_DEBUG_ASSOC("[re]association triggered due to channel change.\n");
6304 if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { 6682 if (!ipw_disassociate(priv))
6305 IPW_DEBUG_ASSOC("Disassociating due to channel change.\n");
6306 ipw_disassociate(priv);
6307 } else if (!(priv->status & (STATUS_SCANNING)))
6308 ipw_associate(priv); 6683 ipw_associate(priv);
6309 6684
6310 return 0; 6685 return 0;
@@ -6316,6 +6691,7 @@ static int ipw_wx_set_freq(struct net_device *dev,
6316{ 6691{
6317 struct ipw_priv *priv = ieee80211_priv(dev); 6692 struct ipw_priv *priv = ieee80211_priv(dev);
6318 struct iw_freq *fwrq = &wrqu->freq; 6693 struct iw_freq *fwrq = &wrqu->freq;
6694 int ret = 0;
6319 6695
6320 /* if setting by freq convert to channel */ 6696 /* if setting by freq convert to channel */
6321 if (fwrq->e == 1) { 6697 if (fwrq->e == 1) {
@@ -6337,7 +6713,10 @@ static int ipw_wx_set_freq(struct net_device *dev,
6337 return -EOPNOTSUPP; 6713 return -EOPNOTSUPP;
6338 6714
6339 IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m); 6715 IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m);
6340 return ipw_set_channel(priv, (u8) fwrq->m); 6716 down(&priv->sem);
6717 ret = ipw_set_channel(priv, (u8) fwrq->m);
6718 up(&priv->sem);
6719 return ret;
6341} 6720}
6342 6721
6343static int ipw_wx_get_freq(struct net_device *dev, 6722static int ipw_wx_get_freq(struct net_device *dev,
@@ -6350,12 +6729,14 @@ static int ipw_wx_get_freq(struct net_device *dev,
6350 6729
6351 /* If we are associated, trying to associate, or have a statically 6730 /* If we are associated, trying to associate, or have a statically
6352 * configured CHANNEL then return that; otherwise return ANY */ 6731 * configured CHANNEL then return that; otherwise return ANY */
6732 down(&priv->sem);
6353 if (priv->config & CFG_STATIC_CHANNEL || 6733 if (priv->config & CFG_STATIC_CHANNEL ||
6354 priv->status & (STATUS_ASSOCIATING | STATUS_ASSOCIATED)) 6734 priv->status & (STATUS_ASSOCIATING | STATUS_ASSOCIATED))
6355 wrqu->freq.m = priv->channel; 6735 wrqu->freq.m = priv->channel;
6356 else 6736 else
6357 wrqu->freq.m = 0; 6737 wrqu->freq.m = 0;
6358 6738
6739 up(&priv->sem);
6359 IPW_DEBUG_WX("GET Freq/Channel -> %d \n", priv->channel); 6740 IPW_DEBUG_WX("GET Freq/Channel -> %d \n", priv->channel);
6360 return 0; 6741 return 0;
6361} 6742}
@@ -6368,9 +6749,11 @@ static int ipw_wx_set_mode(struct net_device *dev,
6368 int err = 0; 6749 int err = 0;
6369 6750
6370 IPW_DEBUG_WX("Set MODE: %d\n", wrqu->mode); 6751 IPW_DEBUG_WX("Set MODE: %d\n", wrqu->mode);
6371 6752 down(&priv->sem);
6372 if (wrqu->mode == priv->ieee->iw_mode) 6753 if (wrqu->mode == priv->ieee->iw_mode) {
6754 up(&priv->sem);
6373 return 0; 6755 return 0;
6756 }
6374 6757
6375 switch (wrqu->mode) { 6758 switch (wrqu->mode) {
6376#ifdef CONFIG_IPW_MONITOR 6759#ifdef CONFIG_IPW_MONITOR
@@ -6383,6 +6766,7 @@ static int ipw_wx_set_mode(struct net_device *dev,
6383 wrqu->mode = IW_MODE_INFRA; 6766 wrqu->mode = IW_MODE_INFRA;
6384 break; 6767 break;
6385 default: 6768 default:
6769 up(&priv->sem);
6386 return -EINVAL; 6770 return -EINVAL;
6387 } 6771 }
6388 6772
@@ -6407,8 +6791,9 @@ static int ipw_wx_set_mode(struct net_device *dev,
6407#endif 6791#endif
6408 6792
6409 priv->ieee->iw_mode = wrqu->mode; 6793 priv->ieee->iw_mode = wrqu->mode;
6410 queue_work(priv->workqueue, &priv->adapter_restart);
6411 6794
6795 queue_work(priv->workqueue, &priv->adapter_restart);
6796 up(&priv->sem);
6412 return err; 6797 return err;
6413} 6798}
6414 6799
@@ -6417,10 +6802,10 @@ static int ipw_wx_get_mode(struct net_device *dev,
6417 union iwreq_data *wrqu, char *extra) 6802 union iwreq_data *wrqu, char *extra)
6418{ 6803{
6419 struct ipw_priv *priv = ieee80211_priv(dev); 6804 struct ipw_priv *priv = ieee80211_priv(dev);
6420 6805 down(&priv->sem);
6421 wrqu->mode = priv->ieee->iw_mode; 6806 wrqu->mode = priv->ieee->iw_mode;
6422 IPW_DEBUG_WX("Get MODE -> %d\n", wrqu->mode); 6807 IPW_DEBUG_WX("Get MODE -> %d\n", wrqu->mode);
6423 6808 up(&priv->sem);
6424 return 0; 6809 return 0;
6425} 6810}
6426 6811
@@ -6466,7 +6851,7 @@ static int ipw_wx_get_range(struct net_device *dev,
6466 range->max_qual.qual = 100; 6851 range->max_qual.qual = 100;
6467 /* TODO: Find real max RSSI and stick here */ 6852 /* TODO: Find real max RSSI and stick here */
6468 range->max_qual.level = 0; 6853 range->max_qual.level = 0;
6469 range->max_qual.noise = 0; 6854 range->max_qual.noise = priv->ieee->worst_rssi + 0x100;
6470 range->max_qual.updated = 7; /* Updated all three */ 6855 range->max_qual.updated = 7; /* Updated all three */
6471 6856
6472 range->avg_qual.qual = 70; 6857 range->avg_qual.qual = 70;
@@ -6474,7 +6859,7 @@ static int ipw_wx_get_range(struct net_device *dev,
6474 range->avg_qual.level = 0; /* FIXME to real average level */ 6859 range->avg_qual.level = 0; /* FIXME to real average level */
6475 range->avg_qual.noise = 0; 6860 range->avg_qual.noise = 0;
6476 range->avg_qual.updated = 7; /* Updated all three */ 6861 range->avg_qual.updated = 7; /* Updated all three */
6477 6862 down(&priv->sem);
6478 range->num_bitrates = min(priv->rates.num_rates, (u8) IW_MAX_BITRATES); 6863 range->num_bitrates = min(priv->rates.num_rates, (u8) IW_MAX_BITRATES);
6479 6864
6480 for (i = 0; i < range->num_bitrates; i++) 6865 for (i = 0; i < range->num_bitrates; i++)
@@ -6507,7 +6892,7 @@ static int ipw_wx_get_range(struct net_device *dev,
6507 break; 6892 break;
6508 } 6893 }
6509 range->num_frequency = val; 6894 range->num_frequency = val;
6510 6895 up(&priv->sem);
6511 IPW_DEBUG_WX("GET Range\n"); 6896 IPW_DEBUG_WX("GET Range\n");
6512 return 0; 6897 return 0;
6513} 6898}
@@ -6527,25 +6912,23 @@ static int ipw_wx_set_wap(struct net_device *dev,
6527 6912
6528 if (wrqu->ap_addr.sa_family != ARPHRD_ETHER) 6913 if (wrqu->ap_addr.sa_family != ARPHRD_ETHER)
6529 return -EINVAL; 6914 return -EINVAL;
6530 6915 down(&priv->sem);
6531 if (!memcmp(any, wrqu->ap_addr.sa_data, ETH_ALEN) || 6916 if (!memcmp(any, wrqu->ap_addr.sa_data, ETH_ALEN) ||
6532 !memcmp(off, wrqu->ap_addr.sa_data, ETH_ALEN)) { 6917 !memcmp(off, wrqu->ap_addr.sa_data, ETH_ALEN)) {
6533 /* we disable mandatory BSSID association */ 6918 /* we disable mandatory BSSID association */
6534 IPW_DEBUG_WX("Setting AP BSSID to ANY\n"); 6919 IPW_DEBUG_WX("Setting AP BSSID to ANY\n");
6535 priv->config &= ~CFG_STATIC_BSSID; 6920 priv->config &= ~CFG_STATIC_BSSID;
6536 if (!(priv->status & (STATUS_SCANNING | STATUS_ASSOCIATED | 6921 IPW_DEBUG_ASSOC("Attempting to associate with new "
6537 STATUS_ASSOCIATING))) { 6922 "parameters.\n");
6538 IPW_DEBUG_ASSOC("Attempting to associate with new " 6923 ipw_associate(priv);
6539 "parameters.\n"); 6924 up(&priv->sem);
6540 ipw_associate(priv);
6541 }
6542
6543 return 0; 6925 return 0;
6544 } 6926 }
6545 6927
6546 priv->config |= CFG_STATIC_BSSID; 6928 priv->config |= CFG_STATIC_BSSID;
6547 if (!memcmp(priv->bssid, wrqu->ap_addr.sa_data, ETH_ALEN)) { 6929 if (!memcmp(priv->bssid, wrqu->ap_addr.sa_data, ETH_ALEN)) {
6548 IPW_DEBUG_WX("BSSID set to current BSSID.\n"); 6930 IPW_DEBUG_WX("BSSID set to current BSSID.\n");
6931 up(&priv->sem);
6549 return 0; 6932 return 0;
6550 } 6933 }
6551 6934
@@ -6554,14 +6937,12 @@ static int ipw_wx_set_wap(struct net_device *dev,
6554 6937
6555 memcpy(priv->bssid, wrqu->ap_addr.sa_data, ETH_ALEN); 6938 memcpy(priv->bssid, wrqu->ap_addr.sa_data, ETH_ALEN);
6556 6939
6557 /* If we are currently associated, or trying to associate 6940 /* Network configuration changed -- force [re]association */
6558 * then see if this is a new BSSID (causing us to disassociate) */ 6941 IPW_DEBUG_ASSOC("[re]association triggered due to BSSID change.\n");
6559 if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { 6942 if (!ipw_disassociate(priv))
6560 IPW_DEBUG_ASSOC("Disassociating due to BSSID change.\n");
6561 ipw_disassociate(priv);
6562 } else if (!(priv->status & (STATUS_SCANNING)))
6563 ipw_associate(priv); 6943 ipw_associate(priv);
6564 6944
6945 up(&priv->sem);
6565 return 0; 6946 return 0;
6566} 6947}
6567 6948
@@ -6572,6 +6953,7 @@ static int ipw_wx_get_wap(struct net_device *dev,
6572 struct ipw_priv *priv = ieee80211_priv(dev); 6953 struct ipw_priv *priv = ieee80211_priv(dev);
6573 /* If we are associated, trying to associate, or have a statically 6954 /* If we are associated, trying to associate, or have a statically
6574 * configured BSSID then return that; otherwise return ANY */ 6955 * configured BSSID then return that; otherwise return ANY */
6956 down(&priv->sem);
6575 if (priv->config & CFG_STATIC_BSSID || 6957 if (priv->config & CFG_STATIC_BSSID ||
6576 priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { 6958 priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) {
6577 wrqu->ap_addr.sa_family = ARPHRD_ETHER; 6959 wrqu->ap_addr.sa_family = ARPHRD_ETHER;
@@ -6581,6 +6963,7 @@ static int ipw_wx_get_wap(struct net_device *dev,
6581 6963
6582 IPW_DEBUG_WX("Getting WAP BSSID: " MAC_FMT "\n", 6964 IPW_DEBUG_WX("Getting WAP BSSID: " MAC_FMT "\n",
6583 MAC_ARG(wrqu->ap_addr.sa_data)); 6965 MAC_ARG(wrqu->ap_addr.sa_data));
6966 up(&priv->sem);
6584 return 0; 6967 return 0;
6585} 6968}
6586 6969
@@ -6591,7 +6974,7 @@ static int ipw_wx_set_essid(struct net_device *dev,
6591 struct ipw_priv *priv = ieee80211_priv(dev); 6974 struct ipw_priv *priv = ieee80211_priv(dev);
6592 char *essid = ""; /* ANY */ 6975 char *essid = ""; /* ANY */
6593 int length = 0; 6976 int length = 0;
6594 6977 down(&priv->sem);
6595 if (wrqu->essid.flags && wrqu->essid.length) { 6978 if (wrqu->essid.flags && wrqu->essid.length) {
6596 length = wrqu->essid.length - 1; 6979 length = wrqu->essid.length - 1;
6597 essid = extra; 6980 essid = extra;
@@ -6599,13 +6982,12 @@ static int ipw_wx_set_essid(struct net_device *dev,
6599 if (length == 0) { 6982 if (length == 0) {
6600 IPW_DEBUG_WX("Setting ESSID to ANY\n"); 6983 IPW_DEBUG_WX("Setting ESSID to ANY\n");
6601 priv->config &= ~CFG_STATIC_ESSID; 6984 priv->config &= ~CFG_STATIC_ESSID;
6602 if (!(priv->status & (STATUS_SCANNING | STATUS_ASSOCIATED | 6985 if (!(priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING))) {
6603 STATUS_ASSOCIATING))) {
6604 IPW_DEBUG_ASSOC("Attempting to associate with new " 6986 IPW_DEBUG_ASSOC("Attempting to associate with new "
6605 "parameters.\n"); 6987 "parameters.\n");
6606 ipw_associate(priv); 6988 ipw_associate(priv);
6607 } 6989 }
6608 6990 up(&priv->sem);
6609 return 0; 6991 return 0;
6610 } 6992 }
6611 6993
@@ -6615,6 +6997,7 @@ static int ipw_wx_set_essid(struct net_device *dev,
6615 6997
6616 if (priv->essid_len == length && !memcmp(priv->essid, extra, length)) { 6998 if (priv->essid_len == length && !memcmp(priv->essid, extra, length)) {
6617 IPW_DEBUG_WX("ESSID set to current ESSID.\n"); 6999 IPW_DEBUG_WX("ESSID set to current ESSID.\n");
7000 up(&priv->sem);
6618 return 0; 7001 return 0;
6619 } 7002 }
6620 7003
@@ -6624,14 +7007,12 @@ static int ipw_wx_set_essid(struct net_device *dev,
6624 priv->essid_len = length; 7007 priv->essid_len = length;
6625 memcpy(priv->essid, essid, priv->essid_len); 7008 memcpy(priv->essid, essid, priv->essid_len);
6626 7009
6627 /* If we are currently associated, or trying to associate 7010 /* Network configuration changed -- force [re]association */
6628 * then see if this is a new ESSID (causing us to disassociate) */ 7011 IPW_DEBUG_ASSOC("[re]association triggered due to ESSID change.\n");
6629 if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { 7012 if (!ipw_disassociate(priv))
6630 IPW_DEBUG_ASSOC("Disassociating due to ESSID change.\n");
6631 ipw_disassociate(priv);
6632 } else if (!(priv->status & (STATUS_SCANNING)))
6633 ipw_associate(priv); 7013 ipw_associate(priv);
6634 7014
7015 up(&priv->sem);
6635 return 0; 7016 return 0;
6636} 7017}
6637 7018
@@ -6643,6 +7024,7 @@ static int ipw_wx_get_essid(struct net_device *dev,
6643 7024
6644 /* If we are associated, trying to associate, or have a statically 7025 /* If we are associated, trying to associate, or have a statically
6645 * configured ESSID then return that; otherwise return ANY */ 7026 * configured ESSID then return that; otherwise return ANY */
7027 down(&priv->sem);
6646 if (priv->config & CFG_STATIC_ESSID || 7028 if (priv->config & CFG_STATIC_ESSID ||
6647 priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { 7029 priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) {
6648 IPW_DEBUG_WX("Getting essid: '%s'\n", 7030 IPW_DEBUG_WX("Getting essid: '%s'\n",
@@ -6655,7 +7037,7 @@ static int ipw_wx_get_essid(struct net_device *dev,
6655 wrqu->essid.length = 0; 7037 wrqu->essid.length = 0;
6656 wrqu->essid.flags = 0; /* active */ 7038 wrqu->essid.flags = 0; /* active */
6657 } 7039 }
6658 7040 up(&priv->sem);
6659 return 0; 7041 return 0;
6660} 7042}
6661 7043
@@ -6668,11 +7050,12 @@ static int ipw_wx_set_nick(struct net_device *dev,
6668 IPW_DEBUG_WX("Setting nick to '%s'\n", extra); 7050 IPW_DEBUG_WX("Setting nick to '%s'\n", extra);
6669 if (wrqu->data.length > IW_ESSID_MAX_SIZE) 7051 if (wrqu->data.length > IW_ESSID_MAX_SIZE)
6670 return -E2BIG; 7052 return -E2BIG;
6671 7053 down(&priv->sem);
6672 wrqu->data.length = min((size_t) wrqu->data.length, sizeof(priv->nick)); 7054 wrqu->data.length = min((size_t) wrqu->data.length, sizeof(priv->nick));
6673 memset(priv->nick, 0, sizeof(priv->nick)); 7055 memset(priv->nick, 0, sizeof(priv->nick));
6674 memcpy(priv->nick, extra, wrqu->data.length); 7056 memcpy(priv->nick, extra, wrqu->data.length);
6675 IPW_DEBUG_TRACE("<<\n"); 7057 IPW_DEBUG_TRACE("<<\n");
7058 up(&priv->sem);
6676 return 0; 7059 return 0;
6677 7060
6678} 7061}
@@ -6683,9 +7066,11 @@ static int ipw_wx_get_nick(struct net_device *dev,
6683{ 7066{
6684 struct ipw_priv *priv = ieee80211_priv(dev); 7067 struct ipw_priv *priv = ieee80211_priv(dev);
6685 IPW_DEBUG_WX("Getting nick\n"); 7068 IPW_DEBUG_WX("Getting nick\n");
7069 down(&priv->sem);
6686 wrqu->data.length = strlen(priv->nick) + 1; 7070 wrqu->data.length = strlen(priv->nick) + 1;
6687 memcpy(extra, priv->nick, wrqu->data.length); 7071 memcpy(extra, priv->nick, wrqu->data.length);
6688 wrqu->data.flags = 1; /* active */ 7072 wrqu->data.flags = 1; /* active */
7073 up(&priv->sem);
6689 return 0; 7074 return 0;
6690} 7075}
6691 7076
@@ -6778,25 +7163,26 @@ static int ipw_wx_set_rate(struct net_device *dev,
6778 apply: 7163 apply:
6779 IPW_DEBUG_WX("Setting rate mask to 0x%08X [%s]\n", 7164 IPW_DEBUG_WX("Setting rate mask to 0x%08X [%s]\n",
6780 mask, fixed ? "fixed" : "sub-rates"); 7165 mask, fixed ? "fixed" : "sub-rates");
6781 7166 down(&priv->sem);
6782 if (mask == IEEE80211_DEFAULT_RATES_MASK) 7167 if (mask == IEEE80211_DEFAULT_RATES_MASK)
6783 priv->config &= ~CFG_FIXED_RATE; 7168 priv->config &= ~CFG_FIXED_RATE;
6784 else 7169 else
6785 priv->config |= CFG_FIXED_RATE; 7170 priv->config |= CFG_FIXED_RATE;
6786 7171
6787 if (priv->rates_mask != mask) { 7172 if (priv->rates_mask == mask) {
6788 priv->rates_mask = mask; 7173 IPW_DEBUG_WX("Mask set to current mask.\n");
6789 /* If we are already associated or are currently trying to 7174 up(&priv->sem);
6790 * associate, disassociate and try again */ 7175 return 0;
6791 if ((priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING))) {
6792 IPW_DEBUG_ASSOC("Disassociating due to RATE change.\n");
6793 ipw_disassociate(priv);
6794 } else if (!(priv->status & (STATUS_SCANNING))) {
6795 /* We are not yet associated, so kick one off... */
6796 ipw_associate(priv);
6797 }
6798 } 7176 }
6799 7177
7178 priv->rates_mask = mask;
7179
7180 /* Network configuration changed -- force [re]association */
7181 IPW_DEBUG_ASSOC("[re]association triggered due to rates change.\n");
7182 if (!ipw_disassociate(priv))
7183 ipw_associate(priv);
7184
7185 up(&priv->sem);
6800 return 0; 7186 return 0;
6801} 7187}
6802 7188
@@ -6805,8 +7191,9 @@ static int ipw_wx_get_rate(struct net_device *dev,
6805 union iwreq_data *wrqu, char *extra) 7191 union iwreq_data *wrqu, char *extra)
6806{ 7192{
6807 struct ipw_priv *priv = ieee80211_priv(dev); 7193 struct ipw_priv *priv = ieee80211_priv(dev);
7194 down(&priv->sem);
6808 wrqu->bitrate.value = priv->last_rate; 7195 wrqu->bitrate.value = priv->last_rate;
6809 7196 up(&priv->sem);
6810 IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value); 7197 IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value);
6811 return 0; 7198 return 0;
6812} 7199}
@@ -6816,18 +7203,20 @@ static int ipw_wx_set_rts(struct net_device *dev,
6816 union iwreq_data *wrqu, char *extra) 7203 union iwreq_data *wrqu, char *extra)
6817{ 7204{
6818 struct ipw_priv *priv = ieee80211_priv(dev); 7205 struct ipw_priv *priv = ieee80211_priv(dev);
6819 7206 down(&priv->sem);
6820 if (wrqu->rts.disabled) 7207 if (wrqu->rts.disabled)
6821 priv->rts_threshold = DEFAULT_RTS_THRESHOLD; 7208 priv->rts_threshold = DEFAULT_RTS_THRESHOLD;
6822 else { 7209 else {
6823 if (wrqu->rts.value < MIN_RTS_THRESHOLD || 7210 if (wrqu->rts.value < MIN_RTS_THRESHOLD ||
6824 wrqu->rts.value > MAX_RTS_THRESHOLD) 7211 wrqu->rts.value > MAX_RTS_THRESHOLD) {
7212 up(&priv->sem);
6825 return -EINVAL; 7213 return -EINVAL;
6826 7214 }
6827 priv->rts_threshold = wrqu->rts.value; 7215 priv->rts_threshold = wrqu->rts.value;
6828 } 7216 }
6829 7217
6830 ipw_send_rts_threshold(priv, priv->rts_threshold); 7218 ipw_send_rts_threshold(priv, priv->rts_threshold);
7219 up(&priv->sem);
6831 IPW_DEBUG_WX("SET RTS Threshold -> %d \n", priv->rts_threshold); 7220 IPW_DEBUG_WX("SET RTS Threshold -> %d \n", priv->rts_threshold);
6832 return 0; 7221 return 0;
6833} 7222}
@@ -6837,10 +7226,11 @@ static int ipw_wx_get_rts(struct net_device *dev,
6837 union iwreq_data *wrqu, char *extra) 7226 union iwreq_data *wrqu, char *extra)
6838{ 7227{
6839 struct ipw_priv *priv = ieee80211_priv(dev); 7228 struct ipw_priv *priv = ieee80211_priv(dev);
7229 down(&priv->sem);
6840 wrqu->rts.value = priv->rts_threshold; 7230 wrqu->rts.value = priv->rts_threshold;
6841 wrqu->rts.fixed = 0; /* no auto select */ 7231 wrqu->rts.fixed = 0; /* no auto select */
6842 wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); 7232 wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD);
6843 7233 up(&priv->sem);
6844 IPW_DEBUG_WX("GET RTS Threshold -> %d \n", wrqu->rts.value); 7234 IPW_DEBUG_WX("GET RTS Threshold -> %d \n", wrqu->rts.value);
6845 return 0; 7235 return 0;
6846} 7236}
@@ -6852,15 +7242,21 @@ static int ipw_wx_set_txpow(struct net_device *dev,
6852 struct ipw_priv *priv = ieee80211_priv(dev); 7242 struct ipw_priv *priv = ieee80211_priv(dev);
6853 struct ipw_tx_power tx_power; 7243 struct ipw_tx_power tx_power;
6854 int i; 7244 int i;
6855 7245 down(&priv->sem);
6856 if (ipw_radio_kill_sw(priv, wrqu->power.disabled)) 7246 if (ipw_radio_kill_sw(priv, wrqu->power.disabled)) {
7247 up(&priv->sem);
6857 return -EINPROGRESS; 7248 return -EINPROGRESS;
7249 }
6858 7250
6859 if (wrqu->power.flags != IW_TXPOW_DBM) 7251 if (wrqu->power.flags != IW_TXPOW_DBM) {
7252 up(&priv->sem);
6860 return -EINVAL; 7253 return -EINVAL;
7254 }
6861 7255
6862 if ((wrqu->power.value > 20) || (wrqu->power.value < -12)) 7256 if ((wrqu->power.value > 20) || (wrqu->power.value < -12)) {
7257 up(&priv->sem);
6863 return -EINVAL; 7258 return -EINVAL;
7259 }
6864 7260
6865 priv->tx_power = wrqu->power.value; 7261 priv->tx_power = wrqu->power.value;
6866 7262
@@ -6881,9 +7277,11 @@ static int ipw_wx_set_txpow(struct net_device *dev,
6881 if (ipw_send_tx_power(priv, &tx_power)) 7277 if (ipw_send_tx_power(priv, &tx_power))
6882 goto error; 7278 goto error;
6883 7279
7280 up(&priv->sem);
6884 return 0; 7281 return 0;
6885 7282
6886 error: 7283 error:
7284 up(&priv->sem);
6887 return -EIO; 7285 return -EIO;
6888} 7286}
6889 7287
@@ -6892,11 +7290,12 @@ static int ipw_wx_get_txpow(struct net_device *dev,
6892 union iwreq_data *wrqu, char *extra) 7290 union iwreq_data *wrqu, char *extra)
6893{ 7291{
6894 struct ipw_priv *priv = ieee80211_priv(dev); 7292 struct ipw_priv *priv = ieee80211_priv(dev);
6895 7293 down(&priv->sem);
6896 wrqu->power.value = priv->tx_power; 7294 wrqu->power.value = priv->tx_power;
6897 wrqu->power.fixed = 1; 7295 wrqu->power.fixed = 1;
6898 wrqu->power.flags = IW_TXPOW_DBM; 7296 wrqu->power.flags = IW_TXPOW_DBM;
6899 wrqu->power.disabled = (priv->status & STATUS_RF_KILL_MASK) ? 1 : 0; 7297 wrqu->power.disabled = (priv->status & STATUS_RF_KILL_MASK) ? 1 : 0;
7298 up(&priv->sem);
6900 7299
6901 IPW_DEBUG_WX("GET TX Power -> %s %d \n", 7300 IPW_DEBUG_WX("GET TX Power -> %s %d \n",
6902 wrqu->power.disabled ? "ON" : "OFF", wrqu->power.value); 7301 wrqu->power.disabled ? "ON" : "OFF", wrqu->power.value);
@@ -6909,7 +7308,7 @@ static int ipw_wx_set_frag(struct net_device *dev,
6909 union iwreq_data *wrqu, char *extra) 7308 union iwreq_data *wrqu, char *extra)
6910{ 7309{
6911 struct ipw_priv *priv = ieee80211_priv(dev); 7310 struct ipw_priv *priv = ieee80211_priv(dev);
6912 7311 down(&priv->sem);
6913 if (wrqu->frag.disabled) 7312 if (wrqu->frag.disabled)
6914 priv->ieee->fts = DEFAULT_FTS; 7313 priv->ieee->fts = DEFAULT_FTS;
6915 else { 7314 else {
@@ -6921,6 +7320,7 @@ static int ipw_wx_set_frag(struct net_device *dev,
6921 } 7320 }
6922 7321
6923 ipw_send_frag_threshold(priv, wrqu->frag.value); 7322 ipw_send_frag_threshold(priv, wrqu->frag.value);
7323 up(&priv->sem);
6924 IPW_DEBUG_WX("SET Frag Threshold -> %d \n", wrqu->frag.value); 7324 IPW_DEBUG_WX("SET Frag Threshold -> %d \n", wrqu->frag.value);
6925 return 0; 7325 return 0;
6926} 7326}
@@ -6930,10 +7330,11 @@ static int ipw_wx_get_frag(struct net_device *dev,
6930 union iwreq_data *wrqu, char *extra) 7330 union iwreq_data *wrqu, char *extra)
6931{ 7331{
6932 struct ipw_priv *priv = ieee80211_priv(dev); 7332 struct ipw_priv *priv = ieee80211_priv(dev);
7333 down(&priv->sem);
6933 wrqu->frag.value = priv->ieee->fts; 7334 wrqu->frag.value = priv->ieee->fts;
6934 wrqu->frag.fixed = 0; /* no auto select */ 7335 wrqu->frag.fixed = 0; /* no auto select */
6935 wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FTS); 7336 wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FTS);
6936 7337 up(&priv->sem);
6937 IPW_DEBUG_WX("GET Frag Threshold -> %d \n", wrqu->frag.value); 7338 IPW_DEBUG_WX("GET Frag Threshold -> %d \n", wrqu->frag.value);
6938 7339
6939 return 0; 7340 return 0;
@@ -6961,8 +7362,12 @@ static int ipw_wx_set_scan(struct net_device *dev,
6961{ 7362{
6962 struct ipw_priv *priv = ieee80211_priv(dev); 7363 struct ipw_priv *priv = ieee80211_priv(dev);
6963 IPW_DEBUG_WX("Start scan\n"); 7364 IPW_DEBUG_WX("Start scan\n");
6964 if (ipw_request_scan(priv)) 7365 down(&priv->sem);
7366 if (ipw_request_scan(priv)) {
7367 up(&priv->sem);
6965 return -EIO; 7368 return -EIO;
7369 }
7370 up(&priv->sem);
6966 return 0; 7371 return 0;
6967} 7372}
6968 7373
@@ -6996,16 +7401,17 @@ static int ipw_wx_set_power(struct net_device *dev,
6996{ 7401{
6997 struct ipw_priv *priv = ieee80211_priv(dev); 7402 struct ipw_priv *priv = ieee80211_priv(dev);
6998 int err; 7403 int err;
6999 7404 down(&priv->sem);
7000 if (wrqu->power.disabled) { 7405 if (wrqu->power.disabled) {
7001 priv->power_mode = IPW_POWER_LEVEL(priv->power_mode); 7406 priv->power_mode = IPW_POWER_LEVEL(priv->power_mode);
7002 err = ipw_send_power_mode(priv, IPW_POWER_MODE_CAM); 7407 err = ipw_send_power_mode(priv, IPW_POWER_MODE_CAM);
7003 if (err) { 7408 if (err) {
7004 IPW_DEBUG_WX("failed setting power mode.\n"); 7409 IPW_DEBUG_WX("failed setting power mode.\n");
7410 up(&priv->sem);
7005 return err; 7411 return err;
7006 } 7412 }
7007 IPW_DEBUG_WX("SET Power Management Mode -> off\n"); 7413 IPW_DEBUG_WX("SET Power Management Mode -> off\n");
7008 7414 up(&priv->sem);
7009 return 0; 7415 return 0;
7010 } 7416 }
7011 7417
@@ -7017,6 +7423,7 @@ static int ipw_wx_set_power(struct net_device *dev,
7017 default: /* Otherwise we don't support it */ 7423 default: /* Otherwise we don't support it */
7018 IPW_DEBUG_WX("SET PM Mode: %X not supported.\n", 7424 IPW_DEBUG_WX("SET PM Mode: %X not supported.\n",
7019 wrqu->power.flags); 7425 wrqu->power.flags);
7426 up(&priv->sem);
7020 return -EOPNOTSUPP; 7427 return -EOPNOTSUPP;
7021 } 7428 }
7022 7429
@@ -7029,11 +7436,12 @@ static int ipw_wx_set_power(struct net_device *dev,
7029 err = ipw_send_power_mode(priv, IPW_POWER_LEVEL(priv->power_mode)); 7436 err = ipw_send_power_mode(priv, IPW_POWER_LEVEL(priv->power_mode));
7030 if (err) { 7437 if (err) {
7031 IPW_DEBUG_WX("failed setting power mode.\n"); 7438 IPW_DEBUG_WX("failed setting power mode.\n");
7439 up(&priv->sem);
7032 return err; 7440 return err;
7033 } 7441 }
7034 7442
7035 IPW_DEBUG_WX("SET Power Management Mode -> 0x%02X\n", priv->power_mode); 7443 IPW_DEBUG_WX("SET Power Management Mode -> 0x%02X\n", priv->power_mode);
7036 7444 up(&priv->sem);
7037 return 0; 7445 return 0;
7038} 7446}
7039 7447
@@ -7042,12 +7450,13 @@ static int ipw_wx_get_power(struct net_device *dev,
7042 union iwreq_data *wrqu, char *extra) 7450 union iwreq_data *wrqu, char *extra)
7043{ 7451{
7044 struct ipw_priv *priv = ieee80211_priv(dev); 7452 struct ipw_priv *priv = ieee80211_priv(dev);
7045 7453 down(&priv->sem);
7046 if (!(priv->power_mode & IPW_POWER_ENABLED)) 7454 if (!(priv->power_mode & IPW_POWER_ENABLED))
7047 wrqu->power.disabled = 1; 7455 wrqu->power.disabled = 1;
7048 else 7456 else
7049 wrqu->power.disabled = 0; 7457 wrqu->power.disabled = 0;
7050 7458
7459 up(&priv->sem);
7051 IPW_DEBUG_WX("GET Power Management Mode -> %02X\n", priv->power_mode); 7460 IPW_DEBUG_WX("GET Power Management Mode -> %02X\n", priv->power_mode);
7052 7461
7053 return 0; 7462 return 0;
@@ -7060,7 +7469,7 @@ static int ipw_wx_set_powermode(struct net_device *dev,
7060 struct ipw_priv *priv = ieee80211_priv(dev); 7469 struct ipw_priv *priv = ieee80211_priv(dev);
7061 int mode = *(int *)extra; 7470 int mode = *(int *)extra;
7062 int err; 7471 int err;
7063 7472 down(&priv->sem);
7064 if ((mode < 1) || (mode > IPW_POWER_LIMIT)) { 7473 if ((mode < 1) || (mode > IPW_POWER_LIMIT)) {
7065 mode = IPW_POWER_AC; 7474 mode = IPW_POWER_AC;
7066 priv->power_mode = mode; 7475 priv->power_mode = mode;
@@ -7073,10 +7482,11 @@ static int ipw_wx_set_powermode(struct net_device *dev,
7073 7482
7074 if (err) { 7483 if (err) {
7075 IPW_DEBUG_WX("failed setting power mode.\n"); 7484 IPW_DEBUG_WX("failed setting power mode.\n");
7485 up(&priv->sem);
7076 return err; 7486 return err;
7077 } 7487 }
7078 } 7488 }
7079 7489 up(&priv->sem);
7080 return 0; 7490 return 0;
7081} 7491}
7082 7492
@@ -7125,7 +7535,7 @@ static int ipw_wx_set_wireless_mode(struct net_device *dev,
7125 IPW_WARNING("Attempt to set invalid wireless mode: %d\n", mode); 7535 IPW_WARNING("Attempt to set invalid wireless mode: %d\n", mode);
7126 return -EINVAL; 7536 return -EINVAL;
7127 } 7537 }
7128 7538 down(&priv->sem);
7129 if (priv->adapter == IPW_2915ABG) { 7539 if (priv->adapter == IPW_2915ABG) {
7130 priv->ieee->abg_true = 1; 7540 priv->ieee->abg_true = 1;
7131 if (mode & IEEE_A) { 7541 if (mode & IEEE_A) {
@@ -7137,6 +7547,7 @@ static int ipw_wx_set_wireless_mode(struct net_device *dev,
7137 if (mode & IEEE_A) { 7547 if (mode & IEEE_A) {
7138 IPW_WARNING("Attempt to set 2200BG into " 7548 IPW_WARNING("Attempt to set 2200BG into "
7139 "802.11a mode\n"); 7549 "802.11a mode\n");
7550 up(&priv->sem);
7140 return -EINVAL; 7551 return -EINVAL;
7141 } 7552 }
7142 7553
@@ -7160,16 +7571,12 @@ static int ipw_wx_set_wireless_mode(struct net_device *dev,
7160 priv->ieee->modulation = modulation; 7571 priv->ieee->modulation = modulation;
7161 init_supported_rates(priv, &priv->rates); 7572 init_supported_rates(priv, &priv->rates);
7162 7573
7163 /* If we are currently associated, or trying to associate 7574 /* Network configuration changed -- force [re]association */
7164 * then see if this is a new configuration (causing us to 7575 IPW_DEBUG_ASSOC("[re]association triggered due to mode change.\n");
7165 * disassociate) */ 7576 if (!ipw_disassociate(priv)) {
7166 if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) {
7167 /* The resulting association will trigger
7168 * the new rates to be sent to the device */
7169 IPW_DEBUG_ASSOC("Disassociating due to mode change.\n");
7170 ipw_disassociate(priv);
7171 } else
7172 ipw_send_supported_rates(priv, &priv->rates); 7577 ipw_send_supported_rates(priv, &priv->rates);
7578 ipw_associate(priv);
7579 }
7173 7580
7174 /* Update the band LEDs */ 7581 /* Update the band LEDs */
7175 ipw_led_band_on(priv); 7582 ipw_led_band_on(priv);
@@ -7177,6 +7584,7 @@ static int ipw_wx_set_wireless_mode(struct net_device *dev,
7177 IPW_DEBUG_WX("PRIV SET MODE: %c%c%c\n", 7584 IPW_DEBUG_WX("PRIV SET MODE: %c%c%c\n",
7178 mode & IEEE_A ? 'a' : '.', 7585 mode & IEEE_A ? 'a' : '.',
7179 mode & IEEE_B ? 'b' : '.', mode & IEEE_G ? 'g' : '.'); 7586 mode & IEEE_B ? 'b' : '.', mode & IEEE_G ? 'g' : '.');
7587 up(&priv->sem);
7180 return 0; 7588 return 0;
7181} 7589}
7182 7590
@@ -7185,7 +7593,7 @@ static int ipw_wx_get_wireless_mode(struct net_device *dev,
7185 union iwreq_data *wrqu, char *extra) 7593 union iwreq_data *wrqu, char *extra)
7186{ 7594{
7187 struct ipw_priv *priv = ieee80211_priv(dev); 7595 struct ipw_priv *priv = ieee80211_priv(dev);
7188 7596 down(&priv->sem);
7189 switch (priv->ieee->mode) { 7597 switch (priv->ieee->mode) {
7190 case IEEE_A: 7598 case IEEE_A:
7191 strncpy(extra, "802.11a (1)", MAX_WX_STRING); 7599 strncpy(extra, "802.11a (1)", MAX_WX_STRING);
@@ -7216,6 +7624,7 @@ static int ipw_wx_get_wireless_mode(struct net_device *dev,
7216 IPW_DEBUG_WX("PRIV GET MODE: %s\n", extra); 7624 IPW_DEBUG_WX("PRIV GET MODE: %s\n", extra);
7217 7625
7218 wrqu->data.length = strlen(extra) + 1; 7626 wrqu->data.length = strlen(extra) + 1;
7627 up(&priv->sem);
7219 7628
7220 return 0; 7629 return 0;
7221} 7630}
@@ -7226,18 +7635,17 @@ static int ipw_wx_set_preamble(struct net_device *dev,
7226{ 7635{
7227 struct ipw_priv *priv = ieee80211_priv(dev); 7636 struct ipw_priv *priv = ieee80211_priv(dev);
7228 int mode = *(int *)extra; 7637 int mode = *(int *)extra;
7229 7638 down(&priv->sem);
7230 /* Switching from SHORT -> LONG requires a disassociation */ 7639 /* Switching from SHORT -> LONG requires a disassociation */
7231 if (mode == 1) { 7640 if (mode == 1) {
7232 if (!(priv->config & CFG_PREAMBLE_LONG)) { 7641 if (!(priv->config & CFG_PREAMBLE_LONG)) {
7233 priv->config |= CFG_PREAMBLE_LONG; 7642 priv->config |= CFG_PREAMBLE_LONG;
7234 if (priv->status & 7643
7235 (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { 7644 /* Network configuration changed -- force [re]association */
7236 IPW_DEBUG_ASSOC 7645 IPW_DEBUG_ASSOC
7237 ("Disassociating due to preamble " 7646 ("[re]association triggered due to preamble change.\n");
7238 "change.\n"); 7647 if (!ipw_disassociate(priv))
7239 ipw_disassociate(priv); 7648 ipw_associate(priv);
7240 }
7241 } 7649 }
7242 goto done; 7650 goto done;
7243 } 7651 }
@@ -7246,10 +7654,11 @@ static int ipw_wx_set_preamble(struct net_device *dev,
7246 priv->config &= ~CFG_PREAMBLE_LONG; 7654 priv->config &= ~CFG_PREAMBLE_LONG;
7247 goto done; 7655 goto done;
7248 } 7656 }
7249 7657 up(&priv->sem);
7250 return -EINVAL; 7658 return -EINVAL;
7251 7659
7252 done: 7660 done:
7661 up(&priv->sem);
7253 return 0; 7662 return 0;
7254} 7663}
7255 7664
@@ -7258,12 +7667,12 @@ static int ipw_wx_get_preamble(struct net_device *dev,
7258 union iwreq_data *wrqu, char *extra) 7667 union iwreq_data *wrqu, char *extra)
7259{ 7668{
7260 struct ipw_priv *priv = ieee80211_priv(dev); 7669 struct ipw_priv *priv = ieee80211_priv(dev);
7261 7670 down(&priv->sem);
7262 if (priv->config & CFG_PREAMBLE_LONG) 7671 if (priv->config & CFG_PREAMBLE_LONG)
7263 snprintf(wrqu->name, IFNAMSIZ, "long (1)"); 7672 snprintf(wrqu->name, IFNAMSIZ, "long (1)");
7264 else 7673 else
7265 snprintf(wrqu->name, IFNAMSIZ, "auto (0)"); 7674 snprintf(wrqu->name, IFNAMSIZ, "auto (0)");
7266 7675 up(&priv->sem);
7267 return 0; 7676 return 0;
7268} 7677}
7269 7678
@@ -7275,7 +7684,7 @@ static int ipw_wx_set_monitor(struct net_device *dev,
7275 struct ipw_priv *priv = ieee80211_priv(dev); 7684 struct ipw_priv *priv = ieee80211_priv(dev);
7276 int *parms = (int *)extra; 7685 int *parms = (int *)extra;
7277 int enable = (parms[0] > 0); 7686 int enable = (parms[0] > 0);
7278 7687 down(&priv->sem);
7279 IPW_DEBUG_WX("SET MONITOR: %d %d\n", enable, parms[1]); 7688 IPW_DEBUG_WX("SET MONITOR: %d %d\n", enable, parms[1]);
7280 if (enable) { 7689 if (enable) {
7281 if (priv->ieee->iw_mode != IW_MODE_MONITOR) { 7690 if (priv->ieee->iw_mode != IW_MODE_MONITOR) {
@@ -7285,11 +7694,14 @@ static int ipw_wx_set_monitor(struct net_device *dev,
7285 7694
7286 ipw_set_channel(priv, parms[1]); 7695 ipw_set_channel(priv, parms[1]);
7287 } else { 7696 } else {
7288 if (priv->ieee->iw_mode != IW_MODE_MONITOR) 7697 if (priv->ieee->iw_mode != IW_MODE_MONITOR) {
7698 up(&priv->sem);
7289 return 0; 7699 return 0;
7700 }
7290 priv->net_dev->type = ARPHRD_ETHER; 7701 priv->net_dev->type = ARPHRD_ETHER;
7291 queue_work(priv->workqueue, &priv->adapter_restart); 7702 queue_work(priv->workqueue, &priv->adapter_restart);
7292 } 7703 }
7704 up(&priv->sem);
7293 return 0; 7705 return 0;
7294} 7706}
7295 7707
@@ -7473,7 +7885,7 @@ static inline void init_sys_config(struct ipw_sys_config *sys_config)
7473 sys_config->dot11g_auto_detection = 0; 7885 sys_config->dot11g_auto_detection = 0;
7474 sys_config->enable_cts_to_self = 0; 7886 sys_config->enable_cts_to_self = 0;
7475 sys_config->bt_coexist_collision_thr = 0; 7887 sys_config->bt_coexist_collision_thr = 0;
7476 sys_config->pass_noise_stats_to_host = 0; //1 -- fix for 256 7888 sys_config->pass_noise_stats_to_host = 1; //1 -- fix for 256
7477} 7889}
7478 7890
7479static int ipw_net_open(struct net_device *dev) 7891static int ipw_net_open(struct net_device *dev)
@@ -7481,9 +7893,11 @@ static int ipw_net_open(struct net_device *dev)
7481 struct ipw_priv *priv = ieee80211_priv(dev); 7893 struct ipw_priv *priv = ieee80211_priv(dev);
7482 IPW_DEBUG_INFO("dev->open\n"); 7894 IPW_DEBUG_INFO("dev->open\n");
7483 /* we should be verifying the device is ready to be opened */ 7895 /* we should be verifying the device is ready to be opened */
7896 down(&priv->sem);
7484 if (!(priv->status & STATUS_RF_KILL_MASK) && 7897 if (!(priv->status & STATUS_RF_KILL_MASK) &&
7485 (priv->status & STATUS_ASSOCIATED)) 7898 (priv->status & STATUS_ASSOCIATED))
7486 netif_start_queue(dev); 7899 netif_start_queue(dev);
7900 up(&priv->sem);
7487 return 0; 7901 return 0;
7488} 7902}
7489 7903
@@ -7511,6 +7925,7 @@ static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb)
7511 struct clx2_queue *q = &txq->q; 7925 struct clx2_queue *q = &txq->q;
7512 u8 id, hdr_len, unicast; 7926 u8 id, hdr_len, unicast;
7513 u16 remaining_bytes; 7927 u16 remaining_bytes;
7928 int fc;
7514 7929
7515 switch (priv->ieee->iw_mode) { 7930 switch (priv->ieee->iw_mode) {
7516 case IW_MODE_ADHOC: 7931 case IW_MODE_ADHOC:
@@ -7562,6 +7977,9 @@ static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb)
7562 if (priv->assoc_request.preamble_length == DCT_FLAG_SHORT_PREAMBLE) 7977 if (priv->assoc_request.preamble_length == DCT_FLAG_SHORT_PREAMBLE)
7563 tfd->u.data.tx_flags |= DCT_FLAG_SHORT_PREAMBLE; 7978 tfd->u.data.tx_flags |= DCT_FLAG_SHORT_PREAMBLE;
7564 7979
7980 fc = le16_to_cpu(hdr->frame_ctl);
7981 hdr->frame_ctl = cpu_to_le16(fc & ~IEEE80211_FCTL_MOREFRAGS);
7982
7565 memcpy(&tfd->u.data.tfd.tfd_24.mchdr, hdr, hdr_len); 7983 memcpy(&tfd->u.data.tfd.tfd_24.mchdr, hdr, hdr_len);
7566 7984
7567 /* payload */ 7985 /* payload */
@@ -7644,7 +8062,6 @@ static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb,
7644 unsigned long flags; 8062 unsigned long flags;
7645 8063
7646 IPW_DEBUG_TX("dev->xmit(%d bytes)\n", txb->payload_size); 8064 IPW_DEBUG_TX("dev->xmit(%d bytes)\n", txb->payload_size);
7647
7648 spin_lock_irqsave(&priv->lock, flags); 8065 spin_lock_irqsave(&priv->lock, flags);
7649 8066
7650 if (!(priv->status & STATUS_ASSOCIATED)) { 8067 if (!(priv->status & STATUS_ASSOCIATED)) {
@@ -7655,13 +8072,15 @@ static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb,
7655 } 8072 }
7656 8073
7657 ipw_tx_skb(priv, txb); 8074 ipw_tx_skb(priv, txb);
8075 spin_unlock_irqrestore(&priv->lock, flags);
7658 ipw_led_activity_on(priv); 8076 ipw_led_activity_on(priv);
7659 8077
7660 spin_unlock_irqrestore(&priv->lock, flags); 8078// up(&priv->sem);
7661 return 0; 8079 return 0;
7662 8080
7663 fail_unlock: 8081 fail_unlock:
7664 spin_unlock_irqrestore(&priv->lock, flags); 8082 spin_unlock_irqrestore(&priv->lock, flags);
8083// up(&priv->sem);
7665 return 1; 8084 return 1;
7666} 8085}
7667 8086
@@ -7685,11 +8104,13 @@ static int ipw_net_set_mac_address(struct net_device *dev, void *p)
7685 struct sockaddr *addr = p; 8104 struct sockaddr *addr = p;
7686 if (!is_valid_ether_addr(addr->sa_data)) 8105 if (!is_valid_ether_addr(addr->sa_data))
7687 return -EADDRNOTAVAIL; 8106 return -EADDRNOTAVAIL;
8107 down(&priv->sem);
7688 priv->config |= CFG_CUSTOM_MAC; 8108 priv->config |= CFG_CUSTOM_MAC;
7689 memcpy(priv->mac_addr, addr->sa_data, ETH_ALEN); 8109 memcpy(priv->mac_addr, addr->sa_data, ETH_ALEN);
7690 printk(KERN_INFO "%s: Setting MAC to " MAC_FMT "\n", 8110 printk(KERN_INFO "%s: Setting MAC to " MAC_FMT "\n",
7691 priv->net_dev->name, MAC_ARG(priv->mac_addr)); 8111 priv->net_dev->name, MAC_ARG(priv->mac_addr));
7692 queue_work(priv->workqueue, &priv->adapter_restart); 8112 queue_work(priv->workqueue, &priv->adapter_restart);
8113 up(&priv->sem);
7693 return 0; 8114 return 0;
7694} 8115}
7695 8116
@@ -7733,8 +8154,9 @@ static int ipw_ethtool_get_eeprom(struct net_device *dev,
7733 8154
7734 if (eeprom->offset + eeprom->len > CX2_EEPROM_IMAGE_SIZE) 8155 if (eeprom->offset + eeprom->len > CX2_EEPROM_IMAGE_SIZE)
7735 return -EINVAL; 8156 return -EINVAL;
7736 8157 down(&p->sem);
7737 memcpy(bytes, &((u8 *) p->eeprom)[eeprom->offset], eeprom->len); 8158 memcpy(bytes, &((u8 *) p->eeprom)[eeprom->offset], eeprom->len);
8159 up(&p->sem);
7738 return 0; 8160 return 0;
7739} 8161}
7740 8162
@@ -7746,12 +8168,12 @@ static int ipw_ethtool_set_eeprom(struct net_device *dev,
7746 8168
7747 if (eeprom->offset + eeprom->len > CX2_EEPROM_IMAGE_SIZE) 8169 if (eeprom->offset + eeprom->len > CX2_EEPROM_IMAGE_SIZE)
7748 return -EINVAL; 8170 return -EINVAL;
7749 8171 down(&p->sem);
7750 memcpy(&((u8 *) p->eeprom)[eeprom->offset], bytes, eeprom->len); 8172 memcpy(&((u8 *) p->eeprom)[eeprom->offset], bytes, eeprom->len);
7751 for (i = IPW_EEPROM_DATA; 8173 for (i = IPW_EEPROM_DATA;
7752 i < IPW_EEPROM_DATA + CX2_EEPROM_IMAGE_SIZE; i++) 8174 i < IPW_EEPROM_DATA + CX2_EEPROM_IMAGE_SIZE; i++)
7753 ipw_write8(p, i, p->eeprom[i]); 8175 ipw_write8(p, i, p->eeprom[i]);
7754 8176 up(&p->sem);
7755 return 0; 8177 return 0;
7756} 8178}
7757 8179
@@ -7775,6 +8197,8 @@ static irqreturn_t ipw_isr(int irq, void *data, struct pt_regs *regs)
7775 8197
7776 if (!(priv->status & STATUS_INT_ENABLED)) { 8198 if (!(priv->status & STATUS_INT_ENABLED)) {
7777 /* Shared IRQ */ 8199 /* Shared IRQ */
8200// ipw_write32(priv, CX2_INTA_RW, CX2_INTA_MASK_ALL);
8201// return IRQ_HANDLED;
7778 goto none; 8202 goto none;
7779 } 8203 }
7780 8204
@@ -7843,6 +8267,14 @@ static void ipw_rf_kill(void *adapter)
7843 spin_unlock_irqrestore(&priv->lock, flags); 8267 spin_unlock_irqrestore(&priv->lock, flags);
7844} 8268}
7845 8269
8270static void ipw_bg_rf_kill(void *data)
8271{
8272 struct ipw_priv *priv = data;
8273 down(&priv->sem);
8274 ipw_rf_kill(data);
8275 up(&priv->sem);
8276}
8277
7846void ipw_link_up(struct ipw_priv *priv) 8278void ipw_link_up(struct ipw_priv *priv)
7847{ 8279{
7848 netif_carrier_on(priv->net_dev); 8280 netif_carrier_on(priv->net_dev);
@@ -7854,6 +8286,7 @@ void ipw_link_up(struct ipw_priv *priv)
7854 netif_start_queue(priv->net_dev); 8286 netif_start_queue(priv->net_dev);
7855 } 8287 }
7856 8288
8289 cancel_delayed_work(&priv->request_scan);
7857 ipw_reset_stats(priv); 8290 ipw_reset_stats(priv);
7858 /* Ensure the rate is updated immediately */ 8291 /* Ensure the rate is updated immediately */
7859 priv->last_rate = ipw_get_current_rate(priv); 8292 priv->last_rate = ipw_get_current_rate(priv);
@@ -7865,6 +8298,14 @@ void ipw_link_up(struct ipw_priv *priv)
7865 queue_delayed_work(priv->workqueue, &priv->request_scan, HZ); 8298 queue_delayed_work(priv->workqueue, &priv->request_scan, HZ);
7866} 8299}
7867 8300
8301static void ipw_bg_link_up(void *data)
8302{
8303 struct ipw_priv *priv = data;
8304 down(&priv->sem);
8305 ipw_link_up(data);
8306 up(&priv->sem);
8307}
8308
7868void ipw_link_down(struct ipw_priv *priv) 8309void ipw_link_down(struct ipw_priv *priv)
7869{ 8310{
7870 ipw_led_link_down(priv); 8311 ipw_led_link_down(priv);
@@ -7883,6 +8324,14 @@ void ipw_link_down(struct ipw_priv *priv)
7883 queue_work(priv->workqueue, &priv->request_scan); 8324 queue_work(priv->workqueue, &priv->request_scan);
7884} 8325}
7885 8326
8327static void ipw_bg_link_down(void *data)
8328{
8329 struct ipw_priv *priv = data;
8330 down(&priv->sem);
8331 ipw_link_down(data);
8332 up(&priv->sem);
8333}
8334
7886static int ipw_setup_deferred_work(struct ipw_priv *priv) 8335static int ipw_setup_deferred_work(struct ipw_priv *priv)
7887{ 8336{
7888 int ret = 0; 8337 int ret = 0;
@@ -7890,28 +8339,31 @@ static int ipw_setup_deferred_work(struct ipw_priv *priv)
7890 priv->workqueue = create_workqueue(DRV_NAME); 8339 priv->workqueue = create_workqueue(DRV_NAME);
7891 init_waitqueue_head(&priv->wait_command_queue); 8340 init_waitqueue_head(&priv->wait_command_queue);
7892 8341
7893 INIT_WORK(&priv->adhoc_check, ipw_adhoc_check, priv); 8342 INIT_WORK(&priv->adhoc_check, ipw_bg_adhoc_check, priv);
7894 INIT_WORK(&priv->associate, ipw_associate, priv); 8343 INIT_WORK(&priv->associate, ipw_bg_associate, priv);
7895 INIT_WORK(&priv->disassociate, ipw_disassociate, priv); 8344 INIT_WORK(&priv->disassociate, ipw_bg_disassociate, priv);
7896 INIT_WORK(&priv->rx_replenish, ipw_rx_queue_replenish, priv); 8345 INIT_WORK(&priv->rx_replenish, ipw_bg_rx_queue_replenish, priv);
7897 INIT_WORK(&priv->adapter_restart, ipw_adapter_restart, priv); 8346 INIT_WORK(&priv->adapter_restart, ipw_bg_adapter_restart, priv);
7898 INIT_WORK(&priv->rf_kill, ipw_rf_kill, priv); 8347 INIT_WORK(&priv->rf_kill, ipw_bg_rf_kill, priv);
7899 INIT_WORK(&priv->up, (void (*)(void *))ipw_up, priv); 8348 INIT_WORK(&priv->up, (void (*)(void *))ipw_bg_up, priv);
7900 INIT_WORK(&priv->down, (void (*)(void *))ipw_down, priv); 8349 INIT_WORK(&priv->down, (void (*)(void *))ipw_bg_down, priv);
7901 INIT_WORK(&priv->request_scan, 8350 INIT_WORK(&priv->request_scan,
7902 (void (*)(void *))ipw_request_scan, priv); 8351 (void (*)(void *))ipw_bg_request_scan, priv);
7903 INIT_WORK(&priv->gather_stats, 8352 INIT_WORK(&priv->gather_stats,
7904 (void (*)(void *))ipw_gather_stats, priv); 8353 (void (*)(void *))ipw_bg_gather_stats, priv);
7905 INIT_WORK(&priv->abort_scan, (void (*)(void *))ipw_abort_scan, priv); 8354 INIT_WORK(&priv->abort_scan, (void (*)(void *))ipw_bg_abort_scan, priv);
7906 INIT_WORK(&priv->roam, ipw_roam, priv); 8355 INIT_WORK(&priv->roam, ipw_bg_roam, priv);
7907 INIT_WORK(&priv->scan_check, ipw_scan_check, priv); 8356 INIT_WORK(&priv->scan_check, ipw_bg_scan_check, priv);
7908 INIT_WORK(&priv->link_up, (void (*)(void *))ipw_link_up, priv); 8357 INIT_WORK(&priv->link_up, (void (*)(void *))ipw_bg_link_up, priv);
7909 INIT_WORK(&priv->link_down, (void (*)(void *))ipw_link_down, priv); 8358 INIT_WORK(&priv->link_down, (void (*)(void *))ipw_bg_link_down, priv);
7910 INIT_WORK(&priv->led_link_on, (void (*)(void *))ipw_led_link_on, priv); 8359 INIT_WORK(&priv->led_link_on, (void (*)(void *))ipw_bg_led_link_on,
7911 INIT_WORK(&priv->led_link_off, (void (*)(void *))ipw_led_link_off, 8360 priv);
8361 INIT_WORK(&priv->led_link_off, (void (*)(void *))ipw_bg_led_link_off,
7912 priv); 8362 priv);
7913 INIT_WORK(&priv->led_act_off, (void (*)(void *))ipw_led_activity_off, 8363 INIT_WORK(&priv->led_act_off, (void (*)(void *))ipw_bg_led_activity_off,
7914 priv); 8364 priv);
8365 INIT_WORK(&priv->merge_networks,
8366 (void (*)(void *))ipw_merge_adhoc_network, priv);
7915 8367
7916 tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) 8368 tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
7917 ipw_irq_tasklet, (unsigned long)priv); 8369 ipw_irq_tasklet, (unsigned long)priv);
@@ -7924,7 +8376,7 @@ static void shim__set_security(struct net_device *dev,
7924{ 8376{
7925 struct ipw_priv *priv = ieee80211_priv(dev); 8377 struct ipw_priv *priv = ieee80211_priv(dev);
7926 int i; 8378 int i;
7927 8379 down(&priv->sem);
7928 for (i = 0; i < 4; i++) { 8380 for (i = 0; i < 4; i++) {
7929 if (sec->flags & (1 << i)) { 8381 if (sec->flags & (1 << i)) {
7930 priv->sec.key_sizes[i] = sec->key_sizes[i]; 8382 priv->sec.key_sizes[i] = sec->key_sizes[i];
@@ -7989,6 +8441,7 @@ static void shim__set_security(struct net_device *dev,
7989 ipw_disassociate(priv); 8441 ipw_disassociate(priv);
7990 } 8442 }
7991#endif 8443#endif
8444 up(&priv->sem);
7992} 8445}
7993 8446
7994static int init_supported_rates(struct ipw_priv *priv, 8447static int init_supported_rates(struct ipw_priv *priv,
@@ -8054,6 +8507,11 @@ static int ipw_config(struct ipw_priv *priv)
8054 8507
8055 /* set basic system config settings */ 8508 /* set basic system config settings */
8056 init_sys_config(&priv->sys_config); 8509 init_sys_config(&priv->sys_config);
8510 if (priv->ieee->iw_mode == IW_MODE_ADHOC)
8511 priv->sys_config.answer_broadcast_ssid_probe = 1;
8512 else
8513 priv->sys_config.answer_broadcast_ssid_probe = 0;
8514
8057 if (ipw_send_system_config(priv, &priv->sys_config)) 8515 if (ipw_send_system_config(priv, &priv->sys_config))
8058 goto error; 8516 goto error;
8059 8517
@@ -8075,8 +8533,10 @@ static int ipw_config(struct ipw_priv *priv)
8075 goto error; 8533 goto error;
8076 8534
8077 /* If configured to try and auto-associate, kick off a scan */ 8535 /* If configured to try and auto-associate, kick off a scan */
8078 if ((priv->config & CFG_ASSOCIATE) && ipw_request_scan(priv)) 8536 if ((priv->config & CFG_ASSOCIATE) && ipw_request_scan(priv)) {
8537 IPW_WARNING("error sending scan request\n");
8079 goto error; 8538 goto error;
8539 }
8080 8540
8081 return 0; 8541 return 0;
8082 8542
@@ -8106,8 +8566,9 @@ static int ipw_up(struct ipw_priv *priv)
8106 eeprom_parse_mac(priv, priv->mac_addr); 8566 eeprom_parse_mac(priv, priv->mac_addr);
8107 memcpy(priv->net_dev->dev_addr, priv->mac_addr, ETH_ALEN); 8567 memcpy(priv->net_dev->dev_addr, priv->mac_addr, ETH_ALEN);
8108 8568
8109 if (priv->status & STATUS_RF_KILL_MASK) 8569 if (priv->status & STATUS_RF_KILL_MASK) {
8110 return 0; 8570 return 0;
8571 }
8111 8572
8112 rc = ipw_config(priv); 8573 rc = ipw_config(priv);
8113 if (!rc) { 8574 if (!rc) {
@@ -8115,12 +8576,11 @@ static int ipw_up(struct ipw_priv *priv)
8115 ipw_led_init(priv); 8576 ipw_led_init(priv);
8116 ipw_led_radio_on(priv); 8577 ipw_led_radio_on(priv);
8117 priv->notif_missed_beacons = 0; 8578 priv->notif_missed_beacons = 0;
8579 priv->status |= STATUS_INIT;
8118 return 0; 8580 return 0;
8119 } else {
8120 IPW_DEBUG_INFO("Device configuration failed: 0x%08X\n",
8121 rc);
8122 } 8581 }
8123 8582
8583 IPW_DEBUG_INFO("Device configuration failed: 0x%08X\n", rc);
8124 IPW_DEBUG_INFO("Failed to config device on retry %d of %d\n", 8584 IPW_DEBUG_INFO("Failed to config device on retry %d of %d\n",
8125 i, MAX_HW_RESTARTS); 8585 i, MAX_HW_RESTARTS);
8126 8586
@@ -8132,13 +8592,22 @@ static int ipw_up(struct ipw_priv *priv)
8132 /* tried to restart and config the device for as long as our 8592 /* tried to restart and config the device for as long as our
8133 * patience could withstand */ 8593 * patience could withstand */
8134 IPW_ERROR("Unable to initialize device after %d attempts.\n", i); 8594 IPW_ERROR("Unable to initialize device after %d attempts.\n", i);
8595
8135 return -EIO; 8596 return -EIO;
8136} 8597}
8137 8598
8599static void ipw_bg_up(void *data)
8600{
8601 struct ipw_priv *priv = data;
8602 down(&priv->sem);
8603 ipw_up(data);
8604 up(&priv->sem);
8605}
8606
8138static void ipw_down(struct ipw_priv *priv) 8607static void ipw_down(struct ipw_priv *priv)
8139{ 8608{
8140 /* Attempt to disable the card */
8141#if 0 8609#if 0
8610 /* Attempt to disable the card */
8142 ipw_send_card_disable(priv, 0); 8611 ipw_send_card_disable(priv, 0);
8143#endif 8612#endif
8144 8613
@@ -8147,7 +8616,6 @@ static void ipw_down(struct ipw_priv *priv)
8147 8616
8148 /* Clear all bits but the RF Kill */ 8617 /* Clear all bits but the RF Kill */
8149 priv->status &= STATUS_RF_KILL_MASK; 8618 priv->status &= STATUS_RF_KILL_MASK;
8150
8151 netif_carrier_off(priv->net_dev); 8619 netif_carrier_off(priv->net_dev);
8152 netif_stop_queue(priv->net_dev); 8620 netif_stop_queue(priv->net_dev);
8153 8621
@@ -8156,6 +8624,14 @@ static void ipw_down(struct ipw_priv *priv)
8156 ipw_led_radio_off(priv); 8624 ipw_led_radio_off(priv);
8157} 8625}
8158 8626
8627static void ipw_bg_down(void *data)
8628{
8629 struct ipw_priv *priv = data;
8630 down(&priv->sem);
8631 ipw_down(data);
8632 up(&priv->sem);
8633}
8634
8159static int ipw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) 8635static int ipw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
8160{ 8636{
8161 struct iwreq *wrq = (struct iwreq *)rq; 8637 struct iwreq *wrq = (struct iwreq *)rq;
@@ -8176,21 +8652,26 @@ static int ipw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
8176static int ipw_net_init(struct net_device *dev) 8652static int ipw_net_init(struct net_device *dev)
8177{ 8653{
8178 struct ipw_priv *priv = ieee80211_priv(dev); 8654 struct ipw_priv *priv = ieee80211_priv(dev);
8179 8655 down(&priv->sem);
8180 if (priv->status & STATUS_RF_KILL_SW) { 8656 if (priv->status & STATUS_RF_KILL_SW) {
8181 IPW_WARNING("Radio disabled by module parameter.\n"); 8657 IPW_WARNING("Radio disabled by module parameter.\n");
8658 up(&priv->sem);
8182 return 0; 8659 return 0;
8183 } else if (rf_kill_active(priv)) { 8660 } else if (rf_kill_active(priv)) {
8184 IPW_WARNING("Radio Frequency Kill Switch is On:\n" 8661 IPW_WARNING("Radio Frequency Kill Switch is On:\n"
8185 "Kill switch must be turned off for " 8662 "Kill switch must be turned off for "
8186 "wireless networking to work.\n"); 8663 "wireless networking to work.\n");
8187 queue_delayed_work(priv->workqueue, &priv->rf_kill, 2 * HZ); 8664 queue_delayed_work(priv->workqueue, &priv->rf_kill, 2 * HZ);
8665 up(&priv->sem);
8188 return 0; 8666 return 0;
8189 } 8667 }
8190 8668
8191 if (ipw_up(priv)) 8669 if (ipw_up(priv)) {
8670 up(&priv->sem);
8192 return -EIO; 8671 return -EIO;
8672 }
8193 8673
8674 up(&priv->sem);
8194 return 0; 8675 return 0;
8195} 8676}
8196 8677
@@ -8275,6 +8756,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
8275#endif 8756#endif
8276 spin_lock_init(&priv->lock); 8757 spin_lock_init(&priv->lock);
8277 8758
8759 init_MUTEX(&priv->sem);
8278 if (pci_enable_device(pdev)) { 8760 if (pci_enable_device(pdev)) {
8279 err = -ENODEV; 8761 err = -ENODEV;
8280 goto out_free_ieee80211; 8762 goto out_free_ieee80211;
@@ -8416,9 +8898,14 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
8416 ipw_wx_data.spy_data = &priv->ieee->spy_data; 8898 ipw_wx_data.spy_data = &priv->ieee->spy_data;
8417 ipw_wx_data.ieee80211 = priv->ieee; 8899 ipw_wx_data.ieee80211 = priv->ieee;
8418 8900
8901 down(&priv->sem);
8902
8419 priv->ieee->hard_start_xmit = ipw_net_hard_start_xmit; 8903 priv->ieee->hard_start_xmit = ipw_net_hard_start_xmit;
8420 priv->ieee->set_security = shim__set_security; 8904 priv->ieee->set_security = shim__set_security;
8421 8905
8906 priv->ieee->perfect_rssi = -20;
8907 priv->ieee->worst_rssi = -85;
8908
8422 net_dev->open = ipw_net_open; 8909 net_dev->open = ipw_net_open;
8423 net_dev->stop = ipw_net_stop; 8910 net_dev->stop = ipw_net_stop;
8424 net_dev->init = ipw_net_init; 8911 net_dev->init = ipw_net_init;
@@ -8438,15 +8925,16 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
8438 err = sysfs_create_group(&pdev->dev.kobj, &ipw_attribute_group); 8925 err = sysfs_create_group(&pdev->dev.kobj, &ipw_attribute_group);
8439 if (err) { 8926 if (err) {
8440 IPW_ERROR("failed to create sysfs device attributes\n"); 8927 IPW_ERROR("failed to create sysfs device attributes\n");
8928 up(&priv->sem);
8441 goto out_release_irq; 8929 goto out_release_irq;
8442 } 8930 }
8443 8931
8932 up(&priv->sem);
8444 err = register_netdev(net_dev); 8933 err = register_netdev(net_dev);
8445 if (err) { 8934 if (err) {
8446 IPW_ERROR("failed to register network device\n"); 8935 IPW_ERROR("failed to register network device\n");
8447 goto out_remove_sysfs; 8936 goto out_remove_sysfs;
8448 } 8937 }
8449
8450 return 0; 8938 return 0;
8451 8939
8452 out_remove_sysfs: 8940 out_remove_sysfs:
@@ -8623,8 +9111,7 @@ module_param(auto_create, int, 0444);
8623MODULE_PARM_DESC(auto_create, "auto create adhoc network (default on)"); 9111MODULE_PARM_DESC(auto_create, "auto create adhoc network (default on)");
8624 9112
8625module_param(led, int, 0444); 9113module_param(led, int, 0444);
8626MODULE_PARM_DESC(auto_create, 9114MODULE_PARM_DESC(led, "enable led control on some systems (default 0 off)\n");
8627 "enable led control on some systems (default 0 off)\n");
8628 9115
8629module_param(debug, int, 0444); 9116module_param(debug, int, 0444);
8630MODULE_PARM_DESC(debug, "debug output mask"); 9117MODULE_PARM_DESC(debug, "debug output mask");
diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h
index 1b339cb7a522..243b8ea14140 100644
--- a/drivers/net/wireless/ipw2200.h
+++ b/drivers/net/wireless/ipw2200.h
@@ -936,8 +936,8 @@ struct ipw_priv {
936 struct ieee80211_device *ieee; 936 struct ieee80211_device *ieee;
937 struct ieee80211_security sec; 937 struct ieee80211_security sec;
938 938
939 /* spinlock */
940 spinlock_t lock; 939 spinlock_t lock;
940 struct semaphore sem;
941 941
942 /* basic pci-network driver stuff */ 942 /* basic pci-network driver stuff */
943 struct pci_dev *pci_dev; 943 struct pci_dev *pci_dev;
@@ -1068,6 +1068,7 @@ struct ipw_priv {
1068 struct work_struct led_link_on; 1068 struct work_struct led_link_on;
1069 struct work_struct led_link_off; 1069 struct work_struct led_link_off;
1070 struct work_struct led_act_off; 1070 struct work_struct led_act_off;
1071 struct work_struct merge_networks;
1071 1072
1072#define IPW_2200BG 1 1073#define IPW_2200BG 1
1073#define IPW_2915ABG 2 1074#define IPW_2915ABG 2
@@ -1160,6 +1161,7 @@ do { if (ipw_debug_level & (level)) \
1160#define IPW_DL_TRACE (1<<28) 1161#define IPW_DL_TRACE (1<<28)
1161 1162
1162#define IPW_DL_STATS (1<<29) 1163#define IPW_DL_STATS (1<<29)
1164#define IPW_DL_MERGE (1<<30)
1163 1165
1164#define IPW_ERROR(f, a...) printk(KERN_ERR DRV_NAME ": " f, ## a) 1166#define IPW_ERROR(f, a...) printk(KERN_ERR DRV_NAME ": " f, ## a)
1165#define IPW_WARNING(f, a...) printk(KERN_WARNING DRV_NAME ": " f, ## a) 1167#define IPW_WARNING(f, a...) printk(KERN_WARNING DRV_NAME ": " f, ## a)
@@ -1187,6 +1189,7 @@ do { if (ipw_debug_level & (level)) \
1187#define IPW_DEBUG_STATE(f, a...) IPW_DEBUG(IPW_DL_STATE | IPW_DL_ASSOC | IPW_DL_INFO, f, ## a) 1189#define IPW_DEBUG_STATE(f, a...) IPW_DEBUG(IPW_DL_STATE | IPW_DL_ASSOC | IPW_DL_INFO, f, ## a)
1188#define IPW_DEBUG_ASSOC(f, a...) IPW_DEBUG(IPW_DL_ASSOC | IPW_DL_INFO, f, ## a) 1190#define IPW_DEBUG_ASSOC(f, a...) IPW_DEBUG(IPW_DL_ASSOC | IPW_DL_INFO, f, ## a)
1189#define IPW_DEBUG_STATS(f, a...) IPW_DEBUG(IPW_DL_STATS, f, ## a) 1191#define IPW_DEBUG_STATS(f, a...) IPW_DEBUG(IPW_DL_STATS, f, ## a)
1192#define IPW_DEBUG_MERGE(f, a...) IPW_DEBUG(IPW_DL_MERGE, f, ## a)
1190 1193
1191#include <linux/ctype.h> 1194#include <linux/ctype.h>
1192 1195