diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath11k/dp.c')
-rw-r--r-- | drivers/net/wireless/ath/ath11k/dp.c | 76 |
1 files changed, 54 insertions, 22 deletions
diff --git a/drivers/net/wireless/ath/ath11k/dp.c b/drivers/net/wireless/ath/ath11k/dp.c index b112825a52ed..50350f77b309 100644 --- a/drivers/net/wireless/ath/ath11k/dp.c +++ b/drivers/net/wireless/ath/ath11k/dp.c @@ -3,6 +3,7 @@ * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. */ +#include <crypto/hash.h> #include "core.h" #include "dp_tx.h" #include "hal_tx.h" @@ -33,14 +34,16 @@ void ath11k_dp_peer_cleanup(struct ath11k *ar, int vdev_id, const u8 *addr) } ath11k_peer_rx_tid_cleanup(ar, peer); + crypto_free_shash(peer->tfm_mmic); spin_unlock_bh(&ab->base_lock); } int ath11k_dp_peer_setup(struct ath11k *ar, int vdev_id, const u8 *addr) { struct ath11k_base *ab = ar->ab; + struct ath11k_peer *peer; u32 reo_dest; - int ret; + int ret = 0, tid; /* NOTE: reo_dest ring id starts from 1 unlike mac_id which starts from 0 */ reo_dest = ar->dp.mac_id + 1; @@ -54,24 +57,42 @@ int ath11k_dp_peer_setup(struct ath11k *ar, int vdev_id, const u8 *addr) return ret; } - ret = ath11k_peer_rx_tid_setup(ar, addr, vdev_id, - HAL_DESC_REO_NON_QOS_TID, 1, 0); - if (ret) { - ath11k_warn(ab, "failed to setup rxd tid queue for non-qos tid %d\n", - ret); - return ret; + for (tid = 0; tid <= IEEE80211_NUM_TIDS; tid++) { + ret = ath11k_peer_rx_tid_setup(ar, addr, vdev_id, tid, 1, 0, + HAL_PN_TYPE_NONE); + if (ret) { + ath11k_warn(ab, "failed to setup rxd tid queue for tid %d: %d\n", + tid, ret); + goto peer_clean; + } } - ret = ath11k_peer_rx_tid_setup(ar, addr, vdev_id, 0, 1, 0); + ret = ath11k_peer_rx_frag_setup(ar, addr, vdev_id); if (ret) { - ath11k_warn(ab, "failed to setup rxd tid queue for tid 0 %d\n", - ret); + ath11k_warn(ab, "failed to setup rx defrag context\n"); return ret; } /* TODO: Setup other peer specific resource used in data path */ return 0; + +peer_clean: + spin_lock_bh(&ab->base_lock); + + peer = ath11k_peer_find(ab, vdev_id, addr); + if (!peer) { + ath11k_warn(ab, "failed to find the peer to del rx tid\n"); + spin_unlock_bh(&ab->base_lock); + return -ENOENT; + } + + for (; tid >= 0; tid--) + ath11k_peer_rx_tid_delete(ar, peer, tid); + + spin_unlock_bh(&ab->base_lock); + + return ret; } void ath11k_dp_srng_cleanup(struct ath11k_base *ab, struct dp_srng *ring) @@ -197,6 +218,7 @@ static int ath11k_dp_srng_common_setup(struct ath11k_base *ab) struct ath11k_dp *dp = &ab->dp; struct hal_srng *srng; int i, ret; + u32 ring_hash_map; ret = ath11k_dp_srng_setup(ab, &dp->wbm_desc_rel_ring, HAL_SW2WBM_RELEASE, 0, 0, @@ -284,7 +306,21 @@ static int ath11k_dp_srng_common_setup(struct ath11k_base *ab) goto err; } - ath11k_hal_reo_hw_setup(ab); + /* When hash based routing of rx packet is enabled, 32 entries to map + * the hash values to the ring will be configured. Each hash entry uses + * three bits to map to a particular ring. The ring mapping will be + * 0:TCL, 1:SW1, 2:SW2, 3:SW3, 4:SW4, 5:Release, 6:FW and 7:Not used. + */ + ring_hash_map = HAL_HASH_ROUTING_RING_SW1 << 0 | + HAL_HASH_ROUTING_RING_SW2 << 3 | + HAL_HASH_ROUTING_RING_SW3 << 6 | + HAL_HASH_ROUTING_RING_SW4 << 9 | + HAL_HASH_ROUTING_RING_SW1 << 12 | + HAL_HASH_ROUTING_RING_SW2 << 15 | + HAL_HASH_ROUTING_RING_SW3 << 18 | + HAL_HASH_ROUTING_RING_SW4 << 21; + + ath11k_hal_reo_hw_setup(ab, ring_hash_map); return 0; @@ -614,17 +650,13 @@ int ath11k_dp_service_srng(struct ath11k_base *ab, } if (ath11k_rx_ring_mask[grp_id]) { - for (i = 0; i < ab->num_radios; i++) { - if (ath11k_rx_ring_mask[grp_id] & BIT(i)) { - work_done = ath11k_dp_process_rx(ab, i, napi, - &irq_grp->pending_q, - budget); - budget -= work_done; - tot_work_done += work_done; - } - if (budget <= 0) - goto done; - } + i = fls(ath11k_rx_ring_mask[grp_id]) - 1; + work_done = ath11k_dp_process_rx(ab, i, napi, + budget); + budget -= work_done; + tot_work_done += work_done; + if (budget <= 0) + goto done; } if (rx_mon_status_ring_mask[grp_id]) { |