diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c index 78d7aa808697..e513a06d13f7 100644 --- a/core/hdd/src/wlan_hdd_ipa.c +++ b/core/hdd/src/wlan_hdd_ipa.c @@ -91,6 +91,8 @@ #define HDD_IPA_MAX_PENDING_EVENT_COUNT 20 +#define IPA_WLAN_RX_SOFTIRQ_THRESH 16 + enum hdd_ipa_uc_op_code { HDD_IPA_UC_OPCODE_TX_SUSPEND = 0, HDD_IPA_UC_OPCODE_TX_RESUME = 1, @@ -4076,6 +4078,40 @@ static void hdd_ipa_destroy_rm_resource(struct hdd_ipa_priv *hdd_ipa) "RM CONS resource delete failed %d", ret); } +#ifdef QCA_CONFIG_SMP +static int hdd_ipa_aggregated_rx_ind(qdf_nbuf_t skb) +{ + return netif_rx_ni(skb); +} +#else +static int hdd_ipa_aggregated_rx_ind(qdf_nbuf_t skb) +{ + struct iphdr *ip_h; + static atomic_t softirq_mitigation_cntr = + ATOMIC_INIT(IPA_WLAN_RX_SOFTIRQ_THRESH); + int result; + + ip_h = (struct iphdr *)(skb->data); + if ((skb->protocol == htons(ETH_P_IP)) && + (ip_h->protocol == IPPROTO_ICMP)) { + result = netif_rx_ni(skb); + } else { + /* Call netif_rx_ni for every IPA_WLAN_RX_SOFTIRQ_THRESH packets + * to avoid excessive softirq's. + */ + if (atomic_dec_and_test(&softirq_mitigation_cntr)) { + result = netif_rx_ni(skb); + atomic_set(&softirq_mitigation_cntr, + IPA_WLAN_RX_SOFTIRQ_THRESH); + } else { + result = netif_rx(skb); + } + } + + return result; +} +#endif + /** * hdd_ipa_send_skb_to_network() - Send skb to kernel * @skb: network buffer @@ -4089,6 +4125,7 @@ static void hdd_ipa_destroy_rm_resource(struct hdd_ipa_priv *hdd_ipa) static void hdd_ipa_send_skb_to_network(qdf_nbuf_t skb, hdd_adapter_t *adapter) { + int result; struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; unsigned int cpu_index; @@ -4114,7 +4151,8 @@ static void hdd_ipa_send_skb_to_network(qdf_nbuf_t skb, cpu_index = wlan_hdd_get_cpu(); ++adapter->hdd_stats.hddTxRxStats.rxPackets[cpu_index]; - if (netif_rx_ni(skb) == NET_RX_SUCCESS) + result = hdd_ipa_aggregated_rx_ind(skb); + if (result == NET_RX_SUCCESS) ++adapter->hdd_stats.hddTxRxStats.rxDelivered[cpu_index]; else ++adapter->hdd_stats.hddTxRxStats.rxRefused[cpu_index];