25
25
#include <asm/cacheflush.h>
26
26
#include <acpi/nfit.h>
27
27
#include "nfit.h"
28
+ #include "intel.h"
28
29
29
30
/*
30
31
* For readq() and writeq() on 32-bit builds, the hi-lo, lo-hi order is
@@ -1551,7 +1552,12 @@ static DEVICE_ATTR_RO(dsm_mask);
1551
1552
static ssize_t flags_show (struct device * dev ,
1552
1553
struct device_attribute * attr , char * buf )
1553
1554
{
1554
- u16 flags = to_nfit_memdev (dev )-> flags ;
1555
+ struct nvdimm * nvdimm = to_nvdimm (dev );
1556
+ struct nfit_mem * nfit_mem = nvdimm_provider_data (nvdimm );
1557
+ u16 flags = __to_nfit_memdev (nfit_mem )-> flags ;
1558
+
1559
+ if (test_bit (NFIT_MEM_DIRTY , & nfit_mem -> flags ))
1560
+ flags |= ACPI_NFIT_MEM_FLUSH_FAILED ;
1555
1561
1556
1562
return sprintf (buf , "%s%s%s%s%s%s%s\n" ,
1557
1563
flags & ACPI_NFIT_MEM_SAVE_FAILED ? "save_fail " : "" ,
@@ -1582,6 +1588,16 @@ static ssize_t id_show(struct device *dev,
1582
1588
}
1583
1589
static DEVICE_ATTR_RO (id );
1584
1590
1591
+ static ssize_t dirty_shutdown_show (struct device * dev ,
1592
+ struct device_attribute * attr , char * buf )
1593
+ {
1594
+ struct nvdimm * nvdimm = to_nvdimm (dev );
1595
+ struct nfit_mem * nfit_mem = nvdimm_provider_data (nvdimm );
1596
+
1597
+ return sprintf (buf , "%d\n" , nfit_mem -> dirty_shutdown );
1598
+ }
1599
+ static DEVICE_ATTR_RO (dirty_shutdown );
1600
+
1585
1601
static struct attribute * acpi_nfit_dimm_attributes [] = {
1586
1602
& dev_attr_handle .attr ,
1587
1603
& dev_attr_phys_id .attr ,
@@ -1599,6 +1615,7 @@ static struct attribute *acpi_nfit_dimm_attributes[] = {
1599
1615
& dev_attr_id .attr ,
1600
1616
& dev_attr_family .attr ,
1601
1617
& dev_attr_dsm_mask .attr ,
1618
+ & dev_attr_dirty_shutdown .attr ,
1602
1619
NULL ,
1603
1620
};
1604
1621
@@ -1607,6 +1624,7 @@ static umode_t acpi_nfit_dimm_attr_visible(struct kobject *kobj,
1607
1624
{
1608
1625
struct device * dev = container_of (kobj , struct device , kobj );
1609
1626
struct nvdimm * nvdimm = to_nvdimm (dev );
1627
+ struct nfit_mem * nfit_mem = nvdimm_provider_data (nvdimm );
1610
1628
1611
1629
if (!to_nfit_dcr (dev )) {
1612
1630
/* Without a dcr only the memdev attributes can be surfaced */
@@ -1620,6 +1638,11 @@ static umode_t acpi_nfit_dimm_attr_visible(struct kobject *kobj,
1620
1638
1621
1639
if (a == & dev_attr_format1 .attr && num_nvdimm_formats (nvdimm ) <= 1 )
1622
1640
return 0 ;
1641
+
1642
+ if (!test_bit (NFIT_MEM_DIRTY_COUNT , & nfit_mem -> flags )
1643
+ && a == & dev_attr_dirty_shutdown .attr )
1644
+ return 0 ;
1645
+
1623
1646
return a -> mode ;
1624
1647
}
1625
1648
@@ -1698,6 +1721,56 @@ static bool acpi_nvdimm_has_method(struct acpi_device *adev, char *method)
1698
1721
return false;
1699
1722
}
1700
1723
1724
+ static void nfit_intel_shutdown_status (struct nfit_mem * nfit_mem )
1725
+ {
1726
+ struct nd_intel_smart smart = { 0 };
1727
+ union acpi_object in_buf = {
1728
+ .type = ACPI_TYPE_BUFFER ,
1729
+ .buffer .pointer = (char * ) & smart ,
1730
+ .buffer .length = sizeof (smart ),
1731
+ };
1732
+ union acpi_object in_obj = {
1733
+ .type = ACPI_TYPE_PACKAGE ,
1734
+ .package .count = 1 ,
1735
+ .package .elements = & in_buf ,
1736
+ };
1737
+ const u8 func = ND_INTEL_SMART ;
1738
+ const guid_t * guid = to_nfit_uuid (nfit_mem -> family );
1739
+ u8 revid = nfit_dsm_revid (nfit_mem -> family , func );
1740
+ struct acpi_device * adev = nfit_mem -> adev ;
1741
+ acpi_handle handle = adev -> handle ;
1742
+ union acpi_object * out_obj ;
1743
+
1744
+ if ((nfit_mem -> dsm_mask & (1 << func )) == 0 )
1745
+ return ;
1746
+
1747
+ out_obj = acpi_evaluate_dsm (handle , guid , revid , func , & in_obj );
1748
+ if (!out_obj )
1749
+ return ;
1750
+
1751
+ if (smart .flags & ND_INTEL_SMART_SHUTDOWN_VALID ) {
1752
+ if (smart .shutdown_state )
1753
+ set_bit (NFIT_MEM_DIRTY , & nfit_mem -> flags );
1754
+ }
1755
+
1756
+ if (smart .flags & ND_INTEL_SMART_SHUTDOWN_COUNT_VALID ) {
1757
+ set_bit (NFIT_MEM_DIRTY_COUNT , & nfit_mem -> flags );
1758
+ nfit_mem -> dirty_shutdown = smart .shutdown_count ;
1759
+ }
1760
+ ACPI_FREE (out_obj );
1761
+ }
1762
+
1763
+ static void populate_shutdown_status (struct nfit_mem * nfit_mem )
1764
+ {
1765
+ /*
1766
+ * For DIMMs that provide a dynamic facility to retrieve a
1767
+ * dirty-shutdown status and/or a dirty-shutdown count, cache
1768
+ * these values in nfit_mem.
1769
+ */
1770
+ if (nfit_mem -> family == NVDIMM_FAMILY_INTEL )
1771
+ nfit_intel_shutdown_status (nfit_mem );
1772
+ }
1773
+
1701
1774
static int acpi_nfit_add_dimm (struct acpi_nfit_desc * acpi_desc ,
1702
1775
struct nfit_mem * nfit_mem , u32 device_handle )
1703
1776
{
@@ -1797,6 +1870,8 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
1797
1870
set_bit (NFIT_MEM_LSW , & nfit_mem -> flags );
1798
1871
}
1799
1872
1873
+ populate_shutdown_status (nfit_mem );
1874
+
1800
1875
return 0 ;
1801
1876
}
1802
1877
0 commit comments