|
@@ -85,55 +85,47 @@ int nvdimm_init_nsarea(struct nvdimm_drvdata *ndd)
|
|
|
return cmd_rc;
|
|
|
}
|
|
|
|
|
|
-int nvdimm_init_config_data(struct nvdimm_drvdata *ndd)
|
|
|
+int nvdimm_get_config_data(struct nvdimm_drvdata *ndd, void *buf,
|
|
|
+ size_t offset, size_t len)
|
|
|
{
|
|
|
struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(ndd->dev);
|
|
|
+ struct nvdimm_bus_descriptor *nd_desc = nvdimm_bus->nd_desc;
|
|
|
int rc = validate_dimm(ndd), cmd_rc = 0;
|
|
|
struct nd_cmd_get_config_data_hdr *cmd;
|
|
|
- struct nvdimm_bus_descriptor *nd_desc;
|
|
|
- u32 max_cmd_size, config_size;
|
|
|
- size_t offset;
|
|
|
+ size_t max_cmd_size, buf_offset;
|
|
|
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
|
|
|
- if (ndd->data)
|
|
|
- return 0;
|
|
|
-
|
|
|
- if (ndd->nsarea.status || ndd->nsarea.max_xfer == 0
|
|
|
- || ndd->nsarea.config_size < ND_LABEL_MIN_SIZE) {
|
|
|
- dev_dbg(ndd->dev, "failed to init config data area: (%d:%d)\n",
|
|
|
- ndd->nsarea.max_xfer, ndd->nsarea.config_size);
|
|
|
+ if (offset + len > ndd->nsarea.config_size)
|
|
|
return -ENXIO;
|
|
|
- }
|
|
|
|
|
|
- ndd->data = kvmalloc(ndd->nsarea.config_size, GFP_KERNEL);
|
|
|
- if (!ndd->data)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- max_cmd_size = min_t(u32, ndd->nsarea.config_size, ndd->nsarea.max_xfer);
|
|
|
+ max_cmd_size = min_t(u32, len, ndd->nsarea.max_xfer);
|
|
|
cmd = kvzalloc(max_cmd_size + sizeof(*cmd), GFP_KERNEL);
|
|
|
if (!cmd)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- nd_desc = nvdimm_bus->nd_desc;
|
|
|
- for (config_size = ndd->nsarea.config_size, offset = 0;
|
|
|
- config_size; config_size -= cmd->in_length,
|
|
|
- offset += cmd->in_length) {
|
|
|
- cmd->in_length = min(config_size, max_cmd_size);
|
|
|
- cmd->in_offset = offset;
|
|
|
+ for (buf_offset = 0; len;
|
|
|
+ len -= cmd->in_length, buf_offset += cmd->in_length) {
|
|
|
+ size_t cmd_size;
|
|
|
+
|
|
|
+ cmd->in_offset = offset + buf_offset;
|
|
|
+ cmd->in_length = min(max_cmd_size, len);
|
|
|
+
|
|
|
+ cmd_size = sizeof(*cmd) + cmd->in_length;
|
|
|
+
|
|
|
rc = nd_desc->ndctl(nd_desc, to_nvdimm(ndd->dev),
|
|
|
- ND_CMD_GET_CONFIG_DATA, cmd,
|
|
|
- cmd->in_length + sizeof(*cmd), &cmd_rc);
|
|
|
+ ND_CMD_GET_CONFIG_DATA, cmd, cmd_size, &cmd_rc);
|
|
|
if (rc < 0)
|
|
|
break;
|
|
|
if (cmd_rc < 0) {
|
|
|
rc = cmd_rc;
|
|
|
break;
|
|
|
}
|
|
|
- memcpy(ndd->data + offset, cmd->out_buf, cmd->in_length);
|
|
|
+
|
|
|
+ /* out_buf should be valid, copy it into our output buffer */
|
|
|
+ memcpy(buf + buf_offset, cmd->out_buf, cmd->in_length);
|
|
|
}
|
|
|
- dev_dbg(ndd->dev, "len: %zu rc: %d\n", offset, rc);
|
|
|
kvfree(cmd);
|
|
|
|
|
|
return rc;
|
|
@@ -151,9 +143,6 @@ int nvdimm_set_config_data(struct nvdimm_drvdata *ndd, size_t offset,
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
|
|
|
- if (!ndd->data)
|
|
|
- return -ENXIO;
|
|
|
-
|
|
|
if (offset + len > ndd->nsarea.config_size)
|
|
|
return -ENXIO;
|
|
|
|