23
23
#include <linux/sizes.h>
24
24
#include <linux/list.h>
25
25
#include <linux/slab.h>
26
+ #include <nd-core.h>
26
27
#include <nfit.h>
27
28
#include <nd.h>
28
29
#include "nfit_test.h"
@@ -1506,6 +1507,225 @@ static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa,
1506
1507
return 0 ;
1507
1508
}
1508
1509
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
+
1509
1729
static int nfit_test_probe (struct platform_device * pdev )
1510
1730
{
1511
1731
struct nvdimm_bus_descriptor * nd_desc ;
@@ -1516,6 +1736,12 @@ static int nfit_test_probe(struct platform_device *pdev)
1516
1736
union acpi_object * obj ;
1517
1737
int rc ;
1518
1738
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
+
1519
1745
nfit_test = to_nfit_test (& pdev -> dev );
1520
1746
1521
1747
/* common alloc */
@@ -1639,11 +1865,13 @@ static __init int nfit_test_init(void)
1639
1865
{
1640
1866
int rc , i ;
1641
1867
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 );
1645
1869
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
+ }
1647
1875
1648
1876
for (i = 0 ; i < NUM_NFITS ; i ++ ) {
1649
1877
struct nfit_test * nfit_test ;
0 commit comments