Skip to content

Commit 18bd771

Browse files
Niklas Casselmartinkpetersen
Niklas Cassel
authored andcommitted
scsi: ata: libata: Handle completion of CDL commands using policy 0xD
A CDL timeout for policy 0xF is defined as a NCQ error, just with a CDL specific sk/asc/ascq in the sense data. Therefore, the existing code in libata does not need to be modified to handle a policy 0xF CDL timeout. For Command Duration Limits policy 0xD: The device shall complete the command without error with the additional sense code set to DATA CURRENTLY UNAVAILABLE. Since a CDL timeout for policy 0xD is not an error, we cannot use the NCQ Command Error log (10h). Instead, we need to read the Sense Data for Successful NCQ Commands log (0Fh). In the success case, just like in the error case, we cannot simply read a log page from the interrupt handler itself, since reading a log page involves sending a READ LOG DMA EXT or READ LOG EXT command. Therefore, we add a new EH action ATA_EH_GET_SUCCESS_SENSE. When a command completes without error, and when the ATA_SENSE bit is set, this new action is set as pending, and EH is scheduled. This way, similar to the NCQ error case, the log page will be read from EH context. An alternative would have been to add a new kthread or workqueue to handle this. However, extending EH can be done with minimal changes and avoids the need to synchronize a new kthread/workqueue with EH. Co-developed-by: Damien Le Moal <[email protected]> Signed-off-by: Damien Le Moal <[email protected]> Reviewed-by: Hannes Reinecke <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Signed-off-by: Niklas Cassel <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Martin K. Petersen <[email protected]>
1 parent eafe804 commit 18bd771

File tree

5 files changed

+295
-4
lines changed

5 files changed

+295
-4
lines changed

drivers/ata/libata-core.c

Lines changed: 86 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -677,8 +677,12 @@ static inline void ata_set_tf_cdl(struct ata_queued_cmd *qc, int cdl)
677677
else
678678
tf->feature |= cdl;
679679

680-
/* Mark this command as having a CDL */
681-
qc->flags |= ATA_QCFLAG_HAS_CDL;
680+
/*
681+
* Mark this command as having a CDL and request the result
682+
* task file so that we can inspect the sense data available
683+
* bit on completion.
684+
*/
685+
qc->flags |= ATA_QCFLAG_HAS_CDL | ATA_QCFLAG_RESULT_TF;
682686
}
683687

684688
/**
@@ -2424,6 +2428,24 @@ static void ata_dev_config_cdl(struct ata_device *dev)
24242428
ata_dev_warn(dev,
24252429
"Command duration guideline is not supported\n");
24262430

2431+
/*
2432+
* We must have support for the sense data for successful NCQ commands
2433+
* log indicated by the successful NCQ command sense data supported bit.
2434+
*/
2435+
val = get_unaligned_le64(&ap->sector_buf[8]);
2436+
if (!(val & BIT_ULL(63)) || !(val & BIT_ULL(47))) {
2437+
ata_dev_warn(dev,
2438+
"CDL supported but Successful NCQ Command Sense Data is not supported\n");
2439+
goto not_supported;
2440+
}
2441+
2442+
/* Without NCQ autosense, the successful NCQ commands log is useless. */
2443+
if (!ata_id_has_ncq_autosense(dev->id)) {
2444+
ata_dev_warn(dev,
2445+
"CDL supported but NCQ autosense is not supported\n");
2446+
goto not_supported;
2447+
}
2448+
24272449
/*
24282450
* If CDL is marked as enabled, make sure the feature is enabled too.
24292451
* Conversely, if CDL is disabled, make sure the feature is turned off.
@@ -2458,6 +2480,35 @@ static void ata_dev_config_cdl(struct ata_device *dev)
24582480
}
24592481
}
24602482

2483+
/*
2484+
* While CDL itself has to be enabled using sysfs, CDL requires that
2485+
* sense data for successful NCQ commands is enabled to work properly.
2486+
* Just like ata_dev_config_sense_reporting(), enable it unconditionally
2487+
* if supported.
2488+
*/
2489+
if (!(val & BIT_ULL(63)) || !(val & BIT_ULL(18))) {
2490+
err_mask = ata_dev_set_feature(dev,
2491+
SETFEATURE_SENSE_DATA_SUCC_NCQ, 0x1);
2492+
if (err_mask) {
2493+
ata_dev_warn(dev,
2494+
"failed to enable Sense Data for successful NCQ commands, Emask 0x%x\n",
2495+
err_mask);
2496+
goto not_supported;
2497+
}
2498+
}
2499+
2500+
/*
2501+
* Allocate a buffer to handle reading the sense data for successful
2502+
* NCQ Commands log page for commands using a CDL with one of the limit
2503+
* policy set to 0xD (successful completion with sense data available
2504+
* bit set).
2505+
*/
2506+
if (!ap->ncq_sense_buf) {
2507+
ap->ncq_sense_buf = kmalloc(ATA_LOG_SENSE_NCQ_SIZE, GFP_KERNEL);
2508+
if (!ap->ncq_sense_buf)
2509+
goto not_supported;
2510+
}
2511+
24612512
/*
24622513
* Command duration limits is supported: cache the CDL log page 18h
24632514
* (command duration descriptors).
@@ -2475,6 +2526,8 @@ static void ata_dev_config_cdl(struct ata_device *dev)
24752526

24762527
not_supported:
24772528
dev->flags &= ~(ATA_DFLAG_CDL | ATA_DFLAG_CDL_ENABLED);
2529+
kfree(ap->ncq_sense_buf);
2530+
ap->ncq_sense_buf = NULL;
24782531
}
24792532

24802533
static int ata_dev_config_lba(struct ata_device *dev)
@@ -4878,6 +4931,36 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
48784931
fill_result_tf(qc);
48794932

48804933
trace_ata_qc_complete_done(qc);
4934+
4935+
/*
4936+
* For CDL commands that completed without an error, check if
4937+
* we have sense data (ATA_SENSE is set). If we do, then the
4938+
* command may have been aborted by the device due to a limit
4939+
* timeout using the policy 0xD. For these commands, invoke EH
4940+
* to get the command sense data.
4941+
*/
4942+
if (qc->result_tf.status & ATA_SENSE &&
4943+
((ata_is_ncq(qc->tf.protocol) &&
4944+
dev->flags & ATA_DFLAG_CDL_ENABLED) ||
4945+
(!(ata_is_ncq(qc->tf.protocol) &&
4946+
ata_id_sense_reporting_enabled(dev->id))))) {
4947+
/*
4948+
* Tell SCSI EH to not overwrite scmd->result even if
4949+
* this command is finished with result SAM_STAT_GOOD.
4950+
*/
4951+
qc->scsicmd->flags |= SCMD_FORCE_EH_SUCCESS;
4952+
qc->flags |= ATA_QCFLAG_EH_SUCCESS_CMD;
4953+
ehi->dev_action[dev->devno] |= ATA_EH_GET_SUCCESS_SENSE;
4954+
4955+
/*
4956+
* set pending so that ata_qc_schedule_eh() does not
4957+
* trigger fast drain, and freeze the port.
4958+
*/
4959+
ap->pflags |= ATA_PFLAG_EH_PENDING;
4960+
ata_qc_schedule_eh(qc);
4961+
return;
4962+
}
4963+
48814964
/* Some commands need post-processing after successful
48824965
* completion.
48834966
*/
@@ -5510,6 +5593,7 @@ static void ata_host_release(struct kref *kref)
55105593

55115594
kfree(ap->pmp_link);
55125595
kfree(ap->slave_link);
5596+
kfree(ap->ncq_sense_buf);
55135597
kfree(ap);
55145598
host->ports[i] = NULL;
55155599
}

drivers/ata/libata-eh.c

Lines changed: 104 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1917,6 +1917,99 @@ static inline bool ata_eh_quiet(struct ata_queued_cmd *qc)
19171917
return qc->flags & ATA_QCFLAG_QUIET;
19181918
}
19191919

1920+
static int ata_eh_read_sense_success_non_ncq(struct ata_link *link)
1921+
{
1922+
struct ata_port *ap = link->ap;
1923+
struct ata_queued_cmd *qc;
1924+
1925+
qc = __ata_qc_from_tag(ap, link->active_tag);
1926+
if (!qc)
1927+
return -EIO;
1928+
1929+
if (!(qc->flags & ATA_QCFLAG_EH) ||
1930+
!(qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD) ||
1931+
qc->err_mask)
1932+
return -EIO;
1933+
1934+
if (!ata_eh_request_sense(qc))
1935+
return -EIO;
1936+
1937+
/*
1938+
* If we have sense data, call scsi_check_sense() in order to set the
1939+
* correct SCSI ML byte (if any). No point in checking the return value,
1940+
* since the command has already completed successfully.
1941+
*/
1942+
scsi_check_sense(qc->scsicmd);
1943+
1944+
return 0;
1945+
}
1946+
1947+
static void ata_eh_get_success_sense(struct ata_link *link)
1948+
{
1949+
struct ata_eh_context *ehc = &link->eh_context;
1950+
struct ata_device *dev = link->device;
1951+
struct ata_port *ap = link->ap;
1952+
struct ata_queued_cmd *qc;
1953+
int tag, ret = 0;
1954+
1955+
if (!(ehc->i.dev_action[dev->devno] & ATA_EH_GET_SUCCESS_SENSE))
1956+
return;
1957+
1958+
/* if frozen, we can't do much */
1959+
if (ata_port_is_frozen(ap)) {
1960+
ata_dev_warn(dev,
1961+
"successful sense data available but port frozen\n");
1962+
goto out;
1963+
}
1964+
1965+
/*
1966+
* If the link has sactive set, then we have outstanding NCQ commands
1967+
* and have to read the Successful NCQ Commands log to get the sense
1968+
* data. Otherwise, we are dealing with a non-NCQ command and use
1969+
* request sense ext command to retrieve the sense data.
1970+
*/
1971+
if (link->sactive)
1972+
ret = ata_eh_read_sense_success_ncq_log(link);
1973+
else
1974+
ret = ata_eh_read_sense_success_non_ncq(link);
1975+
if (ret)
1976+
goto out;
1977+
1978+
ata_eh_done(link, dev, ATA_EH_GET_SUCCESS_SENSE);
1979+
return;
1980+
1981+
out:
1982+
/*
1983+
* If we failed to get sense data for a successful command that ought to
1984+
* have sense data, we cannot simply return BLK_STS_OK to user space.
1985+
* This is because we can't know if the sense data that we couldn't get
1986+
* was actually "DATA CURRENTLY UNAVAILABLE". Reporting such a command
1987+
* as success to user space would result in a silent data corruption.
1988+
* Thus, add a bogus ABORTED_COMMAND sense data to such commands, such
1989+
* that SCSI will report these commands as BLK_STS_IOERR to user space.
1990+
*/
1991+
ata_qc_for_each_raw(ap, qc, tag) {
1992+
if (!(qc->flags & ATA_QCFLAG_EH) ||
1993+
!(qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD) ||
1994+
qc->err_mask ||
1995+
ata_dev_phys_link(qc->dev) != link)
1996+
continue;
1997+
1998+
/* We managed to get sense for this success command, skip. */
1999+
if (qc->flags & ATA_QCFLAG_SENSE_VALID)
2000+
continue;
2001+
2002+
/* This success command did not have any sense data, skip. */
2003+
if (!(qc->result_tf.status & ATA_SENSE))
2004+
continue;
2005+
2006+
/* This success command had sense data, but we failed to get. */
2007+
ata_scsi_set_sense(dev, qc->scsicmd, ABORTED_COMMAND, 0, 0);
2008+
qc->flags |= ATA_QCFLAG_SENSE_VALID;
2009+
}
2010+
ata_eh_done(link, dev, ATA_EH_GET_SUCCESS_SENSE);
2011+
}
2012+
19202013
/**
19212014
* ata_eh_link_autopsy - analyze error and determine recovery action
19222015
* @link: host link to perform autopsy on
@@ -1957,6 +2050,14 @@ static void ata_eh_link_autopsy(struct ata_link *link)
19572050
/* analyze NCQ failure */
19582051
ata_eh_analyze_ncq_error(link);
19592052

2053+
/*
2054+
* Check if this was a successful command that simply needs sense data.
2055+
* Since the sense data is not part of the completion, we need to fetch
2056+
* it using an additional command. Since this can't be done from irq
2057+
* context, the sense data for successful commands are fetched by EH.
2058+
*/
2059+
ata_eh_get_success_sense(link);
2060+
19602061
/* any real error trumps AC_ERR_OTHER */
19612062
if (ehc->i.err_mask & ~AC_ERR_OTHER)
19622063
ehc->i.err_mask &= ~AC_ERR_OTHER;
@@ -1966,6 +2067,7 @@ static void ata_eh_link_autopsy(struct ata_link *link)
19662067
ata_qc_for_each_raw(ap, qc, tag) {
19672068
if (!(qc->flags & ATA_QCFLAG_EH) ||
19682069
qc->flags & ATA_QCFLAG_RETRY ||
2070+
qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD ||
19692071
ata_dev_phys_link(qc->dev) != link)
19702072
continue;
19712073

@@ -3825,7 +3927,8 @@ void ata_eh_finish(struct ata_port *ap)
38253927
else
38263928
ata_eh_qc_complete(qc);
38273929
} else {
3828-
if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
3930+
if (qc->flags & ATA_QCFLAG_SENSE_VALID ||
3931+
qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD) {
38293932
ata_eh_qc_complete(qc);
38303933
} else {
38313934
/* feed zero TF to sense generation */

drivers/ata/libata-sata.c

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
#include <linux/module.h>
1212
#include <scsi/scsi_cmnd.h>
1313
#include <scsi/scsi_device.h>
14+
#include <scsi/scsi_eh.h>
1415
#include <linux/libata.h>
16+
#include <asm/unaligned.h>
1517

1618
#include "libata.h"
1719
#include "libata-transport.h"
@@ -1408,6 +1410,95 @@ static int ata_eh_read_log_10h(struct ata_device *dev,
14081410
return 0;
14091411
}
14101412

1413+
/**
1414+
* ata_eh_read_sense_success_ncq_log - Read the sense data for successful
1415+
* NCQ commands log
1416+
* @link: ATA link to get sense data for
1417+
*
1418+
* Read the sense data for successful NCQ commands log page to obtain
1419+
* sense data for all NCQ commands that completed successfully with
1420+
* the sense data available bit set.
1421+
*
1422+
* LOCKING:
1423+
* Kernel thread context (may sleep).
1424+
*
1425+
* RETURNS:
1426+
* 0 on success, -errno otherwise.
1427+
*/
1428+
int ata_eh_read_sense_success_ncq_log(struct ata_link *link)
1429+
{
1430+
struct ata_device *dev = link->device;
1431+
struct ata_port *ap = dev->link->ap;
1432+
u8 *buf = ap->ncq_sense_buf;
1433+
struct ata_queued_cmd *qc;
1434+
unsigned int err_mask, tag;
1435+
u8 *sense, sk = 0, asc = 0, ascq = 0;
1436+
u64 sense_valid, val;
1437+
int ret = 0;
1438+
1439+
err_mask = ata_read_log_page(dev, ATA_LOG_SENSE_NCQ, 0, buf, 2);
1440+
if (err_mask) {
1441+
ata_dev_err(dev,
1442+
"Failed to read Sense Data for Successful NCQ Commands log\n");
1443+
return -EIO;
1444+
}
1445+
1446+
/* Check the log header */
1447+
val = get_unaligned_le64(&buf[0]);
1448+
if ((val & 0xffff) != 1 || ((val >> 16) & 0xff) != 0x0f) {
1449+
ata_dev_err(dev,
1450+
"Invalid Sense Data for Successful NCQ Commands log\n");
1451+
return -EIO;
1452+
}
1453+
1454+
sense_valid = (u64)buf[8] | ((u64)buf[9] << 8) |
1455+
((u64)buf[10] << 16) | ((u64)buf[11] << 24);
1456+
1457+
ata_qc_for_each_raw(ap, qc, tag) {
1458+
if (!(qc->flags & ATA_QCFLAG_EH) ||
1459+
!(qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD) ||
1460+
qc->err_mask ||
1461+
ata_dev_phys_link(qc->dev) != link)
1462+
continue;
1463+
1464+
/*
1465+
* If the command does not have any sense data, clear ATA_SENSE.
1466+
* Keep ATA_QCFLAG_EH_SUCCESS_CMD so that command is finished.
1467+
*/
1468+
if (!(sense_valid & (1ULL << tag))) {
1469+
qc->result_tf.status &= ~ATA_SENSE;
1470+
continue;
1471+
}
1472+
1473+
sense = &buf[32 + 24 * tag];
1474+
sk = sense[0];
1475+
asc = sense[1];
1476+
ascq = sense[2];
1477+
1478+
if (!ata_scsi_sense_is_valid(sk, asc, ascq)) {
1479+
ret = -EIO;
1480+
continue;
1481+
}
1482+
1483+
/* Set sense without also setting scsicmd->result */
1484+
scsi_build_sense_buffer(dev->flags & ATA_DFLAG_D_SENSE,
1485+
qc->scsicmd->sense_buffer, sk,
1486+
asc, ascq);
1487+
qc->flags |= ATA_QCFLAG_SENSE_VALID;
1488+
1489+
/*
1490+
* If we have sense data, call scsi_check_sense() in order to
1491+
* set the correct SCSI ML byte (if any). No point in checking
1492+
* the return value, since the command has already completed
1493+
* successfully.
1494+
*/
1495+
scsi_check_sense(qc->scsicmd);
1496+
}
1497+
1498+
return ret;
1499+
}
1500+
EXPORT_SYMBOL_GPL(ata_eh_read_sense_success_ncq_log);
1501+
14111502
/**
14121503
* ata_eh_analyze_ncq_error - analyze NCQ error
14131504
* @link: ATA link to analyze NCQ error for
@@ -1488,6 +1579,7 @@ void ata_eh_analyze_ncq_error(struct ata_link *link)
14881579

14891580
ata_qc_for_each_raw(ap, qc, tag) {
14901581
if (!(qc->flags & ATA_QCFLAG_EH) ||
1582+
qc->flags & ATA_QCFLAG_EH_SUCCESS_CMD ||
14911583
ata_dev_phys_link(qc->dev) != link)
14921584
continue;
14931585

include/linux/ata.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,8 @@ enum {
325325
ATA_LOG_CDL = 0x18,
326326
ATA_LOG_CDL_SIZE = ATA_SECT_SIZE,
327327
ATA_LOG_IDENTIFY_DEVICE = 0x30,
328+
ATA_LOG_SENSE_NCQ = 0x0F,
329+
ATA_LOG_SENSE_NCQ_SIZE = ATA_SECT_SIZE * 2,
328330
ATA_LOG_CONCURRENT_POSITIONING_RANGES = 0x47,
329331

330332
/* Identify device log pages: */
@@ -431,6 +433,7 @@ enum {
431433
SATA_DEVSLP = 0x09, /* Device Sleep */
432434

433435
SETFEATURE_SENSE_DATA = 0xC3, /* Sense Data Reporting feature */
436+
SETFEATURE_SENSE_DATA_SUCC_NCQ = 0xC4, /* Sense Data for successful NCQ commands */
434437

435438
/* feature values for SET_MAX */
436439
ATA_SET_MAX_ADDR = 0x00,

0 commit comments

Comments
 (0)