mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 19:21:31 -04:00
libnvdimm for 4.8
1/ Replace pcommit with ADR / directed-flushing:
The pcommit instruction, which has not shipped on any product, is
deprecated. Instead, the requirement is that platforms implement either
ADR, or provide one or more flush addresses per nvdimm. ADR
(Asynchronous DRAM Refresh) flushes data in posted write buffers to the
memory controller on a power-fail event. Flush addresses are defined in
ACPI 6.x as an NVDIMM Firmware Interface Table (NFIT) sub-structure:
"Flush Hint Address Structure". A flush hint is an mmio address that
when written and fenced assures that all previous posted writes
targeting a given dimm have been flushed to media.
2/ On-demand ARS (address range scrub):
Linux uses the results of the ACPI ARS commands to track bad blocks
in pmem devices. When latent errors are detected we re-scrub the media
to refresh the bad block list, userspace can also request a re-scrub at
any time.
3/ Support for the Microsoft DSM (device specific method) command format.
4/ Support for EDK2/OVMF virtual disk device memory ranges.
5/ Various fixes and cleanups across the subsystem.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
iQIcBAABAgAGBQJXmXBsAAoJEB7SkWpmfYgCEwwP/1IOt9ocP+iHLMDH9KE7VaTZ
NmUDR+Zy6g5cRQM7SgcuU5BXUcx+OsSrSrUTVF1cW994o9Gbz1mFotkv0ZAsPcYY
ZVRQxo2oqHrssyOcg+PsgKWiXn68rJOCgmpEyzaJywl5qTMst7pzsT1s1f7rSh6h
trCf4VaJJwxZR8fARGtlHUnnhPe2Orp99EZRKEWprAsIv2kPuWpPHSjRjuEgN1JG
KW8AYwWqFTtiLRUk86I4KBB0wcDrfctsjgN9Ogd6+aHyQBRnVSr2U+vDCFkC8KLu
qiDCpYp+yyxBjclnljz7tRRT3GtzfCUWd4v2KVWqgg2IaobUc0Lbukp/rmikUXQP
WLikT2OCQ994eFK5OX3Q3cIU/4j459TQnof8q14yVSpjAKrNUXVSR5puN7Hxa+V7
41wKrAsnsyY1oq+Yd/rMR8VfH7PHx3bFkrmRCGZCufLX1UQm4aYj+sWagDKiV3yA
DiudghbOnhfurfGsnXUVw7y7GKs+gNWNBmB6ndAD6ZEHmKoGUhAEbJDLCc3DnANl
b/2mv1MIdIcC1DlCmnbbcn6fv6bICe/r8poK3VrCK3UgOq/EOvKIWl7giP+k1JuC
6DdVYhlNYIVFXUNSLFAwz8OkLu8byx7WDm36iEqrKHtPw+8qa/2bWVgOU6OBgpjV
cN3edFVIdxvZeMgM5Ubq
=xCBG
-----END PGP SIGNATURE-----
Merge tag 'libnvdimm-for-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm
Pull libnvdimm updates from Dan Williams:
- Replace pcommit with ADR / directed-flushing.
The pcommit instruction, which has not shipped on any product, is
deprecated. Instead, the requirement is that platforms implement
either ADR, or provide one or more flush addresses per nvdimm.
ADR (Asynchronous DRAM Refresh) flushes data in posted write buffers
to the memory controller on a power-fail event.
Flush addresses are defined in ACPI 6.x as an NVDIMM Firmware
Interface Table (NFIT) sub-structure: "Flush Hint Address Structure".
A flush hint is an mmio address that when written and fenced assures
that all previous posted writes targeting a given dimm have been
flushed to media.
- On-demand ARS (address range scrub).
Linux uses the results of the ACPI ARS commands to track bad blocks
in pmem devices. When latent errors are detected we re-scrub the
media to refresh the bad block list, userspace can also request a
re-scrub at any time.
- Support for the Microsoft DSM (device specific method) command
format.
- Support for EDK2/OVMF virtual disk device memory ranges.
- Various fixes and cleanups across the subsystem.
* tag 'libnvdimm-for-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm: (41 commits)
libnvdimm-btt: Delete an unnecessary check before the function call "__nd_device_register"
nfit: do an ARS scrub on hitting a latent media error
nfit: move to nfit/ sub-directory
nfit, libnvdimm: allow an ARS scrub to be triggered on demand
libnvdimm: register nvdimm_bus devices with an nd_bus driver
pmem: clarify a debug print in pmem_clear_poison
x86/insn: remove pcommit
Revert "KVM: x86: add pcommit support"
nfit, tools/testing/nvdimm/: unify shutdown paths
libnvdimm: move ->module to struct nvdimm_bus_descriptor
nfit: cleanup acpi_nfit_init calling convention
nfit: fix _FIT evaluation memory leak + use after free
tools/testing/nvdimm: add manufacturing_{date|location} dimm properties
tools/testing/nvdimm: add virtual ramdisk range
acpi, nfit: treat virtual ramdisk SPA as pmem region
pmem: kill __pmem address space
pmem: kill wmb_pmem()
libnvdimm, pmem: use nvdimm_flush() for namespace I/O writes
fs/dax: remove wmb_pmem()
libnvdimm, pmem: flush posted-write queues on shutdown
...
This commit is contained in:
commit
f0c98ebc57
65 changed files with 1375 additions and 1015 deletions
|
|
@ -454,32 +454,7 @@ config ACPI_REDUCED_HARDWARE_ONLY
|
|||
|
||||
If you are unsure what to do, do not enable this option.
|
||||
|
||||
config ACPI_NFIT
|
||||
tristate "ACPI NVDIMM Firmware Interface Table (NFIT)"
|
||||
depends on PHYS_ADDR_T_64BIT
|
||||
depends on BLK_DEV
|
||||
depends on ARCH_HAS_MMIO_FLUSH
|
||||
select LIBNVDIMM
|
||||
help
|
||||
Infrastructure to probe ACPI 6 compliant platforms for
|
||||
NVDIMMs (NFIT) and register a libnvdimm device tree. In
|
||||
addition to storage devices this also enables libnvdimm to pass
|
||||
ACPI._DSM messages for platform/dimm configuration.
|
||||
|
||||
To compile this driver as a module, choose M here:
|
||||
the module will be called nfit.
|
||||
|
||||
config ACPI_NFIT_DEBUG
|
||||
bool "NFIT DSM debug"
|
||||
depends on ACPI_NFIT
|
||||
depends on DYNAMIC_DEBUG
|
||||
default n
|
||||
help
|
||||
Enabling this option causes the nfit driver to dump the
|
||||
input and output buffers of _DSM operations on the ACPI0012
|
||||
device and its children. This can be very verbose, so leave
|
||||
it disabled unless you are debugging a hardware / firmware
|
||||
issue.
|
||||
source "drivers/acpi/nfit/Kconfig"
|
||||
|
||||
source "drivers/acpi/apei/Kconfig"
|
||||
source "drivers/acpi/dptf/Kconfig"
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o
|
|||
obj-$(CONFIG_ACPI_PROCESSOR) += processor.o
|
||||
obj-$(CONFIG_ACPI) += container.o
|
||||
obj-$(CONFIG_ACPI_THERMAL) += thermal.o
|
||||
obj-$(CONFIG_ACPI_NFIT) += nfit.o
|
||||
obj-$(CONFIG_ACPI_NFIT) += nfit/
|
||||
obj-$(CONFIG_ACPI) += acpi_memhotplug.o
|
||||
obj-$(CONFIG_ACPI_HOTPLUG_IOAPIC) += ioapic.o
|
||||
obj-$(CONFIG_ACPI_BATTERY) += battery.o
|
||||
|
|
|
|||
26
drivers/acpi/nfit/Kconfig
Normal file
26
drivers/acpi/nfit/Kconfig
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
config ACPI_NFIT
|
||||
tristate "ACPI NVDIMM Firmware Interface Table (NFIT)"
|
||||
depends on PHYS_ADDR_T_64BIT
|
||||
depends on BLK_DEV
|
||||
depends on ARCH_HAS_MMIO_FLUSH
|
||||
select LIBNVDIMM
|
||||
help
|
||||
Infrastructure to probe ACPI 6 compliant platforms for
|
||||
NVDIMMs (NFIT) and register a libnvdimm device tree. In
|
||||
addition to storage devices this also enables libnvdimm to pass
|
||||
ACPI._DSM messages for platform/dimm configuration.
|
||||
|
||||
To compile this driver as a module, choose M here:
|
||||
the module will be called nfit.
|
||||
|
||||
config ACPI_NFIT_DEBUG
|
||||
bool "NFIT DSM debug"
|
||||
depends on ACPI_NFIT
|
||||
depends on DYNAMIC_DEBUG
|
||||
default n
|
||||
help
|
||||
Enabling this option causes the nfit driver to dump the
|
||||
input and output buffers of _DSM operations on the ACPI0012
|
||||
device and its children. This can be very verbose, so leave
|
||||
it disabled unless you are debugging a hardware / firmware
|
||||
issue.
|
||||
3
drivers/acpi/nfit/Makefile
Normal file
3
drivers/acpi/nfit/Makefile
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
obj-$(CONFIG_ACPI_NFIT) := nfit.o
|
||||
nfit-y := core.o
|
||||
nfit-$(CONFIG_X86_MCE) += mce.o
|
||||
File diff suppressed because it is too large
Load diff
89
drivers/acpi/nfit/mce.c
Normal file
89
drivers/acpi/nfit/mce.c
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* NFIT - Machine Check Handler
|
||||
*
|
||||
* Copyright(c) 2013-2016 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*/
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <asm/mce.h>
|
||||
#include "nfit.h"
|
||||
|
||||
static int nfit_handle_mce(struct notifier_block *nb, unsigned long val,
|
||||
void *data)
|
||||
{
|
||||
struct mce *mce = (struct mce *)data;
|
||||
struct acpi_nfit_desc *acpi_desc;
|
||||
struct nfit_spa *nfit_spa;
|
||||
|
||||
/* We only care about memory errors */
|
||||
if (!(mce->status & MCACOD))
|
||||
return NOTIFY_DONE;
|
||||
|
||||
/*
|
||||
* mce->addr contains the physical addr accessed that caused the
|
||||
* machine check. We need to walk through the list of NFITs, and see
|
||||
* if any of them matches that address, and only then start a scrub.
|
||||
*/
|
||||
mutex_lock(&acpi_desc_lock);
|
||||
list_for_each_entry(acpi_desc, &acpi_descs, list) {
|
||||
struct device *dev = acpi_desc->dev;
|
||||
int found_match = 0;
|
||||
|
||||
mutex_lock(&acpi_desc->init_mutex);
|
||||
list_for_each_entry(nfit_spa, &acpi_desc->spas, list) {
|
||||
struct acpi_nfit_system_address *spa = nfit_spa->spa;
|
||||
|
||||
if (nfit_spa_type(spa) == NFIT_SPA_PM)
|
||||
continue;
|
||||
/* find the spa that covers the mce addr */
|
||||
if (spa->address > mce->addr)
|
||||
continue;
|
||||
if ((spa->address + spa->length - 1) < mce->addr)
|
||||
continue;
|
||||
found_match = 1;
|
||||
dev_dbg(dev, "%s: addr in SPA %d (0x%llx, 0x%llx)\n",
|
||||
__func__, spa->range_index, spa->address,
|
||||
spa->length);
|
||||
/*
|
||||
* We can break at the first match because we're going
|
||||
* to rescan all the SPA ranges. There shouldn't be any
|
||||
* aliasing anyway.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&acpi_desc->init_mutex);
|
||||
|
||||
/*
|
||||
* We can ignore an -EBUSY here because if an ARS is already
|
||||
* in progress, just let that be the last authoritative one
|
||||
*/
|
||||
if (found_match)
|
||||
acpi_nfit_ars_rescan(acpi_desc);
|
||||
}
|
||||
|
||||
mutex_unlock(&acpi_desc_lock);
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct notifier_block nfit_mce_dec = {
|
||||
.notifier_call = nfit_handle_mce,
|
||||
};
|
||||
|
||||
void nfit_mce_register(void)
|
||||
{
|
||||
mce_register_decode_chain(&nfit_mce_dec);
|
||||
}
|
||||
|
||||
void nfit_mce_unregister(void)
|
||||
{
|
||||
mce_unregister_decode_chain(&nfit_mce_dec);
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
#define __NFIT_H__
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/libnvdimm.h>
|
||||
#include <linux/ndctl.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/uuid.h>
|
||||
#include <linux/acpi.h>
|
||||
|
|
@ -31,6 +32,9 @@
|
|||
#define UUID_NFIT_DIMM_N_HPE1 "9002c334-acf3-4c0e-9642-a235f0d53bc6"
|
||||
#define UUID_NFIT_DIMM_N_HPE2 "5008664b-b758-41a0-a03c-27c2f2d04f7e"
|
||||
|
||||
/* https://msdn.microsoft.com/library/windows/hardware/mt604741 */
|
||||
#define UUID_NFIT_DIMM_N_MSFT "1ee68b36-d4bd-4a1a-9a16-4f8e53d46e05"
|
||||
|
||||
#define ACPI_NFIT_MEM_FAILED_MASK (ACPI_NFIT_MEM_SAVE_FAILED \
|
||||
| ACPI_NFIT_MEM_RESTORE_FAILED | ACPI_NFIT_MEM_FLUSH_FAILED \
|
||||
| ACPI_NFIT_MEM_NOT_ARMED)
|
||||
|
|
@ -40,6 +44,7 @@ enum nfit_uuids {
|
|||
NFIT_DEV_DIMM = NVDIMM_FAMILY_INTEL,
|
||||
NFIT_DEV_DIMM_N_HPE1 = NVDIMM_FAMILY_HPE1,
|
||||
NFIT_DEV_DIMM_N_HPE2 = NVDIMM_FAMILY_HPE2,
|
||||
NFIT_DEV_DIMM_N_MSFT = NVDIMM_FAMILY_MSFT,
|
||||
NFIT_SPA_VOLATILE,
|
||||
NFIT_SPA_PM,
|
||||
NFIT_SPA_DCR,
|
||||
|
|
@ -74,37 +79,37 @@ enum {
|
|||
};
|
||||
|
||||
struct nfit_spa {
|
||||
struct acpi_nfit_system_address *spa;
|
||||
struct list_head list;
|
||||
struct nd_region *nd_region;
|
||||
unsigned int ars_done:1;
|
||||
unsigned int ars_required:1;
|
||||
u32 clear_err_unit;
|
||||
u32 max_ars;
|
||||
struct acpi_nfit_system_address spa[0];
|
||||
};
|
||||
|
||||
struct nfit_dcr {
|
||||
struct acpi_nfit_control_region *dcr;
|
||||
struct list_head list;
|
||||
struct acpi_nfit_control_region dcr[0];
|
||||
};
|
||||
|
||||
struct nfit_bdw {
|
||||
struct acpi_nfit_data_region *bdw;
|
||||
struct list_head list;
|
||||
struct acpi_nfit_data_region bdw[0];
|
||||
};
|
||||
|
||||
struct nfit_idt {
|
||||
struct acpi_nfit_interleave *idt;
|
||||
struct list_head list;
|
||||
struct acpi_nfit_interleave idt[0];
|
||||
};
|
||||
|
||||
struct nfit_flush {
|
||||
struct acpi_nfit_flush_address *flush;
|
||||
struct list_head list;
|
||||
struct acpi_nfit_flush_address flush[0];
|
||||
};
|
||||
|
||||
struct nfit_memdev {
|
||||
struct acpi_nfit_memory_map *memdev;
|
||||
struct list_head list;
|
||||
struct acpi_nfit_memory_map memdev[0];
|
||||
};
|
||||
|
||||
/* assembled tables for a given dimm/memory-device */
|
||||
|
|
@ -123,6 +128,7 @@ struct nfit_mem {
|
|||
struct list_head list;
|
||||
struct acpi_device *adev;
|
||||
struct acpi_nfit_desc *acpi_desc;
|
||||
struct resource *flush_wpq;
|
||||
unsigned long dsm_mask;
|
||||
int family;
|
||||
};
|
||||
|
|
@ -130,10 +136,7 @@ struct nfit_mem {
|
|||
struct acpi_nfit_desc {
|
||||
struct nvdimm_bus_descriptor nd_desc;
|
||||
struct acpi_table_header acpi_header;
|
||||
struct acpi_nfit_header *nfit;
|
||||
struct mutex spa_map_mutex;
|
||||
struct mutex init_mutex;
|
||||
struct list_head spa_maps;
|
||||
struct list_head memdevs;
|
||||
struct list_head flushes;
|
||||
struct list_head dimms;
|
||||
|
|
@ -146,6 +149,9 @@ struct acpi_nfit_desc {
|
|||
struct nd_cmd_ars_status *ars_status;
|
||||
size_t ars_status_size;
|
||||
struct work_struct work;
|
||||
struct list_head list;
|
||||
struct kernfs_node *scrub_count_state;
|
||||
unsigned int scrub_count;
|
||||
unsigned int cancel:1;
|
||||
unsigned long dimm_cmd_force_en;
|
||||
unsigned long bus_cmd_force_en;
|
||||
|
|
@ -161,7 +167,7 @@ enum nd_blk_mmio_selector {
|
|||
struct nd_blk_addr {
|
||||
union {
|
||||
void __iomem *base;
|
||||
void __pmem *aperture;
|
||||
void *aperture;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -180,28 +186,26 @@ struct nfit_blk {
|
|||
u64 bdw_offset; /* post interleave offset */
|
||||
u64 stat_offset;
|
||||
u64 cmd_offset;
|
||||
void __iomem *nvdimm_flush;
|
||||
u32 dimm_flags;
|
||||
};
|
||||
|
||||
enum spa_map_type {
|
||||
SPA_MAP_CONTROL,
|
||||
SPA_MAP_APERTURE,
|
||||
};
|
||||
extern struct list_head acpi_descs;
|
||||
extern struct mutex acpi_desc_lock;
|
||||
int acpi_nfit_ars_rescan(struct acpi_nfit_desc *acpi_desc);
|
||||
|
||||
struct nfit_spa_mapping {
|
||||
struct acpi_nfit_desc *acpi_desc;
|
||||
struct acpi_nfit_system_address *spa;
|
||||
struct list_head list;
|
||||
struct kref kref;
|
||||
enum spa_map_type type;
|
||||
struct nd_blk_addr addr;
|
||||
};
|
||||
|
||||
static inline struct nfit_spa_mapping *to_spa_map(struct kref *kref)
|
||||
#ifdef CONFIG_X86_MCE
|
||||
void nfit_mce_register(void);
|
||||
void nfit_mce_unregister(void);
|
||||
#else
|
||||
static inline void nfit_mce_register(void)
|
||||
{
|
||||
return container_of(kref, struct nfit_spa_mapping, kref);
|
||||
}
|
||||
static inline void nfit_mce_unregister(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
int nfit_spa_type(struct acpi_nfit_system_address *spa);
|
||||
|
||||
static inline struct acpi_nfit_memory_map *__to_nfit_memdev(
|
||||
struct nfit_mem *nfit_mem)
|
||||
|
|
@ -218,6 +222,6 @@ static inline struct acpi_nfit_desc *to_acpi_desc(
|
|||
}
|
||||
|
||||
const u8 *to_nfit_uuid(enum nfit_uuids id);
|
||||
int acpi_nfit_init(struct acpi_nfit_desc *nfit, acpi_size sz);
|
||||
int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, void *nfit, acpi_size sz);
|
||||
void acpi_nfit_desc_init(struct acpi_nfit_desc *acpi_desc, struct device *dev);
|
||||
#endif /* __NFIT_H__ */
|
||||
Loading…
Reference in a new issue