wlan-ap-Telecominfraproject/feeds/wifi-ax/mac80211/patches/qca/192-ath11k-support-for-2g-phyb-mode.patch
John Crispin 528a778e38 open-converged-wireless: Import 21.02 based uCentral tree
Signed-off-by: John Crispin <john@phrozen.org>
2021-03-25 12:19:47 +01:00

445 lines
16 KiB
Diff

From 855875eaff2282053d536e6774dfabaad4b937d9 Mon Sep 17 00:00:00 2001
From: P Praneesh <ppranees@codeaurora.org>
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 <ppranees@codeaurora.org>
---
drivers/net/wireless/ath/ath11k/ahb.c | 5 +++
drivers/net/wireless/ath/ath11k/core.h | 3 +-
drivers/net/wireless/ath/ath11k/dbring.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(-)
--- a/drivers/net/wireless/ath/ath11k/ahb.c
+++ b/drivers/net/wireless/ath/ath11k/ahb.c
@@ -494,6 +494,11 @@ static int ath11k_ahb_ext_irq_config(str
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 (ab->hw_params.ring_mask->rxdma2host[i] & BIT(j)) {
irq_grp->irqs[num_irq++] =
rxdma2host_destination_ring_mac1 -
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -822,7 +822,8 @@ struct ath11k_base {
struct ath11k_dbring_cap *db_caps;
u32 num_db_cap;
-
+ u32 sw_pdev_id_map[MAX_RADIOS];
+ u32 hw_pdev_id_map[MAX_RADIOS];
/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
};
--- a/drivers/net/wireless/ath/ath11k/dbring.c
+++ b/drivers/net/wireless/ath/ath11k/dbring.c
@@ -121,7 +121,7 @@ int ath11k_dbring_wmi_cfg_setup(struct a
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);
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -1724,7 +1724,7 @@ static void ath11k_htt_backpressure_even
bp_stats = &ab->soc_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;
--- a/drivers/net/wireless/ath/ath11k/dp_tx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c
@@ -773,7 +773,7 @@ int ath11k_dp_tx_htt_srng_setup(struct a
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);
@@ -957,7 +957,7 @@ int ath11k_dp_tx_htt_rx_filter_setup(str
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,
--- a/drivers/net/wireless/ath/ath11k/hw.c
+++ b/drivers/net/wireless/ath/ath11k/hw.c
@@ -12,11 +12,16 @@
#include "ce.h"
/* Map from pdev index to hw mac index */
-static u8 ath11k_hw_ipq8074_mac_from_pdev_id(int pdev_idx)
+static u8 ath11k_hw_ipq8074_mac_from_pdev_id(struct ath11k_hw_params *hw, int pdev_idx)
{
+ struct ath11k_base *ab = container_of(hw, struct ath11k_base, hw_params);
+
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:
@@ -26,7 +31,7 @@ static u8 ath11k_hw_ipq8074_mac_from_pde
}
}
-static u8 ath11k_hw_ipq6018_mac_from_pdev_id(int pdev_idx)
+static u8 ath11k_hw_ipq6018_mac_from_pdev_id(struct ath11k_hw_params *hw, int pdev_idx)
{
return pdev_idx;
}
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -545,8 +545,9 @@ struct ath11k *ath11k_mac_get_ar_by_pdev
return pdev ? pdev->ar : NULL;
}
- 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++) {
if (ab->fw_mode == ATH11K_FIRMWARE_MODE_FTM)
@@ -7517,6 +7518,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;
@@ -7557,6 +7596,8 @@ int ath11k_mac_allocate(struct ath11k_ba
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);
--- 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(st
phy_map = wmi_hw_mode_caps[hw_idx].phy_id_map;
while (phy_map) {
+ phy_idx += phy_map & 1;
phy_map >>= 1;
- phy_idx++;
}
}
@@ -3091,7 +3093,7 @@ int ath11k_wmi_pdev_peer_pktlog_filter(s
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;
@@ -3253,7 +3255,7 @@ int ath11k_wmi_pdev_pktlog_enable(struct
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;
@@ -3283,7 +3285,7 @@ int ath11k_wmi_pdev_pktlog_disable(struc
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);
@@ -3996,7 +3998,8 @@ static int ath11k_wmi_tlv_dma_buf_parse(
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) {
@@ -4225,20 +4228,22 @@ static int ath11k_wmi_tlv_ext_soc_hal_re
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[pdev_index]);
- 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++;
+ }
/* For QCA6390, save mac_phy capability in the same pdev */
if (soc->hw_params.single_pdev_only)
@@ -4337,8 +4342,9 @@ static int ath11k_wmi_tlv_dma_ring_caps(
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;
@@ -5974,18 +5980,25 @@ static int ath11k_reg_chan_list_event(st
goto mem_free;
}
- pdev_idx = reg_info->phy_id;
-
- if (pdev_idx >= ab->num_radios) {
- /* Process the event for phy0 only if single_pdev_only
- * is true. If pdev_idx is valid but not 0, discard the
- * event. Otherwise, it goes to fallback.
- */
- if (ab->hw_params.single_pdev_only &&
- pdev_idx < ab->hw_params.num_rxmda_per_pdev)
- goto mem_free;
- else
+ 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) {
+ /* Process the event for phy0 only if single_pdev_only
+ * is true. If pdev_idx is valid but not 0, discard the
+ * event. Otherwise, it goes to fallback.
+ */
+ if (ab->hw_params.single_pdev_only &&
+ pdev_idx < ab->hw_params.num_rxmda_per_pdev)
+ goto mem_free;
+ else
+ goto fallback;
+ }
}
/* Avoid multiple overwrites to default regd, during core
@@ -7206,16 +7219,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));
@@ -7226,7 +7255,10 @@ static int ath11k_connect_pdev_htc_servi
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) {
--- 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;
@@ -82,6 +83,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 {
@@ -91,7 +94,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
};
@@ -100,13 +104,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
};
@@ -2769,6 +2774,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
--- a/drivers/net/wireless/ath/ath11k/hw.h
+++ b/drivers/net/wireless/ath/ath11k/hw.h
@@ -169,7 +169,7 @@ struct ath11k_hw_params {
};
struct ath11k_hw_ops {
- u8 (*get_hw_mac_from_pdev_id)(int pdev_id);
+ u8 (*get_hw_mac_from_pdev_id)(struct ath11k_hw_params *hw, int pdev_id);
void (*wmi_init_config)(struct ath11k_base *ab,
struct target_resource_config *config);
int (*mac_id_to_pdev_id)(struct ath11k_hw_params *hw, int mac_id);
@@ -222,7 +222,7 @@ int ath11k_hw_get_mac_from_pdev_id(struc
int pdev_idx)
{
if (hw->hw_ops->get_hw_mac_from_pdev_id)
- return hw->hw_ops->get_hw_mac_from_pdev_id(pdev_idx);
+ return hw->hw_ops->get_hw_mac_from_pdev_id(hw, pdev_idx);
return 0;
}