return __le16_to_cpu(rx_desc->mpdu_start.phy_ppdu_id);
 }
 
+static void ath11k_dp_service_mon_ring(struct timer_list *t)
+{
+       struct ath11k_base *ab = from_timer(ab, t, mon_reap_timer);
+       int i;
+
+       for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++)
+               ath11k_dp_rx_process_mon_rings(ab, i, NULL, DP_MON_SERVICE_BUDGET);
+
+       mod_timer(&ab->mon_reap_timer, jiffies +
+                 msecs_to_jiffies(ATH11K_MON_TIMER_INTERVAL));
+}
+
 /* Returns number of Rx buffers replenished */
 int ath11k_dp_rxbufs_replenish(struct ath11k_base *ab, int mac_id,
                               struct dp_rxdma_ring *rx_ring,
        /* if rxdma1_enable is false, then it doesn't need
         * to setup rxdam_mon_buf_ring, rxdma_mon_dst_ring
         * and rxdma_mon_desc_ring.
+        * init reap timer for QCA6390.
         */
-       if (!ar->ab->hw_params.rxdma1_enable)
+       if (!ar->ab->hw_params.rxdma1_enable) {
+               //init mon status buffer reap timer
+               timer_setup(&ar->ab->mon_reap_timer,
+                           ath11k_dp_service_mon_ring, 0);
                return 0;
+       }
 
        ret = ath11k_dp_srng_setup(ar->ab,
                                   &dp->rxdma_mon_buf_ring.refill_buf_ring,
        void *src_srng_desc;
        int ret = 0;
 
-       dp_srng = &dp->rxdma_mon_desc_ring;
-       hal_srng = &ar->ab->hal.srng_list[dp_srng->ring_id];
+       if (ar->ab->hw_params.rxdma1_enable) {
+               dp_srng = &dp->rxdma_mon_desc_ring;
+               hal_srng = &ar->ab->hal.srng_list[dp_srng->ring_id];
+       } else {
+               dp_srng = &ar->ab->dp.wbm_desc_rel_ring;
+               hal_srng = &ar->ab->hal.srng_list[dp_srng->ring_id];
+       }
 
        ath11k_hal_srng_access_begin(ar->ab, hal_srng);
 
 static
 void ath11k_dp_rx_mon_next_link_desc_get(void *rx_msdu_link_desc,
                                         dma_addr_t *paddr, u32 *sw_cookie,
+                                        u8 *rbm,
                                         void **pp_buf_addr_info)
 {
        struct hal_rx_msdu_link *msdu_link =
                        (struct hal_rx_msdu_link *)rx_msdu_link_desc;
        struct ath11k_buffer_addr *buf_addr_info;
-       u8 rbm = 0;
 
        buf_addr_info = (struct ath11k_buffer_addr *)&msdu_link->buf_addr_info;
 
-       ath11k_hal_rx_buf_addr_info_get(buf_addr_info, paddr, sw_cookie, &rbm);
+       ath11k_hal_rx_buf_addr_info_get(buf_addr_info, paddr, sw_cookie, rbm);
 
        *pp_buf_addr_info = (void *)buf_addr_info;
 }
 }
 
 static u32
-ath11k_dp_rx_mon_mpdu_pop(struct ath11k *ar,
+ath11k_dp_rx_mon_mpdu_pop(struct ath11k *ar, int mac_id,
                          void *ring_entry, struct sk_buff **head_msdu,
                          struct sk_buff **tail_msdu, u32 *npackets,
                          u32 *ppdu_id)
        struct hal_reo_entrance_ring *ent_desc =
                        (struct hal_reo_entrance_ring *)ring_entry;
        int buf_id;
+       u32 rx_link_buf_info[2];
+       u8 rbm;
+
+       if (!ar->ab->hw_params.rxdma1_enable)
+               rx_ring = &dp->rx_refill_buf_ring;
 
        ath11k_hal_rx_reo_ent_buf_paddr_get(ring_entry, &paddr,
-                                           &sw_cookie, &p_last_buf_addr_info,
+                                           &sw_cookie,
+                                           &p_last_buf_addr_info, &rbm,
                                            &msdu_cnt);
 
        if (FIELD_GET(HAL_REO_ENTR_RING_INFO1_RXDMA_PUSH_REASON,
                        return rx_bufs_used;
                }
 
-               rx_msdu_link_desc =
-                       (void *)pmon->link_desc_banks[sw_cookie].vaddr +
-                       (paddr - pmon->link_desc_banks[sw_cookie].paddr);
+               if (ar->ab->hw_params.rxdma1_enable)
+                       rx_msdu_link_desc =
+                               (void *)pmon->link_desc_banks[sw_cookie].vaddr +
+                               (paddr - pmon->link_desc_banks[sw_cookie].paddr);
+               else
+                       rx_msdu_link_desc =
+                               (void *)ar->ab->dp.link_desc_banks[sw_cookie].vaddr +
+                               (paddr - ar->ab->dp.link_desc_banks[sw_cookie].paddr);
 
                ath11k_hal_rx_msdu_list_get(ar, rx_msdu_link_desc, &msdu_list,
                                            &num_msdus);
                        spin_unlock_bh(&rx_ring->idr_lock);
                }
 
+               ath11k_hal_rx_buf_addr_info_set(rx_link_buf_info, paddr, sw_cookie, rbm);
+
                ath11k_dp_rx_mon_next_link_desc_get(rx_msdu_link_desc, &paddr,
-                                                   &sw_cookie,
+                                                   &sw_cookie, &rbm,
                                                    &p_buf_addr_info);
 
-               if (ath11k_dp_rx_monitor_link_desc_return(ar,
-                                                         p_last_buf_addr_info,
-                                                         dp->mac_id))
-                       ath11k_dbg(ar->ab, ATH11K_DBG_DATA,
-                                  "dp_rx_monitor_link_desc_return failed");
+               if (ar->ab->hw_params.rxdma1_enable) {
+                       if (ath11k_dp_rx_monitor_link_desc_return(ar,
+                                                                 p_last_buf_addr_info,
+                                                                 dp->mac_id))
+                               ath11k_dbg(ar->ab, ATH11K_DBG_DATA,
+                                          "dp_rx_monitor_link_desc_return failed");
+               } else {
+                       ath11k_dp_rx_link_desc_return(ar->ab, rx_link_buf_info,
+                                                     HAL_WBM_REL_BM_ACT_PUT_IN_IDLE);
+               }
 
                p_last_buf_addr_info = p_buf_addr_info;
 
        return -EINVAL;
 }
 
-static void ath11k_dp_rx_mon_dest_process(struct ath11k *ar, u32 quota,
-                                         struct napi_struct *napi)
+static void ath11k_dp_rx_mon_dest_process(struct ath11k *ar, int mac_id,
+                                         u32 quota, struct napi_struct *napi)
 {
        struct ath11k_pdev_dp *dp = &ar->dp;
        struct ath11k_mon_data *pmon = (struct ath11k_mon_data *)&dp->mon_data;
        void *mon_dst_srng;
        u32 ppdu_id;
        u32 rx_bufs_used;
+       u32 ring_id;
        struct ath11k_pdev_mon_stats *rx_mon_stats;
        u32      npackets = 0;
 
-       mon_dst_srng = &ar->ab->hal.srng_list[dp->rxdma_mon_dst_ring.ring_id];
+       if (ar->ab->hw_params.rxdma1_enable)
+               ring_id = dp->rxdma_mon_dst_ring.ring_id;
+       else
+               ring_id = dp->rxdma_err_dst_ring[mac_id].ring_id;
+
+       mon_dst_srng = &ar->ab->hal.srng_list[ring_id];
 
        if (!mon_dst_srng) {
                ath11k_warn(ar->ab,
                head_msdu = NULL;
                tail_msdu = NULL;
 
-               rx_bufs_used += ath11k_dp_rx_mon_mpdu_pop(ar, ring_entry,
+               rx_bufs_used += ath11k_dp_rx_mon_mpdu_pop(ar, mac_id, ring_entry,
                                                          &head_msdu,
                                                          &tail_msdu,
                                                          &npackets, &ppdu_id);
 
        if (rx_bufs_used) {
                rx_mon_stats->dest_ppdu_done++;
-               ath11k_dp_rxbufs_replenish(ar->ab, dp->mac_id,
-                                          &dp->rxdma_mon_buf_ring,
-                                          rx_bufs_used,
-                                          HAL_RX_BUF_RBM_SW3_BM);
+               if (ar->ab->hw_params.rxdma1_enable)
+                       ath11k_dp_rxbufs_replenish(ar->ab, dp->mac_id,
+                                                  &dp->rxdma_mon_buf_ring,
+                                                  rx_bufs_used,
+                                                  HAL_RX_BUF_RBM_SW3_BM);
+               else
+                       ath11k_dp_rxbufs_replenish(ar->ab, dp->mac_id,
+                                                  &dp->rx_refill_buf_ring,
+                                                  rx_bufs_used,
+                                                  HAL_RX_BUF_RBM_SW3_BM);
        }
 }
 
 static void ath11k_dp_rx_mon_status_process_tlv(struct ath11k *ar,
-                                               u32 quota,
+                                               int mac_id, u32 quota,
                                                struct napi_struct *napi)
 {
        struct ath11k_pdev_dp *dp = &ar->dp;
                if (tlv_status == HAL_TLV_STATUS_PPDU_DONE) {
                        rx_mon_stats->status_ppdu_done++;
                        pmon->mon_ppdu_status = DP_PPDU_STATUS_DONE;
-                       ath11k_dp_rx_mon_dest_process(ar, quota, napi);
+                       ath11k_dp_rx_mon_dest_process(ar, mac_id, quota, napi);
                        pmon->mon_ppdu_status = DP_PPDU_STATUS_START;
                }
                dev_kfree_skb_any(status_skb);
        struct ath11k_mon_data *pmon = (struct ath11k_mon_data *)&dp->mon_data;
        int num_buffs_reaped = 0;
 
-       num_buffs_reaped = ath11k_dp_rx_reap_mon_status_ring(ar->ab, dp->mac_id, &budget,
+       num_buffs_reaped = ath11k_dp_rx_reap_mon_status_ring(ar->ab, mac_id, &budget,
                                                             &pmon->rx_status_q);
        if (num_buffs_reaped)
-               ath11k_dp_rx_mon_status_process_tlv(ar, budget, napi);
+               ath11k_dp_rx_mon_status_process_tlv(ar, mac_id, budget, napi);
 
        return num_buffs_reaped;
 }
 
        cmd->ring_tail_off32_remote_addr_hi = (u64)tp_addr >>
                                              HAL_ADDR_MSB_REG_SHIFT;
 
-       cmd->ring_msi_addr_lo = 0;
-       cmd->ring_msi_addr_hi = 0;
-       cmd->msi_data = 0;
+       cmd->ring_msi_addr_lo = params.msi_addr & 0xffffffff;
+       cmd->ring_msi_addr_hi = ((uint64_t)(params.msi_addr) >> 32) & 0xffffffff;
+       cmd->msi_data = params.msi_data;
 
        cmd->intr_info = FIELD_PREP(
                        HTT_SRNG_SETUP_CMD_INTR_INFO_BATCH_COUNTER_THRESH,
                                params.low_threshold);
        }
 
+       ath11k_dbg(ab, ATH11k_DBG_HAL,
+                  "%s msi_addr_lo:0x%x, msi_addr_hi:0x%x, msi_data:0x%x\n",
+                  __func__, cmd->ring_msi_addr_lo, cmd->ring_msi_addr_hi,
+                  cmd->msi_data);
+
+       ath11k_dbg(ab, ATH11k_DBG_HAL,
+                  "ring_id:%d, ring_type:%d, intr_info:0x%x, flags:0x%x\n",
+                  ring_id, ring_type, cmd->intr_info, cmd->info2);
+
        ret = ath11k_htc_send(&ab->htc, ab->dp.eid, skb);
        if (ret)
                goto err_free;
        int len = sizeof(*cmd);
        u8 pdev_mask;
        int ret;
+       int i;
 
-       skb = ath11k_htc_alloc_skb(ab, len);
-       if (!skb)
-               return -ENOMEM;
-
-       skb_put(skb, len);
-       cmd = (struct htt_ppdu_stats_cfg_cmd *)skb->data;
-       cmd->msg = FIELD_PREP(HTT_PPDU_STATS_CFG_MSG_TYPE,
-                             HTT_H2T_MSG_TYPE_PPDU_STATS_CFG);
-
-       pdev_mask = 1 << (ar->pdev_idx);
-       cmd->msg |= FIELD_PREP(HTT_PPDU_STATS_CFG_PDEV_ID, pdev_mask);
-       cmd->msg |= FIELD_PREP(HTT_PPDU_STATS_CFG_TLV_TYPE_BITMASK, mask);
-
-       ret = ath11k_htc_send(&ab->htc, dp->eid, skb);
-       if (ret) {
-               dev_kfree_skb_any(skb);
-               return ret;
+       for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
+               skb = ath11k_htc_alloc_skb(ab, len);
+               if (!skb)
+                       return -ENOMEM;
+
+               skb_put(skb, len);
+               cmd = (struct htt_ppdu_stats_cfg_cmd *)skb->data;
+               cmd->msg = FIELD_PREP(HTT_PPDU_STATS_CFG_MSG_TYPE,
+                                     HTT_H2T_MSG_TYPE_PPDU_STATS_CFG);
+
+               pdev_mask = 1 << (i + 1);
+               cmd->msg |= FIELD_PREP(HTT_PPDU_STATS_CFG_PDEV_ID, pdev_mask);
+               cmd->msg |= FIELD_PREP(HTT_PPDU_STATS_CFG_TLV_TYPE_BITMASK, mask);
+
+               ret = ath11k_htc_send(&ab->htc, dp->eid, skb);
+               if (ret) {
+                       dev_kfree_skb_any(skb);
+                       return ret;
+               }
        }
 
        return 0;
                                        HTT_RX_MON_MO_DATA_FILTER_FLASG3;
        }
 
-       ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, dp->mac_id,
-                                              HAL_RXDMA_MONITOR_BUF,
-                                              DP_RXDMA_REFILL_RING_SIZE,
-                                              &tlv_filter);
+       if (ab->hw_params.rxdma1_enable) {
+               ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, dp->mac_id,
+                                                      HAL_RXDMA_MONITOR_BUF,
+                                                      DP_RXDMA_REFILL_RING_SIZE,
+                                                      &tlv_filter);
+       } else if (!reset) {
+               /* set in monitor mode only */
+               for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
+                       ring_id = dp->rx_mac_buf_ring[i].ring_id;
+                       ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id,
+                                                              dp->mac_id + i,
+                                                              HAL_RXDMA_BUF,
+                                                              1024,
+                                                              &tlv_filter);
+               }
+       }
+
        if (ret)
                return ret;
 
                                                       &tlv_filter);
        }
 
+       if (!ar->ab->hw_params.rxdma1_enable)
+               mod_timer(&ar->ab->mon_reap_timer, jiffies +
+                         msecs_to_jiffies(ATH11K_MON_TIMER_INTERVAL));
+
        return ret;
 }
 
                ath11k_warn(ar->ab,
                            "fail to set monitor filter: %d\n", ret);
        }
+       ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
+                  "changed_flags:0x%x, total_flags:0x%x, reset_flag:%d\n",
+                  changed_flags, *total_flags, reset_flag);
+
        mutex_unlock(&ar->conf_mutex);
 }
 
        struct ath11k_base *ab = ar->ab;
        struct ath11k_vif *arvif = (void *)vif->drv_priv;
        int ret;
+       struct peer_create_params param;
 
        mutex_lock(&ar->conf_mutex);
 
 
        /* for QCA6390 bss peer must be created before vdev_start */
        if (ab->hw_params.vdev_start_delay &&
-           arvif->vdev_type != WMI_VDEV_TYPE_AP) {
+           arvif->vdev_type != WMI_VDEV_TYPE_AP &&
+           arvif->vdev_type != WMI_VDEV_TYPE_MONITOR) {
                memcpy(&arvif->chanctx, ctx, sizeof(*ctx));
                mutex_unlock(&ar->conf_mutex);
                return 0;
                return -EBUSY;
        }
 
+       if (ab->hw_params.vdev_start_delay) {
+               param.vdev_id = arvif->vdev_id;
+               param.peer_type = WMI_PEER_TYPE_DEFAULT;
+               param.peer_addr = ar->mac_addr;
+               ret = ath11k_peer_create(ar, arvif, NULL, ¶m);
+       }
+
        ret = ath11k_mac_vdev_start(arvif, &ctx->def);
        if (ret) {
                ath11k_warn(ab, "failed to start vdev %i addr %pM on freq %d: %d\n",
 
        WARN_ON(!arvif->is_started);
 
+       if (ab->hw_params.vdev_start_delay &&
+           arvif->vdev_type == WMI_VDEV_TYPE_MONITOR &&
+           ath11k_peer_find_by_addr(ab, ar->mac_addr))
+               ath11k_peer_delete(ar, arvif->vdev_id, ar->mac_addr);
+
        ret = ath11k_mac_vdev_stop(arvif);
        if (ret)
                ath11k_warn(ab, "failed to stop vdev %i: %d\n",
 
        arvif->is_started = false;
 
+       if (ab->hw_params.vdev_start_delay &&
+           arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)
+               ath11k_wmi_vdev_down(ar, arvif->vdev_id);
+
        mutex_unlock(&ar->conf_mutex);
 }