Revision 61620c2f hw/ioh3420.c
b/hw/ioh3420.c | ||
---|---|---|
36 | 36 |
#define IOH_EP_EXP_OFFSET 0x90 |
37 | 37 |
#define IOH_EP_AER_OFFSET 0x100 |
38 | 38 |
|
39 |
/* |
|
40 |
* If two MSI vector are allocated, Advanced Error Interrupt Message Number |
|
41 |
* is 1. otherwise 0. |
|
42 |
* 17.12.5.10 RPERRSTS, 32:27 bit Advanced Error Interrupt Message Number. |
|
43 |
*/ |
|
44 |
static uint8_t ioh3420_aer_vector(const PCIDevice *d) |
|
45 |
{ |
|
46 |
switch (msi_nr_vectors_allocated(d)) { |
|
47 |
case 1: |
|
48 |
return 0; |
|
49 |
case 2: |
|
50 |
return 1; |
|
51 |
case 4: |
|
52 |
case 8: |
|
53 |
case 16: |
|
54 |
case 32: |
|
55 |
default: |
|
56 |
break; |
|
57 |
} |
|
58 |
abort(); |
|
59 |
return 0; |
|
60 |
} |
|
61 |
|
|
62 |
static void ioh3420_aer_vector_update(PCIDevice *d) |
|
63 |
{ |
|
64 |
pcie_aer_root_set_vector(d, ioh3420_aer_vector(d)); |
|
65 |
} |
|
66 |
|
|
39 | 67 |
static void ioh3420_write_config(PCIDevice *d, |
40 | 68 |
uint32_t address, uint32_t val, int len) |
41 | 69 |
{ |
70 |
uint32_t root_cmd = |
|
71 |
pci_get_long(d->config + d->exp.aer_cap + PCI_ERR_ROOT_COMMAND); |
|
72 |
|
|
42 | 73 |
pci_bridge_write_config(d, address, val, len); |
43 | 74 |
msi_write_config(d, address, val, len); |
75 |
ioh3420_aer_vector_update(d); |
|
44 | 76 |
pcie_cap_slot_write_config(d, address, val, len); |
45 |
/* TODO: AER */ |
|
77 |
pcie_aer_write_config(d, address, val, len); |
|
78 |
pcie_aer_root_write_config(d, address, val, len, root_cmd); |
|
46 | 79 |
} |
47 | 80 |
|
48 | 81 |
static void ioh3420_reset(DeviceState *qdev) |
49 | 82 |
{ |
50 | 83 |
PCIDevice *d = DO_UPCAST(PCIDevice, qdev, qdev); |
51 | 84 |
msi_reset(d); |
85 |
ioh3420_aer_vector_update(d); |
|
52 | 86 |
pcie_cap_root_reset(d); |
53 | 87 |
pcie_cap_deverr_reset(d); |
54 | 88 |
pcie_cap_slot_reset(d); |
89 |
pcie_aer_root_reset(d); |
|
55 | 90 |
pci_bridge_reset(qdev); |
56 | 91 |
pci_bridge_disable_base_limit(d); |
57 |
/* TODO: AER */ |
|
58 | 92 |
} |
59 | 93 |
|
60 | 94 |
static int ioh3420_initfn(PCIDevice *d) |
... | ... | |
63 | 97 |
PCIEPort *p = DO_UPCAST(PCIEPort, br, br); |
64 | 98 |
PCIESlot *s = DO_UPCAST(PCIESlot, port, p); |
65 | 99 |
int rc; |
100 |
int tmp; |
|
66 | 101 |
|
67 | 102 |
rc = pci_bridge_initfn(d); |
68 | 103 |
if (rc < 0) { |
... | ... | |
78 | 113 |
rc = pci_bridge_ssvid_init(d, IOH_EP_SSVID_OFFSET, |
79 | 114 |
IOH_EP_SSVID_SVID, IOH_EP_SSVID_SSID); |
80 | 115 |
if (rc < 0) { |
81 |
return rc;
|
|
116 |
goto err_bridge;
|
|
82 | 117 |
} |
83 | 118 |
rc = msi_init(d, IOH_EP_MSI_OFFSET, IOH_EP_MSI_NR_VECTOR, |
84 | 119 |
IOH_EP_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_64BIT, |
85 | 120 |
IOH_EP_MSI_SUPPORTED_FLAGS & PCI_MSI_FLAGS_MASKBIT); |
86 | 121 |
if (rc < 0) { |
87 |
return rc;
|
|
122 |
goto err_bridge;
|
|
88 | 123 |
} |
89 | 124 |
rc = pcie_cap_init(d, IOH_EP_EXP_OFFSET, PCI_EXP_TYPE_ROOT_PORT, p->port); |
90 | 125 |
if (rc < 0) { |
91 |
return rc;
|
|
126 |
goto err_msi;
|
|
92 | 127 |
} |
93 | 128 |
pcie_cap_deverr_init(d); |
94 | 129 |
pcie_cap_slot_init(d, s->slot); |
95 | 130 |
pcie_chassis_create(s->chassis); |
96 | 131 |
rc = pcie_chassis_add_slot(s); |
97 | 132 |
if (rc < 0) { |
133 |
goto err_pcie_cap; |
|
98 | 134 |
return rc; |
99 | 135 |
} |
100 | 136 |
pcie_cap_root_init(d); |
101 |
/* TODO: AER */ |
|
137 |
rc = pcie_aer_init(d, IOH_EP_AER_OFFSET); |
|
138 |
if (rc < 0) { |
|
139 |
goto err; |
|
140 |
} |
|
141 |
pcie_aer_root_init(d); |
|
142 |
ioh3420_aer_vector_update(d); |
|
102 | 143 |
return 0; |
144 |
|
|
145 |
err: |
|
146 |
pcie_chassis_del_slot(s); |
|
147 |
err_pcie_cap: |
|
148 |
pcie_cap_exit(d); |
|
149 |
err_msi: |
|
150 |
msi_uninit(d); |
|
151 |
err_bridge: |
|
152 |
tmp = pci_bridge_exitfn(d); |
|
153 |
assert(!tmp); |
|
154 |
return rc; |
|
103 | 155 |
} |
104 | 156 |
|
105 | 157 |
static int ioh3420_exitfn(PCIDevice *d) |
106 | 158 |
{ |
107 |
/* TODO: AER */ |
|
108 |
msi_uninit(d); |
|
159 |
PCIBridge* br = DO_UPCAST(PCIBridge, dev, d); |
|
160 |
PCIEPort *p = DO_UPCAST(PCIEPort, br, br); |
|
161 |
PCIESlot *s = DO_UPCAST(PCIESlot, port, p); |
|
162 |
|
|
163 |
pcie_aer_exit(d); |
|
164 |
pcie_chassis_del_slot(s); |
|
109 | 165 |
pcie_cap_exit(d); |
166 |
msi_uninit(d); |
|
110 | 167 |
return pci_bridge_exitfn(d); |
111 | 168 |
} |
112 | 169 |
|
... | ... | |
142 | 199 |
.post_load = pcie_cap_slot_post_load, |
143 | 200 |
.fields = (VMStateField[]) { |
144 | 201 |
VMSTATE_PCIE_DEVICE(port.br.dev, PCIESlot), |
145 |
/* TODO: AER */ |
|
202 |
VMSTATE_STRUCT(port.br.dev.exp.aer_log, PCIESlot, 0, |
|
203 |
vmstate_pcie_aer_log, PCIEAERLog), |
|
146 | 204 |
VMSTATE_END_OF_LIST() |
147 | 205 |
} |
148 | 206 |
}; |
... | ... | |
164 | 222 |
DEFINE_PROP_UINT8("port", PCIESlot, port.port, 0), |
165 | 223 |
DEFINE_PROP_UINT8("chassis", PCIESlot, chassis, 0), |
166 | 224 |
DEFINE_PROP_UINT16("slot", PCIESlot, slot, 0), |
167 |
/* TODO: AER */ |
|
225 |
DEFINE_PROP_UINT16("aer_log_max", PCIESlot, |
|
226 |
port.br.dev.exp.aer_log.log_max, |
|
227 |
PCIE_AER_LOG_MAX_DEFAULT), |
|
168 | 228 |
DEFINE_PROP_END_OF_LIST(), |
169 | 229 |
} |
170 | 230 |
}; |
Also available in: Unified diff