]> git.proxmox.com Git - mirror_qemu.git/blame - hw/ppc/spapr_drc.c
spapr: Consolidate DRC state variables
[mirror_qemu.git] / hw / ppc / spapr_drc.c
CommitLineData
bbf5c878
MR
1/*
2 * QEMU SPAPR Dynamic Reconfiguration Connector Implementation
3 *
4 * Copyright IBM Corp. 2014
5 *
6 * Authors:
7 * Michael Roth <mdroth@linux.vnet.ibm.com>
8 *
9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 * See the COPYING file in the top-level directory.
11 */
12
0d75590d 13#include "qemu/osdep.h"
da34e65c 14#include "qapi/error.h"
4771d756 15#include "cpu.h"
f348b6d1 16#include "qemu/cutils.h"
bbf5c878
MR
17#include "hw/ppc/spapr_drc.h"
18#include "qom/object.h"
19#include "hw/qdev.h"
20#include "qapi/visitor.h"
21#include "qemu/error-report.h"
0cb688d2 22#include "hw/ppc/spapr.h" /* for RTAS return codes */
31834723 23#include "hw/pci-host/spapr.h" /* spapr_phb_remove_pci_device_cb callback */
24ac7755 24#include "trace.h"
bbf5c878
MR
25
26#define DRC_CONTAINER_PATH "/dr-connector"
27#define DRC_INDEX_TYPE_SHIFT 28
627c2ef7 28#define DRC_INDEX_ID_MASK ((1ULL << DRC_INDEX_TYPE_SHIFT) - 1)
bbf5c878 29
2d335818
DG
30sPAPRDRConnectorType spapr_drc_type(sPAPRDRConnector *drc)
31{
32 sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
33
34 return 1 << drck->typeshift;
35}
36
0b55aa91 37uint32_t spapr_drc_index(sPAPRDRConnector *drc)
bbf5c878 38{
2d335818
DG
39 sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
40
bbf5c878
MR
41 /* no set format for a drc index: it only needs to be globally
42 * unique. this is how we encode the DRC type on bare-metal
43 * however, so might as well do that here
44 */
2d335818
DG
45 return (drck->typeshift << DRC_INDEX_TYPE_SHIFT)
46 | (drc->id & DRC_INDEX_ID_MASK);
bbf5c878
MR
47}
48
0dfabd39 49static uint32_t drc_isolate_physical(sPAPRDRConnector *drc)
bbf5c878 50{
9d4c0f4f
DG
51 switch (drc->state) {
52 case SPAPR_DRC_STATE_PHYSICAL_POWERON:
53 return RTAS_OUT_SUCCESS; /* Nothing to do */
54 case SPAPR_DRC_STATE_PHYSICAL_CONFIGURED:
55 break; /* see below */
56 case SPAPR_DRC_STATE_PHYSICAL_UNISOLATE:
57 return RTAS_OUT_PARAM_ERROR; /* not allowed */
58 default:
59 g_assert_not_reached();
60 }
61
b8fdd530
DG
62 /* if the guest is configuring a device attached to this DRC, we
63 * should reset the configuration state at this point since it may
64 * no longer be reliable (guest released device and needs to start
65 * over, or unplug occurred so the FDT is no longer valid)
66 */
0dfabd39
DG
67 g_free(drc->ccs);
68 drc->ccs = NULL;
b8fdd530 69
9d4c0f4f 70 drc->state = SPAPR_DRC_STATE_PHYSICAL_POWERON;
0dfabd39 71
f1c52354 72 if (drc->unplug_requested) {
0dfabd39 73 uint32_t drc_index = spapr_drc_index(drc);
9d4c0f4f
DG
74 trace_spapr_drc_set_isolation_state_finalizing(drc_index);
75 spapr_drc_detach(drc);
9d1852ce 76 }
0dfabd39
DG
77
78 return RTAS_OUT_SUCCESS;
79}
80
81static uint32_t drc_unisolate_physical(sPAPRDRConnector *drc)
82{
9d4c0f4f
DG
83 switch (drc->state) {
84 case SPAPR_DRC_STATE_PHYSICAL_UNISOLATE:
85 case SPAPR_DRC_STATE_PHYSICAL_CONFIGURED:
86 return RTAS_OUT_SUCCESS; /* Nothing to do */
87 case SPAPR_DRC_STATE_PHYSICAL_POWERON:
88 break; /* see below */
89 default:
90 g_assert_not_reached();
91 }
92
0dfabd39
DG
93 /* cannot unisolate a non-existent resource, and, or resources
94 * which are in an 'UNUSABLE' allocation state. (PAPR 2.7,
95 * 13.5.3.5)
96 */
97 if (!drc->dev) {
98 return RTAS_OUT_NO_SUCH_INDICATOR;
99 }
100
9d4c0f4f 101 drc->state = SPAPR_DRC_STATE_PHYSICAL_UNISOLATE;
0dfabd39
DG
102
103 return RTAS_OUT_SUCCESS;
104}
105
106static uint32_t drc_isolate_logical(sPAPRDRConnector *drc)
107{
9d4c0f4f
DG
108 switch (drc->state) {
109 case SPAPR_DRC_STATE_LOGICAL_AVAILABLE:
110 case SPAPR_DRC_STATE_LOGICAL_UNUSABLE:
111 return RTAS_OUT_SUCCESS; /* Nothing to do */
112 case SPAPR_DRC_STATE_LOGICAL_CONFIGURED:
113 break; /* see below */
114 case SPAPR_DRC_STATE_LOGICAL_UNISOLATE:
115 return RTAS_OUT_PARAM_ERROR; /* not allowed */
116 default:
117 g_assert_not_reached();
118 }
119
0dfabd39
DG
120 /* if the guest is configuring a device attached to this DRC, we
121 * should reset the configuration state at this point since it may
122 * no longer be reliable (guest released device and needs to start
123 * over, or unplug occurred so the FDT is no longer valid)
124 */
125 g_free(drc->ccs);
126 drc->ccs = NULL;
9d1852ce 127
cf632463
BR
128 /*
129 * Fail any requests to ISOLATE the LMB DRC if this LMB doesn't
130 * belong to a DIMM device that is marked for removal.
131 *
132 * Currently the guest userspace tool drmgr that drives the memory
133 * hotplug/unplug will just try to remove a set of 'removable' LMBs
134 * in response to a hot unplug request that is based on drc-count.
135 * If the LMB being removed doesn't belong to a DIMM device that is
136 * actually being unplugged, fail the isolation request here.
137 */
0dfabd39 138 if (spapr_drc_type(drc) == SPAPR_DR_CONNECTOR_TYPE_LMB
f1c52354 139 && !drc->unplug_requested) {
0dfabd39 140 return RTAS_OUT_HW_ERROR;
cf632463
BR
141 }
142
9d4c0f4f 143 drc->state = SPAPR_DRC_STATE_LOGICAL_AVAILABLE;
bbf5c878 144
0dfabd39
DG
145 /* if we're awaiting release, but still in an unconfigured state,
146 * it's likely the guest is still in the process of configuring
147 * the device and is transitioning the devices to an ISOLATED
148 * state as a part of that process. so we only complete the
149 * removal when this transition happens for a device in a
150 * configured state, as suggested by the state diagram from PAPR+
151 * 2.7, 13.4
152 */
f1c52354 153 if (drc->unplug_requested) {
0dfabd39 154 uint32_t drc_index = spapr_drc_index(drc);
9d4c0f4f
DG
155 trace_spapr_drc_set_isolation_state_finalizing(drc_index);
156 spapr_drc_detach(drc);
bbf5c878 157 }
0dfabd39
DG
158 return RTAS_OUT_SUCCESS;
159}
160
161static uint32_t drc_unisolate_logical(sPAPRDRConnector *drc)
162{
9d4c0f4f
DG
163 switch (drc->state) {
164 case SPAPR_DRC_STATE_LOGICAL_UNISOLATE:
165 case SPAPR_DRC_STATE_LOGICAL_CONFIGURED:
166 return RTAS_OUT_SUCCESS; /* Nothing to do */
167 case SPAPR_DRC_STATE_LOGICAL_AVAILABLE:
168 break; /* see below */
169 case SPAPR_DRC_STATE_LOGICAL_UNUSABLE:
170 return RTAS_OUT_NO_SUCH_INDICATOR; /* not allowed */
171 default:
172 g_assert_not_reached();
0dfabd39
DG
173 }
174
9d4c0f4f
DG
175 /* Move to AVAILABLE state should have ensured device was present */
176 g_assert(drc->dev);
bbf5c878 177
9d4c0f4f 178 drc->state = SPAPR_DRC_STATE_LOGICAL_UNISOLATE;
0cb688d2 179 return RTAS_OUT_SUCCESS;
bbf5c878
MR
180}
181
61736732 182static uint32_t drc_set_usable(sPAPRDRConnector *drc)
bbf5c878 183{
9d4c0f4f
DG
184 switch (drc->state) {
185 case SPAPR_DRC_STATE_LOGICAL_AVAILABLE:
186 case SPAPR_DRC_STATE_LOGICAL_UNISOLATE:
187 case SPAPR_DRC_STATE_LOGICAL_CONFIGURED:
188 return RTAS_OUT_SUCCESS; /* Nothing to do */
189 case SPAPR_DRC_STATE_LOGICAL_UNUSABLE:
190 break; /* see below */
191 default:
192 g_assert_not_reached();
193 }
194
61736732
DG
195 /* if there's no resource/device associated with the DRC, there's
196 * no way for us to put it in an allocation state consistent with
197 * being 'USABLE'. PAPR 2.7, 13.5.3.4 documents that this should
198 * result in an RTAS return code of -3 / "no such indicator"
199 */
200 if (!drc->dev) {
201 return RTAS_OUT_NO_SUCH_INDICATOR;
202 }
f1c52354 203 if (drc->unplug_requested) {
82a93a1d
DG
204 /* Don't allow the guest to move a device away from UNUSABLE
205 * state when we want to unplug it */
61736732 206 return RTAS_OUT_NO_SUCH_INDICATOR;
9d1852ce
MR
207 }
208
9d4c0f4f 209 drc->state = SPAPR_DRC_STATE_LOGICAL_AVAILABLE;
61736732
DG
210
211 return RTAS_OUT_SUCCESS;
212}
213
214static uint32_t drc_set_unusable(sPAPRDRConnector *drc)
215{
9d4c0f4f
DG
216 switch (drc->state) {
217 case SPAPR_DRC_STATE_LOGICAL_UNUSABLE:
218 return RTAS_OUT_SUCCESS; /* Nothing to do */
219 case SPAPR_DRC_STATE_LOGICAL_AVAILABLE:
220 break; /* see below */
221 case SPAPR_DRC_STATE_LOGICAL_UNISOLATE:
222 case SPAPR_DRC_STATE_LOGICAL_CONFIGURED:
223 return RTAS_OUT_NO_SUCH_INDICATOR; /* not allowed */
224 default:
225 g_assert_not_reached();
226 }
227
228 drc->state = SPAPR_DRC_STATE_LOGICAL_UNUSABLE;
f1c52354 229 if (drc->unplug_requested) {
61736732
DG
230 uint32_t drc_index = spapr_drc_index(drc);
231 trace_spapr_drc_set_allocation_state_finalizing(drc_index);
a8dc47fd 232 spapr_drc_detach(drc);
bbf5c878 233 }
61736732 234
0cb688d2 235 return RTAS_OUT_SUCCESS;
bbf5c878
MR
236}
237
79808336 238static const char *spapr_drc_name(sPAPRDRConnector *drc)
bbf5c878 239{
79808336
DG
240 sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
241
242 /* human-readable name for a DRC to encode into the DT
243 * description. this is mainly only used within a guest in place
244 * of the unique DRC index.
245 *
246 * in the case of VIO/PCI devices, it corresponds to a "location
247 * code" that maps a logical device/function (DRC index) to a
248 * physical (or virtual in the case of VIO) location in the system
249 * by chaining together the "location label" for each
250 * encapsulating component.
251 *
252 * since this is more to do with diagnosing physical hardware
253 * issues than guest compatibility, we choose location codes/DRC
254 * names that adhere to the documented format, but avoid encoding
255 * the entire topology information into the label/code, instead
256 * just using the location codes based on the labels for the
257 * endpoints (VIO/PCI adaptor connectors), which is basically just
258 * "C" followed by an integer ID.
259 *
260 * DRC names as documented by PAPR+ v2.7, 13.5.2.4
261 * location codes as documented by PAPR+ v2.7, 12.3.1.5
262 */
263 return g_strdup_printf("%s%d", drck->drc_name_prefix, drc->id);
bbf5c878
MR
264}
265
bbf5c878
MR
266/*
267 * dr-entity-sense sensor value
268 * returned via get-sensor-state RTAS calls
269 * as expected by state diagram in PAPR+ 2.7, 13.4
270 * based on the current allocation/indicator/power states
271 * for the DR connector.
272 */
f224d35b 273static sPAPRDREntitySense physical_entity_sense(sPAPRDRConnector *drc)
bbf5c878 274{
f224d35b
DG
275 /* this assumes all PCI devices are assigned to a 'live insertion'
276 * power domain, where QEMU manages power state automatically as
277 * opposed to the guest. present, non-PCI resources are unaffected
278 * by power state.
279 */
280 return drc->dev ? SPAPR_DR_ENTITY_SENSE_PRESENT
281 : SPAPR_DR_ENTITY_SENSE_EMPTY;
282}
283
284static sPAPRDREntitySense logical_entity_sense(sPAPRDRConnector *drc)
285{
9d4c0f4f
DG
286 switch (drc->state) {
287 case SPAPR_DRC_STATE_LOGICAL_UNUSABLE:
f224d35b 288 return SPAPR_DR_ENTITY_SENSE_UNUSABLE;
9d4c0f4f
DG
289 case SPAPR_DRC_STATE_LOGICAL_AVAILABLE:
290 case SPAPR_DRC_STATE_LOGICAL_UNISOLATE:
291 case SPAPR_DRC_STATE_LOGICAL_CONFIGURED:
292 g_assert(drc->dev);
293 return SPAPR_DR_ENTITY_SENSE_PRESENT;
294 default:
295 g_assert_not_reached();
bbf5c878 296 }
bbf5c878
MR
297}
298
d7bce999
EB
299static void prop_get_index(Object *obj, Visitor *v, const char *name,
300 void *opaque, Error **errp)
bbf5c878
MR
301{
302 sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj);
0b55aa91 303 uint32_t value = spapr_drc_index(drc);
51e72bc1 304 visit_type_uint32(v, name, &value, errp);
bbf5c878
MR
305}
306
d7bce999
EB
307static void prop_get_fdt(Object *obj, Visitor *v, const char *name,
308 void *opaque, Error **errp)
bbf5c878
MR
309{
310 sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj);
c75304a1 311 Error *err = NULL;
bbf5c878
MR
312 int fdt_offset_next, fdt_offset, fdt_depth;
313 void *fdt;
314
315 if (!drc->fdt) {
a543a554 316 visit_type_null(v, NULL, errp);
bbf5c878
MR
317 return;
318 }
319
320 fdt = drc->fdt;
321 fdt_offset = drc->fdt_start_offset;
322 fdt_depth = 0;
323
324 do {
325 const char *name = NULL;
326 const struct fdt_property *prop = NULL;
327 int prop_len = 0, name_len = 0;
328 uint32_t tag;
329
330 tag = fdt_next_tag(fdt, fdt_offset, &fdt_offset_next);
331 switch (tag) {
332 case FDT_BEGIN_NODE:
333 fdt_depth++;
334 name = fdt_get_name(fdt, fdt_offset, &name_len);
337283df 335 visit_start_struct(v, name, NULL, 0, &err);
c75304a1
MA
336 if (err) {
337 error_propagate(errp, err);
338 return;
339 }
bbf5c878
MR
340 break;
341 case FDT_END_NODE:
342 /* shouldn't ever see an FDT_END_NODE before FDT_BEGIN_NODE */
343 g_assert(fdt_depth > 0);
15c2f669 344 visit_check_struct(v, &err);
1158bb2a 345 visit_end_struct(v, NULL);
c75304a1
MA
346 if (err) {
347 error_propagate(errp, err);
348 return;
349 }
bbf5c878
MR
350 fdt_depth--;
351 break;
352 case FDT_PROP: {
353 int i;
354 prop = fdt_get_property_by_offset(fdt, fdt_offset, &prop_len);
355 name = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
d9f62dde 356 visit_start_list(v, name, NULL, 0, &err);
c75304a1
MA
357 if (err) {
358 error_propagate(errp, err);
359 return;
360 }
bbf5c878 361 for (i = 0; i < prop_len; i++) {
51e72bc1 362 visit_type_uint8(v, NULL, (uint8_t *)&prop->data[i], &err);
c75304a1
MA
363 if (err) {
364 error_propagate(errp, err);
365 return;
366 }
367 }
a4a1c70d 368 visit_check_list(v, &err);
1158bb2a 369 visit_end_list(v, NULL);
a4a1c70d
MA
370 if (err) {
371 error_propagate(errp, err);
372 return;
373 }
bbf5c878
MR
374 break;
375 }
376 default:
377 error_setg(&error_abort, "device FDT in unexpected state: %d", tag);
378 }
379 fdt_offset = fdt_offset_next;
380 } while (fdt_depth != 0);
381}
382
0be4e886 383void spapr_drc_attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt,
5c1da812 384 int fdt_start_offset, Error **errp)
bbf5c878 385{
0b55aa91 386 trace_spapr_drc_attach(spapr_drc_index(drc));
bbf5c878 387
9d4c0f4f 388 if (drc->dev) {
bbf5c878
MR
389 error_setg(errp, "an attached device is still awaiting release");
390 return;
391 }
9d4c0f4f
DG
392 g_assert((drc->state == SPAPR_DRC_STATE_LOGICAL_UNUSABLE)
393 || (drc->state == SPAPR_DRC_STATE_PHYSICAL_POWERON));
5c1da812 394 g_assert(fdt);
bbf5c878 395
bbf5c878
MR
396 drc->dev = d;
397 drc->fdt = fdt;
398 drc->fdt_start_offset = fdt_start_offset;
bbf5c878
MR
399
400 object_property_add_link(OBJECT(drc), "device",
401 object_get_typename(OBJECT(drc->dev)),
402 (Object **)(&drc->dev),
403 NULL, 0, NULL);
404}
405
9c914e53 406static void spapr_drc_release(sPAPRDRConnector *drc)
bbf5c878 407{
6b762f29
DG
408 sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
409
410 drck->release(drc->dev);
bbf5c878 411
f1c52354 412 drc->unplug_requested = false;
bbf5c878
MR
413 g_free(drc->fdt);
414 drc->fdt = NULL;
415 drc->fdt_start_offset = 0;
ba50822f 416 object_property_del(OBJECT(drc), "device", &error_abort);
bbf5c878 417 drc->dev = NULL;
bbf5c878
MR
418}
419
a8dc47fd 420void spapr_drc_detach(sPAPRDRConnector *drc)
9c914e53 421{
9d4c0f4f
DG
422 sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
423
9c914e53
DG
424 trace_spapr_drc_detach(spapr_drc_index(drc));
425
9d4c0f4f 426 g_assert(drc->dev);
a8dc47fd 427
9d4c0f4f 428 drc->unplug_requested = true;
9c914e53 429
9d4c0f4f
DG
430 if (drc->state != drck->empty_state) {
431 trace_spapr_drc_awaiting_quiesce(spapr_drc_index(drc));
9c914e53
DG
432 return;
433 }
434
9c914e53
DG
435 spapr_drc_release(drc);
436}
437
94fd9cba 438void spapr_drc_reset(sPAPRDRConnector *drc)
bbf5c878 439{
9d4c0f4f
DG
440 sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
441
0b55aa91 442 trace_spapr_drc_reset(spapr_drc_index(drc));
b8fdd530
DG
443
444 g_free(drc->ccs);
445 drc->ccs = NULL;
446
bbf5c878 447 /* immediately upon reset we can safely assume DRCs whose devices
4f9242fc 448 * are pending removal can be safely removed.
bbf5c878 449 */
f1c52354 450 if (drc->unplug_requested) {
4f9242fc
DG
451 spapr_drc_release(drc);
452 }
453
4f9242fc 454 if (drc->dev) {
9d4c0f4f
DG
455 /* A device present at reset is ready to go, same as coldplugged */
456 drc->state = drck->ready_state;
4f9242fc 457 } else {
9d4c0f4f 458 drc->state = drck->empty_state;
bbf5c878
MR
459 }
460}
461
94fd9cba
LV
462static void drc_reset(void *opaque)
463{
464 spapr_drc_reset(SPAPR_DR_CONNECTOR(opaque));
465}
466
a50919dd
DHB
467static bool spapr_drc_needed(void *opaque)
468{
469 sPAPRDRConnector *drc = (sPAPRDRConnector *)opaque;
470 sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
f224d35b 471 sPAPRDREntitySense value = drck->dr_entity_sense(drc);
a50919dd
DHB
472
473 /* If no dev is plugged in there is no need to migrate the DRC state */
474 if (value != SPAPR_DR_ENTITY_SENSE_PRESENT) {
475 return false;
476 }
477
478 /*
9d4c0f4f
DG
479 * We need to migrate the state if it's not equal to the expected
480 * long-term state, which is the same as the coldplugged initial
481 * state */
482 return (drc->state != drck->ready_state);
a50919dd
DHB
483}
484
485static const VMStateDescription vmstate_spapr_drc = {
486 .name = "spapr_drc",
487 .version_id = 1,
488 .minimum_version_id = 1,
489 .needed = spapr_drc_needed,
490 .fields = (VMStateField []) {
9d4c0f4f 491 VMSTATE_UINT32(state, sPAPRDRConnector),
cd74d27e 492 VMSTATE_UINT32(dr_indicator, sPAPRDRConnector),
a50919dd
DHB
493 VMSTATE_END_OF_LIST()
494 }
495};
496
bbf5c878
MR
497static void realize(DeviceState *d, Error **errp)
498{
499 sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(d);
bbf5c878
MR
500 Object *root_container;
501 char link_name[256];
502 gchar *child_name;
503 Error *err = NULL;
504
0b55aa91 505 trace_spapr_drc_realize(spapr_drc_index(drc));
bbf5c878
MR
506 /* NOTE: we do this as part of realize/unrealize due to the fact
507 * that the guest will communicate with the DRC via RTAS calls
508 * referencing the global DRC index. By unlinking the DRC
509 * from DRC_CONTAINER_PATH/<drc_index> we effectively make it
510 * inaccessible by the guest, since lookups rely on this path
511 * existing in the composition tree
512 */
513 root_container = container_get(object_get_root(), DRC_CONTAINER_PATH);
0b55aa91 514 snprintf(link_name, sizeof(link_name), "%x", spapr_drc_index(drc));
bbf5c878 515 child_name = object_get_canonical_path_component(OBJECT(drc));
0b55aa91 516 trace_spapr_drc_realize_child(spapr_drc_index(drc), child_name);
bbf5c878
MR
517 object_property_add_alias(root_container, link_name,
518 drc->owner, child_name, &err);
519 if (err) {
4fffeb5e 520 error_report_err(err);
bbf5c878
MR
521 object_unref(OBJECT(drc));
522 }
586d2142 523 g_free(child_name);
0b55aa91 524 vmstate_register(DEVICE(drc), spapr_drc_index(drc), &vmstate_spapr_drc,
a50919dd 525 drc);
6caf3ac6 526 qemu_register_reset(drc_reset, drc);
0b55aa91 527 trace_spapr_drc_realize_complete(spapr_drc_index(drc));
bbf5c878
MR
528}
529
530static void unrealize(DeviceState *d, Error **errp)
531{
532 sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(d);
bbf5c878
MR
533 Object *root_container;
534 char name[256];
535 Error *err = NULL;
536
0b55aa91 537 trace_spapr_drc_unrealize(spapr_drc_index(drc));
bbf5c878 538 root_container = container_get(object_get_root(), DRC_CONTAINER_PATH);
0b55aa91 539 snprintf(name, sizeof(name), "%x", spapr_drc_index(drc));
bbf5c878
MR
540 object_property_del(root_container, name, &err);
541 if (err) {
4fffeb5e 542 error_report_err(err);
bbf5c878
MR
543 object_unref(OBJECT(drc));
544 }
545}
546
2d335818 547sPAPRDRConnector *spapr_dr_connector_new(Object *owner, const char *type,
bbf5c878
MR
548 uint32_t id)
549{
2d335818 550 sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(object_new(type));
94649d42 551 char *prop_name;
bbf5c878 552
bbf5c878
MR
553 drc->id = id;
554 drc->owner = owner;
0b55aa91
DG
555 prop_name = g_strdup_printf("dr-connector[%"PRIu32"]",
556 spapr_drc_index(drc));
94649d42 557 object_property_add_child(owner, prop_name, OBJECT(drc), NULL);
bbf5c878 558 object_property_set_bool(OBJECT(drc), true, "realized", NULL);
94649d42 559 g_free(prop_name);
bbf5c878 560
bbf5c878
MR
561 return drc;
562}
563
564static void spapr_dr_connector_instance_init(Object *obj)
565{
566 sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj);
9d4c0f4f 567 sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
bbf5c878 568
bbf5c878
MR
569 object_property_add_uint32_ptr(obj, "id", &drc->id, NULL);
570 object_property_add(obj, "index", "uint32", prop_get_index,
571 NULL, NULL, NULL, NULL);
bbf5c878
MR
572 object_property_add(obj, "fdt", "struct", prop_get_fdt,
573 NULL, NULL, NULL, NULL);
9d4c0f4f 574 drc->state = drck->empty_state;
bbf5c878
MR
575}
576
577static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
578{
579 DeviceClass *dk = DEVICE_CLASS(k);
bbf5c878 580
bbf5c878
MR
581 dk->realize = realize;
582 dk->unrealize = unrealize;
c401ae8c
MA
583 /*
584 * Reason: it crashes FIXME find and document the real reason
585 */
e90f2a8c 586 dk->user_creatable = false;
bbf5c878
MR
587}
588
f224d35b
DG
589static void spapr_drc_physical_class_init(ObjectClass *k, void *data)
590{
591 sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);
592
593 drck->dr_entity_sense = physical_entity_sense;
0dfabd39
DG
594 drck->isolate = drc_isolate_physical;
595 drck->unisolate = drc_unisolate_physical;
9d4c0f4f
DG
596 drck->ready_state = SPAPR_DRC_STATE_PHYSICAL_CONFIGURED;
597 drck->empty_state = SPAPR_DRC_STATE_PHYSICAL_POWERON;
f224d35b
DG
598}
599
600static void spapr_drc_logical_class_init(ObjectClass *k, void *data)
601{
602 sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);
603
604 drck->dr_entity_sense = logical_entity_sense;
0dfabd39
DG
605 drck->isolate = drc_isolate_logical;
606 drck->unisolate = drc_unisolate_logical;
9d4c0f4f
DG
607 drck->ready_state = SPAPR_DRC_STATE_LOGICAL_CONFIGURED;
608 drck->empty_state = SPAPR_DRC_STATE_LOGICAL_UNUSABLE;
f224d35b
DG
609}
610
2d335818
DG
611static void spapr_drc_cpu_class_init(ObjectClass *k, void *data)
612{
613 sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);
614
615 drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_CPU;
1693ea16 616 drck->typename = "CPU";
79808336 617 drck->drc_name_prefix = "CPU ";
6b762f29 618 drck->release = spapr_core_release;
2d335818
DG
619}
620
621static void spapr_drc_pci_class_init(ObjectClass *k, void *data)
622{
623 sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);
624
625 drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_PCI;
1693ea16 626 drck->typename = "28";
79808336 627 drck->drc_name_prefix = "C";
6b762f29 628 drck->release = spapr_phb_remove_pci_device_cb;
2d335818
DG
629}
630
631static void spapr_drc_lmb_class_init(ObjectClass *k, void *data)
632{
633 sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);
634
635 drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_LMB;
1693ea16 636 drck->typename = "MEM";
79808336 637 drck->drc_name_prefix = "LMB ";
6b762f29 638 drck->release = spapr_lmb_release;
2d335818
DG
639}
640
bbf5c878
MR
641static const TypeInfo spapr_dr_connector_info = {
642 .name = TYPE_SPAPR_DR_CONNECTOR,
643 .parent = TYPE_DEVICE,
644 .instance_size = sizeof(sPAPRDRConnector),
645 .instance_init = spapr_dr_connector_instance_init,
646 .class_size = sizeof(sPAPRDRConnectorClass),
647 .class_init = spapr_dr_connector_class_init,
2d335818
DG
648 .abstract = true,
649};
650
651static const TypeInfo spapr_drc_physical_info = {
652 .name = TYPE_SPAPR_DRC_PHYSICAL,
653 .parent = TYPE_SPAPR_DR_CONNECTOR,
f224d35b 654 .class_init = spapr_drc_physical_class_init,
2d335818
DG
655 .abstract = true,
656};
657
658static const TypeInfo spapr_drc_logical_info = {
659 .name = TYPE_SPAPR_DRC_LOGICAL,
660 .parent = TYPE_SPAPR_DR_CONNECTOR,
f224d35b 661 .class_init = spapr_drc_logical_class_init,
2d335818
DG
662 .abstract = true,
663};
664
665static const TypeInfo spapr_drc_cpu_info = {
666 .name = TYPE_SPAPR_DRC_CPU,
667 .parent = TYPE_SPAPR_DRC_LOGICAL,
2d335818
DG
668 .class_init = spapr_drc_cpu_class_init,
669};
670
671static const TypeInfo spapr_drc_pci_info = {
672 .name = TYPE_SPAPR_DRC_PCI,
673 .parent = TYPE_SPAPR_DRC_PHYSICAL,
2d335818
DG
674 .class_init = spapr_drc_pci_class_init,
675};
676
677static const TypeInfo spapr_drc_lmb_info = {
678 .name = TYPE_SPAPR_DRC_LMB,
679 .parent = TYPE_SPAPR_DRC_LOGICAL,
2d335818 680 .class_init = spapr_drc_lmb_class_init,
bbf5c878
MR
681};
682
bbf5c878
MR
683/* helper functions for external users */
684
fbf55397 685sPAPRDRConnector *spapr_drc_by_index(uint32_t index)
bbf5c878
MR
686{
687 Object *obj;
688 char name[256];
689
690 snprintf(name, sizeof(name), "%s/%x", DRC_CONTAINER_PATH, index);
691 obj = object_resolve_path(name, NULL);
692
693 return !obj ? NULL : SPAPR_DR_CONNECTOR(obj);
694}
695
fbf55397 696sPAPRDRConnector *spapr_drc_by_id(const char *type, uint32_t id)
bbf5c878 697{
fbf55397
DG
698 sPAPRDRConnectorClass *drck
699 = SPAPR_DR_CONNECTOR_CLASS(object_class_by_name(type));
700
701 return spapr_drc_by_index(drck->typeshift << DRC_INDEX_TYPE_SHIFT
702 | (id & DRC_INDEX_ID_MASK));
bbf5c878 703}
e4b798bb 704
e4b798bb
MR
705/**
706 * spapr_drc_populate_dt
707 *
708 * @fdt: libfdt device tree
709 * @path: path in the DT to generate properties
710 * @owner: parent Object/DeviceState for which to generate DRC
711 * descriptions for
712 * @drc_type_mask: mask of sPAPRDRConnectorType values corresponding
713 * to the types of DRCs to generate entries for
714 *
715 * generate OF properties to describe DRC topology/indices to guests
716 *
717 * as documented in PAPR+ v2.1, 13.5.2
718 */
719int spapr_drc_populate_dt(void *fdt, int fdt_offset, Object *owner,
720 uint32_t drc_type_mask)
721{
722 Object *root_container;
723 ObjectProperty *prop;
7746abd8 724 ObjectPropertyIterator iter;
e4b798bb
MR
725 uint32_t drc_count = 0;
726 GArray *drc_indexes, *drc_power_domains;
727 GString *drc_names, *drc_types;
728 int ret;
729
730 /* the first entry of each properties is a 32-bit integer encoding
731 * the number of elements in the array. we won't know this until
732 * we complete the iteration through all the matching DRCs, but
733 * reserve the space now and set the offsets accordingly so we
734 * can fill them in later.
735 */
736 drc_indexes = g_array_new(false, true, sizeof(uint32_t));
737 drc_indexes = g_array_set_size(drc_indexes, 1);
738 drc_power_domains = g_array_new(false, true, sizeof(uint32_t));
739 drc_power_domains = g_array_set_size(drc_power_domains, 1);
740 drc_names = g_string_set_size(g_string_new(NULL), sizeof(uint32_t));
741 drc_types = g_string_set_size(g_string_new(NULL), sizeof(uint32_t));
742
743 /* aliases for all DRConnector objects will be rooted in QOM
744 * composition tree at DRC_CONTAINER_PATH
745 */
746 root_container = container_get(object_get_root(), DRC_CONTAINER_PATH);
747
7746abd8
DB
748 object_property_iter_init(&iter, root_container);
749 while ((prop = object_property_iter_next(&iter))) {
e4b798bb
MR
750 Object *obj;
751 sPAPRDRConnector *drc;
752 sPAPRDRConnectorClass *drck;
753 uint32_t drc_index, drc_power_domain;
754
755 if (!strstart(prop->type, "link<", NULL)) {
756 continue;
757 }
758
759 obj = object_property_get_link(root_container, prop->name, NULL);
760 drc = SPAPR_DR_CONNECTOR(obj);
761 drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
762
763 if (owner && (drc->owner != owner)) {
764 continue;
765 }
766
2d335818 767 if ((spapr_drc_type(drc) & drc_type_mask) == 0) {
e4b798bb
MR
768 continue;
769 }
770
771 drc_count++;
772
773 /* ibm,drc-indexes */
0b55aa91 774 drc_index = cpu_to_be32(spapr_drc_index(drc));
e4b798bb
MR
775 g_array_append_val(drc_indexes, drc_index);
776
777 /* ibm,drc-power-domains */
778 drc_power_domain = cpu_to_be32(-1);
779 g_array_append_val(drc_power_domains, drc_power_domain);
780
781 /* ibm,drc-names */
79808336 782 drc_names = g_string_append(drc_names, spapr_drc_name(drc));
e4b798bb
MR
783 drc_names = g_string_insert_len(drc_names, -1, "\0", 1);
784
785 /* ibm,drc-types */
1693ea16 786 drc_types = g_string_append(drc_types, drck->typename);
e4b798bb
MR
787 drc_types = g_string_insert_len(drc_types, -1, "\0", 1);
788 }
789
790 /* now write the drc count into the space we reserved at the
791 * beginning of the arrays previously
792 */
793 *(uint32_t *)drc_indexes->data = cpu_to_be32(drc_count);
794 *(uint32_t *)drc_power_domains->data = cpu_to_be32(drc_count);
795 *(uint32_t *)drc_names->str = cpu_to_be32(drc_count);
796 *(uint32_t *)drc_types->str = cpu_to_be32(drc_count);
797
798 ret = fdt_setprop(fdt, fdt_offset, "ibm,drc-indexes",
799 drc_indexes->data,
800 drc_indexes->len * sizeof(uint32_t));
801 if (ret) {
ce9863b7 802 error_report("Couldn't create ibm,drc-indexes property");
e4b798bb
MR
803 goto out;
804 }
805
806 ret = fdt_setprop(fdt, fdt_offset, "ibm,drc-power-domains",
807 drc_power_domains->data,
808 drc_power_domains->len * sizeof(uint32_t));
809 if (ret) {
ce9863b7 810 error_report("Couldn't finalize ibm,drc-power-domains property");
e4b798bb
MR
811 goto out;
812 }
813
814 ret = fdt_setprop(fdt, fdt_offset, "ibm,drc-names",
815 drc_names->str, drc_names->len);
816 if (ret) {
ce9863b7 817 error_report("Couldn't finalize ibm,drc-names property");
e4b798bb
MR
818 goto out;
819 }
820
821 ret = fdt_setprop(fdt, fdt_offset, "ibm,drc-types",
822 drc_types->str, drc_types->len);
823 if (ret) {
ce9863b7 824 error_report("Couldn't finalize ibm,drc-types property");
e4b798bb
MR
825 goto out;
826 }
827
828out:
829 g_array_free(drc_indexes, true);
830 g_array_free(drc_power_domains, true);
831 g_string_free(drc_names, true);
832 g_string_free(drc_types, true);
833
834 return ret;
835}
b89b3d39
DG
836
837/*
838 * RTAS calls
839 */
840
7b7258f8 841static uint32_t rtas_set_isolation_state(uint32_t idx, uint32_t state)
b89b3d39 842{
7b7258f8
DG
843 sPAPRDRConnector *drc = spapr_drc_by_index(idx);
844 sPAPRDRConnectorClass *drck;
845
846 if (!drc) {
0dfabd39 847 return RTAS_OUT_NO_SUCH_INDICATOR;
b89b3d39
DG
848 }
849
0dfabd39
DG
850 trace_spapr_drc_set_isolation_state(spapr_drc_index(drc), state);
851
7b7258f8 852 drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
0dfabd39
DG
853
854 switch (state) {
855 case SPAPR_DR_ISOLATION_STATE_ISOLATED:
856 return drck->isolate(drc);
857
858 case SPAPR_DR_ISOLATION_STATE_UNISOLATED:
859 return drck->unisolate(drc);
860
861 default:
862 return RTAS_OUT_PARAM_ERROR;
863 }
b89b3d39
DG
864}
865
7b7258f8 866static uint32_t rtas_set_allocation_state(uint32_t idx, uint32_t state)
b89b3d39 867{
7b7258f8 868 sPAPRDRConnector *drc = spapr_drc_by_index(idx);
b89b3d39 869
61736732
DG
870 if (!drc || !object_dynamic_cast(OBJECT(drc), TYPE_SPAPR_DRC_LOGICAL)) {
871 return RTAS_OUT_NO_SUCH_INDICATOR;
b89b3d39
DG
872 }
873
61736732
DG
874 trace_spapr_drc_set_allocation_state(spapr_drc_index(drc), state);
875
876 switch (state) {
877 case SPAPR_DR_ALLOCATION_STATE_USABLE:
878 return drc_set_usable(drc);
879
880 case SPAPR_DR_ALLOCATION_STATE_UNUSABLE:
881 return drc_set_unusable(drc);
882
883 default:
884 return RTAS_OUT_PARAM_ERROR;
885 }
7b7258f8 886}
b89b3d39 887
cd74d27e 888static uint32_t rtas_set_dr_indicator(uint32_t idx, uint32_t state)
7b7258f8
DG
889{
890 sPAPRDRConnector *drc = spapr_drc_by_index(idx);
b89b3d39 891
b89b3d39 892 if (!drc) {
7b7258f8
DG
893 return RTAS_OUT_PARAM_ERROR;
894 }
895
cd74d27e
DG
896 trace_spapr_drc_set_dr_indicator(idx, state);
897 drc->dr_indicator = state;
898 return RTAS_OUT_SUCCESS;
7b7258f8
DG
899}
900
901static void rtas_set_indicator(PowerPCCPU *cpu, sPAPRMachineState *spapr,
902 uint32_t token,
903 uint32_t nargs, target_ulong args,
904 uint32_t nret, target_ulong rets)
905{
906 uint32_t type, idx, state;
907 uint32_t ret = RTAS_OUT_SUCCESS;
908
909 if (nargs != 3 || nret != 1) {
b89b3d39
DG
910 ret = RTAS_OUT_PARAM_ERROR;
911 goto out;
912 }
b89b3d39 913
7b7258f8
DG
914 type = rtas_ld(args, 0);
915 idx = rtas_ld(args, 1);
916 state = rtas_ld(args, 2);
917
918 switch (type) {
b89b3d39 919 case RTAS_SENSOR_TYPE_ISOLATION_STATE:
7b7258f8 920 ret = rtas_set_isolation_state(idx, state);
b89b3d39
DG
921 break;
922 case RTAS_SENSOR_TYPE_DR:
cd74d27e 923 ret = rtas_set_dr_indicator(idx, state);
b89b3d39
DG
924 break;
925 case RTAS_SENSOR_TYPE_ALLOCATION_STATE:
7b7258f8 926 ret = rtas_set_allocation_state(idx, state);
b89b3d39
DG
927 break;
928 default:
7b7258f8 929 ret = RTAS_OUT_NOT_SUPPORTED;
b89b3d39
DG
930 }
931
932out:
933 rtas_st(rets, 0, ret);
b89b3d39
DG
934}
935
936static void rtas_get_sensor_state(PowerPCCPU *cpu, sPAPRMachineState *spapr,
937 uint32_t token, uint32_t nargs,
938 target_ulong args, uint32_t nret,
939 target_ulong rets)
940{
941 uint32_t sensor_type;
942 uint32_t sensor_index;
943 uint32_t sensor_state = 0;
944 sPAPRDRConnector *drc;
945 sPAPRDRConnectorClass *drck;
946 uint32_t ret = RTAS_OUT_SUCCESS;
947
948 if (nargs != 2 || nret != 2) {
949 ret = RTAS_OUT_PARAM_ERROR;
950 goto out;
951 }
952
953 sensor_type = rtas_ld(args, 0);
954 sensor_index = rtas_ld(args, 1);
955
956 if (sensor_type != RTAS_SENSOR_TYPE_ENTITY_SENSE) {
957 /* currently only DR-related sensors are implemented */
958 trace_spapr_rtas_get_sensor_state_not_supported(sensor_index,
959 sensor_type);
960 ret = RTAS_OUT_NOT_SUPPORTED;
961 goto out;
962 }
963
fbf55397 964 drc = spapr_drc_by_index(sensor_index);
b89b3d39
DG
965 if (!drc) {
966 trace_spapr_rtas_get_sensor_state_invalid(sensor_index);
967 ret = RTAS_OUT_PARAM_ERROR;
968 goto out;
969 }
970 drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
f224d35b 971 sensor_state = drck->dr_entity_sense(drc);
b89b3d39
DG
972
973out:
974 rtas_st(rets, 0, ret);
975 rtas_st(rets, 1, sensor_state);
976}
977
978/* configure-connector work area offsets, int32_t units for field
979 * indexes, bytes for field offset/len values.
980 *
981 * as documented by PAPR+ v2.7, 13.5.3.5
982 */
983#define CC_IDX_NODE_NAME_OFFSET 2
984#define CC_IDX_PROP_NAME_OFFSET 2
985#define CC_IDX_PROP_LEN 3
986#define CC_IDX_PROP_DATA_OFFSET 4
987#define CC_VAL_DATA_OFFSET ((CC_IDX_PROP_DATA_OFFSET + 1) * 4)
988#define CC_WA_LEN 4096
989
990static void configure_connector_st(target_ulong addr, target_ulong offset,
991 const void *buf, size_t len)
992{
993 cpu_physical_memory_write(ppc64_phys_to_real(addr + offset),
994 buf, MIN(len, CC_WA_LEN - offset));
995}
996
b89b3d39
DG
997static void rtas_ibm_configure_connector(PowerPCCPU *cpu,
998 sPAPRMachineState *spapr,
999 uint32_t token, uint32_t nargs,
1000 target_ulong args, uint32_t nret,
1001 target_ulong rets)
1002{
1003 uint64_t wa_addr;
1004 uint64_t wa_offset;
1005 uint32_t drc_index;
1006 sPAPRDRConnector *drc;
9d4c0f4f 1007 sPAPRDRConnectorClass *drck;
b89b3d39
DG
1008 sPAPRConfigureConnectorState *ccs;
1009 sPAPRDRCCResponse resp = SPAPR_DR_CC_RESPONSE_CONTINUE;
1010 int rc;
b89b3d39
DG
1011
1012 if (nargs != 2 || nret != 1) {
1013 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
1014 return;
1015 }
1016
1017 wa_addr = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 0);
1018
1019 drc_index = rtas_ld(wa_addr, 0);
fbf55397 1020 drc = spapr_drc_by_index(drc_index);
b89b3d39
DG
1021 if (!drc) {
1022 trace_spapr_rtas_ibm_configure_connector_invalid(drc_index);
1023 rc = RTAS_OUT_PARAM_ERROR;
1024 goto out;
1025 }
1026
9d4c0f4f
DG
1027 if ((drc->state != SPAPR_DRC_STATE_LOGICAL_UNISOLATE)
1028 && (drc->state != SPAPR_DRC_STATE_PHYSICAL_UNISOLATE)) {
1029 /* Need to unisolate the device before configuring */
b89b3d39
DG
1030 rc = SPAPR_DR_CC_RESPONSE_NOT_CONFIGURABLE;
1031 goto out;
1032 }
1033
9d4c0f4f
DG
1034 g_assert(drc->fdt);
1035
1036 drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
1037
b8fdd530 1038 ccs = drc->ccs;
b89b3d39
DG
1039 if (!ccs) {
1040 ccs = g_new0(sPAPRConfigureConnectorState, 1);
88af6ea5 1041 ccs->fdt_offset = drc->fdt_start_offset;
b8fdd530 1042 drc->ccs = ccs;
b89b3d39
DG
1043 }
1044
1045 do {
1046 uint32_t tag;
1047 const char *name;
1048 const struct fdt_property *prop;
1049 int fdt_offset_next, prop_len;
1050
88af6ea5 1051 tag = fdt_next_tag(drc->fdt, ccs->fdt_offset, &fdt_offset_next);
b89b3d39
DG
1052
1053 switch (tag) {
1054 case FDT_BEGIN_NODE:
1055 ccs->fdt_depth++;
88af6ea5 1056 name = fdt_get_name(drc->fdt, ccs->fdt_offset, NULL);
b89b3d39
DG
1057
1058 /* provide the name of the next OF node */
1059 wa_offset = CC_VAL_DATA_OFFSET;
1060 rtas_st(wa_addr, CC_IDX_NODE_NAME_OFFSET, wa_offset);
1061 configure_connector_st(wa_addr, wa_offset, name, strlen(name) + 1);
1062 resp = SPAPR_DR_CC_RESPONSE_NEXT_CHILD;
1063 break;
1064 case FDT_END_NODE:
1065 ccs->fdt_depth--;
1066 if (ccs->fdt_depth == 0) {
0b55aa91 1067 uint32_t drc_index = spapr_drc_index(drc);
9d4c0f4f
DG
1068
1069 /* done sending the device tree, move to configured state */
0b55aa91 1070 trace_spapr_drc_set_configured(drc_index);
9d4c0f4f 1071 drc->state = drck->ready_state;
b8fdd530
DG
1072 g_free(ccs);
1073 drc->ccs = NULL;
b89b3d39
DG
1074 ccs = NULL;
1075 resp = SPAPR_DR_CC_RESPONSE_SUCCESS;
1076 } else {
1077 resp = SPAPR_DR_CC_RESPONSE_PREV_PARENT;
1078 }
1079 break;
1080 case FDT_PROP:
88af6ea5 1081 prop = fdt_get_property_by_offset(drc->fdt, ccs->fdt_offset,
b89b3d39 1082 &prop_len);
88af6ea5 1083 name = fdt_string(drc->fdt, fdt32_to_cpu(prop->nameoff));
b89b3d39
DG
1084
1085 /* provide the name of the next OF property */
1086 wa_offset = CC_VAL_DATA_OFFSET;
1087 rtas_st(wa_addr, CC_IDX_PROP_NAME_OFFSET, wa_offset);
1088 configure_connector_st(wa_addr, wa_offset, name, strlen(name) + 1);
1089
1090 /* provide the length and value of the OF property. data gets
1091 * placed immediately after NULL terminator of the OF property's
1092 * name string
1093 */
1094 wa_offset += strlen(name) + 1,
1095 rtas_st(wa_addr, CC_IDX_PROP_LEN, prop_len);
1096 rtas_st(wa_addr, CC_IDX_PROP_DATA_OFFSET, wa_offset);
1097 configure_connector_st(wa_addr, wa_offset, prop->data, prop_len);
1098 resp = SPAPR_DR_CC_RESPONSE_NEXT_PROPERTY;
1099 break;
1100 case FDT_END:
1101 resp = SPAPR_DR_CC_RESPONSE_ERROR;
1102 default:
1103 /* keep seeking for an actionable tag */
1104 break;
1105 }
1106 if (ccs) {
1107 ccs->fdt_offset = fdt_offset_next;
1108 }
1109 } while (resp == SPAPR_DR_CC_RESPONSE_CONTINUE);
1110
1111 rc = resp;
1112out:
1113 rtas_st(rets, 0, rc);
1114}
1115
1116static void spapr_drc_register_types(void)
1117{
1118 type_register_static(&spapr_dr_connector_info);
2d335818
DG
1119 type_register_static(&spapr_drc_physical_info);
1120 type_register_static(&spapr_drc_logical_info);
1121 type_register_static(&spapr_drc_cpu_info);
1122 type_register_static(&spapr_drc_pci_info);
1123 type_register_static(&spapr_drc_lmb_info);
b89b3d39
DG
1124
1125 spapr_rtas_register(RTAS_SET_INDICATOR, "set-indicator",
1126 rtas_set_indicator);
1127 spapr_rtas_register(RTAS_GET_SENSOR_STATE, "get-sensor-state",
1128 rtas_get_sensor_state);
1129 spapr_rtas_register(RTAS_IBM_CONFIGURE_CONNECTOR, "ibm,configure-connector",
1130 rtas_ibm_configure_connector);
1131}
1132type_init(spapr_drc_register_types)