diff options
| author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2013-05-01 08:47:44 -0700 | 
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2013-05-01 08:47:44 -0700 | 
| commit | bf61c8840efe60fd8f91446860b63338fb424158 (patch) | |
| tree | 7a71832407a4f0d6346db773343f4c3ae2257b19 /drivers/net/wireless/ath/ath9k/init.c | |
| parent | 5846115b30f3a881e542c8bfde59a699c1c13740 (diff) | |
| parent | 0c6a61657da78098472fd0eb71cc01f2387fa1bb (diff) | |
| download | olio-linux-3.10-bf61c8840efe60fd8f91446860b63338fb424158.tar.xz olio-linux-3.10-bf61c8840efe60fd8f91446860b63338fb424158.zip  | |
Merge branch 'next' into for-linus
Prepare first set of updates for 3.10 merge window.
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/init.c')
| -rw-r--r-- | drivers/net/wireless/ath/ath9k/init.c | 186 | 
1 files changed, 106 insertions, 80 deletions
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index fad3ccd5cd9..af932c9444d 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -20,9 +20,15 @@  #include <linux/slab.h>  #include <linux/ath9k_platform.h>  #include <linux/module.h> +#include <linux/relay.h>  #include "ath9k.h" +struct ath9k_eeprom_ctx { +	struct completion complete; +	struct ath_hw *ah; +}; +  static char *dev_info = "ath9k";  MODULE_AUTHOR("Atheros Communications"); @@ -297,16 +303,15 @@ static void setup_ht_cap(struct ath_softc *sc,  	ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;  } -static int ath9k_reg_notifier(struct wiphy *wiphy, -			      struct regulatory_request *request) +static void ath9k_reg_notifier(struct wiphy *wiphy, +			       struct regulatory_request *request)  {  	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);  	struct ath_softc *sc = hw->priv;  	struct ath_hw *ah = sc->sc_ah;  	struct ath_regulatory *reg = ath9k_hw_regulatory(ah); -	int ret; -	ret = ath_reg_notifier_apply(wiphy, request, reg); +	ath_reg_notifier_apply(wiphy, request, reg);  	/* Set tx power */  	if (ah->curchan) { @@ -316,8 +321,6 @@ static int ath9k_reg_notifier(struct wiphy *wiphy,  		sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit;  		ath9k_ps_restore(sc);  	} - -	return ret;  }  /* @@ -332,7 +335,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,  	struct ath_common *common = ath9k_hw_common(sc->sc_ah);  	u8 *ds;  	struct ath_buf *bf; -	int i, bsize, error, desc_len; +	int i, bsize, desc_len;  	ath_dbg(common, CONFIG, "%s DMA: %u buffers %u desc/buf\n",  		name, nbuf, ndesc); @@ -348,8 +351,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,  	if ((desc_len % 4) != 0) {  		ath_err(common, "ath_desc not DWORD aligned\n");  		BUG_ON((desc_len % 4) != 0); -		error = -ENOMEM; -		goto fail; +		return -ENOMEM;  	}  	dd->dd_desc_len = desc_len * nbuf * ndesc; @@ -373,12 +375,11 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,  	}  	/* allocate descriptors */ -	dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len, -					 &dd->dd_desc_paddr, GFP_KERNEL); -	if (dd->dd_desc == NULL) { -		error = -ENOMEM; -		goto fail; -	} +	dd->dd_desc = dmam_alloc_coherent(sc->dev, dd->dd_desc_len, +					  &dd->dd_desc_paddr, GFP_KERNEL); +	if (!dd->dd_desc) +		return -ENOMEM; +  	ds = (u8 *) dd->dd_desc;  	ath_dbg(common, CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n",  		name, ds, (u32) dd->dd_desc_len, @@ -386,12 +387,9 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,  	/* allocate buffers */  	bsize = sizeof(struct ath_buf) * nbuf; -	bf = kzalloc(bsize, GFP_KERNEL); -	if (bf == NULL) { -		error = -ENOMEM; -		goto fail2; -	} -	dd->dd_bufptr = bf; +	bf = devm_kzalloc(sc->dev, bsize, GFP_KERNEL); +	if (!bf) +		return -ENOMEM;  	for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) {  		bf->bf_desc = ds; @@ -417,12 +415,6 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,  		list_add_tail(&bf->list, head);  	}  	return 0; -fail2: -	dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc, -			  dd->dd_desc_paddr); -fail: -	memset(dd, 0, sizeof(*dd)); -	return error;  }  static int ath9k_init_queues(struct ath_softc *sc) @@ -435,7 +427,7 @@ static int ath9k_init_queues(struct ath_softc *sc)  	sc->config.cabqReadytime = ATH_CABQ_READY_TIME;  	ath_cabq_update(sc); -	for (i = 0; i < WME_NUM_AC; i++) { +	for (i = 0; i < IEEE80211_NUM_ACS; i++) {  		sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);  		sc->tx.txq_map[i]->mac80211_qnum = i;  		sc->tx.txq_max_pending[i] = ATH_MAX_QDEPTH; @@ -452,11 +444,13 @@ static int ath9k_init_channels_rates(struct ath_softc *sc)  		     ATH9K_NUM_CHANNELS);  	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) { -		channels = kmemdup(ath9k_2ghz_chantable, +		channels = devm_kzalloc(sc->dev,  			sizeof(ath9k_2ghz_chantable), GFP_KERNEL);  		if (!channels)  		    return -ENOMEM; +		memcpy(channels, ath9k_2ghz_chantable, +		       sizeof(ath9k_2ghz_chantable));  		sc->sbands[IEEE80211_BAND_2GHZ].channels = channels;  		sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;  		sc->sbands[IEEE80211_BAND_2GHZ].n_channels = @@ -467,14 +461,13 @@ static int ath9k_init_channels_rates(struct ath_softc *sc)  	}  	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) { -		channels = kmemdup(ath9k_5ghz_chantable, +		channels = devm_kzalloc(sc->dev,  			sizeof(ath9k_5ghz_chantable), GFP_KERNEL); -		if (!channels) { -			if (sc->sbands[IEEE80211_BAND_2GHZ].channels) -				kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels); +		if (!channels)  			return -ENOMEM; -		} +		memcpy(channels, ath9k_5ghz_chantable, +		       sizeof(ath9k_5ghz_chantable));  		sc->sbands[IEEE80211_BAND_5GHZ].channels = channels;  		sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;  		sc->sbands[IEEE80211_BAND_5GHZ].n_channels = @@ -504,6 +497,58 @@ static void ath9k_init_misc(struct ath_softc *sc)  	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)  		sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT; + +	sc->spec_config.enabled = 0; +	sc->spec_config.short_repeat = true; +	sc->spec_config.count = 8; +	sc->spec_config.endless = false; +	sc->spec_config.period = 0xFF; +	sc->spec_config.fft_period = 0xF; +} + +static void ath9k_eeprom_request_cb(const struct firmware *eeprom_blob, +				    void *ctx) +{ +	struct ath9k_eeprom_ctx *ec = ctx; + +	if (eeprom_blob) +		ec->ah->eeprom_blob = eeprom_blob; + +	complete(&ec->complete); +} + +static int ath9k_eeprom_request(struct ath_softc *sc, const char *name) +{ +	struct ath9k_eeprom_ctx ec; +	struct ath_hw *ah = ah = sc->sc_ah; +	int err; + +	/* try to load the EEPROM content asynchronously */ +	init_completion(&ec.complete); +	ec.ah = sc->sc_ah; + +	err = request_firmware_nowait(THIS_MODULE, 1, name, sc->dev, GFP_KERNEL, +				      &ec, ath9k_eeprom_request_cb); +	if (err < 0) { +		ath_err(ath9k_hw_common(ah), +			"EEPROM request failed\n"); +		return err; +	} + +	wait_for_completion(&ec.complete); + +	if (!ah->eeprom_blob) { +		ath_err(ath9k_hw_common(ah), +			"Unable to load EEPROM file %s\n", name); +		return -EINVAL; +	} + +	return 0; +} + +static void ath9k_eeprom_release(struct ath_softc *sc) +{ +	release_firmware(sc->sc_ah->eeprom_blob);  }  static int ath9k_init_softc(u16 devid, struct ath_softc *sc, @@ -515,10 +560,11 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,  	int ret = 0, i;  	int csz = 0; -	ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); +	ah = devm_kzalloc(sc->dev, sizeof(struct ath_hw), GFP_KERNEL);  	if (!ah)  		return -ENOMEM; +	ah->dev = sc->dev;  	ah->hw = sc->hw;  	ah->hw_version.devid = devid;  	ah->reg_ops.read = ath9k_ioread32; @@ -563,10 +609,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,  	spin_lock_init(&sc->sc_serial_rw);  	spin_lock_init(&sc->sc_pm_lock);  	mutex_init(&sc->mutex); -#ifdef CONFIG_ATH9K_DEBUGFS -	spin_lock_init(&sc->nodes_lock); -	INIT_LIST_HEAD(&sc->nodes); -#endif  #ifdef CONFIG_ATH9K_MAC_DEBUG  	spin_lock_init(&sc->debug.samp_lock);  #endif @@ -587,6 +629,12 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,  	ath_read_cachesize(common, &csz);  	common->cachelsz = csz << 2; /* convert to bytes */ +	if (pdata && pdata->eeprom_name) { +		ret = ath9k_eeprom_request(sc, pdata->eeprom_name); +		if (ret) +			return ret; +	} +  	/* Initializes the hardware for all supported chipsets */  	ret = ath9k_hw_init(ah);  	if (ret) @@ -623,10 +671,7 @@ err_btcoex:  err_queues:  	ath9k_hw_deinit(ah);  err_hw: - -	kfree(ah); -	sc->sc_ah = NULL; - +	ath9k_eeprom_release(sc);  	return ret;  } @@ -687,6 +732,7 @@ static const struct ieee80211_iface_combination if_comb = {  	.n_limits = ARRAY_SIZE(if_limits),  	.max_interfaces = 2048,  	.num_different_channels = 1, +	.beacon_int_infra_match = true,  };  void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) @@ -790,8 +836,8 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,  	/* Bring up device */  	error = ath9k_init_softc(devid, sc, bus_ops); -	if (error != 0) -		goto error_init; +	if (error) +		return error;  	ah = sc->sc_ah;  	common = ath9k_hw_common(ah); @@ -801,19 +847,19 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,  	error = ath_regd_init(&common->regulatory, sc->hw->wiphy,  			      ath9k_reg_notifier);  	if (error) -		goto error_regd; +		goto deinit;  	reg = &common->regulatory;  	/* Setup TX DMA */  	error = ath_tx_init(sc, ATH_TXBUF);  	if (error != 0) -		goto error_tx; +		goto deinit;  	/* Setup RX DMA */  	error = ath_rx_init(sc, ATH_RXBUF);  	if (error != 0) -		goto error_rx; +		goto deinit;  	ath9k_init_txpower_limits(sc); @@ -827,19 +873,19 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,  	/* Register with mac80211 */  	error = ieee80211_register_hw(hw);  	if (error) -		goto error_register; +		goto rx_cleanup;  	error = ath9k_init_debug(ah);  	if (error) {  		ath_err(common, "Unable to create debugfs files\n"); -		goto error_world; +		goto unregister;  	}  	/* Handle world regulatory */  	if (!ath_is_world_regd(reg)) {  		error = regulatory_hint(hw->wiphy, reg->alpha2);  		if (error) -			goto error_world; +			goto unregister;  	}  	ath_init_leds(sc); @@ -847,17 +893,12 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,  	return 0; -error_world: +unregister:  	ieee80211_unregister_hw(hw); -error_register: +rx_cleanup:  	ath_rx_cleanup(sc); -error_rx: -	ath_tx_cleanup(sc); -error_tx: -	/* Nothing */ -error_regd: +deinit:  	ath9k_deinit_softc(sc); -error_init:  	return error;  } @@ -869,12 +910,6 @@ static void ath9k_deinit_softc(struct ath_softc *sc)  {  	int i = 0; -	if (sc->sbands[IEEE80211_BAND_2GHZ].channels) -		kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels); - -	if (sc->sbands[IEEE80211_BAND_5GHZ].channels) -		kfree(sc->sbands[IEEE80211_BAND_5GHZ].channels); -  	ath9k_deinit_btcoex(sc);  	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) @@ -885,8 +920,12 @@ static void ath9k_deinit_softc(struct ath_softc *sc)  	if (sc->dfs_detector != NULL)  		sc->dfs_detector->exit(sc->dfs_detector); -	kfree(sc->sc_ah); -	sc->sc_ah = NULL; +	ath9k_eeprom_release(sc); + +	if (config_enabled(CONFIG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) { +		relay_close(sc->rfs_chan_spec_scan); +		sc->rfs_chan_spec_scan = NULL; +	}  }  void ath9k_deinit_device(struct ath_softc *sc) @@ -902,22 +941,9 @@ void ath9k_deinit_device(struct ath_softc *sc)  	ieee80211_unregister_hw(hw);  	ath_rx_cleanup(sc); -	ath_tx_cleanup(sc);  	ath9k_deinit_softc(sc);  } -void ath_descdma_cleanup(struct ath_softc *sc, -			 struct ath_descdma *dd, -			 struct list_head *head) -{ -	dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc, -			  dd->dd_desc_paddr); - -	INIT_LIST_HEAD(head); -	kfree(dd->dd_bufptr); -	memset(dd, 0, sizeof(*dd)); -} -  /************************/  /*     Module Hooks     */  /************************/  |