summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/nfit.c101
-rw-r--r--drivers/acpi/nfit.h14
-rw-r--r--drivers/nvdimm/bus.c39
-rw-r--r--include/uapi/linux/ndctl.h42
4 files changed, 179 insertions, 17 deletions
diff --git a/drivers/acpi/nfit.c b/drivers/acpi/nfit.c
index 1b98e9dc6138..b85a46873228 100644
--- a/drivers/acpi/nfit.c
+++ b/drivers/acpi/nfit.c
@@ -171,33 +171,46 @@ static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc,
171 unsigned int buf_len, int *cmd_rc) 171 unsigned int buf_len, int *cmd_rc)
172{ 172{
173 struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc); 173 struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc);
174 const struct nd_cmd_desc *desc = NULL;
175 union acpi_object in_obj, in_buf, *out_obj; 174 union acpi_object in_obj, in_buf, *out_obj;
175 const struct nd_cmd_desc *desc = NULL;
176 struct device *dev = acpi_desc->dev; 176 struct device *dev = acpi_desc->dev;
177 struct nd_cmd_pkg *call_pkg = NULL;
177 const char *cmd_name, *dimm_name; 178 const char *cmd_name, *dimm_name;
178 unsigned long cmd_mask; 179 unsigned long cmd_mask, dsm_mask;
179 acpi_handle handle; 180 acpi_handle handle;
181 unsigned int func;
180 const u8 *uuid; 182 const u8 *uuid;
181 u32 offset; 183 u32 offset;
182 int rc, i; 184 int rc, i;
183 185
186 func = cmd;
187 if (cmd == ND_CMD_CALL) {
188 call_pkg = buf;
189 func = call_pkg->nd_command;
190 }
191
184 if (nvdimm) { 192 if (nvdimm) {
185 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm); 193 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
186 struct acpi_device *adev = nfit_mem->adev; 194 struct acpi_device *adev = nfit_mem->adev;
187 195
188 if (!adev) 196 if (!adev)
189 return -ENOTTY; 197 return -ENOTTY;
198 if (call_pkg && nfit_mem->family != call_pkg->nd_family)
199 return -ENOTTY;
200
190 dimm_name = nvdimm_name(nvdimm); 201 dimm_name = nvdimm_name(nvdimm);
191 cmd_name = nvdimm_cmd_name(cmd); 202 cmd_name = nvdimm_cmd_name(cmd);
192 cmd_mask = nvdimm_cmd_mask(nvdimm); 203 cmd_mask = nvdimm_cmd_mask(nvdimm);
204 dsm_mask = nfit_mem->dsm_mask;
193 desc = nd_cmd_dimm_desc(cmd); 205 desc = nd_cmd_dimm_desc(cmd);
194 uuid = to_nfit_uuid(NFIT_DEV_DIMM); 206 uuid = to_nfit_uuid(nfit_mem->family);
195 handle = adev->handle; 207 handle = adev->handle;
196 } else { 208 } else {
197 struct acpi_device *adev = to_acpi_dev(acpi_desc); 209 struct acpi_device *adev = to_acpi_dev(acpi_desc);
198 210
199 cmd_name = nvdimm_bus_cmd_name(cmd); 211 cmd_name = nvdimm_bus_cmd_name(cmd);
200 cmd_mask = nd_desc->cmd_mask; 212 cmd_mask = nd_desc->cmd_mask;
213 dsm_mask = cmd_mask;
201 desc = nd_cmd_bus_desc(cmd); 214 desc = nd_cmd_bus_desc(cmd);
202 uuid = to_nfit_uuid(NFIT_DEV_BUS); 215 uuid = to_nfit_uuid(NFIT_DEV_BUS);
203 handle = adev->handle; 216 handle = adev->handle;
@@ -207,7 +220,7 @@ static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc,
207 if (!desc || (cmd && (desc->out_num + desc->in_num == 0))) 220 if (!desc || (cmd && (desc->out_num + desc->in_num == 0)))
208 return -ENOTTY; 221 return -ENOTTY;
209 222
210 if (!test_bit(cmd, &cmd_mask)) 223 if (!test_bit(cmd, &cmd_mask) || !test_bit(func, &dsm_mask))
211 return -ENOTTY; 224 return -ENOTTY;
212 225
213 in_obj.type = ACPI_TYPE_PACKAGE; 226 in_obj.type = ACPI_TYPE_PACKAGE;
@@ -222,21 +235,44 @@ static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc,
222 in_buf.buffer.length += nd_cmd_in_size(nvdimm, cmd, desc, 235 in_buf.buffer.length += nd_cmd_in_size(nvdimm, cmd, desc,
223 i, buf); 236 i, buf);
224 237
238 if (call_pkg) {
239 /* skip over package wrapper */
240 in_buf.buffer.pointer = (void *) &call_pkg->nd_payload;
241 in_buf.buffer.length = call_pkg->nd_size_in;
242 }
243
225 if (IS_ENABLED(CONFIG_ACPI_NFIT_DEBUG)) { 244 if (IS_ENABLED(CONFIG_ACPI_NFIT_DEBUG)) {
226 dev_dbg(dev, "%s:%s cmd: %s input length: %d\n", __func__, 245 dev_dbg(dev, "%s:%s cmd: %d: func: %d input length: %d\n",
227 dimm_name, cmd_name, in_buf.buffer.length); 246 __func__, dimm_name, cmd, func,
228 print_hex_dump_debug(cmd_name, DUMP_PREFIX_OFFSET, 4, 247 in_buf.buffer.length);
229 4, in_buf.buffer.pointer, min_t(u32, 128, 248 print_hex_dump_debug("nvdimm in ", DUMP_PREFIX_OFFSET, 4, 4,
230 in_buf.buffer.length), true); 249 in_buf.buffer.pointer,
250 min_t(u32, 256, in_buf.buffer.length), true);
231 } 251 }
232 252
233 out_obj = acpi_evaluate_dsm(handle, uuid, 1, cmd, &in_obj); 253 out_obj = acpi_evaluate_dsm(handle, uuid, 1, func, &in_obj);
234 if (!out_obj) { 254 if (!out_obj) {
235 dev_dbg(dev, "%s:%s _DSM failed cmd: %s\n", __func__, dimm_name, 255 dev_dbg(dev, "%s:%s _DSM failed cmd: %s\n", __func__, dimm_name,
236 cmd_name); 256 cmd_name);
237 return -EINVAL; 257 return -EINVAL;
238 } 258 }
239 259
260 if (call_pkg) {
261 call_pkg->nd_fw_size = out_obj->buffer.length;
262 memcpy(call_pkg->nd_payload + call_pkg->nd_size_in,
263 out_obj->buffer.pointer,
264 min(call_pkg->nd_fw_size, call_pkg->nd_size_out));
265
266 ACPI_FREE(out_obj);
267 /*
268 * Need to support FW function w/o known size in advance.
269 * Caller can determine required size based upon nd_fw_size.
270 * If we return an error (like elsewhere) then caller wouldn't
271 * be able to rely upon data returned to make calculation.
272 */
273 return 0;
274 }
275
240 if (out_obj->package.type != ACPI_TYPE_BUFFER) { 276 if (out_obj->package.type != ACPI_TYPE_BUFFER) {
241 dev_dbg(dev, "%s:%s unexpected output object type cmd: %s type: %d\n", 277 dev_dbg(dev, "%s:%s unexpected output object type cmd: %s type: %d\n",
242 __func__, dimm_name, cmd_name, out_obj->type); 278 __func__, dimm_name, cmd_name, out_obj->type);
@@ -923,11 +959,13 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
923{ 959{
924 struct acpi_device *adev, *adev_dimm; 960 struct acpi_device *adev, *adev_dimm;
925 struct device *dev = acpi_desc->dev; 961 struct device *dev = acpi_desc->dev;
926 const u8 *uuid = to_nfit_uuid(NFIT_DEV_DIMM); 962 unsigned long dsm_mask;
963 const u8 *uuid;
927 int i; 964 int i;
928 965
929 /* nfit test assumes 1:1 relationship between commands and dsms */ 966 /* nfit test assumes 1:1 relationship between commands and dsms */
930 nfit_mem->dsm_mask = acpi_desc->dimm_cmd_force_en; 967 nfit_mem->dsm_mask = acpi_desc->dimm_cmd_force_en;
968 nfit_mem->family = NVDIMM_FAMILY_INTEL;
931 adev = to_acpi_dev(acpi_desc); 969 adev = to_acpi_dev(acpi_desc);
932 if (!adev) 970 if (!adev)
933 return 0; 971 return 0;
@@ -940,7 +978,31 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
940 return force_enable_dimms ? 0 : -ENODEV; 978 return force_enable_dimms ? 0 : -ENODEV;
941 } 979 }
942 980
943 for (i = ND_CMD_SMART; i <= ND_CMD_VENDOR; i++) 981 /*
982 * Until standardization materializes we need to consider up to 3
983 * different command sets. Note, that checking for function0 (bit0)
984 * tells us if any commands are reachable through this uuid.
985 */
986 for (i = NVDIMM_FAMILY_INTEL; i <= NVDIMM_FAMILY_HPE2; i++)
987 if (acpi_check_dsm(adev_dimm->handle, to_nfit_uuid(i), 1, 1))
988 break;
989
990 /* limit the supported commands to those that are publicly documented */
991 nfit_mem->family = i;
992 if (nfit_mem->family == NVDIMM_FAMILY_INTEL)
993 dsm_mask = 0x3fe;
994 else if (nfit_mem->family == NVDIMM_FAMILY_HPE1)
995 dsm_mask = 0x1c3c76;
996 else if (nfit_mem->family == NVDIMM_FAMILY_HPE2)
997 dsm_mask = 0x1fe;
998 else {
999 dev_err(dev, "unknown dimm command family\n");
1000 nfit_mem->family = -1;
1001 return force_enable_dimms ? 0 : -ENODEV;
1002 }
1003
1004 uuid = to_nfit_uuid(nfit_mem->family);
1005 for_each_set_bit(i, &dsm_mask, BITS_PER_LONG)
944 if (acpi_check_dsm(adev_dimm->handle, uuid, 1, 1ULL << i)) 1006 if (acpi_check_dsm(adev_dimm->handle, uuid, 1, 1ULL << i))
945 set_bit(i, &nfit_mem->dsm_mask); 1007 set_bit(i, &nfit_mem->dsm_mask);
946 1008
@@ -953,8 +1015,8 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
953 int dimm_count = 0; 1015 int dimm_count = 0;
954 1016
955 list_for_each_entry(nfit_mem, &acpi_desc->dimms, list) { 1017 list_for_each_entry(nfit_mem, &acpi_desc->dimms, list) {
1018 unsigned long flags = 0, cmd_mask;
956 struct nvdimm *nvdimm; 1019 struct nvdimm *nvdimm;
957 unsigned long flags = 0;
958 u32 device_handle; 1020 u32 device_handle;
959 u16 mem_flags; 1021 u16 mem_flags;
960 int rc; 1022 int rc;
@@ -978,12 +1040,17 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
978 continue; 1040 continue;
979 1041
980 /* 1042 /*
981 * For now there is 1:1 relationship between cmd_mask and 1043 * TODO: provide translation for non-NVDIMM_FAMILY_INTEL
982 * dsm_mask. 1044 * devices (i.e. from nd_cmd to acpi_dsm) to standardize the
1045 * userspace interface.
983 */ 1046 */
1047 cmd_mask = 1UL << ND_CMD_CALL;
1048 if (nfit_mem->family == NVDIMM_FAMILY_INTEL)
1049 cmd_mask |= nfit_mem->dsm_mask;
1050
984 nvdimm = nvdimm_create(acpi_desc->nvdimm_bus, nfit_mem, 1051 nvdimm = nvdimm_create(acpi_desc->nvdimm_bus, nfit_mem,
985 acpi_nfit_dimm_attribute_groups, 1052 acpi_nfit_dimm_attribute_groups,
986 flags, nfit_mem->dsm_mask); 1053 flags, cmd_mask);
987 if (!nvdimm) 1054 if (!nvdimm)
988 return -ENOMEM; 1055 return -ENOMEM;
989 1056
@@ -2468,6 +2535,8 @@ static __init int nfit_init(void)
2468 acpi_str_to_uuid(UUID_PERSISTENT_VIRTUAL_CD, nfit_uuid[NFIT_SPA_PCD]); 2535 acpi_str_to_uuid(UUID_PERSISTENT_VIRTUAL_CD, nfit_uuid[NFIT_SPA_PCD]);
2469 acpi_str_to_uuid(UUID_NFIT_BUS, nfit_uuid[NFIT_DEV_BUS]); 2536 acpi_str_to_uuid(UUID_NFIT_BUS, nfit_uuid[NFIT_DEV_BUS]);
2470 acpi_str_to_uuid(UUID_NFIT_DIMM, nfit_uuid[NFIT_DEV_DIMM]); 2537 acpi_str_to_uuid(UUID_NFIT_DIMM, nfit_uuid[NFIT_DEV_DIMM]);
2538 acpi_str_to_uuid(UUID_NFIT_DIMM_N_HPE1, nfit_uuid[NFIT_DEV_DIMM_N_HPE1]);
2539 acpi_str_to_uuid(UUID_NFIT_DIMM_N_HPE2, nfit_uuid[NFIT_DEV_DIMM_N_HPE2]);
2471 2540
2472 nfit_wq = create_singlethread_workqueue("nfit"); 2541 nfit_wq = create_singlethread_workqueue("nfit");
2473 if (!nfit_wq) 2542 if (!nfit_wq)
diff --git a/drivers/acpi/nfit.h b/drivers/acpi/nfit.h
index 332ee6f01662..f82fda55b6de 100644
--- a/drivers/acpi/nfit.h
+++ b/drivers/acpi/nfit.h
@@ -21,13 +21,25 @@
21#include <linux/acpi.h> 21#include <linux/acpi.h>
22#include <acpi/acuuid.h> 22#include <acpi/acuuid.h>
23 23
24/* ACPI 6.1 */
24#define UUID_NFIT_BUS "2f10e7a4-9e91-11e4-89d3-123b93f75cba" 25#define UUID_NFIT_BUS "2f10e7a4-9e91-11e4-89d3-123b93f75cba"
26
27/* http://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf */
25#define UUID_NFIT_DIMM "4309ac30-0d11-11e4-9191-0800200c9a66" 28#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
26#define ACPI_NFIT_MEM_FAILED_MASK (ACPI_NFIT_MEM_SAVE_FAILED \ 34#define ACPI_NFIT_MEM_FAILED_MASK (ACPI_NFIT_MEM_SAVE_FAILED \
27 | ACPI_NFIT_MEM_RESTORE_FAILED | ACPI_NFIT_MEM_FLUSH_FAILED \ 35 | ACPI_NFIT_MEM_RESTORE_FAILED | ACPI_NFIT_MEM_FLUSH_FAILED \
28 | ACPI_NFIT_MEM_NOT_ARMED) 36 | ACPI_NFIT_MEM_NOT_ARMED)
29 37
30enum nfit_uuids { 38enum 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,
31 NFIT_SPA_VOLATILE, 43 NFIT_SPA_VOLATILE,
32 NFIT_SPA_PM, 44 NFIT_SPA_PM,
33 NFIT_SPA_DCR, 45 NFIT_SPA_DCR,
@@ -37,7 +49,6 @@ enum nfit_uuids {
37 NFIT_SPA_PDISK, 49 NFIT_SPA_PDISK,
38 NFIT_SPA_PCD, 50 NFIT_SPA_PCD,
39 NFIT_DEV_BUS, 51 NFIT_DEV_BUS,
40 NFIT_DEV_DIMM,
41 NFIT_UUID_MAX, 52 NFIT_UUID_MAX,
42}; 53};
43 54
@@ -110,6 +121,7 @@ struct nfit_mem {
110 struct list_head list; 121 struct list_head list;
111 struct acpi_device *adev; 122 struct acpi_device *adev;
112 unsigned long dsm_mask; 123 unsigned long dsm_mask;
124 int family;
113}; 125};
114 126
115struct acpi_nfit_desc { 127struct acpi_nfit_desc {
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
index cb2042a12b76..395a9fbbc69d 100644
--- a/drivers/nvdimm/bus.c
+++ b/drivers/nvdimm/bus.c
@@ -439,6 +439,12 @@ static const struct nd_cmd_desc __nd_cmd_dimm_descs[] = {
439 .out_num = 3, 439 .out_num = 3,
440 .out_sizes = { 4, 4, UINT_MAX, }, 440 .out_sizes = { 4, 4, UINT_MAX, },
441 }, 441 },
442 [ND_CMD_CALL] = {
443 .in_num = 2,
444 .in_sizes = { sizeof(struct nd_cmd_pkg), UINT_MAX, },
445 .out_num = 1,
446 .out_sizes = { UINT_MAX, },
447 },
442}; 448};
443 449
444const struct nd_cmd_desc *nd_cmd_dimm_desc(int cmd) 450const struct nd_cmd_desc *nd_cmd_dimm_desc(int cmd)
@@ -473,6 +479,12 @@ static const struct nd_cmd_desc __nd_cmd_bus_descs[] = {
473 .out_num = 3, 479 .out_num = 3,
474 .out_sizes = { 4, 4, 8, }, 480 .out_sizes = { 4, 4, 8, },
475 }, 481 },
482 [ND_CMD_CALL] = {
483 .in_num = 2,
484 .in_sizes = { sizeof(struct nd_cmd_pkg), UINT_MAX, },
485 .out_num = 1,
486 .out_sizes = { UINT_MAX, },
487 },
476}; 488};
477 489
478const struct nd_cmd_desc *nd_cmd_bus_desc(int cmd) 490const struct nd_cmd_desc *nd_cmd_bus_desc(int cmd)
@@ -500,6 +512,10 @@ u32 nd_cmd_in_size(struct nvdimm *nvdimm, int cmd,
500 struct nd_cmd_vendor_hdr *hdr = buf; 512 struct nd_cmd_vendor_hdr *hdr = buf;
501 513
502 return hdr->in_length; 514 return hdr->in_length;
515 } else if (cmd == ND_CMD_CALL) {
516 struct nd_cmd_pkg *pkg = buf;
517
518 return pkg->nd_size_in;
503 } 519 }
504 520
505 return UINT_MAX; 521 return UINT_MAX;
@@ -522,6 +538,12 @@ u32 nd_cmd_out_size(struct nvdimm *nvdimm, int cmd,
522 return out_field[1]; 538 return out_field[1];
523 else if (!nvdimm && cmd == ND_CMD_ARS_STATUS && idx == 2) 539 else if (!nvdimm && cmd == ND_CMD_ARS_STATUS && idx == 2)
524 return out_field[1] - 8; 540 return out_field[1] - 8;
541 else if (cmd == ND_CMD_CALL) {
542 struct nd_cmd_pkg *pkg = (struct nd_cmd_pkg *) in_field;
543
544 return pkg->nd_size_out;
545 }
546
525 547
526 return UINT_MAX; 548 return UINT_MAX;
527} 549}
@@ -588,6 +610,7 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
588 unsigned int cmd = _IOC_NR(ioctl_cmd); 610 unsigned int cmd = _IOC_NR(ioctl_cmd);
589 void __user *p = (void __user *) arg; 611 void __user *p = (void __user *) arg;
590 struct device *dev = &nvdimm_bus->dev; 612 struct device *dev = &nvdimm_bus->dev;
613 struct nd_cmd_pkg pkg;
591 const char *cmd_name, *dimm_name; 614 const char *cmd_name, *dimm_name;
592 unsigned long cmd_mask; 615 unsigned long cmd_mask;
593 void *buf; 616 void *buf;
@@ -605,6 +628,11 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
605 dimm_name = "bus"; 628 dimm_name = "bus";
606 } 629 }
607 630
631 if (cmd == ND_CMD_CALL) {
632 if (copy_from_user(&pkg, p, sizeof(pkg)))
633 return -EFAULT;
634 }
635
608 if (!desc || (desc->out_num + desc->in_num == 0) || 636 if (!desc || (desc->out_num + desc->in_num == 0) ||
609 !test_bit(cmd, &cmd_mask)) 637 !test_bit(cmd, &cmd_mask))
610 return -ENOTTY; 638 return -ENOTTY;
@@ -616,6 +644,7 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
616 case ND_CMD_SET_CONFIG_DATA: 644 case ND_CMD_SET_CONFIG_DATA:
617 case ND_CMD_ARS_START: 645 case ND_CMD_ARS_START:
618 case ND_CMD_CLEAR_ERROR: 646 case ND_CMD_CLEAR_ERROR:
647 case ND_CMD_CALL:
619 dev_dbg(&nvdimm_bus->dev, "'%s' command while read-only.\n", 648 dev_dbg(&nvdimm_bus->dev, "'%s' command while read-only.\n",
620 nvdimm ? nvdimm_cmd_name(cmd) 649 nvdimm ? nvdimm_cmd_name(cmd)
621 : nvdimm_bus_cmd_name(cmd)); 650 : nvdimm_bus_cmd_name(cmd));
@@ -643,6 +672,16 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
643 in_len += in_size; 672 in_len += in_size;
644 } 673 }
645 674
675 if (cmd == ND_CMD_CALL) {
676 dev_dbg(dev, "%s:%s, idx: %llu, in: %zu, out: %zu, len %zu\n",
677 __func__, dimm_name, pkg.nd_command,
678 in_len, out_len, buf_len);
679
680 for (i = 0; i < ARRAY_SIZE(pkg.nd_reserved2); i++)
681 if (pkg.nd_reserved2[i])
682 return -EINVAL;
683 }
684
646 /* process an output envelope */ 685 /* process an output envelope */
647 for (i = 0; i < desc->out_num; i++) { 686 for (i = 0; i < desc->out_num; i++) {
648 u32 out_size = nd_cmd_out_size(nvdimm, cmd, desc, i, 687 u32 out_size = nd_cmd_out_size(nvdimm, cmd, desc, i,
diff --git a/include/uapi/linux/ndctl.h b/include/uapi/linux/ndctl.h
index 7cc28ab05b87..45daa0be5ff9 100644
--- a/include/uapi/linux/ndctl.h
+++ b/include/uapi/linux/ndctl.h
@@ -125,6 +125,7 @@ enum {
125 ND_CMD_VENDOR_EFFECT_LOG_SIZE = 7, 125 ND_CMD_VENDOR_EFFECT_LOG_SIZE = 7,
126 ND_CMD_VENDOR_EFFECT_LOG = 8, 126 ND_CMD_VENDOR_EFFECT_LOG = 8,
127 ND_CMD_VENDOR = 9, 127 ND_CMD_VENDOR = 9,
128 ND_CMD_CALL = 10,
128}; 129};
129 130
130enum { 131enum {
@@ -158,6 +159,7 @@ static inline const char *nvdimm_cmd_name(unsigned cmd)
158 [ND_CMD_VENDOR_EFFECT_LOG_SIZE] = "effect_size", 159 [ND_CMD_VENDOR_EFFECT_LOG_SIZE] = "effect_size",
159 [ND_CMD_VENDOR_EFFECT_LOG] = "effect_log", 160 [ND_CMD_VENDOR_EFFECT_LOG] = "effect_log",
160 [ND_CMD_VENDOR] = "vendor", 161 [ND_CMD_VENDOR] = "vendor",
162 [ND_CMD_CALL] = "cmd_call",
161 }; 163 };
162 164
163 if (cmd < ARRAY_SIZE(names) && names[cmd]) 165 if (cmd < ARRAY_SIZE(names) && names[cmd])
@@ -224,4 +226,44 @@ enum ars_masks {
224 ARS_STATUS_MASK = 0x0000FFFF, 226 ARS_STATUS_MASK = 0x0000FFFF,
225 ARS_EXT_STATUS_SHIFT = 16, 227 ARS_EXT_STATUS_SHIFT = 16,
226}; 228};
229
230/*
231 * struct nd_cmd_pkg
232 *
233 * is a wrapper to a quasi pass thru interface for invoking firmware
234 * associated with nvdimms.
235 *
236 * INPUT PARAMETERS
237 *
238 * nd_family corresponds to the firmware (e.g. DSM) interface.
239 *
240 * nd_command are the function index advertised by the firmware.
241 *
242 * nd_size_in is the size of the input parameters being passed to firmware
243 *
244 * OUTPUT PARAMETERS
245 *
246 * nd_fw_size is the size of the data firmware wants to return for
247 * the call. If nd_fw_size is greater than size of nd_size_out, only
248 * the first nd_size_out bytes are returned.
249 */
250
251struct nd_cmd_pkg {
252 __u64 nd_family; /* family of commands */
253 __u64 nd_command;
254 __u32 nd_size_in; /* INPUT: size of input args */
255 __u32 nd_size_out; /* INPUT: size of payload */
256 __u32 nd_reserved2[9]; /* reserved must be zero */
257 __u32 nd_fw_size; /* OUTPUT: size fw wants to return */
258 unsigned char nd_payload[]; /* Contents of call */
259};
260
261/* These NVDIMM families represent pre-standardization command sets */
262#define NVDIMM_FAMILY_INTEL 0
263#define NVDIMM_FAMILY_HPE1 1
264#define NVDIMM_FAMILY_HPE2 2
265
266#define ND_IOCTL_CALL _IOWR(ND_IOCTL, ND_CMD_CALL,\
267 struct nd_cmd_pkg)
268
227#endif /* __NDCTL_H__ */ 269#endif /* __NDCTL_H__ */