xref: /wlan-dirver/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_desc.c (revision 6ecd284e5a94a1c96e26d571dd47419ac305990d)
1 /*
2  * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include "dp_types.h"
20 #include "dp_rx.h"
21 
22 /*
23  * dp_rx_desc_pool_alloc() - create a pool of software rx_descs
24  *			     at the time of dp rx initialization
25  *
26  * @soc: core txrx main context
27  * @pool_id: pool_id which is one of 3 mac_ids
28  * @pool_size: number of Rx descriptor in the pool
29  * @rx_desc_pool: rx descriptor pool pointer
30  *
31  * return success or failure
32  */
33 QDF_STATUS dp_rx_desc_pool_alloc(struct dp_soc *soc, uint32_t pool_id,
34 	uint32_t pool_size, struct rx_desc_pool *rx_desc_pool)
35 {
36 	uint32_t i;
37 
38 	rx_desc_pool->array =
39 		qdf_mem_malloc(pool_size*sizeof(union dp_rx_desc_list_elem_t));
40 
41 	if (!(rx_desc_pool->array)) {
42 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL,
43 			"%s: RX Desc Pool[%d] allocation failed\n",
44 			__func__, pool_id);
45 
46 		return QDF_STATUS_E_NOMEM;
47 	}
48 
49 	/* Initialize the lock */
50 	qdf_spinlock_create(&rx_desc_pool->lock);
51 
52 	qdf_spin_lock_bh(&rx_desc_pool->lock);
53 	rx_desc_pool->pool_size = pool_size;
54 
55 	/* link SW rx descs into a freelist */
56 	rx_desc_pool->freelist = &rx_desc_pool->array[0];
57 	for (i = 0; i < rx_desc_pool->pool_size-1; i++) {
58 		rx_desc_pool->array[i].next = &rx_desc_pool->array[i+1];
59 		rx_desc_pool->array[i].rx_desc.cookie = i | (pool_id << 18);
60 		rx_desc_pool->array[i].rx_desc.pool_id = pool_id;
61 		rx_desc_pool->array[i].rx_desc.in_use = 0;
62 	}
63 
64 	rx_desc_pool->array[i].next = NULL;
65 	rx_desc_pool->array[i].rx_desc.cookie = i | (pool_id << 18);
66 	rx_desc_pool->array[i].rx_desc.pool_id = pool_id;
67 	qdf_spin_unlock_bh(&rx_desc_pool->lock);
68 	return QDF_STATUS_SUCCESS;
69 }
70 
71 /*
72  * dp_rx_desc_pool_free() - free the sw rx desc pool called during
73  *			    de-initialization of wifi module.
74  *
75  * @soc: core txrx main context
76  * @pool_id: pool_id which is one of 3 mac_ids
77  * @rx_desc_pool: rx descriptor pool pointer
78  */
79 void dp_rx_desc_pool_free(struct dp_soc *soc, uint32_t pool_id,
80 	struct rx_desc_pool *rx_desc_pool)
81 {
82 	int i;
83 
84 	qdf_spin_lock_bh(&rx_desc_pool->lock);
85 	for (i = 0; i < rx_desc_pool->pool_size; i++) {
86 		if (rx_desc_pool->array[i].rx_desc.in_use) {
87 			if (!(rx_desc_pool->array[i].rx_desc.unmapped))
88 				qdf_nbuf_unmap_single(soc->osdev,
89 					rx_desc_pool->array[i].rx_desc.nbuf,
90 					QDF_DMA_BIDIRECTIONAL);
91 			qdf_nbuf_free(rx_desc_pool->array[i].rx_desc.nbuf);
92 		}
93 	}
94 	qdf_mem_free(rx_desc_pool->array);
95 	qdf_spin_unlock_bh(&rx_desc_pool->lock);
96 	qdf_spinlock_destroy(&rx_desc_pool->lock);
97 }
98 
99 /*
100  * dp_rx_get_free_desc_list() - provide a list of descriptors from
101  *				the free rx desc pool.
102  *
103  * @soc: core txrx main context
104  * @pool_id: pool_id which is one of 3 mac_ids
105  * @rx_desc_pool: rx descriptor pool pointer
106  * @num_descs: number of descs requested from freelist
107  * @desc_list: attach the descs to this list (output parameter)
108  * @tail: attach the point to last desc of free list (output parameter)
109  *
110  * Return: number of descs allocated from free list.
111  */
112 uint16_t dp_rx_get_free_desc_list(struct dp_soc *soc, uint32_t pool_id,
113 				struct rx_desc_pool *rx_desc_pool,
114 				uint16_t num_descs,
115 				union dp_rx_desc_list_elem_t **desc_list,
116 				union dp_rx_desc_list_elem_t **tail)
117 {
118 	uint16_t count;
119 
120 	qdf_spin_lock_bh(&rx_desc_pool->lock);
121 
122 	*desc_list = *tail = rx_desc_pool->freelist;
123 
124 	for (count = 0; count < num_descs; count++) {
125 
126 		if (qdf_unlikely(!rx_desc_pool->freelist)) {
127 			qdf_spin_unlock_bh(&rx_desc_pool->lock);
128 			return count;
129 		}
130 		*tail = rx_desc_pool->freelist;
131 		rx_desc_pool->freelist = rx_desc_pool->freelist->next;
132 	}
133 	(*tail)->next = NULL;
134 	qdf_spin_unlock_bh(&rx_desc_pool->lock);
135 	return count;
136 }
137 
138 /*
139  * dp_rx_add_desc_list_to_free_list() - append unused desc_list back to
140  *					freelist.
141  *
142  * @soc: core txrx main context
143  * @local_desc_list: local desc list provided by the caller
144  * @tail: attach the point to last desc of local desc list
145  * @pool_id: pool_id which is one of 3 mac_ids
146  * @rx_desc_pool: rx descriptor pool pointer
147  */
148 void dp_rx_add_desc_list_to_free_list(struct dp_soc *soc,
149 				union dp_rx_desc_list_elem_t **local_desc_list,
150 				union dp_rx_desc_list_elem_t **tail,
151 				uint16_t pool_id,
152 				struct rx_desc_pool *rx_desc_pool)
153 {
154 	union dp_rx_desc_list_elem_t *temp_list = NULL;
155 
156 	qdf_spin_lock_bh(&rx_desc_pool->lock);
157 
158 
159 	temp_list = rx_desc_pool->freelist;
160 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
161 	"temp_list: %pK, *local_desc_list: %pK, *tail: %pK (*tail)->next: %pK\n",
162 	temp_list, *local_desc_list, *tail, (*tail)->next);
163 	rx_desc_pool->freelist = *local_desc_list;
164 	(*tail)->next = temp_list;
165 
166 	qdf_spin_unlock_bh(&rx_desc_pool->lock);
167 }
168