spapr_drc.c 37.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
/*
 * QEMU SPAPR Dynamic Reconfiguration Connector Implementation
 *
 * Copyright IBM Corp. 2014
 *
 * Authors:
 *  Michael Roth      <mdroth@linux.vnet.ibm.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
 */

P
Peter Maydell 已提交
13
#include "qemu/osdep.h"
14
#include "qapi/error.h"
15
#include "qapi/qmp/qnull.h"
16
#include "cpu.h"
17
#include "qemu/cutils.h"
18 19 20 21 22
#include "hw/ppc/spapr_drc.h"
#include "qom/object.h"
#include "hw/qdev.h"
#include "qapi/visitor.h"
#include "qemu/error-report.h"
23
#include "hw/ppc/spapr.h" /* for RTAS return codes */
24
#include "hw/pci-host/spapr.h" /* spapr_phb_remove_pci_device_cb callback */
25
#include "trace.h"
26 27 28

#define DRC_CONTAINER_PATH "/dr-connector"
#define DRC_INDEX_TYPE_SHIFT 28
29
#define DRC_INDEX_ID_MASK ((1ULL << DRC_INDEX_TYPE_SHIFT) - 1)
30

D
David Gibson 已提交
31 32 33 34 35 36 37
sPAPRDRConnectorType spapr_drc_type(sPAPRDRConnector *drc)
{
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);

    return 1 << drck->typeshift;
}

38
uint32_t spapr_drc_index(sPAPRDRConnector *drc)
39
{
D
David Gibson 已提交
40 41
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);

42 43 44 45
    /* no set format for a drc index: it only needs to be globally
     * unique. this is how we encode the DRC type on bare-metal
     * however, so might as well do that here
     */
D
David Gibson 已提交
46 47
    return (drck->typeshift << DRC_INDEX_TYPE_SHIFT)
        | (drc->id & DRC_INDEX_ID_MASK);
48 49
}

50
static uint32_t drc_isolate_physical(sPAPRDRConnector *drc)
51
{
52 53 54 55 56 57 58 59 60 61 62 63
    switch (drc->state) {
    case SPAPR_DRC_STATE_PHYSICAL_POWERON:
        return RTAS_OUT_SUCCESS; /* Nothing to do */
    case SPAPR_DRC_STATE_PHYSICAL_CONFIGURED:
        break; /* see below */
    case SPAPR_DRC_STATE_PHYSICAL_UNISOLATE:
        return RTAS_OUT_PARAM_ERROR; /* not allowed */
    default:
        g_assert_not_reached();
    }

    drc->state = SPAPR_DRC_STATE_PHYSICAL_POWERON;
64

65
    if (drc->unplug_requested) {
66
        uint32_t drc_index = spapr_drc_index(drc);
67 68
        trace_spapr_drc_set_isolation_state_finalizing(drc_index);
        spapr_drc_detach(drc);
69
    }
70 71 72 73 74 75

    return RTAS_OUT_SUCCESS;
}

static uint32_t drc_unisolate_physical(sPAPRDRConnector *drc)
{
76 77 78 79 80 81 82 83 84 85
    switch (drc->state) {
    case SPAPR_DRC_STATE_PHYSICAL_UNISOLATE:
    case SPAPR_DRC_STATE_PHYSICAL_CONFIGURED:
        return RTAS_OUT_SUCCESS; /* Nothing to do */
    case SPAPR_DRC_STATE_PHYSICAL_POWERON:
        break; /* see below */
    default:
        g_assert_not_reached();
    }

86 87 88 89 90 91 92 93
    /* cannot unisolate a non-existent resource, and, or resources
     * which are in an 'UNUSABLE' allocation state. (PAPR 2.7,
     * 13.5.3.5)
     */
    if (!drc->dev) {
        return RTAS_OUT_NO_SUCH_INDICATOR;
    }

94
    drc->state = SPAPR_DRC_STATE_PHYSICAL_UNISOLATE;
95 96
    drc->ccs_offset = drc->fdt_start_offset;
    drc->ccs_depth = 0;
97 98 99 100 101 102

    return RTAS_OUT_SUCCESS;
}

static uint32_t drc_isolate_logical(sPAPRDRConnector *drc)
{
103 104 105 106 107 108 109 110 111 112 113 114
    switch (drc->state) {
    case SPAPR_DRC_STATE_LOGICAL_AVAILABLE:
    case SPAPR_DRC_STATE_LOGICAL_UNUSABLE:
        return RTAS_OUT_SUCCESS; /* Nothing to do */
    case SPAPR_DRC_STATE_LOGICAL_CONFIGURED:
        break; /* see below */
    case SPAPR_DRC_STATE_LOGICAL_UNISOLATE:
        return RTAS_OUT_PARAM_ERROR; /* not allowed */
    default:
        g_assert_not_reached();
    }

B
Bharata B Rao 已提交
115 116 117 118 119 120 121 122 123 124
    /*
     * Fail any requests to ISOLATE the LMB DRC if this LMB doesn't
     * belong to a DIMM device that is marked for removal.
     *
     * Currently the guest userspace tool drmgr that drives the memory
     * hotplug/unplug will just try to remove a set of 'removable' LMBs
     * in response to a hot unplug request that is based on drc-count.
     * If the LMB being removed doesn't belong to a DIMM device that is
     * actually being unplugged, fail the isolation request here.
     */
125
    if (spapr_drc_type(drc) == SPAPR_DR_CONNECTOR_TYPE_LMB
126
        && !drc->unplug_requested) {
127
        return RTAS_OUT_HW_ERROR;
B
Bharata B Rao 已提交
128 129
    }

130
    drc->state = SPAPR_DRC_STATE_LOGICAL_AVAILABLE;
131

132 133 134 135 136 137 138 139
    /* if we're awaiting release, but still in an unconfigured state,
     * it's likely the guest is still in the process of configuring
     * the device and is transitioning the devices to an ISOLATED
     * state as a part of that process. so we only complete the
     * removal when this transition happens for a device in a
     * configured state, as suggested by the state diagram from PAPR+
     * 2.7, 13.4
     */
140
    if (drc->unplug_requested) {
141
        uint32_t drc_index = spapr_drc_index(drc);
142 143
        trace_spapr_drc_set_isolation_state_finalizing(drc_index);
        spapr_drc_detach(drc);
144
    }
145 146 147 148 149
    return RTAS_OUT_SUCCESS;
}

static uint32_t drc_unisolate_logical(sPAPRDRConnector *drc)
{
150 151 152 153 154 155 156 157 158 159
    switch (drc->state) {
    case SPAPR_DRC_STATE_LOGICAL_UNISOLATE:
    case SPAPR_DRC_STATE_LOGICAL_CONFIGURED:
        return RTAS_OUT_SUCCESS; /* Nothing to do */
    case SPAPR_DRC_STATE_LOGICAL_AVAILABLE:
        break; /* see below */
    case SPAPR_DRC_STATE_LOGICAL_UNUSABLE:
        return RTAS_OUT_NO_SUCH_INDICATOR; /* not allowed */
    default:
        g_assert_not_reached();
160 161
    }

162 163
    /* Move to AVAILABLE state should have ensured device was present */
    g_assert(drc->dev);
164

165
    drc->state = SPAPR_DRC_STATE_LOGICAL_UNISOLATE;
166 167 168
    drc->ccs_offset = drc->fdt_start_offset;
    drc->ccs_depth = 0;

169
    return RTAS_OUT_SUCCESS;
170 171
}

172
static uint32_t drc_set_usable(sPAPRDRConnector *drc)
173
{
174 175 176 177 178 179 180 181 182 183 184
    switch (drc->state) {
    case SPAPR_DRC_STATE_LOGICAL_AVAILABLE:
    case SPAPR_DRC_STATE_LOGICAL_UNISOLATE:
    case SPAPR_DRC_STATE_LOGICAL_CONFIGURED:
        return RTAS_OUT_SUCCESS; /* Nothing to do */
    case SPAPR_DRC_STATE_LOGICAL_UNUSABLE:
        break; /* see below */
    default:
        g_assert_not_reached();
    }

185 186 187 188 189 190 191 192
    /* if there's no resource/device associated with the DRC, there's
     * no way for us to put it in an allocation state consistent with
     * being 'USABLE'. PAPR 2.7, 13.5.3.4 documents that this should
     * result in an RTAS return code of -3 / "no such indicator"
     */
    if (!drc->dev) {
        return RTAS_OUT_NO_SUCH_INDICATOR;
    }
193
    if (drc->unplug_requested) {
194 195
        /* Don't allow the guest to move a device away from UNUSABLE
         * state when we want to unplug it */
196
        return RTAS_OUT_NO_SUCH_INDICATOR;
197 198
    }

199
    drc->state = SPAPR_DRC_STATE_LOGICAL_AVAILABLE;
200 201 202 203 204 205

    return RTAS_OUT_SUCCESS;
}

static uint32_t drc_set_unusable(sPAPRDRConnector *drc)
{
206 207 208 209 210 211 212 213 214 215 216 217 218
    switch (drc->state) {
    case SPAPR_DRC_STATE_LOGICAL_UNUSABLE:
        return RTAS_OUT_SUCCESS; /* Nothing to do */
    case SPAPR_DRC_STATE_LOGICAL_AVAILABLE:
        break; /* see below */
    case SPAPR_DRC_STATE_LOGICAL_UNISOLATE:
    case SPAPR_DRC_STATE_LOGICAL_CONFIGURED:
        return RTAS_OUT_NO_SUCH_INDICATOR; /* not allowed */
    default:
        g_assert_not_reached();
    }

    drc->state = SPAPR_DRC_STATE_LOGICAL_UNUSABLE;
219
    if (drc->unplug_requested) {
220 221
        uint32_t drc_index = spapr_drc_index(drc);
        trace_spapr_drc_set_allocation_state_finalizing(drc_index);
222
        spapr_drc_detach(drc);
223
    }
224

225
    return RTAS_OUT_SUCCESS;
226 227
}

D
David Gibson 已提交
228
static const char *spapr_drc_name(sPAPRDRConnector *drc)
229
{
D
David Gibson 已提交
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);

    /* human-readable name for a DRC to encode into the DT
     * description. this is mainly only used within a guest in place
     * of the unique DRC index.
     *
     * in the case of VIO/PCI devices, it corresponds to a "location
     * code" that maps a logical device/function (DRC index) to a
     * physical (or virtual in the case of VIO) location in the system
     * by chaining together the "location label" for each
     * encapsulating component.
     *
     * since this is more to do with diagnosing physical hardware
     * issues than guest compatibility, we choose location codes/DRC
     * names that adhere to the documented format, but avoid encoding
     * the entire topology information into the label/code, instead
     * just using the location codes based on the labels for the
     * endpoints (VIO/PCI adaptor connectors), which is basically just
     * "C" followed by an integer ID.
     *
     * DRC names as documented by PAPR+ v2.7, 13.5.2.4
     * location codes as documented by PAPR+ v2.7, 12.3.1.5
     */
    return g_strdup_printf("%s%d", drck->drc_name_prefix, drc->id);
254 255 256 257 258 259 260 261 262
}

/*
 * dr-entity-sense sensor value
 * returned via get-sensor-state RTAS calls
 * as expected by state diagram in PAPR+ 2.7, 13.4
 * based on the current allocation/indicator/power states
 * for the DR connector.
 */
263
static sPAPRDREntitySense physical_entity_sense(sPAPRDRConnector *drc)
264
{
265 266 267 268 269 270 271 272 273 274 275
    /* this assumes all PCI devices are assigned to a 'live insertion'
     * power domain, where QEMU manages power state automatically as
     * opposed to the guest. present, non-PCI resources are unaffected
     * by power state.
     */
    return drc->dev ? SPAPR_DR_ENTITY_SENSE_PRESENT
        : SPAPR_DR_ENTITY_SENSE_EMPTY;
}

static sPAPRDREntitySense logical_entity_sense(sPAPRDRConnector *drc)
{
276 277
    switch (drc->state) {
    case SPAPR_DRC_STATE_LOGICAL_UNUSABLE:
278
        return SPAPR_DR_ENTITY_SENSE_UNUSABLE;
279 280 281 282 283 284 285
    case SPAPR_DRC_STATE_LOGICAL_AVAILABLE:
    case SPAPR_DRC_STATE_LOGICAL_UNISOLATE:
    case SPAPR_DRC_STATE_LOGICAL_CONFIGURED:
        g_assert(drc->dev);
        return SPAPR_DR_ENTITY_SENSE_PRESENT;
    default:
        g_assert_not_reached();
286 287 288
    }
}

289 290
static void prop_get_index(Object *obj, Visitor *v, const char *name,
                           void *opaque, Error **errp)
291 292
{
    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj);
293
    uint32_t value = spapr_drc_index(drc);
294
    visit_type_uint32(v, name, &value, errp);
295 296
}

297 298
static void prop_get_fdt(Object *obj, Visitor *v, const char *name,
                         void *opaque, Error **errp)
299 300
{
    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj);
301
    QNull *null = NULL;
302
    Error *err = NULL;
303 304 305 306
    int fdt_offset_next, fdt_offset, fdt_depth;
    void *fdt;

    if (!drc->fdt) {
307 308
        visit_type_null(v, NULL, &null, errp);
        QDECREF(null);
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326
        return;
    }

    fdt = drc->fdt;
    fdt_offset = drc->fdt_start_offset;
    fdt_depth = 0;

    do {
        const char *name = NULL;
        const struct fdt_property *prop = NULL;
        int prop_len = 0, name_len = 0;
        uint32_t tag;

        tag = fdt_next_tag(fdt, fdt_offset, &fdt_offset_next);
        switch (tag) {
        case FDT_BEGIN_NODE:
            fdt_depth++;
            name = fdt_get_name(fdt, fdt_offset, &name_len);
327
            visit_start_struct(v, name, NULL, 0, &err);
328 329 330 331
            if (err) {
                error_propagate(errp, err);
                return;
            }
332 333 334 335
            break;
        case FDT_END_NODE:
            /* shouldn't ever see an FDT_END_NODE before FDT_BEGIN_NODE */
            g_assert(fdt_depth > 0);
336
            visit_check_struct(v, &err);
E
Eric Blake 已提交
337
            visit_end_struct(v, NULL);
338 339 340 341
            if (err) {
                error_propagate(errp, err);
                return;
            }
342 343 344 345 346 347
            fdt_depth--;
            break;
        case FDT_PROP: {
            int i;
            prop = fdt_get_property_by_offset(fdt, fdt_offset, &prop_len);
            name = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
348
            visit_start_list(v, name, NULL, 0, &err);
349 350 351 352
            if (err) {
                error_propagate(errp, err);
                return;
            }
353
            for (i = 0; i < prop_len; i++) {
354
                visit_type_uint8(v, NULL, (uint8_t *)&prop->data[i], &err);
355 356 357 358 359
                if (err) {
                    error_propagate(errp, err);
                    return;
                }
            }
360
            visit_check_list(v, &err);
E
Eric Blake 已提交
361
            visit_end_list(v, NULL);
362 363 364 365
            if (err) {
                error_propagate(errp, err);
                return;
            }
366 367 368 369 370 371 372 373 374
            break;
        }
        default:
            error_setg(&error_abort, "device FDT in unexpected state: %d", tag);
        }
        fdt_offset = fdt_offset_next;
    } while (fdt_depth != 0);
}

375
void spapr_drc_attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt,
376
                      int fdt_start_offset, Error **errp)
377
{
378
    trace_spapr_drc_attach(spapr_drc_index(drc));
379

380
    if (drc->dev) {
381 382 383
        error_setg(errp, "an attached device is still awaiting release");
        return;
    }
384 385
    g_assert((drc->state == SPAPR_DRC_STATE_LOGICAL_UNUSABLE)
             || (drc->state == SPAPR_DRC_STATE_PHYSICAL_POWERON));
386
    g_assert(fdt);
387 388 389 390 391 392 393 394 395 396 397

    drc->dev = d;
    drc->fdt = fdt;
    drc->fdt_start_offset = fdt_start_offset;

    object_property_add_link(OBJECT(drc), "device",
                             object_get_typename(OBJECT(drc->dev)),
                             (Object **)(&drc->dev),
                             NULL, 0, NULL);
}

398
static void spapr_drc_release(sPAPRDRConnector *drc)
399
{
D
David Gibson 已提交
400 401 402
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);

    drck->release(drc->dev);
403

404
    drc->unplug_requested = false;
405 406 407
    g_free(drc->fdt);
    drc->fdt = NULL;
    drc->fdt_start_offset = 0;
408
    object_property_del(OBJECT(drc), "device", &error_abort);
409 410 411
    drc->dev = NULL;
}

412
void spapr_drc_detach(sPAPRDRConnector *drc)
413
{
414 415
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);

416 417
    trace_spapr_drc_detach(spapr_drc_index(drc));

418
    g_assert(drc->dev);
419

420
    drc->unplug_requested = true;
421

422 423
    if (drc->state != drck->empty_state) {
        trace_spapr_drc_awaiting_quiesce(spapr_drc_index(drc));
424 425 426 427 428 429
        return;
    }

    spapr_drc_release(drc);
}

430
void spapr_drc_reset(sPAPRDRConnector *drc)
431
{
432 433
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);

434
    trace_spapr_drc_reset(spapr_drc_index(drc));
435

436
    /* immediately upon reset we can safely assume DRCs whose devices
437
     * are pending removal can be safely removed.
438
     */
439
    if (drc->unplug_requested) {
440 441 442 443
        spapr_drc_release(drc);
    }

    if (drc->dev) {
444 445
        /* A device present at reset is ready to go, same as coldplugged */
        drc->state = drck->ready_state;
446 447 448 449 450 451
        /*
         * Ensure that we are able to send the FDT fragment again
         * via configure-connector call if the guest requests.
         */
        drc->ccs_offset = drc->fdt_start_offset;
        drc->ccs_depth = 0;
452
    } else {
453
        drc->state = drck->empty_state;
454 455
        drc->ccs_offset = -1;
        drc->ccs_depth = -1;
456 457 458
    }
}

459
bool spapr_drc_needed(void *opaque)
460 461 462 463 464
{
    sPAPRDRConnector *drc = (sPAPRDRConnector *)opaque;
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);

    /* If no dev is plugged in there is no need to migrate the DRC state */
465
    if (!drc->dev) {
466 467 468 469
        return false;
    }

    /*
470 471 472 473
     * We need to migrate the state if it's not equal to the expected
     * long-term state, which is the same as the coldplugged initial
     * state */
    return (drc->state != drck->ready_state);
474 475 476 477 478 479 480 481
}

static const VMStateDescription vmstate_spapr_drc = {
    .name = "spapr_drc",
    .version_id = 1,
    .minimum_version_id = 1,
    .needed = spapr_drc_needed,
    .fields  = (VMStateField []) {
482
        VMSTATE_UINT32(state, sPAPRDRConnector),
483 484 485 486
        VMSTATE_END_OF_LIST()
    }
};

487 488 489 490
static void realize(DeviceState *d, Error **errp)
{
    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(d);
    Object *root_container;
491
    gchar *link_name;
492 493 494
    gchar *child_name;
    Error *err = NULL;

495
    trace_spapr_drc_realize(spapr_drc_index(drc));
496 497 498 499 500 501 502 503
    /* NOTE: we do this as part of realize/unrealize due to the fact
     * that the guest will communicate with the DRC via RTAS calls
     * referencing the global DRC index. By unlinking the DRC
     * from DRC_CONTAINER_PATH/<drc_index> we effectively make it
     * inaccessible by the guest, since lookups rely on this path
     * existing in the composition tree
     */
    root_container = container_get(object_get_root(), DRC_CONTAINER_PATH);
504
    link_name = g_strdup_printf("%x", spapr_drc_index(drc));
505
    child_name = object_get_canonical_path_component(OBJECT(drc));
506
    trace_spapr_drc_realize_child(spapr_drc_index(drc), child_name);
507 508
    object_property_add_alias(root_container, link_name,
                              drc->owner, child_name, &err);
G
Greg Kurz 已提交
509
    g_free(child_name);
510
    g_free(link_name);
511
    if (err) {
G
Greg Kurz 已提交
512 513
        error_propagate(errp, err);
        return;
514
    }
515
    vmstate_register(DEVICE(drc), spapr_drc_index(drc), &vmstate_spapr_drc,
516
                     drc);
517
    trace_spapr_drc_realize_complete(spapr_drc_index(drc));
518 519 520 521 522 523
}

static void unrealize(DeviceState *d, Error **errp)
{
    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(d);
    Object *root_container;
524
    gchar *name;
525

526
    trace_spapr_drc_unrealize(spapr_drc_index(drc));
G
Greg Kurz 已提交
527
    vmstate_unregister(DEVICE(drc), &vmstate_spapr_drc, drc);
528
    root_container = container_get(object_get_root(), DRC_CONTAINER_PATH);
529
    name = g_strdup_printf("%x", spapr_drc_index(drc));
G
Greg Kurz 已提交
530
    object_property_del(root_container, name, errp);
531
    g_free(name);
532 533
}

D
David Gibson 已提交
534
sPAPRDRConnector *spapr_dr_connector_new(Object *owner, const char *type,
535 536
                                         uint32_t id)
{
D
David Gibson 已提交
537
    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(object_new(type));
538
    char *prop_name;
539 540 541

    drc->id = id;
    drc->owner = owner;
542 543
    prop_name = g_strdup_printf("dr-connector[%"PRIu32"]",
                                spapr_drc_index(drc));
544
    object_property_add_child(owner, prop_name, OBJECT(drc), &error_abort);
545
    object_unref(OBJECT(drc));
546
    object_property_set_bool(OBJECT(drc), true, "realized", NULL);
547
    g_free(prop_name);
548 549 550 551 552 553 554

    return drc;
}

static void spapr_dr_connector_instance_init(Object *obj)
{
    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj);
555
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
556 557 558 559 560 561

    object_property_add_uint32_ptr(obj, "id", &drc->id, NULL);
    object_property_add(obj, "index", "uint32", prop_get_index,
                        NULL, NULL, NULL, NULL);
    object_property_add(obj, "fdt", "struct", prop_get_fdt,
                        NULL, NULL, NULL, NULL);
562
    drc->state = drck->empty_state;
563 564 565 566 567 568 569 570
}

static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
{
    DeviceClass *dk = DEVICE_CLASS(k);

    dk->realize = realize;
    dk->unrealize = unrealize;
571 572 573
    /*
     * Reason: it crashes FIXME find and document the real reason
     */
574
    dk->user_creatable = false;
575 576
}

577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627
static bool drc_physical_needed(void *opaque)
{
    sPAPRDRCPhysical *drcp = (sPAPRDRCPhysical *)opaque;
    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(drcp);

    if ((drc->dev && (drcp->dr_indicator == SPAPR_DR_INDICATOR_ACTIVE))
        || (!drc->dev && (drcp->dr_indicator == SPAPR_DR_INDICATOR_INACTIVE))) {
        return false;
    }
    return true;
}

static const VMStateDescription vmstate_spapr_drc_physical = {
    .name = "spapr_drc/physical",
    .version_id = 1,
    .minimum_version_id = 1,
    .needed = drc_physical_needed,
    .fields  = (VMStateField []) {
        VMSTATE_UINT32(dr_indicator, sPAPRDRCPhysical),
        VMSTATE_END_OF_LIST()
    }
};

static void drc_physical_reset(void *opaque)
{
    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(opaque);
    sPAPRDRCPhysical *drcp = SPAPR_DRC_PHYSICAL(drc);

    if (drc->dev) {
        drcp->dr_indicator = SPAPR_DR_INDICATOR_ACTIVE;
    } else {
        drcp->dr_indicator = SPAPR_DR_INDICATOR_INACTIVE;
    }
}

static void realize_physical(DeviceState *d, Error **errp)
{
    sPAPRDRCPhysical *drcp = SPAPR_DRC_PHYSICAL(d);
    Error *local_err = NULL;

    realize(d, &local_err);
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }

    vmstate_register(DEVICE(drcp), spapr_drc_index(SPAPR_DR_CONNECTOR(drcp)),
                     &vmstate_spapr_drc_physical, drcp);
    qemu_register_reset(drc_physical_reset, drcp);
}

628 629 630 631 632 633 634 635 636 637 638 639 640 641 642
static void unrealize_physical(DeviceState *d, Error **errp)
{
    sPAPRDRCPhysical *drcp = SPAPR_DRC_PHYSICAL(d);
    Error *local_err = NULL;

    unrealize(d, &local_err);
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }

    vmstate_unregister(DEVICE(drcp), &vmstate_spapr_drc_physical, drcp);
    qemu_unregister_reset(drc_physical_reset, drcp);
}

643 644
static void spapr_drc_physical_class_init(ObjectClass *k, void *data)
{
645
    DeviceClass *dk = DEVICE_CLASS(k);
646 647
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);

648
    dk->realize = realize_physical;
649
    dk->unrealize = unrealize_physical;
650
    drck->dr_entity_sense = physical_entity_sense;
651 652
    drck->isolate = drc_isolate_physical;
    drck->unisolate = drc_unisolate_physical;
653 654
    drck->ready_state = SPAPR_DRC_STATE_PHYSICAL_CONFIGURED;
    drck->empty_state = SPAPR_DRC_STATE_PHYSICAL_POWERON;
655 656 657 658 659 660 661
}

static void spapr_drc_logical_class_init(ObjectClass *k, void *data)
{
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);

    drck->dr_entity_sense = logical_entity_sense;
662 663
    drck->isolate = drc_isolate_logical;
    drck->unisolate = drc_unisolate_logical;
664 665
    drck->ready_state = SPAPR_DRC_STATE_LOGICAL_CONFIGURED;
    drck->empty_state = SPAPR_DRC_STATE_LOGICAL_UNUSABLE;
666 667
}

D
David Gibson 已提交
668 669 670 671 672
static void spapr_drc_cpu_class_init(ObjectClass *k, void *data)
{
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);

    drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_CPU;
673
    drck->typename = "CPU";
D
David Gibson 已提交
674
    drck->drc_name_prefix = "CPU ";
D
David Gibson 已提交
675
    drck->release = spapr_core_release;
D
David Gibson 已提交
676 677 678 679 680 681 682
}

static void spapr_drc_pci_class_init(ObjectClass *k, void *data)
{
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);

    drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_PCI;
683
    drck->typename = "28";
D
David Gibson 已提交
684
    drck->drc_name_prefix = "C";
D
David Gibson 已提交
685
    drck->release = spapr_phb_remove_pci_device_cb;
D
David Gibson 已提交
686 687 688 689 690 691 692
}

static void spapr_drc_lmb_class_init(ObjectClass *k, void *data)
{
    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);

    drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_LMB;
693
    drck->typename = "MEM";
D
David Gibson 已提交
694
    drck->drc_name_prefix = "LMB ";
D
David Gibson 已提交
695
    drck->release = spapr_lmb_release;
D
David Gibson 已提交
696 697
}

698 699 700 701 702 703 704
static const TypeInfo spapr_dr_connector_info = {
    .name          = TYPE_SPAPR_DR_CONNECTOR,
    .parent        = TYPE_DEVICE,
    .instance_size = sizeof(sPAPRDRConnector),
    .instance_init = spapr_dr_connector_instance_init,
    .class_size    = sizeof(sPAPRDRConnectorClass),
    .class_init    = spapr_dr_connector_class_init,
D
David Gibson 已提交
705 706 707 708 709 710
    .abstract      = true,
};

static const TypeInfo spapr_drc_physical_info = {
    .name          = TYPE_SPAPR_DRC_PHYSICAL,
    .parent        = TYPE_SPAPR_DR_CONNECTOR,
711
    .instance_size = sizeof(sPAPRDRCPhysical),
712
    .class_init    = spapr_drc_physical_class_init,
D
David Gibson 已提交
713 714 715 716 717 718
    .abstract      = true,
};

static const TypeInfo spapr_drc_logical_info = {
    .name          = TYPE_SPAPR_DRC_LOGICAL,
    .parent        = TYPE_SPAPR_DR_CONNECTOR,
719
    .class_init    = spapr_drc_logical_class_init,
D
David Gibson 已提交
720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738
    .abstract      = true,
};

static const TypeInfo spapr_drc_cpu_info = {
    .name          = TYPE_SPAPR_DRC_CPU,
    .parent        = TYPE_SPAPR_DRC_LOGICAL,
    .class_init    = spapr_drc_cpu_class_init,
};

static const TypeInfo spapr_drc_pci_info = {
    .name          = TYPE_SPAPR_DRC_PCI,
    .parent        = TYPE_SPAPR_DRC_PHYSICAL,
    .class_init    = spapr_drc_pci_class_init,
};

static const TypeInfo spapr_drc_lmb_info = {
    .name          = TYPE_SPAPR_DRC_LMB,
    .parent        = TYPE_SPAPR_DRC_LOGICAL,
    .class_init    = spapr_drc_lmb_class_init,
739 740 741 742
};

/* helper functions for external users */

743
sPAPRDRConnector *spapr_drc_by_index(uint32_t index)
744 745
{
    Object *obj;
746
    gchar *name;
747

748
    name = g_strdup_printf("%s/%x", DRC_CONTAINER_PATH, index);
749
    obj = object_resolve_path(name, NULL);
750
    g_free(name);
751 752 753 754

    return !obj ? NULL : SPAPR_DR_CONNECTOR(obj);
}

755
sPAPRDRConnector *spapr_drc_by_id(const char *type, uint32_t id)
756
{
757 758 759 760 761
    sPAPRDRConnectorClass *drck
        = SPAPR_DR_CONNECTOR_CLASS(object_class_by_name(type));

    return spapr_drc_by_index(drck->typeshift << DRC_INDEX_TYPE_SHIFT
                              | (id & DRC_INDEX_ID_MASK));
762
}
763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782

/**
 * spapr_drc_populate_dt
 *
 * @fdt: libfdt device tree
 * @path: path in the DT to generate properties
 * @owner: parent Object/DeviceState for which to generate DRC
 *         descriptions for
 * @drc_type_mask: mask of sPAPRDRConnectorType values corresponding
 *   to the types of DRCs to generate entries for
 *
 * generate OF properties to describe DRC topology/indices to guests
 *
 * as documented in PAPR+ v2.1, 13.5.2
 */
int spapr_drc_populate_dt(void *fdt, int fdt_offset, Object *owner,
                          uint32_t drc_type_mask)
{
    Object *root_container;
    ObjectProperty *prop;
783
    ObjectPropertyIterator iter;
784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806
    uint32_t drc_count = 0;
    GArray *drc_indexes, *drc_power_domains;
    GString *drc_names, *drc_types;
    int ret;

    /* the first entry of each properties is a 32-bit integer encoding
     * the number of elements in the array. we won't know this until
     * we complete the iteration through all the matching DRCs, but
     * reserve the space now and set the offsets accordingly so we
     * can fill them in later.
     */
    drc_indexes = g_array_new(false, true, sizeof(uint32_t));
    drc_indexes = g_array_set_size(drc_indexes, 1);
    drc_power_domains = g_array_new(false, true, sizeof(uint32_t));
    drc_power_domains = g_array_set_size(drc_power_domains, 1);
    drc_names = g_string_set_size(g_string_new(NULL), sizeof(uint32_t));
    drc_types = g_string_set_size(g_string_new(NULL), sizeof(uint32_t));

    /* aliases for all DRConnector objects will be rooted in QOM
     * composition tree at DRC_CONTAINER_PATH
     */
    root_container = container_get(object_get_root(), DRC_CONTAINER_PATH);

807 808
    object_property_iter_init(&iter, root_container);
    while ((prop = object_property_iter_next(&iter))) {
809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825
        Object *obj;
        sPAPRDRConnector *drc;
        sPAPRDRConnectorClass *drck;
        uint32_t drc_index, drc_power_domain;

        if (!strstart(prop->type, "link<", NULL)) {
            continue;
        }

        obj = object_property_get_link(root_container, prop->name, NULL);
        drc = SPAPR_DR_CONNECTOR(obj);
        drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);

        if (owner && (drc->owner != owner)) {
            continue;
        }

D
David Gibson 已提交
826
        if ((spapr_drc_type(drc) & drc_type_mask) == 0) {
827 828 829 830 831 832
            continue;
        }

        drc_count++;

        /* ibm,drc-indexes */
833
        drc_index = cpu_to_be32(spapr_drc_index(drc));
834 835 836 837 838 839 840
        g_array_append_val(drc_indexes, drc_index);

        /* ibm,drc-power-domains */
        drc_power_domain = cpu_to_be32(-1);
        g_array_append_val(drc_power_domains, drc_power_domain);

        /* ibm,drc-names */
D
David Gibson 已提交
841
        drc_names = g_string_append(drc_names, spapr_drc_name(drc));
842 843 844
        drc_names = g_string_insert_len(drc_names, -1, "\0", 1);

        /* ibm,drc-types */
845
        drc_types = g_string_append(drc_types, drck->typename);
846 847 848 849 850 851 852 853 854 855 856 857 858 859 860
        drc_types = g_string_insert_len(drc_types, -1, "\0", 1);
    }

    /* now write the drc count into the space we reserved at the
     * beginning of the arrays previously
     */
    *(uint32_t *)drc_indexes->data = cpu_to_be32(drc_count);
    *(uint32_t *)drc_power_domains->data = cpu_to_be32(drc_count);
    *(uint32_t *)drc_names->str = cpu_to_be32(drc_count);
    *(uint32_t *)drc_types->str = cpu_to_be32(drc_count);

    ret = fdt_setprop(fdt, fdt_offset, "ibm,drc-indexes",
                      drc_indexes->data,
                      drc_indexes->len * sizeof(uint32_t));
    if (ret) {
861
        error_report("Couldn't create ibm,drc-indexes property");
862 863 864 865 866 867 868
        goto out;
    }

    ret = fdt_setprop(fdt, fdt_offset, "ibm,drc-power-domains",
                      drc_power_domains->data,
                      drc_power_domains->len * sizeof(uint32_t));
    if (ret) {
869
        error_report("Couldn't finalize ibm,drc-power-domains property");
870 871 872 873 874 875
        goto out;
    }

    ret = fdt_setprop(fdt, fdt_offset, "ibm,drc-names",
                      drc_names->str, drc_names->len);
    if (ret) {
876
        error_report("Couldn't finalize ibm,drc-names property");
877 878 879 880 881 882
        goto out;
    }

    ret = fdt_setprop(fdt, fdt_offset, "ibm,drc-types",
                      drc_types->str, drc_types->len);
    if (ret) {
883
        error_report("Couldn't finalize ibm,drc-types property");
884 885 886 887 888 889 890 891 892 893 894
        goto out;
    }

out:
    g_array_free(drc_indexes, true);
    g_array_free(drc_power_domains, true);
    g_string_free(drc_names, true);
    g_string_free(drc_types, true);

    return ret;
}
895 896 897 898 899

/*
 * RTAS calls
 */

900
static uint32_t rtas_set_isolation_state(uint32_t idx, uint32_t state)
901
{
902 903 904 905
    sPAPRDRConnector *drc = spapr_drc_by_index(idx);
    sPAPRDRConnectorClass *drck;

    if (!drc) {
906
        return RTAS_OUT_NO_SUCH_INDICATOR;
907 908
    }

909 910
    trace_spapr_drc_set_isolation_state(spapr_drc_index(drc), state);

911
    drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
912 913 914 915 916 917 918 919 920 921 922

    switch (state) {
    case SPAPR_DR_ISOLATION_STATE_ISOLATED:
        return drck->isolate(drc);

    case SPAPR_DR_ISOLATION_STATE_UNISOLATED:
        return drck->unisolate(drc);

    default:
        return RTAS_OUT_PARAM_ERROR;
    }
923 924
}

925
static uint32_t rtas_set_allocation_state(uint32_t idx, uint32_t state)
926
{
927
    sPAPRDRConnector *drc = spapr_drc_by_index(idx);
928

929 930
    if (!drc || !object_dynamic_cast(OBJECT(drc), TYPE_SPAPR_DRC_LOGICAL)) {
        return RTAS_OUT_NO_SUCH_INDICATOR;
931 932
    }

933 934 935 936 937 938 939 940 941 942 943 944
    trace_spapr_drc_set_allocation_state(spapr_drc_index(drc), state);

    switch (state) {
    case SPAPR_DR_ALLOCATION_STATE_USABLE:
        return drc_set_usable(drc);

    case SPAPR_DR_ALLOCATION_STATE_UNUSABLE:
        return drc_set_unusable(drc);

    default:
        return RTAS_OUT_PARAM_ERROR;
    }
945
}
946

947
static uint32_t rtas_set_dr_indicator(uint32_t idx, uint32_t state)
948 949
{
    sPAPRDRConnector *drc = spapr_drc_by_index(idx);
950

951 952 953 954 955 956 957 958
    if (!drc || !object_dynamic_cast(OBJECT(drc), TYPE_SPAPR_DRC_PHYSICAL)) {
        return RTAS_OUT_NO_SUCH_INDICATOR;
    }
    if ((state != SPAPR_DR_INDICATOR_INACTIVE)
        && (state != SPAPR_DR_INDICATOR_ACTIVE)
        && (state != SPAPR_DR_INDICATOR_IDENTIFY)
        && (state != SPAPR_DR_INDICATOR_ACTION)) {
        return RTAS_OUT_PARAM_ERROR; /* bad state parameter */
959 960
    }

961
    trace_spapr_drc_set_dr_indicator(idx, state);
962
    SPAPR_DRC_PHYSICAL(drc)->dr_indicator = state;
963
    return RTAS_OUT_SUCCESS;
964 965 966 967 968 969 970 971 972 973 974
}

static void rtas_set_indicator(PowerPCCPU *cpu, sPAPRMachineState *spapr,
                               uint32_t token,
                               uint32_t nargs, target_ulong args,
                               uint32_t nret, target_ulong rets)
{
    uint32_t type, idx, state;
    uint32_t ret = RTAS_OUT_SUCCESS;

    if (nargs != 3 || nret != 1) {
975 976 977 978
        ret = RTAS_OUT_PARAM_ERROR;
        goto out;
    }

979 980 981 982 983
    type = rtas_ld(args, 0);
    idx = rtas_ld(args, 1);
    state = rtas_ld(args, 2);

    switch (type) {
984
    case RTAS_SENSOR_TYPE_ISOLATION_STATE:
985
        ret = rtas_set_isolation_state(idx, state);
986 987
        break;
    case RTAS_SENSOR_TYPE_DR:
988
        ret = rtas_set_dr_indicator(idx, state);
989 990
        break;
    case RTAS_SENSOR_TYPE_ALLOCATION_STATE:
991
        ret = rtas_set_allocation_state(idx, state);
992 993
        break;
    default:
994
        ret = RTAS_OUT_NOT_SUPPORTED;
995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028
    }

out:
    rtas_st(rets, 0, ret);
}

static void rtas_get_sensor_state(PowerPCCPU *cpu, sPAPRMachineState *spapr,
                                  uint32_t token, uint32_t nargs,
                                  target_ulong args, uint32_t nret,
                                  target_ulong rets)
{
    uint32_t sensor_type;
    uint32_t sensor_index;
    uint32_t sensor_state = 0;
    sPAPRDRConnector *drc;
    sPAPRDRConnectorClass *drck;
    uint32_t ret = RTAS_OUT_SUCCESS;

    if (nargs != 2 || nret != 2) {
        ret = RTAS_OUT_PARAM_ERROR;
        goto out;
    }

    sensor_type = rtas_ld(args, 0);
    sensor_index = rtas_ld(args, 1);

    if (sensor_type != RTAS_SENSOR_TYPE_ENTITY_SENSE) {
        /* currently only DR-related sensors are implemented */
        trace_spapr_rtas_get_sensor_state_not_supported(sensor_index,
                                                        sensor_type);
        ret = RTAS_OUT_NOT_SUPPORTED;
        goto out;
    }

1029
    drc = spapr_drc_by_index(sensor_index);
1030 1031 1032 1033 1034 1035
    if (!drc) {
        trace_spapr_rtas_get_sensor_state_invalid(sensor_index);
        ret = RTAS_OUT_PARAM_ERROR;
        goto out;
    }
    drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
1036
    sensor_state = drck->dr_entity_sense(drc);
1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071

out:
    rtas_st(rets, 0, ret);
    rtas_st(rets, 1, sensor_state);
}

/* configure-connector work area offsets, int32_t units for field
 * indexes, bytes for field offset/len values.
 *
 * as documented by PAPR+ v2.7, 13.5.3.5
 */
#define CC_IDX_NODE_NAME_OFFSET 2
#define CC_IDX_PROP_NAME_OFFSET 2
#define CC_IDX_PROP_LEN 3
#define CC_IDX_PROP_DATA_OFFSET 4
#define CC_VAL_DATA_OFFSET ((CC_IDX_PROP_DATA_OFFSET + 1) * 4)
#define CC_WA_LEN 4096

static void configure_connector_st(target_ulong addr, target_ulong offset,
                                   const void *buf, size_t len)
{
    cpu_physical_memory_write(ppc64_phys_to_real(addr + offset),
                              buf, MIN(len, CC_WA_LEN - offset));
}

static void rtas_ibm_configure_connector(PowerPCCPU *cpu,
                                         sPAPRMachineState *spapr,
                                         uint32_t token, uint32_t nargs,
                                         target_ulong args, uint32_t nret,
                                         target_ulong rets)
{
    uint64_t wa_addr;
    uint64_t wa_offset;
    uint32_t drc_index;
    sPAPRDRConnector *drc;
1072
    sPAPRDRConnectorClass *drck;
1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083
    sPAPRDRCCResponse resp = SPAPR_DR_CC_RESPONSE_CONTINUE;
    int rc;

    if (nargs != 2 || nret != 1) {
        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
        return;
    }

    wa_addr = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 0);

    drc_index = rtas_ld(wa_addr, 0);
1084
    drc = spapr_drc_by_index(drc_index);
1085 1086 1087 1088 1089 1090
    if (!drc) {
        trace_spapr_rtas_ibm_configure_connector_invalid(drc_index);
        rc = RTAS_OUT_PARAM_ERROR;
        goto out;
    }

1091
    if ((drc->state != SPAPR_DRC_STATE_LOGICAL_UNISOLATE)
1092 1093 1094 1095 1096 1097 1098 1099
        && (drc->state != SPAPR_DRC_STATE_PHYSICAL_UNISOLATE)
        && (drc->state != SPAPR_DRC_STATE_LOGICAL_CONFIGURED)
        && (drc->state != SPAPR_DRC_STATE_PHYSICAL_CONFIGURED)) {
        /*
         * Need to unisolate the device before configuring
         * or it should already be in configured state to
         * allow configure-connector be called repeatedly.
         */
1100 1101 1102 1103
        rc = SPAPR_DR_CC_RESPONSE_NOT_CONFIGURABLE;
        goto out;
    }

1104 1105 1106 1107
    g_assert(drc->fdt);

    drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);

1108 1109 1110 1111 1112 1113
    do {
        uint32_t tag;
        const char *name;
        const struct fdt_property *prop;
        int fdt_offset_next, prop_len;

1114
        tag = fdt_next_tag(drc->fdt, drc->ccs_offset, &fdt_offset_next);
1115 1116 1117

        switch (tag) {
        case FDT_BEGIN_NODE:
1118 1119
            drc->ccs_depth++;
            name = fdt_get_name(drc->fdt, drc->ccs_offset, NULL);
1120 1121 1122 1123 1124 1125 1126 1127

            /* provide the name of the next OF node */
            wa_offset = CC_VAL_DATA_OFFSET;
            rtas_st(wa_addr, CC_IDX_NODE_NAME_OFFSET, wa_offset);
            configure_connector_st(wa_addr, wa_offset, name, strlen(name) + 1);
            resp = SPAPR_DR_CC_RESPONSE_NEXT_CHILD;
            break;
        case FDT_END_NODE:
1128 1129
            drc->ccs_depth--;
            if (drc->ccs_depth == 0) {
1130
                uint32_t drc_index = spapr_drc_index(drc);
1131 1132

                /* done sending the device tree, move to configured state */
1133
                trace_spapr_drc_set_configured(drc_index);
1134
                drc->state = drck->ready_state;
1135 1136 1137 1138 1139 1140 1141
                /*
                 * Ensure that we are able to send the FDT fragment
                 * again via configure-connector call if the guest requests.
                 */
                drc->ccs_offset = drc->fdt_start_offset;
                drc->ccs_depth = 0;
                fdt_offset_next = drc->fdt_start_offset;
1142 1143 1144 1145 1146 1147
                resp = SPAPR_DR_CC_RESPONSE_SUCCESS;
            } else {
                resp = SPAPR_DR_CC_RESPONSE_PREV_PARENT;
            }
            break;
        case FDT_PROP:
1148
            prop = fdt_get_property_by_offset(drc->fdt, drc->ccs_offset,
1149
                                              &prop_len);
D
David Gibson 已提交
1150
            name = fdt_string(drc->fdt, fdt32_to_cpu(prop->nameoff));
1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172

            /* provide the name of the next OF property */
            wa_offset = CC_VAL_DATA_OFFSET;
            rtas_st(wa_addr, CC_IDX_PROP_NAME_OFFSET, wa_offset);
            configure_connector_st(wa_addr, wa_offset, name, strlen(name) + 1);

            /* provide the length and value of the OF property. data gets
             * placed immediately after NULL terminator of the OF property's
             * name string
             */
            wa_offset += strlen(name) + 1,
            rtas_st(wa_addr, CC_IDX_PROP_LEN, prop_len);
            rtas_st(wa_addr, CC_IDX_PROP_DATA_OFFSET, wa_offset);
            configure_connector_st(wa_addr, wa_offset, prop->data, prop_len);
            resp = SPAPR_DR_CC_RESPONSE_NEXT_PROPERTY;
            break;
        case FDT_END:
            resp = SPAPR_DR_CC_RESPONSE_ERROR;
        default:
            /* keep seeking for an actionable tag */
            break;
        }
1173 1174
        if (drc->ccs_offset >= 0) {
            drc->ccs_offset = fdt_offset_next;
1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185
        }
    } while (resp == SPAPR_DR_CC_RESPONSE_CONTINUE);

    rc = resp;
out:
    rtas_st(rets, 0, rc);
}

static void spapr_drc_register_types(void)
{
    type_register_static(&spapr_dr_connector_info);
D
David Gibson 已提交
1186 1187 1188 1189 1190
    type_register_static(&spapr_drc_physical_info);
    type_register_static(&spapr_drc_logical_info);
    type_register_static(&spapr_drc_cpu_info);
    type_register_static(&spapr_drc_pci_info);
    type_register_static(&spapr_drc_lmb_info);
1191 1192 1193 1194 1195 1196 1197 1198 1199

    spapr_rtas_register(RTAS_SET_INDICATOR, "set-indicator",
                        rtas_set_indicator);
    spapr_rtas_register(RTAS_GET_SENSOR_STATE, "get-sensor-state",
                        rtas_get_sensor_state);
    spapr_rtas_register(RTAS_IBM_CONFIGURE_CONNECTOR, "ibm,configure-connector",
                        rtas_ibm_configure_connector);
}
type_init(spapr_drc_register_types)