x86: mp: Add iterators for CPUs
It is convenient to iterate through the CPUs performing work on each one and processing the result. Add a few iterator functions which handle this. These can be used by any client code. It can call mp_run_on_cpus() on each CPU that is returned, handling them one at a time. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Wolfgang Wallner <wolfgang.wallner@br-automation.com> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
This commit is contained in:
parent
99a573fb32
commit
0538d6833c
@ -684,6 +684,69 @@ int mp_park_aps(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mp_first_cpu(int cpu_select)
|
||||
{
|
||||
struct udevice *dev;
|
||||
int num_cpus;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* This assumes that CPUs are numbered from 0. This function tries to
|
||||
* avoid assuming the CPU 0 is the boot CPU
|
||||
*/
|
||||
if (cpu_select == MP_SELECT_ALL)
|
||||
return 0; /* start with the first one */
|
||||
|
||||
ret = get_bsp(&dev, &num_cpus);
|
||||
if (ret < 0)
|
||||
return log_msg_ret("bsp", ret);
|
||||
|
||||
/* Return boot CPU if requested */
|
||||
if (cpu_select == MP_SELECT_BSP)
|
||||
return ret;
|
||||
|
||||
/* Return something other than the boot CPU, if APs requested */
|
||||
if (cpu_select == MP_SELECT_APS && num_cpus > 1)
|
||||
return ret == 0 ? 1 : 0;
|
||||
|
||||
/* Try to check for an invalid value */
|
||||
if (cpu_select < 0 || cpu_select >= num_cpus)
|
||||
return -EINVAL;
|
||||
|
||||
return cpu_select; /* return the only selected one */
|
||||
}
|
||||
|
||||
int mp_next_cpu(int cpu_select, int prev_cpu)
|
||||
{
|
||||
struct udevice *dev;
|
||||
int num_cpus;
|
||||
int ret;
|
||||
int bsp;
|
||||
|
||||
/* If we selected the BSP or a particular single CPU, we are done */
|
||||
if (!IS_ENABLED(CONFIG_SMP_AP_WORK) || cpu_select == MP_SELECT_BSP ||
|
||||
cpu_select >= 0)
|
||||
return -EFBIG;
|
||||
|
||||
/* Must be doing MP_SELECT_ALL or MP_SELECT_APS; return the next CPU */
|
||||
ret = get_bsp(&dev, &num_cpus);
|
||||
if (ret < 0)
|
||||
return log_msg_ret("bsp", ret);
|
||||
bsp = ret;
|
||||
|
||||
/* Move to the next CPU */
|
||||
assert(prev_cpu >= 0);
|
||||
ret = prev_cpu + 1;
|
||||
|
||||
/* Skip the BSP if needed */
|
||||
if (cpu_select == MP_SELECT_APS && ret == bsp)
|
||||
ret++;
|
||||
if (ret >= num_cpus)
|
||||
return -EFBIG;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mp_init(void)
|
||||
{
|
||||
int num_aps, num_cpus;
|
||||
|
@ -118,6 +118,33 @@ int mp_run_on_cpus(int cpu_select, mp_run_func func, void *arg);
|
||||
* @return 0 if OK, -ve on error
|
||||
*/
|
||||
int mp_park_aps(void);
|
||||
|
||||
/**
|
||||
* mp_first_cpu() - Get the first CPU to process, from a selection
|
||||
*
|
||||
* This is used to iterate through selected CPUs. Call this function first, then
|
||||
* call mp_next_cpu() repeatedly (with the same @cpu_select) until it returns
|
||||
* -EFBIG.
|
||||
*
|
||||
* @cpu_select: Selected CPUs (either a CPU number or MP_SELECT_...)
|
||||
* @return next CPU number to run on (e.g. 0)
|
||||
*/
|
||||
int mp_first_cpu(int cpu_select);
|
||||
|
||||
/**
|
||||
* mp_next_cpu() - Get the next CPU to process, from a selection
|
||||
*
|
||||
* This is used to iterate through selected CPUs. After first calling
|
||||
* mp_first_cpu() once, call this function repeatedly until it returns -EFBIG.
|
||||
*
|
||||
* The value of @cpu_select must be the same for all calls and must match the
|
||||
* value passed to mp_first_cpu(), otherwise the behaviour is undefined.
|
||||
*
|
||||
* @cpu_select: Selected CPUs (either a CPU number or MP_SELECT_...)
|
||||
* @prev_cpu: Previous value returned by mp_first_cpu()/mp_next_cpu()
|
||||
* @return next CPU number to run on (e.g. 0)
|
||||
*/
|
||||
int mp_next_cpu(int cpu_select, int prev_cpu);
|
||||
#else
|
||||
static inline int mp_run_on_cpus(int cpu_select, mp_run_func func, void *arg)
|
||||
{
|
||||
@ -134,6 +161,21 @@ static inline int mp_park_aps(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int mp_first_cpu(int cpu_select)
|
||||
{
|
||||
/* We cannot run on any APs, nor a selected CPU */
|
||||
return cpu_select == MP_SELECT_APS ? -EFBIG : MP_SELECT_BSP;
|
||||
}
|
||||
|
||||
static inline int mp_next_cpu(int cpu_select, int prev_cpu)
|
||||
{
|
||||
/*
|
||||
* When MP is not enabled, there is only one CPU and we did it in
|
||||
* mp_first_cpu()
|
||||
*/
|
||||
return -EFBIG;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _X86_MP_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user