Starting with ACPI 6.1 an NFIT table will report multiple 'NVDIMM Control Region Structure' instances per-dimm, one for each supported format interface. Report that code in the following format in sysfs: nmemX/nfit/formats nmemX/nfit/format nmemX/nfit/format1 nmemX/nfit/format2 ... nmemX/nfit/formatN Where format2 - formatN are theoretical as there are no known DIMMs with support for more than two interface formats. This layout is compatible with existing libndctl binaries that only expect one code per-dimm as they will ignore nmemX/nfit/formats and nmemX/nfit/formatN.
Unified · Split
| @@ -655,6 +655,7 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc, · 654 unmodified lines | |||
| 655 | if (!nfit_mem) | 655 | if (!nfit_mem) |
| 656 | return -ENOMEM; | 656 | return -ENOMEM; |
| 657 | INIT_LIST_HEAD(&nfit_mem->list); | 657 | INIT_LIST_HEAD(&nfit_mem->list); |
| 658 | nfit_mem->acpi_desc = acpi_desc; | ||
| 658 | list_add(&nfit_mem->list, &acpi_desc->dimms); | 659 | list_add(&nfit_mem->list, &acpi_desc->dimms); |
| 659 | } | 660 | } |
| 660 | 661 | ||
| @@ -838,6 +839,18 @@ static ssize_t device_show(struct device *dev, · 177 unmodified lines | |||
| 838 | } | 839 | } |
| 839 | static DEVICE_ATTR_RO(device); | 840 | static DEVICE_ATTR_RO(device); |
| 840 | 841 | ||
| 842 | static int num_nvdimm_formats(struct nvdimm *nvdimm) | ||
| 843 | { | ||
| 844 | struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm); | ||
| 845 | int formats = 0; | ||
| 846 | |||
| 847 | if (nfit_mem->memdev_pmem) | ||
| 848 | formats++; | ||
| 849 | if (nfit_mem->memdev_bdw) | ||
| 850 | formats++; | ||
| 851 | return formats; | ||
| 852 | } | ||
| 853 | |||
| 841 | static ssize_t format_show(struct device *dev, | 854 | static ssize_t format_show(struct device *dev, |
| 842 | struct device_attribute *attr, char *buf) | 855 | struct device_attribute *attr, char *buf) |
| 843 | { | 856 | { |
| @@ -847,6 +860,55 @@ static ssize_t format_show(struct device *dev, · 3 unmodified lines | |||
| 847 | } | 860 | } |
| 848 | static DEVICE_ATTR_RO(format); | 861 | static DEVICE_ATTR_RO(format); |
| 849 | 862 | ||
| 863 | static ssize_t format1_show(struct device *dev, | ||
| 864 | struct device_attribute *attr, char *buf) | ||
| 865 | { | ||
| 866 | u32 handle; | ||
| 867 | ssize_t rc = -ENXIO; | ||
| 868 | struct nfit_mem *nfit_mem; | ||
| 869 | struct nfit_memdev *nfit_memdev; | ||
| 870 | struct acpi_nfit_desc *acpi_desc; | ||
| 871 | struct nvdimm *nvdimm = to_nvdimm(dev); | ||
| 872 | struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev); | ||
| 873 | |||
| 874 | nfit_mem = nvdimm_provider_data(nvdimm); | ||
| 875 | acpi_desc = nfit_mem->acpi_desc; | ||
| 876 | handle = to_nfit_memdev(dev)->device_handle; | ||
| 877 | |||
| 878 | /* assumes DIMMs have at most 2 published interface codes */ | ||
| 879 | mutex_lock(&acpi_desc->init_mutex); | ||
| 880 | list_for_each_entry(nfit_memdev, &acpi_desc->memdevs, list) { | ||
| 881 | struct acpi_nfit_memory_map *memdev = nfit_memdev->memdev; | ||
| 882 | struct nfit_dcr *nfit_dcr; | ||
| 883 | |||
| 884 | if (memdev->device_handle != handle) | ||
| 885 | continue; | ||
| 886 | |||
| 887 | list_for_each_entry(nfit_dcr, &acpi_desc->dcrs, list) { | ||
| 888 | if (nfit_dcr->dcr->region_index != memdev->region_index) | ||
| 889 | continue; | ||
| 890 | if (nfit_dcr->dcr->code == dcr->code) | ||
| 891 | continue; | ||
| 892 | rc = sprintf(buf, "%#x\n", nfit_dcr->dcr->code); | ||
| 893 | break; | ||
| 894 | } | ||
| 895 | if (rc != ENXIO) | ||
| 896 | break; | ||
| 897 | } | ||
| 898 | mutex_unlock(&acpi_desc->init_mutex); | ||
| 899 | return rc; | ||
| 900 | } | ||
| 901 | static DEVICE_ATTR_RO(format1); | ||
| 902 | |||
| 903 | static ssize_t formats_show(struct device *dev, | ||
| 904 | struct device_attribute *attr, char *buf) | ||
| 905 | { | ||
| 906 | struct nvdimm *nvdimm = to_nvdimm(dev); | ||
| 907 | |||
| 908 | return sprintf(buf, "%d\n", num_nvdimm_formats(nvdimm)); | ||
| 909 | } | ||
| 910 | static DEVICE_ATTR_RO(formats); | ||
| 911 | |||
| 850 | static ssize_t serial_show(struct device *dev, | 912 | static ssize_t serial_show(struct device *dev, |
| 851 | struct device_attribute *attr, char *buf) | 913 | struct device_attribute *attr, char *buf) |
| 852 | { | 914 | { |
| @@ -876,6 +938,8 @@ static struct attribute *acpi_nfit_dimm_attributes[] = { · 23 unmodified lines | |||
| 876 | &dev_attr_vendor.attr, | 938 | &dev_attr_vendor.attr, |
| 877 | &dev_attr_device.attr, | 939 | &dev_attr_device.attr, |
| 878 | &dev_attr_format.attr, | 940 | &dev_attr_format.attr, |
| 941 | &dev_attr_formats.attr, | ||
| 942 | &dev_attr_format1.attr, | ||
| 879 | &dev_attr_serial.attr, | 943 | &dev_attr_serial.attr, |
| 880 | &dev_attr_rev_id.attr, | 944 | &dev_attr_rev_id.attr, |
| 881 | &dev_attr_flags.attr, | 945 | &dev_attr_flags.attr, |
| @@ -886,11 +950,13 @@ static umode_t acpi_nfit_dimm_attr_visible(struct kobject *kobj, · 4 unmodified lines | |||
| 886 | struct attribute *a, int n) | 950 | struct attribute *a, int n) |
| 887 | { | 951 | { |
| 888 | struct device *dev = container_of(kobj, struct device, kobj); | 952 | struct device *dev = container_of(kobj, struct device, kobj); |
| 953 | struct nvdimm *nvdimm = to_nvdimm(dev); | ||
| 889 | 954 | ||
| 890 | if (to_nfit_dcr(dev)) | 955 | if (!to_nfit_dcr(dev)) |
| 891 | return a->mode; | 956 | return 0; |
| 892 | else | 957 | if (a == &dev_attr_format1.attr && num_nvdimm_formats(nvdimm) <= 1) |
| 893 | return 0; | 958 | return 0; |
| 959 | return a->mode; | ||
| 894 | } | 960 | } |
| 895 | 961 | ||
| 896 | static struct attribute_group acpi_nfit_dimm_attribute_group = { | 962 | static struct attribute_group acpi_nfit_dimm_attribute_group = { |
| @@ -109,6 +109,7 @@ struct nfit_mem { · 108 unmodified lines | |||
| 109 | struct nfit_flush *nfit_flush; | 109 | struct nfit_flush *nfit_flush; |
| 110 | struct list_head list; | 110 | struct list_head list; |
| 111 | struct acpi_device *adev; | 111 | struct acpi_device *adev; |
| 112 | struct acpi_nfit_desc *acpi_desc; | ||
| 112 | unsigned long dsm_mask; | 113 | unsigned long dsm_mask; |
| 113 | }; | 114 | }; |
| 114 | 115 | ||