@@ -72,9 +72,80 @@ static struct acpi_device *to_acpi_dev(struct acpi_nfit_desc *acpi_desc)
7272 return to_acpi_device (acpi_desc -> dev );
7373}
7474
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+
75146static int acpi_nfit_ctl (struct nvdimm_bus_descriptor * nd_desc ,
76147 struct nvdimm * nvdimm , unsigned int cmd , void * buf ,
77- unsigned int buf_len )
148+ unsigned int buf_len , int * cmd_rc )
78149{
79150 struct acpi_nfit_desc * acpi_desc = to_acpi_nfit_desc (nd_desc );
80151 const struct nd_cmd_desc * desc = NULL ;
@@ -185,6 +256,8 @@ static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc,
185256 * unfilled in the output buffer
186257 */
187258 rc = buf_len - offset - in_buf .buffer .length ;
259+ if (cmd_rc )
260+ * cmd_rc = xlat_status (buf , cmd );
188261 } else {
189262 dev_err (dev , "%s:%s underrun cmd: %s buf_len: %d out_len: %d\n" ,
190263 __func__ , dimm_name , cmd_name , buf_len ,
@@ -1105,7 +1178,7 @@ static void write_blk_ctl(struct nfit_blk *nfit_blk, unsigned int bw,
11051178 writeq (cmd , mmio -> addr .base + offset );
11061179 wmb_blk (nfit_blk );
11071180
1108- if (nfit_blk -> dimm_flags & ND_BLK_DCR_LATCH )
1181+ if (nfit_blk -> dimm_flags & NFIT_BLK_DCR_LATCH )
11091182 readq (mmio -> addr .base + offset );
11101183}
11111184
@@ -1141,7 +1214,7 @@ static int acpi_nfit_blk_single_io(struct nfit_blk *nfit_blk,
11411214 memcpy_to_pmem (mmio -> addr .aperture + offset ,
11421215 iobuf + copied , c );
11431216 else {
1144- if (nfit_blk -> dimm_flags & ND_BLK_READ_FLUSH )
1217+ if (nfit_blk -> dimm_flags & NFIT_BLK_READ_FLUSH )
11451218 mmio_flush_range ((void __force * )
11461219 mmio -> addr .aperture + offset , c );
11471220
@@ -1328,13 +1401,13 @@ static int acpi_nfit_blk_get_flags(struct nvdimm_bus_descriptor *nd_desc,
13281401
13291402 memset (& flags , 0 , sizeof (flags ));
13301403 rc = nd_desc -> ndctl (nd_desc , nvdimm , ND_CMD_DIMM_FLAGS , & flags ,
1331- sizeof (flags ));
1404+ sizeof (flags ), NULL );
13321405
13331406 if (rc >= 0 && flags .status == 0 )
13341407 nfit_blk -> dimm_flags = flags .flags ;
13351408 else if (rc == - ENOTTY ) {
13361409 /* 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 ;
13381411 rc = 0 ;
13391412 } else
13401413 rc = - ENXIO ;
@@ -1473,19 +1546,27 @@ static void acpi_nfit_blk_region_disable(struct nvdimm_bus *nvdimm_bus,
14731546 /* devm will free nfit_blk */
14741547}
14751548
1476- static int ars_get_cap (struct nvdimm_bus_descriptor * nd_desc ,
1549+ static int ars_get_cap (struct acpi_nfit_desc * acpi_desc ,
14771550 struct nd_cmd_ars_cap * cmd , u64 addr , u64 length )
14781551{
1552+ struct nvdimm_bus_descriptor * nd_desc = & acpi_desc -> nd_desc ;
1553+ int cmd_rc , rc ;
1554+
14791555 cmd -> address = addr ;
14801556 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 ;
14841564}
14851565
14861566static int ars_do_start (struct nvdimm_bus_descriptor * nd_desc ,
14871567 struct nd_cmd_ars_start * cmd , u64 addr , u64 length )
14881568{
1569+ int cmd_rc ;
14891570 int rc ;
14901571
14911572 cmd -> address = addr ;
@@ -1494,52 +1575,49 @@ static int ars_do_start(struct nvdimm_bus_descriptor *nd_desc,
14941575
14951576 while (1 ) {
14961577 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 )
14991581 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 ) {
15071584 /* ARS is in progress */
15081585 msleep (1000 );
1509- break ;
1510- default :
1511- return - ENXIO ;
1586+ continue ;
15121587 }
1588+
1589+ if (cmd_rc < 0 )
1590+ return cmd_rc ;
1591+
1592+ return 0 ;
15131593 }
15141594}
15151595
15161596static int ars_get_status (struct nvdimm_bus_descriptor * nd_desc ,
15171597 struct nd_cmd_ars_status * cmd , u32 size )
15181598{
1519- int rc ;
1599+ int rc , cmd_rc ;
15201600
15211601 while (1 ) {
15221602 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 ;
15261606
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 ) {
15331609 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 )
15371614 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 )
15411618 return - ENXIO ;
1542- }
1619+
1620+ return cmd_rc ;
15431621 }
15441622}
15451623
@@ -1590,28 +1668,11 @@ static int acpi_nfit_find_poison(struct acpi_nfit_desc *acpi_desc,
15901668 start = ndr_desc -> res -> start ;
15911669 len = ndr_desc -> res -> end - ndr_desc -> res -> start + 1 ;
15921670
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 );
15991672 if (rc == - ENOTTY ) {
1600- dev_dbg (acpi_desc -> dev ,
1601- "Address Range Scrub is not implemented, won't create an error list\n" );
16021673 rc = 0 ;
16031674 goto out ;
16041675 }
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- }
16151676
16161677 /*
16171678 * 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,
16511712 u64 done , end ;
16521713
16531714 rc = ars_do_start (nd_desc , ars_start , cur , remaining );
1654- if (rc )
1715+ if (rc < 0 )
16551716 goto out ;
16561717
16571718 rc = ars_get_status (nd_desc , ars_status , ars_status_size );
1658- if (rc )
1719+ if (rc < 0 )
16591720 goto out ;
16601721
16611722 rc = ars_status_process_records (nvdimm_bus , ars_status , cur );
1662- if (rc )
1723+ if (rc < 0 )
16631724 goto out ;
16641725
16651726 end = min (cur + remaining ,
0 commit comments