Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+284 -59
+128 -19
drivers/acpi/nfit.c
··· 45 45 MODULE_PARM_DESC(scrub_overflow_abort, 46 46 "Number of times we overflow ARS results before abort"); 47 47 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 + 48 53 static struct workqueue_struct *nfit_wq; 49 54 50 55 struct nfit_table_prev { ··· 176 171 unsigned int buf_len, int *cmd_rc) 177 172 { 178 173 struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc); 179 - const struct nd_cmd_desc *desc = NULL; 180 174 union acpi_object in_obj, in_buf, *out_obj; 175 + const struct nd_cmd_desc *desc = NULL; 181 176 struct device *dev = acpi_desc->dev; 177 + struct nd_cmd_pkg *call_pkg = NULL; 182 178 const char *cmd_name, *dimm_name; 183 - unsigned long dsm_mask; 179 + unsigned long cmd_mask, dsm_mask; 184 180 acpi_handle handle; 181 + unsigned int func; 185 182 const u8 *uuid; 186 183 u32 offset; 187 184 int rc, i; 185 + 186 + func = cmd; 187 + if (cmd == ND_CMD_CALL) { 188 + call_pkg = buf; 189 + func = call_pkg->nd_command; 190 + } 188 191 189 192 if (nvdimm) { 190 193 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm); ··· 200 187 201 188 if (!adev) 202 189 return -ENOTTY; 190 + if (call_pkg && nfit_mem->family != call_pkg->nd_family) 191 + return -ENOTTY; 192 + 203 193 dimm_name = nvdimm_name(nvdimm); 204 194 cmd_name = nvdimm_cmd_name(cmd); 195 + cmd_mask = nvdimm_cmd_mask(nvdimm); 205 196 dsm_mask = nfit_mem->dsm_mask; 206 197 desc = nd_cmd_dimm_desc(cmd); 207 - uuid = to_nfit_uuid(NFIT_DEV_DIMM); 198 + uuid = to_nfit_uuid(nfit_mem->family); 208 199 handle = adev->handle; 209 200 } else { 210 201 struct acpi_device *adev = to_acpi_dev(acpi_desc); 211 202 212 203 cmd_name = nvdimm_bus_cmd_name(cmd); 213 - dsm_mask = nd_desc->dsm_mask; 204 + cmd_mask = nd_desc->cmd_mask; 205 + dsm_mask = cmd_mask; 214 206 desc = nd_cmd_bus_desc(cmd); 215 207 uuid = to_nfit_uuid(NFIT_DEV_BUS); 216 208 handle = adev->handle; ··· 225 207 if (!desc || (cmd && (desc->out_num + desc->in_num == 0))) 226 208 return -ENOTTY; 227 209 228 - if (!test_bit(cmd, &dsm_mask)) 210 + if (!test_bit(cmd, &cmd_mask) || !test_bit(func, &dsm_mask)) 229 211 return -ENOTTY; 230 212 231 213 in_obj.type = ACPI_TYPE_PACKAGE; ··· 240 222 in_buf.buffer.length += nd_cmd_in_size(nvdimm, cmd, desc, 241 223 i, buf); 242 224 243 - if (IS_ENABLED(CONFIG_ACPI_NFIT_DEBUG)) { 244 - dev_dbg(dev, "%s:%s cmd: %s input length: %d\n", __func__, 245 - dimm_name, cmd_name, in_buf.buffer.length); 246 - print_hex_dump_debug(cmd_name, DUMP_PREFIX_OFFSET, 4, 247 - 4, in_buf.buffer.pointer, min_t(u32, 128, 248 - in_buf.buffer.length), true); 225 + if (call_pkg) { 226 + /* skip over package wrapper */ 227 + in_buf.buffer.pointer = (void *) &call_pkg->nd_payload; 228 + in_buf.buffer.length = call_pkg->nd_size_in; 249 229 } 250 230 251 - out_obj = acpi_evaluate_dsm(handle, uuid, 1, cmd, &in_obj); 231 + if (IS_ENABLED(CONFIG_ACPI_NFIT_DEBUG)) { 232 + dev_dbg(dev, "%s:%s cmd: %d: func: %d input length: %d\n", 233 + __func__, dimm_name, cmd, func, 234 + in_buf.buffer.length); 235 + print_hex_dump_debug("nvdimm in ", DUMP_PREFIX_OFFSET, 4, 4, 236 + in_buf.buffer.pointer, 237 + min_t(u32, 256, in_buf.buffer.length), true); 238 + } 239 + 240 + out_obj = acpi_evaluate_dsm(handle, uuid, 1, func, &in_obj); 252 241 if (!out_obj) { 253 242 dev_dbg(dev, "%s:%s _DSM failed cmd: %s\n", __func__, dimm_name, 254 243 cmd_name); 255 244 return -EINVAL; 245 + } 246 + 247 + if (call_pkg) { 248 + call_pkg->nd_fw_size = out_obj->buffer.length; 249 + memcpy(call_pkg->nd_payload + call_pkg->nd_size_in, 250 + out_obj->buffer.pointer, 251 + min(call_pkg->nd_fw_size, call_pkg->nd_size_out)); 252 + 253 + ACPI_FREE(out_obj); 254 + /* 255 + * Need to support FW function w/o known size in advance. 256 + * Caller can determine required size based upon nd_fw_size. 257 + * If we return an error (like elsewhere) then caller wouldn't 258 + * be able to rely upon data returned to make calculation. 259 + */ 260 + return 0; 256 261 } 257 262 258 263 if (out_obj->package.type != ACPI_TYPE_BUFFER) { ··· 962 921 } 963 922 static DEVICE_ATTR_RO(serial); 964 923 924 + static ssize_t family_show(struct device *dev, 925 + struct device_attribute *attr, char *buf) 926 + { 927 + struct nvdimm *nvdimm = to_nvdimm(dev); 928 + struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm); 929 + 930 + if (nfit_mem->family < 0) 931 + return -ENXIO; 932 + return sprintf(buf, "%d\n", nfit_mem->family); 933 + } 934 + static DEVICE_ATTR_RO(family); 935 + 936 + static ssize_t dsm_mask_show(struct device *dev, 937 + struct device_attribute *attr, char *buf) 938 + { 939 + struct nvdimm *nvdimm = to_nvdimm(dev); 940 + struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm); 941 + 942 + if (nfit_mem->family < 0) 943 + return -ENXIO; 944 + return sprintf(buf, "%#lx\n", nfit_mem->dsm_mask); 945 + } 946 + static DEVICE_ATTR_RO(dsm_mask); 947 + 965 948 static ssize_t flags_show(struct device *dev, 966 949 struct device_attribute *attr, char *buf) 967 950 { ··· 1011 946 &dev_attr_serial.attr, 1012 947 &dev_attr_rev_id.attr, 1013 948 &dev_attr_flags.attr, 949 + &dev_attr_family.attr, 950 + &dev_attr_dsm_mask.attr, 1014 951 NULL, 1015 952 }; 1016 953 ··· 1059 992 { 1060 993 struct acpi_device *adev, *adev_dimm; 1061 994 struct device *dev = acpi_desc->dev; 1062 - const u8 *uuid = to_nfit_uuid(NFIT_DEV_DIMM); 995 + unsigned long dsm_mask; 996 + const u8 *uuid; 1063 997 int i; 1064 998 1065 - nfit_mem->dsm_mask = acpi_desc->dimm_dsm_force_en; 999 + /* nfit test assumes 1:1 relationship between commands and dsms */ 1000 + nfit_mem->dsm_mask = acpi_desc->dimm_cmd_force_en; 1001 + nfit_mem->family = NVDIMM_FAMILY_INTEL; 1066 1002 adev = to_acpi_dev(acpi_desc); 1067 1003 if (!adev) 1068 1004 return 0; ··· 1078 1008 return force_enable_dimms ? 0 : -ENODEV; 1079 1009 } 1080 1010 1081 - for (i = ND_CMD_SMART; i <= ND_CMD_VENDOR; i++) 1011 + /* 1012 + * Until standardization materializes we need to consider up to 3 1013 + * different command sets. Note, that checking for function0 (bit0) 1014 + * tells us if any commands are reachable through this uuid. 1015 + */ 1016 + for (i = NVDIMM_FAMILY_INTEL; i <= NVDIMM_FAMILY_HPE2; i++) 1017 + if (acpi_check_dsm(adev_dimm->handle, to_nfit_uuid(i), 1, 1)) 1018 + break; 1019 + 1020 + /* limit the supported commands to those that are publicly documented */ 1021 + nfit_mem->family = i; 1022 + if (nfit_mem->family == NVDIMM_FAMILY_INTEL) { 1023 + dsm_mask = 0x3fe; 1024 + if (disable_vendor_specific) 1025 + dsm_mask &= ~(1 << ND_CMD_VENDOR); 1026 + } else if (nfit_mem->family == NVDIMM_FAMILY_HPE1) 1027 + dsm_mask = 0x1c3c76; 1028 + else if (nfit_mem->family == NVDIMM_FAMILY_HPE2) { 1029 + dsm_mask = 0x1fe; 1030 + if (disable_vendor_specific) 1031 + dsm_mask &= ~(1 << 8); 1032 + } else { 1033 + dev_err(dev, "unknown dimm command family\n"); 1034 + nfit_mem->family = -1; 1035 + return force_enable_dimms ? 0 : -ENODEV; 1036 + } 1037 + 1038 + uuid = to_nfit_uuid(nfit_mem->family); 1039 + for_each_set_bit(i, &dsm_mask, BITS_PER_LONG) 1082 1040 if (acpi_check_dsm(adev_dimm->handle, uuid, 1, 1ULL << i)) 1083 1041 set_bit(i, &nfit_mem->dsm_mask); 1084 1042 ··· 1119 1021 int dimm_count = 0; 1120 1022 1121 1023 list_for_each_entry(nfit_mem, &acpi_desc->dimms, list) { 1024 + unsigned long flags = 0, cmd_mask; 1122 1025 struct nvdimm *nvdimm; 1123 - unsigned long flags = 0; 1124 1026 u32 device_handle; 1125 1027 u16 mem_flags; 1126 1028 int rc; ··· 1143 1045 if (rc) 1144 1046 continue; 1145 1047 1048 + /* 1049 + * TODO: provide translation for non-NVDIMM_FAMILY_INTEL 1050 + * devices (i.e. from nd_cmd to acpi_dsm) to standardize the 1051 + * userspace interface. 1052 + */ 1053 + cmd_mask = 1UL << ND_CMD_CALL; 1054 + if (nfit_mem->family == NVDIMM_FAMILY_INTEL) 1055 + cmd_mask |= nfit_mem->dsm_mask; 1056 + 1146 1057 nvdimm = nvdimm_create(acpi_desc->nvdimm_bus, nfit_mem, 1147 1058 acpi_nfit_dimm_attribute_groups, 1148 - flags, &nfit_mem->dsm_mask); 1059 + flags, cmd_mask); 1149 1060 if (!nvdimm) 1150 1061 return -ENOMEM; 1151 1062 ··· 1183 1076 struct acpi_device *adev; 1184 1077 int i; 1185 1078 1186 - nd_desc->dsm_mask = acpi_desc->bus_dsm_force_en; 1079 + nd_desc->cmd_mask = acpi_desc->bus_cmd_force_en; 1187 1080 adev = to_acpi_dev(acpi_desc); 1188 1081 if (!adev) 1189 1082 return; 1190 1083 1191 1084 for (i = ND_CMD_ARS_CAP; i <= ND_CMD_CLEAR_ERROR; i++) 1192 1085 if (acpi_check_dsm(adev->handle, uuid, 1, 1ULL << i)) 1193 - set_bit(i, &nd_desc->dsm_mask); 1086 + set_bit(i, &nd_desc->cmd_mask); 1194 1087 } 1195 1088 1196 1089 static ssize_t range_index_show(struct device *dev, ··· 2639 2532 acpi_str_to_uuid(UUID_PERSISTENT_VIRTUAL_CD, nfit_uuid[NFIT_SPA_PCD]); 2640 2533 acpi_str_to_uuid(UUID_NFIT_BUS, nfit_uuid[NFIT_DEV_BUS]); 2641 2534 acpi_str_to_uuid(UUID_NFIT_DIMM, nfit_uuid[NFIT_DEV_DIMM]); 2535 + acpi_str_to_uuid(UUID_NFIT_DIMM_N_HPE1, nfit_uuid[NFIT_DEV_DIMM_N_HPE1]); 2536 + acpi_str_to_uuid(UUID_NFIT_DIMM_N_HPE2, nfit_uuid[NFIT_DEV_DIMM_N_HPE2]); 2642 2537 2643 2538 nfit_wq = create_singlethread_workqueue("nfit"); 2644 2539 if (!nfit_wq)
+15 -3
drivers/acpi/nfit.h
··· 21 21 #include <linux/acpi.h> 22 22 #include <acpi/acuuid.h> 23 23 24 + /* ACPI 6.1 */ 24 25 #define UUID_NFIT_BUS "2f10e7a4-9e91-11e4-89d3-123b93f75cba" 26 + 27 + /* http://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf */ 25 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 34 #define ACPI_NFIT_MEM_FAILED_MASK (ACPI_NFIT_MEM_SAVE_FAILED \ 27 35 | ACPI_NFIT_MEM_RESTORE_FAILED | ACPI_NFIT_MEM_FLUSH_FAILED \ 28 36 | ACPI_NFIT_MEM_NOT_ARMED) 29 37 30 38 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, 31 43 NFIT_SPA_VOLATILE, 32 44 NFIT_SPA_PM, 33 45 NFIT_SPA_DCR, ··· 49 37 NFIT_SPA_PDISK, 50 38 NFIT_SPA_PCD, 51 39 NFIT_DEV_BUS, 52 - NFIT_DEV_DIMM, 53 40 NFIT_UUID_MAX, 54 41 }; 55 42 ··· 122 111 struct acpi_device *adev; 123 112 struct acpi_nfit_desc *acpi_desc; 124 113 unsigned long dsm_mask; 114 + int family; 125 115 }; 126 116 127 117 struct acpi_nfit_desc { ··· 145 133 size_t ars_status_size; 146 134 struct work_struct work; 147 135 unsigned int cancel:1; 148 - unsigned long dimm_dsm_force_en; 149 - unsigned long bus_dsm_force_en; 136 + unsigned long dimm_cmd_force_en; 137 + unsigned long bus_cmd_force_en; 150 138 int (*blk_do_io)(struct nd_blk_region *ndbr, resource_size_t dpa, 151 139 void *iobuf, u64 len, int rw); 152 140 };
+2 -2
drivers/acpi/utils.c
··· 625 625 * some old BIOSes do expect a buffer or an integer etc. 626 626 */ 627 627 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, 629 629 union acpi_object *argv4) 630 630 { 631 631 acpi_status ret; ··· 674 674 * functions. Currently only support 64 functions at maximum, should be 675 675 * enough for now. 676 676 */ 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) 678 678 { 679 679 int i; 680 680 u64 mask = 0;
+43 -4
drivers/nvdimm/bus.c
··· 443 443 .out_num = 3, 444 444 .out_sizes = { 4, 4, UINT_MAX, }, 445 445 }, 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 + }, 446 452 }; 447 453 448 454 const struct nd_cmd_desc *nd_cmd_dimm_desc(int cmd) ··· 483 477 .out_num = 3, 484 478 .out_sizes = { 4, 4, 8, }, 485 479 }, 480 + [ND_CMD_CALL] = { 481 + .in_num = 2, 482 + .in_sizes = { sizeof(struct nd_cmd_pkg), UINT_MAX, }, 483 + .out_num = 1, 484 + .out_sizes = { UINT_MAX, }, 485 + }, 486 486 }; 487 487 488 488 const struct nd_cmd_desc *nd_cmd_bus_desc(int cmd) ··· 516 504 struct nd_cmd_vendor_hdr *hdr = buf; 517 505 518 506 return hdr->in_length; 507 + } else if (cmd == ND_CMD_CALL) { 508 + struct nd_cmd_pkg *pkg = buf; 509 + 510 + return pkg->nd_size_in; 519 511 } 520 512 521 513 return UINT_MAX; ··· 542 526 return out_field[1]; 543 527 else if (!nvdimm && cmd == ND_CMD_ARS_STATUS && idx == 2) 544 528 return out_field[1] - 8; 529 + else if (cmd == ND_CMD_CALL) { 530 + struct nd_cmd_pkg *pkg = (struct nd_cmd_pkg *) in_field; 531 + 532 + return pkg->nd_size_out; 533 + } 534 + 545 535 546 536 return UINT_MAX; 547 537 } ··· 614 592 unsigned int cmd = _IOC_NR(ioctl_cmd); 615 593 void __user *p = (void __user *) arg; 616 594 struct device *dev = &nvdimm_bus->dev; 595 + struct nd_cmd_pkg pkg; 617 596 const char *cmd_name, *dimm_name; 618 - unsigned long dsm_mask; 597 + unsigned long cmd_mask; 619 598 void *buf; 620 599 int rc, i; 621 600 622 601 if (nvdimm) { 623 602 desc = nd_cmd_dimm_desc(cmd); 624 603 cmd_name = nvdimm_cmd_name(cmd); 625 - dsm_mask = nvdimm->dsm_mask ? *(nvdimm->dsm_mask) : 0; 604 + cmd_mask = nvdimm->cmd_mask; 626 605 dimm_name = dev_name(&nvdimm->dev); 627 606 } else { 628 607 desc = nd_cmd_bus_desc(cmd); 629 608 cmd_name = nvdimm_bus_cmd_name(cmd); 630 - dsm_mask = nd_desc->dsm_mask; 609 + cmd_mask = nd_desc->cmd_mask; 631 610 dimm_name = "bus"; 632 611 } 633 612 613 + if (cmd == ND_CMD_CALL) { 614 + if (copy_from_user(&pkg, p, sizeof(pkg))) 615 + return -EFAULT; 616 + } 617 + 634 618 if (!desc || (desc->out_num + desc->in_num == 0) || 635 - !test_bit(cmd, &dsm_mask)) 619 + !test_bit(cmd, &cmd_mask)) 636 620 return -ENOTTY; 637 621 638 622 /* fail write commands (when read-only) */ ··· 648 620 case ND_CMD_SET_CONFIG_DATA: 649 621 case ND_CMD_ARS_START: 650 622 case ND_CMD_CLEAR_ERROR: 623 + case ND_CMD_CALL: 651 624 dev_dbg(&nvdimm_bus->dev, "'%s' command while read-only.\n", 652 625 nvdimm ? nvdimm_cmd_name(cmd) 653 626 : nvdimm_bus_cmd_name(cmd)); ··· 674 645 if (copy && copy_from_user(&in_env[in_len], p + in_len, copy)) 675 646 return -EFAULT; 676 647 in_len += in_size; 648 + } 649 + 650 + if (cmd == ND_CMD_CALL) { 651 + dev_dbg(dev, "%s:%s, idx: %llu, in: %zu, out: %zu, len %zu\n", 652 + __func__, dimm_name, pkg.nd_command, 653 + in_len, out_len, buf_len); 654 + 655 + for (i = 0; i < ARRAY_SIZE(pkg.nd_reserved2); i++) 656 + if (pkg.nd_reserved2[i]) 657 + return -EINVAL; 677 658 } 678 659 679 660 /* process an output envelope */
+1 -1
drivers/nvdimm/core.c
··· 251 251 struct nvdimm_bus *nvdimm_bus = to_nvdimm_bus(dev); 252 252 struct nvdimm_bus_descriptor *nd_desc = nvdimm_bus->nd_desc; 253 253 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) 255 255 len += sprintf(buf + len, "%s ", nvdimm_bus_cmd_name(cmd)); 256 256 len += sprintf(buf + len, "\n"); 257 257 return len;
+12 -6
drivers/nvdimm/dimm_devs.c
··· 37 37 38 38 nvdimm = to_nvdimm(ndd->dev); 39 39 40 - if (!nvdimm->dsm_mask) 40 + if (!nvdimm->cmd_mask) 41 41 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)) 43 43 return -ENXIO; 44 44 45 45 return 0; ··· 263 263 } 264 264 EXPORT_SYMBOL_GPL(nvdimm_name); 265 265 266 + unsigned long nvdimm_cmd_mask(struct nvdimm *nvdimm) 267 + { 268 + return nvdimm->cmd_mask; 269 + } 270 + EXPORT_SYMBOL_GPL(nvdimm_cmd_mask); 271 + 266 272 void *nvdimm_provider_data(struct nvdimm *nvdimm) 267 273 { 268 274 if (nvdimm) ··· 283 277 struct nvdimm *nvdimm = to_nvdimm(dev); 284 278 int cmd, len = 0; 285 279 286 - if (!nvdimm->dsm_mask) 280 + if (!nvdimm->cmd_mask) 287 281 return sprintf(buf, "\n"); 288 282 289 - for_each_set_bit(cmd, nvdimm->dsm_mask, BITS_PER_LONG) 283 + for_each_set_bit(cmd, &nvdimm->cmd_mask, BITS_PER_LONG) 290 284 len += sprintf(buf + len, "%s ", nvdimm_cmd_name(cmd)); 291 285 len += sprintf(buf + len, "\n"); 292 286 return len; ··· 346 340 347 341 struct nvdimm *nvdimm_create(struct nvdimm_bus *nvdimm_bus, void *provider_data, 348 342 const struct attribute_group **groups, unsigned long flags, 349 - unsigned long *dsm_mask) 343 + unsigned long cmd_mask) 350 344 { 351 345 struct nvdimm *nvdimm = kzalloc(sizeof(*nvdimm), GFP_KERNEL); 352 346 struct device *dev; ··· 361 355 } 362 356 nvdimm->provider_data = provider_data; 363 357 nvdimm->flags = flags; 364 - nvdimm->dsm_mask = dsm_mask; 358 + nvdimm->cmd_mask = cmd_mask; 365 359 atomic_set(&nvdimm->busy, 0); 366 360 dev = &nvdimm->dev; 367 361 dev_set_name(dev, "nmem%d", nvdimm->id);
+1 -1
drivers/nvdimm/nd-core.h
··· 37 37 struct nvdimm { 38 38 unsigned long flags; 39 39 void *provider_data; 40 - unsigned long *dsm_mask; 40 + unsigned long cmd_mask; 41 41 struct device dev; 42 42 atomic_t busy; 43 43 int id;
+3 -3
include/acpi/acpi_bus.h
··· 61 61 bool acpi_bay_match(acpi_handle handle); 62 62 bool acpi_dock_match(acpi_handle handle); 63 63 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); 65 65 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); 67 67 68 68 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, 70 70 union acpi_object *argv4, acpi_object_type type) 71 71 { 72 72 union acpi_object *obj;
+4 -3
include/linux/libnvdimm.h
··· 27 27 /* need to set a limit somewhere, but yes, this is likely overkill */ 28 28 ND_IOCTL_MAX_BUFLEN = SZ_4M, 29 29 ND_CMD_MAX_ELEM = 5, 30 - ND_CMD_MAX_ENVELOPE = 16, 30 + ND_CMD_MAX_ENVELOPE = 256, 31 31 ND_MAX_MAPPINGS = 32, 32 32 33 33 /* region flag indicating to direct-map persistent memory by default */ ··· 68 68 69 69 struct nvdimm_bus_descriptor { 70 70 const struct attribute_group **attr_groups; 71 - unsigned long dsm_mask; 71 + unsigned long cmd_mask; 72 72 char *provider_name; 73 73 ndctl_fn ndctl; 74 74 int (*flush_probe)(struct nvdimm_bus_descriptor *nd_desc); ··· 130 130 struct nd_blk_region *to_nd_blk_region(struct device *dev); 131 131 struct nvdimm_bus_descriptor *to_nd_desc(struct nvdimm_bus *nvdimm_bus); 132 132 const char *nvdimm_name(struct nvdimm *nvdimm); 133 + unsigned long nvdimm_cmd_mask(struct nvdimm *nvdimm); 133 134 void *nvdimm_provider_data(struct nvdimm *nvdimm); 134 135 struct nvdimm *nvdimm_create(struct nvdimm_bus *nvdimm_bus, void *provider_data, 135 136 const struct attribute_group **groups, unsigned long flags, 136 - unsigned long *dsm_mask); 137 + unsigned long cmd_mask); 137 138 const struct nd_cmd_desc *nd_cmd_dimm_desc(int cmd); 138 139 const struct nd_cmd_desc *nd_cmd_bus_desc(int cmd); 139 140 u32 nd_cmd_in_size(struct nvdimm *nvdimm, int cmd,
+42
include/uapi/linux/ndctl.h
··· 159 159 ND_CMD_VENDOR_EFFECT_LOG_SIZE = 7, 160 160 ND_CMD_VENDOR_EFFECT_LOG = 8, 161 161 ND_CMD_VENDOR = 9, 162 + ND_CMD_CALL = 10, 162 163 }; 163 164 164 165 enum { ··· 193 192 [ND_CMD_VENDOR_EFFECT_LOG_SIZE] = "effect_size", 194 193 [ND_CMD_VENDOR_EFFECT_LOG] = "effect_log", 195 194 [ND_CMD_VENDOR] = "vendor", 195 + [ND_CMD_CALL] = "cmd_call", 196 196 }; 197 197 198 198 if (cmd < ARRAY_SIZE(names) && names[cmd]) ··· 262 260 ARS_STATUS_MASK = 0x0000FFFF, 263 261 ARS_EXT_STATUS_SHIFT = 16, 264 262 }; 263 + 264 + /* 265 + * struct nd_cmd_pkg 266 + * 267 + * is a wrapper to a quasi pass thru interface for invoking firmware 268 + * associated with nvdimms. 269 + * 270 + * INPUT PARAMETERS 271 + * 272 + * nd_family corresponds to the firmware (e.g. DSM) interface. 273 + * 274 + * nd_command are the function index advertised by the firmware. 275 + * 276 + * nd_size_in is the size of the input parameters being passed to firmware 277 + * 278 + * OUTPUT PARAMETERS 279 + * 280 + * nd_fw_size is the size of the data firmware wants to return for 281 + * the call. If nd_fw_size is greater than size of nd_size_out, only 282 + * the first nd_size_out bytes are returned. 283 + */ 284 + 285 + struct nd_cmd_pkg { 286 + __u64 nd_family; /* family of commands */ 287 + __u64 nd_command; 288 + __u32 nd_size_in; /* INPUT: size of input args */ 289 + __u32 nd_size_out; /* INPUT: size of payload */ 290 + __u32 nd_reserved2[9]; /* reserved must be zero */ 291 + __u32 nd_fw_size; /* OUTPUT: size fw wants to return */ 292 + unsigned char nd_payload[]; /* Contents of call */ 293 + }; 294 + 295 + /* These NVDIMM families represent pre-standardization command sets */ 296 + #define NVDIMM_FAMILY_INTEL 0 297 + #define NVDIMM_FAMILY_HPE1 1 298 + #define NVDIMM_FAMILY_HPE2 2 299 + 300 + #define ND_IOCTL_CALL _IOWR(ND_IOCTL, ND_CMD_CALL,\ 301 + struct nd_cmd_pkg) 302 + 265 303 #endif /* __NDCTL_H__ */
+33 -17
tools/testing/nvdimm/test/nfit.c
··· 372 372 { 373 373 struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc); 374 374 struct nfit_test *t = container_of(acpi_desc, typeof(*t), acpi_desc); 375 + unsigned int func = cmd; 375 376 int i, rc = 0, __cmd_rc; 376 377 377 378 if (!cmd_rc) ··· 381 380 382 381 if (nvdimm) { 383 382 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm); 383 + unsigned long cmd_mask = nvdimm_cmd_mask(nvdimm); 384 384 385 - if (!nfit_mem || !test_bit(cmd, &nfit_mem->dsm_mask)) 385 + if (!nfit_mem) 386 + return -ENOTTY; 387 + 388 + if (cmd == ND_CMD_CALL) { 389 + struct nd_cmd_pkg *call_pkg = buf; 390 + 391 + buf_len = call_pkg->nd_size_in + call_pkg->nd_size_out; 392 + buf = (void *) call_pkg->nd_payload; 393 + func = call_pkg->nd_command; 394 + if (call_pkg->nd_family != nfit_mem->family) 395 + return -ENOTTY; 396 + } 397 + 398 + if (!test_bit(cmd, &cmd_mask) 399 + || !test_bit(func, &nfit_mem->dsm_mask)) 386 400 return -ENOTTY; 387 401 388 402 /* lookup label space for the given dimm */ ··· 408 392 if (i >= ARRAY_SIZE(handle)) 409 393 return -ENXIO; 410 394 411 - switch (cmd) { 395 + switch (func) { 412 396 case ND_CMD_GET_CONFIG_SIZE: 413 397 rc = nfit_test_cmd_get_config_size(buf, buf_len); 414 398 break; ··· 432 416 } else { 433 417 struct ars_state *ars_state = &t->ars_state; 434 418 435 - if (!nd_desc || !test_bit(cmd, &nd_desc->dsm_mask)) 419 + if (!nd_desc || !test_bit(cmd, &nd_desc->cmd_mask)) 436 420 return -ENOTTY; 437 421 438 - switch (cmd) { 422 + switch (func) { 439 423 case ND_CMD_ARS_CAP: 440 424 rc = nfit_test_cmd_ars_cap(buf, buf_len); 441 425 break; ··· 1309 1293 post_ars_status(&t->ars_state, t->spa_set_dma[0], SPA0_SIZE); 1310 1294 1311 1295 acpi_desc = &t->acpi_desc; 1312 - set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_dsm_force_en); 1313 - set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en); 1314 - set_bit(ND_CMD_SET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en); 1315 - set_bit(ND_CMD_SMART, &acpi_desc->dimm_dsm_force_en); 1316 - set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_dsm_force_en); 1317 - set_bit(ND_CMD_ARS_START, &acpi_desc->bus_dsm_force_en); 1318 - set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_dsm_force_en); 1319 - set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_dsm_force_en); 1320 - set_bit(ND_CMD_SMART_THRESHOLD, &acpi_desc->dimm_dsm_force_en); 1296 + set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_cmd_force_en); 1297 + set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en); 1298 + set_bit(ND_CMD_SET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en); 1299 + set_bit(ND_CMD_SMART, &acpi_desc->dimm_cmd_force_en); 1300 + set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_cmd_force_en); 1301 + set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en); 1302 + set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en); 1303 + set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en); 1304 + set_bit(ND_CMD_SMART_THRESHOLD, &acpi_desc->dimm_cmd_force_en); 1321 1305 } 1322 1306 1323 1307 static void nfit_test1_setup(struct nfit_test *t) ··· 1375 1359 post_ars_status(&t->ars_state, t->spa_set_dma[0], SPA2_SIZE); 1376 1360 1377 1361 acpi_desc = &t->acpi_desc; 1378 - set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_dsm_force_en); 1379 - set_bit(ND_CMD_ARS_START, &acpi_desc->bus_dsm_force_en); 1380 - set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_dsm_force_en); 1381 - set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_dsm_force_en); 1362 + set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_cmd_force_en); 1363 + set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en); 1364 + set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en); 1365 + set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en); 1382 1366 } 1383 1367 1384 1368 static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa,