* [PATCH] ath10k:New interface to get interface combinations from FW
@ 2019-07-02 6:59 Zhonglin Zhang
2019-09-26 13:58 ` Kalle Valo
0 siblings, 1 reply; 2+ messages in thread
From: Zhonglin Zhang @ 2019-07-02 6:59 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless, Zhonglin Zhang
New wmi event "WMI_TLV_IFACE_COMBINATION_EVENTID" is used.
If WMI_SERVICE_IFACE_COMBINATION_SUPPORT service bit set and
WMI_TLV_IFACE_COMBINATION_EVENTID event got from FW side, then
interface combinations reported from FW will override the default
combinations which is hard-coded in host drivers.
Tested HW: WCN3990
Tested FW: WLAN.HL.3.1-01061-QCAHLSWMTPL-1
Signed-off-by: Zhonglin Zhang <zhonglin@codeaurora.org>
---
drivers/net/wireless/ath/ath10k/core.c | 2 +
drivers/net/wireless/ath/ath10k/core.h | 36 +++++
drivers/net/wireless/ath/ath10k/mac.c | 12 ++
drivers/net/wireless/ath/ath10k/wmi-tlv.c | 183 ++++++++++++++++++++++-
drivers/net/wireless/ath/ath10k/wmi-tlv.h | 232 ++++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath10k/wmi.h | 2 +
6 files changed, 466 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index dc45d16..29d558a 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -3210,6 +3210,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
ath10k_core_set_coverage_class_work);
init_dummy_netdev(&ar->napi_dev);
+ ath10k_init_iface_comb(ar);
ret = ath10k_coredump_create(ar);
if (ret)
@@ -3248,6 +3249,7 @@ void ath10k_core_destroy(struct ath10k *ar)
ath10k_coredump_destroy(ar);
ath10k_htt_tx_destroy(&ar->htt);
ath10k_wmi_free_host_mem(ar);
+ ath10k_deinit_iface_comb(ar);
ath10k_mac_destroy(ar);
}
EXPORT_SYMBOL(ath10k_core_destroy);
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 4d7db07..4ec7517 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -40,6 +40,9 @@
#define ATH10K_NUM_CHANS 41
#define ATH10K_MAX_5G_CHAN 173
+#define MAX_NUM_IFACE_COMBINATIONS 16
+#define BEACON_TX_OFFLOAD_MAX_VDEV 2
+
/* Antenna noise floor */
#define ATH10K_DEFAULT_NOISE_FLOOR -95
@@ -940,6 +943,13 @@ struct ath10k_bus_params {
bool hl_msdu_ids;
};
+struct ath10k_iface_comb {
+ struct ieee80211_iface_combination combo[MAX_NUM_IFACE_COMBINATIONS];
+ u16 combo_sz;
+ u16 interface_modes;
+ u32 beacon_tx_offload_max_vdev;
+};
+
struct ath10k {
struct ath_common ath_common;
struct ieee80211_hw *hw;
@@ -1211,10 +1221,36 @@ struct ath10k {
struct ath10k_bus_params bus_param;
struct completion peer_delete_done;
+ /* iface combination */
+ struct ath10k_iface_comb iface;
+
/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
};
+static inline void ath10k_init_iface_comb(struct ath10k *ar)
+{
+ memset(&ar->iface, 0, sizeof(struct ath10k_iface_comb));
+ ar->iface.beacon_tx_offload_max_vdev = BEACON_TX_OFFLOAD_MAX_VDEV;
+}
+
+static inline void ath10k_deinit_iface_comb(struct ath10k *ar)
+{
+ int i;
+
+ for (i = 0; i < ar->iface.combo_sz; i++) {
+ kfree(ar->iface.combo[i].limits);
+ ar->iface.combo[i].limits = NULL;
+ }
+}
+
+static inline void ath10k_iface_comb_assignment(struct ath10k *ar)
+{
+ ar->hw->wiphy->iface_combinations = ar->iface.combo;
+ ar->hw->wiphy->n_iface_combinations = ar->iface.combo_sz;
+ ar->hw->wiphy->interface_modes = ar->iface.interface_modes;
+}
+
static inline bool ath10k_peer_stats_enabled(struct ath10k *ar)
{
if (test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags) &&
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index e43a566..0e90f30 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -8913,6 +8913,18 @@ int ath10k_mac_register(struct ath10k *ar)
ARRAY_SIZE(ath10k_tlv_if_comb);
}
ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
+
+ if (test_bit
+ (WMI_SERVICE_IFACE_COMBINATION_SUPPORT, ar->wmi.svc_map)) {
+ /**
+ * If combo_sz is not ZERO, it means that host will use
+ * iface_combinations reported from FW.
+ */
+ if (ar->iface.combo_sz)
+ ath10k_iface_comb_assignment(ar);
+ else
+ ath10k_warn(ar, "iface combination event missing!\n");
+ }
break;
case ATH10K_FW_WMI_OP_VERSION_10_1:
case ATH10K_FW_WMI_OP_VERSION_10_2:
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index 2985bb1..ce89e96 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -64,6 +64,12 @@ static const struct wmi_tlv_policy wmi_tlv_policies[] = {
= { .min_len = sizeof(struct wmi_tlv_wow_event_info) },
[WMI_TLV_TAG_STRUCT_TX_PAUSE_EVENT]
= { .min_len = sizeof(struct wmi_tlv_tx_pause_ev) },
+ [WMI_TLV_TAG_STRUCT_IFACE_COMBINATION_IND_EVENT]
+ = { .min_len = sizeof(struct wmi_tlv_iface_combination_event) },
+ [WMI_TLV_TAG_STRUCT_IFACE_COMBINATION]
+ = { .min_len = sizeof(struct wmi_tlv_iface_combination) },
+ [WMI_TLV_TAG_STRUCT_IFACE_LIMIT]
+ = { .min_len = sizeof(struct wmi_tlv_iface_limit) },
};
static int
@@ -483,6 +489,177 @@ static int ath10k_wmi_tlv_event_peer_delete_resp(struct ath10k *ar,
return 0;
}
+static u16 ath10k_wmi_tlv_vdev_type_remap(struct wmi_tlv_iface_limit *limit)
+{
+ u32 vdev_has_type = __le32_to_cpu(limit->vdev_type);
+ u32 vdev_has_subtype = __le32_to_cpu(limit->vdev_subtype);
+ u16 type = 0;
+
+ if (vdev_has_subtype) {
+ if (vdev_has_subtype & BIT(WMI_VDEV_SUBTYPE_P2P_DEVICE))
+ type |= BIT(NL80211_IFTYPE_P2P_DEVICE);
+ if (vdev_has_subtype & BIT(WMI_VDEV_SUBTYPE_P2P_CLIENT))
+ type |= BIT(NL80211_IFTYPE_P2P_CLIENT);
+ if (vdev_has_subtype & BIT(WMI_VDEV_SUBTYPE_P2P_GO))
+ type |= BIT(NL80211_IFTYPE_P2P_GO);
+ } else {
+ if (vdev_has_type & BIT(WMI_VDEV_TYPE_AP))
+ type |= BIT(NL80211_IFTYPE_AP);
+ if (vdev_has_type & BIT(WMI_VDEV_TYPE_STA))
+ type |= BIT(NL80211_IFTYPE_STATION);
+ if (vdev_has_type & BIT(WMI_VDEV_TYPE_IBSS))
+ type |= BIT(NL80211_IFTYPE_ADHOC);
+ }
+
+ return type;
+}
+
+static int ath10k_wmi_tlv_iface_comb_parse(struct ath10k *ar, u16 tag, u16 len,
+ const void *ptr, void *data)
+{
+ int ret = 0;
+ unsigned long valid_fields = 0;
+ struct wmi_tlv_iface_comb_parse *p = data;
+ struct ieee80211_iface_combination *comb = &ar->iface.combo[0];
+ struct ieee80211_iface_limit *limit = NULL;
+
+ switch (tag) {
+ case WMI_TLV_TAG_STRUCT_IFACE_COMBINATION_IND_EVENT:
+ p->ev = (struct wmi_tlv_iface_combination_event *)ptr;
+ break;
+ case WMI_TLV_TAG_ARRAY_STRUCT:
+ ret = ath10k_wmi_tlv_iter(ar, ptr, len,
+ ath10k_wmi_tlv_iface_comb_parse, p);
+ break;
+ case WMI_TLV_TAG_STRUCT_IFACE_COMBINATION:
+ p->combs = (struct wmi_tlv_iface_combination *)ptr;
+
+ if (p->n_combs >= MAX_NUM_IFACE_COMBINATIONS) {
+ ath10k_warn(ar, "Exceed Max Num Iface Combinations!\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ valid_fields = __le32_to_cpu(p->combs->valid_fields);
+
+ if (test_bit(WMI_TLV_IFACE_COMB_BCN_INT_MATCH_VALID_BIT,
+ &valid_fields))
+ comb[p->n_combs].beacon_int_infra_match =
+ __le32_to_cpu(p->combs->beacon_int_infra_match);
+
+ if (test_bit(WMI_TLV_IFACE_COMB_BCN_INT_MIN_GCD_VALID_BIT,
+ &valid_fields))
+ comb[p->n_combs].beacon_int_min_gcd =
+ __le32_to_cpu(p->combs->beacon_int_min_gcd);
+
+ comb[p->n_combs].limits =
+ kcalloc(p->combs->limits_n, sizeof(*limit), GFP_ATOMIC);
+ if (!comb[p->n_combs].limits) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ p->n_combs++;
+ ar->iface.combo_sz++;
+ break;
+ case WMI_TLV_TAG_STRUCT_IFACE_LIMIT:
+ p->limits = (struct wmi_tlv_iface_limit *)ptr;
+
+ /**
+ * p->comb_index: current iface combo index, default value 0
+ * comb[p->comb_index]: current iface comb
+ * p->limit_index: point to the next available iface limit slot,
+ * limit_index default value 0.
+ * comb[p->comb_index].n_limits: num of limits of this
+ * comb_index. n_limits value got from
+ * WMI_TLV_TAG_STRUCT_IFACE_COMBINATION assignment.
+ *
+ * So the logic here:
+ * 0) Basic precondition now we have got all comb(s) in
+ * WMI_TLV_TAG_STRUCT_IFACE_COMBINATION assignment.
+ * 1) if (limit_index >= n_limits of current iface combo, then
+ * this new iface limit will belong to a new iface combo. So
+ * update the index
+ * a. comb_index++ and limit_index reset as 0.
+ * b. comb_fill_max_interfaces point to the current iface
+ * combo to fill max_interfaces field. And its default
+ * value should point to the first iface combo.
+ * 2) Use combo_index/limit_index to do assignment, and finally
+ * limit_index++ to point to the next available limit slot.
+ * 3) Loop to 1) when find new iface limit, else exit the parse
+ * procedure.
+ */
+ if (p->limit_index >= comb[p->comb_index].n_limits) {
+ p->comb_index++;
+ p->limit_index = 0;
+ p->comb_fill_max_interfaces = &comb[p->comb_index];
+ }
+
+ limit = (struct ieee80211_iface_limit *)
+ &comb[p->comb_index].limits[p->limit_index];
+ limit->max = __le32_to_cpu(p->limits->vdev_limit_n);
+ limit->types = ath10k_wmi_tlv_vdev_type_remap(p->limits);
+ ar->iface.interface_modes |= limit->types;
+
+ /**
+ * ar->iface.beacon_tx_offload_max_vdev default value is 2.
+ * If limit type is AP and
+ * limit->max > ar->iface.beacon_tx_offload_max_vdev, we will
+ * override this value by limit->max. FW needs this value in
+ * WMI_INIT command for beacon offload function.
+ */
+ if ((limit->types & BIT(NL80211_IFTYPE_AP)) &&
+ limit->max > ar->iface.beacon_tx_offload_max_vdev)
+ ar->iface.beacon_tx_offload_max_vdev = limit->max;
+ if (!p->comb_fill_max_interfaces)
+ /* point to the first combination */
+ p->comb_fill_max_interfaces = comb;
+
+ p->comb_fill_max_interfaces->max_interfaces += limit->max;
+
+ p->limit_index++;
+ break;
+ default:
+ break;
+ }
+out:
+ if (ret) {
+ int i;
+
+ for (i = 0; i < p->n_combs; i++) {
+ kfree(comb[i].limits);
+ comb[i].limits = NULL;
+ }
+ }
+ return ret;
+}
+
+static int ath10k_wmi_tlv_iface_combination(struct ath10k *ar,
+ struct sk_buff *skb)
+{
+ int ret;
+ struct wmi_tlv_iface_comb_parse parse;
+
+ if (!test_bit(WMI_SERVICE_IFACE_COMBINATION_SUPPORT, ar->wmi.svc_map))
+ return 0;
+
+ memset(&parse, 0, sizeof(struct wmi_tlv_iface_comb_parse));
+
+ ath10k_deinit_iface_comb(ar);
+ ath10k_init_iface_comb(ar);
+
+ ret = ath10k_wmi_tlv_iter(ar, skb->data, skb->len,
+ ath10k_wmi_tlv_iface_comb_parse, &parse);
+
+ if (ret) {
+ ath10k_warn(ar, "%s:failed to parse tlv: %d\n", __func__, ret);
+ ar->iface.combo_sz = 0;
+ return ret;
+ }
+
+ return 0;
+}
+
/***********/
/* TLV ops */
/***********/
@@ -608,6 +785,9 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
case WMI_TLV_SERVICE_READY_EVENTID:
ath10k_wmi_event_service_ready(ar, skb);
return;
+ case WMI_TLV_IFACE_COMBINATION_EVENTID:
+ ath10k_wmi_tlv_iface_combination(ar, skb);
+ break;
case WMI_TLV_READY_EVENTID:
ath10k_wmi_event_ready(ar, skb);
break;
@@ -1776,7 +1956,8 @@ static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar)
cfg->max_frag_entries = __cpu_to_le32(2);
cfg->num_tdls_vdevs = __cpu_to_le32(TARGET_TLV_NUM_TDLS_VDEVS);
cfg->num_tdls_conn_table_entries = __cpu_to_le32(0x20);
- cfg->beacon_tx_offload_max_vdev = __cpu_to_le32(2);
+ cfg->beacon_tx_offload_max_vdev =
+ __cpu_to_le32(ar->iface.beacon_tx_offload_max_vdev);
cfg->num_multicast_filter_entries = __cpu_to_le32(5);
cfg->num_wow_filters = __cpu_to_le32(ar->wow.max_num_patterns);
cfg->num_keep_alive_pattern = __cpu_to_le32(6);
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
index d691f06..71d7f396 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
@@ -288,6 +288,7 @@ enum wmi_tlv_event_id {
WMI_TLV_SERVICE_READY_EVENTID = 0x1,
WMI_TLV_READY_EVENTID,
WMI_TLV_SERVICE_AVAILABLE_EVENTID,
+ WMI_TLV_IFACE_COMBINATION_EVENTID,
WMI_TLV_SCAN_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_SCAN),
WMI_TLV_PDEV_TPC_CONFIG_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_PDEV),
WMI_TLV_CHAN_INFO_EVENTID,
@@ -1217,6 +1218,121 @@ enum wmi_tlv_tag {
WMI_TLV_TAG_STRUCT_FD_SEND_FROM_HOST_CMD,
WMI_TLV_TAG_STRUCT_ENABLE_FILS_CMD,
WMI_TLV_TAG_STRUCT_HOST_SWFDA_EVENT,
+ WMI_TLV_TAG_STRUCT_BCN_OFFLOAD_CTRL_CMD,
+ WMI_TLV_TAG_STRUCT_PDEV_SET_AC_TXQ_OPTIMIZED_CMD,
+ WMI_TLV_TAG_STRUCT_STATS_PERIOD,
+ WMI_TLV_TAG_STRUCT_NDL_SCHEDULE_UPDATE,
+ WMI_TLV_TAG_STRUCT_PEER_TID_MSDUQ_QDEPTH_THRESH_UPDATE_CMD,
+ WMI_TLV_TAG_STRUCT_MSDUQ_QDEPTH_THRESH_UPDATE,
+ WMI_TLV_TAG_STRUCT_PDEV_SET_RX_FILTER_PROMISCUOUS_CMD,
+ WMI_TLV_TAG_STRUCT_SAR2_RESULT_EVENT,
+ WMI_TLV_TAG_STRUCT_SAR_CAPABILITIES,
+ WMI_TLV_TAG_STRUCT_SAP_OBSS_DETECTION_CFG_CMD,
+ WMI_TLV_TAG_STRUCT_SAP_OBSS_DETECTION_INFO_EVENT,
+ WMI_TLV_TAG_STRUCT_DMA_RING_CAPABILITIES,
+ WMI_TLV_TAG_STRUCT_DMA_RING_CFG_REQ,
+ WMI_TLV_TAG_STRUCT_DMA_RING_CFG_RSP,
+ WMI_TLV_TAG_STRUCT_DMA_BUF_RELEASE,
+ WMI_TLV_TAG_STRUCT_DMA_BUF_RELEASE_ENTRY,
+ WMI_TLV_TAG_STRUCT_SAR_GET_LIMITS_CMD,
+ WMI_TLV_TAG_STRUCT_SAR_GET_LIMITS_EVENT,
+ WMI_TLV_TAG_STRUCT_SAR_GET_LIMITS_EVENT_ROW,
+ WMI_TLV_TAG_STRUCT_OFFLOAD_11K_REPORT,
+ WMI_TLV_TAG_STRUCT_INVOKE_NEIGHBOR_REPORT,
+ WMI_TLV_TAG_STRUCT_NEIGHBOR_REPORT_OFFLOAD_TLV_PARAM,
+ WMI_TLV_TAG_STRUCT_VDEV_SET_CONNECTIVITY_CHECK_STATS,
+ WMI_TLV_TAG_STRUCT_VDEV_GET_CONNECTIVITY_CHECK_STATS,
+ WMI_TLV_TAG_STRUCT_BPF_SET_VDEV_ENABLE_CMD,
+ WMI_TLV_TAG_STRUCT_BPF_SET_VDEV_WORK_MEMORY_CMD,
+ WMI_TLV_TAG_STRUCT_BPF_GET_VDEV_WORK_MEMORY_CMD,
+ WMI_TLV_TAG_STRUCT_BPF_GET_VDEV_WORK_MEMORY_RESP_EVENT,
+ WMI_TLV_TAG_STRUCT_PDEV_GET_NFCAL_POWER,
+ WMI_TLV_TAG_STRUCT_BSS_COLOR_CHANGE_ENABLE,
+ WMI_TLV_TAG_STRUCT_OBSS_COLOR_COLLISION_DET_CONFIG,
+ WMI_TLV_TAG_STRUCT_OBSS_COLOR_COLLISION_EVENT,
+ WMI_TLV_TAG_STRUCT_RUNTIME_DPD_RECAL_CMD,
+ WMI_TLV_TAG_STRUCT_TWT_ENABLE_CMD,
+ WMI_TLV_TAG_STRUCT_TWT_DISABLE_CMD,
+ WMI_TLV_TAG_STRUCT_TWT_ADD_DIALOG_CMD,
+ WMI_TLV_TAG_STRUCT_TWT_DEL_DIALOG_CMD,
+ WMI_TLV_TAG_STRUCT_TWT_PAUSE_DIALOG_CMD,
+ WMI_TLV_TAG_STRUCT_TWT_RESUME_DIALOG_CMD,
+ WMI_TLV_TAG_STRUCT_TWT_ENABLE_COMPLETE_EVENT,
+ WMI_TLV_TAG_STRUCT_TWT_DISABLE_COMPLETE_EVENT,
+ WMI_TLV_TAG_STRUCT_TWT_ADD_DIALOG_COMPLETE_EVENT,
+ WMI_TLV_TAG_STRUCT_TWT_DEL_DIALOG_COMPLETE_EVENT,
+ WMI_TLV_TAG_STRUCT_TWT_PAUSE_DIALOG_COMPLETE_EVENT,
+ WMI_TLV_TAG_STRUCT_TWT_RESUME_DIALOG_COMPLETE_EVENT,
+ WMI_TLV_TAG_STRUCT_REQUEST_ROAM_SCAN_STATS_CMD,
+ WMI_TLV_TAG_STRUCT_ROAM_SCAN_STATS_EVENT,
+ WMI_TLV_TAG_STRUCT_PEER_TID_CONFIGURATIONS_CMD,
+ WMI_TLV_TAG_STRUCT_VDEV_SET_CUSTOM_SW_RETRY_TH_CMD,
+ WMI_TLV_TAG_STRUCT_GET_TPC_POWER_CMD,
+ WMI_TLV_TAG_STRUCT_GET_TPC_POWER_EVENT,
+ WMI_TLV_TAG_STRUCT_DMA_BUF_RELEASE_SPECTRAL_META_DATA,
+ WMI_TLV_TAG_STRUCT_MOTION_DET_CONFIG_PARAMS_CMD,
+ WMI_TLV_TAG_STRUCT_MOTION_DET_BASE_LINE_CONFIG_PARAMS_CMD,
+ WMI_TLV_TAG_STRUCT_MOTION_DET_START_STOP_CMD,
+ WMI_TLV_TAG_STRUCT_MOTION_DET_BASE_LINE_START_STOP_CMD,
+ WMI_TLV_TAG_STRUCT_MOTION_DET_EVENT,
+ WMI_TLV_TAG_STRUCT_MOTION_DET_BASE_LINE_EVENT,
+ WMI_TLV_TAG_STRUCT_NDP_TRANSPORT_IP_PARAM,
+ WMI_TLV_TAG_STRUCT_OBSS_SPATIAL_REUSE_SET_CMD,
+ WMI_TLV_TAG_STRUCT_ESP_ESTIMATE_EVENT,
+ WMI_TLV_TAG_STRUCT_NAN_HOST_CONFIG_PARAM,
+ WMI_TLV_TAG_STRUCT_SPECTRAL_BIN_SCALING_PARAM,
+ WMI_TLV_TAG_STRUCT_PEER_CFR_CAPTURE_CONF_CMD,
+ WMI_TLV_TAG_STRUCT_PEER_CHAN_WIDTH_SWITCH_CMD,
+ WMI_TLV_TAG_STRUCT_CHAN_WIDTH_PEER_LIST,
+ WMI_TLV_TAG_STRUCT_OBSS_SPATIAL_REUSE_SET_DEF_OBSS_THRESH_CMD,
+ WMI_TLV_TAG_STRUCT_PDEV_HE_TB_ACTION_FRM_CMD,
+ WMI_TLV_TAG_STRUCT_PEER_EXTD2_STATS,
+ WMI_TLV_TAG_STRUCT_HPCS_PULSE_START_CMD,
+ WMI_TLV_TAG_STRUCT_PDEV_CTL_FAILSAFE_CHECK_PARAM,
+ WMI_TLV_TAG_STRUCT_VDEV_CHAINMASK_CONFIG_CMD,
+ WMI_TLV_TAG_STRUCT_VDEV_BCN_OFFLOAD_QUIET_CONFIG_CMD,
+ WMI_TLV_TAG_STRUCT_NAN_EVENT_INFO,
+ WMI_TLV_TAG_STRUCT_NDP_CHANNEL_INFO,
+ WMI_TLV_TAG_STRUCT_NDP_CMD,
+ WMI_TLV_TAG_STRUCT_NDP_EVENT,
+ WMI_TLV_TAG_STRUCT_PDEV_PKTLOG_FILTER_CMD,
+ WMI_TLV_TAG_STRUCT_PDEV_PKTLOG_FILTER_INFO,
+ WMI_TLV_TAG_STRUCT_QUIET_OFFLOAD_INFO,
+ WMI_TLV_TAG_STRUCT_GET_BCN_RECV_STATS,
+ WMI_TLV_TAG_STRUCT_VDEV_BCN_RECV_STATS_EVENT,
+ WMI_TLV_TAG_STRUCT_PEER_TX_PN_REQUEST_CMD,
+ WMI_TLV_TAG_STRUCT_PEER_TX_PN_RESPONSE_EVENT,
+ WMI_TLV_TAG_STRUCT_TLV_ARRAYS_LEN_PARAM,
+ WMI_TLV_TAG_STRUCT_PEER_UNMAP_RESPONSE_CMD,
+ WMI_TLV_TAG_STRUCT_PDEV_CSC_SWITCH_COUNT_STATUS_EVENT,
+ WMI_TLV_TAG_STRUCT_ROAM_BSS_LOAD_CONFIG_CMD,
+ WMI_TLV_TAG_STRUCT_ROAM_BLACKLIST_EVENT,
+ WMI_TLV_TAG_STRUCT_CSC_VDEV_LIST,
+ WMI_TLV_TAG_STRUCT_VDEV_GET_MWS_COEX_INFO_CMD,
+ WMI_TLV_TAG_STRUCT_VDEV_GET_MWS_COEX_STATE,
+ WMI_TLV_TAG_STRUCT_VDEV_GET_MWS_COEX_DPWB_STATE,
+ WMI_TLV_TAG_STRUCT_VDEV_GET_MWS_COEX_TDM_STATE,
+ WMI_TLV_TAG_STRUCT_VDEV_GET_MWS_COEX_IDRX_STATE,
+ WMI_TLV_TAG_STRUCT_VDEV_GET_MWS_COEX_ANTENNA_SHARING_STATE,
+ WMI_TLV_TAG_STRUCT_REQUEST_WLM_STATS_CMD,
+ WMI_TLV_TAG_STRUCT_WLM_STATS_EVENT,
+ WMI_TLV_TAG_STRUCT_KEY_MATERIAL_EXT,
+ WMI_TLV_TAG_STRUCT_PEER_CFR_CAPTURE_EVENT,
+ WMI_TLV_TAG_STRUCT_COLD_BOOT_CAL_DATA,
+ WMI_TLV_TAG_STRUCT_PDEV_SET_RAP_CONFIG,
+ WMI_TLV_TAG_STRUCT_PDEV_SET_RAP_CONFIG_ON_STA_PS,
+ WMI_TLV_TAG_STRUCT_PDEV_RAP_INFO_EVENT,
+ WMI_TLV_TAG_STRUCT_STA_TDCC_CONFIG_CMD,
+ WMI_TLV_TAG_STRUCT_ROAM_DEAUTH_CONFIG_CMD,
+ WMI_TLV_TAG_STRUCT_ROAM_IDLE_CONFIG_CMD,
+ WMI_TLV_TAG_STRUCT_IDLE_TRIGGER_MONITOR_CMD,
+ WMI_TLV_TAG_STRUCT_STATS_INTERFERENCE,
+ WMI_TLV_TAG_STRUCT_ROAM_SCORE_DELTA_PARAM,
+ WMI_TLV_TAG_STRUCT_ROAM_CND_MIN_RSSI_PARAM,
+ WMI_TLV_TAG_STRUCT_CHAN_RF_CHARACTERIZATION_INFO,
+ WMI_TLV_TAG_STRUCT_IFACE_COMBINATION_IND_EVENT,
+ WMI_TLV_TAG_STRUCT_IFACE_COMBINATION,
+ WMI_TLV_TAG_STRUCT_IFACE_LIMIT,
WMI_TLV_TAG_MAX
};
@@ -1409,6 +1525,7 @@ enum wmi_tlv_service {
WMI_TLV_SERVICE_WLAN_HPCS_PULSE = 172,
WMI_TLV_SERVICE_PER_VDEV_CHAINMASK_CONFIG_SUPPORT = 173,
WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI = 174,
+ WMI_TLV_SERVICE_IFACE_COMBINATION_SUPPORT = 209,
WMI_TLV_MAX_EXT_SERVICE = 256,
};
@@ -1588,6 +1705,8 @@ wmi_tlv_svc_map_ext(const __le32 *in, unsigned long *out, size_t len)
WMI_TLV_MAX_SERVICE);
SVCMAP(WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI,
WMI_SERVICE_TX_DATA_ACK_RSSI, WMI_TLV_MAX_SERVICE);
+ SVCMAP(WMI_TLV_SERVICE_IFACE_COMBINATION_SUPPORT,
+ WMI_SERVICE_IFACE_COMBINATION_SUPPORT, WMI_TLV_MAX_SERVICE);
}
#undef SVCMAP
@@ -2483,4 +2602,117 @@ struct wmi_tlv_mgmt_tx_cmd {
__le32 frame_len;
__le32 buf_len;
} __packed;
+
+struct wmi_tlv_iface_combination_event {
+ /* common part */
+ __le32 pdev_n;
+
+ /* iface combination part
+ * wmi_tlv_iface_combinations[] will follow.
+ * 1. iface combinations:
+ * wmi_tlv_iface_combination combinations[0];
+ * wmi_tlv_iface_combination combinations[.];
+ * wmi_tlv_iface_combination combinations[m];
+ * ===========================================
+ * 2. limits for all combinations:
+ * 2.1 limits for first combination:
+ * wmi_tlv_iface_limit limits[0];
+ * wmi_tlv_iface_limit limits[vdev_limit_n - 1];
+ * -------------------------------------------
+ * 2.2 limits for next combination:
+ * wmi_tlv_iface_limit limits[i];
+ * wmi_tlv_iface_limit limits[vdev_limit_n - 1];
+ * -------------------------------------------
+ * 2.3 limits for the last combination:
+ * wmi_tlv_iface_limit limits[m];
+ * wmi_tlv_iface_limit limits[vdev_limit_n - 1];
+ */
+} __packed;
+
+struct wmi_tlv_iface_limit {
+ /**
+ * How many vdevs can work as below vdev_type/vdev_subtype
+ * in one combination
+ */
+ __le32 vdev_limit_n;
+
+ /* Indicate what role above vdev can work as
+ * Refer to "WMI_VDEV_TYPE_xx, WMI_VDEV_SUBTYPE_xx
+ * for role definition
+ */
+ __le32 vdev_type;
+ __le32 vdev_subtype;
+} __packed;
+
+#define WMI_TLV_IFACE_COMB_PEER_MAX_VALID_BIT 0
+#define WMI_TLV_IFACE_COMB_BCN_INT_MATCH_VALID_BIT 1
+#define WMI_TLV_IFACE_COMB_BCN_INT_MIN_GCD_VALID_BIT 2
+#define WMI_TLV_IFACE_COMB_NUM_UNIQUE_BI_VALID_BIT 3
+
+struct wmi_tlv_iface_combination {
+ /**
+ * Max num peers can be supported in this combination.
+ * It excludes the self-peers associated with each vdev.
+ * It's the number of real remote peers.
+ * eg: when working as AP mode, indicating how many clients can be
+ * supported to connect with this AP.
+ */
+ __le32 peer_max;
+ /**
+ * Home channels supported on one single phy concurrently
+ */
+ __le32 channel_n;
+ /**
+ * The number of "wmi_tlv_iface_limit" for a specified combination.
+ */
+ __le32 limits_n;
+ /**
+ * Beacon intervals between infrastructure and AP types must match
+ * or not.
+ * 1: need match
+ * 0: not need
+ */
+ __le32 beacon_int_infra_match;
+ /**
+ * This interface (vdev) combination supports different beacon
+ * intervals.
+ *
+ * = 0
+ * all beacon intervals for different interface must be same.
+ * > 0
+ * any beacon interval for the interface part of this combination AND
+ * GCD of all beacon intervals from beaconing interfaces of this
+ * combination must be greater or equal to this value.
+ */
+ __le32 beacon_int_min_gcd;
+ /**
+ * Number of different beacon intervals supported.
+ */
+ __le32 num_unique_bi;
+ /**
+ * This indicates which field contains valid value from FW side.
+ * All fields except channel_n and limits_n are optional.
+ */
+ __le32 valid_fields;
+} __packed;
+
+/**
+ * It is to save the parse status. Through the parse procedure,
+ * iface_combinations info will be got finally.
+ */
+struct wmi_tlv_iface_comb_parse {
+ struct wmi_tlv_iface_combination_event *ev;
+ struct wmi_tlv_iface_combination *combs;
+ struct wmi_tlv_iface_limit *limits;
+ /* for combos fill */
+ int n_combs;
+ struct ieee80211_iface_combination *comb_fill_max_interfaces;
+
+ /* for limits fill
+ * comb_index point to the current combo
+ * limit_index point to the next available limit slot
+ */
+ int comb_index;
+ int limit_index;
+};
#endif
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 838768c..cdba117 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -202,6 +202,7 @@ enum wmi_service {
WMI_SERVICE_REPORT_AIRTIME,
WMI_SERVICE_SYNC_DELETE_CMDS,
WMI_SERVICE_TX_PWR_PER_PEER,
+ WMI_SERVICE_IFACE_COMBINATION_SUPPORT,
/* Remember to add the new value to wmi_service_name()! */
@@ -496,6 +497,7 @@ static inline char *wmi_service_name(enum wmi_service service_id)
SVCSTR(WMI_SERVICE_REPORT_AIRTIME);
SVCSTR(WMI_SERVICE_SYNC_DELETE_CMDS);
SVCSTR(WMI_SERVICE_TX_PWR_PER_PEER);
+ SVCSTR(WMI_SERVICE_IFACE_COMBINATION_SUPPORT);
case WMI_SERVICE_MAX:
return NULL;
--
2.7.4
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] ath10k:New interface to get interface combinations from FW
2019-07-02 6:59 [PATCH] ath10k:New interface to get interface combinations from FW Zhonglin Zhang
@ 2019-09-26 13:58 ` Kalle Valo
0 siblings, 0 replies; 2+ messages in thread
From: Kalle Valo @ 2019-09-26 13:58 UTC (permalink / raw)
To: Zhonglin Zhang; +Cc: ath10k, linux-wireless, Zhonglin Zhang
Zhonglin Zhang <zhonglin@codeaurora.org> wrote:
> New wmi event "WMI_TLV_IFACE_COMBINATION_EVENTID" is used.
> If WMI_SERVICE_IFACE_COMBINATION_SUPPORT service bit set and
> WMI_TLV_IFACE_COMBINATION_EVENTID event got from FW side, then
> interface combinations reported from FW will override the default
> combinations which is hard-coded in host drivers.
>
> Tested HW: WCN3990
> Tested FW: WLAN.HL.3.1-01061-QCAHLSWMTPL-1
>
> Signed-off-by: Zhonglin Zhang <zhonglin@codeaurora.org>
> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
This introduced a new warning:
drivers/net/wireless/ath/ath10k/wmi-tlv.c:556:41: warning: incorrect type in argument 1 (different base types)
drivers/net/wireless/ath/ath10k/wmi-tlv.c:556:41: expected unsigned long [usertype] n
drivers/net/wireless/ath/ath10k/wmi-tlv.c:556:41: got restricted __le32 [usertype] limits_n
I fixed that in the pending branch.
--
https://patchwork.kernel.org/patch/11027361/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2019-09-26 13:58 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-02 6:59 [PATCH] ath10k:New interface to get interface combinations from FW Zhonglin Zhang
2019-09-26 13:58 ` Kalle Valo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).