aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2017-11-24 17:32:27 -0500
committerDan Williams <dan.j.williams@intel.com>2017-12-04 13:19:31 -0500
commited07c4338dd5ceadb5ffed0a5be03488ac54f5d2 (patch)
tree636c810caed24b852f53624c80096f300c195163
parentcdd77d3e193031cc67426cd671d8aa370f7dfee4 (diff)
tools/testing/nvdimm: smart alarm/threshold control
Allow the smart_threshold values to be changed via the 'set smart threshold command' and trigger notifications when the thresholds are met. Signed-off-by: Dan Williams <dan.j.williams@intel.com>
-rw-r--r--tools/testing/nvdimm/test/nfit.c157
-rw-r--r--tools/testing/nvdimm/test/nfit_test.h9
2 files changed, 122 insertions, 44 deletions
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index 640c02b08a50..2b57254342aa 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -168,6 +168,8 @@ struct nfit_test {
168 spinlock_t lock; 168 spinlock_t lock;
169 } ars_state; 169 } ars_state;
170 struct device *dimm_dev[NUM_DCR]; 170 struct device *dimm_dev[NUM_DCR];
171 struct nd_intel_smart *smart;
172 struct nd_intel_smart_threshold *smart_threshold;
171 struct badrange badrange; 173 struct badrange badrange;
172 struct work_struct work; 174 struct work_struct work;
173}; 175};
@@ -440,50 +442,66 @@ static int nfit_test_cmd_translate_spa(struct nvdimm_bus *bus,
440 return 0; 442 return 0;
441} 443}
442 444
443static int nfit_test_cmd_smart(struct nd_intel_smart *smart, unsigned int buf_len) 445static int nfit_test_cmd_smart(struct nd_intel_smart *smart, unsigned int buf_len,
446 struct nd_intel_smart *smart_data)
444{ 447{
445 static const struct nd_intel_smart smart_data = {
446 .flags = ND_INTEL_SMART_HEALTH_VALID
447 | ND_INTEL_SMART_SPARES_VALID
448 | ND_INTEL_SMART_ALARM_VALID
449 | ND_INTEL_SMART_USED_VALID
450 | ND_INTEL_SMART_SHUTDOWN_VALID
451 | ND_INTEL_SMART_MTEMP_VALID,
452 .health = ND_INTEL_SMART_NON_CRITICAL_HEALTH,
453 .media_temperature = 23 * 16,
454 .ctrl_temperature = 30 * 16,
455 .pmic_temperature = 40 * 16,
456 .spares = 75,
457 .alarm_flags = ND_INTEL_SMART_SPARE_TRIP
458 | ND_INTEL_SMART_TEMP_TRIP,
459 .ait_status = 1,
460 .life_used = 5,
461 .shutdown_state = 0,
462 .vendor_size = 0,
463 .shutdown_count = 100,
464 };
465
466 if (buf_len < sizeof(*smart)) 448 if (buf_len < sizeof(*smart))
467 return -EINVAL; 449 return -EINVAL;
468 memcpy(smart, &smart_data, sizeof(smart_data)); 450 memcpy(smart, smart_data, sizeof(*smart));
469 return 0; 451 return 0;
470} 452}
471 453
472static int nfit_test_cmd_smart_threshold( 454static int nfit_test_cmd_smart_threshold(
473 struct nd_intel_smart_threshold *smart_t, 455 struct nd_intel_smart_threshold *out,
474 unsigned int buf_len) 456 unsigned int buf_len,
457 struct nd_intel_smart_threshold *smart_t)
475{ 458{
476 static const struct nd_intel_smart_threshold smart_t_data = {
477 .alarm_control = ND_INTEL_SMART_SPARE_TRIP
478 | ND_INTEL_SMART_TEMP_TRIP,
479 .media_temperature = 40 * 16,
480 .ctrl_temperature = 30 * 16,
481 .spares = 5,
482 };
483
484 if (buf_len < sizeof(*smart_t)) 459 if (buf_len < sizeof(*smart_t))
485 return -EINVAL; 460 return -EINVAL;
486 memcpy(smart_t, &smart_t_data, sizeof(smart_t_data)); 461 memcpy(out, smart_t, sizeof(*smart_t));
462 return 0;
463}
464
465static void smart_notify(struct device *bus_dev,
466 struct device *dimm_dev, struct nd_intel_smart *smart,
467 struct nd_intel_smart_threshold *thresh)
468{
469 dev_dbg(dimm_dev, "%s: alarm: %#x spares: %d (%d) mtemp: %d (%d) ctemp: %d (%d)\n",
470 __func__, thresh->alarm_control, thresh->spares,
471 smart->spares, thresh->media_temperature,
472 smart->media_temperature, thresh->ctrl_temperature,
473 smart->ctrl_temperature);
474 if (((thresh->alarm_control & ND_INTEL_SMART_SPARE_TRIP)
475 && smart->spares
476 <= thresh->spares)
477 || ((thresh->alarm_control & ND_INTEL_SMART_TEMP_TRIP)
478 && smart->media_temperature
479 >= thresh->media_temperature)
480 || ((thresh->alarm_control & ND_INTEL_SMART_CTEMP_TRIP)
481 && smart->ctrl_temperature
482 >= thresh->ctrl_temperature)) {
483 device_lock(bus_dev);
484 __acpi_nvdimm_notify(dimm_dev, 0x81);
485 device_unlock(bus_dev);
486 }
487}
488
489static int nfit_test_cmd_smart_set_threshold(
490 struct nd_intel_smart_set_threshold *in,
491 unsigned int buf_len,
492 struct nd_intel_smart_threshold *thresh,
493 struct nd_intel_smart *smart,
494 struct device *bus_dev, struct device *dimm_dev)
495{
496 unsigned int size;
497
498 size = sizeof(*in) - 4;
499 if (buf_len < size)
500 return -EINVAL;
501 memcpy(thresh->data, in, size);
502 in->status = 0;
503 smart_notify(bus_dev, dimm_dev, smart, thresh);
504
487 return 0; 505 return 0;
488} 506}
489 507
@@ -608,7 +626,7 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
608 || !test_bit(func, &nfit_mem->dsm_mask)) 626 || !test_bit(func, &nfit_mem->dsm_mask))
609 return -ENOTTY; 627 return -ENOTTY;
610 628
611 /* lookup label space for the given dimm */ 629 /* lookup per-dimm data */
612 for (i = 0; i < ARRAY_SIZE(handle); i++) 630 for (i = 0; i < ARRAY_SIZE(handle); i++)
613 if (__to_nfit_memdev(nfit_mem)->device_handle == 631 if (__to_nfit_memdev(nfit_mem)->device_handle ==
614 handle[i]) 632 handle[i])
@@ -631,14 +649,19 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
631 rc = nfit_test_cmd_set_config_data(buf, buf_len, 649 rc = nfit_test_cmd_set_config_data(buf, buf_len,
632 t->label[i - t->dcr_idx]); 650 t->label[i - t->dcr_idx]);
633 break; 651 break;
634 case ND_CMD_SMART: 652 case ND_INTEL_SMART:
635 rc = nfit_test_cmd_smart(buf, buf_len); 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]);
636 break; 659 break;
637 case ND_CMD_SMART_THRESHOLD: 660 case ND_INTEL_SMART_SET_THRESHOLD:
638 rc = nfit_test_cmd_smart_threshold(buf, buf_len); 661 rc = nfit_test_cmd_smart_set_threshold(buf, buf_len,
639 device_lock(&t->pdev.dev); 662 &t->smart_threshold[i - t->dcr_idx],
640 __acpi_nvdimm_notify(t->dimm_dev[i], 0x81); 663 &t->smart[i - t->dcr_idx],
641 device_unlock(&t->pdev.dev); 664 &t->pdev.dev, t->dimm_dev[i]);
642 break; 665 break;
643 default: 666 default:
644 return -ENOTTY; 667 return -ENOTTY;
@@ -883,6 +906,44 @@ static const struct attribute_group *nfit_test_dimm_attribute_groups[] = {
883 NULL, 906 NULL,
884}; 907};
885 908
909static void smart_init(struct nfit_test *t)
910{
911 int i;
912 const struct nd_intel_smart_threshold smart_t_data = {
913 .alarm_control = ND_INTEL_SMART_SPARE_TRIP
914 | ND_INTEL_SMART_TEMP_TRIP,
915 .media_temperature = 40 * 16,
916 .ctrl_temperature = 30 * 16,
917 .spares = 5,
918 };
919 const struct nd_intel_smart smart_data = {
920 .flags = ND_INTEL_SMART_HEALTH_VALID
921 | ND_INTEL_SMART_SPARES_VALID
922 | ND_INTEL_SMART_ALARM_VALID
923 | ND_INTEL_SMART_USED_VALID
924 | ND_INTEL_SMART_SHUTDOWN_VALID
925 | ND_INTEL_SMART_MTEMP_VALID,
926 .health = ND_INTEL_SMART_NON_CRITICAL_HEALTH,
927 .media_temperature = 23 * 16,
928 .ctrl_temperature = 30 * 16,
929 .pmic_temperature = 40 * 16,
930 .spares = 75,
931 .alarm_flags = ND_INTEL_SMART_SPARE_TRIP
932 | ND_INTEL_SMART_TEMP_TRIP,
933 .ait_status = 1,
934 .life_used = 5,
935 .shutdown_state = 0,
936 .vendor_size = 0,
937 .shutdown_count = 100,
938 };
939
940 for (i = 0; i < t->num_dcr; i++) {
941 memcpy(&t->smart[i], &smart_data, sizeof(smart_data));
942 memcpy(&t->smart_threshold[i], &smart_t_data,
943 sizeof(smart_t_data));
944 }
945}
946
886static int nfit_test0_alloc(struct nfit_test *t) 947static int nfit_test0_alloc(struct nfit_test *t)
887{ 948{
888 size_t nfit_size = sizeof(struct acpi_nfit_system_address) * NUM_SPA 949 size_t nfit_size = sizeof(struct acpi_nfit_system_address) * NUM_SPA
@@ -950,6 +1011,7 @@ static int nfit_test0_alloc(struct nfit_test *t)
950 return -ENOMEM; 1011 return -ENOMEM;
951 } 1012 }
952 1013
1014 smart_init(t);
953 return ars_state_init(&t->pdev.dev, &t->ars_state); 1015 return ars_state_init(&t->pdev.dev, &t->ars_state);
954} 1016}
955 1017
@@ -980,6 +1042,7 @@ static int nfit_test1_alloc(struct nfit_test *t)
980 if (!t->spa_set[1]) 1042 if (!t->spa_set[1])
981 return -ENOMEM; 1043 return -ENOMEM;
982 1044
1045 smart_init(t);
983 return ars_state_init(&t->pdev.dev, &t->ars_state); 1046 return ars_state_init(&t->pdev.dev, &t->ars_state);
984} 1047}
985 1048
@@ -1653,13 +1716,14 @@ static void nfit_test0_setup(struct nfit_test *t)
1653 set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_cmd_force_en); 1716 set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_cmd_force_en);
1654 set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en); 1717 set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en);
1655 set_bit(ND_CMD_SET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en); 1718 set_bit(ND_CMD_SET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en);
1656 set_bit(ND_CMD_SMART, &acpi_desc->dimm_cmd_force_en); 1719 set_bit(ND_INTEL_SMART, &acpi_desc->dimm_cmd_force_en);
1720 set_bit(ND_INTEL_SMART_THRESHOLD, &acpi_desc->dimm_cmd_force_en);
1721 set_bit(ND_INTEL_SMART_SET_THRESHOLD, &acpi_desc->dimm_cmd_force_en);
1657 set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_cmd_force_en); 1722 set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_cmd_force_en);
1658 set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en); 1723 set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en);
1659 set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en); 1724 set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en);
1660 set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en); 1725 set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en);
1661 set_bit(ND_CMD_CALL, &acpi_desc->bus_cmd_force_en); 1726 set_bit(ND_CMD_CALL, &acpi_desc->bus_cmd_force_en);
1662 set_bit(ND_CMD_SMART_THRESHOLD, &acpi_desc->dimm_cmd_force_en);
1663 set_bit(NFIT_CMD_TRANSLATE_SPA, &acpi_desc->bus_nfit_cmd_force_en); 1727 set_bit(NFIT_CMD_TRANSLATE_SPA, &acpi_desc->bus_nfit_cmd_force_en);
1664 set_bit(NFIT_CMD_ARS_INJECT_SET, &acpi_desc->bus_nfit_cmd_force_en); 1728 set_bit(NFIT_CMD_ARS_INJECT_SET, &acpi_desc->bus_nfit_cmd_force_en);
1665 set_bit(NFIT_CMD_ARS_INJECT_CLEAR, &acpi_desc->bus_nfit_cmd_force_en); 1729 set_bit(NFIT_CMD_ARS_INJECT_CLEAR, &acpi_desc->bus_nfit_cmd_force_en);
@@ -2065,6 +2129,11 @@ static int nfit_test_probe(struct platform_device *pdev)
2065 sizeof(struct nfit_test_dcr *), GFP_KERNEL); 2129 sizeof(struct nfit_test_dcr *), GFP_KERNEL);
2066 nfit_test->dcr_dma = devm_kcalloc(dev, num, 2130 nfit_test->dcr_dma = devm_kcalloc(dev, num,
2067 sizeof(dma_addr_t), GFP_KERNEL); 2131 sizeof(dma_addr_t), GFP_KERNEL);
2132 nfit_test->smart = devm_kcalloc(dev, num,
2133 sizeof(struct nd_intel_smart), GFP_KERNEL);
2134 nfit_test->smart_threshold = devm_kcalloc(dev, num,
2135 sizeof(struct nd_intel_smart_threshold),
2136 GFP_KERNEL);
2068 if (nfit_test->dimm && nfit_test->dimm_dma && nfit_test->label 2137 if (nfit_test->dimm && nfit_test->dimm_dma && nfit_test->label
2069 && nfit_test->label_dma && nfit_test->dcr 2138 && nfit_test->label_dma && nfit_test->dcr
2070 && nfit_test->dcr_dma && nfit_test->flush 2139 && nfit_test->dcr_dma && nfit_test->flush
diff --git a/tools/testing/nvdimm/test/nfit_test.h b/tools/testing/nvdimm/test/nfit_test.h
index b85fba2856c7..ba230f6f7676 100644
--- a/tools/testing/nvdimm/test/nfit_test.h
+++ b/tools/testing/nvdimm/test/nfit_test.h
@@ -86,6 +86,7 @@ struct nd_cmd_ars_err_inj_stat {
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 90
90#define ND_INTEL_SMART_HEALTH_VALID (1 << 0) 91#define ND_INTEL_SMART_HEALTH_VALID (1 << 0)
91#define ND_INTEL_SMART_SPARES_VALID (1 << 1) 92#define ND_INTEL_SMART_SPARES_VALID (1 << 1)
@@ -143,6 +144,14 @@ struct nd_intel_smart_threshold {
143 }; 144 };
144} __packed; 145} __packed;
145 146
147struct nd_intel_smart_set_threshold {
148 __u16 alarm_control;
149 __u8 spares;
150 __u16 media_temperature;
151 __u16 ctrl_temperature;
152 __u32 status;
153} __packed;
154
146union acpi_object; 155union acpi_object;
147typedef void *acpi_handle; 156typedef void *acpi_handle;
148 157