summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-07-06 09:41:58 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2017-07-06 09:41:58 -0700
commit109a5db5042c035ded330b948a710b9a0c20934d (patch)
tree5ebd38a4e36ea740a3de6edbc7b6a3250a776ef5 /drivers
parenta4c20b9a574b9720acf6c647eaff5e7e1e688086 (diff)
parentd80210f25ff0050245556bb8ce84d280d8fa4ca7 (diff)
downloadlinux-109a5db5042c035ded330b948a710b9a0c20934d.tar.gz
linux-109a5db5042c035ded330b948a710b9a0c20934d.tar.bz2
linux-109a5db5042c035ded330b948a710b9a0c20934d.zip
Merge branch 'for-4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata
Pull libata updates from Tejun Heo: - Christoph added support for TCG OPAL self encrypting disks - Minwoo added support for ATA PASS-THROUGH(32) - Linus Walleij removed spurious drvdata assignments in some drivers - Support for a few new device and other fixes * 'for-4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata: (33 commits) sd: add support for TCG OPAL self encrypting disks libata: fix build warning from unused goto label libata: Support for an ATA PASS-THROUGH(32) command. ahci: Add Device ID for ASMedia 1061R and 1062R sata_via: Enable optional hotplug on VT6420 ata: ahci_brcm: Avoid writing to read-only registers libata: Add the AHCI_HFLAG_NO_WRITE_TO_RO flag libata: Add the AHCI_HFLAG_YES_ALPM flag ata: ftide010: fix resource printing libata: make the function name in comment match the actual function ata: sata_rcar: make of_device_ids const. ata: pata_octeon_cf: make of_device_ids const. libata: Convert bare printks to pr_cont libahci: wrong comments in ahci_do_softreset() ata: declare ata_port_info structures as const ata: Add driver for Faraday Technology FTIDE010 ata: Add DT bindings for the Gemini SATA bridge ata: Add DT bindings for Faraday Technology FTIDE010 libata: implement SECURITY PROTOCOL IN/OUT libata: factor out a ata_identify_page_supported helper ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/Kconfig21
-rw-r--r--drivers/ata/Makefile2
-rw-r--r--drivers/ata/ahci.c2
-rw-r--r--drivers/ata/ahci.h3
-rw-r--r--drivers/ata/ahci_brcm.c12
-rw-r--r--drivers/ata/ahci_qoriq.c14
-rw-r--r--drivers/ata/libahci.c12
-rw-r--r--drivers/ata/libata-core.c214
-rw-r--r--drivers/ata/libata-eh.c64
-rw-r--r--drivers/ata/libata-scsi.c193
-rw-r--r--drivers/ata/libata-sff.c44
-rw-r--r--drivers/ata/libata.h4
-rw-r--r--drivers/ata/pata_bf54x.c2
-rw-r--r--drivers/ata/pata_ep93xx.c1
-rw-r--r--drivers/ata/pata_ftide010.c567
-rw-r--r--drivers/ata/pata_octeon_cf.c2
-rw-r--r--drivers/ata/pata_rb532_cf.c2
-rw-r--r--drivers/ata/pata_rdc.c2
-rw-r--r--drivers/ata/pata_samsung_cf.c2
-rw-r--r--drivers/ata/pata_sch.c2
-rw-r--r--drivers/ata/sata_dwc_460ex.c1
-rw-r--r--drivers/ata/sata_fsl.c2
-rw-r--r--drivers/ata/sata_gemini.c438
-rw-r--r--drivers/ata/sata_gemini.h21
-rw-r--r--drivers/ata/sata_inic162x.c2
-rw-r--r--drivers/ata/sata_rcar.c2
-rw-r--r--drivers/ata/sata_via.c23
-rw-r--r--drivers/scsi/sd.c53
-rw-r--r--drivers/scsi/sd.h2
29 files changed, 1476 insertions, 233 deletions
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index de3eaf051697..948fc86980a1 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -213,6 +213,16 @@ config SATA_FSL
If unsure, say N.
+config SATA_GEMINI
+ tristate "Gemini SATA bridge support"
+ depends on PATA_FTIDE010
+ default ARCH_GEMINI
+ help
+ This enabled support for the FTIDE010 to SATA bridge
+ found in Cortina Systems Gemini platform.
+
+ If unsure, say N.
+
config SATA_AHCI_SEATTLE
tristate "AMD Seattle 6.0Gbps AHCI SATA host controller support"
depends on ARCH_SEATTLE
@@ -599,6 +609,17 @@ config PATA_EP93XX
If unsure, say N.
+config PATA_FTIDE010
+ tristate "Faraday Technology FTIDE010 PATA support"
+ depends on OF
+ depends on ARM
+ default ARCH_GEMINI
+ help
+ This option enables support for the Faraday FTIDE010
+ PATA controller found in the Cortina Gemini SoCs.
+
+ If unsure, say N.
+
config PATA_HPT366
tristate "HPT 366/368 PATA support"
depends on PCI
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index cd931a5eba92..a26ef5a93919 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_SATA_ACARD_AHCI) += acard-ahci.o libahci.o
obj-$(CONFIG_SATA_AHCI_SEATTLE) += ahci_seattle.o libahci.o libahci_platform.o
obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o libahci_platform.o
obj-$(CONFIG_SATA_FSL) += sata_fsl.o
+obj-$(CONFIG_SATA_GEMINI) += sata_gemini.o
obj-$(CONFIG_SATA_INIC162X) += sata_inic162x.o
obj-$(CONFIG_SATA_SIL24) += sata_sil24.o
obj-$(CONFIG_SATA_DWC) += sata_dwc_460ex.o
@@ -60,6 +61,7 @@ obj-$(CONFIG_PATA_CS5536) += pata_cs5536.o
obj-$(CONFIG_PATA_CYPRESS) += pata_cypress.o
obj-$(CONFIG_PATA_EFAR) += pata_efar.o
obj-$(CONFIG_PATA_EP93XX) += pata_ep93xx.o
+obj-$(CONFIG_PATA_FTIDE010) += pata_ftide010.o
obj-$(CONFIG_PATA_HPT366) += pata_hpt366.o
obj-$(CONFIG_PATA_HPT37X) += pata_hpt37x.o
obj-$(CONFIG_PATA_HPT3X2N) += pata_hpt3x2n.o
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 1e1c355121e4..5a5fd0b404eb 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -548,6 +548,8 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci }, /* ASM1060 */
{ PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */
{ PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */
+ { PCI_VDEVICE(ASMEDIA, 0x0621), board_ahci }, /* ASM1061R */
+ { PCI_VDEVICE(ASMEDIA, 0x0622), board_ahci }, /* ASM1062R */
/*
* Samsung SSDs found on some macbooks. NCQ times out if MSI is
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 30f67a1a4f54..8b61123d2c3c 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -248,6 +248,9 @@ enum {
AHCI_HFLAG_MULTI_MSI = 0,
#endif
AHCI_HFLAG_WAKE_BEFORE_STOP = (1 << 22), /* wake before DMA stop */
+ AHCI_HFLAG_YES_ALPM = (1 << 23), /* force ALPM cap on */
+ AHCI_HFLAG_NO_WRITE_TO_RO = (1 << 24), /* don't write to read
+ only registers */
/* ap->flags bits */
diff --git a/drivers/ata/ahci_brcm.c b/drivers/ata/ahci_brcm.c
index 6f8a7341fa08..5936d1679bf3 100644
--- a/drivers/ata/ahci_brcm.c
+++ b/drivers/ata/ahci_brcm.c
@@ -39,7 +39,6 @@
#define PIODATA_ENDIAN_SHIFT 6
#define ENDIAN_SWAP_NONE 0
#define ENDIAN_SWAP_FULL 2
- #define OVERRIDE_HWINIT BIT(16)
#define SATA_TOP_CTRL_TP_CTRL 0x8
#define SATA_TOP_CTRL_PHY_CTRL 0xc
#define SATA_TOP_CTRL_PHY_CTRL_1 0x0
@@ -126,17 +125,13 @@ static inline void brcm_sata_writereg(u32 val, void __iomem *addr)
static void brcm_sata_alpm_init(struct ahci_host_priv *hpriv)
{
struct brcm_ahci_priv *priv = hpriv->plat_data;
- u32 bus_ctrl, port_ctrl, host_caps;
+ u32 port_ctrl, host_caps;
int i;
/* Enable support for ALPM */
- bus_ctrl = brcm_sata_readreg(priv->top_ctrl +
- SATA_TOP_CTRL_BUS_CTRL);
- brcm_sata_writereg(bus_ctrl | OVERRIDE_HWINIT,
- priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL);
host_caps = readl(hpriv->mmio + HOST_CAP);
- writel(host_caps | HOST_CAP_ALPM, hpriv->mmio);
- brcm_sata_writereg(bus_ctrl, priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL);
+ if (!(host_caps & HOST_CAP_ALPM))
+ hpriv->flags |= AHCI_HFLAG_YES_ALPM;
/*
* Adjust timeout to allow PLL sufficient time to lock while waking
@@ -360,6 +355,7 @@ static int brcm_ahci_probe(struct platform_device *pdev)
if (priv->quirks & BRCM_AHCI_QUIRK_NO_NCQ)
hpriv->flags |= AHCI_HFLAG_NO_NCQ;
+ hpriv->flags |= AHCI_HFLAG_NO_WRITE_TO_RO;
ret = ahci_platform_init_host(pdev, hpriv, &ahci_brcm_port_info,
&ahci_platform_sht);
diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c
index 4c96f3ac4976..b6b0bf76dfc7 100644
--- a/drivers/ata/ahci_qoriq.c
+++ b/drivers/ata/ahci_qoriq.c
@@ -47,12 +47,14 @@
#define SATA_ECC_DISABLE 0x00020000
#define ECC_DIS_ARMV8_CH2 0x80000000
+#define ECC_DIS_LS1088A 0x40000000
enum ahci_qoriq_type {
AHCI_LS1021A,
AHCI_LS1043A,
AHCI_LS2080A,
AHCI_LS1046A,
+ AHCI_LS1088A,
AHCI_LS2088A,
};
@@ -68,6 +70,7 @@ static const struct of_device_id ahci_qoriq_of_match[] = {
{ .compatible = "fsl,ls1043a-ahci", .data = (void *)AHCI_LS1043A},
{ .compatible = "fsl,ls2080a-ahci", .data = (void *)AHCI_LS2080A},
{ .compatible = "fsl,ls1046a-ahci", .data = (void *)AHCI_LS1046A},
+ { .compatible = "fsl,ls1088a-ahci", .data = (void *)AHCI_LS1088A},
{ .compatible = "fsl,ls2088a-ahci", .data = (void *)AHCI_LS2088A},
{},
};
@@ -203,6 +206,17 @@ static int ahci_qoriq_phy_init(struct ahci_host_priv *hpriv)
writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
break;
+ case AHCI_LS1088A:
+ if (!qpriv->ecc_addr)
+ return -EINVAL;
+ writel(readl(qpriv->ecc_addr) | ECC_DIS_LS1088A,
+ qpriv->ecc_addr);
+ writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
+ writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
+ if (qpriv->is_dmacoherent)
+ writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
+ break;
+
case AHCI_LS2088A:
writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 6154f0e2b81a..3e286d86ab42 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -504,6 +504,11 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
cap &= ~HOST_CAP_FBS;
}
+ if (!(cap & HOST_CAP_ALPM) && (hpriv->flags & AHCI_HFLAG_YES_ALPM)) {
+ dev_info(dev, "controller can do ALPM, turning on CAP_ALPM\n");
+ cap |= HOST_CAP_ALPM;
+ }
+
if (hpriv->force_port_map && port_map != hpriv->force_port_map) {
dev_info(dev, "forcing port_map 0x%x -> 0x%x\n",
port_map, hpriv->force_port_map);
@@ -940,7 +945,8 @@ int ahci_reset_controller(struct ata_host *host)
/* Some registers might be cleared on reset. Restore
* initial values.
*/
- ahci_restore_initial_config(host);
+ if (!(hpriv->flags & AHCI_HFLAG_NO_WRITE_TO_RO))
+ ahci_restore_initial_config(host);
} else
dev_info(host->dev, "skipping global host reset\n");
@@ -1400,7 +1406,7 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class,
ata_tf_init(link->device, &tf);
- /* issue the first D2H Register FIS */
+ /* issue the first H2D Register FIS */
msecs = 0;
now = jiffies;
if (time_after(deadline, now))
@@ -1417,7 +1423,7 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class,
/* spec says at least 5us, but be generous and sleep for 1ms */
ata_msleep(ap, 1);
- /* issue the second D2H Register FIS */
+ /* issue the second H2D Register FIS */
tf.ctl &= ~ATA_SRST;
ahci_exec_polled_cmd(ap, pmp, &tf, 0, 0, 0);
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index b82d6bb88d27..8453f9a4682f 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -2047,6 +2047,110 @@ retry:
return rc;
}
+/**
+ * ata_read_log_page - read a specific log page
+ * @dev: target device
+ * @log: log to read
+ * @page: page to read
+ * @buf: buffer to store read page
+ * @sectors: number of sectors to read
+ *
+ * Read log page using READ_LOG_EXT command.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep).
+ *
+ * RETURNS:
+ * 0 on success, AC_ERR_* mask otherwise.
+ */
+unsigned int ata_read_log_page(struct ata_device *dev, u8 log,
+ u8 page, void *buf, unsigned int sectors)
+{
+ unsigned long ap_flags = dev->link->ap->flags;
+ struct ata_taskfile tf;
+ unsigned int err_mask;
+ bool dma = false;
+
+ DPRINTK("read log page - log 0x%x, page 0x%x\n", log, page);
+
+ /*
+ * Return error without actually issuing the command on controllers
+ * which e.g. lockup on a read log page.
+ */
+ if (ap_flags & ATA_FLAG_NO_LOG_PAGE)
+ return AC_ERR_DEV;
+
+retry:
+ ata_tf_init(dev, &tf);
+ if (dev->dma_mode && ata_id_has_read_log_dma_ext(dev->id) &&
+ !(dev->horkage & ATA_HORKAGE_NO_NCQ_LOG)) {
+ tf.command = ATA_CMD_READ_LOG_DMA_EXT;
+ tf.protocol = ATA_PROT_DMA;
+ dma = true;
+ } else {
+ tf.command = ATA_CMD_READ_LOG_EXT;
+ tf.protocol = ATA_PROT_PIO;
+ dma = false;
+ }
+ tf.lbal = log;
+ tf.lbam = page;
+ tf.nsect = sectors;
+ tf.hob_nsect = sectors >> 8;
+ tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_LBA48 | ATA_TFLAG_DEVICE;
+
+ err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
+ buf, sectors * ATA_SECT_SIZE, 0);
+
+ if (err_mask && dma) {
+ dev->horkage |= ATA_HORKAGE_NO_NCQ_LOG;
+ ata_dev_warn(dev, "READ LOG DMA EXT failed, trying unqueued\n");
+ goto retry;
+ }
+
+ DPRINTK("EXIT, err_mask=%x\n", err_mask);
+ return err_mask;
+}
+
+static bool ata_log_supported(struct ata_device *dev, u8 log)
+{
+ struct ata_port *ap = dev->link->ap;
+
+ if (ata_read_log_page(dev, ATA_LOG_DIRECTORY, 0, ap->sector_buf, 1))
+ return false;
+ return get_unaligned_le16(&ap->sector_buf[log * 2]) ? true : false;
+}
+
+static bool ata_identify_page_supported(struct ata_device *dev, u8 page)
+{
+ struct ata_port *ap = dev->link->ap;
+ unsigned int err, i;
+
+ if (!ata_log_supported(dev, ATA_LOG_IDENTIFY_DEVICE)) {
+ ata_dev_warn(dev, "ATA Identify Device Log not supported\n");
+ return false;
+ }
+
+ /*
+ * Read IDENTIFY DEVICE data log, page 0, to figure out if the page is
+ * supported.
+ */
+ err = ata_read_log_page(dev, ATA_LOG_IDENTIFY_DEVICE, 0, ap->sector_buf,
+ 1);
+ if (err) {
+ ata_dev_info(dev,
+ "failed to get Device Identify Log Emask 0x%x\n",
+ err);
+ return false;
+ }
+
+ for (i = 0; i < ap->sector_buf[8]; i++) {
+ if (ap->sector_buf[9 + i] == page)
+ return true;
+ }
+
+ return false;
+}
+
static int ata_do_link_spd_horkage(struct ata_device *dev)
{
struct ata_link *plink = ata_dev_phys_link(dev);
@@ -2094,21 +2198,9 @@ static void ata_dev_config_ncq_send_recv(struct ata_device *dev)
{
struct ata_port *ap = dev->link->ap;
unsigned int err_mask;
- int log_index = ATA_LOG_NCQ_SEND_RECV * 2;
- u16 log_pages;
- err_mask = ata_read_log_page(dev, ATA_LOG_DIRECTORY,
- 0, ap->sector_buf, 1);
- if (err_mask) {
- ata_dev_dbg(dev,
- "failed to get Log Directory Emask 0x%x\n",
- err_mask);
- return;
- }
- log_pages = get_unaligned_le16(&ap->sector_buf[log_index]);
- if (!log_pages) {
- ata_dev_warn(dev,
- "NCQ Send/Recv Log not supported\n");
+ if (!ata_log_supported(dev, ATA_LOG_NCQ_SEND_RECV)) {
+ ata_dev_warn(dev, "NCQ Send/Recv Log not supported\n");
return;
}
err_mask = ata_read_log_page(dev, ATA_LOG_NCQ_SEND_RECV,
@@ -2135,19 +2227,8 @@ static void ata_dev_config_ncq_non_data(struct ata_device *dev)
{
struct ata_port *ap = dev->link->ap;
unsigned int err_mask;
- int log_index = ATA_LOG_NCQ_NON_DATA * 2;
- u16 log_pages;
- err_mask = ata_read_log_page(dev, ATA_LOG_DIRECTORY,
- 0, ap->sector_buf, 1);
- if (err_mask) {
- ata_dev_dbg(dev,
- "failed to get Log Directory Emask 0x%x\n",
- err_mask);
- return;
- }
- log_pages = get_unaligned_le16(&ap->sector_buf[log_index]);
- if (!log_pages) {
+ if (!ata_log_supported(dev, ATA_LOG_NCQ_NON_DATA)) {
ata_dev_warn(dev,
"NCQ Send/Recv Log not supported\n");
return;
@@ -2176,7 +2257,7 @@ static void ata_dev_config_ncq_prio(struct ata_device *dev)
}
err_mask = ata_read_log_page(dev,
- ATA_LOG_SATA_ID_DEV_DATA,
+ ATA_LOG_IDENTIFY_DEVICE,
ATA_LOG_SATA_SETTINGS,
ap->sector_buf,
1);
@@ -2275,8 +2356,6 @@ static void ata_dev_config_zac(struct ata_device *dev)
struct ata_port *ap = dev->link->ap;
unsigned int err_mask;
u8 *identify_buf = ap->sector_buf;
- int log_index = ATA_LOG_SATA_ID_DEV_DATA * 2, i, found = 0;
- u16 log_pages;
dev->zac_zones_optimal_open = U32_MAX;
dev->zac_zones_optimal_nonseq = U32_MAX;
@@ -2296,44 +2375,7 @@ static void ata_dev_config_zac(struct ata_device *dev)
if (!(dev->flags & ATA_DFLAG_ZAC))
return;
- /*
- * Read Log Directory to figure out if IDENTIFY DEVICE log
- * is supported.
- */
- err_mask = ata_read_log_page(dev, ATA_LOG_DIRECTORY,
- 0, ap->sector_buf, 1);
- if (err_mask) {
- ata_dev_info(dev,
- "failed to get Log Directory Emask 0x%x\n",
- err_mask);
- return;
- }
- log_pages = get_unaligned_le16(&ap->sector_buf[log_index]);
- if (log_pages == 0) {
- ata_dev_warn(dev,
- "ATA Identify Device Log not supported\n");
- return;
- }
- /*
- * Read IDENTIFY DEVICE data log, page 0, to figure out
- * if page 9 is supported.
- */
- err_mask = ata_read_log_page(dev, ATA_LOG_SATA_ID_DEV_DATA, 0,
- identify_buf, 1);
- if (err_mask) {
- ata_dev_info(dev,
- "failed to get Device Identify Log Emask 0x%x\n",
- err_mask);
- return;
- }
- log_pages = identify_buf[8];
- for (i = 0; i < log_pages; i++) {
- if (identify_buf[9 + i] == ATA_LOG_ZONED_INFORMATION) {
- found++;
- break;
- }
- }
- if (!found) {
+ if (!ata_identify_page_supported(dev, ATA_LOG_ZONED_INFORMATION)) {
ata_dev_warn(dev,
"ATA Zoned Information Log not supported\n");
return;
@@ -2342,7 +2384,7 @@ static void ata_dev_config_zac(struct ata_device *dev)
/*
* Read IDENTIFY DEVICE data log, page 9 (Zoned-device information)
*/
- err_mask = ata_read_log_page(dev, ATA_LOG_SATA_ID_DEV_DATA,
+ err_mask = ata_read_log_page(dev, ATA_LOG_IDENTIFY_DEVICE,
ATA_LOG_ZONED_INFORMATION,
identify_buf, 1);
if (!err_mask) {
@@ -2363,6 +2405,37 @@ static void ata_dev_config_zac(struct ata_device *dev)
}
}
+static void ata_dev_config_trusted(struct ata_device *dev)
+{
+ struct ata_port *ap = dev->link->ap;
+ u64 trusted_cap;
+ unsigned int err;
+
+ if (!ata_identify_page_supported(dev, ATA_LOG_SECURITY)) {
+ ata_dev_warn(dev,
+ "Security Log not supported\n");
+ return;
+ }
+
+ err = ata_read_log_page(dev, ATA_LOG_IDENTIFY_DEVICE, ATA_LOG_SECURITY,
+ ap->sector_buf, 1);
+ if (err) {
+ ata_dev_dbg(dev,
+ "failed to read Security Log, Emask 0x%x\n", err);
+ return;
+ }
+
+ trusted_cap = get_unaligned_le64(&ap->sector_buf[40]);
+ if (!(trusted_cap & (1ULL << 63))) {
+ ata_dev_dbg(dev,
+ "Trusted Computing capability qword not valid!\n");
+ return;
+ }
+
+ if (trusted_cap & (1 << 0))
+ dev->flags |= ATA_DFLAG_TRUSTED;
+}
+
/**
* ata_dev_configure - Configure the specified ATA/ATAPI device
* @dev: Target device to configure
@@ -2571,7 +2644,7 @@ int ata_dev_configure(struct ata_device *dev)
dev->flags |= ATA_DFLAG_DEVSLP;
err_mask = ata_read_log_page(dev,
- ATA_LOG_SATA_ID_DEV_DATA,
+ ATA_LOG_IDENTIFY_DEVICE,
ATA_LOG_SATA_SETTINGS,
sata_setting,
1);
@@ -2587,7 +2660,8 @@ int ata_dev_configure(struct ata_device *dev)
}
ata_dev_config_sense_reporting(dev);
ata_dev_config_zac(dev);
- dev->cdb_len = 16;
+ ata_dev_config_trusted(dev);
+ dev->cdb_len = 32;
}
/* ATAPI-specific feature tests */
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 7e33e200aae5..b70bcf6d2914 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1488,70 +1488,6 @@ static const char *ata_err_string(unsigned int err_mask)
}
/**
- * ata_read_log_page - read a specific log page
- * @dev: target device
- * @log: log to read
- * @page: page to read
- * @buf: buffer to store read page
- * @sectors: number of sectors to read
- *
- * Read log page using READ_LOG_EXT command.
- *
- * LOCKING:
- * Kernel thread context (may sleep).
- *
- * RETURNS:
- * 0 on success, AC_ERR_* mask otherwise.
- */
-unsigned int ata_read_log_page(struct ata_device *dev, u8 log,
- u8 page, void *buf, unsigned int sectors)
-{
- unsigned long ap_flags = dev->link->ap->flags;
- struct ata_taskfile tf;
- unsigned int err_mask;
- bool dma = false;
-
- DPRINTK("read log page - log 0x%x, page 0x%x\n", log, page);
-
- /*
- * Return error without actually issuing the command on controllers
- * which e.g. lockup on a read log page.
- */
- if (ap_flags & ATA_FLAG_NO_LOG_PAGE)
- return AC_ERR_DEV;
-
-retry:
- ata_tf_init(dev, &tf);
- if (dev->dma_mode && ata_id_has_read_log_dma_ext(dev->id) &&
- !(dev->horkage & ATA_HORKAGE_NO_NCQ_LOG)) {
- tf.command = ATA_CMD_READ_LOG_DMA_EXT;
- tf.protocol = ATA_PROT_DMA;
- dma = true;
- } else {
- tf.command = ATA_CMD_READ_LOG_EXT;
- tf.protocol = ATA_PROT_PIO;
- dma = false;
- }
- tf.lbal = log;
- tf.lbam = page;
- tf.nsect = sectors;
- tf.hob_nsect = sectors >> 8;
- tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_LBA48 | ATA_TFLAG_DEVICE;
-
- err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
- buf, sectors * ATA_SECT_SIZE, 0);
-
- if (err_mask && dma) {
- dev->horkage |= ATA_HORKAGE_NO_NCQ_LOG;
- ata_dev_warn(dev, "READ LOG DMA EXT failed, trying unqueued\n");
- goto retry;
- }
-
- DPRINTK("EXIT, err_mask=%x\n", err_mask);
- return err_mask;
-}
-
-/**
* ata_eh_read_log_10h - Read log page 10h for NCQ error details
* @dev: Device to read log page 10h from
* @tag: Resulting tag of the failed command
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index b0866f040d1f..d462c5a3a7ef 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -903,32 +903,32 @@ static void ata_dump_status(unsigned id, struct ata_taskfile *tf)
{
u8 stat = tf->command, err = tf->feature;
- printk(KERN_WARNING "ata%u: status=0x%02x { ", id, stat);
+ pr_warn("ata%u: status=0x%02x { ", id, stat);
if (stat & ATA_BUSY) {
- printk("Busy }\n"); /* Data is not valid in this case */
+ pr_cont("Busy }\n"); /* Data is not valid in this case */
} else {
- if (stat & ATA_DRDY) printk("DriveReady ");
- if (stat & ATA_DF) printk("DeviceFault ");
- if (stat & ATA_DSC) printk("SeekComplete ");
- if (stat & ATA_DRQ) printk("DataRequest ");
- if (stat & ATA_CORR) printk("CorrectedError ");
- if (stat & ATA_SENSE) printk("Sense ");
- if (stat & ATA_ERR) printk("Error ");
- printk("}\n");
+ if (stat & ATA_DRDY) pr_cont("DriveReady ");
+ if (stat & ATA_DF) pr_cont("DeviceFault ");
+ if (stat & ATA_DSC) pr_cont("SeekComplete ");
+ if (stat & ATA_DRQ) pr_cont("DataRequest ");
+ if (stat & ATA_CORR) pr_cont("CorrectedError ");
+ if (stat & ATA_SENSE) pr_cont("Sense ");
+ if (stat & ATA_ERR) pr_cont("Error ");
+ pr_cont("}\n");
if (err) {
- printk(KERN_WARNING "ata%u: error=0x%02x { ", id, err);
- if (err & ATA_ABORTED) printk("DriveStatusError ");
+ pr_warn("ata%u: error=0x%02x { ", id, err);
+ if (err & ATA_ABORTED) pr_cont("DriveStatusError ");
if (err & ATA_ICRC) {
if (err & ATA_ABORTED)
- printk("BadCRC ");
- else printk("Sector ");
+ pr_cont("BadCRC ");
+ else pr_cont("Sector ");
}
- if (err & ATA_UNC) printk("UncorrectableError ");
- if (err & ATA_IDNF) printk("SectorIdNotFound ");
- if (err & ATA_TRK0NF) printk("TrackZeroNotFound ");
- if (err & ATA_AMNF) printk("AddrMarkNotFound ");
- printk("}\n");
+ if (err & ATA_UNC) pr_cont("UncorrectableError ");
+ if (err & ATA_IDNF) pr_cont("SectorIdNotFound ");
+ if (err & ATA_TRK0NF) pr_cont("TrackZeroNotFound ");
+ if (err & ATA_AMNF) pr_cont("AddrMarkNotFound ");
+ pr_cont("}\n");
}
}
}
@@ -1059,8 +1059,7 @@ static void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk,
translate_done:
if (verbose)
- printk(KERN_ERR "ata%u: translated ATA stat/err 0x%02x/%02x "
- "to SCSI SK/ASC/ASCQ 0x%x/%02x/%02x\n",
+ pr_err("ata%u: translated ATA stat/err 0x%02x/%02x to SCSI SK/ASC/ASCQ 0x%x/%02x/%02x\n",
id, drv_stat, drv_err, *sk, *asc, *ascq);
return;
}
@@ -1322,6 +1321,9 @@ static int ata_scsi_dev_config(struct scsi_device *sdev,
blk_queue_flush_queueable(q, false);
+ if (dev->flags & ATA_DFLAG_TRUSTED)
+ sdev->security_supported = 1;
+
dev->sdev = sdev;
return 0;
}
@@ -3127,7 +3129,7 @@ ata_scsi_map_proto(u8 byte1)
* ata_scsi_pass_thru - convert ATA pass-thru CDB to taskfile
* @qc: command structure to be initialized
*
- * Handles either 12 or 16-byte versions of the CDB.
+ * Handles either 12, 16, or 32-byte versions of the CDB.
*
* RETURNS:
* Zero on success, non-zero on failure.
@@ -3139,13 +3141,19 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
struct ata_device *dev = qc->dev;
const u8 *cdb = scmd->cmnd;
u16 fp;
+ u16 cdb_offset = 0;
+
+ /* 7Fh variable length cmd means a ata pass-thru(32) */
+ if (cdb[0] == VARIABLE_LENGTH_CMD)
+ cdb_offset = 9;
- if ((tf->protocol = ata_scsi_map_proto(cdb[1])) == ATA_PROT_UNKNOWN) {
+ tf->protocol = ata_scsi_map_proto(cdb[1 + cdb_offset]);
+ if (tf->protocol == ATA_PROT_UNKNOWN) {
fp = 1;
goto invalid_fld;
}
- if (ata_is_ncq(tf->protocol) && (cdb[2] & 0x3) == 0)
+ if (ata_is_ncq(tf->protocol) && (cdb[2 + cdb_offset] & 0x3) == 0)
tf->protocol = ATA_PROT_NCQ_NODATA;
/* enable LBA */
@@ -3181,7 +3189,7 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
tf->lbah = cdb[12];
tf->device = cdb[13];
tf->command = cdb[14];
- } else {
+ } else if (cdb[0] == ATA_12) {
/*
* 12-byte CDB - incapable of extended commands.
*/
@@ -3194,6 +3202,30 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
tf->lbah = cdb[7];
tf->device = cdb[8];
tf->command = cdb[9];
+ } else {
+ /*
+ * 32-byte CDB - may contain extended command fields.
+ *
+ * If that is the case, copy the upper byte register values.
+ */
+ if (cdb[10] & 0x01) {
+ tf->hob_feature = cdb[20];
+ tf->hob_nsect = cdb[22];
+ tf->hob_lbal = cdb[16];
+ tf->hob_lbam = cdb[15];
+ tf->hob_lbah = cdb[14];
+ tf->flags |= ATA_TFLAG_LBA48;
+ } else
+ tf->flags &= ~ATA_TFLAG_LBA48;
+
+ tf->feature = cdb[21];
+ tf->nsect = cdb[23];
+ tf->lbal = cdb[19];
+ tf->lbam = cdb[18];
+ tf->lbah = cdb[17];
+ tf->device = cdb[24];
+ tf->command = cdb[25];
+ tf->auxiliary = get_unaligned_be32(&cdb[28]);
}
/* For NCQ commands copy the tag value */
@@ -3564,6 +3596,11 @@ static unsigned int ata_scsiop_maint_in(struct ata_scsi_args *args, u8 *rbuf)
dev->class == ATA_DEV_ZAC)
supported = 3;
break;
+ case SECURITY_PROTOCOL_IN:
+ case SECURITY_PROTOCOL_OUT:
+ if (dev->flags & ATA_DFLAG_TRUSTED)
+ supported = 3;
+ break;
default:
break;
}
@@ -3910,7 +3947,7 @@ static int ata_mselect_control(struct ata_queued_cmd *qc,
}
/**
- * ata_scsiop_mode_select - Simulate MODE SELECT 6, 10 commands
+ * ata_scsi_mode_select_xlat - Simulate MODE SELECT 6, 10 commands
* @qc: Storage for translated ATA taskfile
*
* Converts a MODE SELECT command to an ATA SET FEATURES taskfile.
@@ -4068,6 +4105,99 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc)
return 1;
}
+static u8 ata_scsi_trusted_op(u32 len, bool send, bool dma)
+{
+ if (len == 0)
+ return ATA_CMD_TRUSTED_NONDATA;
+ else if (send)
+ return dma ? ATA_CMD_TRUSTED_SND_DMA : ATA_CMD_TRUSTED_SND;
+ else
+ return dma ? ATA_CMD_TRUSTED_RCV_DMA : ATA_CMD_TRUSTED_RCV;
+}
+
+static unsigned int ata_scsi_security_inout_xlat(struct ata_queued_cmd *qc)
+{
+ struct scsi_cmnd *scmd = qc->scsicmd;
+ const u8 *cdb = scmd->cmnd;
+ struct ata_taskfile *tf = &qc->tf;
+ u8 secp = cdb[1];
+ bool send = (cdb[0] == SECURITY_PROTOCOL_OUT);
+ u16 spsp = get_unaligned_be16(&cdb[2]);
+ u32 len = get_unaligned_be32(&cdb[6]);
+ bool dma = !(qc->dev->flags & ATA_DFLAG_PIO);
+
+ /*
+ * We don't support the ATA "security" protocol.
+ */
+ if (secp == 0xef) {
+ ata_scsi_set_invalid_field(qc->dev, scmd, 1, 0);
+ return 1;
+ }
+
+ if (cdb[4] & 7) { /* INC_512 */
+ if (len > 0xffff) {
+ ata_scsi_set_invalid_field(qc->dev, scmd, 6, 0);
+ return 1;
+ }
+ } else {
+ if (len > 0x01fffe00) {
+ ata_scsi_set_invalid_field(qc->dev, scmd, 6, 0);
+ return 1;
+ }
+
+ /* convert to the sector-based ATA addressing */
+ len = (len + 511) / 512;
+ }