Loading drivers/net/wireless/ath/ath10k/core.h +1 −2 Original line number Diff line number Diff line Loading @@ -67,7 +67,6 @@ /* NAPI poll budget */ #define ATH10K_NAPI_BUDGET 64 #define ATH10K_NAPI_QUOTA_LIMIT 60 /* SMBIOS type containing Board Data File Name Extension */ #define ATH10K_SMBIOS_BDF_EXT_TYPE 0xF8 Loading Loading @@ -364,11 +363,11 @@ struct ath10k_sta { struct rate_info txrate; struct work_struct update_wk; u64 rx_duration; #ifdef CONFIG_MAC80211_DEBUGFS /* protected by conf_mutex */ bool aggr_mode; u64 rx_duration; #endif }; Loading drivers/net/wireless/ath/ath10k/debug.h +0 −3 Original line number Diff line number Diff line Loading @@ -190,9 +190,6 @@ void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct dentry *dir); void ath10k_sta_update_rx_duration(struct ath10k *ar, struct ath10k_fw_stats *stats); void ath10k_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct station_info *sinfo); #else static inline void ath10k_sta_update_rx_duration(struct ath10k *ar, Loading drivers/net/wireless/ath/ath10k/debugfs_sta.c +0 −27 Original line number Diff line number Diff line Loading @@ -65,33 +65,6 @@ void ath10k_sta_update_rx_duration(struct ath10k *ar, ath10k_sta_update_stats_rx_duration(ar, stats); } void ath10k_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct station_info *sinfo) { struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; struct ath10k *ar = arsta->arvif->ar; if (!ath10k_peer_stats_enabled(ar)) return; sinfo->rx_duration = arsta->rx_duration; sinfo->filled |= 1ULL << NL80211_STA_INFO_RX_DURATION; if (!arsta->txrate.legacy && !arsta->txrate.nss) return; if (arsta->txrate.legacy) { sinfo->txrate.legacy = arsta->txrate.legacy; } else { sinfo->txrate.mcs = arsta->txrate.mcs; sinfo->txrate.nss = arsta->txrate.nss; sinfo->txrate.bw = arsta->txrate.bw; } sinfo->txrate.flags = arsta->txrate.flags; sinfo->filled |= 1ULL << NL80211_STA_INFO_TX_BITRATE; } static ssize_t ath10k_dbg_sta_read_aggr_mode(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) Loading drivers/net/wireless/ath/ath10k/htt.h +1 −1 Original line number Diff line number Diff line Loading @@ -1695,7 +1695,7 @@ struct ath10k_htt { /* This is used to group tx/rx completions separately and process them * in batches to reduce cache stalls */ struct sk_buff_head rx_compl_q; struct sk_buff_head rx_msdus_q; struct sk_buff_head rx_in_ord_compl_q; struct sk_buff_head tx_fetch_ind_q; Loading drivers/net/wireless/ath/ath10k/htt_rx.c +62 −59 Original line number Diff line number Diff line Loading @@ -228,7 +228,7 @@ void ath10k_htt_rx_free(struct ath10k_htt *htt) { del_timer_sync(&htt->rx_ring.refill_retry_timer); skb_queue_purge(&htt->rx_compl_q); skb_queue_purge(&htt->rx_msdus_q); skb_queue_purge(&htt->rx_in_ord_compl_q); skb_queue_purge(&htt->tx_fetch_ind_q); Loading Loading @@ -518,7 +518,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt) htt->rx_ring.sw_rd_idx.msdu_payld = 0; hash_init(htt->rx_ring.skb_table); skb_queue_head_init(&htt->rx_compl_q); skb_queue_head_init(&htt->rx_msdus_q); skb_queue_head_init(&htt->rx_in_ord_compl_q); skb_queue_head_init(&htt->tx_fetch_ind_q); atomic_set(&htt->num_mpdus_ready, 0); Loading Loading @@ -954,16 +954,25 @@ static char *ath10k_get_tid(struct ieee80211_hdr *hdr, char *out, size_t size) return out; } static void ath10k_process_rx(struct ath10k *ar, static void ath10k_htt_rx_h_queue_msdu(struct ath10k *ar, struct ieee80211_rx_status *rx_status, struct sk_buff *skb) { struct ieee80211_rx_status *status; status = IEEE80211_SKB_RXCB(skb); *status = *rx_status; __skb_queue_tail(&ar->htt.rx_msdus_q, skb); } static void ath10k_process_rx(struct ath10k *ar, struct sk_buff *skb) { struct ieee80211_rx_status *status; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; char tid[32]; status = IEEE80211_SKB_RXCB(skb); *status = *rx_status; ath10k_dbg(ar, ATH10K_DBG_DATA, "rx skb %pK len %u peer %pM %s %s sn %u %s%s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n", Loading Loading @@ -1495,7 +1504,7 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, } } static void ath10k_htt_rx_h_deliver(struct ath10k *ar, static void ath10k_htt_rx_h_enqueue(struct ath10k *ar, struct sk_buff_head *amsdu, struct ieee80211_rx_status *status) { Loading @@ -1518,7 +1527,7 @@ static void ath10k_htt_rx_h_deliver(struct ath10k *ar, status->flag |= RX_FLAG_ALLOW_SAME_PN; } ath10k_process_rx(ar, status, msdu); ath10k_htt_rx_h_queue_msdu(ar, status, msdu); } } Loading Loading @@ -1630,7 +1639,7 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt) struct ath10k *ar = htt->ar; struct ieee80211_rx_status *rx_status = &htt->rx_status; struct sk_buff_head amsdu; int ret, num_msdus; int ret; __skb_queue_head_init(&amsdu); Loading @@ -1652,7 +1661,6 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt) return ret; } num_msdus = skb_queue_len(&amsdu); ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status, 0xffff); /* only for ret = 1 indicates chained msdus */ Loading @@ -1661,9 +1669,9 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt) ath10k_htt_rx_h_filter(ar, &amsdu, rx_status); ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status, true); ath10k_htt_rx_h_deliver(ar, &amsdu, rx_status); ath10k_htt_rx_h_enqueue(ar, &amsdu, rx_status); return num_msdus; return 0; } static void ath10k_htt_rx_proc_rx_ind(struct ath10k_htt *htt, Loading Loading @@ -1871,7 +1879,7 @@ static void ath10k_htt_rx_h_rx_offload_prot(struct ieee80211_rx_status *status, RX_FLAG_MMIC_STRIPPED; } static int ath10k_htt_rx_h_rx_offload(struct ath10k *ar, static void ath10k_htt_rx_h_rx_offload(struct ath10k *ar, struct sk_buff_head *list) { struct ath10k_htt *htt = &ar->htt; Loading @@ -1879,7 +1887,6 @@ static int ath10k_htt_rx_h_rx_offload(struct ath10k *ar, struct htt_rx_offload_msdu *rx; struct sk_buff *msdu; size_t offset; int num_msdu = 0; while ((msdu = __skb_dequeue(list))) { /* Offloaded frames don't have Rx descriptor. Instead they have Loading Loading @@ -1918,10 +1925,8 @@ static int ath10k_htt_rx_h_rx_offload(struct ath10k *ar, ath10k_htt_rx_h_rx_offload_prot(status, msdu); ath10k_htt_rx_h_channel(ar, status, NULL, rx->vdev_id); ath10k_process_rx(ar, status, msdu); num_msdu++; ath10k_htt_rx_h_queue_msdu(ar, status, msdu); } return num_msdu; } static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb) Loading @@ -1937,7 +1942,7 @@ static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb) u8 tid; bool offload; bool frag; int ret, num_msdus = 0; int ret; lockdep_assert_held(&htt->rx_ring.lock); Loading Loading @@ -1979,7 +1984,7 @@ static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb) * separately. */ if (offload) num_msdus = ath10k_htt_rx_h_rx_offload(ar, &list); ath10k_htt_rx_h_rx_offload(ar, &list); while (!skb_queue_empty(&list)) { __skb_queue_head_init(&amsdu); Loading @@ -1992,11 +1997,10 @@ static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb) * better to report something than nothing though. This * should still give an idea about rx rate to the user. */ num_msdus += skb_queue_len(&amsdu); ath10k_htt_rx_h_ppdu(ar, &amsdu, status, vdev_id); ath10k_htt_rx_h_filter(ar, &amsdu, status); ath10k_htt_rx_h_mpdu(ar, &amsdu, status, false); ath10k_htt_rx_h_deliver(ar, &amsdu, status); ath10k_htt_rx_h_enqueue(ar, &amsdu, status); break; case -EAGAIN: /* fall through */ Loading @@ -2008,7 +2012,7 @@ static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb) return -EIO; } } return num_msdus; return ret; } static void ath10k_htt_rx_tx_fetch_resp_id_confirm(struct ath10k *ar, Loading Loading @@ -2609,6 +2613,24 @@ void ath10k_htt_rx_pktlog_completion_handler(struct ath10k *ar, } EXPORT_SYMBOL(ath10k_htt_rx_pktlog_completion_handler); static int ath10k_htt_rx_deliver_msdu(struct ath10k *ar, int quota, int budget) { struct sk_buff *skb; while (quota < budget) { if (skb_queue_empty(&ar->htt.rx_msdus_q)) break; skb = __skb_dequeue(&ar->htt.rx_msdus_q); if (!skb) break; ath10k_process_rx(ar, skb); quota++; } return quota; } int ath10k_htt_txrx_compl_task(struct ath10k *ar, int budget) { struct ath10k_htt *htt = &ar->htt; Loading @@ -2616,63 +2638,44 @@ int ath10k_htt_txrx_compl_task(struct ath10k *ar, int budget) struct sk_buff_head tx_ind_q; struct sk_buff *skb; unsigned long flags; int quota = 0, done, num_rx_msdus; int quota = 0, done, ret; bool resched_napi = false; __skb_queue_head_init(&tx_ind_q); /* Since in-ord-ind can deliver more than 1 A-MSDU in single event, * process it first to utilize full available quota. /* Process pending frames before dequeuing more data * from hardware. */ while (quota < budget) { if (skb_queue_empty(&htt->rx_in_ord_compl_q)) break; skb = __skb_dequeue(&htt->rx_in_ord_compl_q); if (!skb) { quota = ath10k_htt_rx_deliver_msdu(ar, quota, budget); if (quota == budget) { resched_napi = true; goto exit; } while ((skb = __skb_dequeue(&htt->rx_in_ord_compl_q))) { spin_lock_bh(&htt->rx_ring.lock); num_rx_msdus = ath10k_htt_rx_in_ord_ind(ar, skb); ret = ath10k_htt_rx_in_ord_ind(ar, skb); spin_unlock_bh(&htt->rx_ring.lock); if (num_rx_msdus < 0) { resched_napi = true; goto exit; } dev_kfree_skb_any(skb); if (num_rx_msdus > 0) quota += num_rx_msdus; if ((quota > ATH10K_NAPI_QUOTA_LIMIT) && !skb_queue_empty(&htt->rx_in_ord_compl_q)) { if (ret == -EIO) { resched_napi = true; goto exit; } } while (quota < budget) { /* no more data to receive */ if (!atomic_read(&htt->num_mpdus_ready)) break; num_rx_msdus = ath10k_htt_rx_handle_amsdu(htt); if (num_rx_msdus < 0) { while (atomic_read(&htt->num_mpdus_ready)) { ret = ath10k_htt_rx_handle_amsdu(htt); if (ret == -EIO) { resched_napi = true; goto exit; } quota += num_rx_msdus; atomic_dec(&htt->num_mpdus_ready); if ((quota > ATH10K_NAPI_QUOTA_LIMIT) && atomic_read(&htt->num_mpdus_ready)) { resched_napi = true; goto exit; } } /* Deliver received data after processing data from hardware */ quota = ath10k_htt_rx_deliver_msdu(ar, quota, budget); /* From NAPI documentation: * The napi poll() function may also process TX completions, in which * case if it processes the entire TX ring then it should count that Loading Loading
drivers/net/wireless/ath/ath10k/core.h +1 −2 Original line number Diff line number Diff line Loading @@ -67,7 +67,6 @@ /* NAPI poll budget */ #define ATH10K_NAPI_BUDGET 64 #define ATH10K_NAPI_QUOTA_LIMIT 60 /* SMBIOS type containing Board Data File Name Extension */ #define ATH10K_SMBIOS_BDF_EXT_TYPE 0xF8 Loading Loading @@ -364,11 +363,11 @@ struct ath10k_sta { struct rate_info txrate; struct work_struct update_wk; u64 rx_duration; #ifdef CONFIG_MAC80211_DEBUGFS /* protected by conf_mutex */ bool aggr_mode; u64 rx_duration; #endif }; Loading
drivers/net/wireless/ath/ath10k/debug.h +0 −3 Original line number Diff line number Diff line Loading @@ -190,9 +190,6 @@ void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct dentry *dir); void ath10k_sta_update_rx_duration(struct ath10k *ar, struct ath10k_fw_stats *stats); void ath10k_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct station_info *sinfo); #else static inline void ath10k_sta_update_rx_duration(struct ath10k *ar, Loading
drivers/net/wireless/ath/ath10k/debugfs_sta.c +0 −27 Original line number Diff line number Diff line Loading @@ -65,33 +65,6 @@ void ath10k_sta_update_rx_duration(struct ath10k *ar, ath10k_sta_update_stats_rx_duration(ar, stats); } void ath10k_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct station_info *sinfo) { struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; struct ath10k *ar = arsta->arvif->ar; if (!ath10k_peer_stats_enabled(ar)) return; sinfo->rx_duration = arsta->rx_duration; sinfo->filled |= 1ULL << NL80211_STA_INFO_RX_DURATION; if (!arsta->txrate.legacy && !arsta->txrate.nss) return; if (arsta->txrate.legacy) { sinfo->txrate.legacy = arsta->txrate.legacy; } else { sinfo->txrate.mcs = arsta->txrate.mcs; sinfo->txrate.nss = arsta->txrate.nss; sinfo->txrate.bw = arsta->txrate.bw; } sinfo->txrate.flags = arsta->txrate.flags; sinfo->filled |= 1ULL << NL80211_STA_INFO_TX_BITRATE; } static ssize_t ath10k_dbg_sta_read_aggr_mode(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) Loading
drivers/net/wireless/ath/ath10k/htt.h +1 −1 Original line number Diff line number Diff line Loading @@ -1695,7 +1695,7 @@ struct ath10k_htt { /* This is used to group tx/rx completions separately and process them * in batches to reduce cache stalls */ struct sk_buff_head rx_compl_q; struct sk_buff_head rx_msdus_q; struct sk_buff_head rx_in_ord_compl_q; struct sk_buff_head tx_fetch_ind_q; Loading
drivers/net/wireless/ath/ath10k/htt_rx.c +62 −59 Original line number Diff line number Diff line Loading @@ -228,7 +228,7 @@ void ath10k_htt_rx_free(struct ath10k_htt *htt) { del_timer_sync(&htt->rx_ring.refill_retry_timer); skb_queue_purge(&htt->rx_compl_q); skb_queue_purge(&htt->rx_msdus_q); skb_queue_purge(&htt->rx_in_ord_compl_q); skb_queue_purge(&htt->tx_fetch_ind_q); Loading Loading @@ -518,7 +518,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt) htt->rx_ring.sw_rd_idx.msdu_payld = 0; hash_init(htt->rx_ring.skb_table); skb_queue_head_init(&htt->rx_compl_q); skb_queue_head_init(&htt->rx_msdus_q); skb_queue_head_init(&htt->rx_in_ord_compl_q); skb_queue_head_init(&htt->tx_fetch_ind_q); atomic_set(&htt->num_mpdus_ready, 0); Loading Loading @@ -954,16 +954,25 @@ static char *ath10k_get_tid(struct ieee80211_hdr *hdr, char *out, size_t size) return out; } static void ath10k_process_rx(struct ath10k *ar, static void ath10k_htt_rx_h_queue_msdu(struct ath10k *ar, struct ieee80211_rx_status *rx_status, struct sk_buff *skb) { struct ieee80211_rx_status *status; status = IEEE80211_SKB_RXCB(skb); *status = *rx_status; __skb_queue_tail(&ar->htt.rx_msdus_q, skb); } static void ath10k_process_rx(struct ath10k *ar, struct sk_buff *skb) { struct ieee80211_rx_status *status; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; char tid[32]; status = IEEE80211_SKB_RXCB(skb); *status = *rx_status; ath10k_dbg(ar, ATH10K_DBG_DATA, "rx skb %pK len %u peer %pM %s %s sn %u %s%s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n", Loading Loading @@ -1495,7 +1504,7 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, } } static void ath10k_htt_rx_h_deliver(struct ath10k *ar, static void ath10k_htt_rx_h_enqueue(struct ath10k *ar, struct sk_buff_head *amsdu, struct ieee80211_rx_status *status) { Loading @@ -1518,7 +1527,7 @@ static void ath10k_htt_rx_h_deliver(struct ath10k *ar, status->flag |= RX_FLAG_ALLOW_SAME_PN; } ath10k_process_rx(ar, status, msdu); ath10k_htt_rx_h_queue_msdu(ar, status, msdu); } } Loading Loading @@ -1630,7 +1639,7 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt) struct ath10k *ar = htt->ar; struct ieee80211_rx_status *rx_status = &htt->rx_status; struct sk_buff_head amsdu; int ret, num_msdus; int ret; __skb_queue_head_init(&amsdu); Loading @@ -1652,7 +1661,6 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt) return ret; } num_msdus = skb_queue_len(&amsdu); ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status, 0xffff); /* only for ret = 1 indicates chained msdus */ Loading @@ -1661,9 +1669,9 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt) ath10k_htt_rx_h_filter(ar, &amsdu, rx_status); ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status, true); ath10k_htt_rx_h_deliver(ar, &amsdu, rx_status); ath10k_htt_rx_h_enqueue(ar, &amsdu, rx_status); return num_msdus; return 0; } static void ath10k_htt_rx_proc_rx_ind(struct ath10k_htt *htt, Loading Loading @@ -1871,7 +1879,7 @@ static void ath10k_htt_rx_h_rx_offload_prot(struct ieee80211_rx_status *status, RX_FLAG_MMIC_STRIPPED; } static int ath10k_htt_rx_h_rx_offload(struct ath10k *ar, static void ath10k_htt_rx_h_rx_offload(struct ath10k *ar, struct sk_buff_head *list) { struct ath10k_htt *htt = &ar->htt; Loading @@ -1879,7 +1887,6 @@ static int ath10k_htt_rx_h_rx_offload(struct ath10k *ar, struct htt_rx_offload_msdu *rx; struct sk_buff *msdu; size_t offset; int num_msdu = 0; while ((msdu = __skb_dequeue(list))) { /* Offloaded frames don't have Rx descriptor. Instead they have Loading Loading @@ -1918,10 +1925,8 @@ static int ath10k_htt_rx_h_rx_offload(struct ath10k *ar, ath10k_htt_rx_h_rx_offload_prot(status, msdu); ath10k_htt_rx_h_channel(ar, status, NULL, rx->vdev_id); ath10k_process_rx(ar, status, msdu); num_msdu++; ath10k_htt_rx_h_queue_msdu(ar, status, msdu); } return num_msdu; } static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb) Loading @@ -1937,7 +1942,7 @@ static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb) u8 tid; bool offload; bool frag; int ret, num_msdus = 0; int ret; lockdep_assert_held(&htt->rx_ring.lock); Loading Loading @@ -1979,7 +1984,7 @@ static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb) * separately. */ if (offload) num_msdus = ath10k_htt_rx_h_rx_offload(ar, &list); ath10k_htt_rx_h_rx_offload(ar, &list); while (!skb_queue_empty(&list)) { __skb_queue_head_init(&amsdu); Loading @@ -1992,11 +1997,10 @@ static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb) * better to report something than nothing though. This * should still give an idea about rx rate to the user. */ num_msdus += skb_queue_len(&amsdu); ath10k_htt_rx_h_ppdu(ar, &amsdu, status, vdev_id); ath10k_htt_rx_h_filter(ar, &amsdu, status); ath10k_htt_rx_h_mpdu(ar, &amsdu, status, false); ath10k_htt_rx_h_deliver(ar, &amsdu, status); ath10k_htt_rx_h_enqueue(ar, &amsdu, status); break; case -EAGAIN: /* fall through */ Loading @@ -2008,7 +2012,7 @@ static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb) return -EIO; } } return num_msdus; return ret; } static void ath10k_htt_rx_tx_fetch_resp_id_confirm(struct ath10k *ar, Loading Loading @@ -2609,6 +2613,24 @@ void ath10k_htt_rx_pktlog_completion_handler(struct ath10k *ar, } EXPORT_SYMBOL(ath10k_htt_rx_pktlog_completion_handler); static int ath10k_htt_rx_deliver_msdu(struct ath10k *ar, int quota, int budget) { struct sk_buff *skb; while (quota < budget) { if (skb_queue_empty(&ar->htt.rx_msdus_q)) break; skb = __skb_dequeue(&ar->htt.rx_msdus_q); if (!skb) break; ath10k_process_rx(ar, skb); quota++; } return quota; } int ath10k_htt_txrx_compl_task(struct ath10k *ar, int budget) { struct ath10k_htt *htt = &ar->htt; Loading @@ -2616,63 +2638,44 @@ int ath10k_htt_txrx_compl_task(struct ath10k *ar, int budget) struct sk_buff_head tx_ind_q; struct sk_buff *skb; unsigned long flags; int quota = 0, done, num_rx_msdus; int quota = 0, done, ret; bool resched_napi = false; __skb_queue_head_init(&tx_ind_q); /* Since in-ord-ind can deliver more than 1 A-MSDU in single event, * process it first to utilize full available quota. /* Process pending frames before dequeuing more data * from hardware. */ while (quota < budget) { if (skb_queue_empty(&htt->rx_in_ord_compl_q)) break; skb = __skb_dequeue(&htt->rx_in_ord_compl_q); if (!skb) { quota = ath10k_htt_rx_deliver_msdu(ar, quota, budget); if (quota == budget) { resched_napi = true; goto exit; } while ((skb = __skb_dequeue(&htt->rx_in_ord_compl_q))) { spin_lock_bh(&htt->rx_ring.lock); num_rx_msdus = ath10k_htt_rx_in_ord_ind(ar, skb); ret = ath10k_htt_rx_in_ord_ind(ar, skb); spin_unlock_bh(&htt->rx_ring.lock); if (num_rx_msdus < 0) { resched_napi = true; goto exit; } dev_kfree_skb_any(skb); if (num_rx_msdus > 0) quota += num_rx_msdus; if ((quota > ATH10K_NAPI_QUOTA_LIMIT) && !skb_queue_empty(&htt->rx_in_ord_compl_q)) { if (ret == -EIO) { resched_napi = true; goto exit; } } while (quota < budget) { /* no more data to receive */ if (!atomic_read(&htt->num_mpdus_ready)) break; num_rx_msdus = ath10k_htt_rx_handle_amsdu(htt); if (num_rx_msdus < 0) { while (atomic_read(&htt->num_mpdus_ready)) { ret = ath10k_htt_rx_handle_amsdu(htt); if (ret == -EIO) { resched_napi = true; goto exit; } quota += num_rx_msdus; atomic_dec(&htt->num_mpdus_ready); if ((quota > ATH10K_NAPI_QUOTA_LIMIT) && atomic_read(&htt->num_mpdus_ready)) { resched_napi = true; goto exit; } } /* Deliver received data after processing data from hardware */ quota = ath10k_htt_rx_deliver_msdu(ar, quota, budget); /* From NAPI documentation: * The napi poll() function may also process TX completions, in which * case if it processes the entire TX ring then it should count that Loading