From 2facc6dacc64f14efc6fb81e2019f48e992166e2 Mon Sep 17 00:00:00 2001 From: Tang Yuantian Date: Sun, 9 Oct 2016 16:51:04 +0800 Subject: ahci: qoriq: added ls1046a platform support Ls1046a is a new introduced soc which supports ATA3.0. Signed-off-by: Tang Yuantian Signed-off-by: Tejun Heo --- drivers/ata/ahci_qoriq.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c index 1eba8dff875e..9884c8c6e934 100644 --- a/drivers/ata/ahci_qoriq.c +++ b/drivers/ata/ahci_qoriq.c @@ -46,11 +46,13 @@ #define LS1021A_AXICC_ADDR 0xC0 #define SATA_ECC_DISABLE 0x00020000 +#define LS1046A_SATA_ECC_DIS 0x80000000 enum ahci_qoriq_type { AHCI_LS1021A, AHCI_LS1043A, AHCI_LS2080A, + AHCI_LS1046A, }; struct ahci_qoriq_priv { @@ -63,6 +65,7 @@ static const struct of_device_id ahci_qoriq_of_match[] = { { .compatible = "fsl,ls1021a-ahci", .data = (void *)AHCI_LS1021A}, { .compatible = "fsl,ls1043a-ahci", .data = (void *)AHCI_LS1043A}, { .compatible = "fsl,ls2080a-ahci", .data = (void *)AHCI_LS2080A}, + { .compatible = "fsl,ls1046a-ahci", .data = (void *)AHCI_LS1046A}, {}, }; MODULE_DEVICE_TABLE(of, ahci_qoriq_of_match); @@ -175,6 +178,13 @@ static int ahci_qoriq_phy_init(struct ahci_host_priv *hpriv) writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS); writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC); break; + + case AHCI_LS1046A: + writel(LS1046A_SATA_ECC_DIS, qpriv->ecc_addr); + writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1); + writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS); + writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC); + break; } return 0; @@ -204,9 +214,9 @@ static int ahci_qoriq_probe(struct platform_device *pdev) qoriq_priv->type = (enum ahci_qoriq_type)of_id->data; - if (qoriq_priv->type == AHCI_LS1021A) { - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - "sata-ecc"); + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "sata-ecc"); + if (res) { qoriq_priv->ecc_addr = devm_ioremap_resource(dev, res); if (IS_ERR(qoriq_priv->ecc_addr)) return PTR_ERR(qoriq_priv->ecc_addr); -- cgit v1.2.3 From 8e061784b51ec4a4efed0deaafb5bd9725bf5b06 Mon Sep 17 00:00:00 2001 From: Adam Manzanares Date: Mon, 17 Oct 2016 11:27:29 -0700 Subject: ata: Enabling ATA Command Priorities This patch checks to see if an ATA device supports NCQ command priorities. If so and the user has specified an iocontext that indicates IO_PRIO_CLASS_RT then we build a tf with a high priority command. This is done to improve the tail latency of commands that are high priority by passing priority to the device. tj: Removed trivial ata_ncq_prio_enabled() and open-coded the test. Signed-off-by: Adam Manzanares Signed-off-by: Tejun Heo --- drivers/ata/libata-core.c | 35 ++++++++++++++++++++++++++++++++++- drivers/ata/libata-scsi.c | 6 +++++- drivers/ata/libata.h | 2 +- include/linux/ata.h | 6 ++++++ include/linux/libata.h | 3 +++ 5 files changed, 49 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 223a770f78f3..8346faf63337 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -739,6 +739,7 @@ u64 ata_tf_read_block(const struct ata_taskfile *tf, struct ata_device *dev) * @n_block: Number of blocks * @tf_flags: RW/FUA etc... * @tag: tag + * @class: IO priority class * * LOCKING: * None. @@ -753,7 +754,7 @@ u64 ata_tf_read_block(const struct ata_taskfile *tf, struct ata_device *dev) */ int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, u64 block, u32 n_block, unsigned int tf_flags, - unsigned int tag) + unsigned int tag, int class) { tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; tf->flags |= tf_flags; @@ -785,6 +786,12 @@ int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, tf->device = ATA_LBA; if (tf->flags & ATA_TFLAG_FUA) tf->device |= 1 << 7; + + if (dev->flags & ATA_DFLAG_NCQ_PRIO) { + if (class == IOPRIO_CLASS_RT) + tf->hob_nsect |= ATA_PRIO_HIGH << + ATA_SHIFT_PRIO; + } } else if (dev->flags & ATA_DFLAG_LBA) { tf->flags |= ATA_TFLAG_LBA; @@ -2156,6 +2163,30 @@ static void ata_dev_config_ncq_non_data(struct ata_device *dev) } } +static void ata_dev_config_ncq_prio(struct ata_device *dev) +{ + struct ata_port *ap = dev->link->ap; + unsigned int err_mask; + + err_mask = ata_read_log_page(dev, + ATA_LOG_SATA_ID_DEV_DATA, + ATA_LOG_SATA_SETTINGS, + ap->sector_buf, + 1); + if (err_mask) { + ata_dev_dbg(dev, + "failed to get Identify Device data, Emask 0x%x\n", + err_mask); + return; + } + + if (ap->sector_buf[ATA_LOG_NCQ_PRIO_OFFSET] & BIT(3)) + dev->flags |= ATA_DFLAG_NCQ_PRIO; + else + ata_dev_dbg(dev, "SATA page does not support priority\n"); + +} + static int ata_dev_config_ncq(struct ata_device *dev, char *desc, size_t desc_sz) { @@ -2205,6 +2236,8 @@ static int ata_dev_config_ncq(struct ata_device *dev, ata_dev_config_ncq_send_recv(dev); if (ata_id_has_ncq_non_data(dev->id)) ata_dev_config_ncq_non_data(dev); + if (ata_id_has_ncq_prio(dev->id)) + ata_dev_config_ncq_prio(dev); } return 0; diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 9cceb4a875a5..2bccc3c7de48 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -50,6 +50,7 @@ #include #include #include +#include #include "libata.h" #include "libata-transport.h" @@ -1755,6 +1756,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) { struct scsi_cmnd *scmd = qc->scsicmd; const u8 *cdb = scmd->cmnd; + struct request *rq = scmd->request; + int class = IOPRIO_PRIO_CLASS(req_get_ioprio(rq)); unsigned int tf_flags = 0; u64 block; u32 n_block; @@ -1821,7 +1824,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc) qc->nbytes = n_block * scmd->device->sector_size; rc = ata_build_rw_tf(&qc->tf, qc->dev, block, n_block, tf_flags, - qc->tag); + qc->tag, class); + if (likely(rc == 0)) return 0; diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 3b301a48007c..8f3a5596dd67 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -66,7 +66,7 @@ extern u64 ata_tf_to_lba48(const struct ata_taskfile *tf); extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag); extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, u64 block, u32 n_block, unsigned int tf_flags, - unsigned int tag); + unsigned int tag, int class); extern u64 ata_tf_read_block(const struct ata_taskfile *tf, struct ata_device *dev); extern unsigned ata_exec_internal(struct ata_device *dev, diff --git a/include/linux/ata.h b/include/linux/ata.h index fdb180367ba1..af6859b3a93d 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -348,6 +348,7 @@ enum { ATA_LOG_DEVSLP_DETO = 0x01, ATA_LOG_DEVSLP_VALID = 0x07, ATA_LOG_DEVSLP_VALID_MASK = 0x80, + ATA_LOG_NCQ_PRIO_OFFSET = 0x09, /* NCQ send and receive log */ ATA_LOG_NCQ_SEND_RECV_SUBCMDS_OFFSET = 0x00, @@ -940,6 +941,11 @@ static inline bool ata_id_has_ncq_non_data(const u16 *id) return id[ATA_ID_SATA_CAPABILITY_2] & BIT(5); } +static inline bool ata_id_has_ncq_prio(const u16 *id) +{ + return id[ATA_ID_SATA_CAPABILITY] & BIT(12); +} + static inline bool ata_id_has_trim(const u16 *id) { if (ata_id_major_version(id) >= 7 && diff --git a/include/linux/libata.h b/include/linux/libata.h index 616eef4d81ea..90b69a6293a3 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -166,6 +166,7 @@ enum { ATA_DFLAG_NO_UNLOAD = (1 << 17), /* device doesn't support unload */ ATA_DFLAG_UNLOCK_HPA = (1 << 18), /* unlock HPA */ ATA_DFLAG_NCQ_SEND_RECV = (1 << 19), /* device supports NCQ SEND and RECV */ + ATA_DFLAG_NCQ_PRIO = (1 << 20), /* device supports NCQ priority */ ATA_DFLAG_INIT_MASK = (1 << 24) - 1, ATA_DFLAG_DETACH = (1 << 24), @@ -342,7 +343,9 @@ enum { ATA_SHIFT_PIO = 0, ATA_SHIFT_MWDMA = ATA_SHIFT_PIO + ATA_NR_PIO_MODES, ATA_SHIFT_UDMA = ATA_SHIFT_MWDMA + ATA_NR_MWDMA_MODES, + ATA_SHIFT_PRIO = 6, + ATA_PRIO_HIGH = 2, /* size of buffer to pad xfers ending on unaligned boundaries */ ATA_DMA_PAD_SZ = 4, -- cgit v1.2.3 From 84f95243b5439a20c33837075b88926bfa00c4ec Mon Sep 17 00:00:00 2001 From: Adam Manzanares Date: Mon, 17 Oct 2016 11:27:30 -0700 Subject: ata: ATA Command Priority Disabled By Default Add a sysfs entry to turn on priority information being passed to a ATA device. By default this feature is turned off. This patch depends on ata: Enabling ATA Command Priorities tj: Renamed ncq_prio_on to ncq_prio_enable and removed trivial ata_ncq_prio_on() and open-coded the test. Signed-off-by: Adam Manzanares Signed-off-by: Tejun Heo --- drivers/ata/libahci.c | 1 + drivers/ata/libata-core.c | 3 ++- drivers/ata/libata-scsi.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++ include/linux/libata.h | 2 ++ 4 files changed, 73 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 0d028ead99e8..ee7db3119b18 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -140,6 +140,7 @@ EXPORT_SYMBOL_GPL(ahci_shost_attrs); struct device_attribute *ahci_sdev_attrs[] = { &dev_attr_sw_activity, &dev_attr_unload_heads, + &dev_attr_ncq_prio_enable, NULL }; EXPORT_SYMBOL_GPL(ahci_sdev_attrs); diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 8346faf63337..b294339159a4 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -787,7 +787,8 @@ int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, if (tf->flags & ATA_TFLAG_FUA) tf->device |= 1 << 7; - if (dev->flags & ATA_DFLAG_NCQ_PRIO) { + if ((dev->flags & ATA_DFLAG_NCQ_PRIO) && + (dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLE)) { if (class == IOPRIO_CLASS_RT) tf->hob_nsect |= ATA_PRIO_HIGH << ATA_SHIFT_PRIO; diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 2bccc3c7de48..87597a3f6149 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -271,6 +271,73 @@ DEVICE_ATTR(unload_heads, S_IRUGO | S_IWUSR, ata_scsi_park_show, ata_scsi_park_store); EXPORT_SYMBOL_GPL(dev_attr_unload_heads); +static ssize_t ata_ncq_prio_enable_show(struct device *device, + struct device_attribute *attr, char *buf) +{ + struct scsi_device *sdev = to_scsi_device(device); + struct ata_port *ap; + struct ata_device *dev; + bool ncq_prio_enable; + int rc = 0; + + ap = ata_shost_to_port(sdev->host); + + spin_lock_irq(ap->lock); + dev = ata_scsi_find_dev(ap, sdev); + if (!dev) { + rc = -ENODEV; + goto unlock; + } + + ncq_prio_enable = dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLE; + +unlock: + spin_unlock_irq(ap->lock); + + return rc ? rc : snprintf(buf, 20, "%u\n", ncq_prio_enable); +} + +static ssize_t ata_ncq_prio_enable_store(struct device *device, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct scsi_device *sdev = to_scsi_device(device); + struct ata_port *ap; + struct ata_device *dev; + long int input; + unsigned long flags; + int rc; + + rc = kstrtol(buf, 10, &input); + if (rc) + return rc; + if ((input < 0) || (input > 1)) + return -EINVAL; + + ap = ata_shost_to_port(sdev->host); + + spin_lock_irqsave(ap->lock, flags); + dev = ata_scsi_find_dev(ap, sdev); + if (unlikely(!dev)) { + rc = -ENODEV; + goto unlock; + } + + if (input) + dev->flags |= ATA_DFLAG_NCQ_PRIO_ENABLE; + else + dev->flags &= ~ATA_DFLAG_NCQ_PRIO_ENABLE; + +unlock: + spin_unlock_irqrestore(ap->lock, flags); + + return rc ? rc : len; +} + +DEVICE_ATTR(ncq_prio_enable, S_IRUGO | S_IWUSR, + ata_ncq_prio_enable_show, ata_ncq_prio_enable_store); +EXPORT_SYMBOL_GPL(dev_attr_ncq_prio_enable); + void ata_scsi_set_sense(struct ata_device *dev, struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq) { @@ -402,6 +469,7 @@ EXPORT_SYMBOL_GPL(dev_attr_sw_activity); struct device_attribute *ata_common_sdev_attrs[] = { &dev_attr_unload_heads, + &dev_attr_ncq_prio_enable, NULL }; EXPORT_SYMBOL_GPL(ata_common_sdev_attrs); diff --git a/include/linux/libata.h b/include/linux/libata.h index 90b69a6293a3..c170be548b7f 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -167,6 +167,7 @@ enum { ATA_DFLAG_UNLOCK_HPA = (1 << 18), /* unlock HPA */ ATA_DFLAG_NCQ_SEND_RECV = (1 << 19), /* device supports NCQ SEND and RECV */ ATA_DFLAG_NCQ_PRIO = (1 << 20), /* device supports NCQ priority */ + ATA_DFLAG_NCQ_PRIO_ENABLE = (1 << 21), /* Priority cmds sent to dev */ ATA_DFLAG_INIT_MASK = (1 << 24) - 1, ATA_DFLAG_DETACH = (1 << 24), @@ -545,6 +546,7 @@ typedef void (*ata_postreset_fn_t)(struct ata_link *link, unsigned int *classes) extern struct device_attribute dev_attr_link_power_management_policy; extern struct device_attribute dev_attr_unload_heads; +extern struct device_attribute dev_attr_ncq_prio_enable; extern struct device_attribute dev_attr_em_message_type; extern struct device_attribute dev_attr_em_message; extern struct device_attribute dev_attr_sw_activity; -- cgit v1.2.3 From 4e647d960c510e0d5cd700058fb8ddd529c390ee Mon Sep 17 00:00:00 2001 From: Adam Manzanares Date: Wed, 19 Oct 2016 20:40:19 -0700 Subject: ata: set ncq_prio_enabled iff device has support We previously had a check to see if the device has support for prioritized ncq commands and a check to see if a device flag is set, through a sysfs variable, in order to send a prioritized command. This patch only allows the sysfs variable to be set if the device supports prioritized commands enabling one check in ata_build_rw_tf in order to determine whether or not to send a prioritized command. This patch depends on ata: ATA Command Priority Disabled By Default tj: Minor subject and formatting updates. Signed-off-by: Adam Manzanares Signed-off-by: Tejun Heo --- drivers/ata/libata-core.c | 3 +-- drivers/ata/libata-scsi.c | 10 ++++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index b294339159a4..43842fdcdc87 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -787,8 +787,7 @@ int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, if (tf->flags & ATA_TFLAG_FUA) tf->device |= 1 << 7; - if ((dev->flags & ATA_DFLAG_NCQ_PRIO) && - (dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLE)) { + if (dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLE) { if (class == IOPRIO_CLASS_RT) tf->hob_nsect |= ATA_PRIO_HIGH << ATA_SHIFT_PRIO; diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 87597a3f6149..49c09d876358 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -323,10 +323,16 @@ static ssize_t ata_ncq_prio_enable_store(struct device *device, goto unlock; } - if (input) + if (input) { + if (!(dev->flags & ATA_DFLAG_NCQ_PRIO)) { + rc = -EOPNOTSUPP; + goto unlock; + } + dev->flags |= ATA_DFLAG_NCQ_PRIO_ENABLE; - else + } else { dev->flags &= ~ATA_DFLAG_NCQ_PRIO_ENABLE; + } unlock: spin_unlock_irqrestore(ap->lock, flags); -- cgit v1.2.3 From 07b9733fdad991ded44370badc8bad0c64c6660e Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Wed, 9 Nov 2016 02:56:35 +0200 Subject: pata: imx: sort headers out Put headers in alphabetic order and remove redundant ones. Signed-off-by: Vladimir Zapolskiy Signed-off-by: Tejun Heo --- drivers/ata/pata_imx.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/pata_imx.c b/drivers/ata/pata_imx.c index 139d20778b29..203e3092ed07 100644 --- a/drivers/ata/pata_imx.c +++ b/drivers/ata/pata_imx.c @@ -13,14 +13,12 @@ * - dmaengine support * - check if timing stuff needed */ -#include -#include -#include -#include + #include +#include #include +#include #include -#include #define DRV_NAME "pata_imx" -- cgit v1.2.3 From 65a443ea54832cdf221c03c285930f0089c03f9a Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Wed, 9 Nov 2016 02:56:36 +0200 Subject: pata: imx: set controller PIO mode with .set_piomode callback Convert .set_mode callback function to more specific .set_piomode, the driver does not have support of DMA modes, thus a simpler version of the callback is preferred. Signed-off-by: Vladimir Zapolskiy Signed-off-by: Tejun Heo --- drivers/ata/pata_imx.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/pata_imx.c b/drivers/ata/pata_imx.c index 203e3092ed07..00df18b07fa6 100644 --- a/drivers/ata/pata_imx.c +++ b/drivers/ata/pata_imx.c @@ -38,28 +38,17 @@ struct pata_imx_priv { u32 ata_ctl; }; -static int pata_imx_set_mode(struct ata_link *link, struct ata_device **unused) +static void pata_imx_set_piomode(struct ata_port *ap, struct ata_device *adev) { - struct ata_device *dev; - struct ata_port *ap = link->ap; struct pata_imx_priv *priv = ap->host->private_data; u32 val; - ata_for_each_dev(dev, link, ENABLED) { - dev->pio_mode = dev->xfer_mode = XFER_PIO_0; - dev->xfer_shift = ATA_SHIFT_PIO; - dev->flags |= ATA_DFLAG_PIO; - - val = __raw_readl(priv->host_regs + PATA_IMX_ATA_CONTROL); - if (ata_pio_need_iordy(dev)) - val |= PATA_IMX_ATA_CTRL_IORDY_EN; - else - val &= ~PATA_IMX_ATA_CTRL_IORDY_EN; - __raw_writel(val, priv->host_regs + PATA_IMX_ATA_CONTROL); - - ata_dev_info(dev, "configured for PIO\n"); - } - return 0; + val = __raw_readl(priv->host_regs + PATA_IMX_ATA_CONTROL); + if (ata_pio_need_iordy(adev)) + val |= PATA_IMX_ATA_CTRL_IORDY_EN; + else + val &= ~PATA_IMX_ATA_CTRL_IORDY_EN; + __raw_writel(val, priv->host_regs + PATA_IMX_ATA_CONTROL); } static struct scsi_host_template pata_imx_sht = { @@ -70,7 +59,7 @@ static struct ata_port_operations pata_imx_port_ops = { .inherits = &ata_sff_port_ops, .sff_data_xfer = ata_sff_data_xfer_noirq, .cable_detect = ata_cable_unknown, - .set_mode = pata_imx_set_mode, + .set_piomode = pata_imx_set_piomode, }; static void pata_imx_setup_port(struct ata_ioports *ioaddr) -- cgit v1.2.3 From fab43e14347e510b5872515a47200914182c15f9 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Wed, 9 Nov 2016 02:56:37 +0200 Subject: pata: imx: add support of setting timings for PIO modes The controller is capable to operate in up to PIO4 mode, however before the change the driver relies on timing settings done by a bootloader for PIO0 mode only. The change adds more flexibility in PIO mode selection at runtime and makes the driver to work even if bootloader does not preset ATA timings. Signed-off-by: Vladimir Zapolskiy Signed-off-by: Tejun Heo --- drivers/ata/pata_imx.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/pata_imx.c b/drivers/ata/pata_imx.c index 00df18b07fa6..8f13c9f27c8c 100644 --- a/drivers/ata/pata_imx.c +++ b/drivers/ata/pata_imx.c @@ -11,7 +11,6 @@ * * TODO: * - dmaengine support - * - check if timing stuff needed */ #include @@ -22,6 +21,16 @@ #define DRV_NAME "pata_imx" +#define PATA_IMX_ATA_TIME_OFF 0x00 +#define PATA_IMX_ATA_TIME_ON 0x01 +#define PATA_IMX_ATA_TIME_1 0x02 +#define PATA_IMX_ATA_TIME_2W 0x03 +#define PATA_IMX_ATA_TIME_2R 0x04 +#define PATA_IMX_ATA_TIME_AX 0x05 +#define PATA_IMX_ATA_TIME_PIO_RDX 0x06 +#define PATA_IMX_ATA_TIME_4 0x07 +#define PATA_IMX_ATA_TIME_9 0x08 + #define PATA_IMX_ATA_CONTROL 0x24 #define PATA_IMX_ATA_CTRL_FIFO_RST_B (1<<7) #define PATA_IMX_ATA_CTRL_ATA_RST_B (1<<6) @@ -31,6 +40,10 @@ #define PATA_IMX_DRIVE_DATA 0xA0 #define PATA_IMX_DRIVE_CONTROL 0xD8 +static u32 pio_t4[] = { 30, 20, 15, 10, 10 }; +static u32 pio_t9[] = { 20, 15, 10, 10, 10 }; +static u32 pio_tA[] = { 35, 35, 35, 35, 35 }; + struct pata_imx_priv { struct clk *clk; /* timings/interrupt/control regs */ @@ -38,11 +51,43 @@ struct pata_imx_priv { u32 ata_ctl; }; +static void pata_imx_set_timing(struct ata_device *adev, + struct pata_imx_priv *priv) +{ + struct ata_timing timing; + unsigned long clkrate; + u32 T, mode; + + clkrate = clk_get_rate(priv->clk); + + if (adev->pio_mode < XFER_PIO_0 || adev->pio_mode > XFER_PIO_4 || + !clkrate) + return; + + T = 1000000000 / clkrate; + ata_timing_compute(adev, adev->pio_mode, &timing, T * 1000, 0); + + mode = adev->pio_mode - XFER_PIO_0; + + writeb(3, priv->host_regs + PATA_IMX_ATA_TIME_OFF); + writeb(3, priv->host_regs + PATA_IMX_ATA_TIME_ON); + writeb(timing.setup, priv->host_regs + PATA_IMX_ATA_TIME_1); + writeb(timing.act8b, priv->host_regs + PATA_IMX_ATA_TIME_2W); + writeb(timing.act8b, priv->host_regs + PATA_IMX_ATA_TIME_2R); + writeb(1, priv->host_regs + PATA_IMX_ATA_TIME_PIO_RDX); + + writeb(pio_t4[mode] / T + 1, priv->host_regs + PATA_IMX_ATA_TIME_4); + writeb(pio_t9[mode] / T + 1, priv->host_regs + PATA_IMX_ATA_TIME_9); + writeb(pio_tA[mode] / T + 1, priv->host_regs + PATA_IMX_ATA_TIME_AX); +} + static void pata_imx_set_piomode(struct ata_port *ap, struct ata_device *adev) { struct pata_imx_priv *priv = ap->host->private_data; u32 val; + pata_imx_set_timing(adev, priv); + val = __raw_readl(priv->host_regs + PATA_IMX_ATA_CONTROL); if (ata_pio_need_iordy(adev)) val |= PATA_IMX_ATA_CTRL_IORDY_EN; -- cgit v1.2.3 From b986723c4c937033957ef0971e54effd02afb451 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Wed, 9 Nov 2016 02:56:38 +0200 Subject: pata: imx: support controller modes up to PIO4 Having timing settings for all supported by the controller PIO modes now it is possible to expand its PIO mask. Signed-off-by: Vladimir Zapolskiy Signed-off-by: Tejun Heo --- drivers/ata/pata_imx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/pata_imx.c b/drivers/ata/pata_imx.c index 8f13c9f27c8c..d4caa23f5a88 100644 --- a/drivers/ata/pata_imx.c +++ b/drivers/ata/pata_imx.c @@ -160,7 +160,7 @@ static int pata_imx_probe(struct platform_device *pdev) ap = host->ports[0]; ap->ops = &pata_imx_port_ops; - ap->pio_mask = ATA_PIO0; + ap->pio_mask = ATA_PIO4; ap->flags |= ATA_FLAG_SLAVE_POSS; io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- cgit v1.2.3 From a2e7eefd5618e0f75bae2eb5c9387ea2f627b6ca Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 2 Dec 2016 19:31:01 +0100 Subject: nvme: move NVMe class code to pci_ids.h We'll need to check for it in the AHCI drivers (yes, really) soon. Signed-off-by: Christoph Hellwig Signed-off-by: Tejun Heo --- drivers/nvme/host/pci.c | 3 --- include/linux/pci_ids.h | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 0fc99f0f2571..2c58f159ac61 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -2064,9 +2064,6 @@ static const struct pci_error_handlers nvme_err_handler = { .reset_notify = nvme_reset_notify, }; -/* Move to pci_ids.h later */ -#define PCI_CLASS_STORAGE_EXPRESS 0x010802 - static const struct pci_device_id nvme_id_table[] = { { PCI_VDEVICE(INTEL, 0x0953), .driver_data = NVME_QUIRK_STRIPE_SIZE | diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index c58752fe16c4..a5e6c7bca610 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -23,8 +23,10 @@ #define PCI_CLASS_STORAGE_SATA 0x0106 #define PCI_CLASS_STORAGE_SATA_AHCI 0x010601 #define PCI_CLASS_STORAGE_SAS 0x0107 +#define PCI_CLASS_STORAGE_EXPRESS 0x010802 #define PCI_CLASS_STORAGE_OTHER 0x0180 + #define PCI_BASE_CLASS_NETWORK 0x02 #define PCI_CLASS_NETWORK_ETHERNET 0x0200 #define PCI_CLASS_NETWORK_TOKEN_RING 0x0201 -- cgit v1.2.3 From aecec8b60422118b52e3347430ba9382e57d6d76 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 2 Dec 2016 19:31:03 +0100 Subject: ahci: warn about remapped NVMe devices Some Intel ahci implementations have a completely broken remapping mode where they hide one or more NVMe devices behind the bar of an AHCI device. Intel refuses to let the OS reprogram the BIOS to switch out of this mode at runtime, and so far we're not come up with another good way to undo the mess that the Chipset people created. So for now the only thing we can do is to alert users about this situation and switch to the faster and much saner so called "AHCI" mode insted of the RAID mode in the BIOS so that the BIOS does not hide the NVMe devices from us. The sitation is even worse as at least one vendor (thanks a lot Lenovo..) has started hardcoding their BIOS into the "RAID" mode even for laptops that don't use AHCI _at all_ and just have a single NVMe device. For now there is an unspported Linux-only BIOS that undoes this braindamage, but we'll have to see if things are getting better or worse from here. Based on an earlier patch from Dan Williams . Signed-off-by: Christoph Hellwig Signed-off-by: Tejun Heo --- drivers/ata/ahci.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index ba5f11cebee2..516a689c5f5f 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -46,6 +46,8 @@ #include #include #include +#include +#include #include "ahci.h" #define DRV_NAME "ahci" @@ -1400,6 +1402,40 @@ static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance) } #endif +static void ahci_remap_check(struct pci_dev *pdev, int bar, + struct ahci_host_priv *hpriv) +{ + int i, count = 0; + u32 cap; + + /* + * Check if this device might have remapped nvme devices. + */ + if (pdev->vendor != PCI_VENDOR_ID_INTEL || + pci_resource_len(pdev, bar) < SZ_512K || + bar != AHCI_PCI_BAR_STANDARD || + !(readl(hpriv->mmio + AHCI_VSCAP) & 1)) + return; + + cap = readq(hpriv->mmio + AHCI_REMAP_CAP); + for (i = 0; i < AHCI_MAX_REMAP; i++) { + if ((cap & (1 << i)) == 0) + continue; + if (readl(hpriv->mmio + ahci_remap_dcc(i)) + != PCI_CLASS_STORAGE_EXPRESS) + continue; + + /* We've found a remapped device */ + count++; + } + + if (!count) + return; + + dev_warn(&pdev->dev, "Found %d remapped NVMe devices.\n", count); + dev_warn(&pdev->dev, "Switch your BIOS from RAID to AHCI mode to use them.\n"); +} + static int ahci_get_irq_vector(struct ata_host *host, int port) { return pci_irq_vector(to_pci_dev(host->dev), port); @@ -1545,6 +1581,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar]; + /* detect remapped nvme devices */ + ahci_remap_check(pdev, ahci_pci_bar, hpriv); + /* must set flag prior to save config in order to take effect */ if (ahci_broken_devslp(pdev)) hpriv->flags |= AHCI_HFLAG_NO_DEVSLP; -- cgit v1.2.3