diff --git a/dp/inc/cdp_txrx_cfg.h b/dp/inc/cdp_txrx_cfg.h index b9715a56c194..d5ef3eb7f937 100644 --- a/dp/inc/cdp_txrx_cfg.h +++ b/dp/inc/cdp_txrx_cfg.h @@ -254,4 +254,9 @@ static inline void cdp_cfg_set_flow_steering(ol_txrx_soc_handle soc, return; } + +static inline void cdp_cfg_get_max_peer_id(ol_txrx_soc_handle soc, + struct cdp_cfg *cfg_pdev) +{ +} #endif /* _CDP_TXRX_CFG_H_ */ diff --git a/dp/inc/cdp_txrx_cmn_struct.h b/dp/inc/cdp_txrx_cmn_struct.h index 2a7d2c3f7b4c..dba86835a488 100644 --- a/dp/inc/cdp_txrx_cmn_struct.h +++ b/dp/inc/cdp_txrx_cmn_struct.h @@ -89,6 +89,15 @@ WME_AC_VO) #define CDP_MAX_RX_RINGS 4 + +/* + * DP configuration parameters + */ +enum cdp_cfg_param_type { + CDP_CFG_MAX_PEER_ID, + CDP_CFG_NUM_PARAMS +}; + /* * htt_dbg_stats_type - * bit positions for each stats type within a stats type bitmask diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h index 2d7ef00cb9c5..c35002d86a33 100644 --- a/dp/inc/cdp_txrx_ops.h +++ b/dp/inc/cdp_txrx_ops.h @@ -615,6 +615,7 @@ struct ol_if_ops { uint8_t vdev_id, uint8_t *peer_mac_addr); int (*peer_unmap_event)(void *ol_soc_handle, uint16_t peer_id); + int (*get_dp_cfg_param)(void *ol_soc_handle, enum cdp_cfg_param_type param_num); /* TODO: Add any other control path calls required to OL_IF/WMA layer */ }; diff --git a/dp/inc/cdp_txrx_stats_struct.h b/dp/inc/cdp_txrx_stats_struct.h index 275c3deedb81..cbab6166959f 100644 --- a/dp/inc/cdp_txrx_stats_struct.h +++ b/dp/inc/cdp_txrx_stats_struct.h @@ -213,6 +213,11 @@ struct ol_ath_radiostats { A_INT16 chan_nf; A_UINT32 rx_last_msdu_unset_cnt; A_INT16 chan_nf_sec80; + A_UINT64 wmi_tx_mgmt; + A_UINT64 wmi_tx_mgmt_completions; + A_UINT32 wmi_tx_mgmt_completion_err; + A_UINT32 peer_delete_req; + A_UINT32 peer_delete_resp; }; #ifndef CONFIG_WIN diff --git a/dp/wifi3.0/dp_htt.c b/dp/wifi3.0/dp_htt.c index f0c2aabbec0a..97a8cd47cc54 100644 --- a/dp/wifi3.0/dp_htt.c +++ b/dp/wifi3.0/dp_htt.c @@ -815,7 +815,7 @@ int htt_h2t_rx_ring_cfg(void *htt_soc, int pdev_id, void *hal_srng, htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, PACKET_HEADER, htt_tlv_filter->packet_header); htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, ATTENTION, - htt_tlv_filter->ppdu_end_status_done); + htt_tlv_filter->attention); htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, PPDU_START, htt_tlv_filter->ppdu_start); htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, PPDU_END, diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index 383c004d7172..5feacf88c5f5 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/dp/wifi3.0/dp_internal.h @@ -284,4 +284,5 @@ QDF_STATUS dp_h2t_ext_stats_msg_send(struct dp_pdev *pdev, uint32_t config_param_1, uint32_t config_param_2, uint32_t config_param_3); void dp_htt_stats_print_tag(uint8_t tag_type, uint32_t *tag_buf); +int dp_peer_rxtid_stats(struct dp_peer *peer); #endif /* #ifndef _DP_INTERNAL_H_ */ diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index c83ddbda875a..6efeee31646d 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -422,9 +422,21 @@ static QDF_STATUS dp_soc_interrupt_attach(void *txrx_soc) int rx_mon_mask = wlan_cfg_get_rx_mon_ring_mask(soc->wlan_cfg_ctx, i); + /* + * Mapping the exception/status rings to IRQ Group 0 (CPU 0). + * Later add wlan_cfg interface for these masks + */ + int rx_err_ring_mask = 0x1; + int rx_wbm_rel_ring_mask = 0x1; + int reo_status_ring_mask = 0x1; + soc->intr_ctx[i].tx_ring_mask = tx_mask; soc->intr_ctx[i].rx_ring_mask = rx_mask; soc->intr_ctx[i].rx_mon_ring_mask = rx_mon_mask; + soc->intr_ctx[i].rx_err_ring_mask = rx_err_ring_mask; + soc->intr_ctx[i].rx_wbm_rel_ring_mask = rx_wbm_rel_ring_mask; + soc->intr_ctx[i].reo_status_ring_mask = reo_status_ring_mask; + soc->intr_ctx[i].soc = soc; num_irq = 0; @@ -446,6 +458,16 @@ static QDF_STATUS dp_soc_interrupt_attach(void *txrx_soc) (rxdma2host_monitor_destination_mac1 - j); } + + if (rx_wbm_rel_ring_mask & (1 << j)) + irq_id_map[num_irq++] = wbm2host_rx_release; + + if (rx_err_ring_mask & (1 << j)) + irq_id_map[num_irq++] = reo2host_exception; + + if (reo_status_ring_mask & (1 << j)) + irq_id_map[num_irq++] = reo2host_status; + } @@ -636,10 +658,10 @@ static int dp_hw_link_desc_pool_setup(struct dp_soc *soc) for (i = 0; i < MAX_LINK_DESC_BANKS && soc->link_desc_banks[i].base_paddr; i++) { uint32_t num_entries = (soc->link_desc_banks[i].size - - (unsigned long)( + ((unsigned long)( soc->link_desc_banks[i].base_vaddr) - (unsigned long)( - soc->link_desc_banks[i].base_vaddr_unaligned)) + soc->link_desc_banks[i].base_vaddr_unaligned))) / link_desc_size; unsigned long paddr = (unsigned long)( soc->link_desc_banks[i].base_paddr); @@ -694,11 +716,11 @@ static int dp_hw_link_desc_pool_setup(struct dp_soc *soc) soc->link_desc_banks[i].base_paddr; i++) { uint32_t num_link_descs = (soc->link_desc_banks[i].size - - (unsigned long)( + ((unsigned long)( soc->link_desc_banks[i].base_vaddr) - (unsigned long)( - soc->link_desc_banks[i].base_vaddr_unaligned)) / - link_desc_size; + soc->link_desc_banks[i].base_vaddr_unaligned))) + / link_desc_size; unsigned long paddr = (unsigned long)( soc->link_desc_banks[i].base_paddr); void *desc = NULL; @@ -1153,6 +1175,7 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc, TAILQ_INIT(&pdev->vdev_list); pdev->vdev_count = 0; + qdf_spinlock_create(&pdev->tx_mutex); qdf_spinlock_create(&pdev->neighbour_peer_mutex); TAILQ_INIT(&pdev->neighbour_peers_list); @@ -1348,6 +1371,7 @@ static void dp_pdev_detach_wifi3(struct cdp_pdev *txrx_pdev, int force) dp_rx_pdev_mon_detach(pdev); dp_neighbour_peers_detach(pdev); + qdf_spinlock_destroy(&pdev->tx_mutex); /* Setup per PDEV REO rings if configured */ if (wlan_cfg_per_pdev_rx_ring(soc->wlan_cfg_ctx)) { @@ -2389,8 +2413,8 @@ static int dp_vdev_set_monitor_mode(struct cdp_vdev *vdev_handle, htt_tlv_filter.enable_mo = 1; htt_h2t_rx_ring_cfg(soc->htt_handle, pdev_id, - pdev->rxdma_mon_dst_ring.hal_srng, - RXDMA_MONITOR_BUF, RX_BUFFER_SIZE, &htt_tlv_filter); + pdev->rxdma_mon_buf_ring.hal_srng, + RXDMA_MONITOR_BUF, RX_BUFFER_SIZE, &htt_tlv_filter); htt_tlv_filter.mpdu_start = 1; htt_tlv_filter.msdu_start = 1; @@ -2405,13 +2429,12 @@ static int dp_vdev_set_monitor_mode(struct cdp_vdev *vdev_handle, htt_tlv_filter.ppdu_end_user_stats_ext = 1; htt_tlv_filter.ppdu_end_status_done = 1; htt_tlv_filter.enable_fp = 1; - htt_tlv_filter.enable_md = 1; + htt_tlv_filter.enable_md = 0; htt_tlv_filter.enable_mo = 1; - /* - * htt_h2t_rx_ring_cfg(soc->htt_handle, pdev_id, - * pdev->rxdma_mon_status_ring.hal_srng, - * RXDMA_MONITOR_STATUS, RX_BUFFER_SIZE, &htt_tlv_filter); - */ + + htt_h2t_rx_ring_cfg(soc->htt_handle, pdev_id, + pdev->rxdma_mon_status_ring.hal_srng, RXDMA_MONITOR_STATUS, + RX_BUFFER_SIZE, &htt_tlv_filter); return QDF_STATUS_SUCCESS; } @@ -2864,6 +2887,9 @@ dp_print_soc_rx_stats(struct dp_soc *soc) DP_TRACE_STATS(FATAL, "SOC Rx Stats:\n"); DP_TRACE_STATS(FATAL, "Errors:\n"); + DP_TRACE_STATS(FATAL, "Rx Decrypt Errors = %d", + (soc->stats.rx.err.rxdma_error[HAL_RXDMA_ERR_DECRYPT] + + soc->stats.rx.err.rxdma_error[HAL_RXDMA_ERR_TKIP_MIC])); DP_TRACE_STATS(FATAL, "Invalid RBM = %d", soc->stats.rx.err.invalid_rbm); DP_TRACE_STATS(FATAL, "Invalid Vdev = %d", @@ -2874,6 +2900,7 @@ dp_print_soc_rx_stats(struct dp_soc *soc) soc->stats.rx.err.rx_invalid_peer.num); DP_TRACE_STATS(FATAL, "HAL Ring Access Fail = %d", soc->stats.rx.err.hal_ring_access_fail); + for (i = 0; i < MAX_RXDMA_ERRORS; i++) { index += qdf_snprint(&rxdma_error[index], DP_RXDMA_ERR_LENGTH - index, @@ -3346,7 +3373,14 @@ dp_get_host_peer_stats(struct cdp_pdev *pdev_handle, char *mac_addr) peer = (struct dp_peer *)dp_find_peer_by_addr(pdev_handle, mac_addr, &local_id); + if (!peer) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "%s: Invalid peer\n", __func__); + return; + } + dp_print_peer_stats(peer); + dp_peer_rxtid_stats(peer); return; } @@ -3389,6 +3423,7 @@ dp_get_fw_peer_stats(struct cdp_pdev *pdev_handle, uint8_t *mac_addr, dp_h2t_ext_stats_msg_send(pdev, HTT_DBG_EXT_STATS_PEER_INFO, config_param0, config_param1, config_param2, config_param3); + } /* @@ -4002,6 +4037,16 @@ void *dp_soc_attach_wifi3(void *osif_soc, void *hif_handle, FL("wlan_cfg_soc_attach failed")); goto fail2; } + + if (soc->cdp_soc.ol_ops->get_dp_cfg_param) { + int ret = soc->cdp_soc.ol_ops->get_dp_cfg_param(soc, + CDP_CFG_MAX_PEER_ID); + + if (ret != -EINVAL) { + wlan_cfg_set_max_peer_id(soc->wlan_cfg_ctx, ret); + } + } + qdf_spinlock_create(&soc->peer_ref_mutex); qdf_spinlock_create(&soc->reo_desc_freelist_lock); diff --git a/dp/wifi3.0/dp_peer.c b/dp/wifi3.0/dp_peer.c index 646a8098091b..59d7ed82c475 100644 --- a/dp/wifi3.0/dp_peer.c +++ b/dp/wifi3.0/dp_peer.c @@ -318,6 +318,69 @@ int dp_peer_find_attach(struct dp_soc *soc) return 0; /* success */ } +static void dp_rx_tid_stats_cb(struct dp_soc *soc, void *cb_ctxt, + union hal_reo_status *reo_status) +{ + struct dp_rx_tid *rx_tid = (struct dp_rx_tid *)cb_ctxt; + struct hal_reo_queue_status *queue_status = &(reo_status->queue_status); + + if (queue_status->header.status != HAL_REO_CMD_SUCCESS) { + DP_TRACE_STATS(FATAL, "REO stats failure %d for TID %d\n", + queue_status->header.status, rx_tid->tid); + return; + } + + DP_TRACE_STATS(FATAL, "REO queue stats (TID: %d): \n" + "ssn: %d\n" + "curr_idx : %d\n" + "pn_31_0 : %08x\n" + "pn_63_32 : %08x\n" + "pn_95_64 : %08x\n" + "pn_127_96 : %08x\n" + "last_rx_enq_tstamp : %08x\n" + "last_rx_deq_tstamp : %08x\n" + "rx_bitmap_31_0 : %08x\n" + "rx_bitmap_63_32 : %08x\n" + "rx_bitmap_95_64 : %08x\n" + "rx_bitmap_127_96 : %08x\n" + "rx_bitmap_159_128 : %08x\n" + "rx_bitmap_191_160 : %08x\n" + "rx_bitmap_223_192 : %08x\n" + "rx_bitmap_255_224 : %08x\n" + "curr_mpdu_cnt : %d\n" + "curr_msdu_cnt : %d\n" + "fwd_timeout_cnt : %d\n" + "fwd_bar_cnt : %d\n" + "dup_cnt : %d\n" + "frms_in_order_cnt : %d\n" + "bar_rcvd_cnt : %d\n" + "mpdu_frms_cnt : %d\n" + "msdu_frms_cnt : %d\n" + "total_byte_cnt : %d\n" + "late_recv_mpdu_cnt : %d\n" + "win_jump_2k : %d\n" + "hole_cnt : %d\n", + rx_tid->tid, + queue_status->ssn, queue_status->curr_idx, + queue_status->pn_31_0, queue_status->pn_63_32, + queue_status->pn_95_64, queue_status->pn_127_96, + queue_status->last_rx_enq_tstamp, + queue_status->last_rx_deq_tstamp, + queue_status->rx_bitmap_31_0, queue_status->rx_bitmap_63_32, + queue_status->rx_bitmap_95_64, queue_status->rx_bitmap_127_96, + queue_status->rx_bitmap_159_128, + queue_status->rx_bitmap_191_160, + queue_status->rx_bitmap_223_192, + queue_status->rx_bitmap_255_224, + queue_status->curr_mpdu_cnt, queue_status->curr_msdu_cnt, + queue_status->fwd_timeout_cnt, queue_status->fwd_bar_cnt, + queue_status->dup_cnt, queue_status->frms_in_order_cnt, + queue_status->bar_rcvd_cnt, queue_status->mpdu_frms_cnt, + queue_status->msdu_frms_cnt, queue_status->total_cnt, + queue_status->late_recv_mpdu_cnt, queue_status->win_jump_2k, + queue_status->hole_cnt); +} + static inline void dp_peer_find_add_id(struct dp_soc *soc, uint8_t *peer_mac_addr, uint16_t peer_id, uint16_t hw_peer_id, uint8_t vdev_id) @@ -1536,3 +1599,31 @@ uint8_t dp_get_peer_mac_addr_frm_id(struct cdp_soc_t *soc_handle, qdf_mem_copy(peer_mac, peer->mac_addr.raw, 6); return peer->vdev->vdev_id; } + +/** + * dp_peer_rxtid_stats: Retried Rx TID (REO queue) stats from HW + * @peer: DP peer handle + * + * Return: 0 on success, error code on failure + */ +int dp_peer_rxtid_stats(struct dp_peer *peer) +{ + struct dp_soc *soc = peer->vdev->pdev->soc; + struct hal_reo_cmd_params params; + int i; + + qdf_mem_zero(¶ms, sizeof(params)); + for (i = 0; i < DP_MAX_TIDS; i++) { + struct dp_rx_tid *rx_tid = &peer->rx_tid[i]; + if (rx_tid->hw_qdesc_vaddr_unaligned != NULL) { + params.std.need_status = 1; + params.std.addr_lo = + rx_tid->hw_qdesc_paddr & 0xffffffff; + params.std.addr_hi = + (uint64_t)(rx_tid->hw_qdesc_paddr) >> 32; + dp_reo_send_cmd(soc, CMD_GET_QUEUE_STATS, ¶ms, + dp_rx_tid_stats_cb, rx_tid); + } + } + return 0; +} diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index 64bfb92cdbd0..617583136f61 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -29,6 +29,19 @@ #include "dp_internal.h" #include "dp_rx_mon.h" +#ifdef RX_DESC_DEBUG_CHECK +static inline void dp_rx_desc_prep(struct dp_rx_desc *rx_desc, qdf_nbuf_t nbuf) +{ + rx_desc->magic = DP_RX_DESC_MAGIC; + rx_desc->nbuf = nbuf; +} +#else +static inline void dp_rx_desc_prep(struct dp_rx_desc *rx_desc, qdf_nbuf_t nbuf) +{ + rx_desc->nbuf = nbuf; +} +#endif + /* * dp_rx_buffers_replenish() - replenish rxdma ring with rx nbufs * called during dp rx initialization @@ -160,7 +173,7 @@ QDF_STATUS dp_rx_buffers_replenish(struct dp_soc *dp_soc, uint32_t mac_id, next = (*desc_list)->next; - (*desc_list)->rx_desc.nbuf = rx_netbuf; + dp_rx_desc_prep(&((*desc_list)->rx_desc), rx_netbuf); QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, "rx_netbuf=%p, buf=%p, paddr=0x%llx, cookie=%d\n", @@ -337,6 +350,8 @@ dp_rx_intrabss_fwd(struct dp_soc *soc, if (da_peer->vdev == sa_peer->vdev && !da_peer->bss_peer) { memset(nbuf->cb, 0x0, sizeof(nbuf->cb)); len = qdf_nbuf_len(nbuf); + qdf_nbuf_set_fctx_type(nbuf, (void *)NULL, + CB_FTYPE_INTRABSS_FWD); if (!dp_tx_send(sa_peer->vdev, nbuf)) { DP_STATS_INC_PKT(sa_peer, rx.intra_bss.pkts, 1, len); @@ -363,9 +378,12 @@ dp_rx_intrabss_fwd(struct dp_soc *soc, return false; memset(nbuf_copy->cb, 0x0, sizeof(nbuf_copy->cb)); len = qdf_nbuf_len(nbuf_copy); - if (dp_tx_send(sa_peer->vdev, nbuf_copy)) + qdf_nbuf_set_fctx_type(nbuf_copy, (void *)NULL, + CB_FTYPE_INTRABSS_FWD); + if (dp_tx_send(sa_peer->vdev, nbuf_copy)) { + DP_STATS_INC_PKT(sa_peer, rx.intra_bss.fail, 1, len); qdf_nbuf_free(nbuf_copy); - else + } else DP_STATS_INC_PKT(sa_peer, rx.intra_bss.pkts, 1, len); } /* return false as we have to still send the original pkt diff --git a/dp/wifi3.0/dp_rx.h b/dp/wifi3.0/dp_rx.h index d5715da17526..447c514a3218 100644 --- a/dp/wifi3.0/dp_rx.h +++ b/dp/wifi3.0/dp_rx.h @@ -45,6 +45,8 @@ (((_peer_metadata) & DP_PEER_METADATA_VDEV_ID_MASK) \ >> DP_PEER_METADATA_VDEV_ID_SHIFT) +#define DP_RX_DESC_MAGIC 0xdec0de + /** * struct dp_rx_desc * @@ -65,6 +67,9 @@ struct dp_rx_desc { uint8_t *rx_buf_start; uint32_t cookie; uint8_t pool_id; +#ifdef RX_DESC_DEBUG_CHECK + uint32_t magic; +#endif }; #define RX_DESC_COOKIE_INDEX_SHIFT 0 @@ -343,13 +348,13 @@ dp_rx_wds_srcport_learn(struct dp_soc *soc, if (!hal_rx_msdu_end_sa_is_valid_get(rx_tlv_hdr)) { ret = soc->cdp_soc.ol_ops->peer_add_wds_entry( - soc->osif_soc, + ta_peer->vdev->pdev->osif_pdev, wds_src_mac, ta_peer->mac_addr.raw, flags); } else if (sa_sw_peer_id != ta_peer->peer_ids[0]) { ret = soc->cdp_soc.ol_ops->peer_update_wds_entry( - soc->osif_soc, + ta_peer->vdev->pdev->osif_pdev, wds_src_mac, ta_peer->mac_addr.raw, flags); diff --git a/dp/wifi3.0/dp_rx_desc.c b/dp/wifi3.0/dp_rx_desc.c index bfd0679a8dbc..339944141343 100644 --- a/dp/wifi3.0/dp_rx_desc.c +++ b/dp/wifi3.0/dp_rx_desc.c @@ -55,13 +55,11 @@ QDF_STATUS dp_rx_desc_pool_alloc(struct dp_soc *soc, uint32_t pool_id, rx_desc_pool->array[i].next = &rx_desc_pool->array[i+1]; rx_desc_pool->array[i].rx_desc.cookie = i | (pool_id << 18); rx_desc_pool->array[i].rx_desc.pool_id = pool_id; - rx_desc_pool->array[i].rx_desc.nbuf = NULL; } rx_desc_pool->array[i].next = NULL; rx_desc_pool->array[i].rx_desc.cookie = i | (pool_id << 18); rx_desc_pool->array[i].rx_desc.pool_id = pool_id; - rx_desc_pool->array[i].rx_desc.nbuf = NULL; qdf_spin_unlock_bh(&soc->rx_desc_mutex[pool_id]); return QDF_STATUS_SUCCESS; } diff --git a/dp/wifi3.0/dp_rx_err.c b/dp/wifi3.0/dp_rx_err.c index 6a65be9369fc..cfd054eb4402 100644 --- a/dp/wifi3.0/dp_rx_err.c +++ b/dp/wifi3.0/dp_rx_err.c @@ -31,6 +31,22 @@ #include "dp_rx_defrag.h" #include /* LLC_SNAP_HDR_LEN */ +#ifdef RX_DESC_DEBUG_CHECK +static inline bool dp_rx_desc_check_magic(struct dp_rx_desc *rx_desc) +{ + if (qdf_unlikely(rx_desc->magic != DP_RX_DESC_MAGIC)) { + return false; + } + rx_desc->magic = 0; + return true; +} +#else +static inline bool dp_rx_desc_check_magic(struct dp_rx_desc *rx_desc) +{ + return true; +} +#endif + /** * dp_rx_msdus_drop() - Drops all MSDU's per MPDU * @@ -46,10 +62,10 @@ * Return: uint32_t: No. of elements processed */ static uint32_t dp_rx_msdus_drop(struct dp_soc *soc, void *ring_desc, - struct hal_rx_mpdu_desc_info *mpdu_desc_info, - union dp_rx_desc_list_elem_t **head, - union dp_rx_desc_list_elem_t **tail, - uint32_t quota) + struct hal_rx_mpdu_desc_info *mpdu_desc_info, + union dp_rx_desc_list_elem_t **head, + union dp_rx_desc_list_elem_t **tail, + uint32_t quota) { uint32_t rx_bufs_used = 0; void *link_desc_va; @@ -72,6 +88,13 @@ static uint32_t dp_rx_msdus_drop(struct dp_soc *soc, void *ring_desc, qdf_assert(rx_desc); + if (!dp_rx_desc_check_magic(rx_desc)) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + FL("Invalid rx_desc cookie=%d"), + msdu_list.sw_cookie[i]); + return rx_bufs_used; + } + rx_bufs_used++; /* Just free the buffers */ @@ -224,6 +247,9 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, struct dp_rx_desc *rx_desc, uint16_t peer_id = 0xFFFF; struct dp_peer *peer = NULL; uint32_t sgi, rate_mcs, tid; + uint8_t count; + struct mect_entry *mect_entry; + uint8_t *nbuf_data = NULL; rx_bufs_used++; @@ -293,11 +319,6 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, struct dp_rx_desc *rx_desc, "%s: %d, SGI: %d, rate_mcs: %d, tid: %d", __func__, __LINE__, sgi, rate_mcs, tid); - /* WDS Source Port Learning */ - if (qdf_likely(vdev->rx_decap_type == htt_cmn_pkt_type_ethernet) && - (vdev->wds_enabled)) - dp_rx_wds_srcport_learn(soc, rx_desc->rx_buf_start, peer, nbuf); - /* * Advance the packet start pointer by total size of * pre-header TLV's @@ -307,6 +328,28 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, struct dp_rx_desc *rx_desc, if (l2_hdr_offset) qdf_nbuf_pull_head(nbuf, l2_hdr_offset); + nbuf_data = qdf_nbuf_data(nbuf); + for (count = 0; count < soc->mect_cnt; count++) { + mect_entry = &soc->mect_table[count]; + mect_entry->ts = jiffies_64; + if (!(memcmp(mect_entry->mac_addr, &nbuf_data[DP_MAC_ADDR_LEN], + DP_MAC_ADDR_LEN))) { + QDF_TRACE(QDF_MODULE_ID_DP, + QDF_TRACE_LEVEL_INFO, + FL("received pkt with same src MAC")); + + /* Drop & free packet */ + qdf_nbuf_free(nbuf); + /* Statistics */ + goto fail; + } + } + + /* WDS Source Port Learning */ + if (qdf_likely(vdev->rx_decap_type == htt_cmn_pkt_type_ethernet) && + (vdev->wds_enabled)) + dp_rx_wds_srcport_learn(soc, rx_desc->rx_buf_start, peer, nbuf); + if (hal_rx_mpdu_start_mpdu_qos_control_valid_get( rx_desc->rx_buf_start)) { /* TODO: Assuming that qos_control_valid also indicates @@ -633,12 +676,20 @@ dp_rx_wbm_err_process(struct dp_soc *soc, void *hal_ring, uint32_t quota) rx_desc = dp_rx_cookie_2_va_rxdma_buf(soc, rx_buf_cookie); qdf_assert(rx_desc); + if (!dp_rx_desc_check_magic(rx_desc)) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + FL("Invalid rx_desc cookie=%d"), + rx_buf_cookie); + continue; + } + /* XXX */ buf_type = HAL_RX_WBM_BUF_TYPE_GET(ring_desc); + /* * For WBM ring, expect only MSDU buffers */ - qdf_assert(buf_type == HAL_RX_WBM_BUF_TYPE_REL_BUF); + qdf_assert_always(buf_type == HAL_RX_WBM_BUF_TYPE_REL_BUF); if (wbm_err_src == HAL_RX_WBM_ERR_SRC_REO) { @@ -706,18 +757,6 @@ dp_rx_wbm_err_process(struct dp_soc *soc, void *hal_ring, uint32_t quota) } } else { /* Should not come here */ - rx_buf_cookie = HAL_RX_WBM_BUF_COOKIE_GET(ring_desc); - rx_desc = dp_rx_cookie_2_va_rxdma_buf(soc, rx_buf_cookie); - - qdf_assert(rx_desc); - - qdf_nbuf_unmap_single(soc->osdev, rx_desc->nbuf, - QDF_DMA_BIDIRECTIONAL); - - rx_desc->rx_buf_start = qdf_nbuf_data(rx_desc->nbuf); - hal_rx_dump_pkt_tlvs(rx_desc->rx_buf_start, - QDF_TRACE_LEVEL_INFO); - qdf_assert(0); } diff --git a/dp/wifi3.0/dp_rx_mon_dest.c b/dp/wifi3.0/dp_rx_mon_dest.c index 1ffa37b83425..003ea4fc050a 100644 --- a/dp/wifi3.0/dp_rx_mon_dest.c +++ b/dp/wifi3.0/dp_rx_mon_dest.c @@ -99,8 +99,7 @@ done: * @tail: tail of decs list to be freed * Return: number of msdu in MPDU to be popped */ -static inline -uint32_t +static inline uint32_t dp_rx_mon_mpdu_pop(struct dp_soc *soc, uint32_t mac_id, void *rxdma_dst_ring_desc, qdf_nbuf_t *head_msdu, qdf_nbuf_t *tail_msdu, uint32_t *npackets, uint32_t *ppdu_id, @@ -161,6 +160,23 @@ dp_rx_mon_mpdu_pop(struct dp_soc *soc, uint32_t mac_id, "[%s][%d] msdu_nbuf=%p, data=%p\n", __func__, __LINE__, msdu, data); + rx_desc_tlv = HAL_RX_MON_DEST_GET_DESC(data); + msdu_ppdu_id = + HAL_RX_MON_HW_DESC_GET_PPDUID_GET(rx_desc_tlv); + + QDF_TRACE(QDF_MODULE_ID_DP, + QDF_TRACE_LEVEL_DEBUG, + "[%s][%d] i=%d, ppdu_id=%x, msdu_ppdu_id=%x\n", + __func__, __LINE__, i, *ppdu_id, msdu_ppdu_id); + if (*ppdu_id != msdu_ppdu_id) { + *ppdu_id = msdu_ppdu_id; + return rx_bufs_used; + } + + if (hal_rx_desc_is_first_msdu(rx_desc_tlv)) + hal_rx_mon_hw_desc_get_mpdu_status(rx_desc_tlv, + &(dp_pdev->ppdu_info.rx_status)); + rx_pkt_offset = HAL_RX_MON_HW_RX_DESC_SIZE(); /* * HW structures call this L3 header padding @@ -176,7 +192,6 @@ dp_rx_mon_mpdu_pop(struct dp_soc *soc, uint32_t mac_id, qdf_nbuf_set_pktlen(msdu, rx_buf_size); - rx_desc_tlv = HAL_RX_MON_DEST_GET_DESC(data); #if 0 /* Disble it.see packet on msdu done set to 0 */ @@ -200,17 +215,6 @@ dp_rx_mon_mpdu_pop(struct dp_soc *soc, uint32_t mac_id, } #endif - msdu_ppdu_id = - HAL_RX_MON_HW_DESC_GET_PPDUID_GET(rx_desc_tlv); - -#if 0 - /* Temporary only handle destination ring */ - if (*ppdu_id != msdu_ppdu_id) { - *ppdu_id = msdu_ppdu_id; - return rx_bufs_used; - } -#endif - rx_bufs_used++; QDF_TRACE(QDF_MODULE_ID_DP, @@ -306,8 +310,6 @@ qdf_nbuf_t dp_rx_mon_restitch_mpdu_from_msdus(struct dp_soc *soc, rx_desc = qdf_nbuf_data(head_msdu); - HAL_RX_MON_HW_DESC_GET_PPDU_START_STATUS(rx_desc, rx_status); - decap_format = HAL_RX_DESC_GET_DECAP_FORMAT(rx_desc); /* Easy case - The MSDU status indicates that this is a non-decapped @@ -616,7 +618,6 @@ QDF_STATUS dp_rx_mon_deliver(struct dp_soc *soc, uint32_t mac_id, struct cdp_mon_status *rs = &pdev->rx_mon_recv_status; qdf_nbuf_t mon_skb, skb_next; qdf_nbuf_t mon_mpdu = NULL; - struct mon_rx_status rx_mon_status; if ((pdev->monitor_vdev == NULL) || (pdev->monitor_vdev->osif_rx_mon == NULL)) { @@ -628,13 +629,10 @@ QDF_STATUS dp_rx_mon_deliver(struct dp_soc *soc, uint32_t mac_id, tail_msdu, rs); if (mon_mpdu) { - /* Push radiotap header */ - dp_rx_extract_radiotap_info(rs, &rx_mon_status); - - qdf_nbuf_update_radiotap(&rx_mon_status, mon_mpdu, - sizeof(struct rx_pkt_tlvs)); + qdf_nbuf_update_radiotap(&(pdev->ppdu_info.rx_status), + mon_mpdu, sizeof(struct rx_pkt_tlvs)); pdev->monitor_vdev->osif_rx_mon( - pdev->monitor_vdev->osif_vdev, mon_mpdu, rs); + pdev->monitor_vdev->osif_vdev, mon_mpdu, NULL); } else { goto mon_deliver_fail; } @@ -676,8 +674,8 @@ void dp_rx_mon_dest_process(struct dp_soc *soc, uint32_t mac_id, uint32_t quota) void *mon_dst_srng = pdev->rxdma_mon_dst_ring.hal_srng; union dp_rx_desc_list_elem_t *head = NULL; union dp_rx_desc_list_elem_t *tail = NULL; - struct dp_srng *dp_rxdma_srng; - struct rx_desc_pool *rx_desc_pool; + uint32_t ppdu_id; + uint32_t rx_bufs_used; #ifdef DP_INTR_POLL_BASED if (!pdev) @@ -687,12 +685,6 @@ void dp_rx_mon_dest_process(struct dp_soc *soc, uint32_t mac_id, uint32_t quota) pdev_id = pdev->pdev_id; mon_dst_srng = pdev->rxdma_mon_dst_ring.hal_srng; -#if 0 - /* Temporary only handle destination ring */ - if (pdev->mon_ppdu_status != DP_PPDU_STATUS_DONE) - return; -#endif - if (!mon_dst_srng) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "%s %d : HAL Monitor Destination Ring Init \ @@ -713,44 +705,40 @@ void dp_rx_mon_dest_process(struct dp_soc *soc, uint32_t mac_id, uint32_t quota) return; } + ppdu_id = pdev->ppdu_info.com_info.ppdu_id; + rx_bufs_used = 0; while (qdf_likely((rxdma_dst_ring_desc = - hal_srng_dst_peek(hal_soc, mon_dst_srng)))) { - qdf_nbuf_t head_msdu, tail_msdu; - uint32_t rx_bufs_used = 0; - uint32_t npackets, ppdu_id; - head_msdu = (qdf_nbuf_t) NULL; - tail_msdu = (qdf_nbuf_t) NULL; + hal_srng_dst_peek(hal_soc, mon_dst_srng)) && quota--)) { + qdf_nbuf_t head_msdu, tail_msdu; + uint32_t npackets; + head_msdu = (qdf_nbuf_t) NULL; + tail_msdu = (qdf_nbuf_t) NULL; - ppdu_id = pdev->mon_ppdu_id; - rx_bufs_used += dp_rx_mon_mpdu_pop(soc, mac_id, - rxdma_dst_ring_desc, - &head_msdu, &tail_msdu, - &npackets, &ppdu_id, - &head, &tail); -#if 0 - /* Temporary only handle destination ring */ - if (ppdu_id != pdev->mon_ppdu_id) { - pdev->mon_ppdu_status = DP_PPDU_STATUS_START; - break; - } -#endif + rx_bufs_used += dp_rx_mon_mpdu_pop(soc, mac_id, + rxdma_dst_ring_desc, + &head_msdu, &tail_msdu, + &npackets, &ppdu_id, + &head, &tail); - dp_rx_mon_deliver(soc, mac_id, head_msdu, tail_msdu); + if (ppdu_id != pdev->ppdu_info.com_info.ppdu_id) { + pdev->mon_ppdu_status = DP_PPDU_STATUS_START; + qdf_mem_zero(&(pdev->ppdu_info.rx_status), + sizeof(pdev->ppdu_info.rx_status)); + break; + } - /* replenish function should be changed to include - * ring pointer */ - dp_rxdma_srng = &pdev->rxdma_mon_buf_ring; - rx_desc_pool = &soc->rx_desc_mon[pdev_id]; + dp_rx_mon_deliver(soc, mac_id, head_msdu, tail_msdu); - dp_rx_buffers_replenish(soc, pdev_id, dp_rxdma_srng, - rx_desc_pool, rx_bufs_used, &head, &tail, - HAL_RX_BUF_RBM_SW3_BM); - - rxdma_dst_ring_desc = hal_srng_dst_get_next(hal_soc, - mon_dst_srng); + rxdma_dst_ring_desc = hal_srng_dst_get_next(hal_soc, + mon_dst_srng); } - hal_srng_access_end(hal_soc, mon_dst_srng); + + if (rx_bufs_used) { + dp_rx_buffers_replenish(soc, pdev_id, + &pdev->rxdma_mon_buf_ring, &soc->rx_desc_mon[pdev_id], + rx_bufs_used, &head, &tail, HAL_RX_BUF_RBM_SW3_BM); + } } static QDF_STATUS @@ -940,12 +928,6 @@ static int dp_mon_link_desc_pool_setup(struct dp_soc *soc, uint32_t mac_id) hal_srng_src_get_next(soc->hal_soc, mon_desc_srng))) { - QDF_TRACE(QDF_MODULE_ID_TXRX, - QDF_TRACE_LEVEL_DEBUG, - "[%s][%d] desc=%p, i=%d, vaddr=%lx, paddr=%lx", - __func__, __LINE__, desc, i, - (unsigned long)vaddr, (unsigned long)paddr); - hal_set_link_desc_addr(desc, i, paddr); num_entries--; num_replenish_buf++; diff --git a/dp/wifi3.0/dp_rx_mon_status.c b/dp/wifi3.0/dp_rx_mon_status.c index 5e87fd654f04..2e3d1a6a9ddf 100644 --- a/dp/wifi3.0/dp_rx_mon_status.c +++ b/dp/wifi3.0/dp_rx_mon_status.c @@ -36,7 +36,9 @@ * Return: none */ static inline void -dp_rx_mon_status_process_tlv(struct dp_soc *soc, uint32_t mac_id) { +dp_rx_mon_status_process_tlv(struct dp_soc *soc, uint32_t mac_id, + uint32_t quota) +{ struct dp_pdev *pdev = soc->pdev_list[mac_id]; struct hal_rx_ppdu_info *ppdu_info; qdf_nbuf_t status_nbuf; @@ -73,12 +75,8 @@ dp_rx_mon_status_process_tlv(struct dp_soc *soc, uint32_t mac_id) { qdf_nbuf_free(status_nbuf); if (tlv_status == HAL_TLV_STATUS_PPDU_DONE) { - pdev->mon_ppdu_status = DP_PPDU_STATUS_DONE; - /* Temperary */ - pdev->mon_ppdu_status = - DP_PPDU_STATUS_START; - break; + dp_rx_mon_dest_process(soc, mac_id, quota); } } return; @@ -237,8 +235,8 @@ dp_rx_mon_status_process(struct dp_soc *soc, uint32_t mac_id, uint32_t quota) { uint32_t work_done; work_done = dp_rx_mon_status_srng_process(soc, mac_id, quota); - - dp_rx_mon_status_process_tlv(soc, mac_id); + quota -= work_done; + dp_rx_mon_status_process_tlv(soc, mac_id, quota); return work_done; } @@ -255,14 +253,9 @@ dp_rx_mon_status_process(struct dp_soc *soc, uint32_t mac_id, uint32_t quota) { */ uint32_t dp_mon_process(struct dp_soc *soc, uint32_t mac_id, uint32_t quota) { - uint32_t work_done; - - work_done = dp_rx_mon_status_process(soc, mac_id, quota); - - dp_rx_mon_dest_process(soc, mac_id, quota); - - return work_done; + return dp_rx_mon_status_process(soc, mac_id, quota); } + /** * dp_rx_pdev_mon_detach() - detach dp rx for status ring * @pdev: core txrx pdev context @@ -397,7 +390,7 @@ QDF_STATUS dp_rx_mon_status_buffers_replenish(struct dp_soc *dp_soc, hal_rxdma_buff_addr_info_set(rxdma_ring_entry, paddr, (*desc_list)->rx_desc.cookie, owner); - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, "[%s][%d] rx_desc=%p, cookie=%d, nbuf=%p, \ status_buf=%p paddr=%p\n", __func__, __LINE__, &(*desc_list)->rx_desc, @@ -474,6 +467,8 @@ dp_rx_pdev_mon_status_attach(struct dp_pdev *pdev) { qdf_nbuf_queue_init(&pdev->rx_status_q); pdev->mon_ppdu_status = DP_PPDU_STATUS_START; + qdf_mem_zero(&(pdev->ppdu_info.rx_status), + sizeof(pdev->ppdu_info.rx_status)); return QDF_STATUS_SUCCESS; } diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c index 09f2a33857f1..85e31dd22606 100644 --- a/dp/wifi3.0/dp_tx.c +++ b/dp/wifi3.0/dp_tx.c @@ -1397,11 +1397,53 @@ qdf_nbuf_t dp_tx_send(void *vap_dev, qdf_nbuf_t nbuf) struct dp_tx_msdu_info_s msdu_info; struct dp_tx_seg_info_s seg_info; struct dp_vdev *vdev = (struct dp_vdev *) vap_dev; + struct dp_soc *soc = vdev->pdev->soc; uint16_t peer_id = HTT_INVALID_PEER; + uint8_t count; + uint8_t found = 0; + uint8_t oldest_mec_entry_idx = 0; + uint64_t oldest_mec_ts = 0; + struct mect_entry *mect_entry; qdf_mem_set(&msdu_info, sizeof(msdu_info), 0x0); qdf_mem_set(&seg_info, sizeof(seg_info), 0x0); + if (qdf_nbuf_get_ftype(nbuf) == CB_FTYPE_INTRABSS_FWD) + goto out; + + eh = (struct ether_header *)qdf_nbuf_data(nbuf); + if (DP_FRAME_IS_MULTICAST((eh)->ether_dhost)) { + for (count = 0; count < soc->mect_cnt; count++) { + mect_entry = &soc->mect_table[count]; + if (!memcmp(mect_entry->mac_addr, eh->ether_shost, + DP_MAC_ADDR_LEN)) { + found = 1; + break; + } + + if (!oldest_mec_ts) { + oldest_mec_entry_idx = count; + oldest_mec_ts = mect_entry->ts; + } else if (mect_entry->ts < oldest_mec_ts) { + oldest_mec_entry_idx = count; + oldest_mec_ts = mect_entry->ts; + } + } + + if (!found) { + if (count >= DP_MAX_MECT_ENTRIES) + count = oldest_mec_entry_idx; + else + soc->mect_cnt++; + + mect_entry = &soc->mect_table[count]; + mect_entry->ts = jiffies_64; + memcpy(mect_entry->mac_addr, eh->ether_shost, + DP_MAC_ADDR_LEN); + } + } + +out: QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, "%s , skb %0x:%0x:%0x:%0x:%0x:%0x\n", __func__, nbuf->data[0], nbuf->data[1], nbuf->data[2], diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 27255c187b29..7a472afd2393 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -87,6 +87,7 @@ #define MAX_TX_HW_QUEUES 3 #define DP_MAX_INTERRUPT_CONTEXTS 8 +#define DP_MAX_MECT_ENTRIES 64 struct dp_soc_cmn; struct dp_pdev; @@ -378,6 +379,13 @@ struct dp_ast_entry { TAILQ_ENTRY(dp_ast_entry) ast_entry_elem; }; +struct mect_entry { + uint8_t idx; + uint8_t valid; + uint8_t mac_addr[6]; + uint64_t ts; +}; + /* SOC level structure for data path */ struct dp_soc { /* Common base structure - Should be the first member */ @@ -612,6 +620,9 @@ struct dp_soc { #endif qdf_list_t reo_desc_freelist; qdf_spinlock_t reo_desc_freelist_lock; + struct mect_entry mect_table[DP_MAX_MECT_ENTRIES]; + uint8_t mect_cnt; + /* Obj Mgr SoC */ struct wlan_objmgr_psoc *psoc; qdf_nbuf_t invalid_peer_head_msdu; @@ -791,7 +802,6 @@ struct dp_pdev { uint8_t operating_channel; qdf_nbuf_queue_t rx_status_q; - uint32_t mon_ppdu_id; uint32_t mon_ppdu_status; struct cdp_mon_status rx_mon_recv_status; diff --git a/dp/wifi3.0/hal_rx.h b/dp/wifi3.0/hal_rx.h index c463143b7d9e..cb53401274c9 100644 --- a/dp/wifi3.0/hal_rx.h +++ b/dp/wifi3.0/hal_rx.h @@ -1684,6 +1684,47 @@ enum hal_reo_error_code { HAL_REO_ERR_QUEUE_DESC_BLOCKED_SET }; +/** + * enum hal_rxdma_error_code: Code describing the type of RxDMA error detected + * + * @HAL_RXDMA_ERR_OVERFLOW: MPDU frame is not complete due to a FIFO overflow + * @ HAL_RXDMA_ERR_OVERFLOW : MPDU frame is not complete due to a FIFO + * overflow + * @ HAL_RXDMA_ERR_MPDU_LENGTH : MPDU frame is not complete due to receiving + * incomplete + * MPDU from the PHY + * @ HAL_RXDMA_ERR_FCS : FCS check on the MPDU frame failed + * @ HAL_RXDMA_ERR_DECRYPT : Decryption error + * @ HAL_RXDMA_ERR_TKIP_MIC : TKIP MIC error + * @ HAL_RXDMA_ERR_UNECRYPTED : Received a frame that was expected to be + * encrypted but wasn’t + * @ HAL_RXDMA_ERR_MSDU_LEN : MSDU related length error + * @ HAL_RXDMA_ERR_MSDU_LIMIT : Number of MSDUs in the MPDUs exceeded + * the max allowed + * @ HAL_RXDMA_ERR_WIFI_PARSE : wifi parsing error + * @ HAL_RXDMA_ERR_AMSDU_PARSE : Amsdu parsing error + * @ HAL_RXDMA_ERR_SA_TIMEOUT : Source Address search timeout + * @ HAL_RXDMA_ERR_DA_TIMEOUT : Destination Address search timeout + * @ HAL_RXDMA_ERR_FLOW_TIMEOUT : Flow Search Timeout + * @ HAL_RXDMA_ERR_FLUSH_REQUEST : RxDMA FIFO Flush request + */ +enum hal_rxdma_error_code { + HAL_RXDMA_ERR_OVERFLOW = 0, + HAL_RXDMA_ERR_MPDU_LENGTH, + HAL_RXDMA_ERR_FCS, + HAL_RXDMA_ERR_DECRYPT, + HAL_RXDMA_ERR_TKIP_MIC, + HAL_RXDMA_ERR_UNECRYPTED, + HAL_RXDMA_ERR_MSDU_LEN, + HAL_RXDMA_ERR_MSDU_LIMIT, + HAL_RXDMA_ERR_WIFI_PARSE, + HAL_RXDMA_ERR_AMSDU_PARSE, + HAL_RXDMA_ERR_SA_TIMEOUT, + HAL_RXDMA_ERR_DA_TIMEOUT, + HAL_RXDMA_ERR_FLOW_TIMEOUT, + HAL_RXDMA_ERR_FLUSH_REQUEST +}; + #define HAL_RX_REO_ERROR_GET(reo_desc) (((*(((uint32_t *) reo_desc)+ \ (REO_DESTINATION_RING_7_REO_ERROR_CODE_OFFSET >> 2))) & \ REO_DESTINATION_RING_7_REO_ERROR_CODE_MASK) >> \ @@ -1916,10 +1957,6 @@ enum hal_rx_wbm_rxdma_push_reason { HAL_RX_BUF_COOKIE_GET(&((struct wbm_release_ring *) \ wbm_desc)->released_buff_or_desc_addr_info) -#define HAL_RX_WBM_BUF_COOKIE_GET(wbm_desc) \ - HAL_RX_BUF_COOKIE_GET(&((struct wbm_release_ring *) \ - wbm_desc)->released_buff_or_desc_addr_info) - /** * hal_rx_dump_rx_attention_tlv: dump RX attention TLV in structured * humman readable format. diff --git a/hal/wifi3.0/hal_api_mon.h b/hal/wifi3.0/hal_api_mon.h index 14eb550e140f..b78854563fc8 100644 --- a/hal/wifi3.0/hal_api_mon.h +++ b/hal/wifi3.0/hal_api_mon.h @@ -32,6 +32,7 @@ HAL_RX_LSB(block, field)) #define HAL_RX_PHY_DATA_RADAR 0x01 +#define HAL_SU_MU_CODING_LDPC 0x01 #define HAL_RX_FCS_LEN (4) #define KEY_EXTIV 0x20 @@ -74,6 +75,17 @@ #define HAL_MAX_UL_MU_USERS 8 +#define HAL_RX_PKT_TYPE_11A 0 +#define HAL_RX_PKT_TYPE_11B 1 +#define HAL_RX_PKT_TYPE_11N 2 +#define HAL_RX_PKT_TYPE_11AC 3 +#define HAL_RX_PKT_TYPE_11AX 4 + +#define HAL_RX_RECEPTION_TYPE_SU 0 +#define HAL_RX_RECEPTION_TYPE_MU_MIMO 1 +#define HAL_RX_RECEPTION_TYPE_OFDMA 2 +#define HAL_RX_RECEPTION_TYPE_MU_OFDMA 3 + enum { HAL_HW_RX_DECAP_FORMAT_RAW = 0, HAL_HW_RX_DECAP_FORMAT_NWIFI, @@ -154,6 +166,16 @@ uint32_t HAL_RX_MON_HW_DESC_GET_PPDUID_GET(void *hw_desc_addr) return HAL_RX_GET(rx_attn, RX_ATTENTION_0, PHY_PPDU_ID); } +/* TODO: Move all Rx descriptor functions to hal_rx.h to avoid duplication */ +static inline +uint32_t hal_rx_desc_is_first_msdu(void *hw_desc_addr) +{ + struct rx_pkt_tlvs *rx_tlvs = (struct rx_pkt_tlvs *)hw_desc_addr; + struct rx_msdu_end *msdu_end = &rx_tlvs->msdu_end_tlv.rx_msdu_end; + + return HAL_RX_GET(msdu_end, RX_MSDU_END_5, FIRST_MSDU); +} + #define HAL_RX_BUFFER_ADDR_31_0_GET(buff_addr_info) \ (_HAL_MS((*_OFFSET_TO_WORD_PTR(buff_addr_info, \ BUFFER_ADDR_INFO_0_BUFFER_ADDR_31_0_OFFSET)), \ @@ -286,7 +308,7 @@ uint32 hal_get_rx_msdu_link_desc_size(void) enum { HAL_PKT_TYPE_OFDM = 0, - HAL_CDP_PKT_TYPE_CCK, + HAL_PKT_TYPE_CCK, HAL_PKT_TYPE_HT, HAL_PKT_TYPE_VHT, HAL_PKT_TYPE_HE, @@ -313,73 +335,60 @@ enum { HAL_RX_TYPE_MU_OFDMA_MIMO, }; +/** + * hal_rx_mon_hw_desc_get_mpdu_status: Retrieve MPDU status + * + * @ hw_desc_addr: Start address of Rx HW TLVs + * @ rs: Status for monitor mode + * + * Return: void + */ static inline -void HAL_RX_MON_HW_DESC_GET_PPDU_START_STATUS(void *hw_desc_addr, - struct cdp_mon_status *rs) +void hal_rx_mon_hw_desc_get_mpdu_status(void *hw_desc_addr, + struct mon_rx_status *rs) { struct rx_msdu_start *rx_msdu_start; struct rx_pkt_tlvs *rx_desc = (struct rx_pkt_tlvs *)hw_desc_addr; - uint32_t rx_pream_type; - uint32_t rx_sgi; - uint32_t rx_type; - uint32_t rx_bw; -static uint32_t pkt_type_hw_to_cdp[] = { - CDP_PKT_TYPE_OFDM, - CDP_PKT_TYPE_CCK, - CDP_PKT_TYPE_HT, - CDP_PKT_TYPE_VHT, - CDP_PKT_TYPE_HE, - }; + uint32_t reg_value; -static uint32_t sgi_hw_to_cdp[] = { - CDP_SGI_0_8_US, - CDP_SGI_0_4_US, - CDP_SGI_1_6_US, - CDP_SGI_3_2_US, - }; - -static uint32_t rx_type_hw_to_cdp[] = { - CDP_RX_TYPE_SU, - CDP_RX_TYPE_MU_MIMO, - CDP_RX_TYPE_MU_OFDMA, - CDP_RX_TYPE_MU_OFDMA_MIMO, - }; - -static uint32_t rx_bw_hw_to_cdp[] = { - CDP_FULL_RX_BW_20, - CDP_FULL_RX_BW_40, - CDP_FULL_RX_BW_80, - CDP_FULL_RX_BW_160, - }; + static uint32_t sgi_hw_to_cdp[] = { + CDP_SGI_0_8_US, + CDP_SGI_0_4_US, + CDP_SGI_1_6_US, + CDP_SGI_3_2_US, + }; rx_msdu_start = &rx_desc->msdu_start_tlv.rx_msdu_start; - rs->cdp_rs_tstamp.cdp_tsf = rx_msdu_start->ppdu_start_timestamp; - - rx_pream_type = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, PKT_TYPE); - rs->cdp_rs_pream_type = pkt_type_hw_to_cdp[rx_pream_type]; - - rs->cdp_rs_user_rssi = HAL_RX_GET(rx_msdu_start, + rs->ant_signal_db = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, USER_RSSI); - - rs->cdp_rs_stbc = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, STBC); - - rx_sgi = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, SGI); - rs->cdp_rs_sgi = sgi_hw_to_cdp[rx_sgi]; - - rs->cdf_rs_rate_mcs = HAL_RX_GET(rx_msdu_start, + rs->mcs = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, RATE_MCS); + rs->is_stbc = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, STBC); - rx_type = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, RECEPTION_TYPE); + reg_value = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, SGI); + rs->sgi = sgi_hw_to_cdp[reg_value]; + rs->nr_ant = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, NSS); - rs->cdp_rs_reception_type = rx_type_hw_to_cdp[rx_type]; - - rx_bw = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, RECEIVE_BANDWIDTH); - - rs->cdp_rs_bw = rx_bw_hw_to_cdp[rx_bw]; - - rs->cdp_rs_nss = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, NSS); + reg_value = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, PKT_TYPE); + switch (reg_value) { + case HAL_RX_PKT_TYPE_11AC: + rs->vht_flags = 1; + reg_value = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, + RECEIVE_BANDWIDTH); + rs->vht_flag_values2 = 0x01 << reg_value; + rs->vht_flag_values3[0] = rs->mcs << 4; + break; + case HAL_RX_PKT_TYPE_11AX: + rs->he_flags = 1; + break; + default: + break; + } + reg_value = HAL_RX_GET(rx_msdu_start, RX_MSDU_START_5, RECEPTION_TYPE); + rs->beamformed = (reg_value == HAL_RX_RECEPTION_TYPE_MU_MIMO) ? 1 : 0; + /* TODO: rs->beamformed should be set for SU beamforming also */ } struct hal_rx_ppdu_user_info { @@ -394,6 +403,7 @@ struct hal_rx_ppdu_common_info { struct hal_rx_ppdu_info { struct hal_rx_ppdu_common_info com_info; struct hal_rx_ppdu_user_info user_info[HAL_MAX_UL_MU_USERS]; + struct mon_rx_status rx_status; }; static inline uint32_t @@ -404,9 +414,18 @@ hal_get_rx_status_buf_size(void) { static inline uint8_t* hal_rx_status_get_next_tlv(uint8_t *rx_tlv) { - uint32_t tlv_len; + uint32_t tlv_len, tlv_tag; tlv_len = HAL_RX_GET_USER_TLV32_LEN(rx_tlv); + tlv_tag = HAL_RX_GET_USER_TLV32_TYPE(rx_tlv); + + /* The actual length of PPDU_END is the combined lenght of many PHY + * TLVs that follow. Skip the TLV header and + * rx_rxpcu_classification_overview that follows the header to get to + * next TLV. + */ + if (tlv_tag == WIFIRX_PPDU_END_E) + tlv_len = sizeof(struct rx_rxpcu_classification_overview); return (uint8_t *)(((unsigned long)(rx_tlv + tlv_len + HAL_RX_TLV32_HDR_SIZE + 3)) & (~((unsigned long)3))); @@ -415,7 +434,7 @@ hal_rx_status_get_next_tlv(uint8_t *rx_tlv) { static inline uint32_t hal_rx_status_get_tlv_info(void *rx_tlv, struct hal_rx_ppdu_info *ppdu_info) { - uint32_t tlv_tag, user_id, tlv_len; + uint32_t tlv_tag, user_id, tlv_len, value; tlv_tag = HAL_RX_GET_USER_TLV32_TYPE(rx_tlv); user_id = HAL_RX_GET_USER_TLV32_USERID(rx_tlv); @@ -432,6 +451,10 @@ hal_rx_status_get_tlv_info(void *rx_tlv, struct hal_rx_ppdu_info *ppdu_info) ppdu_info->com_info.ppdu_id = HAL_RX_GET(rx_tlv, RX_PPDU_START_0, PHY_PPDU_ID); + /* TODO: Ensure channel number is set in PHY meta data */ + ppdu_info->rx_status.chan_freq = + HAL_RX_GET(rx_tlv, RX_PPDU_START_1, + SW_PHY_META_DATA); ppdu_info->com_info.ppdu_timestamp = HAL_RX_GET(rx_tlv, RX_PPDU_START_2, PPDU_START_TIMESTAMP); @@ -444,9 +467,16 @@ hal_rx_status_get_tlv_info(void *rx_tlv, struct hal_rx_ppdu_info *ppdu_info) QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, "[%s][%d] ppdu_end_e len=%d\n", __func__, __LINE__, tlv_len); + /* This is followed by sub-TLVs of PPDU_END */ break; case WIFIRXPCU_PPDU_END_INFO_E: + ppdu_info->rx_status.tsft = + HAL_RX_GET(rx_tlv, RXPCU_PPDU_END_INFO_1, + WB_TIMESTAMP_UPPER_32); + ppdu_info->rx_status.tsft = (ppdu_info->rx_status.tsft << 32) | + HAL_RX_GET(rx_tlv, RXPCU_PPDU_END_INFO_0, + WB_TIMESTAMP_LOWER_32); break; case WIFIRX_PPDU_END_USER_STATS_E: @@ -459,8 +489,147 @@ hal_rx_status_get_tlv_info(void *rx_tlv, struct hal_rx_ppdu_info *ppdu_info) return HAL_TLV_STATUS_PPDU_DONE; case WIFIDUMMY_E: - return HAL_TLV_STATUS_DUMMY; + return HAL_TLV_STATUS_PPDU_DONE; + case WIFIPHYRX_HT_SIG_E: + { + uint8_t *ht_sig_info = (uint8_t *)rx_tlv + + HAL_RX_OFFSET(PHYRX_HT_SIG_0, + HT_SIG_INFO_PHYRX_HT_SIG_INFO_DETAILS); + value = HAL_RX_GET(ht_sig_info, HT_SIG_INFO_1, + FEC_CODING); + ppdu_info->rx_status.ldpc = (value == HAL_SU_MU_CODING_LDPC) ? + 1 : 0; + break; + } + case WIFIPHYRX_VHT_SIG_A_E: + { + uint8_t *vht_sig_a_info = (uint8_t *)rx_tlv + + HAL_RX_OFFSET(PHYRX_VHT_SIG_A_0, + VHT_SIG_A_INFO_PHYRX_VHT_SIG_A_INFO_DETAILS); + value = HAL_RX_GET(vht_sig_a_info, VHT_SIG_A_INFO_1, + SU_MU_CODING); + ppdu_info->rx_status.ldpc = (value == HAL_SU_MU_CODING_LDPC) ? + 1 : 0; + break; + } + case WIFIPHYRX_HE_SIG_A_SU_E: + ppdu_info->rx_status.he_sig_A1 = + *((uint32_t *)((uint8_t *)rx_tlv + + HAL_RX_OFFSET(PHYRX_HE_SIG_A_SU_0, + HE_SIG_A_SU_INFO_PHYRX_HE_SIG_A_SU_INFO_DETAILS))); + ppdu_info->rx_status.he_sig_A1 |= + QDF_MON_STATUS_HE_SIG_A1_HE_FORMAT_SU; + /* TODO: Enabling all known bits. Check if this should be + * enabled selectively + */ + ppdu_info->rx_status.he_sig_A1_known = + QDF_MON_STATUS_HE_SIG_A1_SU_KNOWN_ALL; + ppdu_info->rx_status.he_sig_A2 = + *((uint32_t *)((uint8_t *)rx_tlv + + HAL_RX_OFFSET(PHYRX_HE_SIG_A_SU_1, + HE_SIG_A_SU_INFO_PHYRX_HE_SIG_A_SU_INFO_DETAILS))); + ppdu_info->rx_status.he_sig_A2_known = + QDF_MON_STATUS_HE_SIG_A2_SU_KNOWN_ALL; + break; + case WIFIPHYRX_HE_SIG_A_MU_DL_E: + ppdu_info->rx_status.he_sig_A1 = + *((uint32_t *)((uint8_t *)rx_tlv + + HAL_RX_OFFSET(PHYRX_HE_SIG_A_MU_DL_0, + HE_SIG_A_MU_DL_INFO_PHYRX_HE_SIG_A_MU_DL_INFO_DETAILS))); + ppdu_info->rx_status.he_sig_A1 |= + QDF_MON_STATUS_HE_SIG_A1_HE_FORMAT_MU; + ppdu_info->rx_status.he_sig_A1_known = + QDF_MON_STATUS_HE_SIG_A1_MU_KNOWN_ALL; + + ppdu_info->rx_status.he_sig_A2 = + *((uint32_t *)((uint8_t *)rx_tlv + + HAL_RX_OFFSET(PHYRX_HE_SIG_A_MU_DL_1, + HE_SIG_A_MU_DL_INFO_PHYRX_HE_SIG_A_MU_DL_INFO_DETAILS))); + ppdu_info->rx_status.he_sig_A2_known = + QDF_MON_STATUS_HE_SIG_A2_MU_KNOWN_ALL; + break; + case WIFIPHYRX_HE_SIG_B1_MU_E: + { + uint8_t *he_sig_b1_mu_info = (uint8_t *)rx_tlv + + *((uint32_t *)((uint8_t *)rx_tlv + + HAL_RX_OFFSET(PHYRX_HE_SIG_B1_MU_0, + HE_SIG_B1_MU_INFO_PHYRX_HE_SIG_B1_MU_INFO_DETAILS))); + + ppdu_info->rx_status.he_sig_b_common_RU[0] = + HAL_RX_GET(he_sig_b1_mu_info, HE_SIG_B1_MU_INFO_0, + RU_ALLOCATION); + + ppdu_info->rx_status.he_sig_b_common_known = + QDF_MON_STATUS_HE_SIG_B_COMMON_KNOWN_RU0; + /* TODO: Check on the availability of other fields in + * sig_b_common + */ + break; + } + case WIFIPHYRX_HE_SIG_B2_MU_E: + ppdu_info->rx_status.he_sig_b_user = + *((uint32_t *)((uint8_t *)rx_tlv + + HAL_RX_OFFSET(PHYRX_HE_SIG_B2_MU_0, + HE_SIG_B2_MU_INFO_PHYRX_HE_SIG_B2_MU_INFO_DETAILS))); + ppdu_info->rx_status.he_sig_b_user_known = + QDF_MON_STATUS_HE_SIG_B_USER_KNOWN_SIG_B_ALL; + break; + case WIFIPHYRX_HE_SIG_B2_OFDMA_E: + ppdu_info->rx_status.he_sig_b_user = + *((uint32_t *)((uint8_t *)rx_tlv + + HAL_RX_OFFSET(PHYRX_HE_SIG_B2_OFDMA_0, + HE_SIG_B2_OFDMA_INFO_PHYRX_HE_SIG_B2_OFDMA_INFO_DETAILS))); + ppdu_info->rx_status.he_sig_b_user_known = + QDF_MON_STATUS_HE_SIG_B_USER_KNOWN_SIG_B_ALL; + break; + case WIFIPHYRX_RSSI_LEGACY_E: + { + uint8_t *rssi_info_tlv = (uint8_t *)rx_tlv + + HAL_RX_OFFSET(PHYRX_RSSI_LEGACY_3, + RECEIVE_RSSI_INFO_PRE_RSSI_INFO_DETAILS); + + value = HAL_RX_GET(rssi_info_tlv, + RECEIVE_RSSI_INFO_0, RSSI_PRI20_CHAIN0); + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, + "RSSI_PRI20_CHAIN0: %d\n", value); + + value = HAL_RX_GET(rssi_info_tlv, + RECEIVE_RSSI_INFO_0, RSSI_EXT20_CHAIN0); + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, + "RSSI_EXT20_CHAIN0: %d\n", value); + + value = HAL_RX_GET(rssi_info_tlv, + RECEIVE_RSSI_INFO_0, RSSI_EXT40_LOW20_CHAIN0); + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, + "RSSI_EXT40_LOW20_CHAIN0: %d\n", value); + + value = HAL_RX_GET(rssi_info_tlv, + RECEIVE_RSSI_INFO_0, RSSI_EXT40_HIGH20_CHAIN0); + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, + "RSSI_EXT40_HIGH20_CHAIN0: %d\n", value); + + value = HAL_RX_GET(rssi_info_tlv, + RECEIVE_RSSI_INFO_1, RSSI_EXT80_LOW20_CHAIN0); + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, + "RSSI_EXT80_LOW20_CHAIN0: %d\n", value); + + value = HAL_RX_GET(rssi_info_tlv, + RECEIVE_RSSI_INFO_1, RSSI_EXT80_LOW_HIGH20_CHAIN0); + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, + "RSSI_EXT80_LOW_HIGH20_CHAIN0: %d\n", value); + + value = HAL_RX_GET(rssi_info_tlv, + RECEIVE_RSSI_INFO_1, RSSI_EXT80_HIGH_LOW20_CHAIN0); + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, + "RSSI_EXT80_HIGH_LOW20_CHAIN0: %d\n", value); + + value = HAL_RX_GET(rssi_info_tlv, + RECEIVE_RSSI_INFO_1, RSSI_EXT80_HIGH20_CHAIN0); + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, + "RSSI_EXT80_HIGH20_CHAIN0: %d\n", value); + break; + } case 0: return HAL_TLV_STATUS_PPDU_DONE; @@ -468,6 +637,10 @@ hal_rx_status_get_tlv_info(void *rx_tlv, struct hal_rx_ppdu_info *ppdu_info) break; } + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO, + "%s TLV type: %d, TLV len:%d\n", + __func__, tlv_tag, tlv_len); + return HAL_TLV_STATUS_PPDU_NOT_DONE; } diff --git a/hal/wifi3.0/hal_internal.h b/hal/wifi3.0/hal_internal.h index 3df6f3e3746f..3fe719800e8f 100644 --- a/hal/wifi3.0/hal_internal.h +++ b/hal/wifi3.0/hal_internal.h @@ -64,7 +64,18 @@ #include "rx_ppdu_end_user_stats.h" #include "rx_ppdu_end_user_stats_ext.h" #include "rx_mpdu_desc_info.h" +#include "rxpcu_ppdu_end_info.h" +#include "phyrx_he_sig_a_su.h" +#include "phyrx_he_sig_a_mu_dl.h" +#include "phyrx_he_sig_b1_mu.h" +#include "phyrx_he_sig_b2_mu.h" +#include "phyrx_he_sig_b2_ofdma.h" +#include "phyrx_vht_sig_a.h" +#include "phyrx_ht_sig.h" #include "tx_msdu_extension.h" +#include "receive_rssi_info.h" +#include "phyrx_pkt_end.h" +#include "phyrx_rssi_legacy.h" #include "wcss_version.h" #include "pld_common.h" #include "rx_msdu_link.h" diff --git a/hal/wifi3.0/hal_reo.h b/hal/wifi3.0/hal_reo.h index b34f55f27a7f..8986f437949e 100644 --- a/hal/wifi3.0/hal_reo.h +++ b/hal/wifi3.0/hal_reo.h @@ -136,7 +136,8 @@ enum reo_thres_index_reg { enum reo_cmd_exec_status { HAL_REO_CMD_SUCCESS = 0, HAL_REO_CMD_BLOCKED = 1, - HAL_REO_CMD_FAILED = 2 + HAL_REO_CMD_FAILED = 2, + HAL_REO_CMD_RESOURCE_BLOCKED = 3 }; /** diff --git a/hif/inc/hif.h b/hif/inc/hif.h index 2fe3d3373848..c235c53e86f2 100644 --- a/hif/inc/hif.h +++ b/hif/inc/hif.h @@ -122,7 +122,7 @@ enum hif_ic_irq { host2rxdma_monitor_ring3, host2rxdma_monitor_ring2, host2rxdma_monitor_ring1, - reo2ost_exception, + reo2host_exception, wbm2host_rx_release, reo2host_status, reo2host_destination_ring4, @@ -853,12 +853,6 @@ int hif_bus_reset_resume(struct hif_opaque_softc *hif_ctx); void hif_set_attribute(struct hif_opaque_softc *osc, uint8_t hif_attrib); void *hif_get_lro_info(int ctx_id, struct hif_opaque_softc *hif_hdl); -#ifdef WLAN_SUSPEND_RESUME_TEST -typedef void (*hif_fake_resume_callback)(uint32_t val); -void hif_fake_apps_suspend(struct hif_opaque_softc *hif_ctx, - hif_fake_resume_callback callback); -void hif_fake_apps_resume(struct hif_opaque_softc *hif_ctx); -#endif uint32_t hif_register_ext_group_int_handler(struct hif_opaque_softc *hif_ctx, uint32_t numirq, uint32_t irq[], ext_intr_handler handler, diff --git a/hif/inc/hif_unit_test_suspend.h b/hif/inc/hif_unit_test_suspend.h new file mode 100644 index 000000000000..cb036ecabb45 --- /dev/null +++ b/hif/inc/hif_unit_test_suspend.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: Public unit-test related APIs for triggering WoW suspend/resume while + * the application processor is still up. + */ + +#ifndef _HIF_UNIT_TEST_SUSPEND_H_ +#define _HIF_UNIT_TEST_SUSPEND_H_ + +#ifdef WLAN_SUSPEND_RESUME_TEST + +#include "qdf_status.h" +#include "hif.h" + +typedef void (*hif_ut_resume_callback)(void); + +/** + * hif_ut_apps_suspend() - Setup unit-test related suspend state. + * @opaque_scn: The HIF context to operate on + * @callback: The function to call when unit-test resume is triggered + * + * Call after a normal WoW suspend has been completed. + * + * Return: QDF_STATUS + */ +QDF_STATUS hif_ut_apps_suspend(struct hif_opaque_softc *opaque_scn, + hif_ut_resume_callback callback); + +/** + * hif_ut_apps_resume() - Cleanup unit-test related suspend state. + * @opaque_scn: The HIF context to operate on + * + * Call before doing a normal WoW resume if suspend was initiated via + * unit-test suspend. + * + * Return: QDF_STATUS + */ +QDF_STATUS hif_ut_apps_resume(struct hif_opaque_softc *opaque_scn); + +#endif /* WLAN_SUSPEND_RESUME_TEST */ + +#endif /* _HIF_UNIT_TEST_SUSPEND_H_ */ diff --git a/hif/src/ce/ce_assignment.h b/hif/src/ce/ce_assignment.h index a32a7cce3c38..7dfbe3caa5e9 100644 --- a/hif/src/ce/ce_assignment.h +++ b/hif/src/ce/ce_assignment.h @@ -600,21 +600,20 @@ static struct CE_pipe_config target_ce_config_wlan_qca8074[] = { (CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR), 0,}, /* NB: 50% of src nentries, since tx has 2 frags */ /* ipa_uc->target */ - { /* CE5 */ 5, PIPEDIR_OUT, 1024, 64, - (CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR), 0,}, + { /* CE5 */ 5, PIPEDIR_INOUT_H2H, 0, 0, 0, 0,}, /* Reserved for target autonomous HIF_memcpy */ - { /* CE6 */ 6, PIPEDIR_INOUT, 32, 16384, CE_ATTR_FLAGS, 0,}, + { /* CE6 */ 6, PIPEDIR_INOUT, 32, 65535, 64, 0,}, /* CE7 used only by Host */ - { /* CE7 */ 7, PIPEDIR_INOUT_H2H, 0, 0, - (CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR), 0,}, + { /* CE7 */ 7, PIPEDIR_OUT, 32, 2048, + 8192, 0,}, /* CE8 used only by IPA */ - { /* CE8 */ 8, PIPEDIR_IN, 32, 2048, CE_ATTR_FLAGS, 0,}, + { /* CE8 */ 8, PIPEDIR_INOUT, 32, 65535, 112, 0,}, /* CE9 target->host HTT */ - { /* CE9 */ 9, PIPEDIR_IN, 32, 2048, CE_ATTR_FLAGS, 0,}, + { /* CE9 */ 9, PIPEDIR_OUT, 32, 2048, 8192, 0,}, /* CE10 target->host HTT */ - { /* CE10 */ 10, PIPEDIR_IN, 32, 2048, CE_ATTR_FLAGS, 0,}, + { /* CE10 */ 10, PIPEDIR_INOUT_H2H, 0, 0, 0, 0,}, /* Target -> host PKTLOG */ - { /* CE11 */ 11, PIPEDIR_IN, 32, 2048, CE_ATTR_FLAGS, 0,}, + { /* CE11 */ 11, PIPEDIR_IN, 32, 2048, 48, 0,}, }; static struct CE_attr host_ce_config_wlan_qca8074_pci[] = { diff --git a/hif/src/ce/ce_main.c b/hif/src/ce/ce_main.c index d91d991d126c..e713f0deaa9e 100644 --- a/hif/src/ce/ce_main.c +++ b/hif/src/ce/ce_main.c @@ -404,6 +404,29 @@ static struct service_to_pipe target_service_to_ce_map_wlan[] = { /* PIPEDIR_OUT = HOST to Target */ /* PIPEDIR_IN = TARGET to HOST */ +static struct service_to_pipe target_service_to_ce_map_qca8074[] = { + { WMI_DATA_VO_SVC, PIPEDIR_OUT, 3, }, + { WMI_DATA_VO_SVC, PIPEDIR_IN, 2, }, + { WMI_DATA_BK_SVC, PIPEDIR_OUT, 3, }, + { WMI_DATA_BK_SVC, PIPEDIR_IN, 2, }, + { WMI_DATA_BE_SVC, PIPEDIR_OUT, 3, }, + { WMI_DATA_BE_SVC, PIPEDIR_IN, 2, }, + { WMI_DATA_VI_SVC, PIPEDIR_OUT, 3, }, + { WMI_DATA_VI_SVC, PIPEDIR_IN, 2, }, + { WMI_CONTROL_SVC, PIPEDIR_OUT, 3, }, + { WMI_CONTROL_SVC, PIPEDIR_IN, 2, }, + { WMI_CONTROL_SVC_WMAC1, PIPEDIR_OUT, 7}, + { WMI_CONTROL_SVC_WMAC1, PIPEDIR_IN, 2}, + { HTC_CTRL_RSVD_SVC, PIPEDIR_OUT, 0, }, + { HTC_CTRL_RSVD_SVC, PIPEDIR_IN, 1, }, + { HTC_RAW_STREAMS_SVC, PIPEDIR_OUT, 0}, + { HTC_RAW_STREAMS_SVC, PIPEDIR_IN, 1 }, + { HTT_DATA_MSG_SVC, PIPEDIR_OUT, 4, }, + { HTT_DATA_MSG_SVC, PIPEDIR_IN, 1, }, + /* (Additions here) */ + { 0, 0, 0, }, +}; + static struct service_to_pipe target_service_to_ce_map_qca6290[] = { { WMI_DATA_VO_SVC, PIPEDIR_OUT, 3, }, { WMI_DATA_VO_SVC, PIPEDIR_IN , 2, }, @@ -579,6 +602,11 @@ static void hif_select_service_to_pipe_map(struct hif_softc *scn, *sz_tgt_svc_map_to_use = sizeof(target_service_to_ce_map_qca6290); break; + case TARGET_TYPE_QCA8074: + *tgt_svc_map_to_use = target_service_to_ce_map_qca8074; + *sz_tgt_svc_map_to_use = + sizeof(target_service_to_ce_map_qca8074); + break; } } } @@ -2415,16 +2443,6 @@ static inline void hif_post_static_buf_to_target(struct hif_softc *scn) } #endif -#ifdef WLAN_SUSPEND_RESUME_TEST -static void hif_fake_apps_init_ctx(struct hif_softc *scn) -{ - INIT_WORK(&scn->fake_apps_ctx.resume_work, - hif_fake_apps_resume_work); -} -#else -static inline void hif_fake_apps_init_ctx(struct hif_softc *scn) {} -#endif - /** * hif_config_ce() - configure copy engines * @scn: hif context @@ -2511,7 +2529,6 @@ int hif_config_ce(struct hif_softc *scn) HIF_DBG("%s: ce_init done", __func__); init_tasklet_workers(hif_hdl); - hif_fake_apps_init_ctx(scn); HIF_DBG("%s: X, ret = %d", __func__, rv); diff --git a/hif/src/ce/ce_service.c b/hif/src/ce/ce_service.c index 86cdcc8909d0..e511af49681b 100644 --- a/hif/src/ce/ce_service.c +++ b/hif/src/ce/ce_service.c @@ -2106,12 +2106,15 @@ more_watermarks: more_comp_cnt++ < CE_TXRX_COMP_CHECK_THRESHOLD) { goto more_completions; } else { - HIF_ERROR( - "%s:Potential infinite loop detected during Rx processing nentries_mask:0x%x sw read_idx:0x%x hw read_idx:0x%x", - __func__, CE_state->dest_ring->nentries_mask, - CE_state->dest_ring->sw_index, - CE_DEST_RING_READ_IDX_GET(scn, + if (!ce_srng_based(scn)) { + HIF_ERROR( + "%s:Potential infinite loop detected during Rx processing nentries_mask:0x%x sw read_idx:0x%x hw read_idx:0x%x", + __func__, + CE_state->dest_ring->nentries_mask, + CE_state->dest_ring->sw_index, + CE_DEST_RING_READ_IDX_GET(scn, CE_state->ctrl_addr)); + } } } @@ -2122,12 +2125,15 @@ more_watermarks: more_snd_comp_cnt++ < CE_TXRX_COMP_CHECK_THRESHOLD) { goto more_completions; } else { - HIF_ERROR( - "%s:Potential infinite loop detected during send completion nentries_mask:0x%x sw read_idx:0x%x hw read_idx:0x%x", - __func__, CE_state->src_ring->nentries_mask, - CE_state->src_ring->sw_index, - CE_SRC_RING_READ_IDX_GET(scn, + if (!ce_srng_based(scn)) { + HIF_ERROR( + "%s:Potential infinite loop detected during send completion nentries_mask:0x%x sw read_idx:0x%x hw read_idx:0x%x", + __func__, + CE_state->src_ring->nentries_mask, + CE_state->src_ring->sw_index, + CE_SRC_RING_READ_IDX_GET(scn, CE_state->ctrl_addr)); + } } } diff --git a/hif/src/ce/ce_tasklet.c b/hif/src/ce/ce_tasklet.c index 8f938742c3bc..73e0a144432b 100644 --- a/hif/src/ce/ce_tasklet.c +++ b/hif/src/ce/ce_tasklet.c @@ -270,73 +270,19 @@ int hif_drain_tasklets(struct hif_softc *scn) #ifdef WLAN_SUSPEND_RESUME_TEST /** - * hif_fake_apps_resume_work() - Work handler for fake apps resume callback - * @work: The work struct being passed from the linux kernel + * hif_interrupt_is_ut_resume(): Tests if an irq on the given copy engine should + * trigger a unit-test resume. + * @scn: The HIF context to operate on + * @ce_id: The copy engine Id from the originating interrupt * - * Return: none + * Return: true if the raised irq should trigger a unit-test resume */ -void hif_fake_apps_resume_work(struct work_struct *work) +static bool hif_interrupt_is_ut_resume(struct hif_softc *scn, int ce_id) { - struct fake_apps_context *ctx = - container_of(work, struct fake_apps_context, resume_work); - - QDF_BUG(ctx->resume_callback); - ctx->resume_callback(0); - ctx->resume_callback = NULL; -} - -/** - * hif_fake_apps_suspend(): Setup unit-test related suspend state. Call after - * a normal WoW suspend has been completed. - * @hif_ctx: The HIF context to operate on - * @callback: The function to call when fake apps resume is triggered - * - * Set the fake suspend flag such that hif knows that it will need - * to fake the apps resume process using hdd_trigger_fake_apps_resume - * - * Return: none - */ -void hif_fake_apps_suspend(struct hif_opaque_softc *hif_ctx, - hif_fake_resume_callback callback) -{ - struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); - - scn->fake_apps_ctx.resume_callback = callback; - set_bit(HIF_FA_SUSPENDED_BIT, &scn->fake_apps_ctx.state); -} - -/** - * hif_fake_apps_resume(): Cleanup unit-test related suspend state. Call before - * doing a normal WoW resume if suspend was initiated via fake apps - * suspend. - * @hif_ctx: The HIF context to operate on - * - * Return: none - */ -void hif_fake_apps_resume(struct hif_opaque_softc *hif_ctx) -{ - struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); - - clear_bit(HIF_FA_SUSPENDED_BIT, &scn->fake_apps_ctx.state); - scn->fake_apps_ctx.resume_callback = NULL; -} - -/** - * hif_interrupt_is_fake_apps_resume(): Determines if the raised irq should - * trigger a fake apps resume. - * @hif_ctx: The HIF context to operate on - * @ce_id: The copy engine Id from the originating interrupt - * - * Return: true if the raised irq should trigger a fake apps resume - */ -static bool hif_interrupt_is_fake_apps_resume(struct hif_opaque_softc *hif_ctx, - int ce_id) -{ - struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); int errno; uint8_t wake_ce_id; - if (!test_bit(HIF_FA_SUSPENDED_BIT, &scn->fake_apps_ctx.state)) + if (!hif_is_ut_suspended(scn)) return false; /* ensure passed ce_id matches wake ce_id */ @@ -348,39 +294,13 @@ static bool hif_interrupt_is_fake_apps_resume(struct hif_opaque_softc *hif_ctx, return ce_id == wake_ce_id; } - -/** - * hif_trigger_fake_apps_resume(): Trigger a fake apps resume by scheduling the - * previously registered callback for execution - * @hif_ctx: The HIF context to operate on - * - * Return: None - */ -static void hif_trigger_fake_apps_resume(struct hif_opaque_softc *hif_ctx) -{ - struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); - - if (!test_and_clear_bit(HIF_FA_SUSPENDED_BIT, - &scn->fake_apps_ctx.state)) - return; - - schedule_work(&scn->fake_apps_ctx.resume_work); -} - #else - static inline bool -hif_interrupt_is_fake_apps_resume(struct hif_opaque_softc *hif_ctx, int ce_id) +hif_interrupt_is_ut_resume(struct hif_softc *scn, int ce_id) { return false; } - -static inline void -hif_trigger_fake_apps_resume(struct hif_opaque_softc *hif_ctx) -{ -} - -#endif /* End of WLAN_SUSPEND_RESUME_TEST */ +#endif /* WLAN_SUSPEND_RESUME_TEST */ /** * hif_snoc_interrupt_handler() - hif_snoc_interrupt_handler @@ -482,8 +402,8 @@ irqreturn_t ce_dispatch_interrupt(int ce_id, hif_record_ce_desc_event(scn, ce_id, HIF_IRQ_EVENT, NULL, NULL, 0); hif_ce_increment_interrupt_count(hif_ce_state, ce_id); - if (unlikely(hif_interrupt_is_fake_apps_resume(hif_hdl, ce_id))) { - hif_trigger_fake_apps_resume(hif_hdl); + if (unlikely(hif_interrupt_is_ut_resume(scn, ce_id))) { + hif_ut_fw_resume(scn); hif_irq_enable(scn, ce_id); return IRQ_HANDLED; } diff --git a/hif/src/hif_main.c b/hif/src/hif_main.c index f700572b0553..b19ff1517555 100644 --- a/hif/src/hif_main.c +++ b/hif/src/hif_main.c @@ -50,6 +50,7 @@ #include "hal_api.h" #endif #include "hif_napi.h" +#include "hif_unit_test_suspend_i.h" void hif_dump(struct hif_opaque_softc *hif_ctx, uint8_t cmd_id, bool start) { @@ -534,6 +535,8 @@ QDF_STATUS hif_enable(struct hif_opaque_softc *hif_ctx, struct device *dev, return status; } + hif_ut_suspend_init(scn); + /* * Flag to avoid potential unallocated memory access from MSI * interrupt handler which could get scheduled as soon as MSI diff --git a/hif/src/hif_main.h b/hif/src/hif_main.h index 6c05fdc9d2ae..78f07c0cc639 100644 --- a/hif/src/hif_main.h +++ b/hif/src/hif_main.h @@ -47,6 +47,7 @@ #include "cepci.h" #include "hif.h" #include "multibus.h" +#include "hif_unit_test_suspend_i.h" #define HIF_MIN_SLEEP_INACTIVITY_TIME_MS 50 #define HIF_SLEEP_INACTIVITY_TIMER_PERIOD_MS 60 @@ -118,20 +119,6 @@ struct hif_ce_stats { int ce_ring_delta_fail_count; }; -#ifdef WLAN_SUSPEND_RESUME_TEST -struct fake_apps_context { - unsigned long state; - hif_fake_resume_callback resume_callback; - struct work_struct resume_work; -}; - -enum hif_fake_apps_state_bits { - HIF_FA_SUSPENDED_BIT = 0 -}; - -void hif_fake_apps_resume_work(struct work_struct *work); -#endif /* WLAN_SUSPEND_RESUME_TEST */ - struct hif_softc { struct hif_opaque_softc osc; struct hif_config_info hif_config; @@ -178,9 +165,7 @@ struct hif_softc { uint32_t nss_wifi_ol_mode; #endif void *hal_soc; -#ifdef WLAN_SUSPEND_RESUME_TEST - struct fake_apps_context fake_apps_ctx; -#endif /* WLAN_SUSPEND_RESUME_TEST */ + struct hif_ut_suspend_context ut_suspend_ctx; uint32_t hif_attribute; }; diff --git a/hif/src/hif_unit_test_suspend.c b/hif/src/hif_unit_test_suspend.c new file mode 100644 index 000000000000..938648c325de --- /dev/null +++ b/hif/src/hif_unit_test_suspend.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "qdf_status.h" +#include "hif_main.h" +#include "hif_unit_test_suspend.h" +#include "hif_unit_test_suspend_i.h" + +enum hif_ut_suspend_state_bits { + UT_SUSPENDED_BIT = 0 +}; + +/** + * hif_ut_fw_resume_work() - Work handler for firmware-triggered resume + * @work: The work struct being passed from the linux kernel + * + * Return: None + */ +static void hif_ut_fw_resume_work(struct work_struct *work) +{ + struct hif_ut_suspend_context *ctx = + container_of(work, struct hif_ut_suspend_context, resume_work); + + QDF_BUG(ctx); + if (!ctx) + return; + + QDF_BUG(ctx->resume_callback); + if (!ctx->resume_callback) + return; + + ctx->resume_callback(); + ctx->resume_callback = NULL; +} + +void hif_ut_suspend_init(struct hif_softc *scn) +{ + INIT_WORK(&scn->ut_suspend_ctx.resume_work, hif_ut_fw_resume_work); +} + +bool hif_is_ut_suspended(struct hif_softc *scn) +{ + QDF_BUG(scn); + if (!scn) + return false; + + return test_bit(UT_SUSPENDED_BIT, &scn->ut_suspend_ctx.state); +} + +QDF_STATUS hif_ut_apps_suspend(struct hif_opaque_softc *opaque_scn, + hif_ut_resume_callback callback) +{ + struct hif_softc *scn = HIF_GET_SOFTC(opaque_scn); + + QDF_BUG(scn); + if (!scn) + return QDF_STATUS_E_INVAL; + + QDF_BUG(callback); + if (!callback) + return QDF_STATUS_E_INVAL; + + if (test_and_set_bit(UT_SUSPENDED_BIT, &scn->ut_suspend_ctx.state)) + return QDF_STATUS_E_INVAL; + + scn->ut_suspend_ctx.resume_callback = callback; + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS hif_ut_apps_resume(struct hif_opaque_softc *opaque_scn) +{ + struct hif_softc *scn = HIF_GET_SOFTC(opaque_scn); + + QDF_BUG(scn); + if (!scn) + return QDF_STATUS_E_INVAL; + + if (!test_and_clear_bit(UT_SUSPENDED_BIT, &scn->ut_suspend_ctx.state)) + return QDF_STATUS_E_INVAL; + + scn->ut_suspend_ctx.resume_callback = NULL; + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS hif_ut_fw_resume(struct hif_softc *scn) +{ + QDF_BUG(scn); + if (!scn) + return QDF_STATUS_E_INVAL; + + if (!test_and_clear_bit(UT_SUSPENDED_BIT, &scn->ut_suspend_ctx.state)) + return QDF_STATUS_E_INVAL; + + schedule_work(&scn->ut_suspend_ctx.resume_work); + + return QDF_STATUS_SUCCESS; +} diff --git a/hif/src/hif_unit_test_suspend_i.h b/hif/src/hif_unit_test_suspend_i.h new file mode 100644 index 000000000000..dedb1e51cc92 --- /dev/null +++ b/hif/src/hif_unit_test_suspend_i.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: HIF internal unit-test related APIs for triggering WoW suspend/resume + * while the application processor is still up. + */ + +#ifndef _HIF_UNIT_TEST_SUSPEND_I_H_ +#define _HIF_UNIT_TEST_SUSPEND_I_H_ + +#include "qdf_status.h" +#include "hif_main.h" +#include "hif_unit_test_suspend.h" + +#ifdef WLAN_SUSPEND_RESUME_TEST + +struct hif_ut_suspend_context { + unsigned long state; + hif_ut_resume_callback resume_callback; + struct work_struct resume_work; +}; + +/** + * hif_ut_suspend_init() - Initialize the unit-test suspend context + * @scn: the hif context to initialize + * + * Return: None + */ +void hif_ut_suspend_init(struct hif_softc *scn); + +/** + * hif_is_ut_suspended() - Tests if the given hif context is unit-test suspended + * @scn: The HIF context to check + * + * Return: true, if unit-test suspended, otherwise false + */ +bool hif_is_ut_suspended(struct hif_softc *scn); + +/** + * hif_ut_fw_resume() - Initiate a firmware triggered unit-test resume + * @scn: The HIF context to operate on + * + * This schedules the callback previously registered via a call to + * hif_ut_apps_suspend for execution. + * + * Return: QDF_STATUS + */ +QDF_STATUS hif_ut_fw_resume(struct hif_softc *scn); + +#else /* WLAN_SUSPEND_RESUME_TEST */ + +struct hif_ut_suspend_context {}; + +static inline void hif_ut_suspend_init(struct hif_softc *scn) {} + +static inline bool hif_is_ut_suspended(struct hif_softc *scn) +{ + return false; +} + +static inline QDF_STATUS hif_ut_fw_resume(struct hif_softc *scn) +{ + return QDF_STATUS_SUCCESS; +} + +#endif /* WLAN_SUSPEND_RESUME_TEST */ + +#endif /* _HIF_UNIT_TEST_SUSPEND_I_H_ */ diff --git a/hif/src/snoc/if_ahb.c b/hif/src/snoc/if_ahb.c index a527781f6196..fad636fc07a3 100644 --- a/hif/src/snoc/if_ahb.c +++ b/hif/src/snoc/if_ahb.c @@ -301,7 +301,8 @@ int hif_ahb_configure_grp_irq(struct hif_softc *scn) ic_irqnum[hif_ext_group->irq[j]] = irq; ret = request_irq(irq, hif_ext_group_ahb_interrupt_handler, - IRQF_TRIGGER_RISING, "wlan_ahb", + IRQF_TRIGGER_RISING, + ic_irqname[hif_ext_group->irq[j]], hif_ext_group); if (ret) { dev_err(&pdev->dev, diff --git a/os_if/linux/scan/inc/wlan_cfg80211_scan.h b/os_if/linux/scan/inc/wlan_cfg80211_scan.h index b455b87cf3b6..99285eba42c6 100644 --- a/os_if/linux/scan/inc/wlan_cfg80211_scan.h +++ b/os_if/linux/scan/inc/wlan_cfg80211_scan.h @@ -76,11 +76,13 @@ typedef struct { /** * struct osif_scan_pdev - OS scan private strcutre * scan_req_q: Scan request queue + * scan_req_q_lock: Protect scan request queue * req_id: Scan request Id * runtime_pm_lock: Runtime suspend lock */ struct osif_scan_pdev{ qdf_list_t scan_req_q; + qdf_mutex_t scan_req_q_lock; wlan_scan_requester req_id; qdf_runtime_lock_t runtime_pm_lock; }; diff --git a/os_if/linux/scan/src/wlan_cfg80211_scan.c b/os_if/linux/scan/src/wlan_cfg80211_scan.c index 9381ef7b516d..52ddd5ee9226 100644 --- a/os_if/linux/scan/src/wlan_cfg80211_scan.c +++ b/os_if/linux/scan/src/wlan_cfg80211_scan.c @@ -458,9 +458,10 @@ static int wlan_scan_request_enqueue(struct wlan_objmgr_pdev *pdev, scan_req->source = source; scan_req->scan_id = scan_id; + qdf_mutex_acquire(&osif_scan->scan_req_q_lock); status = qdf_list_insert_back(&osif_scan->scan_req_q, &scan_req->node); - + qdf_mutex_release(&osif_scan->scan_req_q_lock); if (QDF_STATUS_SUCCESS != status) { cfg80211_err("Failed to enqueue Scan Req"); qdf_mem_free(scan_req); @@ -509,8 +510,10 @@ static QDF_STATUS wlan_scan_request_dequeue( return QDF_STATUS_E_FAILURE; } + qdf_mutex_acquire(&scan_priv->scan_req_q_lock); if (QDF_STATUS_SUCCESS != qdf_list_peek_front(&scan_priv->scan_req_q, &next_node)) { + qdf_mutex_release(&scan_priv->scan_req_q_lock); cfg80211_err("Failed to remove Scan Req from queue"); return QDF_STATUS_E_FAILURE; } @@ -526,11 +529,13 @@ static QDF_STATUS wlan_scan_request_dequeue( *req = scan_req->scan_request; *source = scan_req->source; qdf_mem_free(scan_req); + qdf_mutex_release(&scan_priv->scan_req_q_lock); cfg80211_info("removed Scan id: %d, req = %p, pending scans %d", scan_id, req, qdf_list_size(&scan_priv->scan_req_q)); return QDF_STATUS_SUCCESS; } else { + qdf_mutex_release(&scan_priv->scan_req_q_lock); cfg80211_err("Failed to remove node scan id %d, pending scans %d", scan_id, qdf_list_size(&scan_priv->scan_req_q)); @@ -539,7 +544,7 @@ static QDF_STATUS wlan_scan_request_dequeue( } } while (QDF_STATUS_SUCCESS == qdf_list_peek_next(&scan_priv->scan_req_q, node, &next_node)); - + qdf_mutex_release(&scan_priv->scan_req_q_lock); cfg80211_err("Failed to find scan id %d", scan_id); return status; @@ -727,6 +732,26 @@ static void wlan_cfg80211_scan_done_callback( goto allow_suspend; } + if (req->wdev == NULL) { + cfg80211_err("wirless dev is NULL,Drop scan event Id: %d", + scan_id); + goto allow_suspend; + } + + if (req->wdev->netdev == NULL) { + cfg80211_err("net dev is NULL,Drop scan event Id: %d", + scan_id); + goto allow_suspend; + } + + /* Make sure vdev is active */ + status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_OSIF_ID); + if (QDF_IS_STATUS_ERROR(status)) { + cfg80211_err("Failed to get vdev reference: scan Id: %d", + scan_id); + goto allow_suspend; + } + /* * Scan can be triggred from NL or vendor scan * - If scan is triggered from NL then cfg80211 scan done should be @@ -739,6 +764,7 @@ static void wlan_cfg80211_scan_done_callback( else wlan_vendor_scan_callback(req, aborted); + wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_ID); allow_suspend: osif_priv = wlan_pdev_get_ospriv(pdev); if (qdf_list_empty(&osif_priv->osif_scan->scan_req_q)) @@ -770,6 +796,7 @@ QDF_STATUS wlan_cfg80211_scan_priv_init(struct wlan_objmgr_pdev *pdev) /* Initialize the scan request queue */ osif_priv->osif_scan = scan_priv; qdf_list_create(&scan_priv->scan_req_q, WLAN_MAX_SCAN_COUNT); + qdf_mutex_create(&scan_priv->scan_req_q_lock); scan_priv->req_id = req_id; scan_priv->runtime_pm_lock = qdf_runtime_lock_init("scan"); @@ -791,6 +818,7 @@ QDF_STATUS wlan_cfg80211_scan_priv_deinit(struct wlan_objmgr_pdev *pdev) osif_priv->osif_scan = NULL; ucfg_scan_unregister_requester(psoc, scan_priv->req_id); qdf_list_destroy(&scan_priv->scan_req_q); + qdf_mutex_destroy(&scan_priv->scan_req_q_lock); qdf_runtime_lock_deinit(scan_priv->runtime_pm_lock); scan_priv->runtime_pm_lock = NULL; qdf_mem_free(scan_priv); @@ -818,15 +846,16 @@ void wlan_cfg80211_cleanup_scan_queue(struct wlan_objmgr_pdev *pdev) wlan_pdev_obj_unlock(pdev); scan_priv = osif_priv->osif_scan; - + qdf_mutex_acquire(&scan_priv->scan_req_q_lock); while (!qdf_list_empty(&scan_priv->scan_req_q)) { if (QDF_STATUS_SUCCESS != qdf_list_remove_front(&scan_priv->scan_req_q, &node)) { + qdf_mutex_release(&scan_priv->scan_req_q_lock); cfg80211_err("Failed to remove scan request"); return; } - + qdf_mutex_release(&scan_priv->scan_req_q_lock); scan_req = container_of(node, struct scan_req, node); req = scan_req->scan_request; source = scan_req->source; @@ -835,7 +864,9 @@ void wlan_cfg80211_cleanup_scan_queue(struct wlan_objmgr_pdev *pdev) else wlan_vendor_scan_callback(req, aborted); qdf_mem_free(scan_req); + qdf_mutex_acquire(&scan_priv->scan_req_q_lock); } + qdf_mutex_release(&scan_priv->scan_req_q_lock); return; } @@ -1109,7 +1140,9 @@ static int wlan_get_scanid(struct wlan_objmgr_pdev *pdev, return ret; } scan_priv = osif_ctx->osif_scan; + qdf_mutex_acquire(&scan_priv->scan_req_q_lock); if (qdf_list_empty(&scan_priv->scan_req_q)) { + qdf_mutex_release(&scan_priv->scan_req_q_lock); cfg80211_err("Failed to retrieve scan id"); return ret; } @@ -1117,6 +1150,7 @@ static int wlan_get_scanid(struct wlan_objmgr_pdev *pdev, if (QDF_STATUS_SUCCESS != qdf_list_peek_front(&scan_priv->scan_req_q, &ptr_node)) { + qdf_mutex_release(&scan_priv->scan_req_q_lock); return ret; } @@ -1133,6 +1167,8 @@ static int wlan_get_scanid(struct wlan_objmgr_pdev *pdev, qdf_list_peek_next(&scan_priv->scan_req_q, node, &ptr_node)); + qdf_mutex_release(&scan_priv->scan_req_q_lock); + return ret; } diff --git a/pmo/dispatcher/src/wlan_pmo_obj_mgmt_api.c b/pmo/dispatcher/src/wlan_pmo_obj_mgmt_api.c index ada0d391d960..7493d5233d68 100644 --- a/pmo/dispatcher/src/wlan_pmo_obj_mgmt_api.c +++ b/pmo/dispatcher/src/wlan_pmo_obj_mgmt_api.c @@ -452,112 +452,114 @@ out: } QDF_STATUS pmo_suspend_all_components(struct wlan_objmgr_psoc *psoc, - enum qdf_suspend_type suspend_type) + enum qdf_suspend_type suspend_type) { - pmo_psoc_suspend_handler handler; - uint8_t index = 0; - QDF_STATUS suspend_status = QDF_STATUS_SUCCESS; - QDF_STATUS resume_status = QDF_STATUS_SUCCESS; - void *arg; + QDF_STATUS status = QDF_STATUS_SUCCESS; + QDF_STATUS resume_status; struct wlan_pmo_ctx *pmo_ctx; + uint8_t i; + pmo_psoc_suspend_handler handler; + void *arg; PMO_ENTER(); + pmo_ctx = pmo_get_context(); if (!pmo_ctx) { - QDF_ASSERT(0); pmo_err("unable to get pmo ctx"); - suspend_status = QDF_STATUS_E_FAILURE; - goto out; + QDF_ASSERT(0); + status = QDF_STATUS_E_FAILURE; + goto exit_with_status; } - /* call all component's Suspend Handler */ - while (index < WLAN_UMAC_MAX_COMPONENTS) { + /* call each component's suspend handler */ + for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) { qdf_spin_lock_bh(&pmo_ctx->lock); - if (pmo_ctx->pmo_suspend_handler[index]) { - handler = pmo_ctx->pmo_suspend_handler[index]; - arg = pmo_ctx->pmo_suspend_handler_arg[index]; - qdf_spin_unlock_bh(&pmo_ctx->lock); - suspend_status = handler(psoc, arg); - if (suspend_status != QDF_STATUS_SUCCESS) { - pmo_err("component id: %d failed to suspend status: %d", - index, suspend_status); - QDF_ASSERT(0); - /* break, no need to suspend next components */ - break; - } - } else { - qdf_spin_unlock_bh(&pmo_ctx->lock); + handler = pmo_ctx->pmo_suspend_handler[i]; + arg = pmo_ctx->pmo_suspend_handler_arg[i]; + qdf_spin_unlock_bh(&pmo_ctx->lock); + + if (!handler) + continue; + + status = handler(psoc, arg); + if (QDF_IS_STATUS_ERROR(status)) { + pmo_err("component %d failed to suspend; status: %d", + i, status); + QDF_ASSERT(0); + goto suspend_recovery; } - index++; } - /* resume the succefully suspended components */ - if (suspend_status != QDF_STATUS_SUCCESS) { - while (index >= 0) { - /* - * index points to id which refuse suspend - * so go to previous id. - */ - index--; - qdf_spin_lock_bh(&pmo_ctx->lock); - handler = pmo_ctx->pmo_resume_handler[index]; - arg = pmo_ctx->pmo_resume_handler_arg[index]; - qdf_spin_unlock_bh(&pmo_ctx->lock); - /* TODO: if resume got failed for some component ?? */ - resume_status = handler(psoc, arg); - if (resume_status != QDF_STATUS_SUCCESS) { - pmo_err("Component id: %d failed to resume status: %d", - index, resume_status); - QDF_ASSERT(0); - } + goto exit_with_status; + +suspend_recovery: + /* resume, starting with the last successfully suspended component */ + for (i -= 1; i >= 0; i--) { + qdf_spin_lock_bh(&pmo_ctx->lock); + handler = pmo_ctx->pmo_resume_handler[i]; + arg = pmo_ctx->pmo_resume_handler_arg[i]; + qdf_spin_unlock_bh(&pmo_ctx->lock); + + if (!handler) + continue; + + resume_status = handler(psoc, arg); + if (QDF_IS_STATUS_ERROR(resume_status)) { + pmo_fatal("Non-recoverable failure occurred!"); + pmo_fatal("component %d failed to resume; status: %d", + i, resume_status); + QDF_BUG(0); } } -out: + +exit_with_status: PMO_EXIT(); - return suspend_status; + return status; } QDF_STATUS pmo_resume_all_components(struct wlan_objmgr_psoc *psoc, - enum qdf_suspend_type suspend_type) + enum qdf_suspend_type suspend_type) { - uint8_t index = 0; - QDF_STATUS component_ret = QDF_STATUS_SUCCESS; - void *arg; + QDF_STATUS status = QDF_STATUS_SUCCESS; struct wlan_pmo_ctx *pmo_ctx; + uint8_t i; pmo_psoc_suspend_handler handler; + void *arg; PMO_ENTER(); + pmo_ctx = pmo_get_context(); if (!pmo_ctx) { - QDF_ASSERT(0); pmo_err("unable to get pmo ctx"); - component_ret = QDF_STATUS_E_FAILURE; - goto out; + QDF_ASSERT(0); + status = QDF_STATUS_E_FAILURE; + goto exit_with_status; } - /* call all components Resume Handler */ - while (index < WLAN_UMAC_MAX_COMPONENTS) { + /* call each component's resume handler */ + for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) { qdf_spin_lock_bh(&pmo_ctx->lock); - if (pmo_ctx->pmo_resume_handler[index]) { - handler = pmo_ctx->pmo_resume_handler[index]; - arg = pmo_ctx->pmo_resume_handler_arg[index]; - qdf_spin_unlock_bh(&pmo_ctx->lock); - component_ret = handler(psoc, arg); - if (component_ret != QDF_STATUS_SUCCESS) { - pmo_err("Component id: %d failed to resume status: %d", - index, component_ret); - QDF_ASSERT(0); - } - } else { - qdf_spin_unlock_bh(&pmo_ctx->lock); + handler = pmo_ctx->pmo_resume_handler[i]; + arg = pmo_ctx->pmo_resume_handler_arg[i]; + qdf_spin_unlock_bh(&pmo_ctx->lock); + + if (!handler) + continue; + + status = handler(psoc, arg); + if (QDF_IS_STATUS_ERROR(status)) { + pmo_fatal("Non-recoverable failure occurred!"); + pmo_fatal("component %d failed to resume; status: %d", + i, status); + QDF_BUG(0); } - index++; -} -out: + } + +exit_with_status: PMO_EXIT(); - return component_ret; + return status; } QDF_STATUS pmo_register_pause_bitmap_notifier(struct wlan_objmgr_psoc *psoc, diff --git a/qdf/inc/qdf_nbuf.h b/qdf/inc/qdf_nbuf.h index d78b30a6b436..cef0e0f14b8b 100644 --- a/qdf/inc/qdf_nbuf.h +++ b/qdf/inc/qdf_nbuf.h @@ -178,6 +178,18 @@ struct mon_rx_status { uint8_t he_sig_b_common_RU[4]; }; +/* Masks for HE SIG known fields in mon_rx_status structure */ +#define QDF_MON_STATUS_HE_SIG_A1_SU_KNOWN_ALL 0x000007ff +#define QDF_MON_STATUS_HE_SIG_A1_MU_KNOWN_ALL 0x000003ff +#define QDF_MON_STATUS_HE_SIG_A2_SU_KNOWN_ALL 0x00000ffd +#define QDF_MON_STATUS_HE_SIG_A2_MU_KNOWN_ALL 0x00000ffd +#define QDF_MON_STATUS_HE_SIG_B_COMMON_KNOWN_RU0 0x00000001 +#define QDF_MON_STATUS_HE_SIG_B_USER_KNOWN_SIG_B_ALL 0x00fe0000 +#define QDF_MON_STATUS_HE_SIG_A1_HE_FORMAT_SU 0x00000000 +#define QDF_MON_STATUS_HE_SIG_A1_HE_FORMAT_EXT_SU 0x40000000 +#define QDF_MON_STATUS_HE_SIG_A1_HE_FORMAT_MU 0x80000000 +#define QDF_MON_STATUS_HE_SIG_A1_HE_FORMAT_TRIG 0xc0000000 + /* DHCP Related Mask */ #define QDF_DHCP_OPTION53 (0x35) #define QDF_DHCP_OPTION53_LENGTH (1) diff --git a/qdf/linux/src/i_qdf_lock.h b/qdf/linux/src/i_qdf_lock.h index 53e7a59d9cec..96acd6b9bc75 100644 --- a/qdf/linux/src/i_qdf_lock.h +++ b/qdf/linux/src/i_qdf_lock.h @@ -295,7 +295,7 @@ static inline void __qdf_spin_lock_bh(__qdf_spinlock_t *lock) static inline void __qdf_spin_unlock_bh(__qdf_spinlock_t *lock) { if (unlikely(lock->flags & QDF_LINUX_UNLOCK_BH)) { - lock->flags &= ~QDF_LINUX_UNLOCK_BH; + lock->flags &= (unsigned long)~QDF_LINUX_UNLOCK_BH; spin_unlock_bh(&lock->spinlock); } else spin_unlock(&lock->spinlock); diff --git a/qdf/linux/src/i_qdf_nbuf.h b/qdf/linux/src/i_qdf_nbuf.h index 1812b8a2bd8e..df162f3c1b19 100644 --- a/qdf/linux/src/i_qdf_nbuf.h +++ b/qdf/linux/src/i_qdf_nbuf.h @@ -569,28 +569,16 @@ void __qdf_nbuf_num_frags_init(struct sk_buff *skb) QDF_NBUF_CB_TX_NUM_EXTRA_FRAGS(skb) = 0; } -#ifdef CONFIG_MCL typedef enum { CB_FTYPE_INVALID = 0, CB_FTYPE_MCAST2UCAST = 1, CB_FTYPE_TSO = 2, CB_FTYPE_TSO_SG = 3, CB_FTYPE_SG = 4, + CB_FTYPE_INTRABSS_FWD = 5, + CB_FTYPE_RX_INFO = 6, + CB_FTYPE_MESH_RX_INFO = 7, } CB_FTYPE; -#else -typedef enum { - CB_FTYPE_INVALID = 0, - CB_FTYPE_MCAST2UCAST = 1, - CB_FTYPE_TSO = 2, - CB_FTYPE_TSO_SG = 3, - CB_FTYPE_SG = 4, -#if ATH_DATA_RX_INFO_EN - CB_FTYPE_RX_INFO = 5, -#else - CB_FTYPE_MESH_RX_INFO = 5, -#endif -} CB_FTYPE; -#endif /* * prototypes. Implemented in qdf_nbuf.c diff --git a/qdf/linux/src/qdf_nbuf.c b/qdf/linux/src/qdf_nbuf.c index 88665521dc74..99141596ddb7 100644 --- a/qdf/linux/src/qdf_nbuf.c +++ b/qdf/linux/src/qdf_nbuf.c @@ -2752,7 +2752,7 @@ unsigned int qdf_nbuf_update_radiotap(struct mon_rx_status *rx_status, qdf_print("ERROR: not enough space to update radiotap\n"); return 0; } - qdf_nbuf_pull_head(nbuf, headroom_sz - rtap_len); + qdf_nbuf_push_head(nbuf, rtap_len); qdf_mem_copy(qdf_nbuf_data(nbuf), rtap_buf, rtap_len); return rtap_len; } diff --git a/qdf/linux/src/qdf_trace.c b/qdf/linux/src/qdf_trace.c index 5981d041475a..9e910463aaa3 100644 --- a/qdf/linux/src/qdf_trace.c +++ b/qdf/linux/src/qdf_trace.c @@ -927,7 +927,7 @@ void qdf_dp_trace_set_track(qdf_nbuf_t nbuf, enum qdf_proto_dir dir) EXPORT_SYMBOL(qdf_dp_trace_set_track); #if CONFIG_MCL #define DPTRACE_PRINT(args...) \ - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO, ## args) + QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG, ## args) #else #define DPTRACE_PRINT(args...) \ QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_NONE, ## args) @@ -1702,15 +1702,13 @@ void qdf_dp_trace_dump_all(uint32_t count, uint8_t pdev_id) int32_t i, tail; if (!g_qdf_dp_trace_data.enable) { - QDF_TRACE(QDF_MODULE_ID_SYS, - QDF_TRACE_LEVEL_ERROR, "Tracing Disabled"); + DPTRACE_PRINT("Tracing Disabled"); return; } - QDF_TRACE(QDF_MODULE_ID_SYS, QDF_TRACE_LEVEL_ERROR, - "Total Records: %d, Head: %d, Tail: %d", - g_qdf_dp_trace_data.num, g_qdf_dp_trace_data.head, - g_qdf_dp_trace_data.tail); + DPTRACE_PRINT("Total Records: %d, Head: %d, Tail: %d", + g_qdf_dp_trace_data.num, g_qdf_dp_trace_data.head, + g_qdf_dp_trace_data.tail); /* aquire the lock so that only one thread at a time can read * the ring buffer diff --git a/umac/cmn_services/obj_mgr/src/wlan_objmgr_pdev_obj.c b/umac/cmn_services/obj_mgr/src/wlan_objmgr_pdev_obj.c index 67a0a1c1cf0d..b00cf1c53348 100644 --- a/umac/cmn_services/obj_mgr/src/wlan_objmgr_pdev_obj.c +++ b/umac/cmn_services/obj_mgr/src/wlan_objmgr_pdev_obj.c @@ -221,10 +221,21 @@ static QDF_STATUS wlan_objmgr_pdev_obj_destroy(struct wlan_objmgr_pdev *pdev) QDF_STATUS wlan_objmgr_pdev_obj_delete(struct wlan_objmgr_pdev *pdev) { + uint8_t print_idx; + if (pdev == NULL) { obj_mgr_err("pdev is NULL"); return QDF_STATUS_E_FAILURE; } + + print_idx = qdf_get_pidx(); + if (qdf_print_is_verbose_enabled(print_idx, QDF_MODULE_ID_OBJ_MGR, + QDF_TRACE_LEVEL_DEBUG)) { + obj_mgr_debug("Logically deleting the pdev(id:%d)", + pdev->pdev_objmgr.wlan_pdev_id); + wlan_objmgr_print_ref_ids(pdev->pdev_objmgr.ref_id_dbg); + } + /* * Update PDEV object state to LOGICALLY DELETED * It prevents further access of this object diff --git a/umac/cmn_services/obj_mgr/src/wlan_objmgr_peer_obj.c b/umac/cmn_services/obj_mgr/src/wlan_objmgr_peer_obj.c index c59760accd03..28dfdc007898 100644 --- a/umac/cmn_services/obj_mgr/src/wlan_objmgr_peer_obj.c +++ b/umac/cmn_services/obj_mgr/src/wlan_objmgr_peer_obj.c @@ -289,11 +289,29 @@ static QDF_STATUS wlan_objmgr_peer_obj_destroy(struct wlan_objmgr_peer *peer) QDF_STATUS wlan_objmgr_peer_obj_delete(struct wlan_objmgr_peer *peer) { + uint8_t print_idx; + uint8_t *macaddr; + if (peer == NULL) { obj_mgr_err("PEER is NULL"); return QDF_STATUS_E_FAILURE; } + wlan_peer_obj_lock(peer); + macaddr = wlan_peer_get_macaddr(peer); + wlan_peer_obj_unlock(peer); + + + print_idx = qdf_get_pidx(); + if (qdf_print_is_verbose_enabled(print_idx, QDF_MODULE_ID_OBJ_MGR, + QDF_TRACE_LEVEL_DEBUG)) { + obj_mgr_debug("Logically deleting the peer" + "(%02x:%02x:%02x:%02x:%02x:%02x)", + macaddr[0], macaddr[1], macaddr[2], + macaddr[3], macaddr[4], macaddr[5]); + wlan_objmgr_print_ref_ids(peer->peer_objmgr.ref_id_dbg); + } + /** * Update VDEV object state to LOGICALLY DELETED * It prevents further access of this object diff --git a/umac/cmn_services/obj_mgr/src/wlan_objmgr_psoc_obj.c b/umac/cmn_services/obj_mgr/src/wlan_objmgr_psoc_obj.c index 8f99154e62ec..05d8b78341f4 100644 --- a/umac/cmn_services/obj_mgr/src/wlan_objmgr_psoc_obj.c +++ b/umac/cmn_services/obj_mgr/src/wlan_objmgr_psoc_obj.c @@ -235,10 +235,21 @@ static QDF_STATUS wlan_objmgr_psoc_obj_destroy(struct wlan_objmgr_psoc *psoc) QDF_STATUS wlan_objmgr_psoc_obj_delete(struct wlan_objmgr_psoc *psoc) { + uint8_t print_idx; + if (psoc == NULL) { obj_mgr_err("psoc is NULL"); return QDF_STATUS_E_FAILURE; } + + print_idx = qdf_get_pidx(); + + if (qdf_print_is_verbose_enabled(print_idx, QDF_MODULE_ID_OBJ_MGR, + QDF_TRACE_LEVEL_DEBUG)) { + obj_mgr_debug("Logically deleting the psoc"); + wlan_objmgr_print_ref_ids(psoc->soc_objmgr.ref_id_dbg); + } + /* * Update PSOC object state to LOGICALLY DELETED * It prevents further access of this object diff --git a/umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj.c b/umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj.c index 0e07247c0d96..63a341c5f9e5 100644 --- a/umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj.c +++ b/umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj.c @@ -276,10 +276,21 @@ static QDF_STATUS wlan_objmgr_vdev_obj_destroy(struct wlan_objmgr_vdev *vdev) QDF_STATUS wlan_objmgr_vdev_obj_delete(struct wlan_objmgr_vdev *vdev) { + uint8_t print_idx; + if (vdev == NULL) { obj_mgr_err("vdev is NULL"); return QDF_STATUS_E_FAILURE; } + + print_idx = qdf_get_pidx(); + if (qdf_print_is_verbose_enabled(print_idx, QDF_MODULE_ID_OBJ_MGR, + QDF_TRACE_LEVEL_DEBUG)) { + obj_mgr_debug("Logically deleting the vdev(id:%d)", + vdev->vdev_objmgr.vdev_id); + wlan_objmgr_print_ref_ids(vdev->vdev_objmgr.ref_id_dbg); + } + /* * Update VDEV object state to LOGICALLY DELETED * It prevents further access of this object diff --git a/umac/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h b/umac/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h index 40cce054c0e1..6c18c484edf9 100644 --- a/umac/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h +++ b/umac/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h @@ -245,9 +245,9 @@ void policy_mgr_incr_active_session(struct wlan_objmgr_psoc *psoc, * mode. In the case of STA/P2P CLI/IBSS upon disconnection it is decremented * In the case of SAP/P2P GO upon bss stop it is decremented * - * Return: None + * Return: QDF_STATUS */ -void policy_mgr_decr_active_session(struct wlan_objmgr_psoc *psoc, +QDF_STATUS policy_mgr_decr_active_session(struct wlan_objmgr_psoc *psoc, enum tQDF_ADAPTER_MODE mode, uint8_t sessionId); /** @@ -782,7 +782,7 @@ struct policy_mgr_hdd_cbacks { QDF_STATUS (*wlan_hdd_get_channel_for_sap_restart)( struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, uint8_t *channel, - uint8_t *sec_ch, bool is_restart_sap); + uint8_t *sec_ch); enum policy_mgr_con_mode (*get_mode_for_non_connected_vdev)( struct wlan_objmgr_psoc *psoc, uint8_t vdev_id); @@ -1360,6 +1360,22 @@ uint32_t policy_mgr_mode_specific_connection_count( struct wlan_objmgr_psoc *psoc, enum policy_mgr_con_mode mode, uint32_t *list); +/** + * policy_mgr_check_conn_with_mode_and_vdev_id() - checks if any active + * session with specific mode and vdev_id + * @psoc: PSOC object information + * @mode: type of connection + * @vdev_id: vdev_id of the connection + * + * This function checks if any active session with specific mode and vdev_id + * is present + * + * Return: QDF STATUS with success if active session is found, else failure + */ +QDF_STATUS policy_mgr_check_conn_with_mode_and_vdev_id( + struct wlan_objmgr_psoc *psoc, enum policy_mgr_con_mode mode, + uint32_t vdev_id); + /** * policy_mgr_hw_mode_transition_cb() - Callback for HW mode * transition from FW diff --git a/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c b/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c index 1695fc4bff80..8990550e66b2 100644 --- a/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c +++ b/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c @@ -599,27 +599,6 @@ static bool policy_mgr_is_restart_sap_allowed( return true; } -/** - * policy_mgr_is_sap_channel_change_without_restart() - Check if - * SAP channel change allowed without restart - * @mcc_to_scc_switch: MCC to SCC switch enabled user config - * - * Check if SAP channel change allowed without restart - * - * Restart: true or false - */ -static bool policy_mgr_is_sap_channel_change_without_restart( - uint32_t mcc_to_scc_switch) { - if (mcc_to_scc_switch == - QDF_MCC_TO_SCC_SWITCH_FORCE_WITHOUT_DISCONNECTION || - mcc_to_scc_switch == - QDF_MCC_TO_SCC_SWITCH_WITH_FAVORITE_CHANNEL) { - policy_mgr_info("SAP chan change without restart allowed"); - return true; - } - return false; -} - /** * policy_mgr_check_sta_ap_concurrent_ch_intf() - Restart SAP in STA-AP case * @data: Pointer check concurrent channel work data @@ -637,8 +616,6 @@ void policy_mgr_check_sta_ap_concurrent_ch_intf(void *data) QDF_STATUS status; uint8_t channel, sec_ch; uint8_t operating_channel, vdev_id; - bool restart_sap; - pm_ctx = policy_mgr_get_context(psoc); if (!pm_ctx) { @@ -661,9 +638,6 @@ void policy_mgr_check_sta_ap_concurrent_ch_intf(void *data) return; } - restart_sap = policy_mgr_is_sap_channel_change_without_restart( - mcc_to_scc_switch) ? false : true; - if (!pm_ctx->hdd_cbacks.wlan_hdd_get_channel_for_sap_restart) { policy_mgr_err("SAP restart get channel callback in NULL"); return; @@ -671,7 +645,7 @@ void policy_mgr_check_sta_ap_concurrent_ch_intf(void *data) qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock); status = pm_ctx->hdd_cbacks. wlan_hdd_get_channel_for_sap_restart(psoc, vdev_id, - &channel, &sec_ch, restart_sap); + &channel, &sec_ch); qdf_mutex_release(&pm_ctx->qdf_conc_list_lock); if (status != QDF_STATUS_SUCCESS) { policy_mgr_err("Failed to switch SAP channel"); diff --git a/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c b/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c index 9d16bdd63c25..2bdebb638c54 100644 --- a/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c +++ b/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c @@ -838,6 +838,33 @@ uint32_t policy_mgr_mode_specific_connection_count( return count; } +QDF_STATUS policy_mgr_check_conn_with_mode_and_vdev_id( + struct wlan_objmgr_psoc *psoc, enum policy_mgr_con_mode mode, + uint32_t vdev_id) +{ + QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE; + uint32_t conn_index = 0; + struct policy_mgr_psoc_priv_obj *pm_ctx; + + pm_ctx = policy_mgr_get_context(psoc); + if (!pm_ctx) { + policy_mgr_err("Invalid Context"); + return qdf_status; + } + + qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock); + while (PM_CONC_CONNECTION_LIST_VALID_INDEX(conn_index)) { + if ((pm_conc_connection_list[conn_index].mode == mode) && + (pm_conc_connection_list[conn_index].vdev_id == vdev_id)) { + qdf_status = QDF_STATUS_SUCCESS; + break; + } + conn_index++; + } + qdf_mutex_release(&pm_ctx->qdf_conc_list_lock); + return qdf_status; +} + void policy_mgr_soc_set_dual_mac_cfg_cb(enum set_hw_mode_status status, uint32_t scan_config, uint32_t fw_mode_config) @@ -1122,16 +1149,27 @@ void policy_mgr_incr_active_session(struct wlan_objmgr_psoc *psoc, qdf_mutex_release(&pm_ctx->qdf_conc_list_lock); } -void policy_mgr_decr_active_session(struct wlan_objmgr_psoc *psoc, +QDF_STATUS policy_mgr_decr_active_session(struct wlan_objmgr_psoc *psoc, enum tQDF_ADAPTER_MODE mode, uint8_t session_id) { struct policy_mgr_psoc_priv_obj *pm_ctx; + QDF_STATUS qdf_status; pm_ctx = policy_mgr_get_context(psoc); if (!pm_ctx) { policy_mgr_err("context is NULL"); - return; + return QDF_STATUS_E_EMPTY; + } + + qdf_status = policy_mgr_check_conn_with_mode_and_vdev_id(psoc, + policy_mgr_convert_device_mode_to_qdf_type(mode), + session_id); + if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { + policy_mgr_err("No connection with mode:%d vdev_id:%d", + policy_mgr_convert_device_mode_to_qdf_type(mode), + session_id); + return qdf_status; } switch (mode) { @@ -1157,6 +1195,8 @@ void policy_mgr_decr_active_session(struct wlan_objmgr_psoc *psoc, pm_ctx->tdls_cbacks.tdls_notify_decrement_session(psoc); policy_mgr_dump_current_concurrency(psoc); + + return qdf_status; } QDF_STATUS policy_mgr_incr_connection_count( diff --git a/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c b/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c index ad0b2c9d0684..6c2a6971125c 100644 --- a/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c +++ b/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c @@ -103,7 +103,12 @@ void policy_mgr_decr_session_set_pcl(struct wlan_objmgr_psoc *psoc, return; } - policy_mgr_decr_active_session(psoc, mode, session_id); + qdf_status = policy_mgr_decr_active_session(psoc, mode, session_id); + if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { + policy_mgr_err("Invalid active session"); + return; + } + /* * After the removal of this connection, we need to check if * a STA connection still exists. The reason for this is that diff --git a/umac/scan/dispatcher/inc/wlan_scan_public_structs.h b/umac/scan/dispatcher/inc/wlan_scan_public_structs.h index a3fada2c6f90..22d5bebce3b3 100644 --- a/umac/scan/dispatcher/inc/wlan_scan_public_structs.h +++ b/umac/scan/dispatcher/inc/wlan_scan_public_structs.h @@ -534,6 +534,7 @@ enum scan_dwelltime_adaptive_mode { * @extraie: list of optional/vendor specific ie's to be added in probe requests * @htcap: htcap ie * @vhtcap: vhtcap ie + * @scan_ctrl_flags_ext: scan control flag extended */ struct scan_req_params { @@ -611,6 +612,7 @@ struct scan_req_params { struct element_info extraie; struct element_info htcap; struct element_info vhtcap; + uint32_t scan_ctrl_flags_ext; }; /** diff --git a/utils/host_diag_log/inc/host_diag_core_event.h b/utils/host_diag_log/inc/host_diag_core_event.h index 6dcb1f6851cf..078a02a34929 100644 --- a/utils/host_diag_log/inc/host_diag_core_event.h +++ b/utils/host_diag_log/inc/host_diag_core_event.h @@ -535,6 +535,7 @@ enum wifi_connectivity_events { * @WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP: Firmware response * @WIFI_POWER_EVENT_WAKELOCK_MISC: Miscellaneous wakelocks * @WIFI_POWER_EVENT_WAKELOCK_DHCP: DHCP negotiation under way + * @WIFI_POWER_EVENT_WAKELOCK_CONNECT: connection in progress * * Indicates the reason for which the wakelock was taken/released */ @@ -558,6 +559,7 @@ enum wake_lock_reason { WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP, WIFI_POWER_EVENT_WAKELOCK_MISC, WIFI_POWER_EVENT_WAKELOCK_DHCP, + WIFI_POWER_EVENT_WAKELOCK_CONNECT, }; #ifdef __cplusplus diff --git a/wlan_cfg/wlan_cfg.c b/wlan_cfg/wlan_cfg.c index f1a9c959c754..72a6a341af9d 100644 --- a/wlan_cfg/wlan_cfg.c +++ b/wlan_cfg/wlan_cfg.c @@ -182,9 +182,10 @@ struct wlan_cfg_dp_pdev_ctxt { * * Return: wlan_cfg_ctx - Handle to Configuration context */ -struct wlan_cfg_dp_soc_ctxt *wlan_cfg_soc_attach(void) +struct wlan_cfg_dp_soc_ctxt *wlan_cfg_soc_attach() { int i = 0; + struct wlan_cfg_dp_soc_ctxt *wlan_cfg_ctx = qdf_mem_malloc(sizeof(struct wlan_cfg_dp_soc_ctxt)); @@ -202,8 +203,8 @@ struct wlan_cfg_dp_soc_ctxt *wlan_cfg_soc_attach(void) wlan_cfg_ctx->num_tx_ext_desc_pool = WLAN_CFG_NUM_TXEXT_DESC_POOL; wlan_cfg_ctx->num_tx_desc = WLAN_CFG_NUM_TX_DESC; wlan_cfg_ctx->num_tx_ext_desc = WLAN_CFG_NUM_TX_EXT_DESC; - wlan_cfg_ctx->max_peer_id = WLAN_CFG_MAX_PEER_ID; wlan_cfg_ctx->htt_packet_type = WLAN_CFG_HTT_PKT_TYPE; + wlan_cfg_ctx->max_peer_id = WLAN_CFG_MAX_PEER_ID; for (i = 0; i < WLAN_CFG_INT_NUM_CONTEXTS; i++) { wlan_cfg_ctx->int_tx_ring_mask[i] = tx_ring_mask[i]; @@ -249,6 +250,11 @@ void wlan_cfg_set_num_contexts(struct wlan_cfg_dp_soc_ctxt *cfg, int num) cfg->num_int_ctxts = num; } +void wlan_cfg_set_max_peer_id(struct wlan_cfg_dp_soc_ctxt *cfg, uint32_t val) +{ + cfg->max_peer_id = val;; +} + void wlan_cfg_set_tx_ring_mask(struct wlan_cfg_dp_soc_ctxt *cfg, int context, int mask) { diff --git a/wlan_cfg/wlan_cfg.h b/wlan_cfg/wlan_cfg.h index 681c4e0ee09b..9d63cb14d31c 100644 --- a/wlan_cfg/wlan_cfg.h +++ b/wlan_cfg/wlan_cfg.h @@ -106,6 +106,9 @@ void wlan_cfg_set_ce_ring_mask(struct wlan_cfg_dp_soc_ctxt *cfg, int context, int mask); void wlan_cfg_set_rxbuf_ring_mask(struct wlan_cfg_dp_soc_ctxt *cfg, int context, int mask); + +void wlan_cfg_set_max_peer_id(struct wlan_cfg_dp_soc_ctxt *cfg, uint32_t val); + /** * wlan_cfg_get_num_contexts() - Number of interrupt contexts to be registered * @wlan_cfg_ctx - Configuration Handle diff --git a/wmi/inc/wmi_unified_api.h b/wmi/inc/wmi_unified_api.h index 3f0c303d0562..f413dd01b250 100644 --- a/wmi/inc/wmi_unified_api.h +++ b/wmi/inc/wmi_unified_api.h @@ -1507,4 +1507,6 @@ void wmi_print_mgmt_event_log(wmi_unified_t wmi, uint32_t count, #endif /* WMI_INTERFACE_EVENT_LOGGING */ +QDF_STATUS wmi_unified_send_dbs_scan_sel_params_cmd(void *wmi_hdl, + struct wmi_dbs_scan_sel_params *wmi_param); #endif /* _WMI_UNIFIED_API_H_ */ diff --git a/wmi/inc/wmi_unified_param.h b/wmi/inc/wmi_unified_param.h index 6be9b31a81a2..6f98ebee4b0f 100644 --- a/wmi/inc/wmi_unified_param.h +++ b/wmi/inc/wmi_unified_param.h @@ -7285,4 +7285,22 @@ struct tbttoffset_params { uint32_t tbttoffset; }; +#define WMI_SCAN_CLIENT_MAX 7 + +/** + * struct wmi_dbs_scan_sel_params - DBS scan selection params + * @num_clients: Number of scan clients dutycycle + * @pdev_id: pdev_id for identifying the MAC + * @module_id: scan client module id + * @num_dbs_scans: number of DBS scans + * @num_non_dbs_scans: number of non-DBS scans + */ +struct wmi_dbs_scan_sel_params { + uint32_t num_clients; + uint32_t pdev_id; + uint32_t module_id[WMI_SCAN_CLIENT_MAX]; + uint32_t num_dbs_scans[WMI_SCAN_CLIENT_MAX]; + uint32_t num_non_dbs_scans[WMI_SCAN_CLIENT_MAX]; +}; + #endif /* _WMI_UNIFIED_PARAM_H_ */ diff --git a/wmi/inc/wmi_unified_priv.h b/wmi/inc/wmi_unified_priv.h index 569bf8ae2230..09f0db08ffd6 100644 --- a/wmi/inc/wmi_unified_priv.h +++ b/wmi/inc/wmi_unified_priv.h @@ -1258,6 +1258,9 @@ QDF_STATUS (*send_multiple_vdev_restart_req_cmd)(wmi_unified_t wmi_handle, QDF_STATUS (*send_adapt_dwelltime_params_cmd)(wmi_unified_t wmi_handle, struct wmi_adaptive_dwelltime_params *dwelltime_params); +QDF_STATUS (*send_dbs_scan_sel_params_cmd)(wmi_unified_t wmi_handle, + struct wmi_dbs_scan_sel_params *dbs_scan_params); + QDF_STATUS (*send_fw_test_cmd)(wmi_unified_t wmi_handle, struct set_fwtest_params *wmi_fwtest); diff --git a/wmi/src/wmi_unified_api.c b/wmi/src/wmi_unified_api.c index b9144df4fae2..2835a37bfb82 100644 --- a/wmi/src/wmi_unified_api.c +++ b/wmi/src/wmi_unified_api.c @@ -6683,3 +6683,23 @@ QDF_STATUS wmi_unified_set_country_cmd_send(void *wmi_hdl, return QDF_STATUS_E_FAILURE; } +/** + * wmi_unified_send_dbs_scan_sel_params_cmd() - send wmi cmd of + * DBS scan selection configuration params + * @wma_handle: wma handler + * @dbs_scan_params: pointer to wmi_dbs_scan_sel_params + * + * Return: QDF_STATUS_SUCCESS on success and QDF failure reason code for failure + */ +QDF_STATUS wmi_unified_send_dbs_scan_sel_params_cmd(void *wmi_hdl, + struct wmi_dbs_scan_sel_params *dbs_scan_params) +{ + wmi_unified_t wmi_handle = (wmi_unified_t) wmi_hdl; + + if (wmi_handle->ops->send_dbs_scan_sel_params_cmd) + return wmi_handle->ops-> + send_dbs_scan_sel_params_cmd(wmi_handle, + dbs_scan_params); + + return QDF_STATUS_E_FAILURE; +} diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index e41f82dd149f..ed77cabd8d23 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/wmi/src/wmi_unified_tlv.c @@ -2226,6 +2226,10 @@ static QDF_STATUS send_scan_start_cmd_tlv(wmi_unified_t wmi_handle, cmd->num_ssids = params->num_ssids; cmd->ie_len = params->extraie.len; cmd->n_probes = params->n_probes; + cmd->scan_ctrl_flags_ext = params->scan_ctrl_flags_ext; + + WMI_LOGD("scan_ctrl_flags_ext = %x", cmd->scan_ctrl_flags_ext); + buf_ptr += sizeof(*cmd); tmp_ptr = (uint32_t *) (buf_ptr + WMI_TLV_HDR_SIZE); for (i = 0; i < params->num_chan; ++i) @@ -5766,6 +5770,71 @@ QDF_STATUS send_adapt_dwelltime_params_cmd_tlv(wmi_unified_t wmi_handle, return QDF_STATUS_SUCCESS; } +/** + * send_dbs_scan_sel_params_cmd_tlv() - send wmi cmd of DBS scan selection + * configuration params + * @wmi_handle: wmi handler + * @dbs_scan_params: pointer to wmi_dbs_scan_sel_params + * + * Return: QDF_STATUS_SUCCESS on success and QDF failure reason code for failure + */ +static QDF_STATUS send_dbs_scan_sel_params_cmd_tlv(wmi_unified_t wmi_handle, + struct wmi_dbs_scan_sel_params *dbs_scan_params) +{ + wmi_scan_dbs_duty_cycle_fixed_param *dbs_scan_param; + wmi_scan_dbs_duty_cycle_tlv_param *cmd; + wmi_buf_t buf; + uint8_t *buf_ptr; + QDF_STATUS err; + uint32_t i; + int len; + + len = sizeof(*dbs_scan_param); + len += WMI_TLV_HDR_SIZE; + len += dbs_scan_params->num_clients * sizeof(*cmd); + + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) { + WMI_LOGE("%s:Failed to allocate buffer to send cmd", __func__); + return QDF_STATUS_E_NOMEM; + } + + buf_ptr = (uint8_t *) wmi_buf_data(buf); + dbs_scan_param = (wmi_scan_dbs_duty_cycle_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&dbs_scan_param->tlv_header, + WMITLV_TAG_STRUC_wmi_scan_dbs_duty_cycle_fixed_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_scan_dbs_duty_cycle_fixed_param)); + + dbs_scan_param->num_clients = dbs_scan_params->num_clients; + dbs_scan_param->pdev_id = dbs_scan_params->pdev_id; + buf_ptr += sizeof(*dbs_scan_param); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + (sizeof(*cmd) * dbs_scan_params->num_clients)); + buf_ptr = buf_ptr + (uint8_t) WMI_TLV_HDR_SIZE; + + for (i = 0; i < dbs_scan_params->num_clients; i++) { + cmd = (wmi_scan_dbs_duty_cycle_tlv_param *) buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_scan_dbs_duty_cycle_param_tlv, + WMITLV_GET_STRUCT_TLVLEN( + wmi_scan_dbs_duty_cycle_tlv_param)); + cmd->module_id = dbs_scan_params->module_id[i]; + cmd->num_dbs_scans = dbs_scan_params->num_dbs_scans[i]; + cmd->num_non_dbs_scans = dbs_scan_params->num_non_dbs_scans[i]; + buf_ptr = buf_ptr + (uint8_t) sizeof(*cmd); + } + + err = wmi_unified_cmd_send(wmi_handle, buf, + len, WMI_SET_SCAN_DBS_DUTY_CYCLE_CMDID); + if (QDF_IS_STATUS_ERROR(err)) { + WMI_LOGE("Failed to send dbs scan selection cmd err=%d", err); + wmi_buf_free(buf); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} /** * send_roam_scan_filter_cmd_tlv() - Filter to be applied while roaming @@ -18066,6 +18135,8 @@ struct wmi_ops tlv_ops = { .send_set_active_bpf_mode_cmd = send_set_active_bpf_mode_cmd_tlv, .send_adapt_dwelltime_params_cmd = send_adapt_dwelltime_params_cmd_tlv, + .send_dbs_scan_sel_params_cmd = + send_dbs_scan_sel_params_cmd_tlv, .init_cmd_send = init_cmd_send_tlv, .send_smart_ant_enable_cmd = send_smart_ant_enable_cmd_tlv, .send_smart_ant_set_rx_ant_cmd = send_smart_ant_set_rx_ant_cmd_tlv,