mirror of
https://github.com/riscv-software-src/opensbi.git
synced 2025-10-09 18:12:18 +01:00
lib: sbi: Introduce IPI device rating
A platform can have multiple IPI devices (such as ACLINT MSWI, AIA IMSIC, etc). Currently, OpenSBI rely on platform calling the sbi_ipi_set_device() function in correct order and prefer the first avaiable IPI device which is fragile. Instead of the above, introduce IPI device rating and prefer the highest rated IPI device. This further allows extending the sbi_ipi_raw_clear() to clear all available IPI devices. Signed-off-by: Anup Patel <apatel@ventanamicro.com> Tested-by: Nick Hu <nick.hu@sifive.com> Link: https://lore.kernel.org/r/20250904052410.546818-2-apatel@ventanamicro.com Signed-off-by: Anup Patel <anup@brainfault.org>
This commit is contained in:
@@ -507,7 +507,7 @@ static void __noreturn init_warmboot(struct sbi_scratch *scratch, u32 hartid)
|
||||
if (hstate == SBI_HSM_STATE_SUSPENDED) {
|
||||
init_warm_resume(scratch, hartid);
|
||||
} else {
|
||||
sbi_ipi_raw_clear();
|
||||
sbi_ipi_raw_clear(true);
|
||||
init_warm_startup(scratch, hartid);
|
||||
}
|
||||
}
|
||||
|
@@ -15,9 +15,11 @@
|
||||
#include <sbi/sbi_domain.h>
|
||||
#include <sbi/sbi_error.h>
|
||||
#include <sbi/sbi_hart.h>
|
||||
#include <sbi/sbi_heap.h>
|
||||
#include <sbi/sbi_hsm.h>
|
||||
#include <sbi/sbi_init.h>
|
||||
#include <sbi/sbi_ipi.h>
|
||||
#include <sbi/sbi_list.h>
|
||||
#include <sbi/sbi_platform.h>
|
||||
#include <sbi/sbi_pmu.h>
|
||||
#include <sbi/sbi_string.h>
|
||||
@@ -32,8 +34,14 @@ _Static_assert(
|
||||
"type of sbi_ipi_data.ipi_type has changed, please redefine SBI_IPI_EVENT_MAX"
|
||||
);
|
||||
|
||||
struct sbi_ipi_device_node {
|
||||
struct sbi_dlist head;
|
||||
const struct sbi_ipi_device *dev;
|
||||
};
|
||||
|
||||
static unsigned long ipi_data_off;
|
||||
static const struct sbi_ipi_device *ipi_dev = NULL;
|
||||
static SBI_LIST_HEAD(ipi_dev_node_list);
|
||||
static const struct sbi_ipi_event_ops *ipi_ops_array[SBI_IPI_EVENT_MAX];
|
||||
|
||||
static int sbi_ipi_send(struct sbi_scratch *scratch, u32 remote_hartindex,
|
||||
@@ -248,7 +256,7 @@ void sbi_ipi_process(void)
|
||||
sbi_scratch_offset_ptr(scratch, ipi_data_off);
|
||||
|
||||
sbi_pmu_ctr_incr_fw(SBI_PMU_FW_IPI_RECVD);
|
||||
sbi_ipi_raw_clear();
|
||||
sbi_ipi_raw_clear(false);
|
||||
|
||||
ipi_type = atomic_raw_xchg_ulong(&ipi_data->ipi_type, 0);
|
||||
ipi_event = 0;
|
||||
@@ -283,10 +291,19 @@ int sbi_ipi_raw_send(u32 hartindex)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sbi_ipi_raw_clear(void)
|
||||
void sbi_ipi_raw_clear(bool all_devices)
|
||||
{
|
||||
if (ipi_dev && ipi_dev->ipi_clear)
|
||||
ipi_dev->ipi_clear();
|
||||
struct sbi_ipi_device_node *entry;
|
||||
|
||||
if (all_devices) {
|
||||
sbi_list_for_each_entry(entry, &ipi_dev_node_list, head) {
|
||||
if (entry->dev->ipi_clear)
|
||||
entry->dev->ipi_clear();
|
||||
}
|
||||
} else {
|
||||
if (ipi_dev && ipi_dev->ipi_clear)
|
||||
ipi_dev->ipi_clear();
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure that memory or MMIO writes after this
|
||||
@@ -305,12 +322,22 @@ const struct sbi_ipi_device *sbi_ipi_get_device(void)
|
||||
return ipi_dev;
|
||||
}
|
||||
|
||||
void sbi_ipi_set_device(const struct sbi_ipi_device *dev)
|
||||
void sbi_ipi_add_device(const struct sbi_ipi_device *dev)
|
||||
{
|
||||
if (!dev || ipi_dev)
|
||||
struct sbi_ipi_device_node *entry;
|
||||
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
ipi_dev = dev;
|
||||
entry = sbi_zalloc(sizeof(*entry));
|
||||
if (!entry)
|
||||
return;
|
||||
SBI_INIT_LIST_HEAD(&entry->head);
|
||||
entry->dev = dev;
|
||||
sbi_list_add_tail(&entry->head, &ipi_dev_node_list);
|
||||
|
||||
if (!ipi_dev || ipi_dev->rating < dev->rating)
|
||||
ipi_dev = dev;
|
||||
}
|
||||
|
||||
int sbi_ipi_init(struct sbi_scratch *scratch, bool cold_boot)
|
||||
@@ -347,7 +374,7 @@ int sbi_ipi_init(struct sbi_scratch *scratch, bool cold_boot)
|
||||
ipi_data->ipi_type = 0x00;
|
||||
|
||||
/* Clear any pending IPIs for the current hart */
|
||||
sbi_ipi_raw_clear();
|
||||
sbi_ipi_raw_clear(true);
|
||||
|
||||
/* Enable software interrupts */
|
||||
csr_set(CSR_MIE, MIP_MSIP);
|
||||
|
@@ -62,6 +62,7 @@ static void mswi_ipi_clear(void)
|
||||
|
||||
static struct sbi_ipi_device aclint_mswi = {
|
||||
.name = "aclint-mswi",
|
||||
.rating = 100,
|
||||
.ipi_send = mswi_ipi_send,
|
||||
.ipi_clear = mswi_ipi_clear
|
||||
};
|
||||
@@ -106,7 +107,7 @@ int aclint_mswi_cold_init(struct aclint_mswi_data *mswi)
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
sbi_ipi_set_device(&aclint_mswi);
|
||||
sbi_ipi_add_device(&aclint_mswi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -61,6 +61,7 @@ static void plicsw_ipi_clear(void)
|
||||
|
||||
static struct sbi_ipi_device plicsw_ipi = {
|
||||
.name = "andes_plicsw",
|
||||
.rating = 200,
|
||||
.ipi_send = plicsw_ipi_send,
|
||||
.ipi_clear = plicsw_ipi_clear
|
||||
};
|
||||
@@ -99,7 +100,7 @@ int plicsw_cold_ipi_init(struct plicsw_data *plicsw)
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
sbi_ipi_set_device(&plicsw_ipi);
|
||||
sbi_ipi_add_device(&plicsw_ipi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -199,6 +199,7 @@ static void imsic_ipi_send(u32 hart_index)
|
||||
|
||||
static struct sbi_ipi_device imsic_ipi_device = {
|
||||
.name = "aia-imsic",
|
||||
.rating = 300,
|
||||
.ipi_send = imsic_ipi_send
|
||||
};
|
||||
|
||||
@@ -393,7 +394,7 @@ int imsic_cold_irqchip_init(struct imsic_data *imsic)
|
||||
sbi_irqchip_add_device(&imsic_device);
|
||||
|
||||
/* Register IPI device */
|
||||
sbi_ipi_set_device(&imsic_ipi_device);
|
||||
sbi_ipi_add_device(&imsic_ipi_device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user