summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath/ath9k/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/init.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c136
1 files changed, 63 insertions, 73 deletions
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index c070a9e51ebf..ee951493e993 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -18,10 +18,10 @@
#include <linux/dma-mapping.h>
#include <linux/slab.h>
-#include <linux/ath9k_platform.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_net.h>
+#include <linux/nvmem-consumer.h>
#include <linux/relay.h>
#include <linux/dmi.h>
#include <net/ieee80211_radiotap.h>
@@ -37,7 +37,6 @@ static char *dev_info = "ath9k";
MODULE_AUTHOR("Atheros Communications");
MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards.");
-MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards");
MODULE_LICENSE("Dual BSD/GPL");
static unsigned int ath9k_debug = ATH_DBG_DEFAULT;
@@ -151,12 +150,12 @@ static void ath9k_deinit_softc(struct ath_softc *sc);
static void ath9k_op_ps_wakeup(struct ath_common *common)
{
- ath9k_ps_wakeup((struct ath_softc *) common->priv);
+ ath9k_ps_wakeup(common->priv);
}
static void ath9k_op_ps_restore(struct ath_common *common)
{
- ath9k_ps_restore((struct ath_softc *) common->priv);
+ ath9k_ps_restore(common->priv);
}
static const struct ath_ps_ops ath9k_ps_ops = {
@@ -174,7 +173,7 @@ static void ath9k_iowrite32(void *hw_priv, u32 val, u32 reg_offset)
{
struct ath_hw *ah = hw_priv;
struct ath_common *common = ath9k_hw_common(ah);
- struct ath_softc *sc = (struct ath_softc *) common->priv;
+ struct ath_softc *sc = common->priv;
if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_ON) {
unsigned long flags;
@@ -189,7 +188,7 @@ static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset)
{
struct ath_hw *ah = hw_priv;
struct ath_common *common = ath9k_hw_common(ah);
- struct ath_softc *sc = (struct ath_softc *) common->priv;
+ struct ath_softc *sc = common->priv;
u32 val;
if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_ON) {
@@ -229,8 +228,8 @@ static unsigned int ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 cl
{
struct ath_hw *ah = hw_priv;
struct ath_common *common = ath9k_hw_common(ah);
- struct ath_softc *sc = (struct ath_softc *) common->priv;
- unsigned long uninitialized_var(flags);
+ struct ath_softc *sc = common->priv;
+ unsigned long flags;
u32 val;
if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_ON) {
@@ -569,45 +568,53 @@ static void ath9k_eeprom_release(struct ath_softc *sc)
release_firmware(sc->sc_ah->eeprom_blob);
}
-static int ath9k_init_platform(struct ath_softc *sc)
+static int ath9k_nvmem_request_eeprom(struct ath_softc *sc)
{
- struct ath9k_platform_data *pdata = sc->dev->platform_data;
struct ath_hw *ah = sc->sc_ah;
- struct ath_common *common = ath9k_hw_common(ah);
- int ret;
+ struct nvmem_cell *cell;
+ void *buf;
+ size_t len;
+ int err;
- if (!pdata)
- return 0;
+ cell = devm_nvmem_cell_get(sc->dev, "calibration");
+ if (IS_ERR(cell)) {
+ err = PTR_ERR(cell);
- if (!pdata->use_eeprom) {
- ah->ah_flags &= ~AH_USE_EEPROM;
- ah->gpio_mask = pdata->gpio_mask;
- ah->gpio_val = pdata->gpio_val;
- ah->led_pin = pdata->led_pin;
- ah->is_clk_25mhz = pdata->is_clk_25mhz;
- ah->get_mac_revision = pdata->get_mac_revision;
- ah->external_reset = pdata->external_reset;
- ah->disable_2ghz = pdata->disable_2ghz;
- ah->disable_5ghz = pdata->disable_5ghz;
-
- if (!pdata->endian_check)
- ah->ah_flags |= AH_NO_EEP_SWAP;
- }
+ /* nvmem cell might not be defined, or the nvmem
+ * subsystem isn't included. In this case, follow
+ * the established "just return 0;" convention
+ * to say:
+ * "All good. Nothing to see here. Please go on."
+ */
+ if (err == -ENOENT || err == -EOPNOTSUPP)
+ return 0;
- if (pdata->eeprom_name) {
- ret = ath9k_eeprom_request(sc, pdata->eeprom_name);
- if (ret)
- return ret;
+ return err;
}
- if (pdata->led_active_high)
- ah->config.led_active_high = true;
+ buf = nvmem_cell_read(cell, &len);
+ if (IS_ERR(buf))
+ return PTR_ERR(buf);
- if (pdata->tx_gain_buffalo)
- ah->config.tx_gain_buffalo = true;
+ /* run basic sanity checks on the returned nvram cell length.
+ * That length has to be a multiple of a "u16" (i.e.: & 1).
+ * Furthermore, it has to be more than "let's say" 512 bytes
+ * but less than the maximum of AR9300_EEPROM_SIZE (16kb).
+ */
+ if ((len & 1) == 1 || len < 512 || len >= AR9300_EEPROM_SIZE) {
+ kfree(buf);
+ return -EINVAL;
+ }
- if (pdata->macaddr)
- ether_addr_copy(common->macaddr, pdata->macaddr);
+ /* devres manages the calibration values release on shutdown */
+ ah->nvmem_blob = devm_kmemdup(sc->dev, buf, len, GFP_KERNEL);
+ kfree(buf);
+ if (!ah->nvmem_blob)
+ return -ENOMEM;
+
+ ah->nvmem_blob_len = len;
+ ah->ah_flags &= ~AH_USE_EEPROM;
+ ah->ah_flags |= AH_NO_EEP_SWAP;
return 0;
}
@@ -618,7 +625,6 @@ static int ath9k_of_init(struct ath_softc *sc)
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
enum ath_bus_type bus_type = common->bus_ops->ath_bus_type;
- const char *mac;
char eeprom_name[100];
int ret;
@@ -636,14 +642,14 @@ static int ath9k_of_init(struct ath_softc *sc)
ret = ath9k_eeprom_request(sc, eeprom_name);
if (ret)
return ret;
- }
- mac = of_get_mac_address(np);
- if (mac)
- ether_addr_copy(common->macaddr, mac);
+ ah->ah_flags &= ~AH_USE_EEPROM;
+ ah->ah_flags |= AH_NO_EEP_SWAP;
+ }
- ah->ah_flags &= ~AH_USE_EEPROM;
- ah->ah_flags |= AH_NO_EEP_SWAP;
+ ret = of_get_mac_address(np, common->macaddr);
+ if (ret == -EPROBE_DEFER)
+ return ret;
return 0;
}
@@ -676,8 +682,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
/* Will be cleared in ath9k_start() */
set_bit(ATH_OP_INVALID, &common->op_flags);
- sc->airtime_flags = (AIRTIME_USE_TX | AIRTIME_USE_RX |
- AIRTIME_USE_NEW_QUEUES);
sc->sc_ah = ah;
sc->dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET);
@@ -702,11 +706,11 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
*/
ath9k_init_pcoem_platform(sc);
- ret = ath9k_init_platform(sc);
+ ret = ath9k_of_init(sc);
if (ret)
return ret;
- ret = ath9k_of_init(sc);
+ ret = ath9k_nvmem_request_eeprom(sc);
if (ret)
return ret;
@@ -730,9 +734,8 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
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,
- (unsigned long)sc);
+ tasklet_setup(&sc->intr_tq, ath9k_tasklet);
+ tasklet_setup(&sc->bcon_tasklet, ath9k_beacon_tasklet);
timer_setup(&sc->sleep_timer, ath_ps_full_sleep, 0);
INIT_WORK(&sc->hw_reset_work, ath_reset_work);
@@ -807,7 +810,7 @@ static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
ah->curchan = &ah->channels[chan->hw_value];
cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_HT20);
ath9k_cmn_get_channel(sc->hw, ah, &chandef);
- ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true);
+ ath9k_hw_set_txpowerlimit(ah, MAX_COMBINED_POWER, true);
}
}
@@ -835,12 +838,6 @@ static const struct ieee80211_iface_limit if_limits[] = {
BIT(NL80211_IFTYPE_P2P_GO) },
};
-#ifdef CONFIG_WIRELESS_WDS
-static const struct ieee80211_iface_limit wds_limits[] = {
- { .max = 2048, .types = BIT(NL80211_IFTYPE_WDS) },
-};
-#endif
-
#ifdef CONFIG_ATH9K_CHANNEL_CONTEXT
static const struct ieee80211_iface_limit if_limits_multi[] = {
@@ -877,15 +874,6 @@ static const struct ieee80211_iface_combination if_comb[] = {
BIT(NL80211_CHAN_WIDTH_40),
#endif
},
-#ifdef CONFIG_WIRELESS_WDS
- {
- .limits = wds_limits,
- .n_limits = ARRAY_SIZE(wds_limits),
- .max_interfaces = 2048,
- .num_different_channels = 1,
- .beacon_int_infra_match = true,
- },
-#endif
};
#ifdef CONFIG_ATH9K_CHANNEL_CONTEXT
@@ -900,7 +888,6 @@ static void ath9k_set_mcc_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
ieee80211_hw_set(hw, QUEUE_CONTROL);
hw->queues = ATH9K_NUM_TX_QUEUES;
hw->offchannel_tx_hw_queue = hw->queues - 1;
- hw->wiphy->interface_modes &= ~ BIT(NL80211_IFTYPE_WDS);
hw->wiphy->iface_combinations = if_comb_multi;
hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb_multi);
hw->wiphy->max_scan_ssids = 255;
@@ -956,9 +943,6 @@ 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) |
-#ifdef CONFIG_WIRELESS_WDS
- BIT(NL80211_IFTYPE_WDS) |
-#endif
BIT(NL80211_IFTYPE_OCB);
if (ath9k_is_chanctx_enabled())
@@ -1013,6 +997,10 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
+ wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_AIRTIME_FAIRNESS);
+ wiphy_ext_feature_set(hw->wiphy,
+ NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS);
+ wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
}
int ath9k_init_device(u16 devid, struct ath_softc *sc,
@@ -1060,6 +1048,8 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
ARRAY_SIZE(ath9k_tpt_blink));
#endif
+ wiphy_read_of_freq_limits(hw->wiphy);
+
/* Register with mac80211 */
error = ieee80211_register_hw(hw);
if (error)
@@ -1109,7 +1099,7 @@ static void ath9k_deinit_softc(struct ath_softc *sc)
if (ATH_TXQ_SETUP(sc, i))
ath_tx_cleanupq(sc, &sc->tx.txq[i]);
- del_timer_sync(&sc->sleep_timer);
+ timer_delete_sync(&sc->sleep_timer);
ath9k_hw_deinit(sc->sc_ah);
if (sc->dfs_detector != NULL)
sc->dfs_detector->exit(sc->dfs_detector);