ssi: cache SSIPeripheralClass to avoid GET_CLASS()
Investigating why some BMC models are so slow compared to a plain ARM virt machines I did some profiling of: ./qemu-system-arm -M romulus-bmc -nic user \ -drive file=obmc-phosphor-image-romulus.static.mtd,format=raw,if=mtd \ -nographic -serial mon:stdio And saw that object_class_dynamic_cast_assert was dominating the profile times. We have a number of cases in this model of the SSI bus. As the class is static once the object is created we just cache it and use it instead of the dynamic case macros. Profiling against: ./tests/venv/bin/avocado run \ tests/avocado/machine_aspeed.py:test_arm_ast2500_romulus_openbmc_v2_9_0 Before: 35.565 s ± 0.087 s After: 15.713 s ± 0.287 s Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Cc: Cédric Le Goater <clg@kaod.org> Tested-by: Cédric Le Goater <clg@kaod.org> Reviewed-by: Cédric Le Goater <clg@kaod.org> Message-Id: <20220811151413.3350684-6-alex.bennee@linaro.org> Message-Id: <20220923084803.498337-6-clg@kaod.org> Signed-off-by: Cédric Le Goater <clg@kaod.org>
This commit is contained in:
parent
7b5093b85b
commit
db96605a49
18
hw/ssi/ssi.c
18
hw/ssi/ssi.c
|
@ -38,9 +38,8 @@ static void ssi_cs_default(void *opaque, int n, int level)
|
||||||
bool cs = !!level;
|
bool cs = !!level;
|
||||||
assert(n == 0);
|
assert(n == 0);
|
||||||
if (s->cs != cs) {
|
if (s->cs != cs) {
|
||||||
SSIPeripheralClass *ssc = SSI_PERIPHERAL_GET_CLASS(s);
|
if (s->spc->set_cs) {
|
||||||
if (ssc->set_cs) {
|
s->spc->set_cs(s, cs);
|
||||||
ssc->set_cs(s, cs);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s->cs = cs;
|
s->cs = cs;
|
||||||
|
@ -48,11 +47,11 @@ static void ssi_cs_default(void *opaque, int n, int level)
|
||||||
|
|
||||||
static uint32_t ssi_transfer_raw_default(SSIPeripheral *dev, uint32_t val)
|
static uint32_t ssi_transfer_raw_default(SSIPeripheral *dev, uint32_t val)
|
||||||
{
|
{
|
||||||
SSIPeripheralClass *ssc = SSI_PERIPHERAL_GET_CLASS(dev);
|
SSIPeripheralClass *ssc = dev->spc;
|
||||||
|
|
||||||
if ((dev->cs && ssc->cs_polarity == SSI_CS_HIGH) ||
|
if ((dev->cs && ssc->cs_polarity == SSI_CS_HIGH) ||
|
||||||
(!dev->cs && ssc->cs_polarity == SSI_CS_LOW) ||
|
(!dev->cs && ssc->cs_polarity == SSI_CS_LOW) ||
|
||||||
ssc->cs_polarity == SSI_CS_NONE) {
|
ssc->cs_polarity == SSI_CS_NONE) {
|
||||||
return ssc->transfer(dev, val);
|
return ssc->transfer(dev, val);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -67,6 +66,7 @@ static void ssi_peripheral_realize(DeviceState *dev, Error **errp)
|
||||||
ssc->cs_polarity != SSI_CS_NONE) {
|
ssc->cs_polarity != SSI_CS_NONE) {
|
||||||
qdev_init_gpio_in_named(dev, ssi_cs_default, SSI_GPIO_CS, 1);
|
qdev_init_gpio_in_named(dev, ssi_cs_default, SSI_GPIO_CS, 1);
|
||||||
}
|
}
|
||||||
|
s->spc = ssc;
|
||||||
|
|
||||||
ssc->realize(s, errp);
|
ssc->realize(s, errp);
|
||||||
}
|
}
|
||||||
|
@ -115,13 +115,11 @@ uint32_t ssi_transfer(SSIBus *bus, uint32_t val)
|
||||||
{
|
{
|
||||||
BusState *b = BUS(bus);
|
BusState *b = BUS(bus);
|
||||||
BusChild *kid;
|
BusChild *kid;
|
||||||
SSIPeripheralClass *ssc;
|
|
||||||
uint32_t r = 0;
|
uint32_t r = 0;
|
||||||
|
|
||||||
QTAILQ_FOREACH(kid, &b->children, sibling) {
|
QTAILQ_FOREACH(kid, &b->children, sibling) {
|
||||||
SSIPeripheral *peripheral = SSI_PERIPHERAL(kid->child);
|
SSIPeripheral *p = SSI_PERIPHERAL(kid->child);
|
||||||
ssc = SSI_PERIPHERAL_GET_CLASS(peripheral);
|
r |= p->spc->transfer_raw(p, val);
|
||||||
r |= ssc->transfer_raw(peripheral, val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
|
|
|
@ -59,6 +59,9 @@ struct SSIPeripheralClass {
|
||||||
struct SSIPeripheral {
|
struct SSIPeripheral {
|
||||||
DeviceState parent_obj;
|
DeviceState parent_obj;
|
||||||
|
|
||||||
|
/* cache the class */
|
||||||
|
SSIPeripheralClass *spc;
|
||||||
|
|
||||||
/* Chip select state */
|
/* Chip select state */
|
||||||
bool cs;
|
bool cs;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue