mirror of
				https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
				synced 2025-10-31 07:02:06 +00:00 
			
		
		
		
	 6bbdce5ac7
			
		
	
	
		6bbdce5ac7
		
	
	
	
	
		
			
			Unconfigured bcm43xx device can hit an assert() during wx_get_rate
queries.  This is because bcm43xx calls ieee80211softmac_start late
(i.e. during open instead of probe).
   bcm43xx_net_open ->
      bcm43xx_init_board ->
         bcm43xx_select_wireless_core ->
            ieee80211softmac_start
Fix is to check that device is running before completing
ieee80211softmac_wx_get_rate.
Signed-off-by: John W. Linville <linville@tuxdriver.com>
		
	
			
		
			
				
	
	
		
			522 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			522 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * This file contains our _wx handlers. Make sure you EXPORT_SYMBOL_GPL them
 | |
|  *
 | |
|  * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net>
 | |
|  *                          Joseph Jezak <josejx@gentoo.org>
 | |
|  *                          Larry Finger <Larry.Finger@lwfinger.net>
 | |
|  *                          Danny van Dyk <kugelfang@gentoo.org>
 | |
|  *                          Michael Buesch <mbuesch@freenet.de>
 | |
|  *
 | |
|  * 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
 | |
|  * published by the Free Software Foundation.
 | |
|  *
 | |
|  * This program is distributed in the hope that it will be useful, but WITHOUT
 | |
|  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | |
|  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | |
|  * more details.
 | |
|  *
 | |
|  * You should have received a copy of the GNU General Public License
 | |
|  * along with this program; if not, write to the Free Software
 | |
|  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 | |
|  *
 | |
|  * The full GNU General Public License is included in this distribution in the
 | |
|  * file called COPYING.
 | |
|  */
 | |
| 
 | |
| #include "ieee80211softmac_priv.h"
 | |
| 
 | |
| #include <net/iw_handler.h>
 | |
| /* for is_broadcast_ether_addr and is_zero_ether_addr */
 | |
| #include <linux/etherdevice.h>
 | |
| 
 | |
| int
 | |
| ieee80211softmac_wx_trigger_scan(struct net_device *net_dev,
 | |
| 				 struct iw_request_info *info,
 | |
| 				 union iwreq_data *data,
 | |
| 				 char *extra)
 | |
| {
 | |
| 	struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
 | |
| 	return ieee80211softmac_start_scan(sm);
 | |
| }
 | |
| EXPORT_SYMBOL_GPL(ieee80211softmac_wx_trigger_scan);
 | |
| 
 | |
| 
 | |
| /* if we're still scanning, return -EAGAIN so that userspace tools
 | |
|  * can get the complete scan results, otherwise return 0. */
 | |
| int
 | |
| ieee80211softmac_wx_get_scan_results(struct net_device *net_dev,
 | |
| 				     struct iw_request_info *info,
 | |
| 				     union iwreq_data *data,
 | |
| 				     char *extra)
 | |
| {
 | |
| 	unsigned long flags;
 | |
| 	struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
 | |
| 
 | |
| 	spin_lock_irqsave(&sm->lock, flags);
 | |
| 	if (sm->scanning) {
 | |
| 		spin_unlock_irqrestore(&sm->lock, flags);
 | |
| 		return -EAGAIN;
 | |
| 	}
 | |
| 	spin_unlock_irqrestore(&sm->lock, flags);
 | |
| 	return ieee80211_wx_get_scan(sm->ieee, info, data, extra);
 | |
| }
 | |
| EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_scan_results);
 | |
| 
 | |
| int
 | |
| ieee80211softmac_wx_set_essid(struct net_device *net_dev,
 | |
| 			      struct iw_request_info *info,
 | |
| 			      union iwreq_data *data,
 | |
| 			      char *extra)
 | |
| {
 | |
| 	struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
 | |
| 	struct ieee80211softmac_network *n;
 | |
| 	struct ieee80211softmac_auth_queue_item *authptr;
 | |
| 	int length = 0;
 | |
| 
 | |
| 	mutex_lock(&sm->associnfo.mutex);
 | |
| 
 | |
| 	/* Check if we're already associating to this or another network
 | |
| 	 * If it's another network, cancel and start over with our new network
 | |
| 	 * If it's our network, ignore the change, we're already doing it!
 | |
| 	 */
 | |
| 	if((sm->associnfo.associating || sm->associnfo.associated) &&
 | |
| 	   (data->essid.flags && data->essid.length)) {
 | |
| 		/* Get the associating network */
 | |
| 		n = ieee80211softmac_get_network_by_bssid(sm, sm->associnfo.bssid);
 | |
| 		if(n && n->essid.len == data->essid.length &&
 | |
| 		   !memcmp(n->essid.data, extra, n->essid.len)) {
 | |
| 			dprintk(KERN_INFO PFX "Already associating or associated to "MAC_FMT"\n",
 | |
| 				MAC_ARG(sm->associnfo.bssid));
 | |
| 			goto out;
 | |
| 		} else {
 | |
| 			dprintk(KERN_INFO PFX "Canceling existing associate request!\n");
 | |
| 			/* Cancel assoc work */
 | |
| 			cancel_delayed_work(&sm->associnfo.work);
 | |
| 			/* We don't have to do this, but it's a little cleaner */
 | |
| 			list_for_each_entry(authptr, &sm->auth_queue, list)
 | |
| 				cancel_delayed_work(&authptr->work);
 | |
| 			sm->associnfo.bssvalid = 0;
 | |
| 			sm->associnfo.bssfixed = 0;
 | |
| 			flush_scheduled_work();
 | |
| 			sm->associnfo.associating = 0;
 | |
| 			sm->associnfo.associated = 0;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	sm->associnfo.static_essid = 0;
 | |
| 	sm->associnfo.assoc_wait = 0;
 | |
| 
 | |
| 	if (data->essid.flags && data->essid.length) {
 | |
| 		length = min((int)data->essid.length, IW_ESSID_MAX_SIZE);
 | |
| 		if (length) {
 | |
| 			memcpy(sm->associnfo.req_essid.data, extra, length);
 | |
| 			sm->associnfo.static_essid = 1;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/* set our requested ESSID length.
 | |
| 	 * If applicable, we have already copied the data in */
 | |
| 	sm->associnfo.req_essid.len = length;
 | |
| 
 | |
| 	sm->associnfo.associating = 1;
 | |
| 	/* queue lower level code to do work (if necessary) */
 | |
| 	schedule_delayed_work(&sm->associnfo.work, 0);
 | |
| out:
 | |
| 	mutex_unlock(&sm->associnfo.mutex);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_essid);
 | |
| 
 | |
| int
 | |
| ieee80211softmac_wx_get_essid(struct net_device *net_dev,
 | |
| 			      struct iw_request_info *info,
 | |
| 			      union iwreq_data *data,
 | |
| 			      char *extra)
 | |
| {
 | |
| 	struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
 | |
| 
 | |
| 	mutex_lock(&sm->associnfo.mutex);
 | |
| 	/* If all fails, return ANY (empty) */
 | |
| 	data->essid.length = 0;
 | |
| 	data->essid.flags = 0;  /* active */
 | |
| 	
 | |
| 	/* If we have a statically configured ESSID then return it */
 | |
| 	if (sm->associnfo.static_essid) {
 | |
| 		data->essid.length = sm->associnfo.req_essid.len;
 | |
| 		data->essid.flags = 1;  /* active */
 | |
| 		memcpy(extra, sm->associnfo.req_essid.data, sm->associnfo.req_essid.len);
 | |
| 	}
 | |
| 	
 | |
| 	/* If we're associating/associated, return that */
 | |
| 	if (sm->associnfo.associated || sm->associnfo.associating) {
 | |
| 		data->essid.length = sm->associnfo.associate_essid.len;
 | |
| 		data->essid.flags = 1;  /* active */
 | |
| 		memcpy(extra, sm->associnfo.associate_essid.data, sm->associnfo.associate_essid.len);
 | |
| 	}
 | |
| 	mutex_unlock(&sm->associnfo.mutex);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_essid);
 | |
| 
 | |
| int
 | |
| ieee80211softmac_wx_set_rate(struct net_device *net_dev,
 | |
| 			     struct iw_request_info *info,
 | |
| 			     union iwreq_data *data,
 | |
| 			     char *extra)
 | |
| {
 | |
| 	struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
 | |
| 	struct ieee80211_device *ieee = mac->ieee;
 | |
| 	unsigned long flags;
 | |
| 	s32 in_rate = data->bitrate.value;
 | |
| 	u8 rate;
 | |
| 	int is_ofdm = 0;
 | |
| 	int err = -EINVAL;
 | |
| 
 | |
| 	if (in_rate == -1) {
 | |
| 		/* FIXME: We don't correctly handle backing down to lower
 | |
| 		   rates, so 801.11g devices start off at 11M for now. People
 | |
| 		   can manually change it if they really need to, but 11M is
 | |
| 		   more reliable. Note similar logic in
 | |
| 		   ieee80211softmac_wx_set_rate() */	 
 | |
| 		if (ieee->modulation & IEEE80211_CCK_MODULATION)
 | |
| 			in_rate = 11000000;
 | |
| 		else
 | |
| 			in_rate = 54000000;
 | |
| 	}
 | |
| 
 | |
| 	switch (in_rate) {
 | |
| 	case 1000000:
 | |
| 		rate = IEEE80211_CCK_RATE_1MB;
 | |
| 		break;
 | |
| 	case 2000000:
 | |
| 		rate = IEEE80211_CCK_RATE_2MB;
 | |
| 		break;
 | |
| 	case 5500000:
 | |
| 		rate = IEEE80211_CCK_RATE_5MB;
 | |
| 		break;
 | |
| 	case 11000000:
 | |
| 		rate = IEEE80211_CCK_RATE_11MB;
 | |
| 		break;
 | |
| 	case 6000000:
 | |
| 		rate = IEEE80211_OFDM_RATE_6MB;
 | |
| 		is_ofdm = 1;
 | |
| 		break;
 | |
| 	case 9000000:
 | |
| 		rate = IEEE80211_OFDM_RATE_9MB;
 | |
| 		is_ofdm = 1;
 | |
| 		break;
 | |
| 	case 12000000:
 | |
| 		rate = IEEE80211_OFDM_RATE_12MB;
 | |
| 		is_ofdm = 1;
 | |
| 		break;
 | |
| 	case 18000000:
 | |
| 		rate = IEEE80211_OFDM_RATE_18MB;
 | |
| 		is_ofdm = 1;
 | |
| 		break;
 | |
| 	case 24000000:
 | |
| 		rate = IEEE80211_OFDM_RATE_24MB;
 | |
| 		is_ofdm = 1;
 | |
| 		break;
 | |
| 	case 36000000:
 | |
| 		rate = IEEE80211_OFDM_RATE_36MB;
 | |
| 		is_ofdm = 1;
 | |
| 		break;
 | |
| 	case 48000000:
 | |
| 		rate = IEEE80211_OFDM_RATE_48MB;
 | |
| 		is_ofdm = 1;
 | |
| 		break;
 | |
| 	case 54000000:
 | |
| 		rate = IEEE80211_OFDM_RATE_54MB;
 | |
| 		is_ofdm = 1;
 | |
| 		break;
 | |
| 	default:
 | |
| 		goto out;
 | |
| 	}
 | |
| 
 | |
| 	spin_lock_irqsave(&mac->lock, flags);
 | |
| 
 | |
| 	/* Check if correct modulation for this PHY. */
 | |
| 	if (is_ofdm && !(ieee->modulation & IEEE80211_OFDM_MODULATION))
 | |
| 		goto out_unlock;
 | |
| 
 | |
| 	mac->txrates.user_rate = rate;
 | |
| 	ieee80211softmac_recalc_txrates(mac);
 | |
| 	err = 0;
 | |
| 
 | |
| out_unlock:	
 | |
| 	spin_unlock_irqrestore(&mac->lock, flags);
 | |
| out:
 | |
| 	return err;
 | |
| }
 | |
| EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_rate);
 | |
| 
 | |
| int
 | |
| ieee80211softmac_wx_get_rate(struct net_device *net_dev,
 | |
| 			     struct iw_request_info *info,
 | |
| 			     union iwreq_data *data,
 | |
| 			     char *extra)
 | |
| {
 | |
| 	struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
 | |
| 	unsigned long flags;
 | |
| 	int err = -EINVAL;
 | |
| 
 | |
| 	spin_lock_irqsave(&mac->lock, flags);
 | |
| 
 | |
| 	if (unlikely(!mac->running)) {
 | |
| 		err = -ENODEV;
 | |
| 		goto out_unlock;
 | |
| 	}
 | |
| 
 | |
| 	switch (mac->txrates.default_rate) {
 | |
| 	case IEEE80211_CCK_RATE_1MB:
 | |
| 		data->bitrate.value = 1000000;
 | |
| 		break;
 | |
| 	case IEEE80211_CCK_RATE_2MB:
 | |
| 		data->bitrate.value = 2000000;
 | |
| 		break;
 | |
| 	case IEEE80211_CCK_RATE_5MB:
 | |
| 		data->bitrate.value = 5500000;
 | |
| 		break;
 | |
| 	case IEEE80211_CCK_RATE_11MB:
 | |
| 		data->bitrate.value = 11000000;
 | |
| 		break;
 | |
| 	case IEEE80211_OFDM_RATE_6MB:
 | |
| 		data->bitrate.value = 6000000;
 | |
| 		break;
 | |
| 	case IEEE80211_OFDM_RATE_9MB:
 | |
| 		data->bitrate.value = 9000000;
 | |
| 		break;
 | |
| 	case IEEE80211_OFDM_RATE_12MB:
 | |
| 		data->bitrate.value = 12000000;
 | |
| 		break;
 | |
| 	case IEEE80211_OFDM_RATE_18MB:
 | |
| 		data->bitrate.value = 18000000;
 | |
| 		break;
 | |
| 	case IEEE80211_OFDM_RATE_24MB:
 | |
| 		data->bitrate.value = 24000000;
 | |
| 		break;
 | |
| 	case IEEE80211_OFDM_RATE_36MB:
 | |
| 		data->bitrate.value = 36000000;
 | |
| 		break;
 | |
| 	case IEEE80211_OFDM_RATE_48MB:
 | |
| 		data->bitrate.value = 48000000;
 | |
| 		break;
 | |
| 	case IEEE80211_OFDM_RATE_54MB:
 | |
| 		data->bitrate.value = 54000000;
 | |
| 		break;
 | |
| 	default:
 | |
| 		assert(0);
 | |
| 		goto out_unlock;
 | |
| 	}
 | |
| 	err = 0;
 | |
| out_unlock:
 | |
| 	spin_unlock_irqrestore(&mac->lock, flags);
 | |
| 
 | |
| 	return err;
 | |
| }
 | |
| EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_rate);
 | |
| 
 | |
| int
 | |
| ieee80211softmac_wx_get_wap(struct net_device *net_dev,
 | |
| 			    struct iw_request_info *info,
 | |
| 			    union iwreq_data *data,
 | |
| 			    char *extra)
 | |
| {
 | |
| 	struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
 | |
| 	int err = 0;
 | |
| 
 | |
| 	mutex_lock(&mac->associnfo.mutex);
 | |
| 	if (mac->associnfo.bssvalid)
 | |
| 		memcpy(data->ap_addr.sa_data, mac->associnfo.bssid, ETH_ALEN);
 | |
| 	else
 | |
| 		memset(data->ap_addr.sa_data, 0xff, ETH_ALEN);
 | |
| 	data->ap_addr.sa_family = ARPHRD_ETHER;
 | |
| 	mutex_unlock(&mac->associnfo.mutex);
 | |
| 
 | |
| 	return err;
 | |
| }
 | |
| EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_wap);
 | |
| 
 | |
| int
 | |
| ieee80211softmac_wx_set_wap(struct net_device *net_dev,
 | |
| 			    struct iw_request_info *info,
 | |
| 			    union iwreq_data *data,
 | |
| 			    char *extra)
 | |
| {
 | |
| 	struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
 | |
| 
 | |
| 	/* sanity check */
 | |
| 	if (data->ap_addr.sa_family != ARPHRD_ETHER) {
 | |
| 		return -EINVAL;
 | |
| 	}
 | |
| 
 | |
| 	mutex_lock(&mac->associnfo.mutex);
 | |
| 	if (is_broadcast_ether_addr(data->ap_addr.sa_data)) {
 | |
| 		/* the bssid we have is not to be fixed any longer,
 | |
| 		 * and we should reassociate to the best AP. */
 | |
| 		mac->associnfo.bssfixed = 0;
 | |
| 		/* force reassociation */
 | |
| 		mac->associnfo.bssvalid = 0;
 | |
| 		if (mac->associnfo.associated)
 | |
| 			schedule_delayed_work(&mac->associnfo.work, 0);
 | |
| 	} else if (is_zero_ether_addr(data->ap_addr.sa_data)) {
 | |
| 		/* the bssid we have is no longer fixed */
 | |
| 		mac->associnfo.bssfixed = 0;
 | |
|         } else {
 | |
| 		if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) {
 | |
| 			if (mac->associnfo.associating || mac->associnfo.associated) {
 | |
| 			/* bssid unchanged and associated or associating - just return */
 | |
| 				goto out;
 | |
| 			}
 | |
| 		} else {
 | |
| 			/* copy new value in data->ap_addr.sa_data to bssid */
 | |
| 			memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN);
 | |
| 		}
 | |
| 		/* tell the other code that this bssid should be used no matter what */
 | |
| 		mac->associnfo.bssfixed = 1;
 | |
| 		/* queue associate if new bssid or (old one again and not associated) */
 | |
| 		schedule_delayed_work(&mac->associnfo.work, 0);
 | |
|         }
 | |
| 
 | |
|  out:
 | |
| 	mutex_unlock(&mac->associnfo.mutex);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_wap);
 | |
| 
 | |
| int
 | |
| ieee80211softmac_wx_set_genie(struct net_device *dev,
 | |
| 			      struct iw_request_info *info,
 | |
| 			      union iwreq_data *wrqu,
 | |
| 			      char *extra)
 | |
| {
 | |
| 	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
 | |
| 	unsigned long flags;
 | |
| 	int err = 0;
 | |
| 	char *buf;
 | |
| 	int i;
 | |
| 
 | |
| 	mutex_lock(&mac->associnfo.mutex);
 | |
| 	spin_lock_irqsave(&mac->lock, flags);
 | |
| 	/* bleh. shouldn't be locked for that kmalloc... */
 | |
| 
 | |
| 	if (wrqu->data.length) {
 | |
| 		if ((wrqu->data.length < 2) || (extra[1]+2 != wrqu->data.length)) {
 | |
| 			/* this is an IE, so the length must be
 | |
| 			 * correct. Is it possible though that
 | |
| 			 * more than one IE is passed in?
 | |
| 			 */
 | |
| 			err = -EINVAL;
 | |
| 			goto out;
 | |
| 		}
 | |
| 		if (mac->wpa.IEbuflen <= wrqu->data.length) {
 | |
| 			buf = kmalloc(wrqu->data.length, GFP_ATOMIC);
 | |
| 			if (!buf) {
 | |
| 				err = -ENOMEM;
 | |
| 				goto out;
 | |
| 			}
 | |
| 			kfree(mac->wpa.IE);
 | |
| 			mac->wpa.IE = buf;
 | |
| 			mac->wpa.IEbuflen = wrqu->data.length;
 | |
| 		}
 | |
| 		memcpy(mac->wpa.IE, extra, wrqu->data.length);
 | |
| 		dprintk(KERN_INFO PFX "generic IE set to ");
 | |
| 		for (i=0;i<wrqu->data.length;i++)
 | |
| 			dprintk("%.2x", (u8)mac->wpa.IE[i]);
 | |
| 		dprintk("\n");
 | |
| 		mac->wpa.IElen = wrqu->data.length;
 | |
| 	} else {
 | |
| 		kfree(mac->wpa.IE);
 | |
| 		mac->wpa.IE = NULL;
 | |
| 		mac->wpa.IElen = 0;
 | |
| 		mac->wpa.IEbuflen = 0;
 | |
| 	}
 | |
| 
 | |
|  out:	
 | |
| 	spin_unlock_irqrestore(&mac->lock, flags);
 | |
| 	mutex_unlock(&mac->associnfo.mutex);
 | |
| 
 | |
| 	return err;
 | |
| }
 | |
| EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_genie);
 | |
| 
 | |
| int
 | |
| ieee80211softmac_wx_get_genie(struct net_device *dev,
 | |
| 			      struct iw_request_info *info,
 | |
| 			      union iwreq_data *wrqu,
 | |
| 			      char *extra)
 | |
| {
 | |
| 	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
 | |
| 	unsigned long flags;
 | |
| 	int err = 0;
 | |
| 	int space = wrqu->data.length;
 | |
| 
 | |
| 	mutex_lock(&mac->associnfo.mutex);
 | |
| 	spin_lock_irqsave(&mac->lock, flags);
 | |
| 	
 | |
| 	wrqu->data.length = 0;
 | |
| 	
 | |
| 	if (mac->wpa.IE && mac->wpa.IElen) {
 | |
| 		wrqu->data.length = mac->wpa.IElen;
 | |
| 		if (mac->wpa.IElen <= space)
 | |
| 			memcpy(extra, mac->wpa.IE, mac->wpa.IElen);
 | |
| 		else
 | |
| 			err = -E2BIG;
 | |
| 	}
 | |
| 	spin_unlock_irqrestore(&mac->lock, flags);
 | |
| 	mutex_unlock(&mac->associnfo.mutex);
 | |
| 
 | |
| 	return err;
 | |
| }
 | |
| EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_genie);
 | |
| 
 | |
| int
 | |
| ieee80211softmac_wx_set_mlme(struct net_device *dev,
 | |
| 			     struct iw_request_info *info,
 | |
| 			     union iwreq_data *wrqu,
 | |
| 			     char *extra)
 | |
| {
 | |
| 	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
 | |
| 	struct iw_mlme *mlme = (struct iw_mlme *)extra;
 | |
| 	u16 reason = cpu_to_le16(mlme->reason_code);
 | |
| 	struct ieee80211softmac_network *net;
 | |
| 	int err = -EINVAL;
 | |
| 
 | |
| 	mutex_lock(&mac->associnfo.mutex);
 | |
| 
 | |
| 	if (memcmp(mac->associnfo.bssid, mlme->addr.sa_data, ETH_ALEN)) {
 | |
| 		printk(KERN_DEBUG PFX "wx_set_mlme: requested operation on net we don't use\n");
 | |
| 		goto out;
 | |
| 	}
 | |
| 
 | |
| 	switch (mlme->cmd) {
 | |
| 	case IW_MLME_DEAUTH:
 | |
| 		net = ieee80211softmac_get_network_by_bssid_locked(mac, mlme->addr.sa_data);
 | |
| 		if (!net) {
 | |
| 			printk(KERN_DEBUG PFX "wx_set_mlme: we should know the net here...\n");
 | |
| 			goto out;
 | |
| 		}
 | |
| 		err =  ieee80211softmac_deauth_req(mac, net, reason);
 | |
| 		goto out;
 | |
| 	case IW_MLME_DISASSOC:
 | |
| 		ieee80211softmac_send_disassoc_req(mac, reason);
 | |
| 		mac->associnfo.associated = 0;
 | |
| 		mac->associnfo.associating = 0;
 | |
| 		err = 0;
 | |
| 		goto out;
 | |
| 	default:
 | |
| 		err = -EOPNOTSUPP;
 | |
| 	}
 | |
| 
 | |
| out:
 | |
| 	mutex_unlock(&mac->associnfo.mutex);
 | |
| 
 | |
| 	return err;
 | |
| }
 | |
| EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_mlme);
 |