754 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			754 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
| /* SPDX-License-Identifier: GPL-2.0 */
 | |
| /*
 | |
|  * Copyright (C) 2020 Marvell International Ltd.
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * Module to support operations on bitmap of cores. Coremask can be used to
 | |
|  * select a specific core, a group of cores, or all available cores, for
 | |
|  * initialization and differentiation of roles within a single shared binary
 | |
|  * executable image.
 | |
|  *
 | |
|  * The core numbers used in this file are the same value as what is found in
 | |
|  * the COP0_EBASE register and the rdhwr 0 instruction.
 | |
|  *
 | |
|  * For the CN78XX and other multi-node environments the core numbers are not
 | |
|  * contiguous.  The core numbers for the CN78XX are as follows:
 | |
|  *
 | |
|  * Node 0:	Cores 0 - 47
 | |
|  * Node 1:	Cores 128 - 175
 | |
|  * Node 2:	Cores 256 - 303
 | |
|  * Node 3:	Cores 384 - 431
 | |
|  *
 | |
|  * The coremask environment generally tries to be node agnostic in order to
 | |
|  * provide future compatibility if more cores are added to future processors
 | |
|  * or more nodes are supported.
 | |
|  */
 | |
| 
 | |
| #ifndef __CVMX_COREMASK_H__
 | |
| #define __CVMX_COREMASK_H__
 | |
| 
 | |
| #include "cvmx-regs.h"
 | |
| 
 | |
| /* bits per holder */
 | |
| #define CVMX_COREMASK_HLDRSZ	((int)(sizeof(u64) * 8))
 | |
| 
 | |
| /** Maximum allowed cores per node */
 | |
| #define CVMX_COREMASK_MAX_CORES_PER_NODE	(1 << CVMX_NODE_NO_SHIFT)
 | |
| 
 | |
| /** Maximum number of bits actually used in the coremask */
 | |
| #define CVMX_MAX_USED_CORES_BMP	(1 << (CVMX_NODE_NO_SHIFT + CVMX_NODE_BITS))
 | |
| 
 | |
| /* the number of valid bits in and the mask of the most significant holder */
 | |
| #define CVMX_COREMASK_MSHLDR_NBITS			\
 | |
| 	(CVMX_MIPS_MAX_CORES % CVMX_COREMASK_HLDRSZ)
 | |
| 
 | |
| #define CVMX_COREMASK_MSHLDR_MASK				\
 | |
| 	((CVMX_COREMASK_MSHLDR_NBITS) ?				\
 | |
| 	 (((u64)1 << CVMX_COREMASK_MSHLDR_NBITS) - 1) :		\
 | |
| 	 ((u64)-1))
 | |
| 
 | |
| /* cvmx_coremask size in u64 */
 | |
| #define CVMX_COREMASK_BMPSZ					\
 | |
| 	((int)(CVMX_MIPS_MAX_CORES / CVMX_COREMASK_HLDRSZ +	\
 | |
| 	       (CVMX_COREMASK_MSHLDR_NBITS != 0)))
 | |
| 
 | |
| #define CVMX_COREMASK_USED_BMPSZ				\
 | |
| 	(CVMX_MAX_USED_CORES_BMP / CVMX_COREMASK_HLDRSZ)
 | |
| 
 | |
| #define CVMX_COREMASK_BMP_NODE_CORE_IDX(node, core)			\
 | |
| 	((((node) << CVMX_NODE_NO_SHIFT) + (core)) / CVMX_COREMASK_HLDRSZ)
 | |
| /**
 | |
|  * Maximum available coremask.
 | |
|  */
 | |
| #define CVMX_COREMASK_MAX				\
 | |
| 	{ {						\
 | |
| 			0x0000FFFFFFFFFFFF, 0,		\
 | |
| 				0x0000FFFFFFFFFFFF, 0,	\
 | |
| 				0x0000FFFFFFFFFFFF, 0,	\
 | |
| 				0x0000FFFFFFFFFFFF, 0,	\
 | |
| 				0, 0,			\
 | |
| 				0, 0,			\
 | |
| 				0, 0,			\
 | |
| 				0, 0} }
 | |
| 
 | |
| /**
 | |
|  * Empty coremask
 | |
|  */
 | |
| #define CVMX_COREMASK_EMPTY					\
 | |
| 	{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }
 | |
| 
 | |
| struct cvmx_coremask {
 | |
| 	u64 coremask_bitmap[CVMX_COREMASK_BMPSZ];
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Macro to iterate through all available cores in a coremask
 | |
|  *
 | |
|  * @param core - core variable to use to iterate
 | |
|  * @param pcm - pointer to core mask
 | |
|  *
 | |
|  * Use this like a for statement
 | |
|  */
 | |
| #define cvmx_coremask_for_each_core(core, pcm)			\
 | |
| 	for ((core) = -1;					\
 | |
| 	     (core) = cvmx_coremask_next_core((core), pcm),	\
 | |
| 		     (core) >= 0;)
 | |
| 
 | |
| /**
 | |
|  * Given a node and node mask, return the next available node.
 | |
|  *
 | |
|  * @param node		starting node number
 | |
|  * @param node_mask	node mask to use to find the next node
 | |
|  *
 | |
|  * Return: next node number or -1 if no more nodes are available
 | |
|  */
 | |
| static inline int cvmx_coremask_next_node(int node, u8 node_mask)
 | |
| {
 | |
| 	int next_offset;
 | |
| 
 | |
| 	next_offset = __builtin_ffs(node_mask >> (node + 1));
 | |
| 	if (next_offset == 0)
 | |
| 		return -1;
 | |
| 	else
 | |
| 		return node + next_offset;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Iterate through all nodes in a node mask
 | |
|  *
 | |
|  * @param node		node iterator variable
 | |
|  * @param node_mask	mask to use for iterating
 | |
|  *
 | |
|  * Use this like a for statement
 | |
|  */
 | |
| #define cvmx_coremask_for_each_node(node, node_mask)		\
 | |
| 	for ((node) = __builtin_ffs(node_mask) - 1;		\
 | |
| 	     (node) >= 0 && (node) < CVMX_MAX_NODES;		\
 | |
| 	     (node) = cvmx_coremask_next_node(node, node_mask))
 | |
| 
 | |
| /**
 | |
|  * Is ``core'' set in the coremask?
 | |
|  *
 | |
|  * @param pcm is the pointer to the coremask.
 | |
|  * @param core
 | |
|  * Return: 1 if core is set and 0 if not.
 | |
|  */
 | |
| static inline int cvmx_coremask_is_core_set(const struct cvmx_coremask *pcm,
 | |
| 					    int core)
 | |
| {
 | |
| 	int n, i;
 | |
| 
 | |
| 	n = core % CVMX_COREMASK_HLDRSZ;
 | |
| 	i = core / CVMX_COREMASK_HLDRSZ;
 | |
| 
 | |
| 	return (pcm->coremask_bitmap[i] & ((u64)1 << n)) != 0;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Is ``current core'' set in the coremask?
 | |
|  *
 | |
|  * @param pcm is the pointer to the coremask.
 | |
|  * Return: 1 if core is set and 0 if not.
 | |
|  */
 | |
| static inline int cvmx_coremask_is_self_set(const struct cvmx_coremask *pcm)
 | |
| {
 | |
| 	return cvmx_coremask_is_core_set(pcm, (int)cvmx_get_core_num());
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Is coremask empty?
 | |
|  * @param pcm is the pointer to the coremask.
 | |
|  * Return: 1 if *pcm is empty (all zeros), 0 if not empty.
 | |
|  */
 | |
| static inline int cvmx_coremask_is_empty(const struct cvmx_coremask *pcm)
 | |
| {
 | |
| 	int i;
 | |
| 
 | |
| 	for (i = 0; i < CVMX_COREMASK_USED_BMPSZ; i++)
 | |
| 		if (pcm->coremask_bitmap[i] != 0)
 | |
| 			return 0;
 | |
| 
 | |
| 	return 1;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Set ``core'' in the coremask.
 | |
|  *
 | |
|  * @param pcm is the pointer to the coremask.
 | |
|  * @param core
 | |
|  * Return: 0.
 | |
|  */
 | |
| static inline int cvmx_coremask_set_core(struct cvmx_coremask *pcm, int core)
 | |
| {
 | |
| 	int n, i;
 | |
| 
 | |
| 	n = core % CVMX_COREMASK_HLDRSZ;
 | |
| 	i = core / CVMX_COREMASK_HLDRSZ;
 | |
| 	pcm->coremask_bitmap[i] |= ((u64)1 << n);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Set ``current core'' in the coremask.
 | |
|  *
 | |
|  * @param pcm is the pointer to the coremask.
 | |
|  * Return: 0.
 | |
|  */
 | |
| static inline int cvmx_coremask_set_self(struct cvmx_coremask *pcm)
 | |
| {
 | |
| 	return cvmx_coremask_set_core(pcm, (int)cvmx_get_core_num());
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Clear ``core'' from the coremask.
 | |
|  *
 | |
|  * @param pcm is the pointer to the coremask.
 | |
|  * @param core
 | |
|  * Return: 0.
 | |
|  */
 | |
| static inline int cvmx_coremask_clear_core(struct cvmx_coremask *pcm, int core)
 | |
| {
 | |
| 	int n, i;
 | |
| 
 | |
| 	n = core % CVMX_COREMASK_HLDRSZ;
 | |
| 	i = core / CVMX_COREMASK_HLDRSZ;
 | |
| 	pcm->coremask_bitmap[i] &= ~((u64)1 << n);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Clear ``current core'' from the coremask.
 | |
|  *
 | |
|  * @param pcm is the pointer to the coremask.
 | |
|  * Return: 0.
 | |
|  */
 | |
| static inline int cvmx_coremask_clear_self(struct cvmx_coremask *pcm)
 | |
| {
 | |
| 	return cvmx_coremask_clear_core(pcm, cvmx_get_core_num());
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Toggle ``core'' in the coremask.
 | |
|  *
 | |
|  * @param pcm is the pointer to the coremask.
 | |
|  * @param core
 | |
|  * Return: 0.
 | |
|  */
 | |
| static inline int cvmx_coremask_toggle_core(struct cvmx_coremask *pcm, int core)
 | |
| {
 | |
| 	int n, i;
 | |
| 
 | |
| 	n = core % CVMX_COREMASK_HLDRSZ;
 | |
| 	i = core / CVMX_COREMASK_HLDRSZ;
 | |
| 	pcm->coremask_bitmap[i] ^= ((u64)1 << n);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Toggle ``current core'' in the coremask.
 | |
|  *
 | |
|  * @param pcm is the pointer to the coremask.
 | |
|  * Return: 0.
 | |
|  */
 | |
| static inline int cvmx_coremask_toggle_self(struct cvmx_coremask *pcm)
 | |
| {
 | |
| 	return cvmx_coremask_toggle_core(pcm, cvmx_get_core_num());
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Set the lower 64-bit of the coremask.
 | |
|  * @param pcm	pointer to coremask
 | |
|  * @param coremask_64	64-bit coremask to apply to the first node (0)
 | |
|  */
 | |
| static inline void cvmx_coremask_set64(struct cvmx_coremask *pcm,
 | |
| 				       u64 coremask_64)
 | |
| {
 | |
| 	pcm->coremask_bitmap[0] = coremask_64;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Set the 64-bit of the coremask for a particular node.
 | |
|  * @param pcm	pointer to coremask
 | |
|  * @param node	node to set
 | |
|  * @param coremask_64	64-bit coremask to apply to the specified node
 | |
|  */
 | |
| static inline void cvmx_coremask_set64_node(struct cvmx_coremask *pcm,
 | |
| 					    u8 node,
 | |
| 					    u64 coremask_64)
 | |
| {
 | |
| 	pcm->coremask_bitmap[CVMX_COREMASK_BMP_NODE_CORE_IDX(node, 0)] =
 | |
| 		coremask_64;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Gets the lower 64-bits of the coremask
 | |
|  *
 | |
|  * @param[in] pcm - pointer to coremask
 | |
|  * Return: 64-bit coremask for the first node
 | |
|  */
 | |
| static inline u64 cvmx_coremask_get64(const struct cvmx_coremask *pcm)
 | |
| {
 | |
| 	return pcm->coremask_bitmap[0];
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Gets the lower 64-bits of the coremask for the specified node
 | |
|  *
 | |
|  * @param[in] pcm - pointer to coremask
 | |
|  * @param node - node to get coremask for
 | |
|  * Return: 64-bit coremask for the first node
 | |
|  */
 | |
| static inline u64 cvmx_coremask_get64_node(const struct cvmx_coremask *pcm,
 | |
| 					   u8 node)
 | |
| {
 | |
| 	return pcm->coremask_bitmap[CVMX_COREMASK_BMP_NODE_CORE_IDX(node, 0)];
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Gets the lower 32-bits of the coremask for compatibility
 | |
|  *
 | |
|  * @param[in] pcm - pointer to coremask
 | |
|  * Return: 32-bit coremask for the first node
 | |
|  * @deprecated This function is to maintain compatibility with older
 | |
|  *             SDK applications and may disappear at some point.
 | |
|  * This function is not compatible with the CN78XX or any other
 | |
|  * Octeon device with more than 32 cores.
 | |
|  */
 | |
| static inline u32 cvmx_coremask_get32(const struct cvmx_coremask *pcm)
 | |
| {
 | |
| 	return pcm->coremask_bitmap[0] & 0xffffffff;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * cvmx_coremask_cmp() returns an integer less than, equal to, or
 | |
|  * greater than zero if *pcm1 is found, respectively, to be less than,
 | |
|  * to match, or be greater than *pcm2.
 | |
|  */
 | |
| static inline int cvmx_coremask_cmp(const struct cvmx_coremask *pcm1,
 | |
| 				    const struct cvmx_coremask *pcm2)
 | |
| {
 | |
| 	int i;
 | |
| 
 | |
| 	/* Start from highest node for arithemtically correct result */
 | |
| 	for (i = CVMX_COREMASK_USED_BMPSZ - 1; i >= 0; i--)
 | |
| 		if (pcm1->coremask_bitmap[i] != pcm2->coremask_bitmap[i]) {
 | |
| 			return (pcm1->coremask_bitmap[i] >
 | |
| 				pcm2->coremask_bitmap[i]) ? 1 : -1;
 | |
| 		}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * cvmx_coremask_OPx(pcm1, pcm2[, pcm3]), where OPx can be
 | |
|  * - and
 | |
|  * - or
 | |
|  * - xor
 | |
|  * - not
 | |
|  * ...
 | |
|  * For binary operators, pcm3 <-- pcm1 OPX pcm2.
 | |
|  * For unaries, pcm2 <-- OPx pcm1.
 | |
|  */
 | |
| #define CVMX_COREMASK_BINARY_DEFUN(binary_op, op)		\
 | |
| 	static inline int cvmx_coremask_##binary_op(		\
 | |
| 		struct cvmx_coremask *pcm1,				\
 | |
| 		const struct cvmx_coremask *pcm2,			\
 | |
| 		const struct cvmx_coremask *pcm3)			\
 | |
| 	{							\
 | |
| 		int i;						\
 | |
| 								\
 | |
| 		for (i = 0; i < CVMX_COREMASK_USED_BMPSZ; i++)	\
 | |
| 			pcm1->coremask_bitmap[i] =		\
 | |
| 				pcm2->coremask_bitmap[i]	\
 | |
| 				op				\
 | |
| 				pcm3->coremask_bitmap[i];	\
 | |
| 								\
 | |
| 		return 0;					\
 | |
| 	}
 | |
| 
 | |
| #define CVMX_COREMASK_UNARY_DEFUN(unary_op, op)			\
 | |
| 	static inline int cvmx_coremask_##unary_op(		\
 | |
| 		struct cvmx_coremask *pcm1,				\
 | |
| 		const struct cvmx_coremask *pcm2)			\
 | |
| 	{							\
 | |
| 		int i;						\
 | |
| 								\
 | |
| 		for (i = 0; i < CVMX_COREMASK_USED_BMPSZ; i++)	\
 | |
| 			pcm1->coremask_bitmap[i] =		\
 | |
| 				op				\
 | |
| 				pcm2->coremask_bitmap[i];	\
 | |
| 								\
 | |
| 		return 0;					\
 | |
| 	}
 | |
| 
 | |
| /* cvmx_coremask_and(pcm1, pcm2, pcm3): pcm1 = pmc2 & pmc3 */
 | |
| CVMX_COREMASK_BINARY_DEFUN(and, &)
 | |
| /* cvmx_coremask_or(pcm1, pcm2, pcm3): pcm1 = pmc2 | pmc3  */
 | |
| CVMX_COREMASK_BINARY_DEFUN(or, |)
 | |
| /* cvmx_coremask_xor(pcm1, pcm2, pcm3): pcm1 = pmc2 ^ pmc3 */
 | |
| CVMX_COREMASK_BINARY_DEFUN(xor, ^)
 | |
| /* cvmx_coremask_maskoff(pcm1, pcm2, pcm3): pcm1 = pmc2 & ~pmc3 */
 | |
| CVMX_COREMASK_BINARY_DEFUN(maskoff, & ~)
 | |
| /* cvmx_coremask_not(pcm1, pcm2): pcm1 = ~pcm2       */
 | |
| CVMX_COREMASK_UNARY_DEFUN(not, ~)
 | |
| /* cvmx_coremask_fill(pcm1, pcm2): pcm1 = -1      */
 | |
| CVMX_COREMASK_UNARY_DEFUN(fill, -1 |)
 | |
| /* cvmx_coremask_clear(pcm1, pcm2): pcm1 = 0     */
 | |
| CVMX_COREMASK_UNARY_DEFUN(clear, 0 &)
 | |
| /* cvmx_coremask_dup(pcm1, pcm2): pcm1 = pcm2       */
 | |
| CVMX_COREMASK_UNARY_DEFUN(dup, +)
 | |
| 
 | |
| /*
 | |
|  * Macros using the unary functions defined w/
 | |
|  * CVMX_COREMASK_UNARY_DEFUN
 | |
|  * - set *pcm to its complement
 | |
|  * - set all bits in *pcm to 0
 | |
|  * - set all (valid) bits in *pcm to 1
 | |
|  */
 | |
| #define cvmx_coremask_complement(pcm)	cvmx_coremask_not(pcm, pcm)
 | |
| /* On clear, even clear the unused bits */
 | |
| #define cvmx_coremask_clear_all(pcm)					\
 | |
| 	*(pcm) = (struct cvmx_coremask)CVMX_COREMASK_EMPTY
 | |
| #define cvmx_coremask_set_all(pcm)	cvmx_coremask_fill(pcm, NULL)
 | |
| 
 | |
| /*
 | |
|  * convert a string of hex digits to struct cvmx_coremask
 | |
|  *
 | |
|  * @param pcm
 | |
|  * @param hexstr can be
 | |
|  *	- "[1-9A-Fa-f][0-9A-Fa-f]*", or
 | |
|  *	- "-1" to set the bits for all the cores.
 | |
|  * return
 | |
|  *	 0 for success,
 | |
|  *	-1 for string too long (i.e., hexstr takes more bits than
 | |
|  *	   CVMX_MIPS_MAX_CORES),
 | |
|  *	-2 for conversion problems from hex string to an unsigned
 | |
|  *	   long long, e.g., non-hex char in hexstr, and
 | |
|  *	-3 for hexstr starting with '0'.
 | |
|  * NOTE:
 | |
|  *	This function clears the bitmask in *pcm before the conversion.
 | |
|  */
 | |
| int cvmx_coremask_str2bmp(struct cvmx_coremask *pcm, char *hexstr);
 | |
| 
 | |
| /*
 | |
|  * convert a struct cvmx_coremask to a string of hex digits
 | |
|  *
 | |
|  * @param pcm
 | |
|  * @param hexstr is "[1-9A-Fa-f][0-9A-Fa-f]*"
 | |
|  *
 | |
|  * return 0.
 | |
|  */
 | |
| int cvmx_coremask_bmp2str(const struct cvmx_coremask *pcm, char *hexstr);
 | |
| 
 | |
| /*
 | |
|  * Returns the index of the lowest bit in a coremask holder.
 | |
|  */
 | |
| static inline int cvmx_coremask_lowest_bit(u64 h)
 | |
| {
 | |
| 	return __builtin_ctzll(h);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Returns the 0-based index of the highest bit in a coremask holder.
 | |
|  */
 | |
| static inline int cvmx_coremask_highest_bit(u64 h)
 | |
| {
 | |
| 	return (64 - __builtin_clzll(h) - 1);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Returns the last core within the coremask and -1 when the coremask
 | |
|  * is empty.
 | |
|  *
 | |
|  * @param[in] pcm - pointer to coremask
 | |
|  * @returns last core set in the coremask or -1 if all clear
 | |
|  *
 | |
|  */
 | |
| static inline int cvmx_coremask_get_last_core(const struct cvmx_coremask *pcm)
 | |
| {
 | |
| 	int i;
 | |
| 	int found = -1;
 | |
| 
 | |
| 	for (i = 0; i < CVMX_COREMASK_USED_BMPSZ; i++) {
 | |
| 		if (pcm->coremask_bitmap[i])
 | |
| 			found = i;
 | |
| 	}
 | |
| 
 | |
| 	if (found == -1)
 | |
| 		return -1;
 | |
| 
 | |
| 	return found * CVMX_COREMASK_HLDRSZ +
 | |
| 		cvmx_coremask_highest_bit(pcm->coremask_bitmap[found]);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Returns the first core within the coremask and -1 when the coremask
 | |
|  * is empty.
 | |
|  *
 | |
|  * @param[in] pcm - pointer to coremask
 | |
|  * @returns first core set in the coremask or -1 if all clear
 | |
|  *
 | |
|  */
 | |
| static inline int cvmx_coremask_get_first_core(const struct cvmx_coremask *pcm)
 | |
| {
 | |
| 	int i;
 | |
| 
 | |
| 	for (i = 0; i < CVMX_COREMASK_USED_BMPSZ; i++)
 | |
| 		if (pcm->coremask_bitmap[i])
 | |
| 			break;
 | |
| 
 | |
| 	if (i == CVMX_COREMASK_USED_BMPSZ)
 | |
| 		return -1;
 | |
| 
 | |
| 	return i * CVMX_COREMASK_HLDRSZ +
 | |
| 		cvmx_coremask_lowest_bit(pcm->coremask_bitmap[i]);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Given a core and coremask, return the next available core in the coremask
 | |
|  * or -1 if none are available.
 | |
|  *
 | |
|  * @param core - starting core to check (can be -1 for core 0)
 | |
|  * @param pcm - pointer to coremask to check for the next core.
 | |
|  *
 | |
|  * Return: next core following the core parameter or -1 if no more cores.
 | |
|  */
 | |
| static inline int cvmx_coremask_next_core(int core,
 | |
| 					  const struct cvmx_coremask *pcm)
 | |
| {
 | |
| 	int n, i;
 | |
| 
 | |
| 	core++;
 | |
| 	n = core % CVMX_COREMASK_HLDRSZ;
 | |
| 	i = core / CVMX_COREMASK_HLDRSZ;
 | |
| 
 | |
| 	if (pcm->coremask_bitmap[i] != 0) {
 | |
| 		for (; n < CVMX_COREMASK_HLDRSZ; n++)
 | |
| 			if (pcm->coremask_bitmap[i] & (1ULL << n))
 | |
| 				return ((i * CVMX_COREMASK_HLDRSZ) + n);
 | |
| 	}
 | |
| 
 | |
| 	for (i = i + 1; i < CVMX_COREMASK_USED_BMPSZ; i++) {
 | |
| 		if (pcm->coremask_bitmap[i] != 0)
 | |
| 			return (i * CVMX_COREMASK_HLDRSZ) +
 | |
| 				cvmx_coremask_lowest_bit(pcm->coremask_bitmap[i]);
 | |
| 	}
 | |
| 	return -1;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Compute coremask for count cores starting with start_core.
 | |
|  * Note that the coremask for multi-node processors may have
 | |
|  * gaps.
 | |
|  *
 | |
|  * @param[out]  pcm        pointer to core mask data structure
 | |
|  * @param	start_core starting code number
 | |
|  * @param       count      number of cores
 | |
|  *
 | |
|  */
 | |
| static inline void cvmx_coremask_set_cores(struct cvmx_coremask *pcm,
 | |
| 					   unsigned int start_core,
 | |
| 					   unsigned int count)
 | |
| {
 | |
| 	int node;
 | |
| 	int core;	/** Current core in node */
 | |
| 	int cores_in_node;
 | |
| 	int i;
 | |
| 
 | |
| 	assert(CVMX_MAX_CORES < CVMX_COREMASK_HLDRSZ);
 | |
| 	node = start_core >> CVMX_NODE_NO_SHIFT;
 | |
| 	core = start_core & ((1 << CVMX_NODE_NO_SHIFT) - 1);
 | |
| 	assert(core < CVMX_MAX_CORES);
 | |
| 
 | |
| 	cvmx_coremask_clear_all(pcm);
 | |
| 	while (count > 0) {
 | |
| 		if (count + core > CVMX_MAX_CORES)
 | |
| 			cores_in_node = CVMX_MAX_CORES - core;
 | |
| 		else
 | |
| 			cores_in_node = count;
 | |
| 
 | |
| 		i = CVMX_COREMASK_BMP_NODE_CORE_IDX(node, core);
 | |
| 		pcm->coremask_bitmap[i] = ((1ULL << cores_in_node) - 1) << core;
 | |
| 		count -= cores_in_node;
 | |
| 		core = 0;
 | |
| 		node++;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Makes a copy of a coremask
 | |
|  *
 | |
|  * @param[out] dest - pointer to destination coremask
 | |
|  * @param[in]  src  - pointer to source coremask
 | |
|  */
 | |
| static inline void cvmx_coremask_copy(struct cvmx_coremask *dest,
 | |
| 				      const struct cvmx_coremask *src)
 | |
| {
 | |
| 	memcpy(dest, src, sizeof(*dest));
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Test to see if the specified core is first core in coremask.
 | |
|  *
 | |
|  * @param[in]  pcm  pointer to the coremask to test against
 | |
|  * @param[in]  core core to check
 | |
|  *
 | |
|  * Return:  1 if the core is first core in the coremask, 0 otherwise
 | |
|  *
 | |
|  */
 | |
| static inline int cvmx_coremask_is_core_first_core(const struct cvmx_coremask *pcm,
 | |
| 						   unsigned int core)
 | |
| {
 | |
| 	int n, i;
 | |
| 
 | |
| 	n = core / CVMX_COREMASK_HLDRSZ;
 | |
| 
 | |
| 	for (i = 0; i < n; i++)
 | |
| 		if (pcm->coremask_bitmap[i] != 0)
 | |
| 			return 0;
 | |
| 
 | |
| 	/* From now on we only care about the core number within an entry */
 | |
| 	core &= (CVMX_COREMASK_HLDRSZ - 1);
 | |
| 	if (__builtin_ffsll(pcm->coremask_bitmap[n]) < (core + 1))
 | |
| 		return 0;
 | |
| 
 | |
| 	return (__builtin_ffsll(pcm->coremask_bitmap[n]) == core + 1);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * NOTE:
 | |
|  * cvmx_coremask_is_first_core() was retired due to improper usage.
 | |
|  * For inquiring about the current core being the initializing
 | |
|  * core for an application, use cvmx_is_init_core().
 | |
|  * For simply inquring if the current core is numerically
 | |
|  * lowest in a given mask, use :
 | |
|  *	cvmx_coremask_is_core_first_core( pcm, dvmx_get_core_num())
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * Returns the number of 1 bits set in a coremask
 | |
|  *
 | |
|  * @param[in] pcm - pointer to core mask
 | |
|  *
 | |
|  * Return: number of bits set in the coremask
 | |
|  */
 | |
| static inline int cvmx_coremask_get_core_count(const struct cvmx_coremask *pcm)
 | |
| {
 | |
| 	int i;
 | |
| 	int count = 0;
 | |
| 
 | |
| 	for (i = 0; i < CVMX_COREMASK_USED_BMPSZ; i++)
 | |
| 		count += __builtin_popcountll(pcm->coremask_bitmap[i]);
 | |
| 
 | |
| 	return count;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * For multi-node systems, return the node a core belongs to.
 | |
|  *
 | |
|  * @param core - core number (0-1023)
 | |
|  *
 | |
|  * Return: node number core belongs to
 | |
|  */
 | |
| static inline int cvmx_coremask_core_to_node(int core)
 | |
| {
 | |
| 	return (core >> CVMX_NODE_NO_SHIFT) & CVMX_NODE_MASK;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Given a core number on a multi-node system, return the core number for a
 | |
|  * particular node.
 | |
|  *
 | |
|  * @param core - global core number
 | |
|  *
 | |
|  * @returns core number local to the node.
 | |
|  */
 | |
| static inline int cvmx_coremask_core_on_node(int core)
 | |
| {
 | |
| 	return (core & ((1 << CVMX_NODE_NO_SHIFT) - 1));
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Returns if one coremask is a subset of another coremask
 | |
|  *
 | |
|  * @param main - main coremask to test
 | |
|  * @param subset - subset coremask to test
 | |
|  *
 | |
|  * Return: 0 if the subset contains cores not in the main coremask or 1 if
 | |
|  *         the subset is fully contained in the main coremask.
 | |
|  */
 | |
| static inline int cvmx_coremask_is_subset(const struct cvmx_coremask *main,
 | |
| 					  const struct cvmx_coremask *subset)
 | |
| {
 | |
| 	int i;
 | |
| 
 | |
| 	for (i = 0; i < CVMX_COREMASK_USED_BMPSZ; i++)
 | |
| 		if ((main->coremask_bitmap[i] & subset->coremask_bitmap[i]) !=
 | |
| 		    subset->coremask_bitmap[i])
 | |
| 			return 0;
 | |
| 	return 1;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Returns if one coremask intersects another coremask
 | |
|  *
 | |
|  * @param c1 - main coremask to test
 | |
|  * @param c2 - subset coremask to test
 | |
|  *
 | |
|  * Return: 1 if coremask c1 intersects coremask c2, 0 if they are exclusive
 | |
|  */
 | |
| static inline int cvmx_coremask_intersects(const struct cvmx_coremask *c1,
 | |
| 					   const struct cvmx_coremask *c2)
 | |
| {
 | |
| 	int i;
 | |
| 
 | |
| 	for (i = 0; i < CVMX_COREMASK_USED_BMPSZ; i++)
 | |
| 		if ((c1->coremask_bitmap[i] & c2->coremask_bitmap[i]) != 0)
 | |
| 			return 1;
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Masks a single node of a coremask
 | |
|  *
 | |
|  * @param pcm - coremask to mask [inout]
 | |
|  * @param node       - node number to mask against
 | |
|  */
 | |
| static inline void cvmx_coremask_mask_node(struct cvmx_coremask *pcm, int node)
 | |
| {
 | |
| 	int i;
 | |
| 
 | |
| 	for (i = 0; i < CVMX_COREMASK_BMP_NODE_CORE_IDX(node, 0); i++)
 | |
| 		pcm->coremask_bitmap[i] = 0;
 | |
| 
 | |
| 	for (i = CVMX_COREMASK_BMP_NODE_CORE_IDX(node + 1, 0);
 | |
| 	     i < CVMX_COREMASK_USED_BMPSZ; i++)
 | |
| 		pcm->coremask_bitmap[i] = 0;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Prints out a coremask in the form of node X: 0x... 0x...
 | |
|  *
 | |
|  * @param[in] pcm - pointer to core mask
 | |
|  *
 | |
|  * Return: nothing
 | |
|  */
 | |
| void cvmx_coremask_print(const struct cvmx_coremask *pcm);
 | |
| 
 | |
| static inline void cvmx_coremask_dprint(const struct cvmx_coremask *pcm)
 | |
| {
 | |
| #if defined(DEBUG)
 | |
| 	cvmx_coremask_print(pcm);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| struct cvmx_coremask *octeon_get_available_coremask(struct cvmx_coremask *pcm);
 | |
| 
 | |
| int validate_coremask(struct cvmx_coremask *pcm);
 | |
| 
 | |
| #endif /* __CVMX_COREMASK_H__ */
 |