Exemple #1
0
static int ieee80211_ioctl_siwfrag(struct net_device *dev,
                                   struct iw_request_info *info,
                                   struct iw_param *frag, char *extra)
{
    struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);

    if (frag->disabled)
        local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
    else if (frag->value < 256 ||
             frag->value > IEEE80211_MAX_FRAG_THRESHOLD)
        return -EINVAL;
    else {
        /* Fragment length must be even, so strip LSB. */
        local->fragmentation_threshold = frag->value & ~0x1;
    }

    /* If the wlan card performs fragmentation in hardware/firmware,
     * configure it here */

    if (local->ops->set_frag_threshold)
        local->ops->set_frag_threshold(
            local_to_hw(local),
            local->fragmentation_threshold);

    return 0;
}
Exemple #2
0
static int ieee80211_ioctl_siwrts(struct net_device *dev,
				  struct iw_request_info *info,
				  struct iw_param *rts, char *extra)
{
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);

	if (rts->disabled)
		local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
	else if (!rts->fixed)
		/* if the rts value is not fixed, then take default */
		local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
	else if (rts->value < 0 || rts->value > IEEE80211_MAX_RTS_THRESHOLD)
		return -EINVAL;
	else
		local->rts_threshold = rts->value;

	/* If the wlan card performs RTS/CTS in hardware/firmware,
	 * configure it here */

	if (local->ops->set_rts_threshold)
		local->ops->set_rts_threshold(local_to_hw(local),
					     local->rts_threshold);

	return 0;
}
Exemple #3
0
static int ieee80211_ioctl_siwretry(struct net_device *dev,
                                    struct iw_request_info *info,
                                    struct iw_param *retry, char *extra)
{
    struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);

    if (retry->disabled ||
            (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
        return -EINVAL;

    if (retry->flags & IW_RETRY_MAX)
        local->long_retry_limit = retry->value;
    else if (retry->flags & IW_RETRY_MIN)
        local->short_retry_limit = retry->value;
    else {
        local->long_retry_limit = retry->value;
        local->short_retry_limit = retry->value;
    }

    if (local->ops->set_retry_limit) {
        return local->ops->set_retry_limit(
                   local_to_hw(local),
                   local->short_retry_limit,
                   local->long_retry_limit);
    }

    return 0;
}
Exemple #4
0
static int ieee80211_ioctl_giwrate(struct net_device *dev,
                                   struct iw_request_info *info,
                                   struct iw_param *rate, char *extra)
{
    struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
    struct sta_info *sta;
    struct ieee80211_sub_if_data *sdata;
    struct ieee80211_supported_band *sband;

    sdata = IEEE80211_DEV_TO_SUB_IF(dev);

    if (sdata->vif.type == IEEE80211_IF_TYPE_STA)
        sta = sta_info_get(local, sdata->u.sta.bssid);
    else
        return -EOPNOTSUPP;
    if (!sta)
        return -ENODEV;

    sband = local->hw.wiphy->bands[local->hw.conf.channel->band];

    if (sta->txrate_idx < sband->n_bitrates)
        rate->value = sband->bitrates[sta->txrate_idx].bitrate;
    else
        rate->value = 0;
    rate->value *= 100000;

    return 0;
}
Exemple #5
0
/* Get wireless statistics.  Called by /proc/net/wireless and by SIOCGIWSTATS */
static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev)
{
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
	struct iw_statistics *wstats = &local->wstats;
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	struct sta_info *sta = NULL;

	rcu_read_lock();

	if (sdata->vif.type == NL80211_IFTYPE_STATION ||
	    sdata->vif.type == NL80211_IFTYPE_ADHOC)
		sta = sta_info_get(local, sdata->u.sta.bssid);
	if (!sta) {
		wstats->discard.fragment = 0;
		wstats->discard.misc = 0;
		wstats->qual.qual = 0;
		wstats->qual.level = 0;
		wstats->qual.noise = 0;
		wstats->qual.updated = IW_QUAL_ALL_INVALID;
	} else {
		wstats->qual.level = sta->last_signal;
		wstats->qual.qual = sta->last_qual;
		wstats->qual.noise = sta->last_noise;
		wstats->qual.updated = local->wstats_flags;
	}

	rcu_read_unlock();

	return wstats;
}
Exemple #6
0
static int ieee80211_ioctl_giwrate(struct net_device *dev,
				  struct iw_request_info *info,
				  struct iw_param *rate, char *extra)
{
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
	struct sta_info *sta;
	struct ieee80211_sub_if_data *sdata;
	struct ieee80211_supported_band *sband;

	sdata = IEEE80211_DEV_TO_SUB_IF(dev);

	if (sdata->vif.type != NL80211_IFTYPE_STATION)
		return -EOPNOTSUPP;

	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];

	rcu_read_lock();

	sta = sta_info_get(local, sdata->u.sta.bssid);

	if (sta && !(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS))
		rate->value = sband->bitrates[sta->last_tx_rate.idx].bitrate;
	else
		rate->value = 0;

	rcu_read_unlock();

	if (!sta)
		return -ENODEV;

	rate->value *= 100000;

	return 0;
}
Exemple #7
0
static int ieee80211_ioctl_siwfreq(struct net_device *dev,
                                   struct iw_request_info *info,
                                   struct iw_freq *freq, char *extra)
{
    struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
    struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);

    if (sdata->vif.type == IEEE80211_IF_TYPE_STA)
        sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL;

    /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */
    if (freq->e == 0) {
        if (freq->m < 0) {
            if (sdata->vif.type == IEEE80211_IF_TYPE_STA)
                sdata->u.sta.flags |=
                    IEEE80211_STA_AUTO_CHANNEL_SEL;
            return 0;
        } else
            return ieee80211_set_freq(local,
                                      ieee80211_channel_to_frequency(freq->m));
    } else {
        int i, div = 1000000;
        for (i = 0; i < freq->e; i++)
            div /= 10;
        if (div > 0)
            return ieee80211_set_freq(local, freq->m / div);
        else
            return -EINVAL;
    }
}
Exemple #8
0
static int ieee80211_ioctl_siwpower(struct net_device *dev,
				    struct iw_request_info *info,
				    struct iw_param *wrq,
				    char *extra)
{
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
	struct ieee80211_conf *conf = &local->hw.conf;
	int ret = 0, timeout = 0;
	bool ps;

	if (sdata->vif.type != NL80211_IFTYPE_STATION)
		return -EINVAL;

	if (wrq->disabled) {
		ps = false;
		timeout = 0;
		goto set;
	}

	switch (wrq->flags & IW_POWER_MODE) {
	case IW_POWER_ON:       /* If not specified */
	case IW_POWER_MODE:     /* If set all mask */
	case IW_POWER_ALL_R:    /* If explicitely state all */
		ps = true;
		break;
	default:                /* Otherwise we ignore */
		break;
	}

	if (wrq->flags & IW_POWER_TIMEOUT)
		timeout = wrq->value / 1000;

set:
	if (ps == local->powersave && timeout == local->dynamic_ps_timeout)
		return ret;

	local->powersave = ps;
	local->dynamic_ps_timeout = timeout;

	if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) {
		if (!(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS) &&
		    local->dynamic_ps_timeout > 0)
			mod_timer(&local->dynamic_ps_timer, jiffies +
				  msecs_to_jiffies(local->dynamic_ps_timeout));
		else {
			if (local->powersave)
				conf->flags |= IEEE80211_CONF_PS;
			else
				conf->flags &= ~IEEE80211_CONF_PS;
		}
		ret = ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
	}

	return ret;
}
Exemple #9
0
static int ieee80211_ioctl_giwfreq(struct net_device *dev,
				   struct iw_request_info *info,
				   struct iw_freq *freq, char *extra)
{
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);

	freq->m = local->hw.conf.channel->center_freq;
	freq->e = 6;

	return 0;
}
Exemple #10
0
static int ieee80211_ioctl_giwpower(struct net_device *dev,
				    struct iw_request_info *info,
				    union iwreq_data *wrqu,
				    char *extra)
{
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);

	wrqu->power.disabled = !local->powersave;

	return 0;
}
Exemple #11
0
static int ieee80211_ioctl_giwrts(struct net_device *dev,
				  struct iw_request_info *info,
				  struct iw_param *rts, char *extra)
{
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);

	rts->value = local->rts_threshold;
	rts->disabled = (rts->value >= IEEE80211_MAX_RTS_THRESHOLD);
	rts->fixed = 1;

	return 0;
}
Exemple #12
0
static int ieee80211_ioctl_giwfrag(struct net_device *dev,
				   struct iw_request_info *info,
				   struct iw_param *frag, char *extra)
{
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);

	frag->value = local->fragmentation_threshold;
	frag->disabled = (frag->value >= IEEE80211_MAX_RTS_THRESHOLD);
	frag->fixed = 1;

	return 0;
}
Exemple #13
0
static int ieee80211_ioctl_giwtxpower(struct net_device *dev,
				   struct iw_request_info *info,
				   union iwreq_data *data, char *extra)
{
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);

	data->txpower.fixed = 1;
	data->txpower.disabled = !(local->hw.conf.radio_enabled);
	data->txpower.value = local->hw.conf.power_level;
	data->txpower.flags = IW_TXPOW_DBM;

	return 0;
}
static struct ieee80211_rate *
rate_control_simple_get_rate(void *priv, struct net_device *dev,
			     struct sk_buff *skb,
			     struct rate_control_extra *extra)
{
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
	struct ieee80211_sub_if_data *sdata;
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
	struct ieee80211_hw_mode *mode = extra->mode;
	struct sta_info *sta;
	int rateidx, nonerp_idx;
	u16 fc;

	memset(extra, 0, sizeof(*extra));

	fc = le16_to_cpu(hdr->frame_control);
	if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
	    (hdr->addr1[0] & 0x01)) {
		/* Send management frames and broadcast/multicast data using
		 * lowest rate. */
		/* TODO: this could probably be improved.. */
		return rate_control_lowest_rate(local, mode);
	}

	sta = sta_info_get(local, hdr->addr1);

	if (!sta)
		return rate_control_lowest_rate(local, mode);

	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	if (sdata->bss && sdata->bss->force_unicast_rateidx > -1)
		sta->txrate = sdata->bss->force_unicast_rateidx;

	rateidx = sta->txrate;

	if (rateidx >= mode->num_rates)
		rateidx = mode->num_rates - 1;

	sta->last_txrate = rateidx;
	nonerp_idx = rateidx;
	while (nonerp_idx > 0 &&
	       ((mode->rates[nonerp_idx].flags & IEEE80211_RATE_ERP) ||
		!(mode->rates[nonerp_idx].flags & IEEE80211_RATE_SUPPORTED) ||
		!(sta->supp_rates & BIT(nonerp_idx))))
		nonerp_idx--;
	extra->nonerp = &mode->rates[nonerp_idx];

	sta_info_put(sta);

	return &mode->rates[rateidx];
}
Exemple #15
0
struct ath6kl *ath6kl_core_alloc(struct device *sdev)
{
	struct net_device *dev;
	struct ath6kl *ar;
	struct wireless_dev *wdev;

	wdev = ath6kl_cfg80211_init(sdev);
	if (!wdev) {
		ath6kl_err("ath6kl_cfg80211_init failed\n");
		return NULL;
	}

	ar = wdev_priv(wdev);
	ar->dev = sdev;
	ar->wdev = wdev;
	wdev->iftype = NL80211_IFTYPE_STATION;

	dev = alloc_netdev(0, "wlan%d", ether_setup);
	if (!dev) {
		ath6kl_err("no memory for network device instance\n");
		ath6kl_cfg80211_deinit(ar);
		return NULL;
	}

	dev->ieee80211_ptr = wdev;
	SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy));
	wdev->netdev = dev;
	ar->sme_state = SME_DISCONNECTED;
	ar->auto_auth_stage = AUTH_IDLE;

	init_netdev(dev);

	ar->net_dev = dev;
	set_bit(WLAN_ENABLED, &ar->flag);

	ar->wlan_pwr_state = WLAN_POWER_STATE_ON;

	spin_lock_init(&ar->lock);

	ath6kl_init_control_info(ar);
	init_waitqueue_head(&ar->event_wq);
	sema_init(&ar->sem, 1);
	clear_bit(DESTROY_IN_PROGRESS, &ar->flag);

	INIT_LIST_HEAD(&ar->amsdu_rx_buffer_queue);

	setup_timer(&ar->disconnect_timer, disconnect_timer_handler,
		    (unsigned long) dev);

	return ar;
}
Exemple #16
0
static void rate_control_pid_get_rate(void *priv, struct net_device *dev,
				      struct ieee80211_supported_band *sband,
				      struct sk_buff *skb,
				      struct rate_selection *sel)
{
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
	struct ieee80211_sub_if_data *sdata;
	struct sta_info *sta;
	int rateidx;
	u16 fc;

	rcu_read_lock();

	sta = sta_info_get(local, hdr->addr1);

	/* Send management frames and broadcast/multicast data using lowest
	 * rate. */
	fc = le16_to_cpu(hdr->frame_control);
	if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
	    is_multicast_ether_addr(hdr->addr1) || !sta) {
		sel->rate = rate_lowest(local, sband, sta);
		rcu_read_unlock();
		return;
	}

	/* If a forced rate is in effect, select it. */
	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	if (sdata->bss && sdata->bss->force_unicast_rateidx > -1)
		sta->txrate_idx = sdata->bss->force_unicast_rateidx;

	rateidx = sta->txrate_idx;

	if (rateidx >= sband->n_bitrates)
		rateidx = sband->n_bitrates - 1;

	sta->last_txrate_idx = rateidx;

	rcu_read_unlock();

	sel->rate = &sband->bitrates[rateidx];

#ifdef CONFIG_MAC80211_DEBUGFS
	rate_control_pid_event_tx_rate(
		&((struct rc_pid_sta_info *) sta->rate_ctrl_priv)->events,
		rateidx, sband->bitrates[rateidx].bitrate);
#endif
}
Exemple #17
0
static int ieee80211_ioctl_siwtxpower(struct net_device *dev,
                                      struct iw_request_info *info,
                                      union iwreq_data *data, char *extra)
{
    struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
    bool need_reconfig = 0;
    int new_power_level;

    if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
        return -EINVAL;
    if (data->txpower.flags & IW_TXPOW_RANGE)
        return -EINVAL;

    if (data->txpower.fixed) {
        new_power_level = data->txpower.value;
    } else {
        /*
         * Automatic power level. Use maximum power for the current
         * channel. Should be part of rate control.
         */
        struct ieee80211_channel* chan = local->hw.conf.channel;
        if (!chan)
            return -EINVAL;

        new_power_level = chan->max_power;
    }

    if (local->hw.conf.power_level != new_power_level) {
        local->hw.conf.power_level = new_power_level;
        need_reconfig = 1;
    }

    if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) {
        local->hw.conf.radio_enabled = !(data->txpower.disabled);
        need_reconfig = 1;
        ieee80211_led_radio(local, local->hw.conf.radio_enabled);
    }

    if (need_reconfig) {
        ieee80211_hw_config(local);
        /* The return value of hw_config is not of big interest here,
         * as it doesn't say that it failed because of _this_ config
         * change or something else. Ignore it. */
    }

    return 0;
}
Exemple #18
0
static int ieee80211_ioctl_giwscan(struct net_device *dev,
                                   struct iw_request_info *info,
                                   struct iw_point *data, char *extra)
{
    int res;
    struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);

    if (local->sta_sw_scanning || local->sta_hw_scanning)
        return -EAGAIN;

    res = ieee80211_sta_scan_results(dev, extra, data->length);
    if (res >= 0) {
        data->length = res;
        return 0;
    }
    data->length = 0;
    return res;
}
Exemple #19
0
static int ieee80211_ioctl_siwfrag(struct net_device *dev,
				   struct iw_request_info *info,
				   struct iw_param *frag, char *extra)
{
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);

	if (frag->disabled)
		local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
	else if (!frag->fixed)
		local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
	else if (frag->value < 256 ||
		 frag->value > IEEE80211_MAX_FRAG_THRESHOLD)
		return -EINVAL;
	else {
		/* Fragment length must be even, so strip LSB. */
		local->fragmentation_threshold = frag->value & ~0x1;
	}

	return 0;
}
Exemple #20
0
/**
 * mesh_send_path error - Sends a PERR mesh management frame
 *
 * @dst: broken destination
 * @dst_dsn: dsn of the broken destination
 * @ra: node this frame is addressed to
 */
int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra,
		struct net_device *dev)
{
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
	struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
	struct ieee80211_mgmt *mgmt;
	u8 *pos;
	int ie_len;

	if (!skb)
		return -1;
	skb_reserve(skb, local->hw.extra_tx_headroom);
	/* 25 is the size of the common mgmt part (24) plus the size of the
	 * common action part (1)
	 */
	mgmt = (struct ieee80211_mgmt *)
		skb_put(skb, 25 + sizeof(mgmt->u.action.u.mesh_action));
	memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.mesh_action));
	mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
					   IEEE80211_STYPE_ACTION);

	memcpy(mgmt->da, ra, ETH_ALEN);
	memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
	/* BSSID is left zeroed, wildcard value */
	mgmt->u.action.category = MESH_PATH_SEL_CATEGORY;
	mgmt->u.action.u.mesh_action.action_code = MPATH_PERR;
	ie_len = 12;
	pos = skb_put(skb, 2 + ie_len);
	*pos++ = WLAN_EID_PERR;
	*pos++ = ie_len;
	/* mode flags, reserved */
	*pos++ = 0;
	/* number of destinations */
	*pos++ = 1;
	memcpy(pos, dst, ETH_ALEN);
	pos += ETH_ALEN;
	memcpy(pos, &dst_dsn, 4);

	ieee80211_sta_tx(dev, skb, 0);
	return 0;
}
Exemple #21
0
static int ieee80211_ioctl_giwscan(struct net_device *dev,
				   struct iw_request_info *info,
				   struct iw_point *data, char *extra)
{
	int res;
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
	struct ieee80211_sub_if_data *sdata;

	sdata = IEEE80211_DEV_TO_SUB_IF(dev);

	if (local->sw_scanning || local->hw_scanning)
		return -EAGAIN;

	res = ieee80211_scan_results(local, info, extra, data->length);
	if (res >= 0) {
		data->length = res;
		return 0;
	}
	data->length = 0;
	return res;
}
Exemple #22
0
static int ieee80211_ioctl_siwrate(struct net_device *dev,
                                   struct iw_request_info *info,
                                   struct iw_param *rate, char *extra)
{
    struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
    int i, err = -EINVAL;
    u32 target_rate = rate->value / 100000;
    struct ieee80211_sub_if_data *sdata;
    struct ieee80211_supported_band *sband;

    sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    if (!sdata->bss)
        return -ENODEV;

    sband = local->hw.wiphy->bands[local->hw.conf.channel->band];

    /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates
     * target_rate = X, rate->fixed = 1 means only rate X
     * target_rate = X, rate->fixed = 0 means all rates <= X */
    sdata->bss->max_ratectrl_rateidx = -1;
    sdata->bss->force_unicast_rateidx = -1;
    if (rate->value < 0)
        return 0;

    for (i=0; i< sband->n_bitrates; i++) {
        struct ieee80211_rate *brate = &sband->bitrates[i];
        int this_rate = brate->bitrate;

        if (target_rate == this_rate) {
            sdata->bss->max_ratectrl_rateidx = i;
            if (rate->fixed)
                sdata->bss->force_unicast_rateidx = i;
            err = 0;
            break;
        }
    }
    return err;
}
Exemple #23
0
static int ieee80211_ioctl_giwretry(struct net_device *dev,
                                    struct iw_request_info *info,
                                    struct iw_param *retry, char *extra)
{
    struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);

    retry->disabled = 0;
    if (retry->flags == 0 || retry->flags & IW_RETRY_MIN) {
        /* first return min value, iwconfig will ask max value
         * later if needed */
        retry->flags |= IW_RETRY_LIMIT;
        retry->value = local->short_retry_limit;
        if (local->long_retry_limit != local->short_retry_limit)
            retry->flags |= IW_RETRY_MIN;
        return 0;
    }
    if (retry->flags & IW_RETRY_MAX) {
        retry->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
        retry->value = local->long_retry_limit;
    }

    return 0;
}
Exemple #24
0
static int ieee80211_ioctl_siwretry(struct net_device *dev,
				    struct iw_request_info *info,
				    struct iw_param *retry, char *extra)
{
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);

	if (retry->disabled ||
	    (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
		return -EINVAL;

	if (retry->flags & IW_RETRY_MAX) {
		local->hw.conf.long_frame_max_tx_count = retry->value;
	} else if (retry->flags & IW_RETRY_MIN) {
		local->hw.conf.short_frame_max_tx_count = retry->value;
	} else {
		local->hw.conf.long_frame_max_tx_count = retry->value;
		local->hw.conf.short_frame_max_tx_count = retry->value;
	}

	ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS);

	return 0;
}
Exemple #25
0
static int ieee80211_ioctl_siwtxpower(struct net_device *dev,
				      struct iw_request_info *info,
				      union iwreq_data *data, char *extra)
{
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
	struct ieee80211_channel* chan = local->hw.conf.channel;
	u32 reconf_flags = 0;
	int new_power_level;

	if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
		return -EINVAL;
	if (data->txpower.flags & IW_TXPOW_RANGE)
		return -EINVAL;
	if (!chan)
		return -EINVAL;

	if (data->txpower.fixed)
		new_power_level = min(data->txpower.value, chan->max_power);
	else /* Automatic power level setting */
		new_power_level = chan->max_power;

	if (local->hw.conf.power_level != new_power_level) {
		local->hw.conf.power_level = new_power_level;
		reconf_flags |= IEEE80211_CONF_CHANGE_POWER;
	}

	if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) {
		local->hw.conf.radio_enabled = !(data->txpower.disabled);
		reconf_flags |= IEEE80211_CONF_CHANGE_RADIO_ENABLED;
		ieee80211_led_radio(local, local->hw.conf.radio_enabled);
	}

	if (reconf_flags)
		ieee80211_hw_config(local, reconf_flags);

	return 0;
}
Exemple #26
0
/**
 * lbs_add_card - adds the card. It will probe the
 * card, allocate the lbs_priv and initialize the device.
 *
 * @card:	A pointer to card
 * @dmdev:	A pointer to &struct device
 * returns:	A pointer to &struct lbs_private structure
 */
struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
{
	struct net_device *dev;
	struct wireless_dev *wdev;
	struct lbs_private *priv = NULL;

	lbs_deb_enter(LBS_DEB_MAIN);

	/* Allocate an Ethernet device and register it */
	wdev = lbs_cfg_alloc(dmdev);
	if (IS_ERR(wdev)) {
		pr_err("cfg80211 init failed\n");
		goto done;
	}

	wdev->iftype = NL80211_IFTYPE_STATION;
	priv = wdev_priv(wdev);
	priv->wdev = wdev;

	if (lbs_init_adapter(priv)) {
		pr_err("failed to initialize adapter structure\n");
		goto err_wdev;
	}

	dev = alloc_netdev(0, "wlan%d", ether_setup);
	if (!dev) {
		dev_err(dmdev, "no memory for network device instance\n");
		goto err_adapter;
	}

	dev->ieee80211_ptr = wdev;
	dev->ml_priv = priv;
	SET_NETDEV_DEV(dev, dmdev);
	wdev->netdev = dev;
	priv->dev = dev;

 	dev->netdev_ops = &lbs_netdev_ops;
	dev->watchdog_timeo = 5 * HZ;
	dev->ethtool_ops = &lbs_ethtool_ops;
	dev->flags |= IFF_BROADCAST | IFF_MULTICAST;

	priv->card = card;

	strcpy(dev->name, "wlan%d");

	lbs_deb_thread("Starting main thread...\n");
	init_waitqueue_head(&priv->waitq);
	priv->main_thread = kthread_run(lbs_thread, dev, "lbs_main");
	if (IS_ERR(priv->main_thread)) {
		lbs_deb_thread("Error creating main thread.\n");
		goto err_ndev;
	}

	priv->work_thread = create_singlethread_workqueue("lbs_worker");
	INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker);

	priv->wol_criteria = EHS_REMOVE_WAKEUP;
	priv->wol_gpio = 0xff;
	priv->wol_gap = 20;
	priv->ehs_remove_supported = true;

	goto done;

 err_ndev:
	free_netdev(dev);

 err_adapter:
	lbs_free_adapter(priv);

 err_wdev:
	lbs_cfg_free(priv);

	priv = NULL;

done:
	lbs_deb_leave_args(LBS_DEB_MAIN, "priv %p", priv);
	return priv;
}
Exemple #27
0
static ssize_t sta_agg_status_write(struct file *file,
		const char __user *user_buf, size_t count, loff_t *ppos)
{
	struct sta_info *sta = file->private_data;
	struct net_device *dev = sta->sdata->dev;
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
	struct ieee80211_hw *hw = &local->hw;
	u8 *da = sta->addr;
	static int tid_static_tx[16] = {0, 0, 0, 0, 0, 0, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0};
	static int tid_static_rx[16] = {1, 1, 1, 1, 1, 1, 1, 1,
					1, 1, 1, 1, 1, 1, 1, 1};
	char *endp;
	char buf[32];
	int buf_size, rs;
	unsigned int tid_num;
	char state[4];

	memset(buf, 0x00, sizeof(buf));
	buf_size = min(count, (sizeof(buf)-1));
	if (copy_from_user(buf, user_buf, buf_size))
		return -EFAULT;

	tid_num = simple_strtoul(buf, &endp, 0);
	if (endp == buf)
		return -EINVAL;

	if ((tid_num >= 100) && (tid_num <= 115)) {
		/* toggle Rx aggregation command */
		tid_num = tid_num - 100;
		if (tid_static_rx[tid_num] == 1) {
			strcpy(state, "off ");
			ieee80211_sta_stop_rx_ba_session(dev, da, tid_num, 0,
					WLAN_REASON_QSTA_REQUIRE_SETUP);
			sta->ampdu_mlme.tid_state_rx[tid_num] |=
					HT_AGG_STATE_DEBUGFS_CTL;
			tid_static_rx[tid_num] = 0;
		} else {
			strcpy(state, "on ");
			sta->ampdu_mlme.tid_state_rx[tid_num] &=
					~HT_AGG_STATE_DEBUGFS_CTL;
			tid_static_rx[tid_num] = 1;
		}
		printk(KERN_DEBUG "debugfs - try switching tid %u %s\n",
				tid_num, state);
	} else if ((tid_num >= 0) && (tid_num <= 15)) {
		/* toggle Tx aggregation command */
		if (tid_static_tx[tid_num] == 0) {
			strcpy(state, "on ");
			rs =  ieee80211_start_tx_ba_session(hw, da, tid_num);
			if (rs == 0)
				tid_static_tx[tid_num] = 1;
		} else {
			strcpy(state, "off");
			rs =  ieee80211_stop_tx_ba_session(hw, da, tid_num, 1);
			if (rs == 0)
				tid_static_tx[tid_num] = 0;
		}
		printk(KERN_DEBUG "debugfs - switching tid %u %s, return=%d\n",
				tid_num, state, rs);
	}

	return count;
}
Exemple #28
0
static void rate_control_pid_tx_status(void *priv, struct net_device *dev,
				       struct sk_buff *skb,
				       struct ieee80211_tx_status *status)
{
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
	struct ieee80211_sub_if_data *sdata;
	struct rc_pid_info *pinfo = priv;
	struct sta_info *sta;
	struct rc_pid_sta_info *spinfo;
	unsigned long period;
	struct ieee80211_supported_band *sband;

	rcu_read_lock();

	sta = sta_info_get(local, hdr->addr1);
	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];

	if (!sta)
		goto unlock;

	/* Don't update the state if we're not controlling the rate. */
	sdata = sta->sdata;
	if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) {
		sta->txrate_idx = sdata->bss->max_ratectrl_rateidx;
		goto unlock;
	}

	/* Ignore all frames that were sent with a different rate than the rate
	 * we currently advise mac80211 to use. */
	if (status->control.tx_rate != &sband->bitrates[sta->txrate_idx])
		goto unlock;

	spinfo = sta->rate_ctrl_priv;
	spinfo->tx_num_xmit++;

#ifdef CONFIG_MAC80211_DEBUGFS
	rate_control_pid_event_tx_status(&spinfo->events, status);
#endif

	/* We count frames that totally failed to be transmitted as two bad
	 * frames, those that made it out but had some retries as one good and
	 * one bad frame. */
	if (status->excessive_retries) {
		spinfo->tx_num_failed += 2;
		spinfo->tx_num_xmit++;
	} else if (status->retry_count) {
		spinfo->tx_num_failed++;
		spinfo->tx_num_xmit++;
	}

	if (status->excessive_retries) {
		sta->tx_retry_failed++;
		sta->tx_num_consecutive_failures++;
		sta->tx_num_mpdu_fail++;
	} else {
		sta->tx_num_consecutive_failures = 0;
		sta->tx_num_mpdu_ok++;
	}
	sta->tx_retry_count += status->retry_count;
	sta->tx_num_mpdu_fail += status->retry_count;

	/* Update PID controller state. */
	period = (HZ * pinfo->sampling_period + 500) / 1000;
	if (!period)
		period = 1;
	if (time_after(jiffies, spinfo->last_sample + period))
		rate_control_pid_sample(pinfo, local, sta);

 unlock:
	rcu_read_unlock();
}
static inline void *ar6k_priv(struct net_device *dev)
{
	return wdev_priv(dev->ieee80211_ptr);
}
Exemple #30
0
static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
		u8 *orig_addr, __le32 orig_dsn, u8 dst_flags, u8 *dst,
		__le32 dst_dsn, u8 *da, u8 hop_count, u8 ttl, __le32 lifetime,
		__le32 metric, __le32 preq_id, struct net_device *dev)
{
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
	struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
	struct ieee80211_mgmt *mgmt;
	u8 *pos;
	int ie_len;

	if (!skb)
		return -1;
	skb_reserve(skb, local->hw.extra_tx_headroom);
	/* 25 is the size of the common mgmt part (24) plus the size of the
	 * common action part (1)
	 */
	mgmt = (struct ieee80211_mgmt *)
		skb_put(skb, 25 + sizeof(mgmt->u.action.u.mesh_action));
	memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.mesh_action));
	mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
					   IEEE80211_STYPE_ACTION);

	memcpy(mgmt->da, da, ETH_ALEN);
	memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
	/* BSSID is left zeroed, wildcard value */
	mgmt->u.action.category = MESH_PATH_SEL_CATEGORY;
	mgmt->u.action.u.mesh_action.action_code = action;

	switch (action) {
	case MPATH_PREQ:
		ie_len = 37;
		pos = skb_put(skb, 2 + ie_len);
		*pos++ = WLAN_EID_PREQ;
		break;
	case MPATH_PREP:
		ie_len = 31;
		pos = skb_put(skb, 2 + ie_len);
		*pos++ = WLAN_EID_PREP;
		break;
	default:
		kfree(skb);
		return -ENOTSUPP;
		break;
	}
	*pos++ = ie_len;
	*pos++ = flags;
	*pos++ = hop_count;
	*pos++ = ttl;
	if (action == MPATH_PREQ) {
		memcpy(pos, &preq_id, 4);
		pos += 4;
	}
	memcpy(pos, orig_addr, ETH_ALEN);
	pos += ETH_ALEN;
	memcpy(pos, &orig_dsn, 4);
	pos += 4;
	memcpy(pos, &lifetime, 4);
	pos += 4;
	memcpy(pos, &metric, 4);
	pos += 4;
	if (action == MPATH_PREQ) {
		/* destination count */
		*pos++ = 1;
		*pos++ = dst_flags;
	}
	memcpy(pos, dst, ETH_ALEN);
	pos += ETH_ALEN;
	memcpy(pos, &dst_dsn, 4);

	ieee80211_sta_tx(dev, skb, 0);
	return 0;
}