Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
authorKalle Valo <kvalo@codeaurora.org>
Mon, 18 Jul 2016 19:50:44 +0000 (22:50 +0300)
committerKalle Valo <kvalo@codeaurora.org>
Mon, 18 Jul 2016 19:50:44 +0000 (22:50 +0300)
ath.git patches for 4.8. Major changes:

ath10k

* enable support for QCA9888

36 files changed:
drivers/net/wireless/ath/ath10k/core.c
drivers/net/wireless/ath/ath10k/core.h
drivers/net/wireless/ath/ath10k/debug.c
drivers/net/wireless/ath/ath10k/debug.h
drivers/net/wireless/ath/ath10k/debugfs_sta.c
drivers/net/wireless/ath/ath10k/htc.h
drivers/net/wireless/ath/ath10k/htt_rx.c
drivers/net/wireless/ath/ath10k/htt_tx.c
drivers/net/wireless/ath/ath10k/hw.c
drivers/net/wireless/ath/ath10k/hw.h
drivers/net/wireless/ath/ath10k/mac.c
drivers/net/wireless/ath/ath10k/pci.c
drivers/net/wireless/ath/ath10k/spectral.c
drivers/net/wireless/ath/ath10k/txrx.c
drivers/net/wireless/ath/ath10k/wmi.c
drivers/net/wireless/ath/ath10k/wmi.h
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/beacon.c
drivers/net/wireless/ath/ath9k/common.h
drivers/net/wireless/ath/ath9k/dynack.c
drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
drivers/net/wireless/ath/ath9k/htc_drv_init.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/ath9k/mac.h
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/pci.c
drivers/net/wireless/ath/wcn36xx/dxe.c
drivers/net/wireless/ath/wcn36xx/dxe.h
drivers/net/wireless/ath/wcn36xx/hal.h
drivers/net/wireless/ath/wcn36xx/main.c
drivers/net/wireless/ath/wcn36xx/smd.c
drivers/net/wireless/ath/wcn36xx/smd.h
drivers/net/wireless/ath/wcn36xx/wcn36xx.h
include/linux/ath9k_platform.h

index dfb3db0..e889829 100644 (file)
@@ -206,6 +206,28 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                        .board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ,
                },
        },
+       {
+               .id = QCA9888_HW_2_0_DEV_VERSION,
+               .dev_id = QCA9888_2_0_DEVICE_ID,
+               .name = "qca9888 hw2.0",
+               .patch_load_addr = QCA9888_HW_2_0_PATCH_LOAD_ADDR,
+               .uart_pin = 7,
+               .otp_exe_param = 0x00000700,
+               .continuous_frag_desc = true,
+               .channel_counters_freq_hz = 150000,
+               .max_probe_resp_desc_thres = 24,
+               .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE,
+               .tx_chain_mask = 3,
+               .rx_chain_mask = 3,
+               .max_spatial_stream = 2,
+               .cal_data_len = 12064,
+               .fw = {
+                       .dir = QCA9888_HW_2_0_FW_DIR,
+                       .board = QCA9888_HW_2_0_BOARD_DATA_FILE,
+                       .board_size = QCA99X0_BOARD_DATA_SZ,
+                       .board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ,
+               },
+       },
        {
                .id = QCA9377_HW_1_0_DEV_VERSION,
                .dev_id = QCA9377_1_0_DEVICE_ID,
@@ -1675,7 +1697,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
                case ATH10K_FW_WMI_OP_VERSION_10_4:
                case ATH10K_FW_WMI_OP_VERSION_UNSET:
                case ATH10K_FW_WMI_OP_VERSION_MAX:
-                       WARN_ON(1);
+                       ath10k_err(ar, "htt op version not found from fw meta data");
                        return -EINVAL;
                }
        }
@@ -2171,6 +2193,10 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
                ar->regs = &qca99x0_regs;
                ar->hw_values = &qca99x0_values;
                break;
+       case ATH10K_HW_QCA9888:
+               ar->regs = &qca99x0_regs;
+               ar->hw_values = &qca9888_values;
+               break;
        case ATH10K_HW_QCA4019:
                ar->regs = &qca4019_regs;
                ar->hw_values = &qca4019_values;
index 3da18c9..9374bcd 100644 (file)
@@ -165,6 +165,13 @@ struct ath10k_fw_stats_peer {
        u32 rx_duration;
 };
 
+struct ath10k_fw_extd_stats_peer {
+       struct list_head list;
+
+       u8 peer_macaddr[ETH_ALEN];
+       u32 rx_duration;
+};
+
 struct ath10k_fw_stats_vdev {
        struct list_head list;
 
@@ -256,9 +263,11 @@ struct ath10k_fw_stats_pdev {
 };
 
 struct ath10k_fw_stats {
+       bool extended;
        struct list_head pdevs;
        struct list_head vdevs;
        struct list_head peers;
+       struct list_head peers_extd;
 };
 
 #define ATH10K_TPC_TABLE_TYPE_FLAG     1
index 8fbb8f2..355e1ae 100644 (file)
@@ -313,13 +313,25 @@ static void ath10k_fw_stats_peers_free(struct list_head *head)
        }
 }
 
+static void ath10k_fw_extd_stats_peers_free(struct list_head *head)
+{
+       struct ath10k_fw_extd_stats_peer *i, *tmp;
+
+       list_for_each_entry_safe(i, tmp, head, list) {
+               list_del(&i->list);
+               kfree(i);
+       }
+}
+
 static void ath10k_debug_fw_stats_reset(struct ath10k *ar)
 {
        spin_lock_bh(&ar->data_lock);
        ar->debug.fw_stats_done = false;
+       ar->debug.fw_stats.extended = false;
        ath10k_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs);
        ath10k_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs);
        ath10k_fw_stats_peers_free(&ar->debug.fw_stats.peers);
+       ath10k_fw_extd_stats_peers_free(&ar->debug.fw_stats.peers_extd);
        spin_unlock_bh(&ar->data_lock);
 }
 
@@ -334,6 +346,7 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
        INIT_LIST_HEAD(&stats.pdevs);
        INIT_LIST_HEAD(&stats.vdevs);
        INIT_LIST_HEAD(&stats.peers);
+       INIT_LIST_HEAD(&stats.peers_extd);
 
        spin_lock_bh(&ar->data_lock);
        ret = ath10k_wmi_pull_fw_stats(ar, skb, &stats);
@@ -354,7 +367,7 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
         *     delivered which is treated as end-of-data and is itself discarded
         */
        if (ath10k_peer_stats_enabled(ar))
-               ath10k_sta_update_rx_duration(ar, &stats.peers);
+               ath10k_sta_update_rx_duration(ar, &stats);
 
        if (ar->debug.fw_stats_done) {
                if (!ath10k_peer_stats_enabled(ar))
@@ -396,6 +409,8 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
 
                list_splice_tail_init(&stats.peers, &ar->debug.fw_stats.peers);
                list_splice_tail_init(&stats.vdevs, &ar->debug.fw_stats.vdevs);
+               list_splice_tail_init(&stats.peers_extd,
+                                     &ar->debug.fw_stats.peers_extd);
        }
 
        complete(&ar->debug.fw_stats_complete);
@@ -407,6 +422,7 @@ free:
        ath10k_fw_stats_pdevs_free(&stats.pdevs);
        ath10k_fw_stats_vdevs_free(&stats.vdevs);
        ath10k_fw_stats_peers_free(&stats.peers);
+       ath10k_fw_extd_stats_peers_free(&stats.peers_extd);
 
        spin_unlock_bh(&ar->data_lock);
 }
@@ -2330,6 +2346,7 @@ int ath10k_debug_create(struct ath10k *ar)
        INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs);
        INIT_LIST_HEAD(&ar->debug.fw_stats.vdevs);
        INIT_LIST_HEAD(&ar->debug.fw_stats.peers);
+       INIT_LIST_HEAD(&ar->debug.fw_stats.peers_extd);
 
        return 0;
 }
index 75c89e3..c458fa9 100644 (file)
@@ -154,10 +154,15 @@ ath10k_debug_get_new_fw_crash_data(struct ath10k *ar)
 #ifdef CONFIG_MAC80211_DEBUGFS
 void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                            struct ieee80211_sta *sta, struct dentry *dir);
-void ath10k_sta_update_rx_duration(struct ath10k *ar, struct list_head *peer);
+void ath10k_sta_update_rx_duration(struct ath10k *ar,
+                                  struct ath10k_fw_stats *stats);
+void ath10k_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                          struct ieee80211_sta *sta,
+                          struct station_info *sinfo);
 #else
-static inline void ath10k_sta_update_rx_duration(struct ath10k *ar,
-                                                struct list_head *peer)
+static inline
+void ath10k_sta_update_rx_duration(struct ath10k *ar,
+                                  struct ath10k_fw_stats *stats)
 {
 }
 #endif /* CONFIG_MAC80211_DEBUGFS */
index 67ef75b..9955fea 100644 (file)
 #include "wmi-ops.h"
 #include "debug.h"
 
-void ath10k_sta_update_rx_duration(struct ath10k *ar, struct list_head *head)
-{      struct ieee80211_sta *sta;
+static void ath10k_sta_update_extd_stats_rx_duration(struct ath10k *ar,
+                                                    struct ath10k_fw_stats *stats)
+{
+       struct ath10k_fw_extd_stats_peer *peer;
+       struct ieee80211_sta *sta;
+       struct ath10k_sta *arsta;
+
+       rcu_read_lock();
+       list_for_each_entry(peer, &stats->peers_extd, list) {
+               sta = ieee80211_find_sta_by_ifaddr(ar->hw, peer->peer_macaddr,
+                                                  NULL);
+               if (!sta)
+                       continue;
+               arsta = (struct ath10k_sta *)sta->drv_priv;
+               arsta->rx_duration += (u64)peer->rx_duration;
+       }
+       rcu_read_unlock();
+}
+
+static void ath10k_sta_update_stats_rx_duration(struct ath10k *ar,
+                                               struct ath10k_fw_stats *stats)
+{
        struct ath10k_fw_stats_peer *peer;
+       struct ieee80211_sta *sta;
        struct ath10k_sta *arsta;
 
        rcu_read_lock();
-       list_for_each_entry(peer, head, list) {
+       list_for_each_entry(peer, &stats->peers, list) {
                sta = ieee80211_find_sta_by_ifaddr(ar->hw, peer->peer_macaddr,
                                                   NULL);
                if (!sta)
@@ -35,6 +56,29 @@ void ath10k_sta_update_rx_duration(struct ath10k *ar, struct list_head *head)
        rcu_read_unlock();
 }
 
+void ath10k_sta_update_rx_duration(struct ath10k *ar,
+                                  struct ath10k_fw_stats *stats)
+{
+       if (stats->extended)
+               ath10k_sta_update_extd_stats_rx_duration(ar, stats);
+       else
+               ath10k_sta_update_stats_rx_duration(ar, stats);
+}
+
+void ath10k_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                          struct ieee80211_sta *sta,
+                          struct station_info *sinfo)
+{
+       struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
+       struct ath10k *ar = arsta->arvif->ar;
+
+       if (!ath10k_peer_stats_enabled(ar))
+               return;
+
+       sinfo->rx_duration = arsta->rx_duration;
+       sinfo->filled |= 1ULL << NL80211_STA_INFO_RX_DURATION;
+}
+
 static ssize_t ath10k_dbg_sta_read_aggr_mode(struct file *file,
                                             char __user *user_buf,
                                             size_t count, loff_t *ppos)
@@ -249,28 +293,6 @@ static const struct file_operations fops_delba = {
        .llseek = default_llseek,
 };
 
-static ssize_t ath10k_dbg_sta_read_rx_duration(struct file *file,
-                                              char __user *user_buf,
-                                              size_t count, loff_t *ppos)
-{
-       struct ieee80211_sta *sta = file->private_data;
-       struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
-       char buf[100];
-       int len = 0;
-
-       len = scnprintf(buf, sizeof(buf),
-                       "%llu usecs\n", arsta->rx_duration);
-
-       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-}
-
-static const struct file_operations fops_rx_duration = {
-       .read = ath10k_dbg_sta_read_rx_duration,
-       .open = simple_open,
-       .owner = THIS_MODULE,
-       .llseek = default_llseek,
-};
-
 void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                            struct ieee80211_sta *sta, struct dentry *dir)
 {
@@ -279,6 +301,4 @@ void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
        debugfs_create_file("addba", S_IWUSR, dir, sta, &fops_addba);
        debugfs_create_file("addba_resp", S_IWUSR, dir, sta, &fops_addba_resp);
        debugfs_create_file("delba", S_IWUSR, dir, sta, &fops_delba);
-       debugfs_create_file("rx_duration", S_IRUGO, dir, sta,
-                           &fops_rx_duration);
 }
index cc82718..0c55cd9 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/list.h>
 #include <linux/bug.h>
 #include <linux/skbuff.h>
-#include <linux/semaphore.h>
 #include <linux/timer.h>
 
 struct ath10k;
index 80e6453..78db5d6 100644 (file)
@@ -748,7 +748,7 @@ ath10k_htt_rx_h_peer_channel(struct ath10k *ar, struct htt_rx_desc *rxd)
        if (WARN_ON_ONCE(!arvif))
                return NULL;
 
-       if (WARN_ON_ONCE(ath10k_mac_vif_chan(arvif->vif, &def)))
+       if (ath10k_mac_vif_chan(arvif->vif, &def))
                return NULL;
 
        return def.chan;
@@ -2307,12 +2307,10 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
                ath10k_htt_rx_delba(ar, resp);
                break;
        case HTT_T2H_MSG_TYPE_PKTLOG: {
-               struct ath10k_pktlog_hdr *hdr =
-                       (struct ath10k_pktlog_hdr *)resp->pktlog_msg.payload;
-
                trace_ath10k_htt_pktlog(ar, resp->pktlog_msg.payload,
-                                       sizeof(*hdr) +
-                                       __le16_to_cpu(hdr->size));
+                                       skb->len -
+                                       offsetof(struct htt_resp,
+                                                pktlog_msg.payload));
                break;
        }
        case HTT_T2H_MSG_TYPE_RX_FLUSH: {
index 6269c61..7c072b6 100644 (file)
@@ -49,7 +49,7 @@ static void __ath10k_htt_tx_txq_recalc(struct ieee80211_hw *hw,
                                       struct ieee80211_txq *txq)
 {
        struct ath10k *ar = hw->priv;
-       struct ath10k_sta *arsta = (void *)txq->sta->drv_priv;
+       struct ath10k_sta *arsta;
        struct ath10k_vif *arvif = (void *)txq->vif->drv_priv;
        unsigned long frame_cnt;
        unsigned long byte_cnt;
@@ -67,10 +67,12 @@ static void __ath10k_htt_tx_txq_recalc(struct ieee80211_hw *hw,
        if (ar->htt.tx_q_state.mode != HTT_TX_MODE_SWITCH_PUSH_PULL)
                return;
 
-       if (txq->sta)
+       if (txq->sta) {
+               arsta = (void *)txq->sta->drv_priv;
                peer_id = arsta->peer_id;
-       else
+       } else {
                peer_id = arvif->peer_id;
+       }
 
        tid = txq->tid;
        bit = BIT(peer_id % 32);
@@ -388,6 +390,8 @@ void ath10k_htt_tx_free(struct ath10k_htt *htt)
 {
        int size;
 
+       tasklet_kill(&htt->txrx_compl_task);
+
        idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar);
        idr_destroy(&htt->pending_tx);
 
@@ -733,16 +737,18 @@ static u8 ath10k_htt_tx_get_vdev_id(struct ath10k *ar, struct sk_buff *skb)
 {
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb);
-       struct ath10k_vif *arvif = (void *)cb->vif->drv_priv;
+       struct ath10k_vif *arvif;
 
-       if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)
+       if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
                return ar->scan.vdev_id;
-       else if (cb->vif)
+       } else if (cb->vif) {
+               arvif = (void *)cb->vif->drv_priv;
                return arvif->vdev_id;
-       else if (ar->monitor_started)
+       } else if (ar->monitor_started) {
                return ar->monitor_vdev_id;
-       else
+       } else {
                return 0;
+       }
 }
 
 static u8 ath10k_htt_tx_get_tid(struct sk_buff *skb, bool is_eth)
index bd86e7a..f903d46 100644 (file)
@@ -19,7 +19,6 @@
 #include "hw.h"
 
 const struct ath10k_hw_regs qca988x_regs = {
-       .rtc_state_cold_reset_mask      = 0x00000400,
        .rtc_soc_base_address           = 0x00004000,
        .rtc_wmac_base_address          = 0x00005000,
        .soc_core_base_address          = 0x00009000,
@@ -46,7 +45,6 @@ const struct ath10k_hw_regs qca988x_regs = {
 };
 
 const struct ath10k_hw_regs qca6174_regs = {
-       .rtc_state_cold_reset_mask              = 0x00002000,
        .rtc_soc_base_address                   = 0x00000800,
        .rtc_wmac_base_address                  = 0x00001000,
        .soc_core_base_address                  = 0x0003a000,
@@ -73,7 +71,6 @@ const struct ath10k_hw_regs qca6174_regs = {
 };
 
 const struct ath10k_hw_regs qca99x0_regs = {
-       .rtc_state_cold_reset_mask              = 0x00000400,
        .rtc_soc_base_address                   = 0x00080000,
        .rtc_wmac_base_address                  = 0x00000000,
        .soc_core_base_address                  = 0x00082000,
@@ -168,6 +165,15 @@ const struct ath10k_hw_values qca99x0_values = {
        .ce_desc_meta_data_lsb          = 4,
 };
 
+const struct ath10k_hw_values qca9888_values = {
+       .rtc_state_val_on               = 3,
+       .ce_count                       = 12,
+       .msi_assign_ce_max              = 12,
+       .num_target_ce_config_wlan      = 10,
+       .ce_desc_meta_data_mask         = 0xFFF0,
+       .ce_desc_meta_data_lsb          = 4,
+};
+
 const struct ath10k_hw_values qca4019_values = {
        .ce_count                       = 12,
        .num_target_ce_config_wlan      = 10,
@@ -198,7 +204,8 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
                case ATH10K_HW_CC_WRAP_SHIFTED_EACH:
                        if (cc < cc_prev)
                                cc_fix = 0x7fffffff;
-                       else
+
+                       if (rcc < rcc_prev)
                                rcc_fix = 0x7fffffff;
                        break;
                case ATH10K_HW_CC_WRAP_DISABLED:
index f31d3ce..e014cd7 100644 (file)
@@ -26,6 +26,7 @@
 #define QCA6164_2_1_DEVICE_ID   (0x0041)
 #define QCA6174_2_1_DEVICE_ID   (0x003e)
 #define QCA99X0_2_0_DEVICE_ID   (0x0040)
+#define QCA9888_2_0_DEVICE_ID  (0x0056)
 #define QCA9984_1_0_DEVICE_ID  (0x0046)
 #define QCA9377_1_0_DEVICE_ID   (0x0042)
 #define QCA9887_1_0_DEVICE_ID   (0x0050)
@@ -108,6 +109,14 @@ enum qca9377_chip_id_rev {
 #define QCA9984_HW_1_0_BOARD_DATA_FILE "board.bin"
 #define QCA9984_HW_1_0_PATCH_LOAD_ADDR 0x1234
 
+/* QCA9888 2.0 defines */
+#define QCA9888_HW_2_0_DEV_VERSION     0x1000000
+#define QCA9888_HW_DEV_TYPE            0xc
+#define QCA9888_HW_2_0_CHIP_ID_REV     0x0
+#define QCA9888_HW_2_0_FW_DIR          ATH10K_FW_DIR "/QCA9888/hw2.0"
+#define QCA9888_HW_2_0_BOARD_DATA_FILE "board.bin"
+#define QCA9888_HW_2_0_PATCH_LOAD_ADDR 0x1234
+
 /* QCA9377 1.0 definitions */
 #define QCA9377_HW_1_0_FW_DIR          ATH10K_FW_DIR "/QCA9377/hw1.0"
 #define QCA9377_HW_1_0_BOARD_DATA_FILE "board.bin"
@@ -210,6 +219,7 @@ enum ath10k_hw_rev {
        ATH10K_HW_QCA988X,
        ATH10K_HW_QCA6174,
        ATH10K_HW_QCA99X0,
+       ATH10K_HW_QCA9888,
        ATH10K_HW_QCA9984,
        ATH10K_HW_QCA9377,
        ATH10K_HW_QCA4019,
@@ -217,7 +227,6 @@ enum ath10k_hw_rev {
 };
 
 struct ath10k_hw_regs {
-       u32 rtc_state_cold_reset_mask;
        u32 rtc_soc_base_address;
        u32 rtc_wmac_base_address;
        u32 soc_core_base_address;
@@ -260,6 +269,7 @@ struct ath10k_hw_values {
 extern const struct ath10k_hw_values qca988x_values;
 extern const struct ath10k_hw_values qca6174_values;
 extern const struct ath10k_hw_values qca99x0_values;
+extern const struct ath10k_hw_values qca9888_values;
 extern const struct ath10k_hw_values qca4019_values;
 
 void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
@@ -269,6 +279,7 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
 #define QCA_REV_9887(ar) ((ar)->hw_rev == ATH10K_HW_QCA9887)
 #define QCA_REV_6174(ar) ((ar)->hw_rev == ATH10K_HW_QCA6174)
 #define QCA_REV_99X0(ar) ((ar)->hw_rev == ATH10K_HW_QCA99X0)
+#define QCA_REV_9888(ar) ((ar)->hw_rev == ATH10K_HW_QCA9888)
 #define QCA_REV_9984(ar) ((ar)->hw_rev == ATH10K_HW_QCA9984)
 #define QCA_REV_9377(ar) ((ar)->hw_rev == ATH10K_HW_QCA9377)
 #define QCA_REV_40XX(ar) ((ar)->hw_rev == ATH10K_HW_QCA4019)
@@ -296,25 +307,6 @@ enum ath10k_mcast2ucast_mode {
        ATH10K_MCAST2UCAST_ENABLED = 1,
 };
 
-struct ath10k_pktlog_hdr {
-       __le16 flags;
-       __le16 missed_cnt;
-       __le16 log_type;
-       __le16 size;
-       __le32 timestamp;
-       u8 payload[0];
-} __packed;
-
-struct ath10k_pktlog_10_4_hdr {
-       __le16 flags;
-       __le16 missed_cnt;
-       __le16 log_type;
-       __le16 size;
-       __le32 timestamp;
-       __le32 type_specific_data;
-       u8 payload[0];
-} __packed;
-
 enum ath10k_hw_rate_ofdm {
        ATH10K_HW_RATE_OFDM_48M = 0,
        ATH10K_HW_RATE_OFDM_24M,
@@ -535,7 +527,6 @@ enum ath10k_hw_cc_wraparound_type {
 /* as of IP3.7.1 */
 #define RTC_STATE_V_ON                         ar->hw_values->rtc_state_val_on
 
-#define RTC_STATE_COLD_RESET_MASK              ar->regs->rtc_state_cold_reset_mask
 #define RTC_STATE_V_LSB                                0
 #define RTC_STATE_V_MASK                       0x00000007
 #define RTC_STATE_ADDRESS                      0x0000
index ebc12c5..55c823f 100644 (file)
@@ -802,6 +802,7 @@ static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id)
 {
        struct ath10k_peer *peer, *tmp;
        int peer_id;
+       int i;
 
        lockdep_assert_held(&ar->conf_mutex);
 
@@ -818,6 +819,17 @@ static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id)
                        ar->peer_map[peer_id] = NULL;
                }
 
+               /* Double check that peer is properly un-referenced from
+                * the peer_map
+                */
+               for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) {
+                       if (ar->peer_map[i] == peer) {
+                               ath10k_warn(ar, "removing stale peer_map entry for %pM (ptr %p idx %d)\n",
+                                           peer->addr, peer, i);
+                               ar->peer_map[i] = NULL;
+                       }
+               }
+
                list_del(&peer->list);
                kfree(peer);
                ar->num_peers--;
@@ -828,6 +840,7 @@ static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id)
 static void ath10k_peer_cleanup_all(struct ath10k *ar)
 {
        struct ath10k_peer *peer, *tmp;
+       int i;
 
        lockdep_assert_held(&ar->conf_mutex);
 
@@ -836,6 +849,10 @@ static void ath10k_peer_cleanup_all(struct ath10k *ar)
                list_del(&peer->list);
                kfree(peer);
        }
+
+       for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++)
+               ar->peer_map[i] = NULL;
+
        spin_unlock_bh(&ar->data_lock);
 
        ar->num_peers = 0;
@@ -2939,7 +2956,7 @@ static int ath10k_update_channel_list(struct ath10k *ar)
                        if (channel->flags & IEEE80211_CHAN_DISABLED)
                                continue;
 
-                       ch->allow_ht   = true;
+                       ch->allow_ht = true;
 
                        /* FIXME: when should we really allow VHT? */
                        ch->allow_vht = true;
@@ -3675,17 +3692,18 @@ void ath10k_mgmt_over_wmi_tx_work(struct work_struct *work)
 
 static void ath10k_mac_txq_init(struct ieee80211_txq *txq)
 {
-       struct ath10k_txq *artxq = (void *)txq->drv_priv;
+       struct ath10k_txq *artxq;
 
        if (!txq)
                return;
 
+       artxq = (void *)txq->drv_priv;
        INIT_LIST_HEAD(&artxq->list);
 }
 
 static void ath10k_mac_txq_unref(struct ath10k *ar, struct ieee80211_txq *txq)
 {
-       struct ath10k_txq *artxq = (void *)txq->drv_priv;
+       struct ath10k_txq *artxq;
        struct ath10k_skb_cb *cb;
        struct sk_buff *msdu;
        int msdu_id;
@@ -3693,6 +3711,7 @@ static void ath10k_mac_txq_unref(struct ath10k *ar, struct ieee80211_txq *txq)
        if (!txq)
                return;
 
+       artxq = (void *)txq->drv_priv;
        spin_lock_bh(&ar->txqs_lock);
        if (!list_empty(&artxq->list))
                list_del_init(&artxq->list);
@@ -4228,6 +4247,9 @@ static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
                        mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2);
        }
 
+       if (ar->cfg_tx_chainmask <= 1)
+               vht_cap.cap &= ~IEEE80211_VHT_CAP_TXSTBC;
+
        vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
        vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
 
@@ -4265,7 +4287,7 @@ static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar)
                ht_cap.cap |= smps;
        }
 
-       if (ar->ht_cap_info & WMI_HT_CAP_TX_STBC)
+       if (ar->ht_cap_info & WMI_HT_CAP_TX_STBC && (ar->cfg_tx_chainmask > 1))
                ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
 
        if (ar->ht_cap_info & WMI_HT_CAP_RX_STBC) {
@@ -5979,9 +6001,17 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
                                continue;
 
                        if (peer->sta == sta) {
-                               ath10k_warn(ar, "found sta peer %pM entry on vdev %i after it was supposedly removed\n",
-                                           sta->addr, arvif->vdev_id);
+                               ath10k_warn(ar, "found sta peer %pM (ptr %p id %d) entry on vdev %i after it was supposedly removed\n",
+                                           sta->addr, peer, i, arvif->vdev_id);
                                peer->sta = NULL;
+
+                               /* Clean up the peer object as well since we
+                                * must have failed to do this above.
+                                */
+                               list_del(&peer->list);
+                               ar->peer_map[i] = NULL;
+                               kfree(peer);
+                               ar->num_peers--;
                        }
                }
                spin_unlock_bh(&ar->data_lock);
@@ -7406,6 +7436,7 @@ static const struct ieee80211_ops ath10k_ops = {
 #endif
 #ifdef CONFIG_MAC80211_DEBUGFS
        .sta_add_debugfs                = ath10k_sta_add_debugfs,
+       .sta_statistics                 = ath10k_sta_statistics,
 #endif
 };
 
index f06dd39..9a22c47 100644 (file)
@@ -56,6 +56,7 @@ static const struct pci_device_id ath10k_pci_id_table[] = {
        { PCI_VDEVICE(ATHEROS, QCA6164_2_1_DEVICE_ID) }, /* PCI-E QCA6164 V2.1 */
        { PCI_VDEVICE(ATHEROS, QCA6174_2_1_DEVICE_ID) }, /* PCI-E QCA6174 V2.1 */
        { PCI_VDEVICE(ATHEROS, QCA99X0_2_0_DEVICE_ID) }, /* PCI-E QCA99X0 V2 */
+       { PCI_VDEVICE(ATHEROS, QCA9888_2_0_DEVICE_ID) }, /* PCI-E QCA9888 V2 */
        { PCI_VDEVICE(ATHEROS, QCA9984_1_0_DEVICE_ID) }, /* PCI-E QCA9984 V1 */
        { PCI_VDEVICE(ATHEROS, QCA9377_1_0_DEVICE_ID) }, /* PCI-E QCA9377 V1 */
        { PCI_VDEVICE(ATHEROS, QCA9887_1_0_DEVICE_ID) }, /* PCI-E QCA9887 */
@@ -85,6 +86,8 @@ static const struct ath10k_pci_supp_chip ath10k_pci_supp_chips[] = {
 
        { QCA9984_1_0_DEVICE_ID, QCA9984_HW_1_0_CHIP_ID_REV },
 
+       { QCA9888_2_0_DEVICE_ID, QCA9888_HW_2_0_CHIP_ID_REV },
+
        { QCA9377_1_0_DEVICE_ID, QCA9377_HW_1_0_CHIP_ID_REV },
        { QCA9377_1_0_DEVICE_ID, QCA9377_HW_1_1_CHIP_ID_REV },
 
@@ -850,6 +853,7 @@ static u32 ath10k_pci_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr)
                                          CORE_CTRL_ADDRESS) &
                       0x7ff) << 21;
                break;
+       case ATH10K_HW_QCA9888:
        case ATH10K_HW_QCA99X0:
        case ATH10K_HW_QCA9984:
        case ATH10K_HW_QCA4019:
@@ -1583,6 +1587,7 @@ static void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar)
                break;
        case ATH10K_HW_QCA99X0:
        case ATH10K_HW_QCA9984:
+       case ATH10K_HW_QCA9888:
        case ATH10K_HW_QCA4019:
                /* TODO: Find appropriate register configuration for QCA99X0
                 *  to mask irq/MSI.
@@ -1608,6 +1613,7 @@ static void ath10k_pci_irq_msi_fw_unmask(struct ath10k *ar)
                break;
        case ATH10K_HW_QCA99X0:
        case ATH10K_HW_QCA9984:
+       case ATH10K_HW_QCA9888:
        case ATH10K_HW_QCA4019:
                /* TODO: Find appropriate register configuration for QCA99X0
                 *  to unmask irq/MSI.
@@ -1948,6 +1954,7 @@ static int ath10k_pci_get_num_banks(struct ath10k *ar)
        switch (ar_pci->pdev->device) {
        case QCA988X_2_0_DEVICE_ID:
        case QCA99X0_2_0_DEVICE_ID:
+       case QCA9888_2_0_DEVICE_ID:
        case QCA9984_1_0_DEVICE_ID:
        case QCA9887_1_0_DEVICE_ID:
                return 1;
@@ -2216,6 +2223,14 @@ static void ath10k_pci_fw_crashed_clear(struct ath10k *ar)
        ath10k_pci_write32(ar, FW_INDICATOR_ADDRESS, val);
 }
 
+static bool ath10k_pci_has_device_gone(struct ath10k *ar)
+{
+       u32 val;
+
+       val = ath10k_pci_read32(ar, FW_INDICATOR_ADDRESS);
+       return (val == 0xffffffff);
+}
+
 /* this function effectively clears target memory controller assert line */
 static void ath10k_pci_warm_reset_si0(struct ath10k *ar)
 {
@@ -2748,6 +2763,9 @@ static irqreturn_t ath10k_pci_interrupt_handler(int irq, void *arg)
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
        int ret;
 
+       if (ath10k_pci_has_device_gone(ar))
+               return IRQ_NONE;
+
        ret = ath10k_pci_force_wake(ar);
        if (ret) {
                ath10k_warn(ar, "failed to wake device up on irq: %d\n", ret);
@@ -3169,6 +3187,12 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
                pci_soft_reset = ath10k_pci_qca99x0_soft_chip_reset;
                pci_hard_reset = ath10k_pci_qca99x0_chip_reset;
                break;
+       case QCA9888_2_0_DEVICE_ID:
+               hw_rev = ATH10K_HW_QCA9888;
+               pci_ps = false;
+               pci_soft_reset = ath10k_pci_qca99x0_soft_chip_reset;
+               pci_hard_reset = ath10k_pci_qca99x0_chip_reset;
+               break;
        case QCA9377_1_0_DEVICE_ID:
                hw_rev = ATH10K_HW_QCA9377;
                pci_ps = true;
index 4671cfb..7d9b0da 100644 (file)
@@ -101,9 +101,9 @@ int ath10k_spectral_process_fft(struct ath10k *ar,
                break;
        case 80:
                /* TODO: As experiments with an analogue sender and various
-                * configuaritions (fft-sizes of 64/128/256 and 20/40/80 Mhz)
+                * configurations (fft-sizes of 64/128/256 and 20/40/80 Mhz)
                 * show, the particular configuration of 80 MHz/64 bins does
-                * not match with the other smaples at all. Until the reason
+                * not match with the other samples at all. Until the reason
                 * for that is found, don't report these samples.
                 */
                if (bin_len == 64)
index 1966c78..b29a86a 100644 (file)
@@ -81,10 +81,11 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
 
        skb_cb = ATH10K_SKB_CB(msdu);
        txq = skb_cb->txq;
-       artxq = (void *)txq->drv_priv;
 
-       if (txq)
+       if (txq) {
+               artxq = (void *)txq->drv_priv;
                artxq->num_fw_queued--;
+       }
 
        ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id);
        ath10k_htt_tx_dec_pending(htt);
@@ -216,6 +217,7 @@ void ath10k_peer_map_event(struct ath10k_htt *htt,
        ath10k_dbg(ar, ATH10K_DBG_HTT, "htt peer map vdev %d peer %pM id %d\n",
                   ev->vdev_id, ev->addr, ev->peer_id);
 
+       WARN_ON(ar->peer_map[ev->peer_id] && (ar->peer_map[ev->peer_id] != peer));
        ar->peer_map[ev->peer_id] = peer;
        set_bit(ev->peer_id, peer->peer_ids);
 exit:
index 6279ab4..169cd2e 100644 (file)
@@ -1826,7 +1826,7 @@ static struct sk_buff *
 ath10k_wmi_op_gen_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu)
 {
        struct ath10k_skb_cb *cb = ATH10K_SKB_CB(msdu);
-       struct ath10k_vif *arvif = (void *)cb->vif->drv_priv;
+       struct ath10k_vif *arvif;
        struct wmi_mgmt_tx_cmd *cmd;
        struct ieee80211_hdr *hdr;
        struct sk_buff *skb;
@@ -1838,10 +1838,12 @@ ath10k_wmi_op_gen_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu)
        hdr = (struct ieee80211_hdr *)msdu->data;
        fc = le16_to_cpu(hdr->frame_control);
 
-       if (cb->vif)
+       if (cb->vif) {
+               arvif = (void *)cb->vif->drv_priv;
                vdev_id = arvif->vdev_id;
-       else
+       } else {
                vdev_id = 0;
+       }
 
        if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control)))
                return ERR_PTR(-EINVAL);
@@ -2924,6 +2926,7 @@ static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar,
        u32 num_pdev_ext_stats;
        u32 num_vdev_stats;
        u32 num_peer_stats;
+       u32 num_bcnflt_stats;
        u32 stats_id;
        int i;
 
@@ -2934,6 +2937,7 @@ static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar,
        num_pdev_ext_stats = __le32_to_cpu(ev->num_pdev_ext_stats);
        num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
        num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
+       num_bcnflt_stats = __le32_to_cpu(ev->num_bcnflt_stats);
        stats_id = __le32_to_cpu(ev->stats_id);
 
        for (i = 0; i < num_pdev_stats; i++) {
@@ -2974,32 +2978,57 @@ static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar,
        /* fw doesn't implement vdev stats */
 
        for (i = 0; i < num_peer_stats; i++) {
-               const struct wmi_10_4_peer_extd_stats *src;
+               const struct wmi_10_4_peer_stats *src;
                struct ath10k_fw_stats_peer *dst;
-               int stats_len;
-               bool extd_peer_stats = !!(stats_id & WMI_10_4_STAT_PEER_EXTD);
-
-               if (extd_peer_stats)
-                       stats_len = sizeof(struct wmi_10_4_peer_extd_stats);
-               else
-                       stats_len = sizeof(struct wmi_10_4_peer_stats);
 
                src = (void *)skb->data;
-               if (!skb_pull(skb, stats_len))
+               if (!skb_pull(skb, sizeof(*src)))
                        return -EPROTO;
 
                dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
                if (!dst)
                        continue;
 
-               ath10k_wmi_10_4_pull_peer_stats(&src->common, dst);
-               /* FIXME: expose 10.4 specific values */
-               if (extd_peer_stats)
-                       dst->rx_duration = __le32_to_cpu(src->rx_duration);
-
+               ath10k_wmi_10_4_pull_peer_stats(src, dst);
                list_add_tail(&dst->list, &stats->peers);
        }
 
+       for (i = 0; i < num_bcnflt_stats; i++) {
+               const struct wmi_10_4_bss_bcn_filter_stats *src;
+
+               src = (void *)skb->data;
+               if (!skb_pull(skb, sizeof(*src)))
+                       return -EPROTO;
+
+               /* FIXME: expose values to userspace
+                *
+                * Note: Even though this loop seems to do nothing it is
+                * required to parse following sub-structures properly.
+                */
+       }
+
+       if ((stats_id & WMI_10_4_STAT_PEER_EXTD) == 0)
+               return 0;
+
+       stats->extended = true;
+
+       for (i = 0; i < num_peer_stats; i++) {
+               const struct wmi_10_4_peer_extd_stats *src;
+               struct ath10k_fw_extd_stats_peer *dst;
+
+               src = (void *)skb->data;
+               if (!skb_pull(skb, sizeof(*src)))
+                       return -EPROTO;
+
+               dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
+               if (!dst)
+                       continue;
+
+               ether_addr_copy(dst->peer_macaddr, src->peer_macaddr.addr);
+               dst->rx_duration = __le32_to_cpu(src->rx_duration);
+               list_add_tail(&dst->list, &stats->peers_extd);
+       }
+
        return 0;
 }
 
@@ -5257,6 +5286,9 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb)
        case WMI_10_4_PEER_STA_KICKOUT_EVENTID:
                ath10k_wmi_event_peer_sta_kickout(ar, skb);
                break;
+       case WMI_10_4_ROAM_EVENTID:
+               ath10k_wmi_event_roam(ar, skb);
+               break;
        case WMI_10_4_HOST_SWBA_EVENTID:
                ath10k_wmi_event_host_swba(ar, skb);
                break;
@@ -7903,6 +7935,7 @@ static const struct wmi_ops wmi_10_4_ops = {
        .pull_phyerr = ath10k_wmi_10_4_op_pull_phyerr_ev,
        .pull_svc_rdy = ath10k_wmi_main_op_pull_svc_rdy_ev,
        .pull_rdy = ath10k_wmi_op_pull_rdy_ev,
+       .pull_roam_ev = ath10k_wmi_op_pull_roam_ev,
        .get_txbf_conf_scheme = ath10k_wmi_10_4_txbf_conf_scheme,
 
        .gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend,
index 90f594e..3ef4688 100644 (file)
@@ -4340,7 +4340,6 @@ struct wmi_10_4_peer_stats {
 } __packed;
 
 struct wmi_10_4_peer_extd_stats {
-       struct wmi_10_4_peer_stats common;
        struct wmi_mac_addr peer_macaddr;
        __le32 inactive_time;
        __le32 peer_chain_rssi;
@@ -4348,6 +4347,19 @@ struct wmi_10_4_peer_extd_stats {
        __le32 reserved[10];
 } __packed;
 
+struct wmi_10_4_bss_bcn_stats {
+       __le32 vdev_id;
+       __le32 bss_bcns_dropped;
+       __le32 bss_bcn_delivered;
+} __packed;
+
+struct wmi_10_4_bss_bcn_filter_stats {
+       __le32 bcns_dropped;
+       __le32 bcns_delivered;
+       __le32 active_filters;
+       struct wmi_10_4_bss_bcn_stats bss_stats;
+} __packed;
+
 struct wmi_10_2_pdev_ext_stats {
        __le32 rx_rssi_comb;
        __le32 rx_rssi[4];
index d0224fc..5bd2cba 100644 (file)
@@ -4175,7 +4175,7 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
        if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah) && !AR_SREV_9531(ah))
                ar9003_hw_internal_regulator_apply(ah);
        ar9003_hw_apply_tuning_caps(ah);
-       ar9003_hw_apply_minccapwr_thresh(ah, chan);
+       ar9003_hw_apply_minccapwr_thresh(ah, is2ghz);
        ar9003_hw_txend_to_xpa_off_apply(ah, is2ghz);
        ar9003_hw_thermometer_apply(ah);
        ar9003_hw_thermo_cal_apply(ah);
index 93b3793..26fc8ec 100644 (file)
@@ -637,6 +637,8 @@ struct ath9k_vif_iter_data {
        int nwds;      /* number of WDS vifs */
        int nadhocs;   /* number of adhoc vifs */
        int nocbs;     /* number of OCB vifs */
+       int nbcnvifs;  /* number of beaconing vifs */
+       struct ieee80211_vif *primary_beacon_vif;
        struct ieee80211_vif *primary_sta;
 };
 
@@ -685,10 +687,11 @@ struct ath_beacon {
 };
 
 void ath9k_beacon_tasklet(unsigned long data);
-void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif,
-                        u32 changed);
+void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *main_vif,
+                        bool beacons);
 void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
 void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
+void ath9k_beacon_ensure_primary_slot(struct ath_softc *sc);
 void ath9k_set_beacon(struct ath_softc *sc);
 bool ath9k_csa_is_finished(struct ath_softc *sc, struct ieee80211_vif *vif);
 void ath9k_csa_update(struct ath_softc *sc);
index 5cf0cd7..e36f947 100644 (file)
@@ -50,7 +50,7 @@ static void ath9k_beaconq_config(struct ath_softc *sc)
                txq = sc->tx.txq_map[IEEE80211_AC_BE];
                ath9k_hw_get_txq_props(ah, txq->axq_qnum, &qi_be);
                qi.tqi_aifs = qi_be.tqi_aifs;
-               if (ah->slottime == ATH9K_SLOT_TIME_20)
+               if (ah->slottime == 20)
                        qi.tqi_cwmin = 2*qi_be.tqi_cwmin;
                else
                        qi.tqi_cwmin = 4*qi_be.tqi_cwmin;
@@ -209,7 +209,6 @@ void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif)
        }
 
        sc->beacon.bslot[avp->av_bslot] = vif;
-       sc->nbcnvifs++;
 
        ath_dbg(common, CONFIG, "Added interface at beacon slot: %d\n",
                avp->av_bslot);
@@ -220,15 +219,12 @@ void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif)
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        struct ath_vif *avp = (void *)vif->drv_priv;
        struct ath_buf *bf = avp->av_bcbuf;
-       struct ath_beacon_config *cur_conf = &sc->cur_chan->beacon;
 
        ath_dbg(common, CONFIG, "Removing interface at beacon slot: %d\n",
                avp->av_bslot);
 
        tasklet_disable(&sc->bcon_tasklet);
 
-       cur_conf->enable_beacon &= ~BIT(avp->av_bslot);
-
        if (bf && bf->bf_mpdu) {
                struct sk_buff *skb = bf->bf_mpdu;
                dma_unmap_single(sc->dev, bf->bf_buf_addr,
@@ -240,12 +236,73 @@ void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif)
 
        avp->av_bcbuf = NULL;
        sc->beacon.bslot[avp->av_bslot] = NULL;
-       sc->nbcnvifs--;
        list_add_tail(&bf->list, &sc->beacon.bbuf);
 
        tasklet_enable(&sc->bcon_tasklet);
 }
 
+void ath9k_beacon_ensure_primary_slot(struct ath_softc *sc)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ieee80211_vif *vif;
+       struct ath_vif *avp;
+       s64 tsfadjust;
+       u32 offset;
+       int first_slot = ATH_BCBUF;
+       int slot;
+
+       tasklet_disable(&sc->bcon_tasklet);
+
+       /* Find first taken slot. */
+       for (slot = 0; slot < ATH_BCBUF; slot++) {
+               if (sc->beacon.bslot[slot]) {
+                       first_slot = slot;
+                       break;
+               }
+       }
+       if (first_slot == 0)
+               goto out;
+
+       /* Re-enumarate all slots, moving them forward. */
+       for (slot = 0; slot < ATH_BCBUF; slot++) {
+               if (slot + first_slot < ATH_BCBUF) {
+                       vif = sc->beacon.bslot[slot + first_slot];
+                       sc->beacon.bslot[slot] = vif;
+
+                       if (vif) {
+                               avp = (void *)vif->drv_priv;
+                               avp->av_bslot = slot;
+                       }
+               } else {
+                       sc->beacon.bslot[slot] = NULL;
+               }
+       }
+
+       vif = sc->beacon.bslot[0];
+       if (WARN_ON(!vif))
+               goto out;
+
+       /* Get the tsf_adjust value for the new first slot. */
+       avp = (void *)vif->drv_priv;
+       tsfadjust = le64_to_cpu(avp->tsf_adjust);
+
+       ath_dbg(common, CONFIG,
+               "Adjusting global TSF after beacon slot reassignment: %lld\n",
+               (signed long long)tsfadjust);
+
+       /* Modify TSF as required and update the HW. */
+       avp->chanctx->tsf_val += tsfadjust;
+       if (sc->cur_chan == avp->chanctx) {
+               offset = ath9k_hw_get_tsf_offset(&avp->chanctx->tsf_ts, NULL);
+               ath9k_hw_settsf64(sc->sc_ah, avp->chanctx->tsf_val + offset);
+       }
+
+       /* The slots tsf_adjust will be updated by ath9k_beacon_config later. */
+
+out:
+       tasklet_enable(&sc->bcon_tasklet);
+}
+
 static int ath9k_beacon_choose_slot(struct ath_softc *sc)
 {
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
@@ -274,22 +331,33 @@ static int ath9k_beacon_choose_slot(struct ath_softc *sc)
        return slot;
 }
 
-static void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif)
+static void ath9k_set_tsfadjust(struct ath_softc *sc,
+                               struct ath_beacon_config *cur_conf)
 {
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-       struct ath_vif *avp = (void *)vif->drv_priv;
-       struct ath_beacon_config *cur_conf = &avp->chanctx->beacon;
-       u32 tsfadjust;
+       s64 tsfadjust;
+       int slot;
 
-       if (avp->av_bslot == 0)
-               return;
+       for (slot = 0; slot < ATH_BCBUF; slot++) {
+               struct ath_vif *avp;
 
-       tsfadjust = cur_conf->beacon_interval * avp->av_bslot;
-       tsfadjust = TU_TO_USEC(tsfadjust) / ATH_BCBUF;
-       avp->tsf_adjust = cpu_to_le64(tsfadjust);
+               if (!sc->beacon.bslot[slot])
+                       continue;
 
-       ath_dbg(common, CONFIG, "tsfadjust is: %llu for bslot: %d\n",
-               (unsigned long long)tsfadjust, avp->av_bslot);
+               avp = (void *)sc->beacon.bslot[slot]->drv_priv;
+
+               /* tsf_adjust is added to the TSF value. We send out the
+                * beacon late, so need to adjust the TSF starting point to be
+                * later in time (i.e. the theoretical first beacon has a TSF
+                * of 0 after correction).
+                */
+               tsfadjust = cur_conf->beacon_interval * avp->av_bslot;
+               tsfadjust = -TU_TO_USEC(tsfadjust) / ATH_BCBUF;
+               avp->tsf_adjust = cpu_to_le64(tsfadjust);
+
+               ath_dbg(common, CONFIG, "tsfadjust is: %lld for bslot: %d\n",
+                       (signed long long)tsfadjust, avp->av_bslot);
+       }
 }
 
 bool ath9k_csa_is_finished(struct ath_softc *sc, struct ieee80211_vif *vif)
@@ -443,20 +511,28 @@ void ath9k_beacon_tasklet(unsigned long data)
  * Both nexttbtt and intval have to be in usecs.
  */
 static void ath9k_beacon_init(struct ath_softc *sc, u32 nexttbtt,
-                             u32 intval, bool reset_tsf)
+                             u32 intval)
 {
        struct ath_hw *ah = sc->sc_ah;
 
        ath9k_hw_disable_interrupts(ah);
-       if (reset_tsf)
-               ath9k_hw_reset_tsf(ah);
        ath9k_beaconq_config(sc);
        ath9k_hw_beaconinit(ah, nexttbtt, intval);
+       ah->imask |= ATH9K_INT_SWBA;
        sc->beacon.bmisscnt = 0;
        ath9k_hw_set_interrupts(ah);
        ath9k_hw_enable_interrupts(ah);
 }
 
+static void ath9k_beacon_stop(struct ath_softc *sc)
+{
+       ath9k_hw_disable_interrupts(sc->sc_ah);
+       sc->sc_ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
+       sc->beacon.bmisscnt = 0;
+       ath9k_hw_set_interrupts(sc->sc_ah);
+       ath9k_hw_enable_interrupts(sc->sc_ah);
+}
+
 /*
  * For multi-bss ap support beacons are either staggered evenly over N slots or
  * burst together.  For the former arrange for the SWBA to be delivered for each
@@ -468,7 +544,7 @@ static void ath9k_beacon_config_ap(struct ath_softc *sc,
        struct ath_hw *ah = sc->sc_ah;
 
        ath9k_cmn_beacon_config_ap(ah, conf, ATH_BCBUF);
-       ath9k_beacon_init(sc, conf->nexttbtt, conf->intval, false);
+       ath9k_beacon_init(sc, conf->nexttbtt, conf->intval);
 }
 
 static void ath9k_beacon_config_sta(struct ath_hw *ah,
@@ -497,7 +573,7 @@ static void ath9k_beacon_config_adhoc(struct ath_softc *sc,
 
        ath9k_cmn_beacon_config_adhoc(ah, conf);
 
-       ath9k_beacon_init(sc, conf->nexttbtt, conf->intval, conf->ibss_creator);
+       ath9k_beacon_init(sc, conf->nexttbtt, conf->intval);
 
        /*
         * Set the global 'beacon has been configured' flag for the
@@ -507,44 +583,6 @@ static void ath9k_beacon_config_adhoc(struct ath_softc *sc,
                set_bit(ATH_OP_BEACONS, &common->op_flags);
 }
 
-static bool ath9k_allow_beacon_config(struct ath_softc *sc,
-                                     struct ieee80211_vif *vif)
-{
-       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-       struct ath_vif *avp = (void *)vif->drv_priv;
-
-       if (ath9k_is_chanctx_enabled()) {
-               /*
-                * If the VIF is not present in the current channel context,
-                * then we can't do the usual opmode checks. Allow the
-                * beacon config for the VIF to be updated in this case and
-                * return immediately.
-                */
-               if (sc->cur_chan != avp->chanctx)
-                       return true;
-       }
-
-       if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
-               if (vif->type != NL80211_IFTYPE_AP) {
-                       ath_dbg(common, CONFIG,
-                               "An AP interface is already present !\n");
-                       return false;
-               }
-       }
-
-       if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) {
-               if ((vif->type == NL80211_IFTYPE_STATION) &&
-                   test_bit(ATH_OP_BEACONS, &common->op_flags) &&
-                   vif != sc->cur_chan->primary_sta) {
-                       ath_dbg(common, CONFIG,
-                               "Beacon already configured for a station interface\n");
-                       return false;
-               }
-       }
-
-       return true;
-}
-
 static void ath9k_cache_beacon_config(struct ath_softc *sc,
                                      struct ath_chanctx *ctx,
                                      struct ieee80211_bss_conf *bss_conf)
@@ -580,87 +618,79 @@ static void ath9k_cache_beacon_config(struct ath_softc *sc,
        if (cur_conf->dtim_period == 0)
                cur_conf->dtim_period = 1;
 
+       ath9k_set_tsfadjust(sc, cur_conf);
 }
 
-void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif,
-                        u32 changed)
+void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *main_vif,
+                        bool beacons)
 {
-       struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
-        struct ath_hw *ah = sc->sc_ah;
-        struct ath_common *common = ath9k_hw_common(ah);
-       struct ath_vif *avp = (void *)vif->drv_priv;
-       struct ath_chanctx *ctx = avp->chanctx;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath_vif *avp;
+       struct ath_chanctx *ctx;
        struct ath_beacon_config *cur_conf;
        unsigned long flags;
+       bool enabled;
        bool skip_beacon = false;
 
-       if (!ctx)
+       if (!beacons) {
+               clear_bit(ATH_OP_BEACONS, &common->op_flags);
+               ath9k_beacon_stop(sc);
                return;
+       }
 
-       cur_conf = &avp->chanctx->beacon;
-       if (vif->type == NL80211_IFTYPE_AP)
-               ath9k_set_tsfadjust(sc, vif);
-
-       if (!ath9k_allow_beacon_config(sc, vif))
+       if (WARN_ON(!main_vif))
                return;
 
-       if (vif->type == NL80211_IFTYPE_STATION) {
-               ath9k_cache_beacon_config(sc, ctx, bss_conf);
-               if (ctx != sc->cur_chan)
-                       return;
+       avp = (void *)main_vif->drv_priv;
+       ctx = avp->chanctx;
+       cur_conf = &ctx->beacon;
+       enabled = cur_conf->enable_beacon;
+       cur_conf->enable_beacon = beacons;
+
+       if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) {
+               ath9k_cache_beacon_config(sc, ctx, &main_vif->bss_conf);
 
                ath9k_set_beacon(sc);
                set_bit(ATH_OP_BEACONS, &common->op_flags);
                return;
        }
 
-       /*
-        * Take care of multiple interfaces when
-        * enabling/disabling SWBA.
-        */
-       if (changed & BSS_CHANGED_BEACON_ENABLED) {
-               bool enabled = cur_conf->enable_beacon;
-
-               if (!bss_conf->enable_beacon) {
-                       cur_conf->enable_beacon &= ~BIT(avp->av_bslot);
-               } else {
-                       cur_conf->enable_beacon |= BIT(avp->av_bslot);
-                       if (!enabled)
-                               ath9k_cache_beacon_config(sc, ctx, bss_conf);
-               }
-       }
-
-       if (ctx != sc->cur_chan)
-               return;
+       /* Update the beacon configuration. */
+       ath9k_cache_beacon_config(sc, ctx, &main_vif->bss_conf);
 
        /*
         * Configure the HW beacon registers only when we have a valid
         * beacon interval.
         */
        if (cur_conf->beacon_interval) {
-               /*
-                * If we are joining an existing IBSS network, start beaconing
-                * only after a TSF-sync has taken place. Ensure that this
-                * happens by setting the appropriate flags.
+               /* Special case to sync the TSF when joining an existing IBSS.
+                * This is only done if no AP interface is active.
+                * Note that mac80211 always resets the TSF when creating a new
+                * IBSS interface.
                 */
-               if ((changed & BSS_CHANGED_IBSS) && !bss_conf->ibss_creator &&
-                   bss_conf->enable_beacon) {
+               if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC &&
+                   !enabled && beacons && !main_vif->bss_conf.ibss_creator) {
                        spin_lock_irqsave(&sc->sc_pm_lock, flags);
                        sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
                        spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
                        skip_beacon = true;
-               } else {
-                       ath9k_set_beacon(sc);
                }
 
                /*
                 * Do not set the ATH_OP_BEACONS flag for IBSS joiner mode
                 * here, it is done in ath9k_beacon_config_adhoc().
                 */
-               if (cur_conf->enable_beacon && !skip_beacon)
+               if (beacons && !skip_beacon) {
                        set_bit(ATH_OP_BEACONS, &common->op_flags);
-               else
+                       ath9k_set_beacon(sc);
+               } else {
                        clear_bit(ATH_OP_BEACONS, &common->op_flags);
+                       ath9k_beacon_stop(sc);
+               }
+       } else {
+               clear_bit(ATH_OP_BEACONS, &common->op_flags);
+               ath9k_beacon_stop(sc);
        }
 }
 
index d237373..f0ab6f9 100644 (file)
@@ -50,6 +50,7 @@
 #define IEEE80211_MS_TO_TU(x)   (((x) * 1000) / 1024)
 
 struct ath_beacon_config {
+       struct ieee80211_vif *main_vif;
        int beacon_interval;
        u16 dtim_period;
        u16 bmiss_timeout;
index d2ff0fc..7334c9b 100644 (file)
@@ -280,7 +280,7 @@ EXPORT_SYMBOL(ath_dynack_sample_ack_ts);
 void ath_dynack_node_init(struct ath_hw *ah, struct ath_node *an)
 {
        /* ackto = slottime + sifs + air delay */
-       u32 ackto = ATH9K_SLOT_TIME_9 + 16 + 64;
+       u32 ackto = 9 + 16 + 64;
        struct ath_dynack *da = &ah->dynack;
 
        an->ackto = ackto;
@@ -315,7 +315,7 @@ EXPORT_SYMBOL(ath_dynack_node_deinit);
 void ath_dynack_reset(struct ath_hw *ah)
 {
        /* ackto = slottime + sifs + air delay */
-       u32 ackto = ATH9K_SLOT_TIME_9 + 16 + 64;
+       u32 ackto = 9 + 16 + 64;
        struct ath_dynack *da = &ah->dynack;
 
        da->lto = jiffies;
index e6bcb4c..2c0e4d2 100644 (file)
@@ -45,7 +45,7 @@ void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv)
                 * Long slot time  : 2x cwmin
                 * Short slot time : 4x cwmin
                 */
-               if (ah->slottime == ATH9K_SLOT_TIME_20)
+               if (ah->slottime == 20)
                        qi.tqi_cwmin = 2*qi_be.tqi_cwmin;
                else
                        qi.tqi_cwmin = 4*qi_be.tqi_cwmin;
index c148c6c..b65c1b6 100644 (file)
@@ -678,7 +678,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
 
        for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++)
                priv->beacon.bslot[i] = NULL;
-       priv->beacon.slottime = ATH9K_SLOT_TIME_9;
+       priv->beacon.slottime = 9;
 
        ath9k_cmn_init_channels_rates(common);
        ath9k_cmn_init_crypto(ah);
index 8b2895f..d1d0c06 100644 (file)
@@ -454,7 +454,7 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
        if (AR_SREV_9100(ah))
                ah->sta_id1_defaults |= AR_STA_ID1_AR9100_BA_FIX;
 
-       ah->slottime = ATH9K_SLOT_TIME_9;
+       ah->slottime = 9;
        ah->globaltxtimeout = (u32) -1;
        ah->power_mode = ATH9K_PM_UNDEFINED;
        ah->htc_reset_init = true;
@@ -471,33 +471,34 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
                ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S);
 }
 
-static int ath9k_hw_init_macaddr(struct ath_hw *ah)
+static void ath9k_hw_init_macaddr(struct ath_hw *ah)
 {
        struct ath_common *common = ath9k_hw_common(ah);
-       u32 sum;
        int i;
        u16 eeval;
        static const u32 EEP_MAC[] = { EEP_MAC_LSW, EEP_MAC_MID, EEP_MAC_MSW };
 
-       sum = 0;
+       /* MAC address may already be loaded via ath9k_platform_data */
+       if (is_valid_ether_addr(common->macaddr))
+               return;
+
        for (i = 0; i < 3; i++) {
                eeval = ah->eep_ops->get_eeprom(ah, EEP_MAC[i]);
-               sum += eeval;
                common->macaddr[2 * i] = eeval >> 8;
                common->macaddr[2 * i + 1] = eeval & 0xff;
        }
-       if (!is_valid_ether_addr(common->macaddr)) {
-               ath_err(common,
-                       "eeprom contains invalid mac address: %pM\n",
-                       common->macaddr);
 
-               random_ether_addr(common->macaddr);
-               ath_err(common,
-                       "random mac address will be used: %pM\n",
-                       common->macaddr);
-       }
+       if (is_valid_ether_addr(common->macaddr))
+               return;
 
-       return 0;
+       ath_err(common, "eeprom contains invalid mac address: %pM\n",
+               common->macaddr);
+
+       random_ether_addr(common->macaddr);
+       ath_err(common, "random mac address will be used: %pM\n",
+               common->macaddr);
+
+       return;
 }
 
 static int ath9k_hw_post_init(struct ath_hw *ah)
@@ -636,12 +637,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
        if (r)
                return r;
 
-       r = ath9k_hw_init_macaddr(ah);
-       if (r) {
-               ath_err(common, "Failed to initialize MAC address\n");
-               return r;
-       }
-
+       ath9k_hw_init_macaddr(ah);
        ath9k_hw_init_hang_checks(ah);
 
        common->state = ATH_HW_INITIALIZED;
@@ -1832,8 +1828,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
        u32 saveLedState;
        u32 saveDefAntenna;
        u32 macStaId1;
+       struct timespec tsf_ts;
+       u32 tsf_offset;
        u64 tsf = 0;
-       s64 usec = 0;
        int r;
        bool start_mci_reset = false;
        bool save_fullsleep = ah->chip_fullsleep;
@@ -1877,8 +1874,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
        macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;
 
        /* Save TSF before chip reset, a cold reset clears it */
+       getrawmonotonic(&tsf_ts);
        tsf = ath9k_hw_gettsf64(ah);
-       usec = ktime_to_us(ktime_get_raw());
 
        saveLedState = REG_READ(ah, AR_CFG_LED) &
                (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL |
@@ -1911,8 +1908,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
        }
 
        /* Restore TSF */
-       usec = ktime_to_us(ktime_get_raw()) - usec;
-       ath9k_hw_settsf64(ah, tsf + usec);
+       tsf_offset = ath9k_hw_get_tsf_offset(&tsf_ts, NULL);
+       ath9k_hw_settsf64(ah, tsf + tsf_offset);
 
        if (AR_SREV_9280_20_OR_LATER(ah))
                REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
@@ -1932,12 +1929,11 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
        /*
         * Some AR91xx SoC devices frequently fail to accept TSF writes
         * right after the chip reset. When that happens, write a new
-        * value after the initvals have been applied, with an offset
-        * based on measured time difference
+        * value after the initvals have been applied.
         */
        if (AR_SREV_9100(ah) && (ath9k_hw_gettsf64(ah) < tsf)) {
-               tsf += 1500;
-               ath9k_hw_settsf64(ah, tsf);
+               tsf_offset = ath9k_hw_get_tsf_offset(&tsf_ts, NULL);
+               ath9k_hw_settsf64(ah, tsf + tsf_offset);
        }
 
        ath9k_hw_init_mfp(ah);
index 2ee8624..edc74fc 100644 (file)
@@ -372,7 +372,7 @@ static void ath9k_init_misc(struct ath_softc *sc)
 
        common->last_rssi = ATH_RSSI_DUMMY_MARKER;
        memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
-       sc->beacon.slottime = ATH9K_SLOT_TIME_9;
+       sc->beacon.slottime = 9;
 
        for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++)
                sc->beacon.bslot[i] = NULL;
@@ -512,31 +512,52 @@ static void ath9k_eeprom_release(struct ath_softc *sc)
        release_firmware(sc->sc_ah->eeprom_blob);
 }
 
-static int ath9k_init_soc_platform(struct ath_softc *sc)
+static int ath9k_init_platform(struct ath_softc *sc)
 {
        struct ath9k_platform_data *pdata = sc->dev->platform_data;
        struct ath_hw *ah = sc->sc_ah;
-       int ret = 0;
+       struct ath_common *common = ath9k_hw_common(ah);
+       int ret;
 
        if (!pdata)
                return 0;
 
+       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;
+       }
+
        if (pdata->eeprom_name) {
                ret = ath9k_eeprom_request(sc, pdata->eeprom_name);
                if (ret)
                        return ret;
        }
 
+       if (pdata->led_active_high)
+               ah->config.led_active_high = true;
+
        if (pdata->tx_gain_buffalo)
                ah->config.tx_gain_buffalo = true;
 
-       return ret;
+       if (pdata->macaddr)
+               ether_addr_copy(common->macaddr, pdata->macaddr);
+
+       return 0;
 }
 
 static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
                            const struct ath_bus_ops *bus_ops)
 {
-       struct ath9k_platform_data *pdata = sc->dev->platform_data;
        struct ath_hw *ah = NULL;
        struct ath9k_hw_capabilities *pCap;
        struct ath_common *common;
@@ -550,6 +571,8 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
        ah->dev = sc->dev;
        ah->hw = sc->hw;
        ah->hw_version.devid = devid;
+       ah->ah_flags |= AH_USE_EEPROM;
+       ah->led_pin = -1;
        ah->reg_ops.read = ath9k_ioread32;
        ah->reg_ops.multi_read = ath9k_multi_ioread32;
        ah->reg_ops.write = ath9k_iowrite32;
@@ -569,22 +592,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
        if (!ath9k_is_chanctx_enabled())
                sc->cur_chan->hw_queue_base = 0;
 
-       if (!pdata || pdata->use_eeprom) {
-               ah->ah_flags |= AH_USE_EEPROM;
-               sc->sc_ah->led_pin = -1;
-       } else {
-               sc->sc_ah->gpio_mask = pdata->gpio_mask;
-               sc->sc_ah->gpio_val = pdata->gpio_val;
-               sc->sc_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;
-       }
-
        common->ops = &ah->reg_ops;
        common->bus_ops = bus_ops;
        common->ps_ops = &ath9k_ps_ops;
@@ -600,7 +607,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
         */
        ath9k_init_pcoem_platform(sc);
 
-       ret = ath9k_init_soc_platform(sc);
+       ret = ath9k_init_platform(sc);
        if (ret)
                return ret;
 
@@ -646,9 +653,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
        if (ret)
                goto err_hw;
 
-       if (pdata && pdata->macaddr)
-               memcpy(common->macaddr, pdata->macaddr, ETH_ALEN);
-
        ret = ath9k_init_queues(sc);
        if (ret)
                goto err_queues;
index 7fbf7f9..3bab014 100644 (file)
 #define INIT_SSH_RETRY  32
 #define INIT_SLG_RETRY  32
 
-#define ATH9K_SLOT_TIME_6 6
-#define ATH9K_SLOT_TIME_9 9
-#define ATH9K_SLOT_TIME_20 20
-
 #define ATH9K_TXERR_XRETRY         0x01
 #define ATH9K_TXERR_FILT           0x02
 #define ATH9K_TXERR_FIFO           0x04
index 8b63988..7594650 100644 (file)
@@ -910,6 +910,22 @@ static bool ath9k_uses_beacons(int type)
        }
 }
 
+static void ath9k_vif_iter_set_beacon(struct ath9k_vif_iter_data *iter_data,
+                                     struct ieee80211_vif *vif)
+{
+       /* Use the first (configured) interface, but prefering AP interfaces. */
+       if (!iter_data->primary_beacon_vif) {
+               iter_data->primary_beacon_vif = vif;
+       } else {
+               if (iter_data->primary_beacon_vif->type != NL80211_IFTYPE_AP &&
+                   vif->type == NL80211_IFTYPE_AP)
+               iter_data->primary_beacon_vif = vif;
+       }
+
+       iter_data->beacons = true;
+       iter_data->nbcnvifs += 1;
+}
+
 static void ath9k_vif_iter(struct ath9k_vif_iter_data *iter_data,
                           u8 *mac, struct ieee80211_vif *vif)
 {
@@ -926,11 +942,13 @@ static void ath9k_vif_iter(struct ath9k_vif_iter_data *iter_data,
        }
 
        if (!vif->bss_conf.use_short_slot)
-               iter_data->slottime = ATH9K_SLOT_TIME_20;
+               iter_data->slottime = 20;
 
        switch (vif->type) {
        case NL80211_IFTYPE_AP:
                iter_data->naps++;
+               if (vif->bss_conf.enable_beacon)
+                       ath9k_vif_iter_set_beacon(iter_data, vif);
                break;
        case NL80211_IFTYPE_STATION:
                iter_data->nstations++;
@@ -943,12 +961,12 @@ static void ath9k_vif_iter(struct ath9k_vif_iter_data *iter_data,
        case NL80211_IFTYPE_ADHOC:
                iter_data->nadhocs++;
                if (vif->bss_conf.enable_beacon)
-                       iter_data->beacons = true;
+                       ath9k_vif_iter_set_beacon(iter_data, vif);
                break;
        case NL80211_IFTYPE_MESH_POINT:
                iter_data->nmeshes++;
                if (vif->bss_conf.enable_beacon)
-                       iter_data->beacons = true;
+                       ath9k_vif_iter_set_beacon(iter_data, vif);
                break;
        case NL80211_IFTYPE_WDS:
                iter_data->nwds++;
@@ -999,7 +1017,7 @@ void ath9k_calculate_iter_data(struct ath_softc *sc,
         */
        memset(iter_data, 0, sizeof(*iter_data));
        eth_broadcast_addr(iter_data->mask);
-       iter_data->slottime = ATH9K_SLOT_TIME_9;
+       iter_data->slottime = 9;
 
        list_for_each_entry(avp, &ctx->vifs, list)
                ath9k_vif_iter(iter_data, avp->vif->addr, avp->vif);
@@ -1061,7 +1079,7 @@ static void ath9k_set_offchannel_state(struct ath_softc *sc)
        ah->opmode = vif->type;
        ah->imask &= ~ATH9K_INT_SWBA;
        ah->imask &= ~ATH9K_INT_TSFOOR;
-       ah->slottime = ATH9K_SLOT_TIME_9;
+       ah->slottime = 9;
 
        ath_hw_setbssidmask(common);
        ath9k_hw_setopmode(ah);
@@ -1081,7 +1099,6 @@ void ath9k_calculate_summary_state(struct ath_softc *sc,
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(ah);
        struct ath9k_vif_iter_data iter_data;
-       struct ath_beacon_config *cur_conf;
 
        ath_chanctx_check_active(sc, ctx);
 
@@ -1103,13 +1120,12 @@ void ath9k_calculate_summary_state(struct ath_softc *sc,
        ath_hw_setbssidmask(common);
 
        if (iter_data.naps > 0) {
-               cur_conf = &ctx->beacon;
                ath9k_hw_set_tsfadjust(ah, true);
                ah->opmode = NL80211_IFTYPE_AP;
-               if (cur_conf->enable_beacon)
-                       iter_data.beacons = true;
        } else {
                ath9k_hw_set_tsfadjust(ah, false);
+               if (iter_data.beacons)
+                       ath9k_beacon_ensure_primary_slot(sc);
 
                if (iter_data.nmeshes)
                        ah->opmode = NL80211_IFTYPE_MESH_POINT;
@@ -1134,7 +1150,6 @@ void ath9k_calculate_summary_state(struct ath_softc *sc,
                        ctx->switch_after_beacon = true;
        }
 
-       ah->imask &= ~ATH9K_INT_SWBA;
        if (ah->opmode == NL80211_IFTYPE_STATION) {
                bool changed = (iter_data.primary_sta != ctx->primary_sta);
 
@@ -1151,16 +1166,12 @@ void ath9k_calculate_summary_state(struct ath_softc *sc,
                        if (ath9k_hw_mci_is_enabled(sc->sc_ah))
                                ath9k_mci_update_wlan_channels(sc, true);
                }
-       } else if (iter_data.beacons) {
-               ah->imask |= ATH9K_INT_SWBA;
        }
+       sc->nbcnvifs = iter_data.nbcnvifs;
+       ath9k_beacon_config(sc, iter_data.primary_beacon_vif,
+                           iter_data.beacons);
        ath9k_hw_set_interrupts(ah);
 
-       if (iter_data.beacons)
-               set_bit(ATH_OP_BEACONS, &common->op_flags);
-       else
-               clear_bit(ATH_OP_BEACONS, &common->op_flags);
-
        if (ah->slottime != iter_data.slottime) {
                ah->slottime = iter_data.slottime;
                ath9k_hw_init_global_settings(ah);
@@ -1777,9 +1788,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
        if ((changed & BSS_CHANGED_BEACON_ENABLED) ||
            (changed & BSS_CHANGED_BEACON_INT) ||
            (changed & BSS_CHANGED_BEACON_INFO)) {
-               ath9k_beacon_config(sc, vif, changed);
-               if (changed & BSS_CHANGED_BEACON_ENABLED)
-                       ath9k_calculate_summary_state(sc, avp->chanctx);
+               ath9k_calculate_summary_state(sc, avp->chanctx);
        }
 
        if ((avp->chanctx == sc->cur_chan) &&
@@ -1788,6 +1797,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
                        slottime = 9;
                else
                        slottime = 20;
+
                if (vif->type == NL80211_IFTYPE_AP) {
                        /*
                         * Defer update, so that connected stations can adjust
@@ -1823,11 +1833,19 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
 static u64 ath9k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 {
        struct ath_softc *sc = hw->priv;
+       struct ath_vif *avp = (void *)vif->drv_priv;
        u64 tsf;
 
        mutex_lock(&sc->mutex);
        ath9k_ps_wakeup(sc);
-       tsf = ath9k_hw_gettsf64(sc->sc_ah);
+       /* Get current TSF either from HW or kernel time. */
+       if (sc->cur_chan == avp->chanctx) {
+               tsf = ath9k_hw_gettsf64(sc->sc_ah);
+       } else {
+               tsf = sc->cur_chan->tsf_val +
+                     ath9k_hw_get_tsf_offset(&sc->cur_chan->tsf_ts, NULL);
+       }
+       tsf += le64_to_cpu(avp->tsf_adjust);
        ath9k_ps_restore(sc);
        mutex_unlock(&sc->mutex);
 
@@ -1839,10 +1857,15 @@ static void ath9k_set_tsf(struct ieee80211_hw *hw,
                          u64 tsf)
 {
        struct ath_softc *sc = hw->priv;
+       struct ath_vif *avp = (void *)vif->drv_priv;
 
        mutex_lock(&sc->mutex);
        ath9k_ps_wakeup(sc);
-       ath9k_hw_settsf64(sc->sc_ah, tsf);
+       tsf -= le64_to_cpu(avp->tsf_adjust);
+       getrawmonotonic(&avp->chanctx->tsf_ts);
+       if (sc->cur_chan == avp->chanctx)
+               ath9k_hw_settsf64(sc->sc_ah, tsf);
+       avp->chanctx->tsf_val = tsf;
        ath9k_ps_restore(sc);
        mutex_unlock(&sc->mutex);
 }
@@ -1850,11 +1873,15 @@ static void ath9k_set_tsf(struct ieee80211_hw *hw,
 static void ath9k_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 {
        struct ath_softc *sc = hw->priv;
+       struct ath_vif *avp = (void *)vif->drv_priv;
 
        mutex_lock(&sc->mutex);
 
        ath9k_ps_wakeup(sc);
-       ath9k_hw_reset_tsf(sc->sc_ah);
+       getrawmonotonic(&avp->chanctx->tsf_ts);
+       if (sc->cur_chan == avp->chanctx)
+               ath9k_hw_reset_tsf(sc->sc_ah);
+       avp->chanctx->tsf_val = 0;
        ath9k_ps_restore(sc);
 
        mutex_unlock(&sc->mutex);
index 7cdaf40..aa04b13 100644 (file)
@@ -794,6 +794,8 @@ static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data)
                        ath_err(common,
                                "%s: eeprom read failed, offset %08x is out of range\n",
                                __func__, off);
+
+                       return false;
                }
 
                *data = pdata->eeprom_data[off];
index 8643801..231fd02 100644 (file)
@@ -35,26 +35,27 @@ void *wcn36xx_dxe_get_next_bd(struct wcn36xx *wcn, bool is_low)
        return ch->head_blk_ctl->bd_cpu_addr;
 }
 
+static void wcn36xx_ccu_write_register(struct wcn36xx *wcn, int addr, int data)
+{
+       wcn36xx_dbg(WCN36XX_DBG_DXE,
+                   "wcn36xx_ccu_write_register: addr=%x, data=%x\n",
+                   addr, data);
+
+       writel(data, wcn->ccu_base + addr);
+}
+
 static void wcn36xx_dxe_write_register(struct wcn36xx *wcn, int addr, int data)
 {
        wcn36xx_dbg(WCN36XX_DBG_DXE,
                    "wcn36xx_dxe_write_register: addr=%x, data=%x\n",
                    addr, data);
 
-       writel(data, wcn->mmio + addr);
+       writel(data, wcn->dxe_base + addr);
 }
 
-#define wcn36xx_dxe_write_register_x(wcn, reg, reg_data)                \
-do {                                                                    \
-       if (wcn->chip_version == WCN36XX_CHIP_3680)                      \
-               wcn36xx_dxe_write_register(wcn, reg ## _3680, reg_data); \
-       else                                                             \
-               wcn36xx_dxe_write_register(wcn, reg ## _3660, reg_data); \
-} while (0)                                                             \
-
 static void wcn36xx_dxe_read_register(struct wcn36xx *wcn, int addr, int *data)
 {
-       *data = readl(wcn->mmio + addr);
+       *data = readl(wcn->dxe_base + addr);
 
        wcn36xx_dbg(WCN36XX_DBG_DXE,
                    "wcn36xx_dxe_read_register: addr=%x, data=%x\n",
@@ -701,9 +702,13 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
        reg_data = WCN36XX_DXE_REG_RESET;
        wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_REG_CSR_RESET, reg_data);
 
-       /* Setting interrupt path */
-       reg_data = WCN36XX_DXE_CCU_INT;
-       wcn36xx_dxe_write_register_x(wcn, WCN36XX_DXE_REG_CCU_INT, reg_data);
+       /* Select channels for rx avail and xfer done interrupts... */
+       reg_data = (WCN36XX_DXE_INT_CH3_MASK | WCN36XX_DXE_INT_CH1_MASK) << 16 |
+                   WCN36XX_DXE_INT_CH0_MASK | WCN36XX_DXE_INT_CH4_MASK;
+       if (wcn->is_pronto)
+               wcn36xx_ccu_write_register(wcn, WCN36XX_CCU_DXE_INT_SELECT_PRONTO, reg_data);
+       else
+               wcn36xx_ccu_write_register(wcn, WCN36XX_CCU_DXE_INT_SELECT_RIVA, reg_data);
 
        /***************************************/
        /* Init descriptors for TX LOW channel */
index 3eca4f9..c012e80 100644 (file)
@@ -28,11 +28,10 @@ H2H_TEST_RX_TX = DMA2
 */
 
 /* DXE registers */
-#define WCN36XX_DXE_MEM_REG                    0x202000
+#define WCN36XX_DXE_MEM_REG                    0
 
-#define WCN36XX_DXE_CCU_INT                    0xA0011
-#define WCN36XX_DXE_REG_CCU_INT_3660           0x200b10
-#define WCN36XX_DXE_REG_CCU_INT_3680           0x2050dc
+#define WCN36XX_CCU_DXE_INT_SELECT_RIVA                0x310
+#define WCN36XX_CCU_DXE_INT_SELECT_PRONTO      0x10dc
 
 /* TODO This must calculated properly but not hardcoded */
 #define WCN36XX_DXE_CTRL_TX_L                  0x328a44
index 658bfb8..4f87ef1 100644 (file)
@@ -4123,7 +4123,7 @@ struct wcn36xx_hal_update_scan_params_req {
 
 /* Update scan params - sent from host to PNO to be used during PNO
  * scanningx */
-struct update_scan_params_req_ex {
+struct wcn36xx_hal_update_scan_params_req_ex {
 
        struct wcn36xx_hal_msg_header header;
 
@@ -4151,7 +4151,7 @@ struct update_scan_params_req_ex {
 
        /* Cb State */
        enum phy_chan_bond_state state;
-};
+} __packed;
 
 /* Update scan params - sent from host to PNO to be used during PNO
  * scanningx */
index a920d70..e1d59da 100644 (file)
@@ -19,6 +19,8 @@
 #include <linux/module.h>
 #include <linux/firmware.h>
 #include <linux/platform_device.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
 #include "wcn36xx.h"
 
 unsigned int wcn36xx_dbg_mask;
@@ -259,17 +261,6 @@ static void wcn36xx_feat_caps_info(struct wcn36xx *wcn)
        }
 }
 
-static void wcn36xx_detect_chip_version(struct wcn36xx *wcn)
-{
-       if (get_feat_caps(wcn->fw_feat_caps, DOT11AC)) {
-               wcn36xx_info("Chip is 3680\n");
-               wcn->chip_version = WCN36XX_CHIP_3680;
-       } else {
-               wcn36xx_info("Chip is 3660\n");
-               wcn->chip_version = WCN36XX_CHIP_3660;
-       }
-}
-
 static int wcn36xx_start(struct ieee80211_hw *hw)
 {
        struct wcn36xx *wcn = hw->priv;
@@ -324,9 +315,6 @@ static int wcn36xx_start(struct ieee80211_hw *hw)
                        wcn36xx_feat_caps_info(wcn);
        }
 
-       wcn36xx_detect_chip_version(wcn);
-       wcn36xx_smd_update_cfg(wcn, WCN36XX_HAL_CFG_ENABLE_MC_ADDR_LIST, 1);
-
        /* DMA channel initialization */
        ret = wcn36xx_dxe_init(wcn);
        if (ret) {
@@ -1064,7 +1052,11 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
 static int wcn36xx_platform_get_resources(struct wcn36xx *wcn,
                                          struct platform_device *pdev)
 {
+       struct device_node *mmio_node;
        struct resource *res;
+       int index;
+       int ret;
+
        /* Set TX IRQ */
        res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
                                           "wcnss_wlantx_irq");
@@ -1083,19 +1075,40 @@ static int wcn36xx_platform_get_resources(struct wcn36xx *wcn,
        }
        wcn->rx_irq = res->start;
 
-       /* Map the memory */
-       res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-                                                "wcnss_mmio");
-       if (!res) {
-               wcn36xx_err("failed to get mmio\n");
-               return -ENOENT;
+       mmio_node = of_parse_phandle(pdev->dev.parent->of_node, "qcom,mmio", 0);
+       if (!mmio_node) {
+               wcn36xx_err("failed to acquire qcom,mmio reference\n");
+               return -EINVAL;
        }
-       wcn->mmio = ioremap(res->start, resource_size(res));
-       if (!wcn->mmio) {
-               wcn36xx_err("failed to map io memory\n");
-               return -ENOMEM;
+
+       wcn->is_pronto = !!of_device_is_compatible(mmio_node, "qcom,pronto");
+
+       /* Map the CCU memory */
+       index = of_property_match_string(mmio_node, "reg-names", "ccu");
+       wcn->ccu_base = of_iomap(mmio_node, index);
+       if (!wcn->ccu_base) {
+               wcn36xx_err("failed to map ccu memory\n");
+               ret = -ENOMEM;
+               goto put_mmio_node;
        }
+
+       /* Map the DXE memory */
+       index = of_property_match_string(mmio_node, "reg-names", "dxe");
+       wcn->dxe_base = of_iomap(mmio_node, index);
+       if (!wcn->dxe_base) {
+               wcn36xx_err("failed to map dxe memory\n");
+               ret = -ENOMEM;
+               goto unmap_ccu;
+       }
+
+       of_node_put(mmio_node);
        return 0;
+
+unmap_ccu:
+       iounmap(wcn->ccu_base);
+put_mmio_node:
+       of_node_put(mmio_node);
+       return ret;
 }
 
 static int wcn36xx_probe(struct platform_device *pdev)
@@ -1138,7 +1151,8 @@ static int wcn36xx_probe(struct platform_device *pdev)
        return 0;
 
 out_unmap:
-       iounmap(wcn->mmio);
+       iounmap(wcn->ccu_base);
+       iounmap(wcn->dxe_base);
 out_wq:
        ieee80211_free_hw(hw);
 out_err:
@@ -1154,7 +1168,8 @@ static int wcn36xx_remove(struct platform_device *pdev)
        mutex_destroy(&wcn->hal_mutex);
 
        ieee80211_unregister_hw(hw);
-       iounmap(wcn->mmio);
+       iounmap(wcn->dxe_base);
+       iounmap(wcn->ccu_base);
        ieee80211_free_hw(hw);
 
        return 0;
index e8b630c..a443992 100644 (file)
@@ -674,22 +674,25 @@ static int wcn36xx_smd_update_scan_params_rsp(void *buf, size_t len)
        return 0;
 }
 
-int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn)
+int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn,
+                                  u8 *channels, size_t channel_count)
 {
-       struct wcn36xx_hal_update_scan_params_req msg_body;
+       struct wcn36xx_hal_update_scan_params_req_ex msg_body;
        int ret = 0;
 
        mutex_lock(&wcn->hal_mutex);
        INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_SCAN_PARAM_REQ);
 
-       msg_body.dot11d_enabled = 0;
-       msg_body.dot11d_resolved = 0;
-       msg_body.channel_count = 26;
+       msg_body.dot11d_enabled = false;
+       msg_body.dot11d_resolved = true;
+
+       msg_body.channel_count = channel_count;
+       memcpy(msg_body.channels, channels, channel_count);
        msg_body.active_min_ch_time = 60;
        msg_body.active_max_ch_time = 120;
        msg_body.passive_min_ch_time = 60;
        msg_body.passive_max_ch_time = 110;
-       msg_body.state = 0;
+       msg_body.state = PHY_SINGLE_CHANNEL_CENTERED;
 
        PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
 
@@ -2226,17 +2229,12 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
 
        case WCN36XX_HAL_COEX_IND:
        case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
+       case WCN36XX_HAL_DEL_BA_IND:
        case WCN36XX_HAL_OTA_TX_COMPL_IND:
        case WCN36XX_HAL_MISSED_BEACON_IND:
        case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
-               msg_ind = kmalloc(sizeof(*msg_ind), GFP_KERNEL);
-               if (!msg_ind)
-                       goto nomem;
-               msg_ind->msg_len = len;
-               msg_ind->msg = kmemdup(buf, len, GFP_KERNEL);
-               if (!msg_ind->msg) {
-                       kfree(msg_ind);
-nomem:
+               msg_ind = kmalloc(sizeof(*msg_ind) + len, GFP_KERNEL);
+               if (!msg_ind) {
                        /*
                         * FIXME: Do something smarter then just
                         * printing an error.
@@ -2245,10 +2243,14 @@ nomem:
                                    msg_header->msg_type);
                        break;
                }
-               mutex_lock(&wcn->hal_ind_mutex);
+
+               msg_ind->msg_len = len;
+               memcpy(msg_ind->msg, buf, len);
+
+               spin_lock(&wcn->hal_ind_lock);
                list_add_tail(&msg_ind->list, &wcn->hal_ind_queue);
                queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work);
-               mutex_unlock(&wcn->hal_ind_mutex);
+               spin_unlock(&wcn->hal_ind_lock);
                wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n");
                break;
        default:
@@ -2262,8 +2264,9 @@ static void wcn36xx_ind_smd_work(struct work_struct *work)
                container_of(work, struct wcn36xx, hal_ind_work);
        struct wcn36xx_hal_msg_header *msg_header;
        struct wcn36xx_hal_ind_msg *hal_ind_msg;
+       unsigned long flags;
 
-       mutex_lock(&wcn->hal_ind_mutex);
+       spin_lock_irqsave(&wcn->hal_ind_lock, flags);
 
        hal_ind_msg = list_first_entry(&wcn->hal_ind_queue,
                                       struct wcn36xx_hal_ind_msg,
@@ -2273,6 +2276,7 @@ static void wcn36xx_ind_smd_work(struct work_struct *work)
 
        switch (msg_header->msg_type) {
        case WCN36XX_HAL_COEX_IND:
+       case WCN36XX_HAL_DEL_BA_IND:
        case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
                break;
        case WCN36XX_HAL_OTA_TX_COMPL_IND:
@@ -2295,9 +2299,8 @@ static void wcn36xx_ind_smd_work(struct work_struct *work)
                              msg_header->msg_type);
        }
        list_del(wcn->hal_ind_queue.next);
-       kfree(hal_ind_msg->msg);
+       spin_unlock_irqrestore(&wcn->hal_ind_lock, flags);
        kfree(hal_ind_msg);
-       mutex_unlock(&wcn->hal_ind_mutex);
 }
 int wcn36xx_smd_open(struct wcn36xx *wcn)
 {
@@ -2310,7 +2313,7 @@ int wcn36xx_smd_open(struct wcn36xx *wcn)
        }
        INIT_WORK(&wcn->hal_ind_work, wcn36xx_ind_smd_work);
        INIT_LIST_HEAD(&wcn->hal_ind_queue);
-       mutex_init(&wcn->hal_ind_mutex);
+       spin_lock_init(&wcn->hal_ind_lock);
 
        ret = wcn->ctrl_ops->open(wcn, wcn36xx_smd_rsp_process);
        if (ret) {
@@ -2330,5 +2333,4 @@ void wcn36xx_smd_close(struct wcn36xx *wcn)
 {
        wcn->ctrl_ops->close();
        destroy_workqueue(wcn->hal_ind_wq);
-       mutex_destroy(&wcn->hal_ind_mutex);
 }
index d93e3fd..df80cbb 100644 (file)
@@ -46,8 +46,8 @@ struct wcn36xx_fw_msg_status_rsp {
 
 struct wcn36xx_hal_ind_msg {
        struct list_head list;
-       u8 *msg;
        size_t msg_len;
+       u8 msg[];
 };
 
 struct wcn36xx;
@@ -63,7 +63,7 @@ int wcn36xx_smd_start_scan(struct wcn36xx *wcn);
 int wcn36xx_smd_end_scan(struct wcn36xx *wcn);
 int wcn36xx_smd_finish_scan(struct wcn36xx *wcn,
                            enum wcn36xx_hal_sys_mode mode);
-int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn);
+int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn, u8 *channels, size_t channel_count);
 int wcn36xx_smd_add_sta_self(struct wcn36xx *wcn, struct ieee80211_vif *vif);
 int wcn36xx_smd_delete_sta_self(struct wcn36xx *wcn, u8 *addr);
 int wcn36xx_smd_delete_sta(struct wcn36xx *wcn, u8 sta_index);
index 7433d67..22242d1 100644 (file)
@@ -193,7 +193,7 @@ struct wcn36xx {
        u8                      fw_minor;
        u8                      fw_major;
        u32                     fw_feat_caps[WCN36XX_HAL_CAPS_SIZE];
-       u32                     chip_version;
+       bool                    is_pronto;
 
        /* extra byte for the NULL termination */
        u8                      crm_version[WCN36XX_HAL_VERSION_LENGTH + 1];
@@ -202,7 +202,8 @@ struct wcn36xx {
        /* IRQs */
        int                     tx_irq;
        int                     rx_irq;
-       void __iomem            *mmio;
+       void __iomem            *ccu_base;
+       void __iomem            *dxe_base;
 
        struct wcn36xx_platform_ctrl_ops *ctrl_ops;
        /*
@@ -215,7 +216,7 @@ struct wcn36xx {
        struct completion       hal_rsp_compl;
        struct workqueue_struct *hal_ind_wq;
        struct work_struct      hal_ind_work;
-       struct mutex            hal_ind_mutex;
+       spinlock_t              hal_ind_lock;
        struct list_head        hal_ind_queue;
 
        /* DXE channels */
@@ -241,9 +242,6 @@ struct wcn36xx {
 
 };
 
-#define WCN36XX_CHIP_3660      0
-#define WCN36XX_CHIP_3680      1
-
 static inline bool wcn36xx_is_fw_version(struct wcn36xx *wcn,
                                         u8 major,
                                         u8 minor,
index e66153d..76860a4 100644 (file)
@@ -40,6 +40,7 @@ struct ath9k_platform_data {
        bool tx_gain_buffalo;
        bool disable_2ghz;
        bool disable_5ghz;
+       bool led_active_high;
 
        int (*get_mac_revision)(void);
        int (*external_reset)(void);