@@ -55,6 +55,10 @@ static bool no_init_ars;
55
55
module_param (no_init_ars , bool , 0644 );
56
56
MODULE_PARM_DESC (no_init_ars , "Skip ARS run at nfit init time" );
57
57
58
+ static bool force_labels ;
59
+ module_param (force_labels , bool , 0444 );
60
+ MODULE_PARM_DESC (force_labels , "Opt-in to labels despite missing methods" );
61
+
58
62
LIST_HEAD (acpi_descs );
59
63
DEFINE_MUTEX (acpi_desc_lock );
60
64
@@ -556,6 +560,13 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
556
560
return - EINVAL ;
557
561
}
558
562
563
+ if (out_obj -> type != ACPI_TYPE_BUFFER ) {
564
+ dev_dbg (dev , "%s unexpected output object type cmd: %s type: %d\n" ,
565
+ dimm_name , cmd_name , out_obj -> type );
566
+ rc = - EINVAL ;
567
+ goto out ;
568
+ }
569
+
559
570
if (call_pkg ) {
560
571
call_pkg -> nd_fw_size = out_obj -> buffer .length ;
561
572
memcpy (call_pkg -> nd_payload + call_pkg -> nd_size_in ,
@@ -574,13 +585,6 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
574
585
return 0 ;
575
586
}
576
587
577
- if (out_obj -> package .type != ACPI_TYPE_BUFFER ) {
578
- dev_dbg (dev , "%s unexpected output object type cmd: %s type: %d\n" ,
579
- dimm_name , cmd_name , out_obj -> type );
580
- rc = - EINVAL ;
581
- goto out ;
582
- }
583
-
584
588
dev_dbg (dev , "%s cmd: %s output length: %d\n" , dimm_name ,
585
589
cmd_name , out_obj -> buffer .length );
586
590
print_hex_dump_debug (cmd_name , DUMP_PREFIX_OFFSET , 4 , 4 ,
@@ -1761,14 +1765,14 @@ static bool acpi_nvdimm_has_method(struct acpi_device *adev, char *method)
1761
1765
1762
1766
__weak void nfit_intel_shutdown_status (struct nfit_mem * nfit_mem )
1763
1767
{
1768
+ struct device * dev = & nfit_mem -> adev -> dev ;
1764
1769
struct nd_intel_smart smart = { 0 };
1765
1770
union acpi_object in_buf = {
1766
- .type = ACPI_TYPE_BUFFER ,
1767
- .buffer .pointer = (char * ) & smart ,
1768
- .buffer .length = sizeof (smart ),
1771
+ .buffer .type = ACPI_TYPE_BUFFER ,
1772
+ .buffer .length = 0 ,
1769
1773
};
1770
1774
union acpi_object in_obj = {
1771
- .type = ACPI_TYPE_PACKAGE ,
1775
+ .package . type = ACPI_TYPE_PACKAGE ,
1772
1776
.package .count = 1 ,
1773
1777
.package .elements = & in_buf ,
1774
1778
};
@@ -1783,8 +1787,15 @@ __weak void nfit_intel_shutdown_status(struct nfit_mem *nfit_mem)
1783
1787
return ;
1784
1788
1785
1789
out_obj = acpi_evaluate_dsm (handle , guid , revid , func , & in_obj );
1786
- if (!out_obj )
1790
+ if (!out_obj || out_obj -> type != ACPI_TYPE_BUFFER
1791
+ || out_obj -> buffer .length < sizeof (smart )) {
1792
+ dev_dbg (dev -> parent , "%s: failed to retrieve initial health\n" ,
1793
+ dev_name (dev ));
1794
+ ACPI_FREE (out_obj );
1787
1795
return ;
1796
+ }
1797
+ memcpy (& smart , out_obj -> buffer .pointer , sizeof (smart ));
1798
+ ACPI_FREE (out_obj );
1788
1799
1789
1800
if (smart .flags & ND_INTEL_SMART_SHUTDOWN_VALID ) {
1790
1801
if (smart .shutdown_state )
@@ -1795,7 +1806,6 @@ __weak void nfit_intel_shutdown_status(struct nfit_mem *nfit_mem)
1795
1806
set_bit (NFIT_MEM_DIRTY_COUNT , & nfit_mem -> flags );
1796
1807
nfit_mem -> dirty_shutdown = smart .shutdown_count ;
1797
1808
}
1798
- ACPI_FREE (out_obj );
1799
1809
}
1800
1810
1801
1811
static void populate_shutdown_status (struct nfit_mem * nfit_mem )
@@ -1863,9 +1873,17 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
1863
1873
dev_set_drvdata (& adev_dimm -> dev , nfit_mem );
1864
1874
1865
1875
/*
1866
- * Until standardization materializes we need to consider 4
1867
- * different command sets. Note, that checking for function0 (bit0)
1868
- * tells us if any commands are reachable through this GUID.
1876
+ * There are 4 "legacy" NVDIMM command sets
1877
+ * (NVDIMM_FAMILY_{INTEL,MSFT,HPE1,HPE2}) that were created before
1878
+ * an EFI working group was established to constrain this
1879
+ * proliferation. The nfit driver probes for the supported command
1880
+ * set by GUID. Note, if you're a platform developer looking to add
1881
+ * a new command set to this probe, consider using an existing set,
1882
+ * or otherwise seek approval to publish the command set at
1883
+ * http://www.uefi.org/RFIC_LIST.
1884
+ *
1885
+ * Note, that checking for function0 (bit0) tells us if any commands
1886
+ * are reachable through this GUID.
1869
1887
*/
1870
1888
for (i = 0 ; i <= NVDIMM_FAMILY_MAX ; i ++ )
1871
1889
if (acpi_check_dsm (adev_dimm -> handle , to_nfit_uuid (i ), 1 , 1 ))
@@ -1888,6 +1906,8 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
1888
1906
dsm_mask &= ~(1 << 8 );
1889
1907
} else if (nfit_mem -> family == NVDIMM_FAMILY_MSFT ) {
1890
1908
dsm_mask = 0xffffffff ;
1909
+ } else if (nfit_mem -> family == NVDIMM_FAMILY_HYPERV ) {
1910
+ dsm_mask = 0x1f ;
1891
1911
} else {
1892
1912
dev_dbg (dev , "unknown dimm command family\n" );
1893
1913
nfit_mem -> family = -1 ;
@@ -1917,18 +1937,32 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
1917
1937
| 1 << ND_CMD_SET_CONFIG_DATA ;
1918
1938
if (family == NVDIMM_FAMILY_INTEL
1919
1939
&& (dsm_mask & label_mask ) == label_mask )
1920
- return 0 ;
1940
+ /* skip _LS{I,R,W} enabling */ ;
1941
+ else {
1942
+ if (acpi_nvdimm_has_method (adev_dimm , "_LSI" )
1943
+ && acpi_nvdimm_has_method (adev_dimm , "_LSR" )) {
1944
+ dev_dbg (dev , "%s: has _LSR\n" , dev_name (& adev_dimm -> dev ));
1945
+ set_bit (NFIT_MEM_LSR , & nfit_mem -> flags );
1946
+ }
1921
1947
1922
- if (acpi_nvdimm_has_method ( adev_dimm , "_LSI" )
1923
- && acpi_nvdimm_has_method (adev_dimm , "_LSR " )) {
1924
- dev_dbg (dev , "%s: has _LSR \n" , dev_name (& adev_dimm -> dev ));
1925
- set_bit (NFIT_MEM_LSR , & nfit_mem -> flags );
1926
- }
1948
+ if (test_bit ( NFIT_MEM_LSR , & nfit_mem -> flags )
1949
+ && acpi_nvdimm_has_method (adev_dimm , "_LSW " )) {
1950
+ dev_dbg (dev , "%s: has _LSW \n" , dev_name (& adev_dimm -> dev ));
1951
+ set_bit (NFIT_MEM_LSW , & nfit_mem -> flags );
1952
+ }
1927
1953
1928
- if (test_bit (NFIT_MEM_LSR , & nfit_mem -> flags )
1929
- && acpi_nvdimm_has_method (adev_dimm , "_LSW" )) {
1930
- dev_dbg (dev , "%s: has _LSW\n" , dev_name (& adev_dimm -> dev ));
1931
- set_bit (NFIT_MEM_LSW , & nfit_mem -> flags );
1954
+ /*
1955
+ * Quirk read-only label configurations to preserve
1956
+ * access to label-less namespaces by default.
1957
+ */
1958
+ if (!test_bit (NFIT_MEM_LSW , & nfit_mem -> flags )
1959
+ && !force_labels ) {
1960
+ dev_dbg (dev , "%s: No _LSW, disable labels\n" ,
1961
+ dev_name (& adev_dimm -> dev ));
1962
+ clear_bit (NFIT_MEM_LSR , & nfit_mem -> flags );
1963
+ } else
1964
+ dev_dbg (dev , "%s: Force enable labels\n" ,
1965
+ dev_name (& adev_dimm -> dev ));
1932
1966
}
1933
1967
1934
1968
populate_shutdown_status (nfit_mem );
@@ -2029,6 +2063,10 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
2029
2063
cmd_mask |= nfit_mem -> dsm_mask & NVDIMM_STANDARD_CMDMASK ;
2030
2064
}
2031
2065
2066
+ /* Quirk to ignore LOCAL for labels on HYPERV DIMMs */
2067
+ if (nfit_mem -> family == NVDIMM_FAMILY_HYPERV )
2068
+ set_bit (NDD_NOBLK , & flags );
2069
+
2032
2070
if (test_bit (NFIT_MEM_LSR , & nfit_mem -> flags )) {
2033
2071
set_bit (ND_CMD_GET_CONFIG_SIZE , & cmd_mask );
2034
2072
set_bit (ND_CMD_GET_CONFIG_DATA , & cmd_mask );
@@ -2052,7 +2090,7 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
2052
2090
if ((mem_flags & ACPI_NFIT_MEM_FAILED_MASK ) == 0 )
2053
2091
continue ;
2054
2092
2055
- dev_info (acpi_desc -> dev , "%s flags:%s%s%s%s%s\n" ,
2093
+ dev_err (acpi_desc -> dev , "Error found in NVDIMM %s flags:%s%s%s%s%s\n" ,
2056
2094
nvdimm_name (nvdimm ),
2057
2095
mem_flags & ACPI_NFIT_MEM_SAVE_FAILED ? " save_fail" : "" ,
2058
2096
mem_flags & ACPI_NFIT_MEM_RESTORE_FAILED ? " restore_fail" :"" ,
@@ -3731,6 +3769,7 @@ static __init int nfit_init(void)
3731
3769
guid_parse (UUID_NFIT_DIMM_N_HPE1 , & nfit_uuid [NFIT_DEV_DIMM_N_HPE1 ]);
3732
3770
guid_parse (UUID_NFIT_DIMM_N_HPE2 , & nfit_uuid [NFIT_DEV_DIMM_N_HPE2 ]);
3733
3771
guid_parse (UUID_NFIT_DIMM_N_MSFT , & nfit_uuid [NFIT_DEV_DIMM_N_MSFT ]);
3772
+ guid_parse (UUID_NFIT_DIMM_N_HYPERV , & nfit_uuid [NFIT_DEV_DIMM_N_HYPERV ]);
3734
3773
3735
3774
nfit_wq = create_singlethread_workqueue ("nfit" );
3736
3775
if (!nfit_wq )
0 commit comments