@@ -72,9 +72,80 @@ static struct acpi_device *to_acpi_dev(struct acpi_nfit_desc *acpi_desc)
72
72
return to_acpi_device (acpi_desc -> dev );
73
73
}
74
74
75
+ static int xlat_status (void * buf , unsigned int cmd )
76
+ {
77
+ struct nd_cmd_ars_status * ars_status ;
78
+ struct nd_cmd_ars_start * ars_start ;
79
+ struct nd_cmd_ars_cap * ars_cap ;
80
+ u16 flags ;
81
+
82
+ switch (cmd ) {
83
+ case ND_CMD_ARS_CAP :
84
+ ars_cap = buf ;
85
+ if ((ars_cap -> status & 0xffff ) == NFIT_ARS_CAP_NONE )
86
+ return - ENOTTY ;
87
+
88
+ /* Command failed */
89
+ if (ars_cap -> status & 0xffff )
90
+ return - EIO ;
91
+
92
+ /* No supported scan types for this range */
93
+ flags = ND_ARS_PERSISTENT | ND_ARS_VOLATILE ;
94
+ if ((ars_cap -> status >> 16 & flags ) == 0 )
95
+ return - ENOTTY ;
96
+ break ;
97
+ case ND_CMD_ARS_START :
98
+ ars_start = buf ;
99
+ /* ARS is in progress */
100
+ if ((ars_start -> status & 0xffff ) == NFIT_ARS_START_BUSY )
101
+ return - EBUSY ;
102
+
103
+ /* Command failed */
104
+ if (ars_start -> status & 0xffff )
105
+ return - EIO ;
106
+ break ;
107
+ case ND_CMD_ARS_STATUS :
108
+ ars_status = buf ;
109
+ /* Command failed */
110
+ if (ars_status -> status & 0xffff )
111
+ return - EIO ;
112
+ /* Check extended status (Upper two bytes) */
113
+ if (ars_status -> status == NFIT_ARS_STATUS_DONE )
114
+ return 0 ;
115
+
116
+ /* ARS is in progress */
117
+ if (ars_status -> status == NFIT_ARS_STATUS_BUSY )
118
+ return - EBUSY ;
119
+
120
+ /* No ARS performed for the current boot */
121
+ if (ars_status -> status == NFIT_ARS_STATUS_NONE )
122
+ return - EAGAIN ;
123
+
124
+ /*
125
+ * ARS interrupted, either we overflowed or some other
126
+ * agent wants the scan to stop. If we didn't overflow
127
+ * then just continue with the returned results.
128
+ */
129
+ if (ars_status -> status == NFIT_ARS_STATUS_INTR ) {
130
+ if (ars_status -> flags & NFIT_ARS_F_OVERFLOW )
131
+ return - ENOSPC ;
132
+ return 0 ;
133
+ }
134
+
135
+ /* Unknown status */
136
+ if (ars_status -> status >> 16 )
137
+ return - EIO ;
138
+ break ;
139
+ default :
140
+ break ;
141
+ }
142
+
143
+ return 0 ;
144
+ }
145
+
75
146
static int acpi_nfit_ctl (struct nvdimm_bus_descriptor * nd_desc ,
76
147
struct nvdimm * nvdimm , unsigned int cmd , void * buf ,
77
- unsigned int buf_len )
148
+ unsigned int buf_len , int * cmd_rc )
78
149
{
79
150
struct acpi_nfit_desc * acpi_desc = to_acpi_nfit_desc (nd_desc );
80
151
const struct nd_cmd_desc * desc = NULL ;
@@ -185,6 +256,8 @@ static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc,
185
256
* unfilled in the output buffer
186
257
*/
187
258
rc = buf_len - offset - in_buf .buffer .length ;
259
+ if (cmd_rc )
260
+ * cmd_rc = xlat_status (buf , cmd );
188
261
} else {
189
262
dev_err (dev , "%s:%s underrun cmd: %s buf_len: %d out_len: %d\n" ,
190
263
__func__ , dimm_name , cmd_name , buf_len ,
@@ -1105,7 +1178,7 @@ static void write_blk_ctl(struct nfit_blk *nfit_blk, unsigned int bw,
1105
1178
writeq (cmd , mmio -> addr .base + offset );
1106
1179
wmb_blk (nfit_blk );
1107
1180
1108
- if (nfit_blk -> dimm_flags & ND_BLK_DCR_LATCH )
1181
+ if (nfit_blk -> dimm_flags & NFIT_BLK_DCR_LATCH )
1109
1182
readq (mmio -> addr .base + offset );
1110
1183
}
1111
1184
@@ -1141,7 +1214,7 @@ static int acpi_nfit_blk_single_io(struct nfit_blk *nfit_blk,
1141
1214
memcpy_to_pmem (mmio -> addr .aperture + offset ,
1142
1215
iobuf + copied , c );
1143
1216
else {
1144
- if (nfit_blk -> dimm_flags & ND_BLK_READ_FLUSH )
1217
+ if (nfit_blk -> dimm_flags & NFIT_BLK_READ_FLUSH )
1145
1218
mmio_flush_range ((void __force * )
1146
1219
mmio -> addr .aperture + offset , c );
1147
1220
@@ -1328,13 +1401,13 @@ static int acpi_nfit_blk_get_flags(struct nvdimm_bus_descriptor *nd_desc,
1328
1401
1329
1402
memset (& flags , 0 , sizeof (flags ));
1330
1403
rc = nd_desc -> ndctl (nd_desc , nvdimm , ND_CMD_DIMM_FLAGS , & flags ,
1331
- sizeof (flags ));
1404
+ sizeof (flags ), NULL );
1332
1405
1333
1406
if (rc >= 0 && flags .status == 0 )
1334
1407
nfit_blk -> dimm_flags = flags .flags ;
1335
1408
else if (rc == - ENOTTY ) {
1336
1409
/* fall back to a conservative default */
1337
- nfit_blk -> dimm_flags = ND_BLK_DCR_LATCH | ND_BLK_READ_FLUSH ;
1410
+ nfit_blk -> dimm_flags = NFIT_BLK_DCR_LATCH | NFIT_BLK_READ_FLUSH ;
1338
1411
rc = 0 ;
1339
1412
} else
1340
1413
rc = - ENXIO ;
@@ -1473,19 +1546,27 @@ static void acpi_nfit_blk_region_disable(struct nvdimm_bus *nvdimm_bus,
1473
1546
/* devm will free nfit_blk */
1474
1547
}
1475
1548
1476
- static int ars_get_cap (struct nvdimm_bus_descriptor * nd_desc ,
1549
+ static int ars_get_cap (struct acpi_nfit_desc * acpi_desc ,
1477
1550
struct nd_cmd_ars_cap * cmd , u64 addr , u64 length )
1478
1551
{
1552
+ struct nvdimm_bus_descriptor * nd_desc = & acpi_desc -> nd_desc ;
1553
+ int cmd_rc , rc ;
1554
+
1479
1555
cmd -> address = addr ;
1480
1556
cmd -> length = length ;
1481
-
1482
- return nd_desc -> ndctl (nd_desc , NULL , ND_CMD_ARS_CAP , cmd ,
1483
- sizeof (* cmd ));
1557
+ rc = nd_desc -> ndctl (nd_desc , NULL , ND_CMD_ARS_CAP , cmd ,
1558
+ sizeof (* cmd ), & cmd_rc );
1559
+ if (rc < 0 )
1560
+ return rc ;
1561
+ if (cmd_rc < 0 )
1562
+ return cmd_rc ;
1563
+ return 0 ;
1484
1564
}
1485
1565
1486
1566
static int ars_do_start (struct nvdimm_bus_descriptor * nd_desc ,
1487
1567
struct nd_cmd_ars_start * cmd , u64 addr , u64 length )
1488
1568
{
1569
+ int cmd_rc ;
1489
1570
int rc ;
1490
1571
1491
1572
cmd -> address = addr ;
@@ -1494,52 +1575,49 @@ static int ars_do_start(struct nvdimm_bus_descriptor *nd_desc,
1494
1575
1495
1576
while (1 ) {
1496
1577
rc = nd_desc -> ndctl (nd_desc , NULL , ND_CMD_ARS_START , cmd ,
1497
- sizeof (* cmd ));
1498
- if (rc )
1578
+ sizeof (* cmd ), & cmd_rc );
1579
+
1580
+ if (rc < 0 )
1499
1581
return rc ;
1500
- switch (cmd -> status ) {
1501
- case 0 :
1502
- return 0 ;
1503
- case 1 :
1504
- /* ARS unsupported, but we should never get here */
1505
- return 0 ;
1506
- case 6 :
1582
+
1583
+ if (cmd_rc == - EBUSY ) {
1507
1584
/* ARS is in progress */
1508
1585
msleep (1000 );
1509
- break ;
1510
- default :
1511
- return - ENXIO ;
1586
+ continue ;
1512
1587
}
1588
+
1589
+ if (cmd_rc < 0 )
1590
+ return cmd_rc ;
1591
+
1592
+ return 0 ;
1513
1593
}
1514
1594
}
1515
1595
1516
1596
static int ars_get_status (struct nvdimm_bus_descriptor * nd_desc ,
1517
1597
struct nd_cmd_ars_status * cmd , u32 size )
1518
1598
{
1519
- int rc ;
1599
+ int rc , cmd_rc ;
1520
1600
1521
1601
while (1 ) {
1522
1602
rc = nd_desc -> ndctl (nd_desc , NULL , ND_CMD_ARS_STATUS , cmd ,
1523
- size );
1524
- if (rc || cmd -> status & 0xffff )
1525
- return - ENXIO ;
1603
+ size , & cmd_rc );
1604
+ if (rc < 0 )
1605
+ return rc ;
1526
1606
1527
- /* Check extended status (Upper two bytes) */
1528
- switch (cmd -> status >> 16 ) {
1529
- case 0 :
1530
- return 0 ;
1531
- case 1 :
1532
- /* ARS is in progress */
1607
+ /* FIXME make async and have a timeout */
1608
+ if (cmd_rc == - EBUSY ) {
1533
1609
msleep (1000 );
1534
- break ;
1535
- case 2 :
1536
- /* No ARS performed for the current boot */
1610
+ continue ;
1611
+ }
1612
+
1613
+ if (cmd_rc == - EAGAIN || cmd_rc == 0 )
1537
1614
return 0 ;
1538
- case 3 :
1539
- /* TODO: error list overflow support */
1540
- default :
1615
+
1616
+ /* TODO: error list overflow support */
1617
+ if ( cmd_rc == - ENOSPC )
1541
1618
return - ENXIO ;
1542
- }
1619
+
1620
+ return cmd_rc ;
1543
1621
}
1544
1622
}
1545
1623
@@ -1590,28 +1668,11 @@ static int acpi_nfit_find_poison(struct acpi_nfit_desc *acpi_desc,
1590
1668
start = ndr_desc -> res -> start ;
1591
1669
len = ndr_desc -> res -> end - ndr_desc -> res -> start + 1 ;
1592
1670
1593
- /*
1594
- * If ARS is unimplemented, unsupported, or if the 'Persistent Memory
1595
- * Scrub' flag in extended status is not set, skip this but continue
1596
- * initialization
1597
- */
1598
- rc = ars_get_cap (nd_desc , ars_cap , start , len );
1671
+ rc = ars_get_cap (acpi_desc , ars_cap , start , len );
1599
1672
if (rc == - ENOTTY ) {
1600
- dev_dbg (acpi_desc -> dev ,
1601
- "Address Range Scrub is not implemented, won't create an error list\n" );
1602
1673
rc = 0 ;
1603
1674
goto out ;
1604
1675
}
1605
- if (rc )
1606
- goto out ;
1607
-
1608
- if ((ars_cap -> status & 0xffff ) ||
1609
- !(ars_cap -> status >> 16 & ND_ARS_PERSISTENT )) {
1610
- dev_warn (acpi_desc -> dev ,
1611
- "ARS unsupported (status: 0x%x), won't create an error list\n" ,
1612
- ars_cap -> status );
1613
- goto out ;
1614
- }
1615
1676
1616
1677
/*
1617
1678
* Check if a full-range ARS has been run. If so, use those results
@@ -1651,15 +1712,15 @@ static int acpi_nfit_find_poison(struct acpi_nfit_desc *acpi_desc,
1651
1712
u64 done , end ;
1652
1713
1653
1714
rc = ars_do_start (nd_desc , ars_start , cur , remaining );
1654
- if (rc )
1715
+ if (rc < 0 )
1655
1716
goto out ;
1656
1717
1657
1718
rc = ars_get_status (nd_desc , ars_status , ars_status_size );
1658
- if (rc )
1719
+ if (rc < 0 )
1659
1720
goto out ;
1660
1721
1661
1722
rc = ars_status_process_records (nvdimm_bus , ars_status , cur );
1662
- if (rc )
1723
+ if (rc < 0 )
1663
1724
goto out ;
1664
1725
1665
1726
end = min (cur + remaining ,
0 commit comments