mirror of
https://github.com/breeze303/openwrt-ipq.git
synced 2025-12-16 20:41:05 +00:00
689 lines
21 KiB
Diff
689 lines
21 KiB
Diff
From d4c3b17e66243a2d6d8845192453ef7da568bac2 Mon Sep 17 00:00:00 2001
|
|
From: Sathishkumar Muruganandam <murugana@codeaurora.org>
|
|
Date: Thu, 10 Sep 2020 15:58:53 +0530
|
|
Subject: [PATCH 1/2] ath11k: add WDS offload changes to NSS driver interface
|
|
|
|
add WDS and MEC AST handling to NSS
|
|
|
|
Signed-off-by: Sathishkumar Muruganandam <murugana@codeaurora.org>
|
|
---
|
|
drivers/net/wireless/ath/ath11k/nss.c | 465 ++++++++++++++++++++++++++++++++--
|
|
drivers/net/wireless/ath/ath11k/nss.h | 36 ++-
|
|
2 files changed, 473 insertions(+), 28 deletions(-)
|
|
|
|
--- a/drivers/net/wireless/ath/ath11k/nss.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/nss.c
|
|
@@ -307,6 +307,22 @@ void ath11k_nss_wifili_event_receive(str
|
|
case NSS_WIFILI_TID_REOQ_SETUP_MSG:
|
|
/* TODO setup tidq */
|
|
break;
|
|
+ case NSS_WIFILI_WDS_PEER_ADD_MSG:
|
|
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS, "nss wifili wds peer add event received %d response %d error %d\n",
|
|
+ msg_type, response, error);
|
|
+ break;
|
|
+ case NSS_WIFILI_WDS_PEER_UPDATE_MSG:
|
|
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS, "nss wifili wds peer update event received %d response %d error %d\n",
|
|
+ msg_type, response, error);
|
|
+ break;
|
|
+ case NSS_WIFILI_WDS_PEER_MAP_MSG:
|
|
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS, "nss wifili wds peer map event received %d response %d error %d\n",
|
|
+ msg_type, response, error);
|
|
+ break;
|
|
+ case NSS_WIFILI_WDS_PEER_DEL_MSG:
|
|
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS, "nss wifili wds peer del event received %d response %d error %d\n",
|
|
+ msg_type, response, error);
|
|
+ break;
|
|
default:
|
|
ath11k_dbg(ab, ATH11K_DBG_NSS, "unhandled event %d\n", msg_type);
|
|
break;
|
|
@@ -417,13 +433,6 @@ static void ath11k_nss_vdev_event_receiv
|
|
/*TODO*/
|
|
}
|
|
|
|
-static void
|
|
-ath11k_nss_vdev_special_data_receive(struct net_device *dev, struct sk_buff *skb,
|
|
- __attribute__((unused)) struct napi_struct *napi)
|
|
-{
|
|
- /* TODO */
|
|
-}
|
|
-
|
|
/* TODO: move to mac80211 after cleanups/refactoring required after feature completion */
|
|
static int ath11k_nss_deliver_rx(struct ieee80211_vif *vif, struct sk_buff *skb,
|
|
bool eth, int data_offs, struct napi_struct *napi)
|
|
@@ -547,11 +556,239 @@ static int ath11k_nss_undecap_nwifi(stru
|
|
return 0;
|
|
}
|
|
|
|
+static void ath11k_nss_wds_type_rx(struct ath11k *ar, u8* src_mac, u8 is_sa_valid,
|
|
+ u8 addr4_valid, u16 peer_id)
|
|
+{
|
|
+ struct ath11k_base *ab = ar->ab;
|
|
+ struct ath11k_ast_entry *ast_entry = NULL;
|
|
+ struct ath11k_peer *ta_peer = NULL;
|
|
+
|
|
+ spin_lock_bh(&ab->base_lock);
|
|
+ ta_peer = ath11k_peer_find_by_id(ab, peer_id);
|
|
+
|
|
+ if (!ta_peer) {
|
|
+ spin_unlock_bh(&ab->base_lock);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS,"ath11k_nss_wds_type_rx ta_peer %pM\n",
|
|
+ ta_peer->addr);
|
|
+
|
|
+ if (addr4_valid) {
|
|
+ ast_entry = ath11k_peer_ast_find_by_addr(ab, src_mac);
|
|
+ if (!is_sa_valid) {
|
|
+ ath11k_peer_add_ast(ar, ta_peer, src_mac,
|
|
+ ATH11K_AST_TYPE_WDS);
|
|
+ ath11k_nss_add_wds_peer(ar, ta_peer,
|
|
+ src_mac, ATH11K_AST_TYPE_WDS);
|
|
+ } else {
|
|
+ if (!ast_entry) {
|
|
+ ath11k_peer_add_ast(ar, ta_peer, src_mac,
|
|
+ ATH11K_AST_TYPE_WDS);
|
|
+ ath11k_nss_add_wds_peer(ar, ta_peer, src_mac,
|
|
+ ATH11K_AST_TYPE_WDS);
|
|
+ } else {
|
|
+ ath11k_peer_update_ast(ar, ta_peer, ast_entry);
|
|
+ ath11k_nss_update_wds_peer(ar, ta_peer, src_mac);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ spin_unlock_bh(&ab->base_lock);
|
|
+}
|
|
+
|
|
+static void ath11k_nss_mec_handler(struct ath11k *ar, u8* mec_mac_addr)
|
|
+{
|
|
+ struct ath11k_base *ab = ar->ab;
|
|
+ struct ath11k_peer *peer = ar->bss_peer;
|
|
+ u8 mac_addr[ETH_ALEN];
|
|
+ u32 *mac_addr_l32;
|
|
+ u16 *mac_addr_h16;
|
|
+
|
|
+ if (!peer)
|
|
+ return;
|
|
+
|
|
+ /* mec_mac_addr has the swapped mac_addr after 4 bytes (sizeof(u32))
|
|
+ * mec_mac_addr[0]
|
|
+ * |
|
|
+ * 03:0a:00:00:2d:15:22:f0:fd:8c
|
|
+ * ^
|
|
+ * Swapped MAC address present after 4 bytes
|
|
+ * MAC address after swapping is 8c:fd:f0:22:15:2d */
|
|
+
|
|
+ mac_addr_l32 = (u32 *) (mec_mac_addr + sizeof(u32));
|
|
+ mac_addr_h16 = (u16 *) (mec_mac_addr + sizeof(u32) + sizeof(u32));
|
|
+
|
|
+ *mac_addr_l32 = swab32(*mac_addr_l32);
|
|
+ *mac_addr_h16 = swab16(*mac_addr_h16);
|
|
+
|
|
+ memcpy(mac_addr, mac_addr_h16, ETH_ALEN - 4);
|
|
+ memcpy(mac_addr + 2, mac_addr_l32, 4);
|
|
+
|
|
+ if (!ether_addr_equal(ar->mac_addr, mac_addr)) {
|
|
+ spin_lock_bh(&ab->base_lock);
|
|
+ ath11k_peer_add_ast(ar, peer, mac_addr,
|
|
+ ATH11K_AST_TYPE_MEC);
|
|
+ spin_unlock_bh(&ab->base_lock);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void ath11k_nss_vdev_spl_receive_ext_wdsdata(struct ath11k_vif *arvif,
|
|
+ struct sk_buff *skb,
|
|
+ struct nss_wifi_vdev_wds_per_packet_metadata *wds_metadata)
|
|
+{
|
|
+ struct ath11k *ar = arvif->ar;
|
|
+ struct ath11k_base *ab = ar->ab;
|
|
+ enum wifi_vdev_ext_wds_info_type wds_type;
|
|
+ u8 is_sa_valid = 0, addr4_valid = 0;
|
|
+ u16 peer_id;
|
|
+ u8 src_mac[ETH_ALEN];
|
|
+
|
|
+ is_sa_valid = wds_metadata->is_sa_valid;
|
|
+ addr4_valid = wds_metadata->addr4_valid;
|
|
+ wds_type = wds_metadata->wds_type;
|
|
+ peer_id = wds_metadata->peer_id;
|
|
+
|
|
+ memcpy(src_mac, ((struct ethhdr *)skb->data)->h_source, ETH_ALEN);
|
|
+
|
|
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS,"receive_ext_wdsdata wds_type %d peer id %u sa_valid %d addr4_valid %d src_mac %pM\n",
|
|
+ wds_type, peer_id, is_sa_valid, addr4_valid, src_mac);
|
|
+
|
|
+ switch (wds_type) {
|
|
+ case NSS_WIFI_VDEV_WDS_TYPE_RX:
|
|
+ ath11k_nss_wds_type_rx(ar, src_mac, is_sa_valid,
|
|
+ addr4_valid, peer_id);
|
|
+ break;
|
|
+ case NSS_WIFI_VDEV_WDS_TYPE_MEC:
|
|
+ ath11k_nss_mec_handler(ar, (u8 *)(skb->data));
|
|
+ break;
|
|
+ default:
|
|
+ ath11k_warn(ab, "unsupported wds_type %d\n", wds_type);
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+static bool ath11k_nss_vdev_data_receive_mec_check(struct ath11k *ar,
|
|
+ struct sk_buff *skb)
|
|
+{
|
|
+ struct ath11k_base *ab = ar->ab;
|
|
+ struct ath11k_ast_entry *ast_entry = NULL;
|
|
+ u8 src_mac[ETH_ALEN];
|
|
+
|
|
+ memcpy(src_mac, ((struct ethhdr *)skb->data)->h_source, ETH_ALEN);
|
|
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS,
|
|
+ "ath11k_nss_vdev_data_receive_mec_check src mac %pM\n",
|
|
+ src_mac);
|
|
+
|
|
+ spin_lock_bh(&ab->base_lock);
|
|
+ ast_entry = ath11k_peer_ast_find_by_addr(ab, src_mac);
|
|
+
|
|
+ if (ast_entry && ast_entry->type == ATH11K_AST_TYPE_MEC) {
|
|
+ spin_unlock_bh(&ab->base_lock);
|
|
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS,
|
|
+ "dropping mec traffic from %pM\n", ast_entry->addr);
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ spin_unlock_bh(&ab->base_lock);
|
|
+ return false;
|
|
+}
|
|
+
|
|
+static int ath11k_nss_undecap(struct ath11k_vif *arvif, struct sk_buff *skb,
|
|
+ int *data_offs, bool *eth_decap)
|
|
+{
|
|
+ enum ath11k_hw_txrx_mode decap_type;
|
|
+
|
|
+ decap_type = arvif->nss.decap;
|
|
+
|
|
+ switch (decap_type) {
|
|
+ case ATH11K_HW_TXRX_RAW:
|
|
+ return ath11k_nss_undecap_raw(arvif, skb, data_offs);
|
|
+ case ATH11K_HW_TXRX_NATIVE_WIFI:
|
|
+ return ath11k_nss_undecap_nwifi(arvif, skb, data_offs);
|
|
+ case ATH11K_HW_TXRX_ETHERNET:
|
|
+ *eth_decap = true;
|
|
+ return 0;
|
|
+ default:
|
|
+ return -EINVAL;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+ath11k_nss_vdev_special_data_receive(struct net_device *dev, struct sk_buff *skb,
|
|
+ __attribute__((unused)) struct napi_struct *napi)
|
|
+{
|
|
+ struct nss_wifi_vdev_per_packet_metadata *wifi_metadata = NULL;
|
|
+ struct nss_wifi_vdev_wds_per_packet_metadata *wds_metadata = NULL;
|
|
+ struct wireless_dev *wdev;
|
|
+ struct ieee80211_vif *vif;
|
|
+ struct ath11k_vif *arvif;
|
|
+ struct ath11k_base *ab;
|
|
+ bool eth_decap = false;
|
|
+ int data_offs = 0;
|
|
+ int ret = 0;
|
|
+
|
|
+ if (!dev) {
|
|
+ dev_kfree_skb_any(skb);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ wdev = dev->ieee80211_ptr;
|
|
+ if (!wdev) {
|
|
+ dev_kfree_skb_any(skb);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ vif = wdev_to_ieee80211_vif(wdev);
|
|
+ if (!vif) {
|
|
+ dev_kfree_skb_any(skb);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ arvif = (struct ath11k_vif *)vif->drv_priv;
|
|
+ if (!arvif) {
|
|
+ dev_kfree_skb_any(skb);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ ab = arvif->ar->ab;
|
|
+
|
|
+ skb->dev = dev;
|
|
+
|
|
+ dma_unmap_single(ab->dev, virt_to_phys(skb->head),
|
|
+ NSS_WIFI_VDEV_PER_PACKET_METADATA_OFFSET +
|
|
+ sizeof(struct nss_wifi_vdev_per_packet_metadata),
|
|
+ DMA_FROM_DEVICE);
|
|
+
|
|
+ wifi_metadata = (struct nss_wifi_vdev_per_packet_metadata *)(skb->head +
|
|
+ NSS_WIFI_VDEV_PER_PACKET_METADATA_OFFSET);
|
|
+
|
|
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS,
|
|
+ "dp special data from nss: wifi_metadata->pkt_type %d",
|
|
+ wifi_metadata->pkt_type);
|
|
+
|
|
+ ret = ath11k_nss_undecap(arvif, skb, &data_offs, ð_decap);
|
|
+ if (ret) {
|
|
+ ath11k_warn(ab, "error in nss rx undecap, type %d err %d\n",
|
|
+ arvif->nss.decap, ret);
|
|
+ dev_kfree_skb_any(skb);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (eth_decap && wifi_metadata->pkt_type ==
|
|
+ NSS_WIFI_VDEV_EXT_DATA_PKT_TYPE_WDS_LEARN) {
|
|
+ wds_metadata = &wifi_metadata->metadata.wds_metadata;
|
|
+ ath11k_nss_vdev_spl_receive_ext_wdsdata(arvif, skb,
|
|
+ wds_metadata);
|
|
+ }
|
|
+
|
|
+ ath11k_nss_deliver_rx(arvif->vif, skb, eth_decap, data_offs, napi);
|
|
+}
|
|
+
|
|
static void
|
|
ath11k_nss_vdev_data_receive(struct net_device *dev, struct sk_buff *skb,
|
|
__attribute__((unused)) struct napi_struct *napi)
|
|
{
|
|
- enum ath11k_hw_txrx_mode decap_type;
|
|
struct wireless_dev *wdev = NULL;
|
|
struct ieee80211_vif *vif = NULL;
|
|
struct ath11k_vif *arvif;
|
|
@@ -591,28 +828,16 @@ ath11k_nss_vdev_data_receive(struct net_
|
|
ath11k_dbg_dump(ab, ATH11K_DBG_DP_RX, "", "dp rx msdu from nss: ",
|
|
skb->data, skb->len);
|
|
|
|
- decap_type = arvif->nss.decap;
|
|
-
|
|
- switch (decap_type) {
|
|
- case ATH11K_HW_TXRX_RAW:
|
|
- ret = ath11k_nss_undecap_raw(arvif, skb, &data_offs);
|
|
- break;
|
|
- case ATH11K_HW_TXRX_NATIVE_WIFI:
|
|
- ret = ath11k_nss_undecap_nwifi(arvif, skb, &data_offs);
|
|
- break;
|
|
- case ATH11K_HW_TXRX_ETHERNET:
|
|
- /* no changes required for ethernet decap */
|
|
- ret = 0;
|
|
- eth_decap = true;
|
|
- break;
|
|
- default:
|
|
- ret = -EINVAL;
|
|
- break;
|
|
+ if ((vif->type == NL80211_IFTYPE_STATION && wdev->use_4addr) &&
|
|
+ ath11k_nss_vdev_data_receive_mec_check(arvif->ar, skb)) {
|
|
+ dev_kfree_skb_any(skb);
|
|
+ return;
|
|
}
|
|
|
|
+ ret = ath11k_nss_undecap(arvif, skb, &data_offs, ð_decap);
|
|
if (ret) {
|
|
- ath11k_warn(ab, "error in nss rx undecap, type %d err %d\n", decap_type,
|
|
- ret);
|
|
+ ath11k_warn(ab, "error in nss rx undecap, type %d err %d\n",
|
|
+ arvif->nss.decap, ret);
|
|
dev_kfree_skb_any(skb);
|
|
return;
|
|
}
|
|
@@ -1324,7 +1549,7 @@ void ath11k_nss_update_sta_rxrate(struct
|
|
peer->nss.nss_stats->rxrate.bw = ath11k_mac_bw_to_mac80211_bw(ppdu_info->bw);
|
|
}
|
|
|
|
-int ath11k_nss_peer_delete(struct ath11k_base *ab, const u8 *addr)
|
|
+int ath11k_nss_peer_delete(struct ath11k_base *ab, u32 vdev_id, const u8 *addr)
|
|
{
|
|
struct nss_wifili_peer_msg *peer_msg;
|
|
struct nss_wifili_msg *wlmsg = NULL;
|
|
@@ -1338,9 +1563,10 @@ int ath11k_nss_peer_delete(struct ath11k
|
|
|
|
spin_lock_bh(&ab->base_lock);
|
|
|
|
- peer = ath11k_peer_find_by_addr(ab, addr);
|
|
+ peer = ath11k_peer_find(ab, vdev_id, addr);
|
|
if (!peer) {
|
|
- ath11k_warn(ab, "peer (%pM) not found for nss peer delete\n", addr);
|
|
+ ath11k_warn(ab, "peer (%pM) not found on vdev_id %d for nss peer delete\n",
|
|
+ addr, vdev_id);
|
|
spin_unlock_bh(&ab->base_lock);
|
|
return -EINVAL;
|
|
}
|
|
@@ -1413,8 +1639,9 @@ free_peer:
|
|
return ret;
|
|
}
|
|
|
|
-int ath11k_nss_peer_create(struct ath11k_base *ab, struct ath11k_peer *peer)
|
|
+int ath11k_nss_peer_create(struct ath11k *ar, struct ath11k_peer *peer)
|
|
{
|
|
+ struct ath11k_base *ab = ar->ab;
|
|
struct nss_wifili_peer_msg *peer_msg;
|
|
struct nss_wifili_msg *wlmsg = NULL;
|
|
nss_wifili_msg_callback_t msg_cb;
|
|
@@ -1471,17 +1698,23 @@ int ath11k_nss_peer_create(struct ath11k
|
|
status = nss_wifili_tx_msg(ab->nss.ctx, wlmsg);
|
|
if (status != NSS_TX_SUCCESS) {
|
|
ret = -EINVAL;
|
|
- ath11k_warn(ab, "nss send peer (%pM) create msg tx error\n",
|
|
- peer->addr);
|
|
+ ath11k_warn(ab, "nss send peer (%pM) create msg tx error: %d\n",
|
|
+ peer->addr, status);
|
|
goto peer_mem_free;
|
|
}
|
|
|
|
- ret = 0;
|
|
ath11k_dbg(ab, ATH11K_DBG_NSS,
|
|
"nss peer_create msg success mac:%pM vdev:%d peer_id:%d hw_ast_idx:%d ast_hash:%d\n",
|
|
peer_msg->peer_mac_addr, peer_msg->vdev_id, peer_msg->peer_id,
|
|
peer_msg->hw_ast_idx, peer_msg->tx_ast_hash);
|
|
|
|
+ ret = ath11k_peer_add_ast(ar, peer, peer->addr,
|
|
+ ATH11K_AST_TYPE_STATIC);
|
|
+ if (ret) {
|
|
+ ath11k_warn(ab, "failed to add STATIC ast: %d\n", ret);
|
|
+ goto peer_mem_free;
|
|
+ }
|
|
+
|
|
peer->nss.nss_stats = kzalloc(sizeof(*peer->nss.nss_stats), GFP_ATOMIC);
|
|
if (!peer->nss.nss_stats) {
|
|
ret = -ENOMEM;
|
|
@@ -1500,6 +1733,199 @@ msg_free:
|
|
return ret;
|
|
}
|
|
|
|
+int ath11k_nss_add_wds_peer(struct ath11k *ar, struct ath11k_peer *peer,
|
|
+ u8 *dest_mac, enum ath11k_ast_entry_type type)
|
|
+{
|
|
+ struct ath11k_base *ab = ar->ab;
|
|
+ struct nss_wifili_wds_peer_msg *wds_peer_msg;
|
|
+ struct nss_wifili_msg *wlmsg = NULL;
|
|
+ nss_wifili_msg_callback_t msg_cb;
|
|
+ nss_tx_status_t status;
|
|
+ int ret = 0;
|
|
+
|
|
+ wlmsg = kzalloc(sizeof(struct nss_wifili_msg), GFP_ATOMIC);
|
|
+ if (wlmsg == NULL)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ wds_peer_msg = &wlmsg->msg.wdspeermsg;
|
|
+
|
|
+ wds_peer_msg->pdev_id = ar->pdev->pdev_id;
|
|
+ wds_peer_msg->ast_type = type;
|
|
+ wds_peer_msg->peer_id = peer->peer_id;
|
|
+
|
|
+ if (type == ATH11K_AST_TYPE_MEC)
|
|
+ ether_addr_copy(wds_peer_msg->peer_mac, ar->mac_addr);
|
|
+ else
|
|
+ ether_addr_copy(wds_peer_msg->peer_mac, peer->addr);
|
|
+
|
|
+ ether_addr_copy(wds_peer_msg->dest_mac, dest_mac);
|
|
+
|
|
+ msg_cb = (nss_wifili_msg_callback_t)ath11k_nss_wifili_event_receive;
|
|
+
|
|
+ nss_cmn_msg_init(&wlmsg->cm, ab->nss.if_num,
|
|
+ NSS_WIFILI_WDS_PEER_ADD_MSG,
|
|
+ sizeof(struct nss_wifili_wds_peer_msg),
|
|
+ msg_cb, NULL);
|
|
+
|
|
+ status = nss_wifili_tx_msg(ab->nss.ctx, wlmsg);
|
|
+ if (status != NSS_TX_SUCCESS) {
|
|
+ ret = -EINVAL;
|
|
+ ath11k_warn(ab, "nss send wds add peer msg tx error: %d\n",
|
|
+ status);
|
|
+ goto msg_free;
|
|
+ }
|
|
+
|
|
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS,
|
|
+ "nss add wds peer success peer mac:%pM dest mac:%pM peer_id:%d\n",
|
|
+ wds_peer_msg->peer_mac, wds_peer_msg->dest_mac, wds_peer_msg->peer_id);
|
|
+
|
|
+msg_free:
|
|
+ kfree(wlmsg);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+int ath11k_nss_update_wds_peer(struct ath11k *ar, struct ath11k_peer *peer,
|
|
+ u8 *dest_mac)
|
|
+{
|
|
+ struct ath11k_base *ab = ar->ab;
|
|
+ struct nss_wifili_wds_peer_msg *wds_peer_msg;
|
|
+ struct nss_wifili_msg *wlmsg = NULL;
|
|
+ nss_wifili_msg_callback_t msg_cb;
|
|
+ nss_tx_status_t status;
|
|
+ int ret = 0;
|
|
+
|
|
+ wlmsg = kzalloc(sizeof(struct nss_wifili_msg), GFP_ATOMIC);
|
|
+ if (wlmsg == NULL)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ wds_peer_msg = &wlmsg->msg.wdspeermsg;
|
|
+
|
|
+ wds_peer_msg->pdev_id = ar->pdev->pdev_id;
|
|
+ wds_peer_msg->ast_type = ATH11K_AST_TYPE_WDS;
|
|
+ wds_peer_msg->peer_id = peer->peer_id;
|
|
+ ether_addr_copy(wds_peer_msg->peer_mac, peer->addr);
|
|
+ ether_addr_copy(wds_peer_msg->dest_mac, dest_mac);
|
|
+
|
|
+ msg_cb = (nss_wifili_msg_callback_t)ath11k_nss_wifili_event_receive;
|
|
+
|
|
+ nss_cmn_msg_init(&wlmsg->cm, ab->nss.if_num,
|
|
+ NSS_WIFILI_WDS_PEER_UPDATE_MSG,
|
|
+ sizeof(struct nss_wifili_wds_peer_msg),
|
|
+ msg_cb, NULL);
|
|
+
|
|
+ status = nss_wifili_tx_msg(ab->nss.ctx, wlmsg);
|
|
+ if (status != NSS_TX_SUCCESS) {
|
|
+ ret = -EINVAL;
|
|
+ ath11k_warn(ab, "nss send wds update peer msg tx error: %d\n",
|
|
+ status);
|
|
+ goto msg_free;
|
|
+ }
|
|
+
|
|
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS,
|
|
+ "nss update wds peer success peer mac:%pM dest mac:%pM peer_id:%d\n",
|
|
+ wds_peer_msg->peer_mac, wds_peer_msg->dest_mac, wds_peer_msg->peer_id);
|
|
+
|
|
+msg_free:
|
|
+ kfree(wlmsg);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+int ath11k_nss_map_wds_peer(struct ath11k *ar, struct ath11k_peer *peer,
|
|
+ u8 *dest_mac, enum ath11k_ast_entry_type type)
|
|
+{
|
|
+ struct ath11k_base *ab = ar->ab;
|
|
+ struct nss_wifili_wds_peer_map_msg *wds_peer_map_msg;
|
|
+ struct nss_wifili_msg *wlmsg = NULL;
|
|
+ nss_wifili_msg_callback_t msg_cb;
|
|
+ nss_tx_status_t status;
|
|
+ int ret = 0;
|
|
+
|
|
+ wlmsg = kzalloc(sizeof(struct nss_wifili_msg), GFP_ATOMIC);
|
|
+ if (wlmsg == NULL)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ wds_peer_map_msg = &wlmsg->msg.wdspeermapmsg;
|
|
+
|
|
+ wds_peer_map_msg->vdev_id = peer->vdev_id;
|
|
+ wds_peer_map_msg->ast_idx = peer->hw_peer_id;
|
|
+
|
|
+ if (type == ATH11K_AST_TYPE_MEC)
|
|
+ wds_peer_map_msg->peer_id = NSS_WIFILI_MEC_PEER_ID;
|
|
+ else
|
|
+ wds_peer_map_msg->peer_id = peer->peer_id;
|
|
+
|
|
+ ether_addr_copy(wds_peer_map_msg->dest_mac, dest_mac);
|
|
+
|
|
+ msg_cb = (nss_wifili_msg_callback_t)ath11k_nss_wifili_event_receive;
|
|
+
|
|
+ nss_cmn_msg_init(&wlmsg->cm, ab->nss.if_num,
|
|
+ NSS_WIFILI_WDS_PEER_MAP_MSG,
|
|
+ sizeof(struct nss_wifili_wds_peer_map_msg),
|
|
+ msg_cb, NULL);
|
|
+
|
|
+ status = nss_wifili_tx_msg(ab->nss.ctx, wlmsg);
|
|
+ if (status != NSS_TX_SUCCESS) {
|
|
+ ret = -EINVAL;
|
|
+ ath11k_warn(ab, "nss send wds peer map msg tx error: %d\n",
|
|
+ status);
|
|
+ goto msg_free;
|
|
+ }
|
|
+
|
|
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS,
|
|
+ "nss wds peer map success mac:%pM hw_ast_idx:%d peer_id:%d\n",
|
|
+ wds_peer_map_msg->dest_mac, wds_peer_map_msg->ast_idx, wds_peer_map_msg->peer_id);
|
|
+
|
|
+msg_free:
|
|
+ kfree(wlmsg);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+int ath11k_nss_del_wds_peer(struct ath11k *ar, struct ath11k_peer *peer,
|
|
+ u8 *dest_mac)
|
|
+{
|
|
+ struct ath11k_base *ab = ar->ab;
|
|
+ struct nss_wifili_wds_peer_msg *wds_peer_msg;
|
|
+ struct nss_wifili_msg *wlmsg = NULL;
|
|
+ nss_wifili_msg_callback_t msg_cb;
|
|
+ nss_tx_status_t status;
|
|
+ int ret = 0;
|
|
+
|
|
+ wlmsg = kzalloc(sizeof(struct nss_wifili_msg), GFP_ATOMIC);
|
|
+ if (wlmsg == NULL)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ wds_peer_msg = &wlmsg->msg.wdspeermsg;
|
|
+
|
|
+ wds_peer_msg->pdev_id = ar->pdev->pdev_id;
|
|
+ wds_peer_msg->ast_type = ATH11K_AST_TYPE_NONE;
|
|
+ wds_peer_msg->peer_id = peer->peer_id;
|
|
+ ether_addr_copy(wds_peer_msg->peer_mac, peer->addr);
|
|
+ ether_addr_copy(wds_peer_msg->dest_mac, dest_mac);
|
|
+
|
|
+ msg_cb = (nss_wifili_msg_callback_t)ath11k_nss_wifili_event_receive;
|
|
+
|
|
+ nss_cmn_msg_init(&wlmsg->cm, ab->nss.if_num,
|
|
+ NSS_WIFILI_WDS_PEER_DEL_MSG,
|
|
+ sizeof(struct nss_wifili_wds_peer_msg),
|
|
+ msg_cb, NULL);
|
|
+
|
|
+ status = nss_wifili_tx_msg(ab->nss.ctx, wlmsg);
|
|
+ if (status != NSS_TX_SUCCESS) {
|
|
+ ret = -EINVAL;
|
|
+ ath11k_warn(ab, "nss send wds del peer msg tx error: %d\n",
|
|
+ status);
|
|
+ goto msg_free;
|
|
+ }
|
|
+
|
|
+ ath11k_dbg(ab, ATH11K_DBG_NSS_WDS,
|
|
+ "nss del wds peer success peer mac:%pM dest mac:%pM peer_id:%d\n",
|
|
+ wds_peer_msg->peer_mac, wds_peer_msg->dest_mac, wds_peer_msg->peer_id);
|
|
+
|
|
+msg_free:
|
|
+ kfree(wlmsg);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
/*-------------------------------INIT/DEINIT---------------------------------*/
|
|
|
|
static int ath11k_nss_radio_buf_cfg(struct ath11k *ar, int range, int buf_sz)
|
|
@@ -1893,7 +2319,7 @@ static int ath11k_nss_init(struct ath11k
|
|
|
|
status = nss_wifili_tx_msg(nss_contex, wlmsg);
|
|
if (status != NSS_TX_SUCCESS) {
|
|
- ath11k_warn(ab, "failure to send nss init msg\n");
|
|
+ ath11k_warn(ab, "failure to send nss init msg: %d \n", status);
|
|
goto unregister;
|
|
}
|
|
|
|
@@ -1947,7 +2373,8 @@ static int ath11k_nss_stats_cfg(struct a
|
|
|
|
status = nss_wifili_tx_msg(ar->nss.ctx, wlmsg);
|
|
if (status != NSS_TX_SUCCESS) {
|
|
- ath11k_warn(ab, "nss stats cfg %d msg tx failure\n", nss_msg);
|
|
+ ath11k_warn(ab, "nss stats cfg %d msg tx failure: %d\n",
|
|
+ nss_msg, status);
|
|
ret = -EINVAL;
|
|
goto free;
|
|
}
|
|
--- a/drivers/net/wireless/ath/ath11k/nss.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/nss.h
|
|
@@ -17,12 +17,14 @@ struct ath11k_base;
|
|
struct ath11k_vif;
|
|
struct ath11k_peer;
|
|
struct ath11k_sta;
|
|
+enum ath11k_ast_entry_type;
|
|
struct hal_rx_mon_ppdu_info;
|
|
struct hal_rx_user_status;
|
|
|
|
/* NSS DBG macro is not included as part of debug enum to avoid
|
|
* frequent changes during upgrade*/
|
|
-#define ATH11K_DBG_NSS 0x80000000
|
|
+#define ATH11K_DBG_NSS 0x40000000
|
|
+#define ATH11K_DBG_NSS_WDS 0x80000000
|
|
|
|
/* WIFILI Supported Target Types */
|
|
#define ATH11K_WIFILI_TARGET_TYPE_UNKNOWN 0xFF
|
|
@@ -205,11 +207,19 @@ int ath11k_nss_vdev_create(struct ath11k
|
|
void ath11k_nss_vdev_delete(struct ath11k_vif *arvif);
|
|
int ath11k_nss_vdev_up(struct ath11k_vif *arvif);
|
|
int ath11k_nss_vdev_down(struct ath11k_vif *arvif);
|
|
-int ath11k_nss_peer_delete(struct ath11k_base *ab, const u8 *addr);
|
|
+int ath11k_nss_peer_delete(struct ath11k_base *ab, u32 vdev_id, const u8 *addr);
|
|
int ath11k_nss_set_peer_authorize(struct ath11k *ar, u16 peer_id);
|
|
-int ath11k_nss_peer_create(struct ath11k_base *ab, struct ath11k_peer *peer);
|
|
+int ath11k_nss_peer_create(struct ath11k *ar, struct ath11k_peer *peer);
|
|
void ath11k_nss_peer_stats_enable(struct ath11k *ar);
|
|
void ath11k_nss_peer_stats_disable(struct ath11k *ar);
|
|
+int ath11k_nss_add_wds_peer(struct ath11k *ar, struct ath11k_peer *peer,
|
|
+ u8 *dest_mac, enum ath11k_ast_entry_type type);
|
|
+int ath11k_nss_update_wds_peer(struct ath11k *ar, struct ath11k_peer *peer,
|
|
+ u8 *dest_mac);
|
|
+int ath11k_nss_map_wds_peer(struct ath11k *ar, struct ath11k_peer *peer,
|
|
+ u8 *dest_mac, enum ath11k_ast_entry_type type);
|
|
+int ath11k_nss_del_wds_peer(struct ath11k *ar, struct ath11k_peer *peer,
|
|
+ u8 *dest_mac);
|
|
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 station_info *sinfo,
|
|
@@ -271,12 +281,37 @@ static inline int ath11k_nss_vdev_down(s
|
|
return 0;
|
|
}
|
|
|
|
-static inline int ath11k_nss_peer_delete(struct ath11k_base *ab, const u8 *addr)
|
|
+static inline int ath11k_nss_peer_delete(struct ath11k_base *ab, u32 vdev_id,
|
|
+ const u8 *addr)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
-static inline int ath11k_nss_peer_create(struct ath11k_base *ab, struct ath11k_peer *peer)
|
|
+static inline int ath11k_nss_add_wds_peer(struct ath11k *ar, struct ath11k_peer *peer,
|
|
+ u8 *dest_mac, int type)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static inline int ath11k_nss_update_wds_peer(struct ath11k *ar, struct ath11k_peer *peer,
|
|
+ u8 *dest_mac)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static inline int ath11k_nss_map_wds_peer(struct ath11k *ar, struct ath11k_peer *peer,
|
|
+ u8 *dest_mac, int type)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static inline int ath11k_nss_del_wds_peer(struct ath11k_vif *arvif, struct ath11k_peer *peer,
|
|
+ u8 *dest_mac)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static inline int ath11k_nss_peer_create(struct ath11k *ar, struct ath11k_peer *peer)
|
|
{
|
|
return 0;
|
|
}
|