2323#include <linux/sizes.h>
2424#include <linux/list.h>
2525#include <linux/slab.h>
26+ #include <nd-core.h>
2627#include <nfit.h>
2728#include <nd.h>
2829#include "nfit_test.h"
@@ -1506,6 +1507,225 @@ static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa,
15061507 return 0 ;
15071508}
15081509
1510+ static unsigned long nfit_ctl_handle ;
1511+
1512+ union acpi_object * result ;
1513+
1514+ static union acpi_object * nfit_test_evaluate_dsm (acpi_handle handle ,
1515+ const u8 * uuid , u64 rev , u64 func , union acpi_object * argv4 )
1516+ {
1517+ if (handle != & nfit_ctl_handle )
1518+ return ERR_PTR (- ENXIO );
1519+
1520+ return result ;
1521+ }
1522+
1523+ static int setup_result (void * buf , size_t size )
1524+ {
1525+ result = kmalloc (sizeof (union acpi_object ) + size , GFP_KERNEL );
1526+ if (!result )
1527+ return - ENOMEM ;
1528+ result -> package .type = ACPI_TYPE_BUFFER ,
1529+ result -> buffer .pointer = (void * ) (result + 1 );
1530+ result -> buffer .length = size ;
1531+ memcpy (result -> buffer .pointer , buf , size );
1532+ memset (buf , 0 , size );
1533+ return 0 ;
1534+ }
1535+
1536+ static int nfit_ctl_test (struct device * dev )
1537+ {
1538+ int rc , cmd_rc ;
1539+ struct nvdimm * nvdimm ;
1540+ struct acpi_device * adev ;
1541+ struct nfit_mem * nfit_mem ;
1542+ struct nd_ars_record * record ;
1543+ struct acpi_nfit_desc * acpi_desc ;
1544+ const u64 test_val = 0x0123456789abcdefULL ;
1545+ unsigned long mask , cmd_size , offset ;
1546+ union {
1547+ struct nd_cmd_get_config_size cfg_size ;
1548+ struct nd_cmd_ars_status ars_stat ;
1549+ struct nd_cmd_ars_cap ars_cap ;
1550+ char buf [sizeof (struct nd_cmd_ars_status )
1551+ + sizeof (struct nd_ars_record )];
1552+ } cmds ;
1553+
1554+ adev = devm_kzalloc (dev , sizeof (* adev ), GFP_KERNEL );
1555+ if (!adev )
1556+ return - ENOMEM ;
1557+ * adev = (struct acpi_device ) {
1558+ .handle = & nfit_ctl_handle ,
1559+ .dev = {
1560+ .init_name = "test-adev" ,
1561+ },
1562+ };
1563+
1564+ acpi_desc = devm_kzalloc (dev , sizeof (* acpi_desc ), GFP_KERNEL );
1565+ if (!acpi_desc )
1566+ return - ENOMEM ;
1567+ * acpi_desc = (struct acpi_nfit_desc ) {
1568+ .nd_desc = {
1569+ .cmd_mask = 1UL << ND_CMD_ARS_CAP
1570+ | 1UL << ND_CMD_ARS_START
1571+ | 1UL << ND_CMD_ARS_STATUS
1572+ | 1UL << ND_CMD_CLEAR_ERROR ,
1573+ .module = THIS_MODULE ,
1574+ .provider_name = "ACPI.NFIT" ,
1575+ .ndctl = acpi_nfit_ctl ,
1576+ },
1577+ .dev = & adev -> dev ,
1578+ };
1579+
1580+ nfit_mem = devm_kzalloc (dev , sizeof (* nfit_mem ), GFP_KERNEL );
1581+ if (!nfit_mem )
1582+ return - ENOMEM ;
1583+
1584+ mask = 1UL << ND_CMD_SMART | 1UL << ND_CMD_SMART_THRESHOLD
1585+ | 1UL << ND_CMD_DIMM_FLAGS | 1UL << ND_CMD_GET_CONFIG_SIZE
1586+ | 1UL << ND_CMD_GET_CONFIG_DATA | 1UL << ND_CMD_SET_CONFIG_DATA
1587+ | 1UL << ND_CMD_VENDOR ;
1588+ * nfit_mem = (struct nfit_mem ) {
1589+ .adev = adev ,
1590+ .family = NVDIMM_FAMILY_INTEL ,
1591+ .dsm_mask = mask ,
1592+ };
1593+
1594+ nvdimm = devm_kzalloc (dev , sizeof (* nvdimm ), GFP_KERNEL );
1595+ if (!nvdimm )
1596+ return - ENOMEM ;
1597+ * nvdimm = (struct nvdimm ) {
1598+ .provider_data = nfit_mem ,
1599+ .cmd_mask = mask ,
1600+ .dev = {
1601+ .init_name = "test-dimm" ,
1602+ },
1603+ };
1604+
1605+
1606+ /* basic checkout of a typical 'get config size' command */
1607+ cmd_size = sizeof (cmds .cfg_size );
1608+ cmds .cfg_size = (struct nd_cmd_get_config_size ) {
1609+ .status = 0 ,
1610+ .config_size = SZ_128K ,
1611+ .max_xfer = SZ_4K ,
1612+ };
1613+ rc = setup_result (cmds .buf , cmd_size );
1614+ if (rc )
1615+ return rc ;
1616+ rc = acpi_nfit_ctl (& acpi_desc -> nd_desc , nvdimm , ND_CMD_GET_CONFIG_SIZE ,
1617+ cmds .buf , cmd_size , & cmd_rc );
1618+
1619+ if (rc < 0 || cmd_rc || cmds .cfg_size .status != 0
1620+ || cmds .cfg_size .config_size != SZ_128K
1621+ || cmds .cfg_size .max_xfer != SZ_4K ) {
1622+ dev_dbg (dev , "%s: failed at: %d rc: %d cmd_rc: %d\n" ,
1623+ __func__ , __LINE__ , rc , cmd_rc );
1624+ return - EIO ;
1625+ }
1626+
1627+
1628+ /* test ars_status with zero output */
1629+ cmd_size = offsetof(struct nd_cmd_ars_status , address );
1630+ cmds .ars_stat = (struct nd_cmd_ars_status ) {
1631+ .out_length = 0 ,
1632+ };
1633+ rc = setup_result (cmds .buf , cmd_size );
1634+ if (rc )
1635+ return rc ;
1636+ rc = acpi_nfit_ctl (& acpi_desc -> nd_desc , NULL , ND_CMD_ARS_STATUS ,
1637+ cmds .buf , cmd_size , & cmd_rc );
1638+
1639+ if (rc < 0 || cmd_rc ) {
1640+ dev_dbg (dev , "%s: failed at: %d rc: %d cmd_rc: %d\n" ,
1641+ __func__ , __LINE__ , rc , cmd_rc );
1642+ return - EIO ;
1643+ }
1644+
1645+
1646+ /* test ars_cap with benign extended status */
1647+ cmd_size = sizeof (cmds .ars_cap );
1648+ cmds .ars_cap = (struct nd_cmd_ars_cap ) {
1649+ .status = ND_ARS_PERSISTENT << 16 ,
1650+ };
1651+ offset = offsetof(struct nd_cmd_ars_cap , status );
1652+ rc = setup_result (cmds .buf + offset , cmd_size - offset );
1653+ if (rc )
1654+ return rc ;
1655+ rc = acpi_nfit_ctl (& acpi_desc -> nd_desc , NULL , ND_CMD_ARS_CAP ,
1656+ cmds .buf , cmd_size , & cmd_rc );
1657+
1658+ if (rc < 0 || cmd_rc ) {
1659+ dev_dbg (dev , "%s: failed at: %d rc: %d cmd_rc: %d\n" ,
1660+ __func__ , __LINE__ , rc , cmd_rc );
1661+ return - EIO ;
1662+ }
1663+
1664+
1665+ /* test ars_status with 'status' trimmed from 'out_length' */
1666+ cmd_size = sizeof (cmds .ars_stat ) + sizeof (struct nd_ars_record );
1667+ cmds .ars_stat = (struct nd_cmd_ars_status ) {
1668+ .out_length = cmd_size - 4 ,
1669+ };
1670+ record = & cmds .ars_stat .records [0 ];
1671+ * record = (struct nd_ars_record ) {
1672+ .length = test_val ,
1673+ };
1674+ rc = setup_result (cmds .buf , cmd_size );
1675+ if (rc )
1676+ return rc ;
1677+ rc = acpi_nfit_ctl (& acpi_desc -> nd_desc , NULL , ND_CMD_ARS_STATUS ,
1678+ cmds .buf , cmd_size , & cmd_rc );
1679+
1680+ if (rc < 0 || cmd_rc || record -> length != test_val ) {
1681+ dev_dbg (dev , "%s: failed at: %d rc: %d cmd_rc: %d\n" ,
1682+ __func__ , __LINE__ , rc , cmd_rc );
1683+ return - EIO ;
1684+ }
1685+
1686+
1687+ /* test ars_status with 'Output (Size)' including 'status' */
1688+ cmd_size = sizeof (cmds .ars_stat ) + sizeof (struct nd_ars_record );
1689+ cmds .ars_stat = (struct nd_cmd_ars_status ) {
1690+ .out_length = cmd_size ,
1691+ };
1692+ record = & cmds .ars_stat .records [0 ];
1693+ * record = (struct nd_ars_record ) {
1694+ .length = test_val ,
1695+ };
1696+ rc = setup_result (cmds .buf , cmd_size );
1697+ if (rc )
1698+ return rc ;
1699+ rc = acpi_nfit_ctl (& acpi_desc -> nd_desc , NULL , ND_CMD_ARS_STATUS ,
1700+ cmds .buf , cmd_size , & cmd_rc );
1701+
1702+ if (rc < 0 || cmd_rc || record -> length != test_val ) {
1703+ dev_dbg (dev , "%s: failed at: %d rc: %d cmd_rc: %d\n" ,
1704+ __func__ , __LINE__ , rc , cmd_rc );
1705+ return - EIO ;
1706+ }
1707+
1708+
1709+ /* test extended status for get_config_size results in failure */
1710+ cmd_size = sizeof (cmds .cfg_size );
1711+ cmds .cfg_size = (struct nd_cmd_get_config_size ) {
1712+ .status = 1 << 16 ,
1713+ };
1714+ rc = setup_result (cmds .buf , cmd_size );
1715+ if (rc )
1716+ return rc ;
1717+ rc = acpi_nfit_ctl (& acpi_desc -> nd_desc , nvdimm , ND_CMD_GET_CONFIG_SIZE ,
1718+ cmds .buf , cmd_size , & cmd_rc );
1719+
1720+ if (rc < 0 || cmd_rc >= 0 ) {
1721+ dev_dbg (dev , "%s: failed at: %d rc: %d cmd_rc: %d\n" ,
1722+ __func__ , __LINE__ , rc , cmd_rc );
1723+ return - EIO ;
1724+ }
1725+
1726+ return 0 ;
1727+ }
1728+
15091729static int nfit_test_probe (struct platform_device * pdev )
15101730{
15111731 struct nvdimm_bus_descriptor * nd_desc ;
@@ -1516,6 +1736,12 @@ static int nfit_test_probe(struct platform_device *pdev)
15161736 union acpi_object * obj ;
15171737 int rc ;
15181738
1739+ if (strcmp (dev_name (& pdev -> dev ), "nfit_test.0" ) == 0 ) {
1740+ rc = nfit_ctl_test (& pdev -> dev );
1741+ if (rc )
1742+ return rc ;
1743+ }
1744+
15191745 nfit_test = to_nfit_test (& pdev -> dev );
15201746
15211747 /* common alloc */
@@ -1639,11 +1865,13 @@ static __init int nfit_test_init(void)
16391865{
16401866 int rc , i ;
16411867
1642- nfit_test_dimm = class_create (THIS_MODULE , "nfit_test_dimm" );
1643- if (IS_ERR (nfit_test_dimm ))
1644- return PTR_ERR (nfit_test_dimm );
1868+ nfit_test_setup (nfit_test_lookup , nfit_test_evaluate_dsm );
16451869
1646- nfit_test_setup (nfit_test_lookup );
1870+ nfit_test_dimm = class_create (THIS_MODULE , "nfit_test_dimm" );
1871+ if (IS_ERR (nfit_test_dimm )) {
1872+ rc = PTR_ERR (nfit_test_dimm );
1873+ goto err_register ;
1874+ }
16471875
16481876 for (i = 0 ; i < NUM_NFITS ; i ++ ) {
16491877 struct nfit_test * nfit_test ;
0 commit comments