Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

libata: Implement support for sense data reporting

ACS-4 defines a sense data reporting feature set.
This patch implements support for it.

Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Tejun Heo <tj@kernel.org>

authored by

Hannes Reinecke and committed by
Tejun Heo
fe7173c2 42b966fb

+120 -4
+19 -1
drivers/ata/libata-core.c
··· 2144 2144 return 0; 2145 2145 } 2146 2146 2147 + static void ata_dev_config_sense_reporting(struct ata_device *dev) 2148 + { 2149 + unsigned int err_mask; 2150 + 2151 + if (!ata_id_has_sense_reporting(dev->id)) 2152 + return; 2153 + 2154 + if (ata_id_sense_reporting_enabled(dev->id)) 2155 + return; 2156 + 2157 + err_mask = ata_dev_set_feature(dev, SETFEATURE_SENSE_DATA, 0x1); 2158 + if (err_mask) { 2159 + ata_dev_dbg(dev, 2160 + "failed to enable Sense Data Reporting, Emask 0x%x\n", 2161 + err_mask); 2162 + } 2163 + } 2164 + 2147 2165 /** 2148 2166 * ata_dev_configure - Configure the specified ATA/ATAPI device 2149 2167 * @dev: Target device to configure ··· 2384 2366 dev->devslp_timing[i] = sata_setting[j]; 2385 2367 } 2386 2368 } 2387 - 2369 + ata_dev_config_sense_reporting(dev); 2388 2370 dev->cdb_len = 16; 2389 2371 } 2390 2372
+83 -3
drivers/ata/libata-eh.c
··· 1618 1618 } 1619 1619 1620 1620 /** 1621 + * ata_eh_request_sense - perform REQUEST_SENSE_DATA_EXT 1622 + * @dev: device to perform REQUEST_SENSE_SENSE_DATA_EXT to 1623 + * @sense_buf: result sense data buffer (SCSI_SENSE_BUFFERSIZE bytes long) 1624 + * @dfl_sense_key: default sense key to use 1625 + * 1626 + * Perform REQUEST_SENSE_DATA_EXT after the device reported CHECK 1627 + * SENSE. This function is EH helper. 1628 + * 1629 + * LOCKING: 1630 + * Kernel thread context (may sleep). 1631 + * 1632 + * RETURNS: 1633 + * encoded sense data on success, 0 on failure or if sense data 1634 + * is not available. 1635 + */ 1636 + static u32 ata_eh_request_sense(struct ata_queued_cmd *qc, 1637 + struct scsi_cmnd *cmd) 1638 + { 1639 + struct ata_device *dev = qc->dev; 1640 + struct ata_taskfile tf; 1641 + unsigned int err_mask; 1642 + 1643 + if (!cmd) 1644 + return 0; 1645 + 1646 + DPRINTK("ATA request sense\n"); 1647 + ata_dev_warn(dev, "request sense\n"); 1648 + if (!ata_id_sense_reporting_enabled(dev->id)) { 1649 + ata_dev_warn(qc->dev, "sense data reporting disabled\n"); 1650 + return 0; 1651 + } 1652 + ata_tf_init(dev, &tf); 1653 + 1654 + tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; 1655 + tf.flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48; 1656 + tf.command = ATA_CMD_REQ_SENSE_DATA; 1657 + tf.protocol = ATA_PROT_NODATA; 1658 + 1659 + err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0); 1660 + /* 1661 + * ACS-4 states: 1662 + * The device may set the SENSE DATA AVAILABLE bit to one in the 1663 + * STATUS field and clear the ERROR bit to zero in the STATUS field 1664 + * to indicate that the command returned completion without an error 1665 + * and the sense data described in table 306 is available. 1666 + * 1667 + * IOW the 'ATA_SENSE' bit might not be set even though valid 1668 + * sense data is available. 1669 + * So check for both. 1670 + */ 1671 + if ((tf.command & ATA_SENSE) || 1672 + tf.lbah != 0 || tf.lbam != 0 || tf.lbal != 0) { 1673 + ata_scsi_set_sense(cmd, tf.lbah, tf.lbam, tf.lbal); 1674 + qc->flags |= ATA_QCFLAG_SENSE_VALID; 1675 + ata_dev_warn(dev, "sense data %02x/%02x/%02x\n", 1676 + tf.lbah, tf.lbam, tf.lbal); 1677 + } else { 1678 + ata_dev_warn(dev, "request sense failed stat %02x emask %x\n", 1679 + tf.command, err_mask); 1680 + } 1681 + return err_mask; 1682 + } 1683 + 1684 + /** 1621 1685 * atapi_eh_request_sense - perform ATAPI REQUEST_SENSE 1622 1686 * @dev: device to perform REQUEST_SENSE to 1623 1687 * @sense_buf: result sense data buffer (SCSI_SENSE_BUFFERSIZE bytes long) ··· 1884 1820 return ATA_EH_RESET; 1885 1821 } 1886 1822 1887 - /* Set by NCQ autosense */ 1823 + /* 1824 + * Sense data reporting does not work if the 1825 + * device fault bit is set. 1826 + */ 1827 + if ((stat & ATA_SENSE) && !(stat & ATA_DF) && 1828 + !(qc->flags & ATA_QCFLAG_SENSE_VALID)) { 1829 + if (!(qc->ap->pflags & ATA_PFLAG_FROZEN)) { 1830 + tmp = ata_eh_request_sense(qc, qc->scsicmd); 1831 + if (tmp) 1832 + qc->err_mask |= tmp; 1833 + } else { 1834 + ata_dev_warn(qc->dev, "sense data available but port frozen\n"); 1835 + } 1836 + } 1837 + 1838 + /* Set by NCQ autosense or request sense above */ 1888 1839 if (qc->flags & ATA_QCFLAG_SENSE_VALID) 1889 1840 return 0; 1890 1841 ··· 2645 2566 2646 2567 #ifdef CONFIG_ATA_VERBOSE_ERROR 2647 2568 if (res->command & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ | 2648 - ATA_ERR)) { 2569 + ATA_SENSE | ATA_ERR)) { 2649 2570 if (res->command & ATA_BUSY) 2650 2571 ata_dev_err(qc->dev, "status: { Busy }\n"); 2651 2572 else 2652 - ata_dev_err(qc->dev, "status: { %s%s%s%s}\n", 2573 + ata_dev_err(qc->dev, "status: { %s%s%s%s%s}\n", 2653 2574 res->command & ATA_DRDY ? "DRDY " : "", 2654 2575 res->command & ATA_DF ? "DF " : "", 2655 2576 res->command & ATA_DRQ ? "DRQ " : "", 2577 + res->command & ATA_SENSE ? "SENSE " : "", 2656 2578 res->command & ATA_ERR ? "ERR " : ""); 2657 2579 } 2658 2580
+18
include/linux/ata.h
··· 94 94 ATA_ID_SECTOR_SIZE = 106, 95 95 ATA_ID_WWN = 108, 96 96 ATA_ID_LOGICAL_SECTOR_SIZE = 117, /* and 118 */ 97 + ATA_ID_COMMAND_SET_3 = 119, 98 + ATA_ID_COMMAND_SET_4 = 120, 97 99 ATA_ID_LAST_LUN = 126, 98 100 ATA_ID_DLF = 128, 99 101 ATA_ID_CSFO = 129, ··· 383 381 SATA_AN = 0x05, /* Asynchronous Notification */ 384 382 SATA_SSP = 0x06, /* Software Settings Preservation */ 385 383 SATA_DEVSLP = 0x09, /* Device Sleep */ 384 + 385 + SETFEATURE_SENSE_DATA = 0xC3, /* Sense Data Reporting feature */ 386 386 387 387 /* feature values for SET_MAX */ 388 388 ATA_SET_MAX_ADDR = 0x00, ··· 707 703 if (!(id[ATA_ID_CFS_ENABLE_2] & (1 << 15))) 708 704 return false; 709 705 return id[ATA_ID_COMMAND_SET_3] & (1 << 3); 706 + } 707 + 708 + static inline bool ata_id_has_sense_reporting(const u16 *id) 709 + { 710 + if (!(id[ATA_ID_CFS_ENABLE_2] & (1 << 15))) 711 + return false; 712 + return id[ATA_ID_COMMAND_SET_3] & (1 << 6); 713 + } 714 + 715 + static inline bool ata_id_sense_reporting_enabled(const u16 *id) 716 + { 717 + if (!(id[ATA_ID_CFS_ENABLE_2] & (1 << 15))) 718 + return false; 719 + return id[ATA_ID_COMMAND_SET_4] & (1 << 6); 710 720 } 711 721 712 722 /**