Revision a66e657e

b/hw/pci/pcie.c
26 26
#include "hw/pci/pci_bus.h"
27 27
#include "hw/pci/pcie_regs.h"
28 28
#include "qemu/range.h"
29
#include "qapi/qmp/qerror.h"
29 30

  
30 31
//#define DEBUG_PCIE
31 32
#ifdef DEBUG_PCIE
......
216 217
    hotplug_event_notify(dev);
217 218
}
218 219

  
219
static int pcie_cap_slot_hotplug(DeviceState *qdev,
220
                                 PCIDevice *pci_dev, PCIHotplugState state)
220
static void pcie_cap_slot_hotplug_common(PCIDevice *hotplug_dev,
221
                                         DeviceState *dev,
222
                                         uint8_t **exp_cap, Error **errp)
221 223
{
222
    PCIDevice *d = PCI_DEVICE(qdev);
223
    uint8_t *exp_cap = d->config + d->exp.exp_cap;
224
    uint16_t sltsta = pci_get_word(exp_cap + PCI_EXP_SLTSTA);
225

  
226
    /* Don't send event when device is enabled during qemu machine creation:
227
     * it is present on boot, no hotplug event is necessary. We do send an
228
     * event when the device is disabled later. */
229
    if (state == PCI_COLDPLUG_ENABLED) {
230
        pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
231
                                   PCI_EXP_SLTSTA_PDS);
232
        return 0;
233
    }
224
    PCIDevice *pci_dev = PCI_DEVICE(dev);
225
    *exp_cap = hotplug_dev->config + hotplug_dev->exp.exp_cap;
226
    uint16_t sltsta = pci_get_word(*exp_cap + PCI_EXP_SLTSTA);
234 227

  
235 228
    PCIE_DEV_PRINTF(pci_dev, "hotplug state: %d\n", state);
236 229
    if (sltsta & PCI_EXP_SLTSTA_EIS) {
237 230
        /* the slot is electromechanically locked.
238 231
         * This error is propagated up to qdev and then to HMP/QMP.
239 232
         */
240
        return -EBUSY;
233
        error_setg_errno(errp, -EBUSY, "slot is electromechanically locked");
241 234
    }
242 235

  
243 236
    /* TODO: multifunction hot-plug.
......
245 238
     * hot plugged/unplugged.
246 239
     */
247 240
    assert(PCI_FUNC(pci_dev->devfn) == 0);
241
}
248 242

  
249
    if (state == PCI_HOTPLUG_ENABLED) {
243
void pcie_cap_slot_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
244
                              Error **errp)
245
{
246
    uint8_t *exp_cap;
247

  
248
    pcie_cap_slot_hotplug_common(PCI_DEVICE(hotplug_dev), dev, &exp_cap, errp);
249

  
250
    /* Don't send event when device is enabled during qemu machine creation:
251
     * it is present on boot, no hotplug event is necessary. We do send an
252
     * event when the device is disabled later. */
253
    if (!dev->hotplugged) {
250 254
        pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
251 255
                                   PCI_EXP_SLTSTA_PDS);
252
        pcie_cap_slot_event(d, PCI_EXP_HP_EV_PDC);
253
    } else {
254
        object_unparent(OBJECT(pci_dev));
255
        pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA,
256
                                     PCI_EXP_SLTSTA_PDS);
257
        pcie_cap_slot_event(d, PCI_EXP_HP_EV_PDC);
256
        return;
258 257
    }
259
    return 0;
258

  
259
    pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
260
                               PCI_EXP_SLTSTA_PDS);
261
    pcie_cap_slot_event(PCI_DEVICE(hotplug_dev), PCI_EXP_HP_EV_PDC);
262
}
263

  
264
void pcie_cap_slot_hot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
265
                                 Error **errp)
266
{
267
    uint8_t *exp_cap;
268

  
269
    pcie_cap_slot_hotplug_common(PCI_DEVICE(hotplug_dev), dev, &exp_cap, errp);
270

  
271
    object_unparent(OBJECT(dev));
272
    pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA,
273
                                 PCI_EXP_SLTSTA_PDS);
274
    pcie_cap_slot_event(PCI_DEVICE(hotplug_dev), PCI_EXP_HP_EV_PDC);
260 275
}
261 276

  
262 277
/* pci express slot for pci express root/downstream port
......
305 320

  
306 321
    dev->exp.hpev_notified = false;
307 322

  
308
    pci_bus_hotplug(pci_bridge_get_sec_bus(PCI_BRIDGE(dev)),
309
                    pcie_cap_slot_hotplug, &dev->qdev);
323
    qbus_set_hotplug_handler(BUS(pci_bridge_get_sec_bus(PCI_BRIDGE(dev))),
324
                             DEVICE(dev), NULL);
310 325
}
311 326

  
312 327
void pcie_cap_slot_reset(PCIDevice *dev)
b/hw/pci/pcie_port.c
19 19
 */
20 20

  
21 21
#include "hw/pci/pcie_port.h"
22
#include "hw/hotplug.h"
22 23

  
23 24
void pcie_port_init_reg(PCIDevice *d)
24 25
{
......
149 150
static void pcie_slot_class_init(ObjectClass *oc, void *data)
150 151
{
151 152
    DeviceClass *dc = DEVICE_CLASS(oc);
153
    HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
152 154

  
153 155
    dc->props = pcie_slot_props;
156
    hc->plug = pcie_cap_slot_hotplug_cb;
157
    hc->unplug = pcie_cap_slot_hot_unplug_cb;
154 158
}
155 159

  
156 160
static const TypeInfo pcie_slot_type_info = {
......
159 163
    .instance_size = sizeof(PCIESlot),
160 164
    .abstract = true,
161 165
    .class_init = pcie_slot_class_init,
166
    .interfaces = (InterfaceInfo[]) {
167
        { TYPE_HOTPLUG_HANDLER },
168
        { }
169
    }
162 170
};
163 171

  
164 172
static void pcie_port_register_types(void)
b/include/hw/pci/pcie.h
25 25
#include "hw/pci/pci_regs.h"
26 26
#include "hw/pci/pcie_regs.h"
27 27
#include "hw/pci/pcie_aer.h"
28
#include "hw/hotplug.h"
28 29

  
29 30
typedef enum {
30 31
    /* for attention and power indicator */
......
122 123
    .offset     = vmstate_offset_value(_state, _field, PCIDevice),   \
123 124
}
124 125

  
126
void pcie_cap_slot_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
127
                              Error **errp);
128
void pcie_cap_slot_hot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
129
                                 Error **errp);
125 130
#endif /* QEMU_PCIE_H */

Also available in: Unified diff