From 855875eaff2282053d536e6774dfabaad4b937d9 Mon Sep 17 00:00:00 2001 From: P Praneesh Date: Tue, 16 Jun 2020 16:57:46 +0530 Subject: [PATCH] ath11k: add support for 2G PHYB mode This mode is supported through hw_mode_id 7 and it is special mode for IPQ8074 platform alone to bring up single pdev alone on 2G mode. Signed-off-by: P Praneesh --- drivers/net/wireless/ath/ath11k/ahb.c | 5 +++ drivers/net/wireless/ath/ath11k/core.h | 3 +- drivers/net/wireless/ath/ath11k/db_ring.c | 2 +- drivers/net/wireless/ath/ath11k/dp_rx.c | 2 +- drivers/net/wireless/ath/ath11k/dp_tx.c | 4 +- drivers/net/wireless/ath/ath11k/hw.c | 5 ++- drivers/net/wireless/ath/ath11k/mac.c | 45 +++++++++++++++++++- drivers/net/wireless/ath/ath11k/wmi.c | 71 +++++++++++++++++++++++-------- drivers/net/wireless/ath/ath11k/wmi.h | 10 ++++- 9 files changed, 119 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c index d3d0754..428bed8 100644 --- a/drivers/net/wireless/ath/ath11k/ahb.c +++ b/drivers/net/wireless/ath/ath11k/ahb.c @@ -727,6 +727,11 @@ static int ath11k_ahb_ext_irq_config(struct ath11k_base *ab) irq_grp->irqs[num_irq++] = reo2host_status; if (j < ab->hw_params.max_radios) { + /* for phyb_2g mode configure irq for only pdev_idx 0 */ + if (ab->wmi_ab.preferred_hw_mode == WMI_HOST_HW_MODE_2G_PHYB) + if (j != 0) + continue; + if (ath11k_rxdma2host_ring_mask[i] & BIT(j)) { irq_grp->irqs[num_irq++] = rxdma2host_destination_ring_mac1 diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h index 49b0a9d..3f57aeb 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -833,7 +833,8 @@ struct ath11k_base { bool is_poll; struct ath11k_poll poll; const struct hal_srng_regs *srng_regs; - + u32 sw_pdev_id_map[MAX_RADIOS]; + u32 hw_pdev_id_map[MAX_RADIOS]; /* must be last */ u8 drv_priv[0] __aligned(sizeof(void *)); }; diff --git a/drivers/net/wireless/ath/ath11k/db_ring.c b/drivers/net/wireless/ath/ath11k/db_ring.c index 5638bbe..f8b3fc7 100644 --- a/drivers/net/wireless/ath/ath11k/db_ring.c +++ b/drivers/net/wireless/ath/ath11k/db_ring.c @@ -121,7 +121,7 @@ int ath11k_db_ring_wmi_cfg_setup(struct ath11k *ar, if (id >= WMI_DIRECT_BUF_MAX) return -EINVAL; - param.pdev_id = DP_SW2HW_MACID(ring->pdev_id); + param.pdev_id = ar->ab->hw_pdev_id_map[ring->pdev_id]; param.module_id = id; param.base_paddr_lo = lower_32_bits(ring->refill_srng.paddr); param.base_paddr_hi = upper_32_bits(ring->refill_srng.paddr); diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c index 57c443c..3c903ec 100644 --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c @@ -1673,7 +1673,7 @@ static void ath11k_htt_backpressure_event_handler(struct ath11k_base *ab, return; bp_stats = &ab->ring_stats.bp_stats.umac_ring_bp_stats[ring_id]; } else if (ring_type == HTT_BACKPRESSURE_LMAC_RING_TYPE) { - pdev_idx = DP_HW2SW_MACID(pdev_id); + pdev_idx = ab->sw_pdev_id_map[pdev_id - 1]; if (ring_id >= HTT_SW_LMAC_RING_IDX_MAX || pdev_idx >= MAX_RADIOS) return; diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c index ba6cdd9..9df27f9 100644 --- a/drivers/net/wireless/ath/ath11k/dp_tx.c +++ b/drivers/net/wireless/ath/ath11k/dp_tx.c @@ -752,7 +752,7 @@ int ath11k_dp_tx_htt_srng_setup(struct ath11k_base *ab, u32 ring_id, if (htt_ring_type == HTT_SW_TO_HW_RING || htt_ring_type == HTT_HW_TO_SW_RING) cmd->info0 |= FIELD_PREP(HTT_SRNG_SETUP_CMD_INFO0_PDEV_ID, - DP_SW2HW_MACID(mac_id)); + ab->hw_pdev_id_map[mac_id]); else cmd->info0 |= FIELD_PREP(HTT_SRNG_SETUP_CMD_INFO0_PDEV_ID, mac_id); @@ -936,7 +936,7 @@ int ath11k_dp_tx_htt_rx_filter_setup(struct ath11k_base *ab, u32 ring_id, htt_ring_type == HTT_HW_TO_SW_RING) cmd->info0 |= FIELD_PREP(HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID, - DP_SW2HW_MACID(mac_id)); + ab->hw_pdev_id_map[mac_id]); else cmd->info0 |= FIELD_PREP(HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID, diff --git a/drivers/net/wireless/ath/ath11k/hw.c b/drivers/net/wireless/ath/ath11k/hw.c index c13cd56..8082cd7 100644 --- a/drivers/net/wireless/ath/ath11k/hw.c +++ b/drivers/net/wireless/ath/ath11k/hw.c @@ -15,7 +15,10 @@ static u8 ath11k_qca8074_hw_mac_from_pdev_id(struct ath11k_base *ab, { switch (pdev_idx) { case 0: - return 0; + if (ab->wmi_ab.preferred_hw_mode == WMI_HOST_HW_MODE_2G_PHYB) + return 2; + else + return 0; case 1: return 2; case 2: diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index bc007d8..16eff7f 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -449,8 +449,9 @@ struct ath11k *ath11k_mac_get_ar_by_pdev_id(struct ath11k_base *ab, u32 pdev_id) int i; struct ath11k_pdev *pdev; - if (WARN_ON(pdev_id > ab->num_radios)) - return NULL; + if (ab->wmi_ab.preferred_hw_mode != WMI_HOST_HW_MODE_2G_PHYB) + if (WARN_ON(pdev_id > ab->num_radios)) + return NULL; for (i = 0; i < ab->num_radios; i++) { pdev = rcu_dereference(ab->pdevs_active[i]); @@ -7246,6 +7247,44 @@ err_cleanup: return ret; } +void ath11k_mac_pdev_map(struct ath11k_base *ab) +{ + /* sw_pdev_id_map is used by host*/ + u32 sw_pdev_id_map[MAX_RADIOS] = { WMI_HOST_PDEV_ID_0, + WMI_HOST_PDEV_ID_1, + WMI_HOST_PDEV_ID_2 }; + + /* hw_pdev_id_map is used by firmware */ + u32 hw_pdev_id_map[MAX_RADIOS] = { WMI_HOST_PDEV_ID_1, + WMI_HOST_PDEV_ID_2, + WMI_HOST_PDEV_ID_3 }; + + /* In PHYB-2G mode, host WMI_HOST_PDEV_ID_1 and + * WMI_HOST_PDEV_ID_2 are unused, only 2G radio is active */ + u32 sw_pdev_id_map_phyb2g[MAX_RADIOS] = { WMI_HOST_PDEV_ID_1, + WMI_HOST_PDEV_ID_0, + WMI_HOST_PDEV_ID_2 }; + + /* In PHYB-2G mode, firmware WMI_HOST_PDEV_ID_1 and + * WMI_HOST_PDEV_ID_3 are unused, only 2G radio is active */ + u32 hw_pdev_id_map_phyb2g[MAX_RADIOS] = { WMI_HOST_PDEV_ID_2, + WMI_HOST_PDEV_ID_1, + WMI_HOST_PDEV_ID_3 }; + + if (ab->wmi_ab.preferred_hw_mode == WMI_HOST_HW_MODE_2G_PHYB) { + /* Host and firmware pdev_map for PHYB2G hw mode */ + memcpy(ab->sw_pdev_id_map,sw_pdev_id_map_phyb2g, + MAX_RADIOS * sizeof(u32)); + memcpy(ab->hw_pdev_id_map,hw_pdev_id_map_phyb2g, + MAX_RADIOS * sizeof(u32)); + } else { + memcpy(ab->sw_pdev_id_map,sw_pdev_id_map, + MAX_RADIOS * sizeof(u32)); + memcpy(ab->hw_pdev_id_map,hw_pdev_id_map, + MAX_RADIOS * sizeof(u32)); + } +} + int ath11k_mac_allocate(struct ath11k_base *ab) { struct ieee80211_hw *hw; @@ -7286,6 +7325,8 @@ int ath11k_mac_allocate(struct ath11k_base *ab) ar->num_rx_chains = get_num_chains(pdev->cap.rx_chain_mask); pdev->ar = ar; + ath11k_mac_pdev_map(ab); + spin_lock_init(&ar->data_lock); INIT_LIST_HEAD(&ar->arvifs); INIT_LIST_HEAD(&ar->ppdu_stats_info); diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c index e548fce..c6939b8 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -139,6 +139,8 @@ static const int ath11k_hw_mode_pri_map[] = { PRIMAP(WMI_HOST_HW_MODE_SBS), PRIMAP(WMI_HOST_HW_MODE_DBS_SBS), PRIMAP(WMI_HOST_HW_MODE_DBS_OR_SBS), + PRIMAP(WMI_HOST_HW_MODE_FW_INTERNAL), + PRIMAP(WMI_HOST_HW_MODE_2G_PHYB), /* keep last */ PRIMAP(WMI_HOST_HW_MODE_MAX), }; @@ -343,8 +345,8 @@ ath11k_pull_mac_phy_cap_svc_ready_ext(struct ath11k_pdev_wmi *wmi_handle, phy_map = wmi_hw_mode_caps[hw_idx].phy_id_map; while (phy_map) { + phy_idx += phy_map & 1; phy_map >>= 1; - phy_idx++; } } @@ -2973,7 +2975,7 @@ int ath11k_wmi_pdev_peer_pktlog_filter(struct ath11k *ar, u8 *addr, u8 enable) cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_PDEV_PEER_PKTLOG_FILTER_CMD) | FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); - cmd->pdev_id = DP_HW2SW_MACID(ar->pdev->pdev_id); + cmd->pdev_id = ar->ab->sw_pdev_id_map[ar->pdev->pdev_id - 1]; cmd->num_mac = 1; cmd->enable = enable; @@ -3135,7 +3137,7 @@ int ath11k_wmi_pdev_pktlog_enable(struct ath11k *ar, u32 pktlog_filter) cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_PDEV_PKTLOG_ENABLE_CMD) | FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); - cmd->pdev_id = DP_HW2SW_MACID(ar->pdev->pdev_id); + cmd->pdev_id = ar->ab->sw_pdev_id_map[ar->pdev->pdev_id - 1]; cmd->evlist = pktlog_filter; cmd->enable = ATH11K_WMI_PKTLOG_ENABLE_FORCE; @@ -3165,7 +3167,7 @@ int ath11k_wmi_pdev_pktlog_disable(struct ath11k *ar) cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_PDEV_PKTLOG_DISABLE_CMD) | FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); - cmd->pdev_id = DP_HW2SW_MACID(ar->pdev->pdev_id); + cmd->pdev_id = ar->ab->sw_pdev_id_map[ar->pdev->pdev_id - 1]; ret = ath11k_wmi_cmd_send(wmi, skb, WMI_PDEV_PKTLOG_DISABLE_CMDID); @@ -3875,7 +3877,8 @@ static int ath11k_wmi_tlv_dma_buf_parse(struct ath11k_base *ab, case WMI_TAG_DMA_BUF_RELEASE: memcpy(&parse->fixed, ptr, sizeof(struct ath11k_wmi_dma_buf_release_fixed_param)); - parse->fixed.pdev_id = DP_HW2SW_MACID(parse->fixed.pdev_id); + parse->fixed.pdev_id = + ab->sw_pdev_id_map[parse->fixed.pdev_id - 1]; break; case WMI_TAG_ARRAY_STRUCT: if (!parse->buf_entry_done) { @@ -4098,23 +4101,26 @@ static int ath11k_wmi_tlv_ext_soc_hal_reg_caps_parse(struct ath11k_base *soc, svc_rdy_ext->param.num_phy = svc_rdy_ext->soc_hal_reg_caps->num_phy; soc->num_radios = 0; + phy_id_map = svc_rdy_ext->pref_hw_mode_caps.phy_id_map; while (phy_id_map && soc->num_radios < MAX_RADIOS) { - ret = ath11k_pull_mac_phy_cap_svc_ready_ext(wmi_handle, + if(phy_id_map & 1) { + ret = ath11k_pull_mac_phy_cap_svc_ready_ext(wmi_handle, svc_rdy_ext->hw_caps, svc_rdy_ext->hw_mode_caps, svc_rdy_ext->soc_hal_reg_caps, svc_rdy_ext->mac_phy_caps, hw_mode_id, soc->num_radios, &soc->pdevs[soc->num_radios]); - if (ret) { - ath11k_warn(soc, "failed to extract mac caps, idx :%d\n", - soc->num_radios); + if (ret) { + ath11k_warn(soc, "failed to extract mac caps, idx :%d\n", + soc->num_radios); return ret; - } + } - soc->num_radios++; + soc->num_radios++; + } /* TODO: mac_phy_cap prints */ phy_id_map >>= 1; @@ -4197,8 +4203,9 @@ static int ath11k_wmi_tlv_dma_ring_caps(struct ath11k_base *ab, goto free_dir_buff; } + dir_buff_caps[i].pdev_id = + ab->sw_pdev_id_map[dma_caps[i].pdev_id - 1]; dir_buff_caps[i].id = dma_caps[i].module_id; - dir_buff_caps[i].pdev_id = DP_HW2SW_MACID(dma_caps[i].pdev_id); dir_buff_caps[i].min_elem = dma_caps[i].min_elem; dir_buff_caps[i].min_buf_sz = dma_caps[i].min_buf_sz; dir_buff_caps[i].min_buf_align = dma_caps[i].min_buf_align; @@ -5835,8 +5842,17 @@ static int ath11k_reg_chan_list_event(struct ath11k_base *ab, struct sk_buff *sk pdev_idx = reg_info->phy_id; - if (pdev_idx >= ab->num_radios) - goto fallback; + if (ab->wmi_ab.preferred_hw_mode == WMI_HOST_HW_MODE_2G_PHYB) { + pdev_idx = WMI_PHYID2PDEVIDX_MAP(reg_info->phy_id); + if ((pdev_idx > ab->num_radios) && + (pdev_idx >= MAX_RADIOS)) + goto fallback; + } + else { + pdev_idx = reg_info->phy_id; + if (pdev_idx >= ab->num_radios) + goto fallback; + } /* Avoid multiple overwrites to default regd, during core * stop-start after mac registration. @@ -7053,16 +7069,32 @@ out: dev_kfree_skb(skb); } +static bool ath11k_wmi_check_phyb2g_mode(struct ath11k_base *ab) +{ + struct device *dev = ab->dev; + u32 hw_mode_id = WMI_HOST_HW_MODE_MAX; + + if (!of_property_read_u32(dev->of_node , "wlan-hw-mode", + &hw_mode_id)) { + if (hw_mode_id == WMI_HOST_HW_MODE_2G_PHYB) + return true; + } + return false; +} + static int ath11k_connect_pdev_htc_service(struct ath11k_base *ab, u32 pdev_idx) { int status; - u32 svc_id[] = { ATH11K_HTC_SVC_ID_WMI_CONTROL, - ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC1, - ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC2 }; + u32 default_svc_id[] = { ATH11K_HTC_SVC_ID_WMI_CONTROL, + ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC1, + ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC2 }; struct ath11k_htc_svc_conn_req conn_req; struct ath11k_htc_svc_conn_resp conn_resp; + u32 phyb2g_svc_id[] = { ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC1, + ATH11K_HTC_SVC_ID_WMI_CONTROL, + ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC2 }; memset(&conn_req, 0, sizeof(conn_req)); memset(&conn_resp, 0, sizeof(conn_resp)); @@ -7073,7 +7105,10 @@ static int ath11k_connect_pdev_htc_service(struct ath11k_base *ab, conn_req.ep_ops.ep_tx_credits = ath11k_wmi_op_ep_tx_credits; /* connect to control service */ - conn_req.service_id = svc_id[pdev_idx]; + if(ath11k_wmi_check_phyb2g_mode(ab)) + conn_req.service_id = phyb2g_svc_id[pdev_idx]; + else + conn_req.service_id = default_svc_id[pdev_idx]; status = ath11k_htc_connect_service(&ab->htc, &conn_req, &conn_resp); if (status) { diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h index 9d29ee2..62a9011 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h @@ -34,6 +34,7 @@ struct ath11k_fw_stats; #define WMI_TLV_CMD_UNSUPPORTED 0 #define WMI_TLV_PDEV_PARAM_UNSUPPORTED 0 #define WMI_TLV_VDEV_PARAM_UNSUPPORTED 0 +#define WMI_PHYID2PDEVIDX_MAP(phy_id) ((phy_id) ? 0 : 1) struct wmi_cmd_hdr { u32 cmd_id; @@ -74,6 +75,8 @@ struct wmi_tlv { * as in WMI_HW_MODE_SBS, and 3rd on the other band * @WMI_HOST_HW_MODE_DBS_OR_SBS: Two PHY with one PHY capabale of both 2G and * 5G. It can support SBS (5G + 5G) OR DBS (5G + 2G). + * @WMI_HOST_HW_MODE_FW_INTERNAL: FW specific internal mode. + * @WMI_HOST_HW_MODE_2G_PHYB: Only one phy is active. 2G mode on PhyB. * @WMI_HOST_HW_MODE_MAX: Max hw_mode_id. Used to indicate invalid mode. */ enum wmi_host_hw_mode_config_type { @@ -83,7 +86,8 @@ enum wmi_host_hw_mode_config_type { WMI_HOST_HW_MODE_SBS = 3, WMI_HOST_HW_MODE_DBS_SBS = 4, WMI_HOST_HW_MODE_DBS_OR_SBS = 5, - + WMI_HOST_HW_MODE_FW_INTERNAL = 6, + WMI_HOST_HW_MODE_2G_PHYB = 7, /* keep last */ WMI_HOST_HW_MODE_MAX }; @@ -92,13 +96,14 @@ enum wmi_host_hw_mode_config_type { * on the available modes. */ enum wmi_host_hw_mode_priority { + WMI_HOST_HW_MODE_2G_PHYB_PRI, WMI_HOST_HW_MODE_DBS_SBS_PRI, WMI_HOST_HW_MODE_DBS_PRI, WMI_HOST_HW_MODE_DBS_OR_SBS_PRI, WMI_HOST_HW_MODE_SBS_PRI, WMI_HOST_HW_MODE_SBS_PASSIVE_PRI, WMI_HOST_HW_MODE_SINGLE_PRI, - + WMI_HOST_HW_MODE_FW_INTERNAL_PRI, /* keep last the lowest priority */ WMI_HOST_HW_MODE_MAX_PRI }; @@ -2778,6 +2783,7 @@ struct rx_reorder_queue_remove_params { #define WMI_HOST_PDEV_ID_0 0 #define WMI_HOST_PDEV_ID_1 1 #define WMI_HOST_PDEV_ID_2 2 +#define WMI_HOST_PDEV_ID_3 3 #define WMI_PDEV_ID_SOC 0 #define WMI_PDEV_ID_1ST 1 -- 2.7.4