xref: /dpdk/drivers/crypto/ccp/ccp_dev.c (revision 3c20cf98e2c99e6178585299056f3fb6d08467f3)
1ef4b04f8SRavi Kumar /*   SPDX-License-Identifier: BSD-3-Clause
2ef4b04f8SRavi Kumar  *   Copyright(c) 2018 Advanced Micro Devices, Inc. All rights reserved.
3ef4b04f8SRavi Kumar  */
4ef4b04f8SRavi Kumar 
5ef4b04f8SRavi Kumar #include <dirent.h>
6ef4b04f8SRavi Kumar #include <fcntl.h>
7ef4b04f8SRavi Kumar #include <stdio.h>
8ef4b04f8SRavi Kumar #include <string.h>
9ef4b04f8SRavi Kumar #include <sys/mman.h>
10ef4b04f8SRavi Kumar #include <sys/queue.h>
11ef4b04f8SRavi Kumar #include <sys/types.h>
12ef4b04f8SRavi Kumar #include <sys/file.h>
13ef4b04f8SRavi Kumar #include <unistd.h>
14ef4b04f8SRavi Kumar 
15ef4b04f8SRavi Kumar #include <rte_hexdump.h>
16ef4b04f8SRavi Kumar #include <rte_memzone.h>
17ef4b04f8SRavi Kumar #include <rte_malloc.h>
18ef4b04f8SRavi Kumar #include <rte_memory.h>
19ef4b04f8SRavi Kumar #include <rte_spinlock.h>
20ef4b04f8SRavi Kumar #include <rte_string_fns.h>
21ef4b04f8SRavi Kumar 
22ef4b04f8SRavi Kumar #include "ccp_dev.h"
23ef4b04f8SRavi Kumar #include "ccp_pci.h"
24ef4b04f8SRavi Kumar #include "ccp_pmd_private.h"
25ef4b04f8SRavi Kumar 
26ef4b04f8SRavi Kumar struct ccp_list ccp_list = TAILQ_HEAD_INITIALIZER(ccp_list);
27ef4b04f8SRavi Kumar static int ccp_dev_id;
28ef4b04f8SRavi Kumar 
29*3c20cf98SRavi Kumar int
30*3c20cf98SRavi Kumar ccp_dev_start(struct rte_cryptodev *dev)
31*3c20cf98SRavi Kumar {
32*3c20cf98SRavi Kumar 	struct ccp_private *priv = dev->data->dev_private;
33*3c20cf98SRavi Kumar 
34*3c20cf98SRavi Kumar 	priv->last_dev = TAILQ_FIRST(&ccp_list);
35*3c20cf98SRavi Kumar 	return 0;
36*3c20cf98SRavi Kumar }
37*3c20cf98SRavi Kumar 
38ef4b04f8SRavi Kumar static const struct rte_memzone *
39ef4b04f8SRavi Kumar ccp_queue_dma_zone_reserve(const char *queue_name,
40ef4b04f8SRavi Kumar 			   uint32_t queue_size,
41ef4b04f8SRavi Kumar 			   int socket_id)
42ef4b04f8SRavi Kumar {
43ef4b04f8SRavi Kumar 	const struct rte_memzone *mz;
44ef4b04f8SRavi Kumar 
45ef4b04f8SRavi Kumar 	mz = rte_memzone_lookup(queue_name);
46ef4b04f8SRavi Kumar 	if (mz != 0) {
47ef4b04f8SRavi Kumar 		if (((size_t)queue_size <= mz->len) &&
48ef4b04f8SRavi Kumar 		    ((socket_id == SOCKET_ID_ANY) ||
49ef4b04f8SRavi Kumar 		     (socket_id == mz->socket_id))) {
50ef4b04f8SRavi Kumar 			CCP_LOG_INFO("re-use memzone already "
51ef4b04f8SRavi Kumar 				     "allocated for %s", queue_name);
52ef4b04f8SRavi Kumar 			return mz;
53ef4b04f8SRavi Kumar 		}
54ef4b04f8SRavi Kumar 		CCP_LOG_ERR("Incompatible memzone already "
55ef4b04f8SRavi Kumar 			    "allocated %s, size %u, socket %d. "
56ef4b04f8SRavi Kumar 			    "Requested size %u, socket %u",
57ef4b04f8SRavi Kumar 			    queue_name, (uint32_t)mz->len,
58ef4b04f8SRavi Kumar 			    mz->socket_id, queue_size, socket_id);
59ef4b04f8SRavi Kumar 		return NULL;
60ef4b04f8SRavi Kumar 	}
61ef4b04f8SRavi Kumar 
62ef4b04f8SRavi Kumar 	CCP_LOG_INFO("Allocate memzone for %s, size %u on socket %u",
63ef4b04f8SRavi Kumar 		     queue_name, queue_size, socket_id);
64ef4b04f8SRavi Kumar 
65ef4b04f8SRavi Kumar 	return rte_memzone_reserve_aligned(queue_name, queue_size,
66ef4b04f8SRavi Kumar 			socket_id, RTE_MEMZONE_IOVA_CONTIG, queue_size);
67ef4b04f8SRavi Kumar }
68ef4b04f8SRavi Kumar 
69ef4b04f8SRavi Kumar /* bitmap support apis */
70ef4b04f8SRavi Kumar static inline void
71ef4b04f8SRavi Kumar ccp_set_bit(unsigned long *bitmap, int n)
72ef4b04f8SRavi Kumar {
73ef4b04f8SRavi Kumar 	__sync_fetch_and_or(&bitmap[WORD_OFFSET(n)], (1UL << BIT_OFFSET(n)));
74ef4b04f8SRavi Kumar }
75ef4b04f8SRavi Kumar 
76ef4b04f8SRavi Kumar static inline void
77ef4b04f8SRavi Kumar ccp_clear_bit(unsigned long *bitmap, int n)
78ef4b04f8SRavi Kumar {
79ef4b04f8SRavi Kumar 	__sync_fetch_and_and(&bitmap[WORD_OFFSET(n)], ~(1UL << BIT_OFFSET(n)));
80ef4b04f8SRavi Kumar }
81ef4b04f8SRavi Kumar 
82ef4b04f8SRavi Kumar static inline uint32_t
83ef4b04f8SRavi Kumar ccp_get_bit(unsigned long *bitmap, int n)
84ef4b04f8SRavi Kumar {
85ef4b04f8SRavi Kumar 	return ((bitmap[WORD_OFFSET(n)] & (1 << BIT_OFFSET(n))) != 0);
86ef4b04f8SRavi Kumar }
87ef4b04f8SRavi Kumar 
88ef4b04f8SRavi Kumar 
89ef4b04f8SRavi Kumar static inline uint32_t
90ef4b04f8SRavi Kumar ccp_ffz(unsigned long word)
91ef4b04f8SRavi Kumar {
92ef4b04f8SRavi Kumar 	unsigned long first_zero;
93ef4b04f8SRavi Kumar 
94ef4b04f8SRavi Kumar 	first_zero = __builtin_ffsl(~word);
95ef4b04f8SRavi Kumar 	return first_zero ? (first_zero - 1) :
96ef4b04f8SRavi Kumar 		BITS_PER_WORD;
97ef4b04f8SRavi Kumar }
98ef4b04f8SRavi Kumar 
99ef4b04f8SRavi Kumar static inline uint32_t
100ef4b04f8SRavi Kumar ccp_find_first_zero_bit(unsigned long *addr, uint32_t limit)
101ef4b04f8SRavi Kumar {
102ef4b04f8SRavi Kumar 	uint32_t i;
103ef4b04f8SRavi Kumar 	uint32_t nwords = 0;
104ef4b04f8SRavi Kumar 
105ef4b04f8SRavi Kumar 	nwords = (limit - 1) / BITS_PER_WORD + 1;
106ef4b04f8SRavi Kumar 	for (i = 0; i < nwords; i++) {
107ef4b04f8SRavi Kumar 		if (addr[i] == 0UL)
108ef4b04f8SRavi Kumar 			return i * BITS_PER_WORD;
109ef4b04f8SRavi Kumar 		if (addr[i] < ~(0UL))
110ef4b04f8SRavi Kumar 			break;
111ef4b04f8SRavi Kumar 	}
112ef4b04f8SRavi Kumar 	return (i == nwords) ? limit : i * BITS_PER_WORD + ccp_ffz(addr[i]);
113ef4b04f8SRavi Kumar }
114ef4b04f8SRavi Kumar 
115ef4b04f8SRavi Kumar static void
116ef4b04f8SRavi Kumar ccp_bitmap_set(unsigned long *map, unsigned int start, int len)
117ef4b04f8SRavi Kumar {
118ef4b04f8SRavi Kumar 	unsigned long *p = map + WORD_OFFSET(start);
119ef4b04f8SRavi Kumar 	const unsigned int size = start + len;
120ef4b04f8SRavi Kumar 	int bits_to_set = BITS_PER_WORD - (start % BITS_PER_WORD);
121ef4b04f8SRavi Kumar 	unsigned long mask_to_set = CCP_BITMAP_FIRST_WORD_MASK(start);
122ef4b04f8SRavi Kumar 
123ef4b04f8SRavi Kumar 	while (len - bits_to_set >= 0) {
124ef4b04f8SRavi Kumar 		*p |= mask_to_set;
125ef4b04f8SRavi Kumar 		len -= bits_to_set;
126ef4b04f8SRavi Kumar 		bits_to_set = BITS_PER_WORD;
127ef4b04f8SRavi Kumar 		mask_to_set = ~0UL;
128ef4b04f8SRavi Kumar 		p++;
129ef4b04f8SRavi Kumar 	}
130ef4b04f8SRavi Kumar 	if (len) {
131ef4b04f8SRavi Kumar 		mask_to_set &= CCP_BITMAP_LAST_WORD_MASK(size);
132ef4b04f8SRavi Kumar 		*p |= mask_to_set;
133ef4b04f8SRavi Kumar 	}
134ef4b04f8SRavi Kumar }
135ef4b04f8SRavi Kumar 
136ef4b04f8SRavi Kumar static void
137ef4b04f8SRavi Kumar ccp_bitmap_clear(unsigned long *map, unsigned int start, int len)
138ef4b04f8SRavi Kumar {
139ef4b04f8SRavi Kumar 	unsigned long *p = map + WORD_OFFSET(start);
140ef4b04f8SRavi Kumar 	const unsigned int size = start + len;
141ef4b04f8SRavi Kumar 	int bits_to_clear = BITS_PER_WORD - (start % BITS_PER_WORD);
142ef4b04f8SRavi Kumar 	unsigned long mask_to_clear = CCP_BITMAP_FIRST_WORD_MASK(start);
143ef4b04f8SRavi Kumar 
144ef4b04f8SRavi Kumar 	while (len - bits_to_clear >= 0) {
145ef4b04f8SRavi Kumar 		*p &= ~mask_to_clear;
146ef4b04f8SRavi Kumar 		len -= bits_to_clear;
147ef4b04f8SRavi Kumar 		bits_to_clear = BITS_PER_WORD;
148ef4b04f8SRavi Kumar 		mask_to_clear = ~0UL;
149ef4b04f8SRavi Kumar 		p++;
150ef4b04f8SRavi Kumar 	}
151ef4b04f8SRavi Kumar 	if (len) {
152ef4b04f8SRavi Kumar 		mask_to_clear &= CCP_BITMAP_LAST_WORD_MASK(size);
153ef4b04f8SRavi Kumar 		*p &= ~mask_to_clear;
154ef4b04f8SRavi Kumar 	}
155ef4b04f8SRavi Kumar }
156ef4b04f8SRavi Kumar 
157ef4b04f8SRavi Kumar 
158ef4b04f8SRavi Kumar static unsigned long
159ef4b04f8SRavi Kumar _ccp_find_next_bit(const unsigned long *addr,
160ef4b04f8SRavi Kumar 		   unsigned long nbits,
161ef4b04f8SRavi Kumar 		   unsigned long start,
162ef4b04f8SRavi Kumar 		   unsigned long invert)
163ef4b04f8SRavi Kumar {
164ef4b04f8SRavi Kumar 	unsigned long tmp;
165ef4b04f8SRavi Kumar 
166ef4b04f8SRavi Kumar 	if (!nbits || start >= nbits)
167ef4b04f8SRavi Kumar 		return nbits;
168ef4b04f8SRavi Kumar 
169ef4b04f8SRavi Kumar 	tmp = addr[start / BITS_PER_WORD] ^ invert;
170ef4b04f8SRavi Kumar 
171ef4b04f8SRavi Kumar 	/* Handle 1st word. */
172ef4b04f8SRavi Kumar 	tmp &= CCP_BITMAP_FIRST_WORD_MASK(start);
173ef4b04f8SRavi Kumar 	start = ccp_round_down(start, BITS_PER_WORD);
174ef4b04f8SRavi Kumar 
175ef4b04f8SRavi Kumar 	while (!tmp) {
176ef4b04f8SRavi Kumar 		start += BITS_PER_WORD;
177ef4b04f8SRavi Kumar 		if (start >= nbits)
178ef4b04f8SRavi Kumar 			return nbits;
179ef4b04f8SRavi Kumar 
180ef4b04f8SRavi Kumar 		tmp = addr[start / BITS_PER_WORD] ^ invert;
181ef4b04f8SRavi Kumar 	}
182ef4b04f8SRavi Kumar 
183ef4b04f8SRavi Kumar 	return RTE_MIN(start + (ffs(tmp) - 1), nbits);
184ef4b04f8SRavi Kumar }
185ef4b04f8SRavi Kumar 
186ef4b04f8SRavi Kumar static unsigned long
187ef4b04f8SRavi Kumar ccp_find_next_bit(const unsigned long *addr,
188ef4b04f8SRavi Kumar 		  unsigned long size,
189ef4b04f8SRavi Kumar 		  unsigned long offset)
190ef4b04f8SRavi Kumar {
191ef4b04f8SRavi Kumar 	return _ccp_find_next_bit(addr, size, offset, 0UL);
192ef4b04f8SRavi Kumar }
193ef4b04f8SRavi Kumar 
194ef4b04f8SRavi Kumar static unsigned long
195ef4b04f8SRavi Kumar ccp_find_next_zero_bit(const unsigned long *addr,
196ef4b04f8SRavi Kumar 		       unsigned long size,
197ef4b04f8SRavi Kumar 		       unsigned long offset)
198ef4b04f8SRavi Kumar {
199ef4b04f8SRavi Kumar 	return _ccp_find_next_bit(addr, size, offset, ~0UL);
200ef4b04f8SRavi Kumar }
201ef4b04f8SRavi Kumar 
202ef4b04f8SRavi Kumar /**
203ef4b04f8SRavi Kumar  * bitmap_find_next_zero_area - find a contiguous aligned zero area
204ef4b04f8SRavi Kumar  * @map: The address to base the search on
205ef4b04f8SRavi Kumar  * @size: The bitmap size in bits
206ef4b04f8SRavi Kumar  * @start: The bitnumber to start searching at
207ef4b04f8SRavi Kumar  * @nr: The number of zeroed bits we're looking for
208ef4b04f8SRavi Kumar  */
209ef4b04f8SRavi Kumar static unsigned long
210ef4b04f8SRavi Kumar ccp_bitmap_find_next_zero_area(unsigned long *map,
211ef4b04f8SRavi Kumar 			       unsigned long size,
212ef4b04f8SRavi Kumar 			       unsigned long start,
213ef4b04f8SRavi Kumar 			       unsigned int nr)
214ef4b04f8SRavi Kumar {
215ef4b04f8SRavi Kumar 	unsigned long index, end, i;
216ef4b04f8SRavi Kumar 
217ef4b04f8SRavi Kumar again:
218ef4b04f8SRavi Kumar 	index = ccp_find_next_zero_bit(map, size, start);
219ef4b04f8SRavi Kumar 
220ef4b04f8SRavi Kumar 	end = index + nr;
221ef4b04f8SRavi Kumar 	if (end > size)
222ef4b04f8SRavi Kumar 		return end;
223ef4b04f8SRavi Kumar 	i = ccp_find_next_bit(map, end, index);
224ef4b04f8SRavi Kumar 	if (i < end) {
225ef4b04f8SRavi Kumar 		start = i + 1;
226ef4b04f8SRavi Kumar 		goto again;
227ef4b04f8SRavi Kumar 	}
228ef4b04f8SRavi Kumar 	return index;
229ef4b04f8SRavi Kumar }
230ef4b04f8SRavi Kumar 
231ef4b04f8SRavi Kumar static uint32_t
232ef4b04f8SRavi Kumar ccp_lsb_alloc(struct ccp_queue *cmd_q, unsigned int count)
233ef4b04f8SRavi Kumar {
234ef4b04f8SRavi Kumar 	struct ccp_device *ccp;
235ef4b04f8SRavi Kumar 	int start;
236ef4b04f8SRavi Kumar 
237ef4b04f8SRavi Kumar 	/* First look at the map for the queue */
238ef4b04f8SRavi Kumar 	if (cmd_q->lsb >= 0) {
239ef4b04f8SRavi Kumar 		start = (uint32_t)ccp_bitmap_find_next_zero_area(cmd_q->lsbmap,
240ef4b04f8SRavi Kumar 								 LSB_SIZE, 0,
241ef4b04f8SRavi Kumar 								 count);
242ef4b04f8SRavi Kumar 		if (start < LSB_SIZE) {
243ef4b04f8SRavi Kumar 			ccp_bitmap_set(cmd_q->lsbmap, start, count);
244ef4b04f8SRavi Kumar 			return start + cmd_q->lsb * LSB_SIZE;
245ef4b04f8SRavi Kumar 		}
246ef4b04f8SRavi Kumar 	}
247ef4b04f8SRavi Kumar 
248ef4b04f8SRavi Kumar 	/* try to get an entry from the shared blocks */
249ef4b04f8SRavi Kumar 	ccp = cmd_q->dev;
250ef4b04f8SRavi Kumar 
251ef4b04f8SRavi Kumar 	rte_spinlock_lock(&ccp->lsb_lock);
252ef4b04f8SRavi Kumar 
253ef4b04f8SRavi Kumar 	start = (uint32_t)ccp_bitmap_find_next_zero_area(ccp->lsbmap,
254ef4b04f8SRavi Kumar 						    MAX_LSB_CNT * LSB_SIZE,
255ef4b04f8SRavi Kumar 						    0, count);
256ef4b04f8SRavi Kumar 	if (start <= MAX_LSB_CNT * LSB_SIZE) {
257ef4b04f8SRavi Kumar 		ccp_bitmap_set(ccp->lsbmap, start, count);
258ef4b04f8SRavi Kumar 		rte_spinlock_unlock(&ccp->lsb_lock);
259ef4b04f8SRavi Kumar 		return start * LSB_ITEM_SIZE;
260ef4b04f8SRavi Kumar 	}
261ef4b04f8SRavi Kumar 	CCP_LOG_ERR("NO LSBs available");
262ef4b04f8SRavi Kumar 
263ef4b04f8SRavi Kumar 	rte_spinlock_unlock(&ccp->lsb_lock);
264ef4b04f8SRavi Kumar 
265ef4b04f8SRavi Kumar 	return 0;
266ef4b04f8SRavi Kumar }
267ef4b04f8SRavi Kumar 
268ef4b04f8SRavi Kumar static void __rte_unused
269ef4b04f8SRavi Kumar ccp_lsb_free(struct ccp_queue *cmd_q,
270ef4b04f8SRavi Kumar 	     unsigned int start,
271ef4b04f8SRavi Kumar 	     unsigned int count)
272ef4b04f8SRavi Kumar {
273ef4b04f8SRavi Kumar 	int lsbno = start / LSB_SIZE;
274ef4b04f8SRavi Kumar 
275ef4b04f8SRavi Kumar 	if (!start)
276ef4b04f8SRavi Kumar 		return;
277ef4b04f8SRavi Kumar 
278ef4b04f8SRavi Kumar 	if (cmd_q->lsb == lsbno) {
279ef4b04f8SRavi Kumar 		/* An entry from the private LSB */
280ef4b04f8SRavi Kumar 		ccp_bitmap_clear(cmd_q->lsbmap, start % LSB_SIZE, count);
281ef4b04f8SRavi Kumar 	} else {
282ef4b04f8SRavi Kumar 		/* From the shared LSBs */
283ef4b04f8SRavi Kumar 		struct ccp_device *ccp = cmd_q->dev;
284ef4b04f8SRavi Kumar 
285ef4b04f8SRavi Kumar 		rte_spinlock_lock(&ccp->lsb_lock);
286ef4b04f8SRavi Kumar 		ccp_bitmap_clear(ccp->lsbmap, start, count);
287ef4b04f8SRavi Kumar 		rte_spinlock_unlock(&ccp->lsb_lock);
288ef4b04f8SRavi Kumar 	}
289ef4b04f8SRavi Kumar }
290ef4b04f8SRavi Kumar 
291ef4b04f8SRavi Kumar static int
292ef4b04f8SRavi Kumar ccp_find_lsb_regions(struct ccp_queue *cmd_q, uint64_t status)
293ef4b04f8SRavi Kumar {
294ef4b04f8SRavi Kumar 	int q_mask = 1 << cmd_q->id;
295ef4b04f8SRavi Kumar 	int weight = 0;
296ef4b04f8SRavi Kumar 	int j;
297ef4b04f8SRavi Kumar 
298ef4b04f8SRavi Kumar 	/* Build a bit mask to know which LSBs
299ef4b04f8SRavi Kumar 	 * this queue has access to.
300ef4b04f8SRavi Kumar 	 * Don't bother with segment 0
301ef4b04f8SRavi Kumar 	 * as it has special
302ef4b04f8SRavi Kumar 	 * privileges.
303ef4b04f8SRavi Kumar 	 */
304ef4b04f8SRavi Kumar 	cmd_q->lsbmask = 0;
305ef4b04f8SRavi Kumar 	status >>= LSB_REGION_WIDTH;
306ef4b04f8SRavi Kumar 	for (j = 1; j < MAX_LSB_CNT; j++) {
307ef4b04f8SRavi Kumar 		if (status & q_mask)
308ef4b04f8SRavi Kumar 			ccp_set_bit(&cmd_q->lsbmask, j);
309ef4b04f8SRavi Kumar 
310ef4b04f8SRavi Kumar 		status >>= LSB_REGION_WIDTH;
311ef4b04f8SRavi Kumar 	}
312ef4b04f8SRavi Kumar 
313ef4b04f8SRavi Kumar 	for (j = 0; j < MAX_LSB_CNT; j++)
314ef4b04f8SRavi Kumar 		if (ccp_get_bit(&cmd_q->lsbmask, j))
315ef4b04f8SRavi Kumar 			weight++;
316ef4b04f8SRavi Kumar 
317ef4b04f8SRavi Kumar 	printf("Queue %d can access %d LSB regions  of mask  %lu\n",
318ef4b04f8SRavi Kumar 	       (int)cmd_q->id, weight, cmd_q->lsbmask);
319ef4b04f8SRavi Kumar 
320ef4b04f8SRavi Kumar 	return weight ? 0 : -EINVAL;
321ef4b04f8SRavi Kumar }
322ef4b04f8SRavi Kumar 
323ef4b04f8SRavi Kumar static int
324ef4b04f8SRavi Kumar ccp_find_and_assign_lsb_to_q(struct ccp_device *ccp,
325ef4b04f8SRavi Kumar 			     int lsb_cnt, int n_lsbs,
326ef4b04f8SRavi Kumar 			     unsigned long *lsb_pub)
327ef4b04f8SRavi Kumar {
328ef4b04f8SRavi Kumar 	unsigned long qlsb = 0;
329ef4b04f8SRavi Kumar 	int bitno = 0;
330ef4b04f8SRavi Kumar 	int qlsb_wgt = 0;
331ef4b04f8SRavi Kumar 	int i, j;
332ef4b04f8SRavi Kumar 
333ef4b04f8SRavi Kumar 	/* For each queue:
334ef4b04f8SRavi Kumar 	 * If the count of potential LSBs available to a queue matches the
335ef4b04f8SRavi Kumar 	 * ordinal given to us in lsb_cnt:
336ef4b04f8SRavi Kumar 	 * Copy the mask of possible LSBs for this queue into "qlsb";
337ef4b04f8SRavi Kumar 	 * For each bit in qlsb, see if the corresponding bit in the
338ef4b04f8SRavi Kumar 	 * aggregation mask is set; if so, we have a match.
339ef4b04f8SRavi Kumar 	 *     If we have a match, clear the bit in the aggregation to
340ef4b04f8SRavi Kumar 	 *     mark it as no longer available.
341ef4b04f8SRavi Kumar 	 *     If there is no match, clear the bit in qlsb and keep looking.
342ef4b04f8SRavi Kumar 	 */
343ef4b04f8SRavi Kumar 	for (i = 0; i < ccp->cmd_q_count; i++) {
344ef4b04f8SRavi Kumar 		struct ccp_queue *cmd_q = &ccp->cmd_q[i];
345ef4b04f8SRavi Kumar 
346ef4b04f8SRavi Kumar 		qlsb_wgt = 0;
347ef4b04f8SRavi Kumar 		for (j = 0; j < MAX_LSB_CNT; j++)
348ef4b04f8SRavi Kumar 			if (ccp_get_bit(&cmd_q->lsbmask, j))
349ef4b04f8SRavi Kumar 				qlsb_wgt++;
350ef4b04f8SRavi Kumar 
351ef4b04f8SRavi Kumar 		if (qlsb_wgt == lsb_cnt) {
352ef4b04f8SRavi Kumar 			qlsb = cmd_q->lsbmask;
353ef4b04f8SRavi Kumar 
354ef4b04f8SRavi Kumar 			bitno = ffs(qlsb) - 1;
355ef4b04f8SRavi Kumar 			while (bitno < MAX_LSB_CNT) {
356ef4b04f8SRavi Kumar 				if (ccp_get_bit(lsb_pub, bitno)) {
357ef4b04f8SRavi Kumar 					/* We found an available LSB
358ef4b04f8SRavi Kumar 					 * that this queue can access
359ef4b04f8SRavi Kumar 					 */
360ef4b04f8SRavi Kumar 					cmd_q->lsb = bitno;
361ef4b04f8SRavi Kumar 					ccp_clear_bit(lsb_pub, bitno);
362ef4b04f8SRavi Kumar 					break;
363ef4b04f8SRavi Kumar 				}
364ef4b04f8SRavi Kumar 				ccp_clear_bit(&qlsb, bitno);
365ef4b04f8SRavi Kumar 				bitno = ffs(qlsb) - 1;
366ef4b04f8SRavi Kumar 			}
367ef4b04f8SRavi Kumar 			if (bitno >= MAX_LSB_CNT)
368ef4b04f8SRavi Kumar 				return -EINVAL;
369ef4b04f8SRavi Kumar 			n_lsbs--;
370ef4b04f8SRavi Kumar 		}
371ef4b04f8SRavi Kumar 	}
372ef4b04f8SRavi Kumar 	return n_lsbs;
373ef4b04f8SRavi Kumar }
374ef4b04f8SRavi Kumar 
375ef4b04f8SRavi Kumar /* For each queue, from the most- to least-constrained:
376ef4b04f8SRavi Kumar  * find an LSB that can be assigned to the queue. If there are N queues that
377ef4b04f8SRavi Kumar  * can only use M LSBs, where N > M, fail; otherwise, every queue will get a
378ef4b04f8SRavi Kumar  * dedicated LSB. Remaining LSB regions become a shared resource.
379ef4b04f8SRavi Kumar  * If we have fewer LSBs than queues, all LSB regions become shared
380ef4b04f8SRavi Kumar  * resources.
381ef4b04f8SRavi Kumar  */
382ef4b04f8SRavi Kumar static int
383ef4b04f8SRavi Kumar ccp_assign_lsbs(struct ccp_device *ccp)
384ef4b04f8SRavi Kumar {
385ef4b04f8SRavi Kumar 	unsigned long lsb_pub = 0, qlsb = 0;
386ef4b04f8SRavi Kumar 	int n_lsbs = 0;
387ef4b04f8SRavi Kumar 	int bitno;
388ef4b04f8SRavi Kumar 	int i, lsb_cnt;
389ef4b04f8SRavi Kumar 	int rc = 0;
390ef4b04f8SRavi Kumar 
391ef4b04f8SRavi Kumar 	rte_spinlock_init(&ccp->lsb_lock);
392ef4b04f8SRavi Kumar 
393ef4b04f8SRavi Kumar 	/* Create an aggregate bitmap to get a total count of available LSBs */
394ef4b04f8SRavi Kumar 	for (i = 0; i < ccp->cmd_q_count; i++)
395ef4b04f8SRavi Kumar 		lsb_pub |= ccp->cmd_q[i].lsbmask;
396ef4b04f8SRavi Kumar 
397ef4b04f8SRavi Kumar 	for (i = 0; i < MAX_LSB_CNT; i++)
398ef4b04f8SRavi Kumar 		if (ccp_get_bit(&lsb_pub, i))
399ef4b04f8SRavi Kumar 			n_lsbs++;
400ef4b04f8SRavi Kumar 
401ef4b04f8SRavi Kumar 	if (n_lsbs >= ccp->cmd_q_count) {
402ef4b04f8SRavi Kumar 		/* We have enough LSBS to give every queue a private LSB.
403ef4b04f8SRavi Kumar 		 * Brute force search to start with the queues that are more
404ef4b04f8SRavi Kumar 		 * constrained in LSB choice. When an LSB is privately
405ef4b04f8SRavi Kumar 		 * assigned, it is removed from the public mask.
406ef4b04f8SRavi Kumar 		 * This is an ugly N squared algorithm with some optimization.
407ef4b04f8SRavi Kumar 		 */
408ef4b04f8SRavi Kumar 		for (lsb_cnt = 1; n_lsbs && (lsb_cnt <= MAX_LSB_CNT);
409ef4b04f8SRavi Kumar 		     lsb_cnt++) {
410ef4b04f8SRavi Kumar 			rc = ccp_find_and_assign_lsb_to_q(ccp, lsb_cnt, n_lsbs,
411ef4b04f8SRavi Kumar 							  &lsb_pub);
412ef4b04f8SRavi Kumar 			if (rc < 0)
413ef4b04f8SRavi Kumar 				return -EINVAL;
414ef4b04f8SRavi Kumar 			n_lsbs = rc;
415ef4b04f8SRavi Kumar 		}
416ef4b04f8SRavi Kumar 	}
417ef4b04f8SRavi Kumar 
418ef4b04f8SRavi Kumar 	rc = 0;
419ef4b04f8SRavi Kumar 	/* What's left of the LSBs, according to the public mask, now become
420ef4b04f8SRavi Kumar 	 * shared. Any zero bits in the lsb_pub mask represent an LSB region
421ef4b04f8SRavi Kumar 	 * that can't be used as a shared resource, so mark the LSB slots for
422ef4b04f8SRavi Kumar 	 * them as "in use".
423ef4b04f8SRavi Kumar 	 */
424ef4b04f8SRavi Kumar 	qlsb = lsb_pub;
425ef4b04f8SRavi Kumar 	bitno = ccp_find_first_zero_bit(&qlsb, MAX_LSB_CNT);
426ef4b04f8SRavi Kumar 	while (bitno < MAX_LSB_CNT) {
427ef4b04f8SRavi Kumar 		ccp_bitmap_set(ccp->lsbmap, bitno * LSB_SIZE, LSB_SIZE);
428ef4b04f8SRavi Kumar 		ccp_set_bit(&qlsb, bitno);
429ef4b04f8SRavi Kumar 		bitno = ccp_find_first_zero_bit(&qlsb, MAX_LSB_CNT);
430ef4b04f8SRavi Kumar 	}
431ef4b04f8SRavi Kumar 
432ef4b04f8SRavi Kumar 	return rc;
433ef4b04f8SRavi Kumar }
434ef4b04f8SRavi Kumar 
435ef4b04f8SRavi Kumar static int
436ef4b04f8SRavi Kumar ccp_add_device(struct ccp_device *dev, int type)
437ef4b04f8SRavi Kumar {
438ef4b04f8SRavi Kumar 	int i;
439ef4b04f8SRavi Kumar 	uint32_t qmr, status_lo, status_hi, dma_addr_lo, dma_addr_hi;
440ef4b04f8SRavi Kumar 	uint64_t status;
441ef4b04f8SRavi Kumar 	struct ccp_queue *cmd_q;
442ef4b04f8SRavi Kumar 	const struct rte_memzone *q_mz;
443ef4b04f8SRavi Kumar 	void *vaddr;
444ef4b04f8SRavi Kumar 
445ef4b04f8SRavi Kumar 	if (dev == NULL)
446ef4b04f8SRavi Kumar 		return -1;
447ef4b04f8SRavi Kumar 
448ef4b04f8SRavi Kumar 	dev->id = ccp_dev_id++;
449ef4b04f8SRavi Kumar 	dev->qidx = 0;
450ef4b04f8SRavi Kumar 	vaddr = (void *)(dev->pci.mem_resource[2].addr);
451ef4b04f8SRavi Kumar 
452ef4b04f8SRavi Kumar 	if (type == CCP_VERSION_5B) {
453ef4b04f8SRavi Kumar 		CCP_WRITE_REG(vaddr, CMD_TRNG_CTL_OFFSET, 0x00012D57);
454ef4b04f8SRavi Kumar 		CCP_WRITE_REG(vaddr, CMD_CONFIG_0_OFFSET, 0x00000003);
455ef4b04f8SRavi Kumar 		for (i = 0; i < 12; i++) {
456ef4b04f8SRavi Kumar 			CCP_WRITE_REG(vaddr, CMD_AES_MASK_OFFSET,
457ef4b04f8SRavi Kumar 				      CCP_READ_REG(vaddr, TRNG_OUT_REG));
458ef4b04f8SRavi Kumar 		}
459ef4b04f8SRavi Kumar 		CCP_WRITE_REG(vaddr, CMD_QUEUE_MASK_OFFSET, 0x0000001F);
460ef4b04f8SRavi Kumar 		CCP_WRITE_REG(vaddr, CMD_QUEUE_PRIO_OFFSET, 0x00005B6D);
461ef4b04f8SRavi Kumar 		CCP_WRITE_REG(vaddr, CMD_CMD_TIMEOUT_OFFSET, 0x00000000);
462ef4b04f8SRavi Kumar 
463ef4b04f8SRavi Kumar 		CCP_WRITE_REG(vaddr, LSB_PRIVATE_MASK_LO_OFFSET, 0x3FFFFFFF);
464ef4b04f8SRavi Kumar 		CCP_WRITE_REG(vaddr, LSB_PRIVATE_MASK_HI_OFFSET, 0x000003FF);
465ef4b04f8SRavi Kumar 
466ef4b04f8SRavi Kumar 		CCP_WRITE_REG(vaddr, CMD_CLK_GATE_CTL_OFFSET, 0x00108823);
467ef4b04f8SRavi Kumar 	}
468ef4b04f8SRavi Kumar 	CCP_WRITE_REG(vaddr, CMD_REQID_CONFIG_OFFSET, 0x00001249);
469ef4b04f8SRavi Kumar 
470ef4b04f8SRavi Kumar 	/* Copy the private LSB mask to the public registers */
471ef4b04f8SRavi Kumar 	status_lo = CCP_READ_REG(vaddr, LSB_PRIVATE_MASK_LO_OFFSET);
472ef4b04f8SRavi Kumar 	status_hi = CCP_READ_REG(vaddr, LSB_PRIVATE_MASK_HI_OFFSET);
473ef4b04f8SRavi Kumar 	CCP_WRITE_REG(vaddr, LSB_PUBLIC_MASK_LO_OFFSET, status_lo);
474ef4b04f8SRavi Kumar 	CCP_WRITE_REG(vaddr, LSB_PUBLIC_MASK_HI_OFFSET, status_hi);
475ef4b04f8SRavi Kumar 	status = ((uint64_t)status_hi<<30) | ((uint64_t)status_lo);
476ef4b04f8SRavi Kumar 
477ef4b04f8SRavi Kumar 	dev->cmd_q_count = 0;
478ef4b04f8SRavi Kumar 	/* Find available queues */
479ef4b04f8SRavi Kumar 	qmr = CCP_READ_REG(vaddr, Q_MASK_REG);
480ef4b04f8SRavi Kumar 	for (i = 0; i < MAX_HW_QUEUES; i++) {
481ef4b04f8SRavi Kumar 		if (!(qmr & (1 << i)))
482ef4b04f8SRavi Kumar 			continue;
483ef4b04f8SRavi Kumar 		cmd_q = &dev->cmd_q[dev->cmd_q_count++];
484ef4b04f8SRavi Kumar 		cmd_q->dev = dev;
485ef4b04f8SRavi Kumar 		cmd_q->id = i;
486ef4b04f8SRavi Kumar 		cmd_q->qidx = 0;
487ef4b04f8SRavi Kumar 		cmd_q->qsize = Q_SIZE(Q_DESC_SIZE);
488ef4b04f8SRavi Kumar 
489ef4b04f8SRavi Kumar 		cmd_q->reg_base = (uint8_t *)vaddr +
490ef4b04f8SRavi Kumar 			CMD_Q_STATUS_INCR * (i + 1);
491ef4b04f8SRavi Kumar 
492ef4b04f8SRavi Kumar 		/* CCP queue memory */
493ef4b04f8SRavi Kumar 		snprintf(cmd_q->memz_name, sizeof(cmd_q->memz_name),
494ef4b04f8SRavi Kumar 			 "%s_%d_%s_%d_%s",
495ef4b04f8SRavi Kumar 			 "ccp_dev",
496ef4b04f8SRavi Kumar 			 (int)dev->id, "queue",
497ef4b04f8SRavi Kumar 			 (int)cmd_q->id, "mem");
498ef4b04f8SRavi Kumar 		q_mz = ccp_queue_dma_zone_reserve(cmd_q->memz_name,
499ef4b04f8SRavi Kumar 						  cmd_q->qsize, SOCKET_ID_ANY);
500ef4b04f8SRavi Kumar 		cmd_q->qbase_addr = (void *)q_mz->addr;
501ef4b04f8SRavi Kumar 		cmd_q->qbase_desc = (void *)q_mz->addr;
502ef4b04f8SRavi Kumar 		cmd_q->qbase_phys_addr =  q_mz->phys_addr;
503ef4b04f8SRavi Kumar 
504ef4b04f8SRavi Kumar 		cmd_q->qcontrol = 0;
505ef4b04f8SRavi Kumar 		/* init control reg to zero */
506ef4b04f8SRavi Kumar 		CCP_WRITE_REG(cmd_q->reg_base, CMD_Q_CONTROL_BASE,
507ef4b04f8SRavi Kumar 			      cmd_q->qcontrol);
508ef4b04f8SRavi Kumar 
509ef4b04f8SRavi Kumar 		/* Disable the interrupts */
510ef4b04f8SRavi Kumar 		CCP_WRITE_REG(cmd_q->reg_base, CMD_Q_INT_ENABLE_BASE, 0x00);
511ef4b04f8SRavi Kumar 		CCP_READ_REG(cmd_q->reg_base, CMD_Q_INT_STATUS_BASE);
512ef4b04f8SRavi Kumar 		CCP_READ_REG(cmd_q->reg_base, CMD_Q_STATUS_BASE);
513ef4b04f8SRavi Kumar 
514ef4b04f8SRavi Kumar 		/* Clear the interrupts */
515ef4b04f8SRavi Kumar 		CCP_WRITE_REG(cmd_q->reg_base, CMD_Q_INTERRUPT_STATUS_BASE,
516ef4b04f8SRavi Kumar 			      ALL_INTERRUPTS);
517ef4b04f8SRavi Kumar 
518ef4b04f8SRavi Kumar 		/* Configure size of each virtual queue accessible to host */
519ef4b04f8SRavi Kumar 		cmd_q->qcontrol &= ~(CMD_Q_SIZE << CMD_Q_SHIFT);
520ef4b04f8SRavi Kumar 		cmd_q->qcontrol |= QUEUE_SIZE_VAL << CMD_Q_SHIFT;
521ef4b04f8SRavi Kumar 
522ef4b04f8SRavi Kumar 		dma_addr_lo = low32_value(cmd_q->qbase_phys_addr);
523ef4b04f8SRavi Kumar 		CCP_WRITE_REG(cmd_q->reg_base, CMD_Q_TAIL_LO_BASE,
524ef4b04f8SRavi Kumar 			      (uint32_t)dma_addr_lo);
525ef4b04f8SRavi Kumar 		CCP_WRITE_REG(cmd_q->reg_base, CMD_Q_HEAD_LO_BASE,
526ef4b04f8SRavi Kumar 			      (uint32_t)dma_addr_lo);
527ef4b04f8SRavi Kumar 
528ef4b04f8SRavi Kumar 		dma_addr_hi = high32_value(cmd_q->qbase_phys_addr);
529ef4b04f8SRavi Kumar 		cmd_q->qcontrol |= (dma_addr_hi << 16);
530ef4b04f8SRavi Kumar 		CCP_WRITE_REG(cmd_q->reg_base, CMD_Q_CONTROL_BASE,
531ef4b04f8SRavi Kumar 			      cmd_q->qcontrol);
532ef4b04f8SRavi Kumar 
533ef4b04f8SRavi Kumar 		/* create LSB Mask map */
534ef4b04f8SRavi Kumar 		if (ccp_find_lsb_regions(cmd_q, status))
535ef4b04f8SRavi Kumar 			CCP_LOG_ERR("queue doesn't have lsb regions");
536ef4b04f8SRavi Kumar 		cmd_q->lsb = -1;
537ef4b04f8SRavi Kumar 
538ef4b04f8SRavi Kumar 		rte_atomic64_init(&cmd_q->free_slots);
539ef4b04f8SRavi Kumar 		rte_atomic64_set(&cmd_q->free_slots, (COMMANDS_PER_QUEUE - 1));
540ef4b04f8SRavi Kumar 		/* unused slot barrier b/w H&T */
541ef4b04f8SRavi Kumar 	}
542ef4b04f8SRavi Kumar 
543ef4b04f8SRavi Kumar 	if (ccp_assign_lsbs(dev))
544ef4b04f8SRavi Kumar 		CCP_LOG_ERR("Unable to assign lsb region");
545ef4b04f8SRavi Kumar 
546ef4b04f8SRavi Kumar 	/* pre-allocate LSB slots */
547ef4b04f8SRavi Kumar 	for (i = 0; i < dev->cmd_q_count; i++) {
548ef4b04f8SRavi Kumar 		dev->cmd_q[i].sb_key =
549ef4b04f8SRavi Kumar 			ccp_lsb_alloc(&dev->cmd_q[i], 1);
550ef4b04f8SRavi Kumar 		dev->cmd_q[i].sb_iv =
551ef4b04f8SRavi Kumar 			ccp_lsb_alloc(&dev->cmd_q[i], 1);
552ef4b04f8SRavi Kumar 		dev->cmd_q[i].sb_sha =
553ef4b04f8SRavi Kumar 			ccp_lsb_alloc(&dev->cmd_q[i], 2);
554ef4b04f8SRavi Kumar 		dev->cmd_q[i].sb_hmac =
555ef4b04f8SRavi Kumar 			ccp_lsb_alloc(&dev->cmd_q[i], 2);
556ef4b04f8SRavi Kumar 	}
557ef4b04f8SRavi Kumar 
558ef4b04f8SRavi Kumar 	TAILQ_INSERT_TAIL(&ccp_list, dev, next);
559ef4b04f8SRavi Kumar 	return 0;
560ef4b04f8SRavi Kumar }
561ef4b04f8SRavi Kumar 
562ef4b04f8SRavi Kumar static void
563ef4b04f8SRavi Kumar ccp_remove_device(struct ccp_device *dev)
564ef4b04f8SRavi Kumar {
565ef4b04f8SRavi Kumar 	if (dev == NULL)
566ef4b04f8SRavi Kumar 		return;
567ef4b04f8SRavi Kumar 
568ef4b04f8SRavi Kumar 	TAILQ_REMOVE(&ccp_list, dev, next);
569ef4b04f8SRavi Kumar }
570ef4b04f8SRavi Kumar 
571ef4b04f8SRavi Kumar static int
572ef4b04f8SRavi Kumar is_ccp_device(const char *dirname,
573ef4b04f8SRavi Kumar 	      const struct rte_pci_id *ccp_id,
574ef4b04f8SRavi Kumar 	      int *type)
575ef4b04f8SRavi Kumar {
576ef4b04f8SRavi Kumar 	char filename[PATH_MAX];
577ef4b04f8SRavi Kumar 	const struct rte_pci_id *id;
578ef4b04f8SRavi Kumar 	uint16_t vendor, device_id;
579ef4b04f8SRavi Kumar 	int i;
580ef4b04f8SRavi Kumar 	unsigned long tmp;
581ef4b04f8SRavi Kumar 
582ef4b04f8SRavi Kumar 	/* get vendor id */
583ef4b04f8SRavi Kumar 	snprintf(filename, sizeof(filename), "%s/vendor", dirname);
584ef4b04f8SRavi Kumar 	if (ccp_pci_parse_sysfs_value(filename, &tmp) < 0)
585ef4b04f8SRavi Kumar 		return 0;
586ef4b04f8SRavi Kumar 	vendor = (uint16_t)tmp;
587ef4b04f8SRavi Kumar 
588ef4b04f8SRavi Kumar 	/* get device id */
589ef4b04f8SRavi Kumar 	snprintf(filename, sizeof(filename), "%s/device", dirname);
590ef4b04f8SRavi Kumar 	if (ccp_pci_parse_sysfs_value(filename, &tmp) < 0)
591ef4b04f8SRavi Kumar 		return 0;
592ef4b04f8SRavi Kumar 	device_id = (uint16_t)tmp;
593ef4b04f8SRavi Kumar 
594ef4b04f8SRavi Kumar 	for (id = ccp_id, i = 0; id->vendor_id != 0; id++, i++) {
595ef4b04f8SRavi Kumar 		if (vendor == id->vendor_id &&
596ef4b04f8SRavi Kumar 		    device_id == id->device_id) {
597ef4b04f8SRavi Kumar 			*type = i;
598ef4b04f8SRavi Kumar 			return 1; /* Matched device */
599ef4b04f8SRavi Kumar 		}
600ef4b04f8SRavi Kumar 	}
601ef4b04f8SRavi Kumar 	return 0;
602ef4b04f8SRavi Kumar }
603ef4b04f8SRavi Kumar 
604ef4b04f8SRavi Kumar static int
605ef4b04f8SRavi Kumar ccp_probe_device(const char *dirname, uint16_t domain,
606ef4b04f8SRavi Kumar 		 uint8_t bus, uint8_t devid,
607ef4b04f8SRavi Kumar 		 uint8_t function, int ccp_type)
608ef4b04f8SRavi Kumar {
609ef4b04f8SRavi Kumar 	struct ccp_device *ccp_dev = NULL;
610ef4b04f8SRavi Kumar 	struct rte_pci_device *pci;
611ef4b04f8SRavi Kumar 	char filename[PATH_MAX];
612ef4b04f8SRavi Kumar 	unsigned long tmp;
613ef4b04f8SRavi Kumar 	int uio_fd = -1, i, uio_num;
614ef4b04f8SRavi Kumar 	char uio_devname[PATH_MAX];
615ef4b04f8SRavi Kumar 	void *map_addr;
616ef4b04f8SRavi Kumar 
617ef4b04f8SRavi Kumar 	ccp_dev = rte_zmalloc("ccp_device", sizeof(*ccp_dev),
618ef4b04f8SRavi Kumar 			      RTE_CACHE_LINE_SIZE);
619ef4b04f8SRavi Kumar 	if (ccp_dev == NULL)
620ef4b04f8SRavi Kumar 		goto fail;
621ef4b04f8SRavi Kumar 	pci = &(ccp_dev->pci);
622ef4b04f8SRavi Kumar 
623ef4b04f8SRavi Kumar 	pci->addr.domain = domain;
624ef4b04f8SRavi Kumar 	pci->addr.bus = bus;
625ef4b04f8SRavi Kumar 	pci->addr.devid = devid;
626ef4b04f8SRavi Kumar 	pci->addr.function = function;
627ef4b04f8SRavi Kumar 
628ef4b04f8SRavi Kumar 	/* get vendor id */
629ef4b04f8SRavi Kumar 	snprintf(filename, sizeof(filename), "%s/vendor", dirname);
630ef4b04f8SRavi Kumar 	if (ccp_pci_parse_sysfs_value(filename, &tmp) < 0)
631ef4b04f8SRavi Kumar 		goto fail;
632ef4b04f8SRavi Kumar 	pci->id.vendor_id = (uint16_t)tmp;
633ef4b04f8SRavi Kumar 
634ef4b04f8SRavi Kumar 	/* get device id */
635ef4b04f8SRavi Kumar 	snprintf(filename, sizeof(filename), "%s/device", dirname);
636ef4b04f8SRavi Kumar 	if (ccp_pci_parse_sysfs_value(filename, &tmp) < 0)
637ef4b04f8SRavi Kumar 		goto fail;
638ef4b04f8SRavi Kumar 	pci->id.device_id = (uint16_t)tmp;
639ef4b04f8SRavi Kumar 
640ef4b04f8SRavi Kumar 	/* get subsystem_vendor id */
641ef4b04f8SRavi Kumar 	snprintf(filename, sizeof(filename), "%s/subsystem_vendor",
642ef4b04f8SRavi Kumar 			dirname);
643ef4b04f8SRavi Kumar 	if (ccp_pci_parse_sysfs_value(filename, &tmp) < 0)
644ef4b04f8SRavi Kumar 		goto fail;
645ef4b04f8SRavi Kumar 	pci->id.subsystem_vendor_id = (uint16_t)tmp;
646ef4b04f8SRavi Kumar 
647ef4b04f8SRavi Kumar 	/* get subsystem_device id */
648ef4b04f8SRavi Kumar 	snprintf(filename, sizeof(filename), "%s/subsystem_device",
649ef4b04f8SRavi Kumar 			dirname);
650ef4b04f8SRavi Kumar 	if (ccp_pci_parse_sysfs_value(filename, &tmp) < 0)
651ef4b04f8SRavi Kumar 		goto fail;
652ef4b04f8SRavi Kumar 	pci->id.subsystem_device_id = (uint16_t)tmp;
653ef4b04f8SRavi Kumar 
654ef4b04f8SRavi Kumar 	/* get class_id */
655ef4b04f8SRavi Kumar 	snprintf(filename, sizeof(filename), "%s/class",
656ef4b04f8SRavi Kumar 			dirname);
657ef4b04f8SRavi Kumar 	if (ccp_pci_parse_sysfs_value(filename, &tmp) < 0)
658ef4b04f8SRavi Kumar 		goto fail;
659ef4b04f8SRavi Kumar 	/* the least 24 bits are valid: class, subclass, program interface */
660ef4b04f8SRavi Kumar 	pci->id.class_id = (uint32_t)tmp & RTE_CLASS_ANY_ID;
661ef4b04f8SRavi Kumar 
662ef4b04f8SRavi Kumar 	/* parse resources */
663ef4b04f8SRavi Kumar 	snprintf(filename, sizeof(filename), "%s/resource", dirname);
664ef4b04f8SRavi Kumar 	if (ccp_pci_parse_sysfs_resource(filename, pci) < 0)
665ef4b04f8SRavi Kumar 		goto fail;
666ef4b04f8SRavi Kumar 
667ef4b04f8SRavi Kumar 	uio_num = ccp_find_uio_devname(dirname);
668ef4b04f8SRavi Kumar 	if (uio_num < 0) {
669ef4b04f8SRavi Kumar 		/*
670ef4b04f8SRavi Kumar 		 * It may take time for uio device to appear,
671ef4b04f8SRavi Kumar 		 * wait  here and try again
672ef4b04f8SRavi Kumar 		 */
673ef4b04f8SRavi Kumar 		usleep(100000);
674ef4b04f8SRavi Kumar 		uio_num = ccp_find_uio_devname(dirname);
675ef4b04f8SRavi Kumar 		if (uio_num < 0)
676ef4b04f8SRavi Kumar 			goto fail;
677ef4b04f8SRavi Kumar 	}
678ef4b04f8SRavi Kumar 	snprintf(uio_devname, sizeof(uio_devname), "/dev/uio%u", uio_num);
679ef4b04f8SRavi Kumar 
680ef4b04f8SRavi Kumar 	uio_fd = open(uio_devname, O_RDWR | O_NONBLOCK);
681ef4b04f8SRavi Kumar 	if (uio_fd < 0)
682ef4b04f8SRavi Kumar 		goto fail;
683ef4b04f8SRavi Kumar 	if (flock(uio_fd, LOCK_EX | LOCK_NB))
684ef4b04f8SRavi Kumar 		goto fail;
685ef4b04f8SRavi Kumar 
686ef4b04f8SRavi Kumar 	/* Map the PCI memory resource of device */
687ef4b04f8SRavi Kumar 	for (i = 0; i < PCI_MAX_RESOURCE; i++) {
688ef4b04f8SRavi Kumar 
689ef4b04f8SRavi Kumar 		char devname[PATH_MAX];
690ef4b04f8SRavi Kumar 		int res_fd;
691ef4b04f8SRavi Kumar 
692ef4b04f8SRavi Kumar 		if (pci->mem_resource[i].phys_addr == 0)
693ef4b04f8SRavi Kumar 			continue;
694ef4b04f8SRavi Kumar 		snprintf(devname, sizeof(devname), "%s/resource%d", dirname, i);
695ef4b04f8SRavi Kumar 		res_fd = open(devname, O_RDWR);
696ef4b04f8SRavi Kumar 		if (res_fd < 0)
697ef4b04f8SRavi Kumar 			goto fail;
698ef4b04f8SRavi Kumar 		map_addr = mmap(NULL, pci->mem_resource[i].len,
699ef4b04f8SRavi Kumar 				PROT_READ | PROT_WRITE,
700ef4b04f8SRavi Kumar 				MAP_SHARED, res_fd, 0);
701ef4b04f8SRavi Kumar 		if (map_addr == MAP_FAILED)
702ef4b04f8SRavi Kumar 			goto fail;
703ef4b04f8SRavi Kumar 
704ef4b04f8SRavi Kumar 		pci->mem_resource[i].addr = map_addr;
705ef4b04f8SRavi Kumar 	}
706ef4b04f8SRavi Kumar 
707ef4b04f8SRavi Kumar 	/* device is valid, add in list */
708ef4b04f8SRavi Kumar 	if (ccp_add_device(ccp_dev, ccp_type)) {
709ef4b04f8SRavi Kumar 		ccp_remove_device(ccp_dev);
710ef4b04f8SRavi Kumar 		goto fail;
711ef4b04f8SRavi Kumar 	}
712ef4b04f8SRavi Kumar 
713ef4b04f8SRavi Kumar 	return 0;
714ef4b04f8SRavi Kumar fail:
715ef4b04f8SRavi Kumar 	CCP_LOG_ERR("CCP Device probe failed");
716ef4b04f8SRavi Kumar 	if (uio_fd > 0)
717ef4b04f8SRavi Kumar 		close(uio_fd);
718ef4b04f8SRavi Kumar 	if (ccp_dev)
719ef4b04f8SRavi Kumar 		rte_free(ccp_dev);
720ef4b04f8SRavi Kumar 	return -1;
721ef4b04f8SRavi Kumar }
722ef4b04f8SRavi Kumar 
723ef4b04f8SRavi Kumar int
724ef4b04f8SRavi Kumar ccp_probe_devices(const struct rte_pci_id *ccp_id)
725ef4b04f8SRavi Kumar {
726ef4b04f8SRavi Kumar 	int dev_cnt = 0;
727ef4b04f8SRavi Kumar 	int ccp_type = 0;
728ef4b04f8SRavi Kumar 	struct dirent *d;
729ef4b04f8SRavi Kumar 	DIR *dir;
730ef4b04f8SRavi Kumar 	int ret = 0;
731ef4b04f8SRavi Kumar 	int module_idx = 0;
732ef4b04f8SRavi Kumar 	uint16_t domain;
733ef4b04f8SRavi Kumar 	uint8_t bus, devid, function;
734ef4b04f8SRavi Kumar 	char dirname[PATH_MAX];
735ef4b04f8SRavi Kumar 
736ef4b04f8SRavi Kumar 	module_idx = ccp_check_pci_uio_module();
737ef4b04f8SRavi Kumar 	if (module_idx < 0)
738ef4b04f8SRavi Kumar 		return -1;
739ef4b04f8SRavi Kumar 
740ef4b04f8SRavi Kumar 	TAILQ_INIT(&ccp_list);
741ef4b04f8SRavi Kumar 	dir = opendir(SYSFS_PCI_DEVICES);
742ef4b04f8SRavi Kumar 	if (dir == NULL)
743ef4b04f8SRavi Kumar 		return -1;
744ef4b04f8SRavi Kumar 	while ((d = readdir(dir)) != NULL) {
745ef4b04f8SRavi Kumar 		if (d->d_name[0] == '.')
746ef4b04f8SRavi Kumar 			continue;
747ef4b04f8SRavi Kumar 		if (ccp_parse_pci_addr_format(d->d_name, sizeof(d->d_name),
748ef4b04f8SRavi Kumar 					&domain, &bus, &devid, &function) != 0)
749ef4b04f8SRavi Kumar 			continue;
750ef4b04f8SRavi Kumar 		snprintf(dirname, sizeof(dirname), "%s/%s",
751ef4b04f8SRavi Kumar 			     SYSFS_PCI_DEVICES, d->d_name);
752ef4b04f8SRavi Kumar 		if (is_ccp_device(dirname, ccp_id, &ccp_type)) {
753ef4b04f8SRavi Kumar 			printf("CCP : Detected CCP device with ID = 0x%x\n",
754ef4b04f8SRavi Kumar 			       ccp_id[ccp_type].device_id);
755ef4b04f8SRavi Kumar 			ret = ccp_probe_device(dirname, domain, bus, devid,
756ef4b04f8SRavi Kumar 					       function, ccp_type);
757ef4b04f8SRavi Kumar 			if (ret == 0)
758ef4b04f8SRavi Kumar 				dev_cnt++;
759ef4b04f8SRavi Kumar 		}
760ef4b04f8SRavi Kumar 	}
761ef4b04f8SRavi Kumar 	closedir(dir);
762ef4b04f8SRavi Kumar 	return dev_cnt;
763ef4b04f8SRavi Kumar }
764