aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/wcn36xx/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/wcn36xx/main.c')
-rw-r--r--drivers/net/wireless/ath/wcn36xx/main.c321
1 files changed, 200 insertions, 121 deletions
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
index b04533bbc3a4..6b8d2889d73f 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -28,6 +28,7 @@
#include <net/ipv6.h>
#include "wcn36xx.h"
#include "testmode.h"
+#include "firmware.h"
unsigned int wcn36xx_dbg_mask;
module_param_named(debug_mask, wcn36xx_dbg_mask, uint, 0644);
@@ -192,84 +193,15 @@ static inline u8 get_sta_index(struct ieee80211_vif *vif,
sta_priv->sta_index;
}
-static const char * const wcn36xx_caps_names[] = {
- "MCC", /* 0 */
- "P2P", /* 1 */
- "DOT11AC", /* 2 */
- "SLM_SESSIONIZATION", /* 3 */
- "DOT11AC_OPMODE", /* 4 */
- "SAP32STA", /* 5 */
- "TDLS", /* 6 */
- "P2P_GO_NOA_DECOUPLE_INIT_SCAN",/* 7 */
- "WLANACTIVE_OFFLOAD", /* 8 */
- "BEACON_OFFLOAD", /* 9 */
- "SCAN_OFFLOAD", /* 10 */
- "ROAM_OFFLOAD", /* 11 */
- "BCN_MISS_OFFLOAD", /* 12 */
- "STA_POWERSAVE", /* 13 */
- "STA_ADVANCED_PWRSAVE", /* 14 */
- "AP_UAPSD", /* 15 */
- "AP_DFS", /* 16 */
- "BLOCKACK", /* 17 */
- "PHY_ERR", /* 18 */
- "BCN_FILTER", /* 19 */
- "RTT", /* 20 */
- "RATECTRL", /* 21 */
- "WOW", /* 22 */
- "WLAN_ROAM_SCAN_OFFLOAD", /* 23 */
- "SPECULATIVE_PS_POLL", /* 24 */
- "SCAN_SCH", /* 25 */
- "IBSS_HEARTBEAT_OFFLOAD", /* 26 */
- "WLAN_SCAN_OFFLOAD", /* 27 */
- "WLAN_PERIODIC_TX_PTRN", /* 28 */
- "ADVANCE_TDLS", /* 29 */
- "BATCH_SCAN", /* 30 */
- "FW_IN_TX_PATH", /* 31 */
- "EXTENDED_NSOFFLOAD_SLOT", /* 32 */
- "CH_SWITCH_V1", /* 33 */
- "HT40_OBSS_SCAN", /* 34 */
- "UPDATE_CHANNEL_LIST", /* 35 */
- "WLAN_MCADDR_FLT", /* 36 */
- "WLAN_CH144", /* 37 */
- "NAN", /* 38 */
- "TDLS_SCAN_COEXISTENCE", /* 39 */
- "LINK_LAYER_STATS_MEAS", /* 40 */
- "MU_MIMO", /* 41 */
- "EXTENDED_SCAN", /* 42 */
- "DYNAMIC_WMM_PS", /* 43 */
- "MAC_SPOOFED_SCAN", /* 44 */
- "BMU_ERROR_GENERIC_RECOVERY", /* 45 */
- "DISA", /* 46 */
- "FW_STATS", /* 47 */
- "WPS_PRBRSP_TMPL", /* 48 */
- "BCN_IE_FLT_DELTA", /* 49 */
- "TDLS_OFF_CHANNEL", /* 51 */
- "RTT3", /* 52 */
- "MGMT_FRAME_LOGGING", /* 53 */
- "ENHANCED_TXBD_COMPLETION", /* 54 */
- "LOGGING_ENHANCEMENT", /* 55 */
- "EXT_SCAN_ENHANCED", /* 56 */
- "MEMORY_DUMP_SUPPORTED", /* 57 */
- "PER_PKT_STATS_SUPPORTED", /* 58 */
- "EXT_LL_STAT", /* 60 */
- "WIFI_CONFIG", /* 61 */
- "ANTENNA_DIVERSITY_SELECTION", /* 62 */
-};
-
-static const char *wcn36xx_get_cap_name(enum place_holder_in_cap_bitmap x)
-{
- if (x >= ARRAY_SIZE(wcn36xx_caps_names))
- return "UNKNOWN";
- return wcn36xx_caps_names[x];
-}
-
static void wcn36xx_feat_caps_info(struct wcn36xx *wcn)
{
int i;
for (i = 0; i < MAX_FEATURE_SUPPORTED; i++) {
- if (get_feat_caps(wcn->fw_feat_caps, i))
- wcn36xx_dbg(WCN36XX_DBG_MAC, "FW Cap %s\n", wcn36xx_get_cap_name(i));
+ if (wcn36xx_firmware_get_feat_caps(wcn->fw_feat_caps, i)) {
+ wcn36xx_dbg(WCN36XX_DBG_MAC, "FW Cap %s\n",
+ wcn36xx_firmware_get_cap_name(i));
+ }
}
}
@@ -331,6 +263,7 @@ static int wcn36xx_start(struct ieee80211_hw *hw)
INIT_LIST_HEAD(&wcn->vif_list);
spin_lock_init(&wcn->dxe_lock);
+ spin_lock_init(&wcn->survey_lock);
return 0;
@@ -380,7 +313,7 @@ static void wcn36xx_change_ps(struct wcn36xx *wcn, bool enable)
list_for_each_entry(tmp, &wcn->vif_list, list) {
vif = wcn36xx_priv_to_vif(tmp);
if (enable && !wcn->sw_scan) {
- if (vif->bss_conf.ps) /* ps allowed ? */
+ if (vif->cfg.ps) /* ps allowed ? */
wcn36xx_pmc_enter_bmps_state(wcn, vif);
} else {
wcn36xx_pmc_exit_bmps_state(wcn, vif);
@@ -392,16 +325,47 @@ static void wcn36xx_change_opchannel(struct wcn36xx *wcn, int ch)
{
struct ieee80211_vif *vif = NULL;
struct wcn36xx_vif *tmp;
+ struct ieee80211_supported_band *band;
+ struct ieee80211_channel *channel = NULL;
+ unsigned long flags;
+ int i, j;
+
+ for (i = 0; i < ARRAY_SIZE(wcn->hw->wiphy->bands); i++) {
+ band = wcn->hw->wiphy->bands[i];
+ if (!band)
+ break;
+ for (j = 0; j < band->n_channels; j++) {
+ if (HW_VALUE_CHANNEL(band->channels[j].hw_value) == ch) {
+ channel = &band->channels[j];
+ break;
+ }
+ }
+ if (channel)
+ break;
+ }
+
+ if (!channel) {
+ wcn36xx_err("Cannot tune to channel %d\n", ch);
+ return;
+ }
+
+ spin_lock_irqsave(&wcn->survey_lock, flags);
+ wcn->band = band;
+ wcn->channel = channel;
+ spin_unlock_irqrestore(&wcn->survey_lock, flags);
list_for_each_entry(tmp, &wcn->vif_list, list) {
vif = wcn36xx_priv_to_vif(tmp);
wcn36xx_smd_switch_channel(wcn, vif, ch);
}
+
+ return;
}
static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed)
{
struct wcn36xx *wcn = hw->priv;
+ int ret;
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac config changed 0x%08x\n", changed);
@@ -417,17 +381,31 @@ static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed)
* want to receive/transmit regular data packets, then
* simply stop the scan session and exit PS mode.
*/
- wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN,
- wcn->sw_scan_vif);
- wcn->sw_scan_channel = 0;
+ if (wcn->sw_scan_channel)
+ wcn36xx_smd_end_scan(wcn, wcn->sw_scan_channel);
+ if (wcn->sw_scan_init) {
+ wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN,
+ wcn->sw_scan_vif);
+ }
} else if (wcn->sw_scan) {
/* A scan is ongoing, do not change the operating
* channel, but start a scan session on the channel.
*/
- wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN,
- wcn->sw_scan_vif);
+ if (wcn->sw_scan_channel)
+ wcn36xx_smd_end_scan(wcn, wcn->sw_scan_channel);
+ if (!wcn->sw_scan_init) {
+ /* This can fail if we are unable to notify the
+ * operating channel.
+ */
+ ret = wcn36xx_smd_init_scan(wcn,
+ HAL_SYS_MODE_SCAN,
+ wcn->sw_scan_vif);
+ if (ret) {
+ mutex_unlock(&wcn->conf_mutex);
+ return -EIO;
+ }
+ }
wcn36xx_smd_start_scan(wcn, ch);
- wcn->sw_scan_channel = ch;
} else {
wcn36xx_change_opchannel(wcn, ch);
}
@@ -655,7 +633,7 @@ static int wcn36xx_hw_scan(struct ieee80211_hw *hw,
{
struct wcn36xx *wcn = hw->priv;
- if (!get_feat_caps(wcn->fw_feat_caps, SCAN_OFFLOAD)) {
+ if (!wcn36xx_firmware_get_feat_caps(wcn->fw_feat_caps, SCAN_OFFLOAD)) {
/* fallback to mac80211 software scan */
return 1;
}
@@ -693,7 +671,7 @@ static void wcn36xx_cancel_hw_scan(struct ieee80211_hw *hw,
wcn->scan_aborted = true;
mutex_unlock(&wcn->scan_lock);
- if (get_feat_caps(wcn->fw_feat_caps, SCAN_OFFLOAD)) {
+ if (wcn36xx_firmware_get_feat_caps(wcn->fw_feat_caps, SCAN_OFFLOAD)) {
/* ieee80211_scan_completed will be called on FW scan
* indication */
wcn36xx_smd_stop_hw_scan(wcn);
@@ -707,6 +685,8 @@ static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw,
struct wcn36xx *wcn = hw->priv;
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
+ wcn36xx_dbg(WCN36XX_DBG_MAC, "sw_scan_start");
+
wcn->sw_scan = true;
wcn->sw_scan_vif = vif;
wcn->sw_scan_channel = 0;
@@ -721,8 +701,15 @@ static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw,
{
struct wcn36xx *wcn = hw->priv;
+ wcn36xx_dbg(WCN36XX_DBG_MAC, "sw_scan_complete");
+
/* ensure that any scan session is finished */
- wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN, wcn->sw_scan_vif);
+ if (wcn->sw_scan_channel)
+ wcn36xx_smd_end_scan(wcn, wcn->sw_scan_channel);
+ if (wcn->sw_scan_init) {
+ wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN,
+ wcn->sw_scan_vif);
+ }
wcn->sw_scan = false;
wcn->sw_scan_opchannel = 0;
}
@@ -733,7 +720,7 @@ static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta,
int i, size;
u16 *rates_table;
struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
- u32 rates = sta->supp_rates[band];
+ u32 rates = sta->deflink.supp_rates[band];
memset(&sta_priv->supported_rates, 0,
sizeof(sta_priv->supported_rates));
@@ -759,20 +746,20 @@ static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta,
}
}
- if (sta->ht_cap.ht_supported) {
- BUILD_BUG_ON(sizeof(sta->ht_cap.mcs.rx_mask) >
- sizeof(sta_priv->supported_rates.supported_mcs_set));
+ if (sta->deflink.ht_cap.ht_supported) {
+ BUILD_BUG_ON(sizeof(sta->deflink.ht_cap.mcs.rx_mask) >
+ sizeof(sta_priv->supported_rates.supported_mcs_set));
memcpy(sta_priv->supported_rates.supported_mcs_set,
- sta->ht_cap.mcs.rx_mask,
- sizeof(sta->ht_cap.mcs.rx_mask));
+ sta->deflink.ht_cap.mcs.rx_mask,
+ sizeof(sta->deflink.ht_cap.mcs.rx_mask));
}
- if (sta->vht_cap.vht_supported) {
+ if (sta->deflink.vht_cap.vht_supported) {
sta_priv->supported_rates.op_rate_mode = STA_11ac;
sta_priv->supported_rates.vht_rx_mcs_map =
- sta->vht_cap.vht_mcs.rx_mcs_map;
+ sta->deflink.vht_cap.vht_mcs.rx_mcs_map;
sta_priv->supported_rates.vht_tx_mcs_map =
- sta->vht_cap.vht_mcs.tx_mcs_map;
+ sta->deflink.vht_cap.vht_mcs.tx_mcs_map;
}
}
@@ -813,7 +800,7 @@ void wcn36xx_set_default_rates_v1(struct wcn36xx_hal_supported_rates_v1 *rates)
static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
- u32 changed)
+ u64 changed)
{
struct wcn36xx *wcn = hw->priv;
struct sk_buff *skb = NULL;
@@ -821,7 +808,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
enum wcn36xx_hal_link_state link_state;
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
- wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%08x\n",
+ wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%llx\n",
vif, changed);
mutex_lock(&wcn->conf_mutex);
@@ -860,17 +847,17 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
wcn36xx_dbg(WCN36XX_DBG_MAC,
"mac bss changed ssid\n");
wcn36xx_dbg_dump(WCN36XX_DBG_MAC, "ssid ",
- bss_conf->ssid, bss_conf->ssid_len);
+ vif->cfg.ssid, vif->cfg.ssid_len);
- vif_priv->ssid.length = bss_conf->ssid_len;
+ vif_priv->ssid.length = vif->cfg.ssid_len;
memcpy(&vif_priv->ssid.ssid,
- bss_conf->ssid,
- bss_conf->ssid_len);
+ vif->cfg.ssid,
+ vif->cfg.ssid_len);
}
if (changed & BSS_CHANGED_ASSOC) {
vif_priv->is_joining = false;
- if (bss_conf->assoc) {
+ if (vif->cfg.assoc) {
struct ieee80211_sta *sta;
struct wcn36xx_sta *sta_priv;
@@ -878,7 +865,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
"mac assoc bss %pM vif %pM AID=%d\n",
bss_conf->bssid,
vif->addr,
- bss_conf->aid);
+ vif->cfg.aid);
vif_priv->sta_assoc = true;
@@ -904,19 +891,21 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
wcn36xx_smd_config_bss(wcn, vif, sta,
bss_conf->bssid,
true);
- sta_priv->aid = bss_conf->aid;
+ sta_priv->aid = vif->cfg.aid;
/*
* config_sta must be called from because this is the
* place where AID is available.
*/
wcn36xx_smd_config_sta(wcn, vif, sta);
+ if (vif->type == NL80211_IFTYPE_STATION)
+ wcn36xx_smd_add_beacon_filter(wcn, vif);
wcn36xx_enable_keep_alive_null_packet(wcn, vif);
} else {
wcn36xx_dbg(WCN36XX_DBG_MAC,
"disassociated bss %pM vif %pM AID=%d\n",
bss_conf->bssid,
vif->addr,
- bss_conf->aid);
+ vif->cfg.aid);
vif_priv->sta_assoc = false;
wcn36xx_smd_set_link_st(wcn,
bss_conf->bssid,
@@ -949,7 +938,7 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
wcn36xx_smd_config_bss(wcn, vif, NULL,
vif->addr, false);
skb = ieee80211_beacon_get_tim(hw, vif, &tim_off,
- &tim_len);
+ &tim_len, 0);
if (!skb) {
wcn36xx_err("failed to alloc beacon skb\n");
goto out;
@@ -1196,7 +1185,7 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
u16 tid = params->tid;
u16 *ssn = &params->ssn;
int ret = 0;
- u8 session;
+ int session;
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n",
action, tid);
@@ -1208,9 +1197,11 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
sta_priv->tid = tid;
session = wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 0,
get_sta_index(vif, sta_priv));
+ if (session < 0) {
+ ret = session;
+ goto out;
+ }
wcn36xx_smd_add_ba(wcn, session);
- wcn36xx_smd_trigger_ba(wcn, get_sta_index(vif, sta_priv), tid,
- session);
break;
case IEEE80211_AMPDU_RX_STOP:
wcn36xx_smd_del_ba(wcn, tid, 0, get_sta_index(vif, sta_priv));
@@ -1220,6 +1211,18 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_START;
spin_unlock_bh(&sta_priv->ampdu_lock);
+ /* Replace the mac80211 ssn with the firmware one */
+ wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu ssn = %u\n", *ssn);
+ wcn36xx_smd_trigger_ba(wcn, get_sta_index(vif, sta_priv), tid, ssn);
+ wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu fw-ssn = %u\n", *ssn);
+
+ /* Start BA session */
+ session = wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 1,
+ get_sta_index(vif, sta_priv));
+ if (session < 0) {
+ ret = session;
+ goto out;
+ }
ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
break;
case IEEE80211_AMPDU_TX_OPERATIONAL:
@@ -1227,8 +1230,6 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_OPERATIONAL;
spin_unlock_bh(&sta_priv->ampdu_lock);
- wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 1,
- get_sta_index(vif, sta_priv));
break;
case IEEE80211_AMPDU_TX_STOP_FLUSH:
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
@@ -1244,6 +1245,7 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
wcn36xx_err("Unknown AMPDU action\n");
}
+out:
mutex_unlock(&wcn->conf_mutex);
return ret;
@@ -1277,6 +1279,74 @@ static void wcn36xx_ipv6_addr_change(struct ieee80211_hw *hw,
}
#endif
+static void wcn36xx_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ u32 queues, bool drop)
+{
+ struct wcn36xx *wcn = hw->priv;
+
+ if (wcn36xx_dxe_tx_flush(wcn)) {
+ wcn36xx_err("Failed to flush hardware tx queues\n");
+ }
+}
+
+static int wcn36xx_get_survey(struct ieee80211_hw *hw, int idx,
+ struct survey_info *survey)
+{
+ struct wcn36xx *wcn = hw->priv;
+ struct ieee80211_supported_band *sband;
+ struct wcn36xx_chan_survey *chan_survey;
+ int band_idx;
+ unsigned long flags;
+
+ sband = wcn->hw->wiphy->bands[NL80211_BAND_2GHZ];
+ band_idx = idx;
+ if (band_idx >= sband->n_channels) {
+ band_idx -= sband->n_channels;
+ sband = wcn->hw->wiphy->bands[NL80211_BAND_5GHZ];
+ }
+
+ if (!sband || band_idx >= sband->n_channels)
+ return -ENOENT;
+
+ spin_lock_irqsave(&wcn->survey_lock, flags);
+
+ chan_survey = &wcn->chan_survey[idx];
+ survey->channel = &sband->channels[band_idx];
+ survey->noise = chan_survey->rssi - chan_survey->snr;
+ survey->filled = 0;
+
+ if (chan_survey->rssi > -100 && chan_survey->rssi < 0)
+ survey->filled |= SURVEY_INFO_NOISE_DBM;
+
+ if (survey->channel == wcn->channel)
+ survey->filled |= SURVEY_INFO_IN_USE;
+
+ spin_unlock_irqrestore(&wcn->survey_lock, flags);
+
+ wcn36xx_dbg(WCN36XX_DBG_MAC,
+ "ch %d rssi %d snr %d noise %d filled %x freq %d\n",
+ HW_VALUE_CHANNEL(survey->channel->hw_value),
+ chan_survey->rssi, chan_survey->snr, survey->noise,
+ survey->filled, survey->channel->center_freq);
+
+ return 0;
+}
+
+static void wcn36xx_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta, struct station_info *sinfo)
+{
+ struct wcn36xx *wcn;
+ u8 sta_index;
+ int status;
+
+ wcn = hw->priv;
+ sta_index = get_sta_index(vif, wcn36xx_sta_to_priv(sta));
+ status = wcn36xx_smd_get_stats(wcn, sta_index, HAL_GLOBAL_CLASS_A_STATS_INFO, sinfo);
+
+ if (status)
+ wcn36xx_err("wcn36xx_smd_get_stats failed\n");
+}
+
static const struct ieee80211_ops wcn36xx_ops = {
.start = wcn36xx_start,
.stop = wcn36xx_stop,
@@ -1300,10 +1370,13 @@ static const struct ieee80211_ops wcn36xx_ops = {
.set_rts_threshold = wcn36xx_set_rts_threshold,
.sta_add = wcn36xx_sta_add,
.sta_remove = wcn36xx_sta_remove,
+ .sta_statistics = wcn36xx_sta_statistics,
.ampdu_action = wcn36xx_ampdu_action,
#if IS_ENABLED(CONFIG_IPV6)
.ipv6_addr_change = wcn36xx_ipv6_addr_change,
#endif
+ .flush = wcn36xx_flush,
+ .get_survey = wcn36xx_get_survey,
CFG80211_TESTMODE_CMD(wcn36xx_tm_cmd)
};
@@ -1396,25 +1469,20 @@ static int wcn36xx_platform_get_resources(struct wcn36xx *wcn,
{
struct device_node *mmio_node;
struct device_node *iris_node;
- struct resource *res;
int index;
int ret;
/* Set TX IRQ */
- res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "tx");
- if (!res) {
- wcn36xx_err("failed to get tx_irq\n");
- return -ENOENT;
- }
- wcn->tx_irq = res->start;
+ ret = platform_get_irq_byname(pdev, "tx");
+ if (ret < 0)
+ return ret;
+ wcn->tx_irq = ret;
/* Set RX IRQ */
- res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "rx");
- if (!res) {
- wcn36xx_err("failed to get rx_irq\n");
- return -ENOENT;
- }
- wcn->rx_irq = res->start;
+ ret = platform_get_irq_byname(pdev, "rx");
+ if (ret < 0)
+ return ret;
+ wcn->rx_irq = ret;
/* Acquire SMSM tx enable handle */
wcn->tx_enable_state = qcom_smem_state_get(&pdev->dev,
@@ -1463,6 +1531,9 @@ static int wcn36xx_platform_get_resources(struct wcn36xx *wcn,
if (iris_node) {
if (of_device_is_compatible(iris_node, "qcom,wcn3620"))
wcn->rf_id = RF_IRIS_WCN3620;
+ if (of_device_is_compatible(iris_node, "qcom,wcn3660") ||
+ of_device_is_compatible(iris_node, "qcom,wcn3660b"))
+ wcn->rf_id = RF_IRIS_WCN3660;
if (of_device_is_compatible(iris_node, "qcom,wcn3680"))
wcn->rf_id = RF_IRIS_WCN3680;
of_node_put(iris_node);
@@ -1485,6 +1556,7 @@ static int wcn36xx_probe(struct platform_device *pdev)
void *wcnss;
int ret;
const u8 *addr;
+ int n_channels;
wcn36xx_dbg(WCN36XX_DBG_MAC, "platform probe\n");
@@ -1512,6 +1584,13 @@ static int wcn36xx_probe(struct platform_device *pdev)
goto out_wq;
}
+ n_channels = wcn_band_2ghz.n_channels + wcn_band_5ghz.n_channels;
+ wcn->chan_survey = devm_kmalloc(wcn->dev, n_channels, GFP_KERNEL);
+ if (!wcn->chan_survey) {
+ ret = -ENOMEM;
+ goto out_wq;
+ }
+
ret = dma_set_mask_and_coherent(wcn->dev, DMA_BIT_MASK(32));
if (ret < 0) {
wcn36xx_err("failed to set DMA mask: %d\n", ret);