History

Merge branch 'for-4.7/dsm' into libnvdimm-for-next

Dan Williams committed 10 years ago

Commit 1f716d02 parents 2159669 a94e3fb11 files · +283 −58Browse files

Unified · Split

11 files
  1. drivers/acpi/nfit.c +127 −18
  2. drivers/acpi/nfit.h +15 −3
  3. drivers/acpi/utils.c +2 −2
  4. drivers/nvdimm/bus.c +43 −4
  5. drivers/nvdimm/core.c +1 −1
  6. drivers/nvdimm/dimm_devs.c +12 −6
  7. drivers/nvdimm/nd-core.h +1 −1
  8. include/acpi/acpi_bus.h +3 −3
  9. include/linux/libnvdimm.h +4 −3
  10. include/uapi/linux/ndctl.h +42 −0
  11. tools/testing/nvdimm/test/nfit.c +33 −17
drivers/acpi/nfit.c+127−18
@@ -45,6 +45,11 @@ module_param(scrub_overflow_abort, uint, S_IRUGO|S_IWUSR); · 44 unmodified lines
4545 MODULE_PARM_DESC(scrub_overflow_abort,
4646 "Number of times we overflow ARS results before abort");
4747
48+static bool disable_vendor_specific;
49+module_param(disable_vendor_specific, bool, S_IRUGO);
50+MODULE_PARM_DESC(disable_vendor_specific,
51+ "Limit commands to the publicly specified set\n");
52+
4853 static struct workqueue_struct *nfit_wq;
4954
5055 struct nfit_table_prev {
@@ -171,33 +176,46 @@ static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, · 120 unmodified lines
171176 unsigned int buf_len, int *cmd_rc)
172177 {
173178 struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc);
174− const struct nd_cmd_desc *desc = NULL;
175179 union acpi_object in_obj, in_buf, *out_obj;
180+ const struct nd_cmd_desc *desc = NULL;
176181 struct device *dev = acpi_desc->dev;
182+ struct nd_cmd_pkg *call_pkg = NULL;
177183 const char *cmd_name, *dimm_name;
178− unsigned long dsm_mask;
184+ unsigned long cmd_mask, dsm_mask;
179185 acpi_handle handle;
186+ unsigned int func;
180187 const u8 *uuid;
181188 u32 offset;
182189 int rc, i;
183190
191+ func = cmd;
192+ if (cmd == ND_CMD_CALL) {
193+ call_pkg = buf;
194+ func = call_pkg->nd_command;
195+ }
196+
184197 if (nvdimm) {
185198 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
186199 struct acpi_device *adev = nfit_mem->adev;
187200
188201 if (!adev)
189202 return -ENOTTY;
203+ if (call_pkg && nfit_mem->family != call_pkg->nd_family)
204+ return -ENOTTY;
205+
190206 dimm_name = nvdimm_name(nvdimm);
191207 cmd_name = nvdimm_cmd_name(cmd);
208+ cmd_mask = nvdimm_cmd_mask(nvdimm);
192209 dsm_mask = nfit_mem->dsm_mask;
193210 desc = nd_cmd_dimm_desc(cmd);
194− uuid = to_nfit_uuid(NFIT_DEV_DIMM);
211+ uuid = to_nfit_uuid(nfit_mem->family);
195212 handle = adev->handle;
196213 } else {
197214 struct acpi_device *adev = to_acpi_dev(acpi_desc);
198215
199216 cmd_name = nvdimm_bus_cmd_name(cmd);
200− dsm_mask = nd_desc->dsm_mask;
217+ cmd_mask = nd_desc->cmd_mask;
218+ dsm_mask = cmd_mask;
201219 desc = nd_cmd_bus_desc(cmd);
202220 uuid = to_nfit_uuid(NFIT_DEV_BUS);
203221 handle = adev->handle;
@@ -207,7 +225,7 @@ static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, · 3 unmodified lines
207225 if (!desc || (cmd && (desc->out_num + desc->in_num == 0)))
208226 return -ENOTTY;
209227
210− if (!test_bit(cmd, &dsm_mask))
228+ if (!test_bit(cmd, &cmd_mask) || !test_bit(func, &dsm_mask))
211229 return -ENOTTY;
212230
213231 in_obj.type = ACPI_TYPE_PACKAGE;
@@ -222,21 +240,44 @@ static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, · 8 unmodified lines
222240 in_buf.buffer.length += nd_cmd_in_size(nvdimm, cmd, desc,
223241 i, buf);
224242
243+ if (call_pkg) {
244+ /* skip over package wrapper */
245+ in_buf.buffer.pointer = (void *) &call_pkg->nd_payload;
246+ in_buf.buffer.length = call_pkg->nd_size_in;
247+ }
248+
225249 if (IS_ENABLED(CONFIG_ACPI_NFIT_DEBUG)) {
226− dev_dbg(dev, "%s:%s cmd: %s input length: %d\n", __func__,
227− dimm_name, cmd_name, in_buf.buffer.length);
228− print_hex_dump_debug(cmd_name, DUMP_PREFIX_OFFSET, 4,
229− 4, in_buf.buffer.pointer, min_t(u32, 128,
230− in_buf.buffer.length), true);
250+ dev_dbg(dev, "%s:%s cmd: %d: func: %d input length: %d\n",
251+ __func__, dimm_name, cmd, func,
252+ in_buf.buffer.length);
253+ print_hex_dump_debug("nvdimm in ", DUMP_PREFIX_OFFSET, 4, 4,
254+ in_buf.buffer.pointer,
255+ min_t(u32, 256, in_buf.buffer.length), true);
231256 }
232257
233− out_obj = acpi_evaluate_dsm(handle, uuid, 1, cmd, &in_obj);
258+ out_obj = acpi_evaluate_dsm(handle, uuid, 1, func, &in_obj);
234259 if (!out_obj) {
235260 dev_dbg(dev, "%s:%s _DSM failed cmd: %s\n", __func__, dimm_name,
236261 cmd_name);
237262 return -EINVAL;
238263 }
239264
265+ if (call_pkg) {
266+ call_pkg->nd_fw_size = out_obj->buffer.length;
267+ memcpy(call_pkg->nd_payload + call_pkg->nd_size_in,
268+ out_obj->buffer.pointer,
269+ min(call_pkg->nd_fw_size, call_pkg->nd_size_out));
270+
271+ ACPI_FREE(out_obj);
272+ /*
273+ * Need to support FW function w/o known size in advance.
274+ * Caller can determine required size based upon nd_fw_size.
275+ * If we return an error (like elsewhere) then caller wouldn't
276+ * be able to rely upon data returned to make calculation.
277+ */
278+ return 0;
279+ }
280+
240281 if (out_obj->package.type != ACPI_TYPE_BUFFER) {
241282 dev_dbg(dev, "%s:%s unexpected output object type cmd: %s type: %d\n",
242283 __func__, dimm_name, cmd_name, out_obj->type);
@@ -921,6 +962,30 @@ static ssize_t serial_show(struct device *dev, · 678 unmodified lines
921962 }
922963 static DEVICE_ATTR_RO(serial);
923964
965+static ssize_t family_show(struct device *dev,
966+ struct device_attribute *attr, char *buf)
967+{
968+ struct nvdimm *nvdimm = to_nvdimm(dev);
969+ struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
970+
971+ if (nfit_mem->family < 0)
972+ return -ENXIO;
973+ return sprintf(buf, "%d\n", nfit_mem->family);
974+}
975+static DEVICE_ATTR_RO(family);
976+
977+static ssize_t dsm_mask_show(struct device *dev,
978+ struct device_attribute *attr, char *buf)
979+{
980+ struct nvdimm *nvdimm = to_nvdimm(dev);
981+ struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
982+
983+ if (nfit_mem->family < 0)
984+ return -ENXIO;
985+ return sprintf(buf, "%#lx\n", nfit_mem->dsm_mask);
986+}
987+static DEVICE_ATTR_RO(dsm_mask);
988+
924989 static ssize_t flags_show(struct device *dev,
925990 struct device_attribute *attr, char *buf)
926991 {
@@ -946,6 +1011,8 @@ static struct attribute *acpi_nfit_dimm_attributes[] = { · 19 unmodified lines
9461011 &dev_attr_serial.attr,
9471012 &dev_attr_rev_id.attr,
9481013 &dev_attr_flags.attr,
1014+ &dev_attr_family.attr,
1015+ &dev_attr_dsm_mask.attr,
9491016 NULL,
9501017 };
9511018
@@ -992,10 +1059,13 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc, · 40 unmodified lines
9921059 {
9931060 struct acpi_device *adev, *adev_dimm;
9941061 struct device *dev = acpi_desc->dev;
995− const u8 *uuid = to_nfit_uuid(NFIT_DEV_DIMM);
1062+ unsigned long dsm_mask;
1063+ const u8 *uuid;
9961064 int i;
9971065
998− nfit_mem->dsm_mask = acpi_desc->dimm_dsm_force_en;
1066+ /* nfit test assumes 1:1 relationship between commands and dsms */
1067+ nfit_mem->dsm_mask = acpi_desc->dimm_cmd_force_en;
1068+ nfit_mem->family = NVDIMM_FAMILY_INTEL;
9991069 adev = to_acpi_dev(acpi_desc);
10001070 if (!adev)
10011071 return 0;
@@ -1008,7 +1078,35 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc, · 6 unmodified lines
10081078 return force_enable_dimms ? 0 : -ENODEV;
10091079 }
10101080
1011− for (i = ND_CMD_SMART; i <= ND_CMD_VENDOR; i++)
1081+ /*
1082+ * Until standardization materializes we need to consider up to 3
1083+ * different command sets. Note, that checking for function0 (bit0)
1084+ * tells us if any commands are reachable through this uuid.
1085+ */
1086+ for (i = NVDIMM_FAMILY_INTEL; i <= NVDIMM_FAMILY_HPE2; i++)
1087+ if (acpi_check_dsm(adev_dimm->handle, to_nfit_uuid(i), 1, 1))
1088+ break;
1089+
1090+ /* limit the supported commands to those that are publicly documented */
1091+ nfit_mem->family = i;
1092+ if (nfit_mem->family == NVDIMM_FAMILY_INTEL) {
1093+ dsm_mask = 0x3fe;
1094+ if (disable_vendor_specific)
1095+ dsm_mask &= ~(1 << ND_CMD_VENDOR);
1096+ } else if (nfit_mem->family == NVDIMM_FAMILY_HPE1)
1097+ dsm_mask = 0x1c3c76;
1098+ else if (nfit_mem->family == NVDIMM_FAMILY_HPE2) {
1099+ dsm_mask = 0x1fe;
1100+ if (disable_vendor_specific)
1101+ dsm_mask &= ~(1 << 8);
1102+ } else {
1103+ dev_err(dev, "unknown dimm command family\n");
1104+ nfit_mem->family = -1;
1105+ return force_enable_dimms ? 0 : -ENODEV;
1106+ }
1107+
1108+ uuid = to_nfit_uuid(nfit_mem->family);
1109+ for_each_set_bit(i, &dsm_mask, BITS_PER_LONG)
10121110 if (acpi_check_dsm(adev_dimm->handle, uuid, 1, 1ULL << i))
10131111 set_bit(i, &nfit_mem->dsm_mask);
10141112
@@ -1021,8 +1119,8 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc) · 6 unmodified lines
10211119 int dimm_count = 0;
10221120
10231121 list_for_each_entry(nfit_mem, &acpi_desc->dimms, list) {
1122+ unsigned long flags = 0, cmd_mask;
10241123 struct nvdimm *nvdimm;
1025− unsigned long flags = 0;
10261124 u32 device_handle;
10271125 u16 mem_flags;
10281126 int rc;
@@ -1045,9 +1143,18 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc) · 16 unmodified lines
10451143 if (rc)
10461144 continue;
10471145
1146+ /*
1147+ * TODO: provide translation for non-NVDIMM_FAMILY_INTEL
1148+ * devices (i.e. from nd_cmd to acpi_dsm) to standardize the
1149+ * userspace interface.
1150+ */
1151+ cmd_mask = 1UL << ND_CMD_CALL;
1152+ if (nfit_mem->family == NVDIMM_FAMILY_INTEL)
1153+ cmd_mask |= nfit_mem->dsm_mask;
1154+
10481155 nvdimm = nvdimm_create(acpi_desc->nvdimm_bus, nfit_mem,
10491156 acpi_nfit_dimm_attribute_groups,
1050− flags, &nfit_mem->dsm_mask);
1157+ flags, cmd_mask);
10511158 if (!nvdimm)
10521159 return -ENOMEM;
10531160
@@ -1076,14 +1183,14 @@ static void acpi_nfit_init_dsms(struct acpi_nfit_desc *acpi_desc) · 22 unmodified lines
10761183 struct acpi_device *adev;
10771184 int i;
10781185
1079− nd_desc->dsm_mask = acpi_desc->bus_dsm_force_en;
1186+ nd_desc->cmd_mask = acpi_desc->bus_cmd_force_en;
10801187 adev = to_acpi_dev(acpi_desc);
10811188 if (!adev)
10821189 return;
10831190
10841191 for (i = ND_CMD_ARS_CAP; i <= ND_CMD_CLEAR_ERROR; i++)
10851192 if (acpi_check_dsm(adev->handle, uuid, 1, 1ULL << i))
1086− set_bit(i, &nd_desc->dsm_mask);
1193+ set_bit(i, &nd_desc->cmd_mask);
10871194 }
10881195
10891196 static ssize_t range_index_show(struct device *dev,
@@ -2532,6 +2639,8 @@ static __init int nfit_init(void) · 1442 unmodified lines
25322639 acpi_str_to_uuid(UUID_PERSISTENT_VIRTUAL_CD, nfit_uuid[NFIT_SPA_PCD]);
25332640 acpi_str_to_uuid(UUID_NFIT_BUS, nfit_uuid[NFIT_DEV_BUS]);
25342641 acpi_str_to_uuid(UUID_NFIT_DIMM, nfit_uuid[NFIT_DEV_DIMM]);
2642+ acpi_str_to_uuid(UUID_NFIT_DIMM_N_HPE1, nfit_uuid[NFIT_DEV_DIMM_N_HPE1]);
2643+ acpi_str_to_uuid(UUID_NFIT_DIMM_N_HPE2, nfit_uuid[NFIT_DEV_DIMM_N_HPE2]);
25352644
25362645 nfit_wq = create_singlethread_workqueue("nfit");
25372646 if (!nfit_wq)
drivers/acpi/nfit.h+15−3
@@ -21,13 +21,25 @@ · 20 unmodified lines
2121 #include <linux/acpi.h>
2222 #include <acpi/acuuid.h>
2323
24+/* ACPI 6.1 */
2425 #define UUID_NFIT_BUS "2f10e7a4-9e91-11e4-89d3-123b93f75cba"
26+
27+/* http://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf */
2528 #define UUID_NFIT_DIMM "4309ac30-0d11-11e4-9191-0800200c9a66"
29+
30+/* https://github.com/HewlettPackard/hpe-nvm/blob/master/Documentation/ */
31+#define UUID_NFIT_DIMM_N_HPE1 "9002c334-acf3-4c0e-9642-a235f0d53bc6"
32+#define UUID_NFIT_DIMM_N_HPE2 "5008664b-b758-41a0-a03c-27c2f2d04f7e"
33+
2634 #define ACPI_NFIT_MEM_FAILED_MASK (ACPI_NFIT_MEM_SAVE_FAILED \
2735 | ACPI_NFIT_MEM_RESTORE_FAILED | ACPI_NFIT_MEM_FLUSH_FAILED \
2836 | ACPI_NFIT_MEM_NOT_ARMED)
2937
3038 enum nfit_uuids {
39+ /* for simplicity alias the uuid index with the family id */
40+ NFIT_DEV_DIMM = NVDIMM_FAMILY_INTEL,
41+ NFIT_DEV_DIMM_N_HPE1 = NVDIMM_FAMILY_HPE1,
42+ NFIT_DEV_DIMM_N_HPE2 = NVDIMM_FAMILY_HPE2,
3143 NFIT_SPA_VOLATILE,
3244 NFIT_SPA_PM,
3345 NFIT_SPA_DCR,
@@ -37,7 +49,6 @@ enum nfit_uuids { · 3 unmodified lines
3749 NFIT_SPA_PDISK,
3850 NFIT_SPA_PCD,
3951 NFIT_DEV_BUS,
40− NFIT_DEV_DIMM,
4152 NFIT_UUID_MAX,
4253 };
4354
@@ -111,6 +122,7 @@ struct nfit_mem { · 67 unmodified lines
111122 struct acpi_device *adev;
112123 struct acpi_nfit_desc *acpi_desc;
113124 unsigned long dsm_mask;
125+ int family;
114126 };
115127
116128 struct acpi_nfit_desc {
@@ -133,8 +145,8 @@ struct acpi_nfit_desc { · 16 unmodified lines
133145 size_t ars_status_size;
134146 struct work_struct work;
135147 unsigned int cancel:1;
136− unsigned long dimm_dsm_force_en;
137− unsigned long bus_dsm_force_en;
148+ unsigned long dimm_cmd_force_en;
149+ unsigned long bus_cmd_force_en;
138150 int (*blk_do_io)(struct nd_blk_region *ndbr, resource_size_t dpa,
139151 void *iobuf, u64 len, int rw);
140152 };
drivers/acpi/utils.c+2−2
@@ -625,7 +625,7 @@ acpi_status acpi_evaluate_lck(acpi_handle handle, int lock) · 624 unmodified lines
625625 * some old BIOSes do expect a buffer or an integer etc.
626626 */
627627 union acpi_object *
628−acpi_evaluate_dsm(acpi_handle handle, const u8 *uuid, int rev, int func,
628+acpi_evaluate_dsm(acpi_handle handle, const u8 *uuid, u64 rev, u64 func,
629629 union acpi_object *argv4)
630630 {
631631 acpi_status ret;
@@ -674,7 +674,7 @@ EXPORT_SYMBOL(acpi_evaluate_dsm); · 42 unmodified lines
674674 * functions. Currently only support 64 functions at maximum, should be
675675 * enough for now.
676676 */
677−bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs)
677+bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, u64 rev, u64 funcs)
678678 {
679679 int i;
680680 u64 mask = 0;
drivers/nvdimm/bus.c+43−4
@@ -443,6 +443,12 @@ static const struct nd_cmd_desc __nd_cmd_dimm_descs[] = { · 442 unmodified lines
443443 .out_num = 3,
444444 .out_sizes = { 4, 4, UINT_MAX, },
445445 },
446+ [ND_CMD_CALL] = {
447+ .in_num = 2,
448+ .in_sizes = { sizeof(struct nd_cmd_pkg), UINT_MAX, },
449+ .out_num = 1,
450+ .out_sizes = { UINT_MAX, },
451+ },
446452 };
447453
448454 const struct nd_cmd_desc *nd_cmd_dimm_desc(int cmd)
@@ -477,6 +483,12 @@ static const struct nd_cmd_desc __nd_cmd_bus_descs[] = { · 28 unmodified lines
477483 .out_num = 3,
478484 .out_sizes = { 4, 4, 8, },
479485 },
486+ [ND_CMD_CALL] = {
487+ .in_num = 2,
488+ .in_sizes = { sizeof(struct nd_cmd_pkg), UINT_MAX, },
489+ .out_num = 1,
490+ .out_sizes = { UINT_MAX, },
491+ },
480492 };
481493
482494 const struct nd_cmd_desc *nd_cmd_bus_desc(int cmd)
@@ -504,6 +516,10 @@ u32 nd_cmd_in_size(struct nvdimm *nvdimm, int cmd, · 21 unmodified lines
504516 struct nd_cmd_vendor_hdr *hdr = buf;
505517
506518 return hdr->in_length;
519+ } else if (cmd == ND_CMD_CALL) {
520+ struct nd_cmd_pkg *pkg = buf;
521+
522+ return pkg->nd_size_in;
507523 }
508524
509525 return UINT_MAX;
@@ -526,6 +542,12 @@ u32 nd_cmd_out_size(struct nvdimm *nvdimm, int cmd, · 16 unmodified lines
526542 return out_field[1];
527543 else if (!nvdimm && cmd == ND_CMD_ARS_STATUS && idx == 2)
528544 return out_field[1] - 8;
545+ else if (cmd == ND_CMD_CALL) {
546+ struct nd_cmd_pkg *pkg = (struct nd_cmd_pkg *) in_field;
547+
548+ return pkg->nd_size_out;
549+ }
550+
529551
530552 return UINT_MAX;
531553 }
@@ -592,25 +614,31 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm, · 60 unmodified lines
592614 unsigned int cmd = _IOC_NR(ioctl_cmd);
593615 void __user *p = (void __user *) arg;
594616 struct device *dev = &nvdimm_bus->dev;
617+ struct nd_cmd_pkg pkg;
595618 const char *cmd_name, *dimm_name;
596− unsigned long dsm_mask;
619+ unsigned long cmd_mask;
597620 void *buf;
598621 int rc, i;
599622
600623 if (nvdimm) {
601624 desc = nd_cmd_dimm_desc(cmd);
602625 cmd_name = nvdimm_cmd_name(cmd);
603− dsm_mask = nvdimm->dsm_mask ? *(nvdimm->dsm_mask) : 0;
626+ cmd_mask = nvdimm->cmd_mask;
604627 dimm_name = dev_name(&nvdimm->dev);
605628 } else {
606629 desc = nd_cmd_bus_desc(cmd);
607630 cmd_name = nvdimm_bus_cmd_name(cmd);
608− dsm_mask = nd_desc->dsm_mask;
631+ cmd_mask = nd_desc->cmd_mask;
609632 dimm_name = "bus";
610633 }
611634
635+ if (cmd == ND_CMD_CALL) {
636+ if (copy_from_user(&pkg, p, sizeof(pkg)))
637+ return -EFAULT;
638+ }
639+
612640 if (!desc || (desc->out_num + desc->in_num == 0) ||
613− !test_bit(cmd, &dsm_mask))
641+ !test_bit(cmd, &cmd_mask))
614642 return -ENOTTY;
615643
616644 /* fail write commands (when read-only) */
@@ -620,6 +648,7 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm, · 3 unmodified lines
620648 case ND_CMD_SET_CONFIG_DATA:
621649 case ND_CMD_ARS_START:
622650 case ND_CMD_CLEAR_ERROR:
651+ case ND_CMD_CALL:
623652 dev_dbg(&nvdimm_bus->dev, "'%s' command while read-only.\n",
624653 nvdimm ? nvdimm_cmd_name(cmd)
625654 : nvdimm_bus_cmd_name(cmd));
@@ -647,6 +676,16 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm, · 21 unmodified lines
647676 in_len += in_size;
648677 }
649678
679+ if (cmd == ND_CMD_CALL) {
680+ dev_dbg(dev, "%s:%s, idx: %llu, in: %zu, out: %zu, len %zu\n",
681+ __func__, dimm_name, pkg.nd_command,
682+ in_len, out_len, buf_len);
683+
684+ for (i = 0; i < ARRAY_SIZE(pkg.nd_reserved2); i++)
685+ if (pkg.nd_reserved2[i])
686+ return -EINVAL;
687+ }
688+
650689 /* process an output envelope */
651690 for (i = 0; i < desc->out_num; i++) {
652691 u32 out_size = nd_cmd_out_size(nvdimm, cmd, desc, i,
drivers/nvdimm/core.c+1−1
@@ -251,7 +251,7 @@ static ssize_t commands_show(struct device *dev, · 250 unmodified lines
251251 struct nvdimm_bus *nvdimm_bus = to_nvdimm_bus(dev);
252252 struct nvdimm_bus_descriptor *nd_desc = nvdimm_bus->nd_desc;
253253
254− for_each_set_bit(cmd, &nd_desc->dsm_mask, BITS_PER_LONG)
254+ for_each_set_bit(cmd, &nd_desc->cmd_mask, BITS_PER_LONG)
255255 len += sprintf(buf + len, "%s ", nvdimm_bus_cmd_name(cmd));
256256 len += sprintf(buf + len, "\n");
257257 return len;
drivers/nvdimm/dimm_devs.c+12−6
@@ -37,9 +37,9 @@ static int __validate_dimm(struct nvdimm_drvdata *ndd) · 36 unmodified lines
3737
3838 nvdimm = to_nvdimm(ndd->dev);
3939
40− if (!nvdimm->dsm_mask)
40+ if (!nvdimm->cmd_mask)
4141 return -ENXIO;
42− if (!test_bit(ND_CMD_GET_CONFIG_DATA, nvdimm->dsm_mask))
42+ if (!test_bit(ND_CMD_GET_CONFIG_DATA, &nvdimm->cmd_mask))
4343 return -ENXIO;
4444
4545 return 0;
@@ -263,6 +263,12 @@ const char *nvdimm_name(struct nvdimm *nvdimm) · 217 unmodified lines
263263 }
264264 EXPORT_SYMBOL_GPL(nvdimm_name);
265265
266+unsigned long nvdimm_cmd_mask(struct nvdimm *nvdimm)
267+{
268+ return nvdimm->cmd_mask;
269+}
270+EXPORT_SYMBOL_GPL(nvdimm_cmd_mask);
271+
266272 void *nvdimm_provider_data(struct nvdimm *nvdimm)
267273 {
268274 if (nvdimm)
@@ -277,10 +283,10 @@ static ssize_t commands_show(struct device *dev, · 8 unmodified lines
277283 struct nvdimm *nvdimm = to_nvdimm(dev);
278284 int cmd, len = 0;
279285
280− if (!nvdimm->dsm_mask)
286+ if (!nvdimm->cmd_mask)
281287 return sprintf(buf, "\n");
282288
283− for_each_set_bit(cmd, nvdimm->dsm_mask, BITS_PER_LONG)
289+ for_each_set_bit(cmd, &nvdimm->cmd_mask, BITS_PER_LONG)
284290 len += sprintf(buf + len, "%s ", nvdimm_cmd_name(cmd));
285291 len += sprintf(buf + len, "\n");
286292 return len;
@@ -340,7 +346,7 @@ EXPORT_SYMBOL_GPL(nvdimm_attribute_group); · 53 unmodified lines
340346
341347 struct nvdimm *nvdimm_create(struct nvdimm_bus *nvdimm_bus, void *provider_data,
342348 const struct attribute_group **groups, unsigned long flags,
343− unsigned long *dsm_mask)
349+ unsigned long cmd_mask)
344350 {
345351 struct nvdimm *nvdimm = kzalloc(sizeof(*nvdimm), GFP_KERNEL);
346352 struct device *dev;
@@ -355,7 +361,7 @@ struct nvdimm *nvdimm_create(struct nvdimm_bus *nvdimm_bus, void *provider_data, · 8 unmodified lines
355361 }
356362 nvdimm->provider_data = provider_data;
357363 nvdimm->flags = flags;
358− nvdimm->dsm_mask = dsm_mask;
364+ nvdimm->cmd_mask = cmd_mask;
359365 atomic_set(&nvdimm->busy, 0);
360366 dev = &nvdimm->dev;
361367 dev_set_name(dev, "nmem%d", nvdimm->id);
drivers/nvdimm/nd-core.h+1−1
@@ -37,7 +37,7 @@ struct nvdimm_bus { · 36 unmodified lines
3737 struct nvdimm {
3838 unsigned long flags;
3939 void *provider_data;
40− unsigned long *dsm_mask;
40+ unsigned long cmd_mask;
4141 struct device dev;
4242 atomic_t busy;
4343 int id;
include/acpi/acpi_bus.h+3−3
@@ -61,12 +61,12 @@ bool acpi_ata_match(acpi_handle handle); · 60 unmodified lines
6161 bool acpi_bay_match(acpi_handle handle);
6262 bool acpi_dock_match(acpi_handle handle);
6363
64−bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs);
64+bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, u64 rev, u64 funcs);
6565 union acpi_object *acpi_evaluate_dsm(acpi_handle handle, const u8 *uuid,
66− int rev, int func, union acpi_object *argv4);
66+ u64 rev, u64 func, union acpi_object *argv4);
6767
6868 static inline union acpi_object *
69−acpi_evaluate_dsm_typed(acpi_handle handle, const u8 *uuid, int rev, int func,
69+acpi_evaluate_dsm_typed(acpi_handle handle, const u8 *uuid, u64 rev, u64 func,
7070 union acpi_object *argv4, acpi_object_type type)
7171 {
7272 union acpi_object *obj;
include/linux/libnvdimm.h+4−3
@@ -27,7 +27,7 @@ enum { · 26 unmodified lines
2727 /* need to set a limit somewhere, but yes, this is likely overkill */
2828 ND_IOCTL_MAX_BUFLEN = SZ_4M,
2929 ND_CMD_MAX_ELEM = 5,
30− ND_CMD_MAX_ENVELOPE = 16,
30+ ND_CMD_MAX_ENVELOPE = 256,
3131 ND_MAX_MAPPINGS = 32,
3232
3333 /* region flag indicating to direct-map persistent memory by default */
@@ -68,7 +68,7 @@ struct nd_mapping { · 34 unmodified lines
6868
6969 struct nvdimm_bus_descriptor {
7070 const struct attribute_group **attr_groups;
71− unsigned long dsm_mask;
71+ unsigned long cmd_mask;
7272 char *provider_name;
7373 ndctl_fn ndctl;
7474 int (*flush_probe)(struct nvdimm_bus_descriptor *nd_desc);
@@ -130,10 +130,11 @@ struct nd_region *to_nd_region(struct device *dev); · 55 unmodified lines
130130 struct nd_blk_region *to_nd_blk_region(struct device *dev);
131131 struct nvdimm_bus_descriptor *to_nd_desc(struct nvdimm_bus *nvdimm_bus);
132132 const char *nvdimm_name(struct nvdimm *nvdimm);
133+unsigned long nvdimm_cmd_mask(struct nvdimm *nvdimm);
133134 void *nvdimm_provider_data(struct nvdimm *nvdimm);
134135 struct nvdimm *nvdimm_create(struct nvdimm_bus *nvdimm_bus, void *provider_data,
135136 const struct attribute_group **groups, unsigned long flags,
136− unsigned long *dsm_mask);
137+ unsigned long cmd_mask);
137138 const struct nd_cmd_desc *nd_cmd_dimm_desc(int cmd);
138139 const struct nd_cmd_desc *nd_cmd_bus_desc(int cmd);
139140 u32 nd_cmd_in_size(struct nvdimm *nvdimm, int cmd,
include/uapi/linux/ndctl.h+42−0
@@ -159,6 +159,7 @@ enum { · 158 unmodified lines
159159 ND_CMD_VENDOR_EFFECT_LOG_SIZE = 7,
160160 ND_CMD_VENDOR_EFFECT_LOG = 8,
161161 ND_CMD_VENDOR = 9,
162+ ND_CMD_CALL = 10,
162163 };
163164
164165 enum {
@@ -192,6 +193,7 @@ static inline const char *nvdimm_cmd_name(unsigned cmd) · 27 unmodified lines
192193 [ND_CMD_VENDOR_EFFECT_LOG_SIZE] = "effect_size",
193194 [ND_CMD_VENDOR_EFFECT_LOG] = "effect_log",
194195 [ND_CMD_VENDOR] = "vendor",
196+ [ND_CMD_CALL] = "cmd_call",
195197 };
196198
197199 if (cmd < ARRAY_SIZE(names) && names[cmd])
@@ -260,4 +262,44 @@ enum ars_masks { · 62 unmodified lines
260262 ARS_STATUS_MASK = 0x0000FFFF,
261263 ARS_EXT_STATUS_SHIFT = 16,
262264 };
265+
266+/*
267+ * struct nd_cmd_pkg
268+ *
269+ * is a wrapper to a quasi pass thru interface for invoking firmware
270+ * associated with nvdimms.
271+ *
272+ * INPUT PARAMETERS
273+ *
274+ * nd_family corresponds to the firmware (e.g. DSM) interface.
275+ *
276+ * nd_command are the function index advertised by the firmware.
277+ *
278+ * nd_size_in is the size of the input parameters being passed to firmware
279+ *
280+ * OUTPUT PARAMETERS
281+ *
282+ * nd_fw_size is the size of the data firmware wants to return for
283+ * the call. If nd_fw_size is greater than size of nd_size_out, only
284+ * the first nd_size_out bytes are returned.
285+ */
286+
287+struct nd_cmd_pkg {
288+ __u64 nd_family; /* family of commands */
289+ __u64 nd_command;
290+ __u32 nd_size_in; /* INPUT: size of input args */
291+ __u32 nd_size_out; /* INPUT: size of payload */
292+ __u32 nd_reserved2[9]; /* reserved must be zero */
293+ __u32 nd_fw_size; /* OUTPUT: size fw wants to return */
294+ unsigned char nd_payload[]; /* Contents of call */
295+};
296+
297+/* These NVDIMM families represent pre-standardization command sets */
298+#define NVDIMM_FAMILY_INTEL 0
299+#define NVDIMM_FAMILY_HPE1 1
300+#define NVDIMM_FAMILY_HPE2 2
301+
302+#define ND_IOCTL_CALL _IOWR(ND_IOCTL, ND_CMD_CALL,\
303+ struct nd_cmd_pkg)
304+
263305 #endif /* __NDCTL_H__ */
tools/testing/nvdimm/test/nfit.c+33−17
@@ -372,6 +372,7 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, · 371 unmodified lines
372372 {
373373 struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
374374 struct nfit_test *t = container_of(acpi_desc, typeof(*t), acpi_desc);
375+ unsigned int func = cmd;
375376 int i, rc = 0, __cmd_rc;
376377
377378 if (!cmd_rc)
@@ -380,8 +381,23 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, · 2 unmodified lines
380381
381382 if (nvdimm) {
382383 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
384+ unsigned long cmd_mask = nvdimm_cmd_mask(nvdimm);
383385
384− if (!nfit_mem || !test_bit(cmd, &nfit_mem->dsm_mask))
386+ if (!nfit_mem)
387+ return -ENOTTY;
388+
389+ if (cmd == ND_CMD_CALL) {
390+ struct nd_cmd_pkg *call_pkg = buf;
391+
392+ buf_len = call_pkg->nd_size_in + call_pkg->nd_size_out;
393+ buf = (void *) call_pkg->nd_payload;
394+ func = call_pkg->nd_command;
395+ if (call_pkg->nd_family != nfit_mem->family)
396+ return -ENOTTY;
397+ }
398+
399+ if (!test_bit(cmd, &cmd_mask)
400+ || !test_bit(func, &nfit_mem->dsm_mask))
385401 return -ENOTTY;
386402
387403 /* lookup label space for the given dimm */
@@ -392,7 +408,7 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, · 4 unmodified lines
392408 if (i >= ARRAY_SIZE(handle))
393409 return -ENXIO;
394410
395− switch (cmd) {
411+ switch (func) {
396412 case ND_CMD_GET_CONFIG_SIZE:
397413 rc = nfit_test_cmd_get_config_size(buf, buf_len);
398414 break;
@@ -416,10 +432,10 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, · 17 unmodified lines
416432 } else {
417433 struct ars_state *ars_state = &t->ars_state;
418434
419− if (!nd_desc || !test_bit(cmd, &nd_desc->dsm_mask))
435+ if (!nd_desc || !test_bit(cmd, &nd_desc->cmd_mask))
420436 return -ENOTTY;
421437
422− switch (cmd) {
438+ switch (func) {
423439 case ND_CMD_ARS_CAP:
424440 rc = nfit_test_cmd_ars_cap(buf, buf_len);
425441 break;
@@ -1293,15 +1309,15 @@ static void nfit_test0_setup(struct nfit_test *t) · 867 unmodified lines
12931309 post_ars_status(&t->ars_state, t->spa_set_dma[0], SPA0_SIZE);
12941310
12951311 acpi_desc = &t->acpi_desc;
1296− set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_dsm_force_en);
1297− set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en);
1298− set_bit(ND_CMD_SET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en);
1299− set_bit(ND_CMD_SMART, &acpi_desc->dimm_dsm_force_en);
1300− set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_dsm_force_en);
1301− set_bit(ND_CMD_ARS_START, &acpi_desc->bus_dsm_force_en);
1302− set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_dsm_force_en);
1303− set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_dsm_force_en);
1304− set_bit(ND_CMD_SMART_THRESHOLD, &acpi_desc->dimm_dsm_force_en);
1312+ set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_cmd_force_en);
1313+ set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en);
1314+ set_bit(ND_CMD_SET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en);
1315+ set_bit(ND_CMD_SMART, &acpi_desc->dimm_cmd_force_en);
1316+ set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_cmd_force_en);
1317+ set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en);
1318+ set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en);
1319+ set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en);
1320+ set_bit(ND_CMD_SMART_THRESHOLD, &acpi_desc->dimm_cmd_force_en);
13051321 }
13061322
13071323 static void nfit_test1_setup(struct nfit_test *t)
@@ -1359,10 +1375,10 @@ static void nfit_test1_setup(struct nfit_test *t) · 51 unmodified lines
13591375 post_ars_status(&t->ars_state, t->spa_set_dma[0], SPA2_SIZE);
13601376
13611377 acpi_desc = &t->acpi_desc;
1362− set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_dsm_force_en);
1363− set_bit(ND_CMD_ARS_START, &acpi_desc->bus_dsm_force_en);
1364− set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_dsm_force_en);
1365− set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_dsm_force_en);
1378+ set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_cmd_force_en);
1379+ set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en);
1380+ set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en);
1381+ set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en);
13661382 }
13671383
13681384 static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa,