aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorVishal Verma <vishal.l.verma@intel.com>2015-07-09 15:25:36 -0400
committerDan Williams <dan.j.williams@intel.com>2015-07-27 22:53:19 -0400
commit39c686b862cdb2049b90e095b6c6c727b2a7ab60 (patch)
tree4858a38b3c4441bad3e9599ff8cf0de01be13817 /tools
parentec92777f2ba93c00387b8fe53780c25adc57c744 (diff)
libnvdimm: Add DSM support for Address Range Scrub commands
Add support for the three ARS DSM commands: - Query ARS Capabilities - Queries the firmware to check if a given range supports scrub, and if so, which type (persistent vs. volatile) - Start ARS - Starts a scrub for a given range/type - Query ARS Status - Checks status of a previously started scrub, and provides the error logs if any. The commands are described by the example DSM spec at: http://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf Also add these commands to the nfit_test test framework, and return canned data. Signed-off-by: Vishal Verma <vishal.l.verma@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/testing/nvdimm/test/nfit.c199
1 files changed, 140 insertions, 59 deletions
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index d0bdae40ccc9..28dba918524e 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -147,75 +147,153 @@ static struct nfit_test *to_nfit_test(struct device *dev)
147 return container_of(pdev, struct nfit_test, pdev); 147 return container_of(pdev, struct nfit_test, pdev);
148} 148}
149 149
150static int nfit_test_cmd_get_config_size(struct nd_cmd_get_config_size *nd_cmd,
151 unsigned int buf_len)
152{
153 if (buf_len < sizeof(*nd_cmd))
154 return -EINVAL;
155
156 nd_cmd->status = 0;
157 nd_cmd->config_size = LABEL_SIZE;
158 nd_cmd->max_xfer = SZ_4K;
159
160 return 0;
161}
162
163static int nfit_test_cmd_get_config_data(struct nd_cmd_get_config_data_hdr
164 *nd_cmd, unsigned int buf_len, void *label)
165{
166 unsigned int len, offset = nd_cmd->in_offset;
167 int rc;
168
169 if (buf_len < sizeof(*nd_cmd))
170 return -EINVAL;
171 if (offset >= LABEL_SIZE)
172 return -EINVAL;
173 if (nd_cmd->in_length + sizeof(*nd_cmd) > buf_len)
174 return -EINVAL;
175
176 nd_cmd->status = 0;
177 len = min(nd_cmd->in_length, LABEL_SIZE - offset);
178 memcpy(nd_cmd->out_buf, label + offset, len);
179 rc = buf_len - sizeof(*nd_cmd) - len;
180
181 return rc;
182}
183
184static int nfit_test_cmd_set_config_data(struct nd_cmd_set_config_hdr *nd_cmd,
185 unsigned int buf_len, void *label)
186{
187 unsigned int len, offset = nd_cmd->in_offset;
188 u32 *status;
189 int rc;
190
191 if (buf_len < sizeof(*nd_cmd))
192 return -EINVAL;
193 if (offset >= LABEL_SIZE)
194 return -EINVAL;
195 if (nd_cmd->in_length + sizeof(*nd_cmd) + 4 > buf_len)
196 return -EINVAL;
197
198 status = (void *)nd_cmd + nd_cmd->in_length + sizeof(*nd_cmd);
199 *status = 0;
200 len = min(nd_cmd->in_length, LABEL_SIZE - offset);
201 memcpy(label + offset, nd_cmd->in_buf, len);
202 rc = buf_len - sizeof(*nd_cmd) - (len + 4);
203
204 return rc;
205}
206
207static int nfit_test_cmd_ars_cap(struct nd_cmd_ars_cap *nd_cmd,
208 unsigned int buf_len)
209{
210 if (buf_len < sizeof(*nd_cmd))
211 return -EINVAL;
212
213 nd_cmd->max_ars_out = 256;
214 nd_cmd->status = (ND_ARS_PERSISTENT | ND_ARS_VOLATILE) << 16;
215
216 return 0;
217}
218
219static int nfit_test_cmd_ars_start(struct nd_cmd_ars_start *nd_cmd,
220 unsigned int buf_len)
221{
222 if (buf_len < sizeof(*nd_cmd))
223 return -EINVAL;
224
225 nd_cmd->status = 0;
226
227 return 0;
228}
229
230static int nfit_test_cmd_ars_status(struct nd_cmd_ars_status *nd_cmd,
231 unsigned int buf_len)
232{
233 if (buf_len < sizeof(*nd_cmd))
234 return -EINVAL;
235
236 nd_cmd->out_length = 256;
237 nd_cmd->num_records = 0;
238 nd_cmd->status = 0;
239
240 return 0;
241}
242
150static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, 243static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
151 struct nvdimm *nvdimm, unsigned int cmd, void *buf, 244 struct nvdimm *nvdimm, unsigned int cmd, void *buf,
152 unsigned int buf_len) 245 unsigned int buf_len)
153{ 246{
154 struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc); 247 struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
155 struct nfit_test *t = container_of(acpi_desc, typeof(*t), acpi_desc); 248 struct nfit_test *t = container_of(acpi_desc, typeof(*t), acpi_desc);
156 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm); 249 int i, rc = 0;
157 int i, rc; 250
251 if (nvdimm) {
252 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
158 253
159 if (!nfit_mem || !test_bit(cmd, &nfit_mem->dsm_mask)) 254 if (!nfit_mem || !test_bit(cmd, &nfit_mem->dsm_mask))
160 return -ENOTTY; 255 return -ENOTTY;
161 256
162 /* lookup label space for the given dimm */ 257 /* lookup label space for the given dimm */
163 for (i = 0; i < ARRAY_SIZE(handle); i++) 258 for (i = 0; i < ARRAY_SIZE(handle); i++)
164 if (__to_nfit_memdev(nfit_mem)->device_handle == handle[i]) 259 if (__to_nfit_memdev(nfit_mem)->device_handle ==
260 handle[i])
261 break;
262 if (i >= ARRAY_SIZE(handle))
263 return -ENXIO;
264
265 switch (cmd) {
266 case ND_CMD_GET_CONFIG_SIZE:
267 rc = nfit_test_cmd_get_config_size(buf, buf_len);
165 break; 268 break;
166 if (i >= ARRAY_SIZE(handle)) 269 case ND_CMD_GET_CONFIG_DATA:
167 return -ENXIO; 270 rc = nfit_test_cmd_get_config_data(buf, buf_len,
271 t->label[i]);
272 break;
273 case ND_CMD_SET_CONFIG_DATA:
274 rc = nfit_test_cmd_set_config_data(buf, buf_len,
275 t->label[i]);
276 break;
277 default:
278 return -ENOTTY;
279 }
280 } else {
281 if (!nd_desc || !test_bit(cmd, &nd_desc->dsm_mask))
282 return -ENOTTY;
168 283
169 switch (cmd) { 284 switch (cmd) {
170 case ND_CMD_GET_CONFIG_SIZE: { 285 case ND_CMD_ARS_CAP:
171 struct nd_cmd_get_config_size *nd_cmd = buf; 286 rc = nfit_test_cmd_ars_cap(buf, buf_len);
172 287 break;
173 if (buf_len < sizeof(*nd_cmd)) 288 case ND_CMD_ARS_START:
174 return -EINVAL; 289 rc = nfit_test_cmd_ars_start(buf, buf_len);
175 nd_cmd->status = 0; 290 break;
176 nd_cmd->config_size = LABEL_SIZE; 291 case ND_CMD_ARS_STATUS:
177 nd_cmd->max_xfer = SZ_4K; 292 rc = nfit_test_cmd_ars_status(buf, buf_len);
178 rc = 0; 293 break;
179 break; 294 default:
180 } 295 return -ENOTTY;
181 case ND_CMD_GET_CONFIG_DATA: { 296 }
182 struct nd_cmd_get_config_data_hdr *nd_cmd = buf;
183 unsigned int len, offset = nd_cmd->in_offset;
184
185 if (buf_len < sizeof(*nd_cmd))
186 return -EINVAL;
187 if (offset >= LABEL_SIZE)
188 return -EINVAL;
189 if (nd_cmd->in_length + sizeof(*nd_cmd) > buf_len)
190 return -EINVAL;
191
192 nd_cmd->status = 0;
193 len = min(nd_cmd->in_length, LABEL_SIZE - offset);
194 memcpy(nd_cmd->out_buf, t->label[i] + offset, len);
195 rc = buf_len - sizeof(*nd_cmd) - len;
196 break;
197 }
198 case ND_CMD_SET_CONFIG_DATA: {
199 struct nd_cmd_set_config_hdr *nd_cmd = buf;
200 unsigned int len, offset = nd_cmd->in_offset;
201 u32 *status;
202
203 if (buf_len < sizeof(*nd_cmd))
204 return -EINVAL;
205 if (offset >= LABEL_SIZE)
206 return -EINVAL;
207 if (nd_cmd->in_length + sizeof(*nd_cmd) + 4 > buf_len)
208 return -EINVAL;
209
210 status = buf + nd_cmd->in_length + sizeof(*nd_cmd);
211 *status = 0;
212 len = min(nd_cmd->in_length, LABEL_SIZE - offset);
213 memcpy(t->label[i] + offset, nd_cmd->in_buf, len);
214 rc = buf_len - sizeof(*nd_cmd) - (len + 4);
215 break;
216 }
217 default:
218 return -ENOTTY;
219 } 297 }
220 298
221 return rc; 299 return rc;
@@ -876,6 +954,9 @@ static void nfit_test0_setup(struct nfit_test *t)
876 set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_dsm_force_en); 954 set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_dsm_force_en);
877 set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en); 955 set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en);
878 set_bit(ND_CMD_SET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en); 956 set_bit(ND_CMD_SET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en);
957 set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_dsm_force_en);
958 set_bit(ND_CMD_ARS_START, &acpi_desc->bus_dsm_force_en);
959 set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_dsm_force_en);
879 nd_desc = &acpi_desc->nd_desc; 960 nd_desc = &acpi_desc->nd_desc;
880 nd_desc->ndctl = nfit_test_ctl; 961 nd_desc->ndctl = nfit_test_ctl;
881} 962}