ahci.c: Don't assume AHCIState's parent is AHCIPCIState
The AHCIState struct can either have AHCIPCIState or SysbusAHCIState as a parent. The ahci_irq_lower() and ahci_irq_raise() functions assume that it is always AHCIPCIState, which is not always the case, which causes a seg fault. Verify what the container of AHCIState is before setting the PCIDevice struct. Signed-off-by: Alistair Francis <alistair.francis@xilinx.com> Acked-by: John Snow <jsnow@redhat.com> Reviewed-by: Peter Crosthwaite <crosthwaite.peter@gmail.com> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
5ea8b9c5a3
commit
bb639f829f
@ -121,9 +121,9 @@ static uint32_t ahci_port_read(AHCIState *s, int port, int offset)
|
|||||||
|
|
||||||
static void ahci_irq_raise(AHCIState *s, AHCIDevice *dev)
|
static void ahci_irq_raise(AHCIState *s, AHCIDevice *dev)
|
||||||
{
|
{
|
||||||
AHCIPCIState *d = container_of(s, AHCIPCIState, ahci);
|
DeviceState *dev_state = s->container;
|
||||||
PCIDevice *pci_dev =
|
PCIDevice *pci_dev = (PCIDevice *) object_dynamic_cast(OBJECT(dev_state),
|
||||||
(PCIDevice *)object_dynamic_cast(OBJECT(d), TYPE_PCI_DEVICE);
|
TYPE_PCI_DEVICE);
|
||||||
|
|
||||||
DPRINTF(0, "raise irq\n");
|
DPRINTF(0, "raise irq\n");
|
||||||
|
|
||||||
@ -136,9 +136,9 @@ static void ahci_irq_raise(AHCIState *s, AHCIDevice *dev)
|
|||||||
|
|
||||||
static void ahci_irq_lower(AHCIState *s, AHCIDevice *dev)
|
static void ahci_irq_lower(AHCIState *s, AHCIDevice *dev)
|
||||||
{
|
{
|
||||||
AHCIPCIState *d = container_of(s, AHCIPCIState, ahci);
|
DeviceState *dev_state = s->container;
|
||||||
PCIDevice *pci_dev =
|
PCIDevice *pci_dev = (PCIDevice *) object_dynamic_cast(OBJECT(dev_state),
|
||||||
(PCIDevice *)object_dynamic_cast(OBJECT(d), TYPE_PCI_DEVICE);
|
TYPE_PCI_DEVICE);
|
||||||
|
|
||||||
DPRINTF(0, "lower irq\n");
|
DPRINTF(0, "lower irq\n");
|
||||||
|
|
||||||
@ -1436,6 +1436,7 @@ void ahci_init(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports)
|
|||||||
s->as = as;
|
s->as = as;
|
||||||
s->ports = ports;
|
s->ports = ports;
|
||||||
s->dev = g_new0(AHCIDevice, ports);
|
s->dev = g_new0(AHCIDevice, ports);
|
||||||
|
s->container = qdev;
|
||||||
ahci_reg_init(s);
|
ahci_reg_init(s);
|
||||||
/* XXX BAR size should be 1k, but that breaks, so bump it to 4k for now */
|
/* XXX BAR size should be 1k, but that breaks, so bump it to 4k for now */
|
||||||
memory_region_init_io(&s->mem, OBJECT(qdev), &ahci_mem_ops, s,
|
memory_region_init_io(&s->mem, OBJECT(qdev), &ahci_mem_ops, s,
|
||||||
|
@ -287,6 +287,8 @@ struct AHCIDevice {
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef struct AHCIState {
|
typedef struct AHCIState {
|
||||||
|
DeviceState *container;
|
||||||
|
|
||||||
AHCIDevice *dev;
|
AHCIDevice *dev;
|
||||||
AHCIControlRegs control_regs;
|
AHCIControlRegs control_regs;
|
||||||
MemoryRegion mem;
|
MemoryRegion mem;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user