Commit b75dba7f authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'libnvdimm-fixes-5.11-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm

Pull libnvdimm fixes from Dan Williams:
 "A fix for a crash scenario that has been present since the initial
  merge, a minor regression in sysfs attribute visibility, and a fix for
  some flexible array warnings.

  The bulk of this pull is an update to the libnvdimm unit test
  infrastructure to test non-ACPI platforms. Given there is zero
  regression risk for test updates, and the tests enable validation of
  bits headed towards the next merge window, I saw no reason to hold the
  new tests back. Santosh originally submitted this before the v5.11
  window opened.

  Summary:

   - Fix a crash when sysfs accesses race 'dimm' driver probe/remove.

   - Fix a regression in 'resource' attribute visibility necessary for
     mapping badblocks and other physical address interrogations.

   - Fix some flexible array warnings

   - Expand the unit test infrastructure for non-ACPI platforms"

* tag 'libnvdimm-fixes-5.11-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm:
  libnvdimm/dimm: Avoid race between probe and available_slots_show()
  ndtest: Add papr health related flags
  ndtest: Add nvdimm control functions
  ndtest: Add regions and mappings to the test buses
  ndtest: Add dimm attributes
  ndtest: Add dimms to the two buses
  ndtest: Add compatability string to treat it as PAPR family
  testing/nvdimm: Add test module for non-nfit platforms
  libnvdimm/namespace: Fix visibility of namespace resource attribute
  libnvdimm/pmem: Remove unused header
  ACPI: NFIT: Fix flexible_array.cocci warnings
parents ff92acb2 7018c897
...@@ -2269,40 +2269,24 @@ static const struct attribute_group *acpi_nfit_region_attribute_groups[] = { ...@@ -2269,40 +2269,24 @@ static const struct attribute_group *acpi_nfit_region_attribute_groups[] = {
/* enough info to uniquely specify an interleave set */ /* enough info to uniquely specify an interleave set */
struct nfit_set_info { struct nfit_set_info {
struct nfit_set_info_map { u64 region_offset;
u64 region_offset; u32 serial_number;
u32 serial_number; u32 pad;
u32 pad;
} mapping[0];
}; };
struct nfit_set_info2 { struct nfit_set_info2 {
struct nfit_set_info_map2 { u64 region_offset;
u64 region_offset; u32 serial_number;
u32 serial_number; u16 vendor_id;
u16 vendor_id; u16 manufacturing_date;
u16 manufacturing_date; u8 manufacturing_location;
u8 manufacturing_location; u8 reserved[31];
u8 reserved[31];
} mapping[0];
}; };
static size_t sizeof_nfit_set_info(int num_mappings)
{
return sizeof(struct nfit_set_info)
+ num_mappings * sizeof(struct nfit_set_info_map);
}
static size_t sizeof_nfit_set_info2(int num_mappings)
{
return sizeof(struct nfit_set_info2)
+ num_mappings * sizeof(struct nfit_set_info_map2);
}
static int cmp_map_compat(const void *m0, const void *m1) static int cmp_map_compat(const void *m0, const void *m1)
{ {
const struct nfit_set_info_map *map0 = m0; const struct nfit_set_info *map0 = m0;
const struct nfit_set_info_map *map1 = m1; const struct nfit_set_info *map1 = m1;
return memcmp(&map0->region_offset, &map1->region_offset, return memcmp(&map0->region_offset, &map1->region_offset,
sizeof(u64)); sizeof(u64));
...@@ -2310,8 +2294,8 @@ static int cmp_map_compat(const void *m0, const void *m1) ...@@ -2310,8 +2294,8 @@ static int cmp_map_compat(const void *m0, const void *m1)
static int cmp_map(const void *m0, const void *m1) static int cmp_map(const void *m0, const void *m1)
{ {
const struct nfit_set_info_map *map0 = m0; const struct nfit_set_info *map0 = m0;
const struct nfit_set_info_map *map1 = m1; const struct nfit_set_info *map1 = m1;
if (map0->region_offset < map1->region_offset) if (map0->region_offset < map1->region_offset)
return -1; return -1;
...@@ -2322,8 +2306,8 @@ static int cmp_map(const void *m0, const void *m1) ...@@ -2322,8 +2306,8 @@ static int cmp_map(const void *m0, const void *m1)
static int cmp_map2(const void *m0, const void *m1) static int cmp_map2(const void *m0, const void *m1)
{ {
const struct nfit_set_info_map2 *map0 = m0; const struct nfit_set_info2 *map0 = m0;
const struct nfit_set_info_map2 *map1 = m1; const struct nfit_set_info2 *map1 = m1;
if (map0->region_offset < map1->region_offset) if (map0->region_offset < map1->region_offset)
return -1; return -1;
...@@ -2361,22 +2345,22 @@ static int acpi_nfit_init_interleave_set(struct acpi_nfit_desc *acpi_desc, ...@@ -2361,22 +2345,22 @@ static int acpi_nfit_init_interleave_set(struct acpi_nfit_desc *acpi_desc,
return -ENOMEM; return -ENOMEM;
import_guid(&nd_set->type_guid, spa->range_guid); import_guid(&nd_set->type_guid, spa->range_guid);
info = devm_kzalloc(dev, sizeof_nfit_set_info(nr), GFP_KERNEL); info = devm_kcalloc(dev, nr, sizeof(*info), GFP_KERNEL);
if (!info) if (!info)
return -ENOMEM; return -ENOMEM;
info2 = devm_kzalloc(dev, sizeof_nfit_set_info2(nr), GFP_KERNEL); info2 = devm_kcalloc(dev, nr, sizeof(*info2), GFP_KERNEL);
if (!info2) if (!info2)
return -ENOMEM; return -ENOMEM;
for (i = 0; i < nr; i++) { for (i = 0; i < nr; i++) {
struct nd_mapping_desc *mapping = &ndr_desc->mapping[i]; struct nd_mapping_desc *mapping = &ndr_desc->mapping[i];
struct nfit_set_info_map *map = &info->mapping[i];
struct nfit_set_info_map2 *map2 = &info2->mapping[i];
struct nvdimm *nvdimm = mapping->nvdimm; struct nvdimm *nvdimm = mapping->nvdimm;
struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm); struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
struct acpi_nfit_memory_map *memdev = memdev_from_spa(acpi_desc, struct nfit_set_info *map = &info[i];
spa->range_index, i); struct nfit_set_info2 *map2 = &info2[i];
struct acpi_nfit_memory_map *memdev =
memdev_from_spa(acpi_desc, spa->range_index, i);
struct acpi_nfit_control_region *dcr = nfit_mem->dcr; struct acpi_nfit_control_region *dcr = nfit_mem->dcr;
if (!memdev || !nfit_mem->dcr) { if (!memdev || !nfit_mem->dcr) {
...@@ -2395,23 +2379,20 @@ static int acpi_nfit_init_interleave_set(struct acpi_nfit_desc *acpi_desc, ...@@ -2395,23 +2379,20 @@ static int acpi_nfit_init_interleave_set(struct acpi_nfit_desc *acpi_desc,
} }
/* v1.1 namespaces */ /* v1.1 namespaces */
sort(&info->mapping[0], nr, sizeof(struct nfit_set_info_map), sort(info, nr, sizeof(*info), cmp_map, NULL);
cmp_map, NULL); nd_set->cookie1 = nd_fletcher64(info, sizeof(*info) * nr, 0);
nd_set->cookie1 = nd_fletcher64(info, sizeof_nfit_set_info(nr), 0);
/* v1.2 namespaces */ /* v1.2 namespaces */
sort(&info2->mapping[0], nr, sizeof(struct nfit_set_info_map2), sort(info2, nr, sizeof(*info2), cmp_map2, NULL);
cmp_map2, NULL); nd_set->cookie2 = nd_fletcher64(info2, sizeof(*info2) * nr, 0);
nd_set->cookie2 = nd_fletcher64(info2, sizeof_nfit_set_info2(nr), 0);
/* support v1.1 namespaces created with the wrong sort order */ /* support v1.1 namespaces created with the wrong sort order */
sort(&info->mapping[0], nr, sizeof(struct nfit_set_info_map), sort(info, nr, sizeof(*info), cmp_map_compat, NULL);
cmp_map_compat, NULL); nd_set->altcookie = nd_fletcher64(info, sizeof(*info) * nr, 0);
nd_set->altcookie = nd_fletcher64(info, sizeof_nfit_set_info(nr), 0);
/* record the result of the sort for the mapping position */ /* record the result of the sort for the mapping position */
for (i = 0; i < nr; i++) { for (i = 0; i < nr; i++) {
struct nfit_set_info_map2 *map2 = &info2->mapping[i]; struct nfit_set_info2 *map2 = &info2[i];
int j; int j;
for (j = 0; j < nr; j++) { for (j = 0; j < nr; j++) {
......
...@@ -335,16 +335,16 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr, ...@@ -335,16 +335,16 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr,
} }
static DEVICE_ATTR_RO(state); static DEVICE_ATTR_RO(state);
static ssize_t available_slots_show(struct device *dev, static ssize_t __available_slots_show(struct nvdimm_drvdata *ndd, char *buf)
struct device_attribute *attr, char *buf)
{ {
struct nvdimm_drvdata *ndd = dev_get_drvdata(dev); struct device *dev;
ssize_t rc; ssize_t rc;
u32 nfree; u32 nfree;
if (!ndd) if (!ndd)
return -ENXIO; return -ENXIO;
dev = ndd->dev;
nvdimm_bus_lock(dev); nvdimm_bus_lock(dev);
nfree = nd_label_nfree(ndd); nfree = nd_label_nfree(ndd);
if (nfree - 1 > nfree) { if (nfree - 1 > nfree) {
...@@ -356,6 +356,18 @@ static ssize_t available_slots_show(struct device *dev, ...@@ -356,6 +356,18 @@ static ssize_t available_slots_show(struct device *dev,
nvdimm_bus_unlock(dev); nvdimm_bus_unlock(dev);
return rc; return rc;
} }
static ssize_t available_slots_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t rc;
nd_device_lock(dev);
rc = __available_slots_show(dev_get_drvdata(dev), buf);
nd_device_unlock(dev);
return rc;
}
static DEVICE_ATTR_RO(available_slots); static DEVICE_ATTR_RO(available_slots);
__weak ssize_t security_show(struct device *dev, __weak ssize_t security_show(struct device *dev,
......
...@@ -1635,11 +1635,11 @@ static umode_t namespace_visible(struct kobject *kobj, ...@@ -1635,11 +1635,11 @@ static umode_t namespace_visible(struct kobject *kobj,
return a->mode; return a->mode;
} }
if (a == &dev_attr_nstype.attr || a == &dev_attr_size.attr /* base is_namespace_io() attributes */
|| a == &dev_attr_holder.attr if (a == &dev_attr_nstype.attr || a == &dev_attr_size.attr ||
|| a == &dev_attr_holder_class.attr a == &dev_attr_holder.attr || a == &dev_attr_holder_class.attr ||
|| a == &dev_attr_force_raw.attr a == &dev_attr_force_raw.attr || a == &dev_attr_mode.attr ||
|| a == &dev_attr_mode.attr) a == &dev_attr_resource.attr)
return a->mode; return a->mode;
return 0; return 0;
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#include <linux/uio.h> #include <linux/uio.h>
#include <linux/dax.h> #include <linux/dax.h>
#include <linux/nd.h> #include <linux/nd.h>
#include <linux/backing-dev.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include "pmem.h" #include "pmem.h"
......
...@@ -12,7 +12,8 @@ void check(void) ...@@ -12,7 +12,8 @@ void check(void)
BUILD_BUG_ON(!IS_MODULE(CONFIG_ND_BTT)); BUILD_BUG_ON(!IS_MODULE(CONFIG_ND_BTT));
BUILD_BUG_ON(!IS_MODULE(CONFIG_ND_PFN)); BUILD_BUG_ON(!IS_MODULE(CONFIG_ND_PFN));
BUILD_BUG_ON(!IS_MODULE(CONFIG_ND_BLK)); BUILD_BUG_ON(!IS_MODULE(CONFIG_ND_BLK));
BUILD_BUG_ON(!IS_MODULE(CONFIG_ACPI_NFIT)); if (IS_ENABLED(CONFIG_ACPI_NFIT))
BUILD_BUG_ON(!IS_MODULE(CONFIG_ACPI_NFIT));
BUILD_BUG_ON(!IS_MODULE(CONFIG_DEV_DAX)); BUILD_BUG_ON(!IS_MODULE(CONFIG_DEV_DAX));
BUILD_BUG_ON(!IS_MODULE(CONFIG_DEV_DAX_PMEM)); BUILD_BUG_ON(!IS_MODULE(CONFIG_DEV_DAX_PMEM));
} }
...@@ -5,5 +5,9 @@ ccflags-y += -I$(srctree)/drivers/acpi/nfit/ ...@@ -5,5 +5,9 @@ ccflags-y += -I$(srctree)/drivers/acpi/nfit/
obj-m += nfit_test.o obj-m += nfit_test.o
obj-m += nfit_test_iomap.o obj-m += nfit_test_iomap.o
nfit_test-y := nfit.o ifeq ($(CONFIG_ACPI_NFIT),m)
nfit_test-y := nfit.o
else
nfit_test-y := ndtest.o
endif
nfit_test_iomap-y := iomap.o nfit_test_iomap-y := iomap.o
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef NDTEST_H
#define NDTEST_H
#include <linux/platform_device.h>
#include <linux/libnvdimm.h>
/* SCM device is unable to persist memory contents */
#define PAPR_PMEM_UNARMED (1ULL << (63 - 0))
/* SCM device failed to persist memory contents */
#define PAPR_PMEM_SHUTDOWN_DIRTY (1ULL << (63 - 1))
/* SCM device contents are not persisted from previous IPL */
#define PAPR_PMEM_EMPTY (1ULL << (63 - 3))
#define PAPR_PMEM_HEALTH_CRITICAL (1ULL << (63 - 4))
/* SCM device will be garded off next IPL due to failure */
#define PAPR_PMEM_HEALTH_FATAL (1ULL << (63 - 5))
/* SCM contents cannot persist due to current platform health status */
#define PAPR_PMEM_HEALTH_UNHEALTHY (1ULL << (63 - 6))
/* Bits status indicators for health bitmap indicating unarmed dimm */
#define PAPR_PMEM_UNARMED_MASK (PAPR_PMEM_UNARMED | \
PAPR_PMEM_HEALTH_UNHEALTHY)
#define PAPR_PMEM_SAVE_FAILED (1ULL << (63 - 10))
/* Bits status indicators for health bitmap indicating unflushed dimm */
#define PAPR_PMEM_BAD_SHUTDOWN_MASK (PAPR_PMEM_SHUTDOWN_DIRTY)
/* Bits status indicators for health bitmap indicating unrestored dimm */
#define PAPR_PMEM_BAD_RESTORE_MASK (PAPR_PMEM_EMPTY)
/* Bit status indicators for smart event notification */
#define PAPR_PMEM_SMART_EVENT_MASK (PAPR_PMEM_HEALTH_CRITICAL | \
PAPR_PMEM_HEALTH_FATAL | \
PAPR_PMEM_HEALTH_UNHEALTHY)
#define PAPR_PMEM_SAVE_MASK (PAPR_PMEM_SAVE_FAILED)
struct ndtest_config;
struct ndtest_priv {
struct platform_device pdev;
struct device_node *dn;
struct list_head resources;
struct nvdimm_bus_descriptor bus_desc;
struct nvdimm_bus *bus;
struct ndtest_config *config;
dma_addr_t *dcr_dma;
dma_addr_t *label_dma;
dma_addr_t *dimm_dma;
};
struct ndtest_blk_mmio {
void __iomem *base;
u64 size;
u64 base_offset;
u32 line_size;
u32 num_lines;
u32 table_size;
};
struct ndtest_dimm {
struct device *dev;
struct nvdimm *nvdimm;
struct ndtest_blk_mmio *mmio;
struct nd_region *blk_region;
dma_addr_t address;
unsigned long long flags;
unsigned long config_size;
void *label_area;
char *uuid_str;
unsigned int size;
unsigned int handle;
unsigned int fail_cmd;
unsigned int physical_id;
unsigned int num_formats;
int id;
int fail_cmd_code;
u8 no_alias;
};
struct ndtest_mapping {
u64 start;
u64 size;
u8 position;
u8 dimm;
};
struct ndtest_region {
struct nd_region *region;
struct ndtest_mapping *mapping;
u64 size;
u8 type;
u8 num_mappings;
u8 range_index;
};
struct ndtest_config {
struct ndtest_dimm *dimms;
struct ndtest_region *regions;
unsigned int dimm_count;
unsigned int dimm_start;
u8 num_regions;
};
#endif /* NDTEST_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment