diff options
| -rw-r--r-- | tools/testing/nvdimm/test/nfit.c | 322 | ||||
| -rw-r--r-- | tools/testing/nvdimm/test/nfit_test.h | 66 |
2 files changed, 360 insertions, 28 deletions
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c index 2b57254342aa..a043fea4d58d 100644 --- a/tools/testing/nvdimm/test/nfit.c +++ b/tools/testing/nvdimm/test/nfit.c | |||
| @@ -137,6 +137,14 @@ static u32 handle[] = { | |||
| 137 | 137 | ||
| 138 | static unsigned long dimm_fail_cmd_flags[NUM_DCR]; | 138 | static unsigned long dimm_fail_cmd_flags[NUM_DCR]; |
| 139 | 139 | ||
| 140 | struct nfit_test_fw { | ||
| 141 | enum intel_fw_update_state state; | ||
| 142 | u32 context; | ||
| 143 | u64 version; | ||
| 144 | u32 size_received; | ||
| 145 | u64 end_time; | ||
| 146 | }; | ||
| 147 | |||
| 140 | struct nfit_test { | 148 | struct nfit_test { |
| 141 | struct acpi_nfit_desc acpi_desc; | 149 | struct acpi_nfit_desc acpi_desc; |
| 142 | struct platform_device pdev; | 150 | struct platform_device pdev; |
| @@ -172,6 +180,7 @@ struct nfit_test { | |||
| 172 | struct nd_intel_smart_threshold *smart_threshold; | 180 | struct nd_intel_smart_threshold *smart_threshold; |
| 173 | struct badrange badrange; | 181 | struct badrange badrange; |
| 174 | struct work_struct work; | 182 | struct work_struct work; |
| 183 | struct nfit_test_fw *fw; | ||
| 175 | }; | 184 | }; |
| 176 | 185 | ||
| 177 | static struct workqueue_struct *nfit_wq; | 186 | static struct workqueue_struct *nfit_wq; |
| @@ -183,6 +192,226 @@ static struct nfit_test *to_nfit_test(struct device *dev) | |||
| 183 | return container_of(pdev, struct nfit_test, pdev); | 192 | return container_of(pdev, struct nfit_test, pdev); |
| 184 | } | 193 | } |
| 185 | 194 | ||
| 195 | static int nd_intel_test_get_fw_info(struct nfit_test *t, | ||
| 196 | struct nd_intel_fw_info *nd_cmd, unsigned int buf_len, | ||
| 197 | int idx) | ||
| 198 | { | ||
| 199 | struct device *dev = &t->pdev.dev; | ||
| 200 | struct nfit_test_fw *fw = &t->fw[idx]; | ||
| 201 | |||
| 202 | dev_dbg(dev, "%s(nfit_test: %p nd_cmd: %p, buf_len: %u, idx: %d\n", | ||
| 203 | __func__, t, nd_cmd, buf_len, idx); | ||
| 204 | |||
| 205 | if (buf_len < sizeof(*nd_cmd)) | ||
| 206 | return -EINVAL; | ||
| 207 | |||
| 208 | nd_cmd->status = 0; | ||
| 209 | nd_cmd->storage_size = INTEL_FW_STORAGE_SIZE; | ||
| 210 | nd_cmd->max_send_len = INTEL_FW_MAX_SEND_LEN; | ||
| 211 | nd_cmd->query_interval = INTEL_FW_QUERY_INTERVAL; | ||
| 212 | nd_cmd->max_query_time = INTEL_FW_QUERY_MAX_TIME; | ||
| 213 | nd_cmd->update_cap = 0; | ||
| 214 | nd_cmd->fis_version = INTEL_FW_FIS_VERSION; | ||
| 215 | nd_cmd->run_version = 0; | ||
| 216 | nd_cmd->updated_version = fw->version; | ||
| 217 | |||
| 218 | return 0; | ||
| 219 | } | ||
| 220 | |||
| 221 | static int nd_intel_test_start_update(struct nfit_test *t, | ||
| 222 | struct nd_intel_fw_start *nd_cmd, unsigned int buf_len, | ||
| 223 | int idx) | ||
| 224 | { | ||
| 225 | struct device *dev = &t->pdev.dev; | ||
| 226 | struct nfit_test_fw *fw = &t->fw[idx]; | ||
| 227 | |||
| 228 | dev_dbg(dev, "%s(nfit_test: %p nd_cmd: %p buf_len: %u idx: %d)\n", | ||
| 229 | __func__, t, nd_cmd, buf_len, idx); | ||
| 230 | |||
| 231 | if (buf_len < sizeof(*nd_cmd)) | ||
| 232 | return -EINVAL; | ||
| 233 | |||
| 234 | if (fw->state != FW_STATE_NEW) { | ||
| 235 | /* extended status, FW update in progress */ | ||
| 236 | nd_cmd->status = 0x10007; | ||
| 237 | return 0; | ||
| 238 | } | ||
| 239 | |||
| 240 | fw->state = FW_STATE_IN_PROGRESS; | ||
| 241 | fw->context++; | ||
| 242 | fw->size_received = 0; | ||
| 243 | nd_cmd->status = 0; | ||
| 244 | nd_cmd->context = fw->context; | ||
| 245 | |||
| 246 | dev_dbg(dev, "%s: context issued: %#x\n", __func__, nd_cmd->context); | ||
| 247 | |||
| 248 | return 0; | ||
| 249 | } | ||
| 250 | |||
| 251 | static int nd_intel_test_send_data(struct nfit_test *t, | ||
| 252 | struct nd_intel_fw_send_data *nd_cmd, unsigned int buf_len, | ||
| 253 | int idx) | ||
| 254 | { | ||
| 255 | struct device *dev = &t->pdev.dev; | ||
| 256 | struct nfit_test_fw *fw = &t->fw[idx]; | ||
| 257 | u32 *status = (u32 *)&nd_cmd->data[nd_cmd->length]; | ||
| 258 | |||
| 259 | dev_dbg(dev, "%s(nfit_test: %p nd_cmd: %p buf_len: %u idx: %d)\n", | ||
| 260 | __func__, t, nd_cmd, buf_len, idx); | ||
| 261 | |||
| 262 | if (buf_len < sizeof(*nd_cmd)) | ||
| 263 | return -EINVAL; | ||
| 264 | |||
| 265 | |||
| 266 | dev_dbg(dev, "%s: cmd->status: %#x\n", __func__, *status); | ||
| 267 | dev_dbg(dev, "%s: cmd->data[0]: %#x\n", __func__, nd_cmd->data[0]); | ||
| 268 | dev_dbg(dev, "%s: cmd->data[%u]: %#x\n", __func__, nd_cmd->length-1, | ||
| 269 | nd_cmd->data[nd_cmd->length-1]); | ||
| 270 | |||
| 271 | if (fw->state != FW_STATE_IN_PROGRESS) { | ||
| 272 | dev_dbg(dev, "%s: not in IN_PROGRESS state\n", __func__); | ||
| 273 | *status = 0x5; | ||
| 274 | return 0; | ||
| 275 | } | ||
| 276 | |||
| 277 | if (nd_cmd->context != fw->context) { | ||
| 278 | dev_dbg(dev, "%s: incorrect context: in: %#x correct: %#x\n", | ||
| 279 | __func__, nd_cmd->context, fw->context); | ||
| 280 | *status = 0x10007; | ||
| 281 | return 0; | ||
| 282 | } | ||
| 283 | |||
| 284 | /* | ||
| 285 | * check offset + len > size of fw storage | ||
| 286 | * check length is > max send length | ||
| 287 | */ | ||
| 288 | if (nd_cmd->offset + nd_cmd->length > INTEL_FW_STORAGE_SIZE || | ||
| 289 | nd_cmd->length > INTEL_FW_MAX_SEND_LEN) { | ||
| 290 | *status = 0x3; | ||
| 291 | dev_dbg(dev, "%s: buffer boundary violation\n", __func__); | ||
| 292 | return 0; | ||
| 293 | } | ||
| 294 | |||
| 295 | fw->size_received += nd_cmd->length; | ||
| 296 | dev_dbg(dev, "%s: copying %u bytes, %u bytes so far\n", | ||
| 297 | __func__, nd_cmd->length, fw->size_received); | ||
| 298 | *status = 0; | ||
| 299 | return 0; | ||
| 300 | } | ||
| 301 | |||
| 302 | static int nd_intel_test_finish_fw(struct nfit_test *t, | ||
| 303 | struct nd_intel_fw_finish_update *nd_cmd, | ||
| 304 | unsigned int buf_len, int idx) | ||
| 305 | { | ||
| 306 | struct device *dev = &t->pdev.dev; | ||
| 307 | struct nfit_test_fw *fw = &t->fw[idx]; | ||
| 308 | |||
| 309 | dev_dbg(dev, "%s(nfit_test: %p nd_cmd: %p buf_len: %u idx: %d)\n", | ||
| 310 | __func__, t, nd_cmd, buf_len, idx); | ||
| 311 | |||
| 312 | if (fw->state == FW_STATE_UPDATED) { | ||
| 313 | /* update already done, need cold boot */ | ||
| 314 | nd_cmd->status = 0x20007; | ||
| 315 | return 0; | ||
| 316 | } | ||
| 317 | |||
| 318 | dev_dbg(dev, "%s: context: %#x ctrl_flags: %#x\n", | ||
| 319 | __func__, nd_cmd->context, nd_cmd->ctrl_flags); | ||
| 320 | |||
| 321 | switch (nd_cmd->ctrl_flags) { | ||
| 322 | case 0: /* finish */ | ||
| 323 | if (nd_cmd->context != fw->context) { | ||
| 324 | dev_dbg(dev, "%s: incorrect context: in: %#x correct: %#x\n", | ||
| 325 | __func__, nd_cmd->context, | ||
| 326 | fw->context); | ||
| 327 | nd_cmd->status = 0x10007; | ||
| 328 | return 0; | ||
| 329 | } | ||
| 330 | nd_cmd->status = 0; | ||
| 331 | fw->state = FW_STATE_VERIFY; | ||
| 332 | /* set 1 second of time for firmware "update" */ | ||
| 333 | fw->end_time = jiffies + HZ; | ||
| 334 | break; | ||
| 335 | |||
| 336 | case 1: /* abort */ | ||
| 337 | fw->size_received = 0; | ||
| 338 | /* successfully aborted status */ | ||
| 339 | nd_cmd->status = 0x40007; | ||
| 340 | fw->state = FW_STATE_NEW; | ||
| 341 | dev_dbg(dev, "%s: abort successful\n", __func__); | ||
| 342 | break; | ||
| 343 | |||
| 344 | default: /* bad control flag */ | ||
| 345 | dev_warn(dev, "%s: unknown control flag: %#x\n", | ||
| 346 | __func__, nd_cmd->ctrl_flags); | ||
| 347 | return -EINVAL; | ||
| 348 | } | ||
| 349 | |||
| 350 | return 0; | ||
| 351 | } | ||
| 352 | |||
| 353 | static int nd_intel_test_finish_query(struct nfit_test *t, | ||
| 354 | struct nd_intel_fw_finish_query *nd_cmd, | ||
| 355 | unsigned int buf_len, int idx) | ||
| 356 | { | ||
| 357 | struct device *dev = &t->pdev.dev; | ||
| 358 | struct nfit_test_fw *fw = &t->fw[idx]; | ||
| 359 | |||
| 360 | dev_dbg(dev, "%s(nfit_test: %p nd_cmd: %p buf_len: %u idx: %d)\n", | ||
| 361 | __func__, t, nd_cmd, buf_len, idx); | ||
| 362 | |||
| 363 | if (buf_len < sizeof(*nd_cmd)) | ||
| 364 | return -EINVAL; | ||
| 365 | |||
| 366 | if (nd_cmd->context != fw->context) { | ||
| 367 | dev_dbg(dev, "%s: incorrect context: in: %#x correct: %#x\n", | ||
| 368 | __func__, nd_cmd->context, fw->context); | ||
| 369 | nd_cmd->status = 0x10007; | ||
| 370 | return 0; | ||
| 371 | } | ||
| 372 | |||
| 373 | dev_dbg(dev, "%s context: %#x\n", __func__, nd_cmd->context); | ||
| 374 | |||
| 375 | switch (fw->state) { | ||
| 376 | case FW_STATE_NEW: | ||
| 377 | nd_cmd->updated_fw_rev = 0; | ||
| 378 | nd_cmd->status = 0; | ||
| 379 | dev_dbg(dev, "%s: new state\n", __func__); | ||
| 380 | break; | ||
| 381 | |||
| 382 | case FW_STATE_IN_PROGRESS: | ||
| 383 | /* sequencing error */ | ||
| 384 | nd_cmd->status = 0x40007; | ||
| 385 | nd_cmd->updated_fw_rev = 0; | ||
| 386 | dev_dbg(dev, "%s: sequence error\n", __func__); | ||
| 387 | break; | ||
| 388 | |||
| 389 | case FW_STATE_VERIFY: | ||
| 390 | if (time_is_after_jiffies64(fw->end_time)) { | ||
| 391 | nd_cmd->updated_fw_rev = 0; | ||
| 392 | nd_cmd->status = 0x20007; | ||
| 393 | dev_dbg(dev, "%s: still verifying\n", __func__); | ||
| 394 | break; | ||
| 395 | } | ||
| 396 | |||
| 397 | dev_dbg(dev, "%s: transition out verify\n", __func__); | ||
| 398 | fw->state = FW_STATE_UPDATED; | ||
| 399 | /* we are going to fall through if it's "done" */ | ||
| 400 | case FW_STATE_UPDATED: | ||
| 401 | nd_cmd->status = 0; | ||
| 402 | /* bogus test version */ | ||
| 403 | fw->version = nd_cmd->updated_fw_rev = | ||
| 404 | INTEL_FW_FAKE_VERSION; | ||
| 405 | dev_dbg(dev, "%s: updated\n", __func__); | ||
| 406 | break; | ||
| 407 | |||
| 408 | default: /* we should never get here */ | ||
| 409 | return -EINVAL; | ||
| 410 | } | ||
| 411 | |||
| 412 | return 0; | ||
| 413 | } | ||
| 414 | |||
| 186 | static int nfit_test_cmd_get_config_size(struct nd_cmd_get_config_size *nd_cmd, | 415 | static int nfit_test_cmd_get_config_size(struct nd_cmd_get_config_size *nd_cmd, |
| 187 | unsigned int buf_len) | 416 | unsigned int buf_len) |
| 188 | { | 417 | { |
| @@ -592,6 +821,23 @@ static int nfit_test_cmd_ars_inject_status(struct nfit_test *t, | |||
| 592 | return 0; | 821 | return 0; |
| 593 | } | 822 | } |
| 594 | 823 | ||
| 824 | static int get_dimm(struct nfit_mem *nfit_mem, unsigned int func) | ||
| 825 | { | ||
| 826 | int i; | ||
| 827 | |||
| 828 | /* lookup per-dimm data */ | ||
| 829 | for (i = 0; i < ARRAY_SIZE(handle); i++) | ||
| 830 | if (__to_nfit_memdev(nfit_mem)->device_handle == handle[i]) | ||
| 831 | break; | ||
| 832 | if (i >= ARRAY_SIZE(handle)) | ||
| 833 | return -ENXIO; | ||
| 834 | |||
| 835 | if ((1 << func) & dimm_fail_cmd_flags[i]) | ||
| 836 | return -EIO; | ||
| 837 | |||
| 838 | return i; | ||
| 839 | } | ||
| 840 | |||
| 595 | static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, | 841 | static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, |
| 596 | struct nvdimm *nvdimm, unsigned int cmd, void *buf, | 842 | struct nvdimm *nvdimm, unsigned int cmd, void *buf, |
| 597 | unsigned int buf_len, int *cmd_rc) | 843 | unsigned int buf_len, int *cmd_rc) |
| @@ -620,22 +866,54 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, | |||
| 620 | func = call_pkg->nd_command; | 866 | func = call_pkg->nd_command; |
| 621 | if (call_pkg->nd_family != nfit_mem->family) | 867 | if (call_pkg->nd_family != nfit_mem->family) |
| 622 | return -ENOTTY; | 868 | return -ENOTTY; |
| 869 | |||
| 870 | i = get_dimm(nfit_mem, func); | ||
| 871 | if (i < 0) | ||
| 872 | return i; | ||
| 873 | |||
| 874 | switch (func) { | ||
| 875 | case ND_INTEL_FW_GET_INFO: | ||
| 876 | return nd_intel_test_get_fw_info(t, buf, | ||
| 877 | buf_len, i - t->dcr_idx); | ||
| 878 | case ND_INTEL_FW_START_UPDATE: | ||
| 879 | return nd_intel_test_start_update(t, buf, | ||
| 880 | buf_len, i - t->dcr_idx); | ||
| 881 | case ND_INTEL_FW_SEND_DATA: | ||
| 882 | return nd_intel_test_send_data(t, buf, | ||
| 883 | buf_len, i - t->dcr_idx); | ||
| 884 | case ND_INTEL_FW_FINISH_UPDATE: | ||
| 885 | return nd_intel_test_finish_fw(t, buf, | ||
| 886 | buf_len, i - t->dcr_idx); | ||
| 887 | case ND_INTEL_FW_FINISH_QUERY: | ||
| 888 | return nd_intel_test_finish_query(t, buf, | ||
| 889 | buf_len, i - t->dcr_idx); | ||
| 890 | case ND_INTEL_SMART: | ||
| 891 | return nfit_test_cmd_smart(buf, buf_len, | ||
| 892 | &t->smart[i - t->dcr_idx]); | ||
| 893 | case ND_INTEL_SMART_THRESHOLD: | ||
| 894 | return nfit_test_cmd_smart_threshold(buf, | ||
| 895 | buf_len, | ||
| 896 | &t->smart_threshold[i - | ||
| 897 | t->dcr_idx]); | ||
| 898 | case ND_INTEL_SMART_SET_THRESHOLD: | ||
| 899 | return nfit_test_cmd_smart_set_threshold(buf, | ||
| 900 | buf_len, | ||
| 901 | &t->smart_threshold[i - | ||
| 902 | t->dcr_idx], | ||
| 903 | &t->smart[i - t->dcr_idx], | ||
| 904 | &t->pdev.dev, t->dimm_dev[i]); | ||
| 905 | default: | ||
| 906 | return -ENOTTY; | ||
| 907 | } | ||
| 623 | } | 908 | } |
| 624 | 909 | ||
| 625 | if (!test_bit(cmd, &cmd_mask) | 910 | if (!test_bit(cmd, &cmd_mask) |
| 626 | || !test_bit(func, &nfit_mem->dsm_mask)) | 911 | || !test_bit(func, &nfit_mem->dsm_mask)) |
| 627 | return -ENOTTY; | 912 | return -ENOTTY; |
| 628 | 913 | ||
| 629 | /* lookup per-dimm data */ | 914 | i = get_dimm(nfit_mem, func); |
| 630 | for (i = 0; i < ARRAY_SIZE(handle); i++) | 915 | if (i < 0) |
| 631 | if (__to_nfit_memdev(nfit_mem)->device_handle == | 916 | return i; |
| 632 | handle[i]) | ||
| 633 | break; | ||
| 634 | if (i >= ARRAY_SIZE(handle)) | ||
| 635 | return -ENXIO; | ||
| 636 | |||
| 637 | if ((1 << func) & dimm_fail_cmd_flags[i]) | ||
| 638 | return -EIO; | ||
| 639 | 917 | ||
| 640 | switch (func) { | 918 | switch (func) { |
| 641 | case ND_CMD_GET_CONFIG_SIZE: | 919 | case ND_CMD_GET_CONFIG_SIZE: |
| @@ -649,20 +927,6 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, | |||
| 649 | rc = nfit_test_cmd_set_config_data(buf, buf_len, | 927 | rc = nfit_test_cmd_set_config_data(buf, buf_len, |
| 650 | t->label[i - t->dcr_idx]); | 928 | t->label[i - t->dcr_idx]); |
| 651 | break; | 929 | break; |
| 652 | case ND_INTEL_SMART: | ||
| 653 | rc = nfit_test_cmd_smart(buf, buf_len, | ||
| 654 | &t->smart[i - t->dcr_idx]); | ||
| 655 | break; | ||
| 656 | case ND_INTEL_SMART_THRESHOLD: | ||
| 657 | rc = nfit_test_cmd_smart_threshold(buf, buf_len, | ||
| 658 | &t->smart_threshold[i - t->dcr_idx]); | ||
| 659 | break; | ||
| 660 | case ND_INTEL_SMART_SET_THRESHOLD: | ||
| 661 | rc = nfit_test_cmd_smart_set_threshold(buf, buf_len, | ||
| 662 | &t->smart_threshold[i - t->dcr_idx], | ||
| 663 | &t->smart[i - t->dcr_idx], | ||
| 664 | &t->pdev.dev, t->dimm_dev[i]); | ||
| 665 | break; | ||
| 666 | default: | 930 | default: |
| 667 | return -ENOTTY; | 931 | return -ENOTTY; |
| 668 | } | 932 | } |
| @@ -1728,6 +1992,11 @@ static void nfit_test0_setup(struct nfit_test *t) | |||
| 1728 | set_bit(NFIT_CMD_ARS_INJECT_SET, &acpi_desc->bus_nfit_cmd_force_en); | 1992 | set_bit(NFIT_CMD_ARS_INJECT_SET, &acpi_desc->bus_nfit_cmd_force_en); |
| 1729 | set_bit(NFIT_CMD_ARS_INJECT_CLEAR, &acpi_desc->bus_nfit_cmd_force_en); | 1993 | set_bit(NFIT_CMD_ARS_INJECT_CLEAR, &acpi_desc->bus_nfit_cmd_force_en); |
| 1730 | set_bit(NFIT_CMD_ARS_INJECT_GET, &acpi_desc->bus_nfit_cmd_force_en); | 1994 | set_bit(NFIT_CMD_ARS_INJECT_GET, &acpi_desc->bus_nfit_cmd_force_en); |
| 1995 | set_bit(ND_INTEL_FW_GET_INFO, &acpi_desc->dimm_cmd_force_en); | ||
| 1996 | set_bit(ND_INTEL_FW_START_UPDATE, &acpi_desc->dimm_cmd_force_en); | ||
| 1997 | set_bit(ND_INTEL_FW_SEND_DATA, &acpi_desc->dimm_cmd_force_en); | ||
| 1998 | set_bit(ND_INTEL_FW_FINISH_UPDATE, &acpi_desc->dimm_cmd_force_en); | ||
| 1999 | set_bit(ND_INTEL_FW_FINISH_QUERY, &acpi_desc->dimm_cmd_force_en); | ||
| 1731 | } | 2000 | } |
| 1732 | 2001 | ||
| 1733 | static void nfit_test1_setup(struct nfit_test *t) | 2002 | static void nfit_test1_setup(struct nfit_test *t) |
| @@ -2134,10 +2403,13 @@ static int nfit_test_probe(struct platform_device *pdev) | |||
| 2134 | nfit_test->smart_threshold = devm_kcalloc(dev, num, | 2403 | nfit_test->smart_threshold = devm_kcalloc(dev, num, |
| 2135 | sizeof(struct nd_intel_smart_threshold), | 2404 | sizeof(struct nd_intel_smart_threshold), |
| 2136 | GFP_KERNEL); | 2405 | GFP_KERNEL); |
| 2406 | nfit_test->fw = devm_kcalloc(dev, num, | ||
| 2407 | sizeof(struct nfit_test_fw), GFP_KERNEL); | ||
| 2137 | if (nfit_test->dimm && nfit_test->dimm_dma && nfit_test->label | 2408 | if (nfit_test->dimm && nfit_test->dimm_dma && nfit_test->label |
| 2138 | && nfit_test->label_dma && nfit_test->dcr | 2409 | && nfit_test->label_dma && nfit_test->dcr |
| 2139 | && nfit_test->dcr_dma && nfit_test->flush | 2410 | && nfit_test->dcr_dma && nfit_test->flush |
| 2140 | && nfit_test->flush_dma) | 2411 | && nfit_test->flush_dma |
| 2412 | && nfit_test->fw) | ||
| 2141 | /* pass */; | 2413 | /* pass */; |
| 2142 | else | 2414 | else |
| 2143 | return -ENOMEM; | 2415 | return -ENOMEM; |
diff --git a/tools/testing/nvdimm/test/nfit_test.h b/tools/testing/nvdimm/test/nfit_test.h index ba230f6f7676..be8fa8ec0615 100644 --- a/tools/testing/nvdimm/test/nfit_test.h +++ b/tools/testing/nvdimm/test/nfit_test.h | |||
| @@ -84,9 +84,14 @@ struct nd_cmd_ars_err_inj_stat { | |||
| 84 | } __packed record[0]; | 84 | } __packed record[0]; |
| 85 | } __packed; | 85 | } __packed; |
| 86 | 86 | ||
| 87 | #define ND_INTEL_SMART 1 | 87 | #define ND_INTEL_SMART 1 |
| 88 | #define ND_INTEL_SMART_THRESHOLD 2 | 88 | #define ND_INTEL_SMART_THRESHOLD 2 |
| 89 | #define ND_INTEL_SMART_SET_THRESHOLD 17 | 89 | #define ND_INTEL_FW_GET_INFO 12 |
| 90 | #define ND_INTEL_FW_START_UPDATE 13 | ||
| 91 | #define ND_INTEL_FW_SEND_DATA 14 | ||
| 92 | #define ND_INTEL_FW_FINISH_UPDATE 15 | ||
| 93 | #define ND_INTEL_FW_FINISH_QUERY 16 | ||
| 94 | #define ND_INTEL_SMART_SET_THRESHOLD 17 | ||
| 90 | 95 | ||
| 91 | #define ND_INTEL_SMART_HEALTH_VALID (1 << 0) | 96 | #define ND_INTEL_SMART_HEALTH_VALID (1 << 0) |
| 92 | #define ND_INTEL_SMART_SPARES_VALID (1 << 1) | 97 | #define ND_INTEL_SMART_SPARES_VALID (1 << 1) |
| @@ -152,6 +157,61 @@ struct nd_intel_smart_set_threshold { | |||
| 152 | __u32 status; | 157 | __u32 status; |
| 153 | } __packed; | 158 | } __packed; |
| 154 | 159 | ||
| 160 | #define INTEL_FW_STORAGE_SIZE 0x100000 | ||
| 161 | #define INTEL_FW_MAX_SEND_LEN 0xFFEC | ||
| 162 | #define INTEL_FW_QUERY_INTERVAL 250000 | ||
| 163 | #define INTEL_FW_QUERY_MAX_TIME 3000000 | ||
| 164 | #define INTEL_FW_FIS_VERSION 0x0105 | ||
| 165 | #define INTEL_FW_FAKE_VERSION 0xffffffffabcd | ||
| 166 | |||
| 167 | enum intel_fw_update_state { | ||
| 168 | FW_STATE_NEW = 0, | ||
| 169 | FW_STATE_IN_PROGRESS, | ||
| 170 | FW_STATE_VERIFY, | ||
| 171 | FW_STATE_UPDATED, | ||
| 172 | }; | ||
| 173 | |||
| 174 | struct nd_intel_fw_info { | ||
| 175 | __u32 status; | ||
| 176 | __u32 storage_size; | ||
| 177 | __u32 max_send_len; | ||
| 178 | __u32 query_interval; | ||
| 179 | __u32 max_query_time; | ||
| 180 | __u8 update_cap; | ||
| 181 | __u8 reserved[3]; | ||
| 182 | __u32 fis_version; | ||
| 183 | __u64 run_version; | ||
| 184 | __u64 updated_version; | ||
| 185 | } __packed; | ||
| 186 | |||
| 187 | struct nd_intel_fw_start { | ||
| 188 | __u32 status; | ||
| 189 | __u32 context; | ||
| 190 | } __packed; | ||
| 191 | |||
| 192 | /* this one has the output first because the variable input data size */ | ||
| 193 | struct nd_intel_fw_send_data { | ||
| 194 | __u32 context; | ||
| 195 | __u32 offset; | ||
| 196 | __u32 length; | ||
| 197 | __u8 data[0]; | ||
| 198 | /* this field is not declared due ot variable data from input */ | ||
| 199 | /* __u32 status; */ | ||
| 200 | } __packed; | ||
| 201 | |||
| 202 | struct nd_intel_fw_finish_update { | ||
| 203 | __u8 ctrl_flags; | ||
| 204 | __u8 reserved[3]; | ||
| 205 | __u32 context; | ||
| 206 | __u32 status; | ||
| 207 | } __packed; | ||
| 208 | |||
| 209 | struct nd_intel_fw_finish_query { | ||
| 210 | __u32 context; | ||
| 211 | __u32 status; | ||
| 212 | __u64 updated_fw_rev; | ||
| 213 | } __packed; | ||
| 214 | |||
| 155 | union acpi_object; | 215 | union acpi_object; |
| 156 | typedef void *acpi_handle; | 216 | typedef void *acpi_handle; |
| 157 | 217 | ||
