Răsfoiți Sursa

qcacld-3.0: Make rx hash look-up SMP safe

Place a big spinlock on the rxhash so that only one
activity happens on it at a time.

Change-Id: Id1a020f508b6232d401d44da1cd0b9592288c81c
CRs-Fixed: 1048807
Orhan K AKYILDIZ 8 ani în urmă
părinte
comite
b257bff22b
2 a modificat fișierele cu 31 adăugiri și 5 ștergeri
  1. 30 5
      core/dp/htt/htt_rx.c
  2. 1 0
      core/dp/htt/htt_types.h

+ 30 - 5
core/dp/htt/htt_rx.c

@@ -127,6 +127,9 @@ void htt_rx_hash_deinit(struct htt_pdev_t *pdev)
 
 	if (NULL == pdev->rx_ring.hash_table)
 		return;
+
+	qdf_spin_lock_bh(&(pdev->rx_ring.rx_hash_lock));
+
 	for (i = 0; i < RX_NUM_HASH_BUCKETS; i++) {
 		/* Free the hash entries in hash bucket i */
 		list_iter = pdev->rx_ring.hash_table[i]->listhead.next;
@@ -157,6 +160,10 @@ void htt_rx_hash_deinit(struct htt_pdev_t *pdev)
 	}
 	qdf_mem_free(pdev->rx_ring.hash_table);
 	pdev->rx_ring.hash_table = NULL;
+
+	qdf_spin_unlock_bh(&(pdev->rx_ring.rx_hash_lock));
+	qdf_spinlock_destroy(&(pdev->rx_ring.rx_hash_lock));
+
 }
 
 /*
@@ -2895,8 +2902,11 @@ htt_rx_hash_list_insert(struct htt_pdev_t *pdev, uint32_t paddr,
 			qdf_nbuf_t netbuf)
 {
 	int i;
+	int rc = 0;
 	struct htt_rx_hash_entry *hash_element = NULL;
 
+	qdf_spin_lock_bh(&(pdev->rx_ring.rx_hash_lock));
+
 	i = RX_HASH_FUNCTION(paddr);
 
 	/* Check if there are any entries in the pre-allocated free list */
@@ -2910,7 +2920,8 @@ htt_rx_hash_list_insert(struct htt_pdev_t *pdev, uint32_t paddr,
 				pdev->rx_ring.listnode_offset);
 		if (qdf_unlikely(NULL == hash_element)) {
 			HTT_ASSERT_ALWAYS(0);
-			return 1;
+			rc = 1;
+			goto hli_end;
 		}
 
 		htt_list_remove(pdev->rx_ring.hash_table[i]->freepool.next);
@@ -2918,7 +2929,8 @@ htt_rx_hash_list_insert(struct htt_pdev_t *pdev, uint32_t paddr,
 		hash_element = qdf_mem_malloc(sizeof(struct htt_rx_hash_entry));
 		if (qdf_unlikely(NULL == hash_element)) {
 			HTT_ASSERT_ALWAYS(0);
-			return 1;
+			rc = 1;
+			goto hli_end;
 		}
 		hash_element->fromlist = 0;
 	}
@@ -2936,7 +2948,9 @@ htt_rx_hash_list_insert(struct htt_pdev_t *pdev, uint32_t paddr,
 	HTT_RX_HASH_COUNT_INCR(pdev->rx_ring.hash_table[i]);
 	HTT_RX_HASH_COUNT_PRINT(pdev->rx_ring.hash_table[i]);
 
-	return 0;
+hli_end:
+	qdf_spin_unlock_bh(&(pdev->rx_ring.rx_hash_lock));
+	return rc;
 }
 
 /* Given a physical address this function will find the corresponding network
@@ -2949,6 +2963,8 @@ qdf_nbuf_t htt_rx_hash_list_lookup(struct htt_pdev_t *pdev, uint32_t paddr)
 	qdf_nbuf_t netbuf = NULL;
 	struct htt_rx_hash_entry *hash_entry;
 
+	qdf_spin_lock_bh(&(pdev->rx_ring.rx_hash_lock));
+
 	i = RX_HASH_FUNCTION(paddr);
 
 	HTT_LIST_ITER_FWD(list_iter, &pdev->rx_ring.hash_table[i]->listhead) {
@@ -2980,6 +2996,8 @@ qdf_nbuf_t htt_rx_hash_list_lookup(struct htt_pdev_t *pdev, uint32_t paddr)
 			      __func__, paddr, netbuf, (int)i));
 	HTT_RX_HASH_COUNT_PRINT(pdev->rx_ring.hash_table[i]);
 
+	qdf_spin_unlock_bh(&(pdev->rx_ring.rx_hash_lock));
+
 	if (netbuf == NULL) {
 		qdf_print("rx hash: %s: no entry found for 0x%x!!!\n",
 			  __func__, paddr);
@@ -2995,6 +3013,7 @@ qdf_nbuf_t htt_rx_hash_list_lookup(struct htt_pdev_t *pdev, uint32_t paddr)
 int htt_rx_hash_init(struct htt_pdev_t *pdev)
 {
 	int i, j;
+	int rc = 0;
 
 	HTT_ASSERT2(QDF_IS_PWR2(RX_NUM_HASH_BUCKETS));
 
@@ -3008,6 +3027,9 @@ int htt_rx_hash_init(struct htt_pdev_t *pdev)
 		return 1;
 	}
 
+	qdf_spinlock_create(&(pdev->rx_ring.rx_hash_lock));
+	qdf_spin_lock_bh(&(pdev->rx_ring.rx_hash_lock));
+
 	for (i = 0; i < RX_NUM_HASH_BUCKETS; i++) {
 
 		/* pre-allocate bucket and pool of entries for this bucket */
@@ -3038,7 +3060,8 @@ int htt_rx_hash_init(struct htt_pdev_t *pdev)
 			}
 			qdf_mem_free(pdev->rx_ring.hash_table);
 			pdev->rx_ring.hash_table = NULL;
-			return 1;
+			rc = 1;
+			goto hi_end;
 		}
 
 		/* initialize the free list with pre-allocated entries */
@@ -3052,8 +3075,10 @@ int htt_rx_hash_init(struct htt_pdev_t *pdev)
 
 	pdev->rx_ring.listnode_offset =
 		qdf_offsetof(struct htt_rx_hash_entry, listnode);
+hi_end:
+	qdf_spin_unlock_bh(&(pdev->rx_ring.rx_hash_lock));
 
-	return 0;
+	return rc;
 }
 
 void htt_rx_hash_dump_table(struct htt_pdev_t *pdev)

+ 1 - 0
core/dp/htt/htt_types.h

@@ -358,6 +358,7 @@ struct htt_pdev_t {
 		int rx_reset;
 		uint8_t htt_rx_restore;
 #endif
+		qdf_spinlock_t rx_hash_lock;
 		struct htt_rx_hash_bucket **hash_table;
 		uint32_t listnode_offset;
 	} rx_ring;