Commit 71569cd8ab for qemu.org
commit 71569cd8aba31fcb3a326c56c307d2b811417c0b
Merge: 94d689d0c6 0f17ae24b5
Author: Stefan Hajnoczi <stefanha@redhat.com>
Date: Wed Mar 12 07:50:24 2025 +0800
Merge tag 'pull-ppc-for-10.0-1-20250311' of https://gitlab.com/npiggin/qemu into staging
* Next round of XIVE patches...
* tag 'pull-ppc-for-10.0-1-20250311' of https://gitlab.com/npiggin/qemu: (72 commits)
docs/system/ppc/amigang.rst: Update for NVRAM emulation
ppc/amigaone: Add #defines for memory map constants
ppc/amigaone: Add kernel and initrd support
ppc/amigaone: Add default environment
ppc/amigaone: Implement NVRAM emulation
ppc/amigaone: Simplify replacement dummy_fw
spapr: Generate random HASHPKEYR for spapr machines
target/ppc: Avoid warning message for zero process table entries
target/ppc: Wire up BookE ATB registers for e500 family
target/ppc: fix timebase register reset state
spapr: nested: Add support for reporting Hostwide state counter
ppc: spapr: Enable 2nd DAWR on Power10 pSeries machine
ppc: Enable 2nd DAWR support on Power10 PowerNV machine
hw/ppc/epapr: Do not swap ePAPR magic value
hw/ppc/spapr: Convert DIRTY_HPTE() macro as hpte_set_dirty() method
hw/ppc/spapr: Convert CLEAN_HPTE() macro as hpte_set_clean() method
hw/ppc/spapr: Convert HPTE_DIRTY() macro as hpte_is_dirty() method
hw/ppc/spapr: Convert HPTE_VALID() macro as hpte_is_valid() method
hw/ppc/spapr: Convert HPTE() macro as hpte_get_ptr() method
target/ppc: Restrict ATTN / SCV / PMINSN helpers to TCG
...
[Fix __packed macro redefinition on FreeBSD 14 hosts:
../hw/ppc/pnv_occ.c:397:9: error: '__packed' macro redefined [-Werror,-Wmacro-redefined]
397 | #define __packed QEMU_PACKED
| ^
/usr/include/sys/cdefs.h:217:9: note: previous definition is here
217 | #define __packed __attribute__((__packed__))
| ^
--Stefan]
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
diff --cc hw/ppc/pnv_occ.c
index 48123ceae1,d9ce35a4d6..bda6b23ad3
--- a/hw/ppc/pnv_occ.c
+++ b/hw/ppc/pnv_occ.c
@@@ -308,3 -363,568 +363,570 @@@ static void pnv_occ_register_types(void
}
type_init(pnv_occ_register_types);
+
+ /* From skiboot/hw/occ.c with tab to space conversion */
+ /* OCC Communication Area for PStates */
+
+ #define OPAL_DYNAMIC_DATA_OFFSET 0x0B80
+ /* relative to HOMER_OPAL_DATA_OFFSET */
+
+ #define MAX_PSTATES 256
+ #define MAX_P8_CORES 12
+ #define MAX_P9_CORES 24
+ #define MAX_P10_CORES 32
+
+ #define MAX_OPAL_CMD_DATA_LENGTH 4090
+ #define MAX_OCC_RSP_DATA_LENGTH 8698
+
+ #define P8_PIR_CORE_MASK 0xFFF8
+ #define P9_PIR_QUAD_MASK 0xFFF0
+ #define P10_PIR_CHIP_MASK 0x0000
+ #define FREQ_MAX_IN_DOMAIN 0
+ #define FREQ_MOST_RECENTLY_SET 1
+
+ #define u8 uint8_t
+ #define s8 int8_t
+ #define u16 uint16_t
+ #define s16 int16_t
+ #define u32 uint32_t
+ #define s32 int32_t
+ #define u64 uint64_t
+ #define s64 int64_t
+ #define __be16 uint16_t
+ #define __be32 uint32_t
++#ifndef __packed
+ #define __packed QEMU_PACKED
++#endif /* !__packed */
+
+ /**
+ * OCC-OPAL Shared Memory Region
+ *
+ * Reference document :
+ * https://github.com/open-power/docs/blob/master/occ/OCC_OpenPwr_FW_Interfaces.pdf
+ *
+ * Supported layout versions:
+ * - 0x01, 0x02 : P8
+ * https://github.com/open-power/occ/blob/master_p8/src/occ/proc/proc_pstate.h
+ *
+ * - 0x90 : P9
+ * https://github.com/open-power/occ/blob/master/src/occ_405/proc/proc_pstate.h
+ * In 0x90 the data is separated into :-
+ * -- Static Data (struct occ_pstate_table): Data is written once by OCC
+ * -- Dynamic Data (struct occ_dynamic_data): Data is updated at runtime
+ *
+ * struct occ_pstate_table - Pstate table layout
+ * @valid: Indicates if data is valid
+ * @version: Layout version [Major/Minor]
+ * @v2.throttle: Reason for limiting the max pstate
+ * @v9.occ_role: OCC role (Master/Slave)
+ * @v#.pstate_min: Minimum pstate ever allowed
+ * @v#.pstate_nom: Nominal pstate
+ * @v#.pstate_turbo: Maximum turbo pstate
+ * @v#.pstate_ultra_turbo: Maximum ultra turbo pstate and the maximum
+ * pstate ever allowed
+ * @v#.pstates: Pstate-id and frequency list from Pmax to Pmin
+ * @v#.pstates.id: Pstate-id
+ * @v#.pstates.flags: Pstate-flag(reserved)
+ * @v2.pstates.vdd: Voltage Identifier
+ * @v2.pstates.vcs: Voltage Identifier
+ * @v#.pstates.freq_khz: Frequency in KHz
+ * @v#.core_max[1..N]: Max pstate with N active cores
+ * @spare/reserved/pad: Unused data
+ */
+ struct occ_pstate_table {
+ u8 valid;
+ u8 version;
+ union __packed {
+ struct __packed { /* Version 0x01 and 0x02 */
+ u8 throttle;
+ s8 pstate_min;
+ s8 pstate_nom;
+ s8 pstate_turbo;
+ s8 pstate_ultra_turbo;
+ u8 spare;
+ u64 reserved;
+ struct __packed {
+ s8 id;
+ u8 flags;
+ u8 vdd;
+ u8 vcs;
+ __be32 freq_khz;
+ } pstates[MAX_PSTATES];
+ s8 core_max[MAX_P8_CORES];
+ u8 pad[100];
+ } v2;
+ struct __packed { /* Version 0x90 */
+ u8 occ_role;
+ u8 pstate_min;
+ u8 pstate_nom;
+ u8 pstate_turbo;
+ u8 pstate_ultra_turbo;
+ u8 spare;
+ u64 reserved1;
+ u64 reserved2;
+ struct __packed {
+ u8 id;
+ u8 flags;
+ u16 reserved;
+ __be32 freq_khz;
+ } pstates[MAX_PSTATES];
+ u8 core_max[MAX_P9_CORES];
+ u8 pad[56];
+ } v9;
+ struct __packed { /* Version 0xA0 */
+ u8 occ_role;
+ u8 pstate_min;
+ u8 pstate_fixed_freq;
+ u8 pstate_base;
+ u8 pstate_ultra_turbo;
+ u8 pstate_fmax;
+ u8 minor;
+ u8 pstate_bottom_throttle;
+ u8 spare;
+ u8 spare1;
+ u32 reserved_32;
+ u64 reserved_64;
+ struct __packed {
+ u8 id;
+ u8 valid;
+ u16 reserved;
+ __be32 freq_khz;
+ } pstates[MAX_PSTATES];
+ u8 core_max[MAX_P10_CORES];
+ u8 pad[48];
+ } v10;
+ };
+ } __packed;
+
+ /**
+ * OPAL-OCC Command Response Interface
+ *
+ * OPAL-OCC Command Buffer
+ *
+ * ---------------------------------------------------------------------
+ * | OPAL | Cmd | OPAL | | Cmd Data | Cmd Data | OPAL |
+ * | Cmd | Request | OCC | Reserved | Length | Length | Cmd |
+ * | Flags | ID | Cmd | | (MSB) | (LSB) | Data... |
+ * ---------------------------------------------------------------------
+ * | ….OPAL Command Data up to max of Cmd Data Length 4090 bytes |
+ * | |
+ * ---------------------------------------------------------------------
+ *
+ * OPAL Command Flag
+ *
+ * -----------------------------------------------------------------
+ * | Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
+ * | (msb) | | | | | | | (lsb) |
+ * -----------------------------------------------------------------
+ * |Cmd | | | | | | | |
+ * |Ready | | | | | | | |
+ * -----------------------------------------------------------------
+ *
+ * struct opal_command_buffer - Defines the layout of OPAL command buffer
+ * @flag: Provides general status of the command
+ * @request_id: Token to identify request
+ * @cmd: Command sent
+ * @data_size: Command data length
+ * @data: Command specific data
+ * @spare: Unused byte
+ */
+ struct opal_command_buffer {
+ u8 flag;
+ u8 request_id;
+ u8 cmd;
+ u8 spare;
+ __be16 data_size;
+ u8 data[MAX_OPAL_CMD_DATA_LENGTH];
+ } __packed;
+
+ /**
+ * OPAL-OCC Response Buffer
+ *
+ * ---------------------------------------------------------------------
+ * | OCC | Cmd | OPAL | Response | Rsp Data | Rsp Data | OPAL |
+ * | Rsp | Request | OCC | Status | Length | Length | Rsp |
+ * | Flags | ID | Cmd | | (MSB) | (LSB) | Data... |
+ * ---------------------------------------------------------------------
+ * | ….OPAL Response Data up to max of Rsp Data Length 8698 bytes |
+ * | |
+ * ---------------------------------------------------------------------
+ *
+ * OCC Response Flag
+ *
+ * -----------------------------------------------------------------
+ * | Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
+ * | (msb) | | | | | | | (lsb) |
+ * -----------------------------------------------------------------
+ * | | | | | | |OCC in | Rsp |
+ * | | | | | | |progress|Ready |
+ * -----------------------------------------------------------------
+ *
+ * struct occ_response_buffer - Defines the layout of OCC response buffer
+ * @flag: Provides general status of the response
+ * @request_id: Token to identify request
+ * @cmd: Command requested
+ * @status: Indicates success/failure status of
+ * the command
+ * @data_size: Response data length
+ * @data: Response specific data
+ */
+ struct occ_response_buffer {
+ u8 flag;
+ u8 request_id;
+ u8 cmd;
+ u8 status;
+ __be16 data_size;
+ u8 data[MAX_OCC_RSP_DATA_LENGTH];
+ } __packed;
+
+ /**
+ * OCC-OPAL Shared Memory Interface Dynamic Data Vx90
+ *
+ * struct occ_dynamic_data - Contains runtime attributes
+ * @occ_state: Current state of OCC
+ * @major_version: Major version number
+ * @minor_version: Minor version number (backwards compatible)
+ * Version 1 indicates GPU presence populated
+ * @gpus_present: Bitmask of GPUs present (on systems where GPU
+ * presence is detected through APSS)
+ * @cpu_throttle: Reason for limiting the max pstate
+ * @mem_throttle: Reason for throttling memory
+ * @quick_pwr_drop: Indicates if QPD is asserted
+ * @pwr_shifting_ratio: Indicates the current percentage of power to
+ * take away from the CPU vs GPU when shifting
+ * power to maintain a power cap. Value of 100
+ * means take all power from CPU.
+ * @pwr_cap_type: Indicates type of power cap in effect
+ * @hard_min_pwr_cap: Hard minimum system power cap in Watts.
+ * Guaranteed unless hardware failure
+ * @max_pwr_cap: Maximum allowed system power cap in Watts
+ * @cur_pwr_cap: Current system power cap
+ * @soft_min_pwr_cap: Soft powercap minimum. OCC may or may not be
+ * able to maintain this
+ * @spare/reserved: Unused data
+ * @cmd: Opal Command Buffer
+ * @rsp: OCC Response Buffer
+ */
+ struct occ_dynamic_data {
+ u8 occ_state;
+ u8 major_version;
+ u8 minor_version;
+ u8 gpus_present;
+ union __packed {
+ struct __packed { /* Version 0x90 */
+ u8 spare1;
+ } v9;
+ struct __packed { /* Version 0xA0 */
+ u8 wof_enabled;
+ } v10;
+ };
+ u8 cpu_throttle;
+ u8 mem_throttle;
+ u8 quick_pwr_drop;
+ u8 pwr_shifting_ratio;
+ u8 pwr_cap_type;
+ __be16 hard_min_pwr_cap;
+ __be16 max_pwr_cap;
+ __be16 cur_pwr_cap;
+ __be16 soft_min_pwr_cap;
+ u8 pad[110];
+ struct opal_command_buffer cmd;
+ struct occ_response_buffer rsp;
+ } __packed;
+
+ enum occ_response_status {
+ OCC_RSP_SUCCESS = 0x00,
+ OCC_RSP_INVALID_COMMAND = 0x11,
+ OCC_RSP_INVALID_CMD_DATA_LENGTH = 0x12,
+ OCC_RSP_INVALID_DATA = 0x13,
+ OCC_RSP_INTERNAL_ERROR = 0x15,
+ };
+
+ #define OCC_ROLE_SLAVE 0x00
+ #define OCC_ROLE_MASTER 0x01
+
+ #define OCC_FLAG_RSP_READY 0x01
+ #define OCC_FLAG_CMD_IN_PROGRESS 0x02
+ #define OPAL_FLAG_CMD_READY 0x80
+
+ #define PCAP_MAX_POWER_W 100
+ #define PCAP_SOFT_MIN_POWER_W 20
+ #define PCAP_HARD_MIN_POWER_W 10
+
+ static bool occ_write_static_data(PnvOCC *occ,
+ struct occ_pstate_table *static_data,
+ Error **errp)
+ {
+ PnvOCCClass *poc = PNV_OCC_GET_CLASS(occ);
+ PnvHomer *homer = occ->homer;
+ hwaddr static_addr = homer->base + poc->opal_shared_memory_offset;
+ MemTxResult ret;
+
+ ret = address_space_write(&address_space_memory, static_addr,
+ MEMTXATTRS_UNSPECIFIED, static_data,
+ sizeof(*static_data));
+ if (ret != MEMTX_OK) {
+ error_setg(errp, "OCC: cannot write OCC-OPAL static data");
+ return false;
+ }
+
+ return true;
+ }
+
+ static bool occ_read_dynamic_data(PnvOCC *occ,
+ struct occ_dynamic_data *dynamic_data,
+ Error **errp)
+ {
+ PnvOCCClass *poc = PNV_OCC_GET_CLASS(occ);
+ PnvHomer *homer = occ->homer;
+ hwaddr static_addr = homer->base + poc->opal_shared_memory_offset;
+ hwaddr dynamic_addr = static_addr + OPAL_DYNAMIC_DATA_OFFSET;
+ MemTxResult ret;
+
+ ret = address_space_read(&address_space_memory, dynamic_addr,
+ MEMTXATTRS_UNSPECIFIED, dynamic_data,
+ sizeof(*dynamic_data));
+ if (ret != MEMTX_OK) {
+ error_setg(errp, "OCC: cannot read OCC-OPAL dynamic data");
+ return false;
+ }
+
+ return true;
+ }
+
+ static bool occ_write_dynamic_data(PnvOCC *occ,
+ struct occ_dynamic_data *dynamic_data,
+ Error **errp)
+ {
+ PnvOCCClass *poc = PNV_OCC_GET_CLASS(occ);
+ PnvHomer *homer = occ->homer;
+ hwaddr static_addr = homer->base + poc->opal_shared_memory_offset;
+ hwaddr dynamic_addr = static_addr + OPAL_DYNAMIC_DATA_OFFSET;
+ MemTxResult ret;
+
+ ret = address_space_write(&address_space_memory, dynamic_addr,
+ MEMTXATTRS_UNSPECIFIED, dynamic_data,
+ sizeof(*dynamic_data));
+ if (ret != MEMTX_OK) {
+ error_setg(errp, "OCC: cannot write OCC-OPAL dynamic data");
+ return false;
+ }
+
+ return true;
+ }
+
+ static bool occ_opal_send_response(PnvOCC *occ,
+ struct occ_dynamic_data *dynamic_data,
+ enum occ_response_status status,
+ uint8_t *data, uint16_t datalen)
+ {
+ struct opal_command_buffer *cmd = &dynamic_data->cmd;
+ struct occ_response_buffer *rsp = &dynamic_data->rsp;
+
+ rsp->request_id = cmd->request_id;
+ rsp->cmd = cmd->cmd;
+ rsp->status = status;
+ rsp->data_size = cpu_to_be16(datalen);
+ if (datalen) {
+ memcpy(rsp->data, data, datalen);
+ }
+ if (!occ_write_dynamic_data(occ, dynamic_data, NULL)) {
+ return false;
+ }
+ /* Would be a memory barrier here */
+ rsp->flag = OCC_FLAG_RSP_READY;
+ cmd->flag = 0;
+ if (!occ_write_dynamic_data(occ, dynamic_data, NULL)) {
+ return false;
+ }
+
+ pnv_occ_raise_msg_irq(occ);
+
+ return true;
+ }
+
+ /* Returns error status */
+ static bool occ_opal_process_command(PnvOCC *occ,
+ struct occ_dynamic_data *dynamic_data)
+ {
+ struct opal_command_buffer *cmd = &dynamic_data->cmd;
+ struct occ_response_buffer *rsp = &dynamic_data->rsp;
+
+ if (rsp->flag == 0) {
+ /* Spend one "tick" in the in-progress state */
+ rsp->flag = OCC_FLAG_CMD_IN_PROGRESS;
+ return occ_write_dynamic_data(occ, dynamic_data, NULL);
+ } else if (rsp->flag != OCC_FLAG_CMD_IN_PROGRESS) {
+ return occ_opal_send_response(occ, dynamic_data,
+ OCC_RSP_INTERNAL_ERROR,
+ NULL, 0);
+ }
+
+ switch (cmd->cmd) {
+ case 0xD1: { /* SET_POWER_CAP */
+ uint16_t data;
+ if (be16_to_cpu(cmd->data_size) != 2) {
+ return occ_opal_send_response(occ, dynamic_data,
+ OCC_RSP_INVALID_CMD_DATA_LENGTH,
+ (uint8_t *)&dynamic_data->cur_pwr_cap,
+ 2);
+ }
+ data = be16_to_cpu(*(uint16_t *)cmd->data);
+ if (data == 0) { /* clear power cap */
+ dynamic_data->pwr_cap_type = 0x00; /* none */
+ data = PCAP_MAX_POWER_W;
+ } else {
+ dynamic_data->pwr_cap_type = 0x02; /* user set in-band */
+ if (data < PCAP_HARD_MIN_POWER_W) {
+ data = PCAP_HARD_MIN_POWER_W;
+ } else if (data > PCAP_MAX_POWER_W) {
+ data = PCAP_MAX_POWER_W;
+ }
+ }
+ dynamic_data->cur_pwr_cap = cpu_to_be16(data);
+ return occ_opal_send_response(occ, dynamic_data,
+ OCC_RSP_SUCCESS,
+ (uint8_t *)&dynamic_data->cur_pwr_cap, 2);
+ }
+
+ default:
+ return occ_opal_send_response(occ, dynamic_data,
+ OCC_RSP_INVALID_COMMAND,
+ NULL, 0);
+ }
+ g_assert_not_reached();
+ }
+
+ static bool occ_model_tick(PnvOCC *occ)
+ {
+ struct occ_dynamic_data dynamic_data;
+
+ if (!occ_read_dynamic_data(occ, &dynamic_data, NULL)) {
+ /* Can't move OCC state field to safe because we can't map it! */
+ qemu_log("OCC: failed to read HOMER data, shutting down OCC\n");
+ return false;
+ }
+ if (dynamic_data.cmd.flag == OPAL_FLAG_CMD_READY) {
+ if (!occ_opal_process_command(occ, &dynamic_data)) {
+ qemu_log("OCC: failed to write HOMER data, shutting down OCC\n");
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ static bool occ_init_homer_memory(PnvOCC *occ, Error **errp)
+ {
+ PnvOCCClass *poc = PNV_OCC_GET_CLASS(occ);
+ PnvHomer *homer = occ->homer;
+ PnvChip *chip = homer->chip;
+ struct occ_pstate_table static_data;
+ struct occ_dynamic_data dynamic_data;
+ int i;
+
+ memset(&static_data, 0, sizeof(static_data));
+ static_data.valid = 1;
+ static_data.version = poc->opal_shared_memory_version;
+ switch (poc->opal_shared_memory_version) {
+ case 0x02:
+ static_data.v2.throttle = 0;
+ static_data.v2.pstate_min = -2;
+ static_data.v2.pstate_nom = -1;
+ static_data.v2.pstate_turbo = -1;
+ static_data.v2.pstate_ultra_turbo = 0;
+ static_data.v2.pstates[0].id = 0;
+ static_data.v2.pstates[1].freq_khz = cpu_to_be32(4000000);
+ static_data.v2.pstates[1].id = -1;
+ static_data.v2.pstates[1].freq_khz = cpu_to_be32(3000000);
+ static_data.v2.pstates[2].id = -2;
+ static_data.v2.pstates[2].freq_khz = cpu_to_be32(2000000);
+ for (i = 0; i < chip->nr_cores; i++) {
+ static_data.v2.core_max[i] = 1;
+ }
+ break;
+ case 0x90:
+ if (chip->chip_id == 0) {
+ static_data.v9.occ_role = OCC_ROLE_MASTER;
+ } else {
+ static_data.v9.occ_role = OCC_ROLE_SLAVE;
+ }
+ static_data.v9.pstate_min = 2;
+ static_data.v9.pstate_nom = 1;
+ static_data.v9.pstate_turbo = 1;
+ static_data.v9.pstate_ultra_turbo = 0;
+ static_data.v9.pstates[0].id = 0;
+ static_data.v9.pstates[0].freq_khz = cpu_to_be32(4000000);
+ static_data.v9.pstates[1].id = 1;
+ static_data.v9.pstates[1].freq_khz = cpu_to_be32(3000000);
+ static_data.v9.pstates[2].id = 2;
+ static_data.v9.pstates[2].freq_khz = cpu_to_be32(2000000);
+ for (i = 0; i < chip->nr_cores; i++) {
+ static_data.v9.core_max[i] = 1;
+ }
+ break;
+ case 0xA0:
+ if (chip->chip_id == 0) {
+ static_data.v10.occ_role = OCC_ROLE_MASTER;
+ } else {
+ static_data.v10.occ_role = OCC_ROLE_SLAVE;
+ }
+ static_data.v10.pstate_min = 4;
+ static_data.v10.pstate_fixed_freq = 3;
+ static_data.v10.pstate_base = 2;
+ static_data.v10.pstate_ultra_turbo = 0;
+ static_data.v10.pstate_fmax = 1;
+ static_data.v10.minor = 0x01;
+ static_data.v10.pstates[0].valid = 1;
+ static_data.v10.pstates[0].id = 0;
+ static_data.v10.pstates[0].freq_khz = cpu_to_be32(4200000);
+ static_data.v10.pstates[1].valid = 1;
+ static_data.v10.pstates[1].id = 1;
+ static_data.v10.pstates[1].freq_khz = cpu_to_be32(4000000);
+ static_data.v10.pstates[2].valid = 1;
+ static_data.v10.pstates[2].id = 2;
+ static_data.v10.pstates[2].freq_khz = cpu_to_be32(3800000);
+ static_data.v10.pstates[3].valid = 1;
+ static_data.v10.pstates[3].id = 3;
+ static_data.v10.pstates[3].freq_khz = cpu_to_be32(3000000);
+ static_data.v10.pstates[4].valid = 1;
+ static_data.v10.pstates[4].id = 4;
+ static_data.v10.pstates[4].freq_khz = cpu_to_be32(2000000);
+ for (i = 0; i < chip->nr_cores; i++) {
+ static_data.v10.core_max[i] = 1;
+ }
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ if (!occ_write_static_data(occ, &static_data, errp)) {
+ return false;
+ }
+
+ memset(&dynamic_data, 0, sizeof(dynamic_data));
+ dynamic_data.occ_state = 0x3; /* active */
+ dynamic_data.major_version = 0x0;
+ dynamic_data.hard_min_pwr_cap = cpu_to_be16(PCAP_HARD_MIN_POWER_W);
+ dynamic_data.max_pwr_cap = cpu_to_be16(PCAP_MAX_POWER_W);
+ dynamic_data.cur_pwr_cap = cpu_to_be16(PCAP_MAX_POWER_W);
+ dynamic_data.soft_min_pwr_cap = cpu_to_be16(PCAP_SOFT_MIN_POWER_W);
+ switch (poc->opal_shared_memory_version) {
+ case 0xA0:
+ dynamic_data.minor_version = 0x1;
+ dynamic_data.v10.wof_enabled = 0x1;
+ break;
+ case 0x90:
+ dynamic_data.minor_version = 0x1;
+ break;
+ case 0x02:
+ dynamic_data.minor_version = 0x0;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ if (!occ_write_dynamic_data(occ, &dynamic_data, errp)) {
+ return false;
+ }
+
+ return true;
+ }