summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOrhan K AKYILDIZ <oka@codeaurora.org>2016-09-28 19:06:50 -0700
committerqcabuildsw <qcabuildsw@localhost>2016-10-03 17:38:31 -0700
commit5f0ff7223866ac01be220d10f4fe6cc83dfdb31e (patch)
treee72bc31f53794d76a3a450d71819d6fc2f5e347c
parent7a65740e470c3e3ccd80940dd7b5aee1743ce8a3 (diff)
qcacld-3.0: Fix multiple adapter LRO flush issue
A new adapter overwrite previous adapter information for LRO flush callback, causing LRO packets for that adapter not being flushed and sit in the LRO manager queues. LRO flush now walks through the adapter list and flushes for every LRO-enabled adapter. Change-Id: I4c882a6521759c1c8fa05b9d9be4134feabd08aa CRs-Fixed: 1072471
-rw-r--r--core/hdd/src/wlan_hdd_lro.c47
1 files changed, 37 insertions, 10 deletions
diff --git a/core/hdd/src/wlan_hdd_lro.c b/core/hdd/src/wlan_hdd_lro.c
index b1fe8f078d52..dde5d9e4fc01 100644
--- a/core/hdd/src/wlan_hdd_lro.c
+++ b/core/hdd/src/wlan_hdd_lro.c
@@ -442,20 +442,47 @@ void hdd_lro_flush_pkt(struct net_lro_mgr *lro_mgr,
void hdd_lro_flush(void *data)
{
hdd_adapter_t *adapter = (hdd_adapter_t *)data;
- struct hdd_lro_s *hdd_lro = &adapter->lro_info;
+ struct hdd_lro_s *hdd_lro;
+ struct hdd_context_s *ctx;
+ QDF_STATUS status;
+ hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
int i;
- qdf_spin_lock_bh(&hdd_lro->lro_mgr_arr_access_lock);
- for (i = 0; i < adapter->lro_info.lro_mgr->max_desc; i++) {
- if (adapter->lro_info.lro_mgr->lro_arr[i].active) {
- hdd_lro_desc_free(
- &adapter->lro_info.lro_mgr->lro_arr[i],
- (void *)adapter);
- lro_flush_desc(adapter->lro_info.lro_mgr,
- &adapter->lro_info.lro_mgr->lro_arr[i]);
+ /*
+ * There is a more comprehensive solution that refactors
+ * lro_mgr in the adapter into multiple instances, that
+ * will replace this solution. The following is an interim
+ * fix.
+ */
+
+ /* Loop over all adapters and flush them all */
+ ctx = (struct hdd_context_s *)cds_get_context(QDF_MODULE_ID_HDD);
+ if (unlikely(ctx == NULL)) {
+ hdd_err("%s: cannot get hdd_ctx. Flushing failed", __func__);
+ return;
+ }
+
+ status = hdd_get_front_adapter(ctx, &adapter_node);
+ while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
+ adapter = adapter_node->pAdapter;
+ hdd_lro = &adapter->lro_info;
+ if (adapter->dev->features & NETIF_F_LRO) {
+ qdf_spin_lock_bh(&hdd_lro->lro_mgr_arr_access_lock);
+ for (i = 0; i < hdd_lro->lro_mgr->max_desc; i++) {
+ if (hdd_lro->lro_mgr->lro_arr[i].active) {
+ hdd_lro_desc_free(
+ &hdd_lro->lro_mgr->lro_arr[i],
+ (void *)adapter);
+ lro_flush_desc(
+ hdd_lro->lro_mgr,
+ &hdd_lro->lro_mgr->lro_arr[i]);
+ }
+ }
+ qdf_spin_unlock_bh(&hdd_lro->lro_mgr_arr_access_lock);
}
+ status = hdd_get_next_adapter(ctx, adapter_node, &next);
+ adapter_node = next;
}
- qdf_spin_unlock_bh(&hdd_lro->lro_mgr_arr_access_lock);
}
/**