[16/16] nvdimm: support NFIT_CMD_SET_CONFIG_DATA
diff mbox

Message ID 1435762232-15543-17-git-send-email-guangrong.xiao@linux.intel.com
State New
Headers show

Commit Message

Xiao Guangrong July 1, 2015, 2:50 p.m. UTC
Function 6 is used to set Namespace Label Data

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
---
 hw/mem/pc-nvdimm.c | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

Patch
diff mbox

diff --git a/hw/mem/pc-nvdimm.c b/hw/mem/pc-nvdimm.c
index 0498de3..0d2d9fb 100644
--- a/hw/mem/pc-nvdimm.c
+++ b/hw/mem/pc-nvdimm.c
@@ -450,12 +450,17 @@  struct cmd_out_get_config_data {
     uint8_t out_buf[0];
 } QEMU_PACKED;
 
+struct cmd_out_set_config_data {
+    uint32_t status;
+} QEMU_PACKED;
+
 struct dsm_out {
     union {
         uint32_t status;
         struct cmd_out_implemented cmd_implemented;
         struct cmd_out_get_config_size cmd_config_size;
         struct cmd_out_get_config_data cmd_config_get;
+        struct cmd_out_set_config_data cmd_config_set;
         uint8_t data[PAGE_SIZE];
     };
 };
@@ -555,6 +560,35 @@  exit:
     return status;
 }
 
+static uint32_t dsm_cmd_config_set(struct dsm_buffer *in, struct dsm_out *out)
+{
+    GSList *list = get_nvdimm_built_list();
+    PCNVDIMMDevice *nvdimm = get_nvdimm_device_by_handle(list, in->handle);
+    struct cmd_in_set_config_data *cmd_in = &in->cmd_config_set;
+    uint32_t status = NFIT_STATUS_NON_EXISTING_MEM_DEV;
+
+    if (!nvdimm) {
+        goto exit;
+    }
+
+    nvdebug("Write Config: offset %#x length %#x.\n", cmd_in->offset,
+            cmd_in->length);
+    if (nvdimm->config_data_size < cmd_in->length + cmd_in->offset) {
+        nvdebug("position %#x is beyond config data (len = %#lx).\n",
+                cmd_in->length + cmd_in->offset, nvdimm->config_data_size);
+        status = NFIT_STATUS_INVALID_PARAS;
+        goto exit;
+    }
+
+    status = NFIT_STATUS_SUCCESS;
+    memcpy(nvdimm->config_data_addr + cmd_in->offset, cmd_in->in_buf,
+           cmd_in->length);
+
+exit:
+    g_slist_free(list);
+    return status;
+}
+
 static void dsm_write_nvdimm(struct dsm_buffer *in, struct dsm_out *out)
 {
     uint32_t function = in->arg2;
@@ -570,6 +604,9 @@  static void dsm_write_nvdimm(struct dsm_buffer *in, struct dsm_out *out)
     case NFIT_CMD_GET_CONFIG_DATA:
         status = dsm_cmd_config_get(in, out);
         break;
+    case NFIT_CMD_SET_CONFIG_DATA:
+        status = dsm_cmd_config_set(in, out);
+        break;
     default:
         status = NFIT_STATUS_NOT_SUPPORTED;
     };