diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/init.c')
| -rw-r--r-- | drivers/net/wireless/ath/ath9k/init.c | 57 | 
1 files changed, 48 insertions, 9 deletions
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 0246b990fe87..39419ea845cc 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -61,7 +61,7 @@ static int ath9k_ps_enable;  module_param_named(ps_enable, ath9k_ps_enable, int, 0444);  MODULE_PARM_DESC(ps_enable, "Enable WLAN PowerSave"); -static int ath9k_use_chanctx; +int ath9k_use_chanctx;  module_param_named(use_chanctx, ath9k_use_chanctx, int, 0444);  MODULE_PARM_DESC(use_chanctx, "Enable channel context for concurrency"); @@ -169,9 +169,9 @@ static void ath9k_reg_notifier(struct wiphy *wiphy,  	/* Set tx power */  	if (ah->curchan) { -		sc->config.txpowlimit = 2 * ah->curchan->chan->max_power; +		sc->cur_chan->txpower = 2 * ah->curchan->chan->max_power;  		ath9k_ps_wakeup(sc); -		ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false); +		ath9k_hw_set_txpowerlimit(ah, sc->cur_chan->txpower, false);  		sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit;  		/* synchronize DFS detector if regulatory domain changed */  		if (sc->dfs_detector != NULL) @@ -335,7 +335,6 @@ static void ath9k_init_misc(struct ath_softc *sc)  	setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc);  	common->last_rssi = ATH_RSSI_DUMMY_MARKER; -	sc->config.txpowlimit = ATH_TXPOWER_MAX;  	memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);  	sc->beacon.slottime = ATH9K_SLOT_TIME_9; @@ -511,6 +510,9 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,  	sc->dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET);  	sc->tx99_power = MAX_RATE_POWER + 1;  	init_waitqueue_head(&sc->tx_wait); +	sc->cur_chan = &sc->chanctx[0]; +	if (!ath9k_use_chanctx) +		sc->cur_chan->hw_queue_base = 0;  	if (!pdata || pdata->use_eeprom) {  		ah->ah_flags |= AH_USE_EEPROM; @@ -556,6 +558,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,  	spin_lock_init(&common->cc_lock);  	spin_lock_init(&sc->sc_serial_rw);  	spin_lock_init(&sc->sc_pm_lock); +	spin_lock_init(&sc->chan_lock);  	mutex_init(&sc->mutex);  	tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);  	tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet, @@ -564,7 +567,11 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,  	setup_timer(&sc->sleep_timer, ath_ps_full_sleep, (unsigned long)sc);  	INIT_WORK(&sc->hw_reset_work, ath_reset_work);  	INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); +	INIT_WORK(&sc->chanctx_work, ath_chanctx_work);  	INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work); +	setup_timer(&sc->offchannel.timer, ath_offchannel_timer, +		    (unsigned long)sc); +	setup_timer(&sc->sched.timer, ath_chanctx_timer, (unsigned long)sc);  	/*  	 * Cache line size is used to size and align various @@ -599,6 +606,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,  	ath9k_cmn_init_crypto(sc->sc_ah);  	ath9k_init_misc(sc);  	ath_fill_led_pin(sc); +	ath_chanctx_init(sc);  	if (common->bus_ops->aspm_init)  		common->bus_ops->aspm_init(common); @@ -664,6 +672,12 @@ static const struct ieee80211_iface_limit wds_limits[] = {  	{ .max = 2048,	.types = BIT(NL80211_IFTYPE_WDS) },  }; +static const struct ieee80211_iface_limit if_limits_multi[] = { +	{ .max = 1,	.types = BIT(NL80211_IFTYPE_STATION) }, +	{ .max = 1,	.types = BIT(NL80211_IFTYPE_P2P_CLIENT) | +				 BIT(NL80211_IFTYPE_P2P_GO) }, +}; +  static const struct ieee80211_iface_limit if_dfs_limits[] = {  	{ .max = 1,	.types = BIT(NL80211_IFTYPE_AP) |  #ifdef CONFIG_MAC80211_MESH @@ -672,6 +686,16 @@ static const struct ieee80211_iface_limit if_dfs_limits[] = {  				 BIT(NL80211_IFTYPE_ADHOC) },  }; +static const struct ieee80211_iface_combination if_comb_multi[] = { +	{ +		.limits = if_limits_multi, +		.n_limits = ARRAY_SIZE(if_limits_multi), +		.max_interfaces = 2, +		.num_different_channels = 2, +		.beacon_int_infra_match = true, +	}, +}; +  static const struct ieee80211_iface_combination if_comb[] = {  	{  		.limits = if_limits, @@ -712,6 +736,7 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)  		IEEE80211_HW_SPECTRUM_MGMT |  		IEEE80211_HW_REPORTS_TX_ACK_STATUS |  		IEEE80211_HW_SUPPORTS_RC_TABLE | +		IEEE80211_HW_QUEUE_CONTROL |  		IEEE80211_HW_SUPPORTS_HT_CCK_RATES;  	if (ath9k_ps_enable) @@ -739,12 +764,21 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)  			BIT(NL80211_IFTYPE_STATION) |  			BIT(NL80211_IFTYPE_ADHOC) |  			BIT(NL80211_IFTYPE_MESH_POINT); -		hw->wiphy->iface_combinations = if_comb;  		if (!ath9k_use_chanctx) { +			hw->wiphy->iface_combinations = if_comb;  			hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);  			hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_WDS); -		} else -			hw->wiphy->n_iface_combinations = 1; +		} else { +			hw->wiphy->iface_combinations = if_comb_multi; +			hw->wiphy->n_iface_combinations = +				ARRAY_SIZE(if_comb_multi); +			hw->wiphy->max_scan_ssids = 255; +			hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; +			hw->wiphy->max_remain_on_channel_duration = 10000; +			hw->chanctx_data_size = sizeof(void *); +			hw->extra_beacon_tailroom = +				sizeof(struct ieee80211_p2p_noa_attr) + 9; +		}  	}  	hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; @@ -756,9 +790,14 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)  	hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;  	hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; -	hw->queues = 4; +	/* allow 4 queues per channel context + +	 * 1 cab queue + 1 offchannel tx queue +	 */ +	hw->queues = 10; +	/* last queue for offchannel */ +	hw->offchannel_tx_hw_queue = hw->queues - 1;  	hw->max_rates = 4; -	hw->max_listen_interval = 1; +	hw->max_listen_interval = 10;  	hw->max_rate_tries = 10;  	hw->sta_data_size = sizeof(struct ath_node);  	hw->vif_data_size = sizeof(struct ath_vif);  |