Example #1
0
static int p54_config(struct ieee80211_hw *dev, u32 changed)
{
	int ret = 0;
	struct p54_common *priv = dev->priv;
	struct ieee80211_conf *conf = &dev->conf;

	mutex_lock(&priv->conf_mutex);
	if (changed & IEEE80211_CONF_CHANGE_POWER)
		priv->output_power = conf->power_level << 2;
	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
		struct ieee80211_channel *oldchan;
		WARN_ON(p54_wait_for_stats(dev));
		oldchan = priv->curchan;
		priv->curchan = NULL;
		ret = p54_scan(priv, P54_SCAN_EXIT, 0);
		if (ret) {
			priv->curchan = oldchan;
			goto out;
		}
		/*
		 * TODO: Use the LM_SCAN_TRAP to determine the current
		 * operating channel.
		 */
		priv->curchan = priv->hw->conf.chandef.chan;
		p54_reset_stats(priv);
		WARN_ON(p54_fetch_statistics(priv));
	}
	if (changed & IEEE80211_CONF_CHANGE_PS) {
		WARN_ON(p54_wait_for_stats(dev));
		ret = p54_set_ps(priv);
		if (ret)
			goto out;
		WARN_ON(p54_wait_for_stats(dev));
	}
	if (changed & IEEE80211_CONF_CHANGE_IDLE) {
		WARN_ON(p54_wait_for_stats(dev));
		ret = p54_setup_mac(priv);
		if (ret)
			goto out;
		WARN_ON(p54_wait_for_stats(dev));
	}

out:
	mutex_unlock(&priv->conf_mutex);
	return ret;
}
Example #2
0
struct ieee80211_hw *p54_init_common(size_t priv_data_len)
{
	struct ieee80211_hw *dev;
	struct p54_common *priv;

	dev = ieee80211_alloc_hw(priv_data_len, &p54_ops);
	if (!dev)
		return NULL;

	priv = dev->priv;
	priv->hw = dev;
	priv->mode = NL80211_IFTYPE_UNSPECIFIED;
	priv->basic_rate_mask = 0x15f;
	spin_lock_init(&priv->tx_stats_lock);
	skb_queue_head_init(&priv->tx_queue);
	skb_queue_head_init(&priv->tx_pending);
	dev->flags = IEEE80211_HW_RX_INCLUDES_FCS |
		     IEEE80211_HW_SIGNAL_DBM |
		     IEEE80211_HW_SUPPORTS_PS |
		     IEEE80211_HW_PS_NULLFUNC_STACK |
		     IEEE80211_HW_MFP_CAPABLE |
		     IEEE80211_HW_REPORTS_TX_ACK_STATUS;

	dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
				      BIT(NL80211_IFTYPE_ADHOC) |
				      BIT(NL80211_IFTYPE_AP) |
				      BIT(NL80211_IFTYPE_MESH_POINT);

	dev->channel_change_time = 1000;	/* TODO: find actual value */
	priv->beacon_req_id = cpu_to_le32(0);
	priv->tx_stats[P54_QUEUE_BEACON].limit = 1;
	priv->tx_stats[P54_QUEUE_FWSCAN].limit = 1;
	priv->tx_stats[P54_QUEUE_MGMT].limit = 3;
	priv->tx_stats[P54_QUEUE_CAB].limit = 3;
	priv->tx_stats[P54_QUEUE_DATA].limit = 5;
	dev->queues = 1;
	priv->noise = -94;
	/*
	 * We support at most 8 tries no matter which rate they're at,
	 * we cannot support max_rates * max_rate_tries as we set it
	 * here, but setting it correctly to 4/2 or so would limit us
	 * artificially if the RC algorithm wants just two rates, so
	 * let's say 4/7, we'll redistribute it at TX time, see the
	 * comments there.
	 */
	dev->max_rates = 4;
	dev->max_rate_tries = 7;
	dev->extra_tx_headroom = sizeof(struct p54_hdr) + 4 +
				 sizeof(struct p54_tx_data);

	/*
	 * For now, disable PS by default because it affects
	 * link stability significantly.
	 */
	dev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;

	mutex_init(&priv->conf_mutex);
	mutex_init(&priv->eeprom_mutex);
	init_completion(&priv->stat_comp);
	init_completion(&priv->eeprom_comp);
	init_completion(&priv->beacon_comp);
	INIT_DELAYED_WORK(&priv->work, p54_work);

	memset(&priv->mc_maclist[0], ~0, ETH_ALEN);
	priv->curchan = NULL;
	p54_reset_stats(priv);
	return dev;
}