From 6f51430f2614ca2fb2a1e45cc81464c6d7a29f03 Mon Sep 17 00:00:00 2001 From: Sathishkumar Muruganandam Date: Fri, 8 Jan 2021 00:34:09 +0530 Subject: [PATCH 2/3] ath11k: extend ext vdev in NSS for dynamic VLAN handling - add ext vdev NSS API callbacks required for dynamic AP_VLAN vif - existing ext vdev NSS API callbacks are used for both WDS and dynamic VLAN di_types. Signed-off-by: Sathishkumar Muruganandam --- drivers/net/wireless/ath/ath11k/nss.c | 101 +++++++++++++++++++++++++++++++--- drivers/net/wireless/ath/ath11k/nss.h | 17 ++++++ 2 files changed, 109 insertions(+), 9 deletions(-) --- a/drivers/net/wireless/ath/ath11k/nss.c +++ b/drivers/net/wireless/ath/ath11k/nss.c @@ -1483,14 +1483,11 @@ static int ath11k_nss_ext_vdev_register( struct ath11k *ar = arvif->ar; struct ath11k_base *ab = ar->ab; nss_tx_status_t status; - enum nss_dynamic_interface_type di_type; u32 features = 0; if (arvif->vif->type != NL80211_IFTYPE_AP_VLAN || arvif->nss.ctx) return -EINVAL; - di_type = NSS_DYNAMIC_INTERFACE_TYPE_WIFI_EXT_VDEV_WDS; - arvif->nss.ctx = nss_wifi_ext_vdev_register_if(arvif->nss.if_num, ath11k_nss_ext_vdev_data_receive, ath11k_nss_ext_vdev_special_data_receive, @@ -1518,7 +1515,8 @@ static void ath11k_nss_ext_vdev_free(str status = nss_dynamic_interface_dealloc_node( arvif->nss.if_num, - NSS_DYNAMIC_INTERFACE_TYPE_WIFI_EXT_VDEV_WDS); + arvif->nss.di_type); + if (status != NSS_TX_SUCCESS) ath11k_warn(ab, "failed to free nss ext vdev err:%d\n", status); @@ -1527,14 +1525,19 @@ static void ath11k_nss_ext_vdev_free(str "nss ext vdev interface deallocated\n"); } -static int ath11k_nss_ext_vdev_alloc(struct ath11k_vif *arvif) +static int ath11k_nss_ext_vdev_alloc(struct ath11k_vif *arvif, + struct wireless_dev *wdev) { struct ath11k_base *ab = arvif->ar->ab; enum nss_dynamic_interface_type di_type; int if_num; - di_type = NSS_DYNAMIC_INTERFACE_TYPE_WIFI_EXT_VDEV_WDS; + if (wdev->use_4addr) + di_type = NSS_DYNAMIC_INTERFACE_TYPE_WIFI_EXT_VDEV_WDS; + else + di_type = NSS_DYNAMIC_INTERFACE_TYPE_WIFI_EXT_VDEV_VLAN; + arvif->nss.di_type = di_type; if_num = nss_dynamic_interface_alloc_node(di_type); if (if_num < 0) { ath11k_warn(ab, "failed to allocate nss ext vdev\n"); @@ -1543,8 +1546,8 @@ static int ath11k_nss_ext_vdev_alloc(str arvif->nss.if_num = if_num; ath11k_dbg(ab, ATH11K_DBG_NSS_WDS, - "nss ext vdev interface %pM allocated if_num %d\n", - arvif->vif->addr, if_num); + "nss ext vdev interface %pM di_type %d allocated if_num %d\n", + arvif->vif->addr, di_type, if_num); return 0; } @@ -1573,7 +1576,7 @@ int ath11k_nss_ext_vdev_create(struct at return -EINVAL; } - ret = ath11k_nss_ext_vdev_alloc(arvif); + ret = ath11k_nss_ext_vdev_alloc(arvif, wdev); if (ret) return ret; @@ -1684,6 +1687,86 @@ free: return ret; } +int ath11k_nss_ext_vdev_cfg_dyn_vlan(struct ath11k_vif *arvif, u16 vlan_id) +{ + struct ath11k *ar = arvif->ar; + struct nss_wifi_ext_vdev_msg *ext_vdev_msg = NULL; + struct nss_wifi_ext_vdev_vlan_msg *cfg_dyn_vlan_msg = NULL; + nss_tx_status_t status; + int ret; + + if (!ar->ab->nss.enabled) + return 0; + + if (arvif->vif->type != NL80211_IFTYPE_AP_VLAN) + return -EINVAL; + + ext_vdev_msg = kzalloc(sizeof(struct nss_wifi_ext_vdev_msg), GFP_ATOMIC); + if (!ext_vdev_msg) + return -ENOMEM; + + cfg_dyn_vlan_msg = &ext_vdev_msg->msg.vmsg; + cfg_dyn_vlan_msg->vlan_id = vlan_id; + + nss_wifi_ext_vdev_msg_init(ext_vdev_msg, arvif->nss.if_num, + NSS_WIFI_EXT_VDEV_MSG_CONFIGURE_VLAN, + sizeof(struct nss_wifi_ext_vdev_vlan_msg), + NULL, arvif); + + status = nss_wifi_ext_vdev_tx_msg_sync(arvif->nss.ctx, ext_vdev_msg); + if (status != NSS_TX_SUCCESS) { + ath11k_warn(ar->ab, "failed to configure dyn vlan nss_err:%d\n", + status); + ret = -EINVAL; + goto free; + } + + ret = 0; +free: + kfree(ext_vdev_msg); + + return ret; +} + +int ath11k_nss_dyn_vlan_set_group_key(struct ath11k_vif *arvif, u16 vlan_id, + u16 group_key) +{ + struct nss_wifi_vdev_msg *vdev_msg = NULL; + struct nss_wifi_vdev_set_vlan_group_key *vlan_group_key; + struct ath11k *ar = arvif->ar; + nss_tx_status_t status; + int ret = 0; + + if (!ar->ab->nss.enabled) + return 0; + + vdev_msg = kzalloc(sizeof(struct nss_wifi_vdev_msg), GFP_ATOMIC); + if (!vdev_msg) + return -ENOMEM; + + vlan_group_key = &vdev_msg->msg.vlan_group_key; + vlan_group_key->vlan_id = vlan_id; + vlan_group_key->group_key = group_key; + + nss_wifi_vdev_msg_init(vdev_msg, arvif->nss.if_num, + NSS_WIFI_VDEV_SET_GROUP_KEY, + sizeof(struct nss_wifi_vdev_set_vlan_group_key), + NULL, NULL); + + status = nss_wifi_vdev_tx_msg(ar->nss.ctx, vdev_msg); + if (status != NSS_TX_SUCCESS) { + ath11k_warn(ar->ab, "nss vdev set vlan group key error %d\n", status); + ret = -EINVAL; + goto free; + } + + ath11k_dbg(ar->ab, ATH11K_DBG_NSS_WDS, "nss vdev set vlan group key success\n"); +free: + kfree(vdev_msg); + return ret; + +} + /*----------------------------Peer Setup/Config -----------------------------*/ int ath11k_nss_set_peer_sec_type(struct ath11k *ar, --- a/drivers/net/wireless/ath/ath11k/nss.h +++ b/drivers/net/wireless/ath/ath11k/nss.h @@ -150,6 +150,8 @@ struct arvif_nss { bool added; /* Flag to notify if ext vdev is up/down */ bool ext_vdev_up; + /* Keep the copy of di_type for nss */ + enum nss_dynamic_interface_type di_type; /* WDS cfg should be done only once for ext vdev */ bool wds_cfg_done; bool created; @@ -215,6 +217,9 @@ void ath11k_nss_ext_vdev_unregister(stru int ath11k_nss_ext_vdev_up(struct ath11k_vif *arvif); int ath11k_nss_ext_vdev_down(struct ath11k_vif *arvif); void ath11k_nss_ext_vdev_delete(struct ath11k_vif *arvif); +int ath11k_nss_ext_vdev_cfg_dyn_vlan(struct ath11k_vif *arvif, u16 vlan_id); +int ath11k_nss_dyn_vlan_set_group_key(struct ath11k_vif *arvif, u16 vlan_id, + u16 group_key); int ath11k_nss_set_peer_sec_type(struct ath11k *ar, struct ath11k_peer *peer, struct ieee80211_key_conf *key_conf); void ath11k_nss_update_sta_stats(struct ath11k_vif *arvif, @@ -343,6 +348,18 @@ static inline int ath11k_nss_ext_vdev_do { return 0; } + +static inline int ath11k_nss_ext_vdev_cfg_dyn_vlan(struct ath11k_vif *arvif, + u16 vlan_id) +{ + return 0; +} + +static inline int ath11k_nss_dyn_vlan_set_group_key(struct ath11k_vif *arvif, + u16 vlan_id, u16 group_key) +{ + return 0; +} static inline void ath11k_nss_peer_stats_enable(struct ath11k *ar) {