From 515d9b2c03943ca904cd135e1b1d9ddd168c1b27 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 12 Aug 2014 18:22:27 +0200 Subject: ata: remove deprecated struct ahci_platform_data The last user of the deprecated struct ahci_platform_data has been cleaned up recently (SPEAr1340 got a proper PHY driver). Signed-off-by: Bartlomiej Zolnierkiewicz Acked-by: Hans de Goede Signed-off-by: Tejun Heo --- drivers/ata/ahci_platform.c | 18 +----------------- drivers/ata/libahci_platform.c | 23 ----------------------- 2 files changed, 1 insertion(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c index f61ddb9..06f1d59 100644 --- a/drivers/ata/ahci_platform.c +++ b/drivers/ata/ahci_platform.c @@ -32,7 +32,6 @@ static const struct ata_port_info ahci_port_info = { static int ahci_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct ahci_platform_data *pdata = dev_get_platdata(dev); struct ahci_host_priv *hpriv; int rc; @@ -44,29 +43,14 @@ static int ahci_probe(struct platform_device *pdev) if (rc) return rc; - /* - * Some platforms might need to prepare for mmio region access, - * which could be done in the following init call. So, the mmio - * region shouldn't be accessed before init (if provided) has - * returned successfully. - */ - if (pdata && pdata->init) { - rc = pdata->init(dev, hpriv->mmio); - if (rc) - goto disable_resources; - } - if (of_device_is_compatible(dev->of_node, "hisilicon,hisi-ahci")) hpriv->flags |= AHCI_HFLAG_NO_FBS | AHCI_HFLAG_NO_NCQ; rc = ahci_platform_init_host(pdev, hpriv, &ahci_port_info); if (rc) - goto pdata_exit; + goto disable_resources; return 0; -pdata_exit: - if (pdata && pdata->exit) - pdata->exit(dev); disable_resources: ahci_platform_disable_resources(hpriv); return rc; diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c index 5b92c29..c0510de 100644 --- a/drivers/ata/libahci_platform.c +++ b/drivers/ata/libahci_platform.c @@ -502,13 +502,8 @@ EXPORT_SYMBOL_GPL(ahci_platform_init_host); static void ahci_host_stop(struct ata_host *host) { - struct device *dev = host->dev; - struct ahci_platform_data *pdata = dev_get_platdata(dev); struct ahci_host_priv *hpriv = host->private_data; - if (pdata && pdata->exit) - pdata->exit(dev); - ahci_platform_disable_resources(hpriv); } @@ -592,7 +587,6 @@ EXPORT_SYMBOL_GPL(ahci_platform_resume_host); */ int ahci_platform_suspend(struct device *dev) { - struct ahci_platform_data *pdata = dev_get_platdata(dev); struct ata_host *host = dev_get_drvdata(dev); struct ahci_host_priv *hpriv = host->private_data; int rc; @@ -601,19 +595,9 @@ int ahci_platform_suspend(struct device *dev) if (rc) return rc; - if (pdata && pdata->suspend) { - rc = pdata->suspend(dev); - if (rc) - goto resume_host; - } - ahci_platform_disable_resources(hpriv); return 0; - -resume_host: - ahci_platform_resume_host(dev); - return rc; } EXPORT_SYMBOL_GPL(ahci_platform_suspend); @@ -629,7 +613,6 @@ EXPORT_SYMBOL_GPL(ahci_platform_suspend); */ int ahci_platform_resume(struct device *dev) { - struct ahci_platform_data *pdata = dev_get_platdata(dev); struct ata_host *host = dev_get_drvdata(dev); struct ahci_host_priv *hpriv = host->private_data; int rc; @@ -638,12 +621,6 @@ int ahci_platform_resume(struct device *dev) if (rc) return rc; - if (pdata && pdata->resume) { - rc = pdata->resume(dev); - if (rc) - goto disable_resources; - } - rc = ahci_platform_resume_host(dev); if (rc) goto disable_resources; -- cgit v1.1 From 4f37b504768c952b64bc9469a2d579c7597590f2 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Tue, 19 Aug 2014 10:51:04 +0400 Subject: libata: Use dev_name() for request_irq() to distinguish devices Use dev_name() instead of driver name for request_irq(). This will help to distinguish between multiple identical devices. Before: CPU0 5: 34425 clps711x-intc 5 pata_of_platform 6: 6778 clps711x-intc 6 pata_of_platform After: CPU0 5: 2182 clps711x-intc 5 20000000.ide 6: 11024 clps711x-intc 6 20100000.ide Signed-off-by: Alexander Shiyan Signed-off-by: Tejun Heo --- drivers/ata/libata-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index dbdc5d3..782d126 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -6227,7 +6227,7 @@ int ata_host_activate(struct ata_host *host, int irq, } rc = devm_request_irq(host->dev, irq, irq_handler, irq_flags, - dev_driver_string(host->dev), host); + dev_name(host->dev), host); if (rc) return rc; -- cgit v1.1 From ca99140a63b7326ee9a38f64c326317f2c63b594 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Sat, 23 Aug 2014 14:46:10 +0400 Subject: pata_of_platform: Remove "electra-ide" quirk "electra-ide" is not used anywhere in the kernel and could be represented in devicetree in a normal way. This patch removes specific quirk for "electra-ide". Signed-off-by: Alexander Shiyan Signed-off-by: Tejun Heo --- drivers/ata/pata_of_platform.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/pata_of_platform.c b/drivers/ata/pata_of_platform.c index a7e95a5..6af1c9b 100644 --- a/drivers/ata/pata_of_platform.c +++ b/drivers/ata/pata_of_platform.c @@ -35,20 +35,11 @@ static int pata_of_platform_probe(struct platform_device *ofdev) return -EINVAL; } - if (of_device_is_compatible(dn, "electra-ide")) { - /* Altstatus is really at offset 0x3f6 from the primary window - * on electra-ide. Adjust ctl_res and io_res accordingly. - */ - ctl_res = io_res; - ctl_res.start = ctl_res.start+0x3f6; - io_res.end = ctl_res.start-1; - } else { - ret = of_address_to_resource(dn, 1, &ctl_res); - if (ret) { - dev_err(&ofdev->dev, "can't get CTL address from " - "device tree\n"); - return -EINVAL; - } + ret = of_address_to_resource(dn, 1, &ctl_res); + if (ret) { + dev_err(&ofdev->dev, "can't get CTL address from " + "device tree\n"); + return -EINVAL; } irq_res = platform_get_resource(ofdev, IORESOURCE_IRQ, 0); @@ -79,8 +70,7 @@ static int pata_of_platform_probe(struct platform_device *ofdev) static struct of_device_id pata_of_platform_match[] = { { .compatible = "ata-generic", }, - { .compatible = "electra-ide", }, - {}, + { }, }; MODULE_DEVICE_TABLE(of, pata_of_platform_match); -- cgit v1.1 From 53f3cc46336b9e514c98556b4a009a69ed808d3b Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Sat, 23 Aug 2014 14:45:47 +0400 Subject: pata_platform: Remove useless irq_flags field IRQ flags can be obtained from resource structure, there are no need to use additional field in the platform_data to store these values. This patch removes this field and convert existing users of this driver to use IRQ flags from the resources. Signed-off-by: Alexander Shiyan Signed-off-by: Tejun Heo --- drivers/ata/pata_of_platform.c | 2 -- drivers/ata/pata_platform.c | 4 +--- 2 files changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/pata_of_platform.c b/drivers/ata/pata_of_platform.c index 6af1c9b..6496539 100644 --- a/drivers/ata/pata_of_platform.c +++ b/drivers/ata/pata_of_platform.c @@ -43,8 +43,6 @@ static int pata_of_platform_probe(struct platform_device *ofdev) } irq_res = platform_get_resource(ofdev, IORESOURCE_IRQ, 0); - if (irq_res) - irq_res->flags = 0; prop = of_get_property(dn, "reg-shift", NULL); if (prop) diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c index a5579b5..f8cff3e 100644 --- a/drivers/ata/pata_platform.c +++ b/drivers/ata/pata_platform.c @@ -118,7 +118,7 @@ int __pata_platform_probe(struct device *dev, struct resource *io_res, */ if (irq_res && irq_res->start > 0) { irq = irq_res->start; - irq_flags = irq_res->flags; + irq_flags = irq_res->flags & IRQF_TRIGGER_MASK; } /* @@ -213,8 +213,6 @@ static int pata_platform_probe(struct platform_device *pdev) * And the IRQ */ irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (irq_res) - irq_res->flags = pp_info ? pp_info->irq_flags : 0; return __pata_platform_probe(&pdev->dev, io_res, ctl_res, irq_res, pp_info ? pp_info->ioport_shift : 0, -- cgit v1.1 From 6bb86fefa086faba7b60bb452300b76a47cde1a5 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sat, 30 Aug 2014 16:39:09 -0300 Subject: libahci_platform: Staticize ahci_platform_able_phys() ahci_platform_enable_phys() and ahci_platform_disable_phys() are currently exported, but they are not used anywhere else other than libahci_platform.c. So make them static and do not export them to fix the following sparse warnings: drivers/ata/libahci_platform.c:52:5: warning: symbol 'ahci_platform_enable_phys' was not declared. Should it be static? drivers/ata/libahci_platform.c:88:6: warning: symbol 'ahci_platform_disable_phys' was not declared. Should it be static? Signed-off-by: Fabio Estevam Signed-off-by: Tejun Heo --- drivers/ata/libahci_platform.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c index c0510de..c7f787e 100644 --- a/drivers/ata/libahci_platform.c +++ b/drivers/ata/libahci_platform.c @@ -49,7 +49,7 @@ static struct scsi_host_template ahci_platform_sht = { * RETURNS: * 0 on success otherwise a negative error code */ -int ahci_platform_enable_phys(struct ahci_host_priv *hpriv) +static int ahci_platform_enable_phys(struct ahci_host_priv *hpriv) { int rc, i; @@ -77,7 +77,6 @@ disable_phys: } return rc; } -EXPORT_SYMBOL_GPL(ahci_platform_enable_phys); /** * ahci_platform_disable_phys - Disable PHYs @@ -85,7 +84,7 @@ EXPORT_SYMBOL_GPL(ahci_platform_enable_phys); * * This function disables all PHYs found in hpriv->phys. */ -void ahci_platform_disable_phys(struct ahci_host_priv *hpriv) +static void ahci_platform_disable_phys(struct ahci_host_priv *hpriv) { int i; @@ -97,7 +96,6 @@ void ahci_platform_disable_phys(struct ahci_host_priv *hpriv) phy_exit(hpriv->phys[i]); } } -EXPORT_SYMBOL_GPL(ahci_platform_disable_phys); /** * ahci_platform_enable_clks - Enable platform clocks -- cgit v1.1 From 1bd06867f7f168273c80ba10ce4025a97be98305 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Sun, 31 Aug 2014 10:57:09 +0200 Subject: ahci: ahci_p5wdh_workaround - constify DMI table The DMI table does not need to be written to, make it r/o. Signed-off-by: Mathias Krause Signed-off-by: Tejun Heo --- drivers/ata/ahci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index a29f801..c880699 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -780,7 +780,7 @@ static void ahci_pci_print_info(struct ata_host *host) */ static void ahci_p5wdh_workaround(struct ata_host *host) { - static struct dmi_system_id sysids[] = { + static const struct dmi_system_id sysids[] = { { .ident = "P5W DH Deluxe", .matches = { -- cgit v1.1 From ee309f382985cbb29d85965a2de96bc715260463 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Mon, 22 Sep 2014 15:09:45 -0500 Subject: ahci-platform: Bump max number of clocks to 5 Qualcomm IPQ806x SoCs with SATA controllers need 5 clocks to be enabled. Signed-off-by: Kumar Gala Reviewed-by: Hans de Goede Signed-off-by: Tejun Heo --- drivers/ata/ahci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index 59ae0ee..90156ff 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -53,7 +53,7 @@ enum { AHCI_MAX_PORTS = 32, - AHCI_MAX_CLKS = 4, + AHCI_MAX_CLKS = 5, AHCI_MAX_SG = 168, /* hardware max is 64K */ AHCI_DMA_BOUNDARY = 0xffffffff, AHCI_MAX_CMDS = 32, -- cgit v1.1 From d7bead1b8890c3e47a24db270fdb840ea728d8f0 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 22 Sep 2014 09:52:18 -0700 Subject: libata: change ata__printk routines to return void The return value is not used by callers of these functions nor by uses of all macros so change the functions to return void. Signed-off-by: Joe Perches Signed-off-by: Tejun Heo --- drivers/ata/libata-core.c | 35 +++++++++++++---------------------- 1 file changed, 13 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 782d126..f785ae5 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -6772,32 +6772,28 @@ const struct ata_port_info ata_dummy_port_info = { /* * Utility print functions */ -int ata_port_printk(const struct ata_port *ap, const char *level, - const char *fmt, ...) +void ata_port_printk(const struct ata_port *ap, const char *level, + const char *fmt, ...) { struct va_format vaf; va_list args; - int r; va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; - r = printk("%sata%u: %pV", level, ap->print_id, &vaf); + printk("%sata%u: %pV", level, ap->print_id, &vaf); va_end(args); - - return r; } EXPORT_SYMBOL(ata_port_printk); -int ata_link_printk(const struct ata_link *link, const char *level, - const char *fmt, ...) +void ata_link_printk(const struct ata_link *link, const char *level, + const char *fmt, ...) { struct va_format vaf; va_list args; - int r; va_start(args, fmt); @@ -6805,37 +6801,32 @@ int ata_link_printk(const struct ata_link *link, const char *level, vaf.va = &args; if (sata_pmp_attached(link->ap) || link->ap->slave_link) - r = printk("%sata%u.%02u: %pV", - level, link->ap->print_id, link->pmp, &vaf); + printk("%sata%u.%02u: %pV", + level, link->ap->print_id, link->pmp, &vaf); else - r = printk("%sata%u: %pV", - level, link->ap->print_id, &vaf); + printk("%sata%u: %pV", + level, link->ap->print_id, &vaf); va_end(args); - - return r; } EXPORT_SYMBOL(ata_link_printk); -int ata_dev_printk(const struct ata_device *dev, const char *level, +void ata_dev_printk(const struct ata_device *dev, const char *level, const char *fmt, ...) { struct va_format vaf; va_list args; - int r; va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; - r = printk("%sata%u.%02u: %pV", - level, dev->link->ap->print_id, dev->link->pmp + dev->devno, - &vaf); + printk("%sata%u.%02u: %pV", + level, dev->link->ap->print_id, dev->link->pmp + dev->devno, + &vaf); va_end(args); - - return r; } EXPORT_SYMBOL(ata_dev_printk); -- cgit v1.1 From a77b6ee90dfc3798bdcbdca7a9284d7e8c006af7 Mon Sep 17 00:00:00 2001 From: Suman Tripathi Date: Mon, 22 Sep 2014 18:31:33 +0530 Subject: ahci_xgene: Fix the error print invalid resource for APM X-Gene SoC AHCI SATA Host Controller driver. This patch fixes the error print invalid resource for the APM X-Gene SoC AHCI SATA Host Controller driver. This print was due to the fact that the controller 3 don't have a mux resource. This didn't result in any errors but the print seems like meaningless. Signed-off-by: Loc Ho Signed-off-by: Suman Tripathi Signed-off-by: Tejun Heo --- drivers/ata/ahci_xgene.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c index bc28111..7822c8e 100644 --- a/drivers/ata/ahci_xgene.c +++ b/drivers/ata/ahci_xgene.c @@ -406,7 +406,7 @@ static int xgene_ahci_mux_select(struct xgene_ahci_context *ctx) u32 val; /* Check for optional MUX resource */ - if (IS_ERR(ctx->csr_mux)) + if (!ctx->csr_mux) return 0; val = readl(ctx->csr_mux + SATA_ENET_CONFIG_REG); @@ -456,7 +456,13 @@ static int xgene_ahci_probe(struct platform_device *pdev) /* Retrieve the optional IP mux resource */ res = platform_get_resource(pdev, IORESOURCE_MEM, 4); - ctx->csr_mux = devm_ioremap_resource(dev, res); + if (res) { + void __iomem *csr = devm_ioremap_resource(dev, res); + if (IS_ERR(csr)) + return PTR_ERR(csr); + + ctx->csr_mux = csr; + } dev_dbg(dev, "VAddr 0x%p Mmio VAddr 0x%p\n", ctx->csr_core, hpriv->mmio); -- cgit v1.1 From 6d8ca28fa688a9354bc9fbc935bdaeb3651b6677 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Sat, 27 Sep 2014 00:04:46 +0200 Subject: libata-sff: Fix controllers with no ctl port Currently, ata_sff_softreset is skipped for controllers with no ctl port. But that also skips ata_sff_dev_classify required for device detection. This means that libata is currently broken on controllers with no ctl port. No device connected: [ 1.872480] pata_isapnp 01:01.02: activated [ 1.889823] scsi2 : pata_isapnp [ 1.890109] ata3: PATA max PIO0 cmd 0x1e8 ctl 0x0 irq 11 [ 6.888110] ata3.01: qc timeout (cmd 0xec) [ 6.888179] ata3.01: failed to IDENTIFY (I/O error, err_mask=0x5) [ 16.888085] ata3.01: qc timeout (cmd 0xec) [ 16.888147] ata3.01: failed to IDENTIFY (I/O error, err_mask=0x5) [ 46.888086] ata3.01: qc timeout (cmd 0xec) [ 46.888148] ata3.01: failed to IDENTIFY (I/O error, err_mask=0x5) [ 51.888100] ata3.00: qc timeout (cmd 0xec) [ 51.888160] ata3.00: failed to IDENTIFY (I/O error, err_mask=0x5) [ 61.888079] ata3.00: qc timeout (cmd 0xec) [ 61.888141] ata3.00: failed to IDENTIFY (I/O error, err_mask=0x5) [ 91.888089] ata3.00: qc timeout (cmd 0xec) [ 91.888152] ata3.00: failed to IDENTIFY (I/O error, err_mask=0x5) ATAPI device connected: [ 1.882061] pata_isapnp 01:01.02: activated [ 1.893430] scsi2 : pata_isapnp [ 1.893719] ata3: PATA max PIO0 cmd 0x1e8 ctl 0x0 irq 11 [ 6.892107] ata3.01: qc timeout (cmd 0xec) [ 6.892171] ata3.01: failed to IDENTIFY (I/O error, err_mask=0x5) [ 16.892079] ata3.01: qc timeout (cmd 0xec) [ 16.892138] ata3.01: failed to IDENTIFY (I/O error, err_mask=0x5) [ 46.892079] ata3.01: qc timeout (cmd 0xec) [ 46.892138] ata3.01: failed to IDENTIFY (I/O error, err_mask=0x5) [ 46.908586] ata3.00: ATAPI: ACER CD-767E/O, V1.5X, max PIO2, CDB intr [ 46.924570] ata3.00: configured for PIO0 (device error ignored) [ 46.926295] scsi 2:0:0:0: CD-ROM ACER CD-767E/O 1.5X PQ: 0 ANSI: 5 [ 46.984519] sr0: scsi3-mmc drive: 6x/6x xa/form2 tray [ 46.984592] cdrom: Uniform CD-ROM driver Revision: 3.20 So don't skip ata_sff_softreset, just skip the reset part of ata_bus_softreset if the ctl port is not available. This makes IDE port on ES968 behave correctly: No device connected: [ 4.670888] pata_isapnp 01:01.02: activated [ 4.673207] scsi host2: pata_isapnp [ 4.673675] ata3: PATA max PIO0 cmd 0x1e8 ctl 0x0 irq 11 [ 7.081840] Adding 2541652k swap on /dev/sda2. Priority:-1 extents:1 across:2541652k ATAPI device connected: [ 4.704362] pata_isapnp 01:01.02: activated [ 4.706620] scsi host2: pata_isapnp [ 4.706877] ata3: PATA max PIO0 cmd 0x1e8 ctl 0x0 irq 11 [ 4.872782] ata3.00: ATAPI: ACER CD-767E/O, V1.5X, max PIO2, CDB intr [ 4.888673] ata3.00: configured for PIO0 (device error ignored) [ 4.893984] scsi 2:0:0:0: CD-ROM ACER CD-767E/O 1.5X PQ: 0 ANSI: 5 [ 7.015578] Adding 2541652k swap on /dev/sda2. Priority:-1 extents:1 across:2541652k Signed-off-by: Ondrej Zary Signed-off-by: Tejun Heo Cc: stable@vger.kernel.org --- drivers/ata/libata-sff.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 1121153..db90aa3 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -2008,13 +2008,15 @@ static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask, DPRINTK("ata%u: bus reset via SRST\n", ap->print_id); - /* software reset. causes dev0 to be selected */ - iowrite8(ap->ctl, ioaddr->ctl_addr); - udelay(20); /* FIXME: flush */ - iowrite8(ap->ctl | ATA_SRST, ioaddr->ctl_addr); - udelay(20); /* FIXME: flush */ - iowrite8(ap->ctl, ioaddr->ctl_addr); - ap->last_ctl = ap->ctl; + if (ap->ioaddr.ctl_addr) { + /* software reset. causes dev0 to be selected */ + iowrite8(ap->ctl, ioaddr->ctl_addr); + udelay(20); /* FIXME: flush */ + iowrite8(ap->ctl | ATA_SRST, ioaddr->ctl_addr); + udelay(20); /* FIXME: flush */ + iowrite8(ap->ctl, ioaddr->ctl_addr); + ap->last_ctl = ap->ctl; + } /* wait the port to become ready */ return ata_sff_wait_after_reset(&ap->link, devmask, deadline); @@ -2215,10 +2217,6 @@ void ata_sff_error_handler(struct ata_port *ap) spin_unlock_irqrestore(ap->lock, flags); - /* ignore ata_sff_softreset if ctl isn't accessible */ - if (softreset == ata_sff_softreset && !ap->ioaddr.ctl_addr) - softreset = NULL; - /* ignore built-in hardresets if SCR access is not available */ if ((hardreset == sata_std_hardreset || hardreset == sata_sff_hardreset) && !sata_scr_valid(&ap->link)) -- cgit v1.1 From c3ebd6a9b614ef1fbb5a44a3a33cd639ff4694bf Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Thu, 25 Sep 2014 15:13:21 +0200 Subject: AHCI: Cleanup checking of multiple MSIs/SLM modes Sharing Last Message (SLM) mode is currently checked in two functions: ahci_host_activate() and ahci_init_interrupts(). This update consolidates SLM mode check with activation of multiple MSIs mode. Signed-off-by: Alexander Gordeev Signed-off-by: Tejun Heo Cc: linux-ide@vger.kernel.org --- drivers/ata/ahci.c | 18 +++++++----------- drivers/ata/ahci.h | 2 +- 2 files changed, 8 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index c880699..f68a995 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1211,6 +1211,9 @@ static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports, goto single_msi; } + if (nvec > 1) + hpriv->flags |= AHCI_HFLAG_MULTI_MSI; + return nvec; single_msi: @@ -1227,7 +1230,6 @@ intx: * ahci_host_activate - start AHCI host, request IRQs and register it * @host: target ATA host * @irq: base IRQ number to request - * @n_msis: number of MSIs allocated for this host * @irq_handler: irq_handler used when requesting IRQs * @irq_flags: irq_flags used when requesting IRQs * @@ -1241,14 +1243,10 @@ intx: * RETURNS: * 0 on success, -errno otherwise. */ -int ahci_host_activate(struct ata_host *host, int irq, unsigned int n_msis) +int ahci_host_activate(struct ata_host *host, int irq) { int i, rc; - /* Sharing Last Message among several ports is not supported */ - if (n_msis < host->n_ports) - return -EINVAL; - rc = ata_host_start(host); if (rc) return rc; @@ -1296,7 +1294,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) struct device *dev = &pdev->dev; struct ahci_host_priv *hpriv; struct ata_host *host; - int n_ports, n_msis, i, rc; + int n_ports, i, rc; int ahci_pci_bar = AHCI_PCI_BAR_STANDARD; VPRINTK("ENTER\n"); @@ -1437,9 +1435,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) */ n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); - n_msis = ahci_init_interrupts(pdev, n_ports, hpriv); - if (n_msis > 1) - hpriv->flags |= AHCI_HFLAG_MULTI_MSI; + ahci_init_interrupts(pdev, n_ports, hpriv); host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); if (!host) @@ -1492,7 +1488,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_master(pdev); if (hpriv->flags & AHCI_HFLAG_MULTI_MSI) - return ahci_host_activate(host, pdev->irq, n_msis); + return ahci_host_activate(host, pdev->irq); return ata_host_activate(host, pdev->irq, ahci_interrupt, IRQF_SHARED, &ahci_sht); diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index 90156ff..a074c73 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -392,7 +392,7 @@ irqreturn_t ahci_interrupt(int irq, void *dev_instance); irqreturn_t ahci_hw_interrupt(int irq, void *dev_instance); irqreturn_t ahci_thread_fn(int irq, void *dev_instance); void ahci_print_info(struct ata_host *host, const char *scc_s); -int ahci_host_activate(struct ata_host *host, int irq, unsigned int n_msis); +int ahci_host_activate(struct ata_host *host, int irq); void ahci_error_handler(struct ata_port *ap); static inline void __iomem *__ahci_port_base(struct ata_host *host, -- cgit v1.1 From 36888e955c7c7ba8c66756fed60ac6e453fcbb5f Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sat, 4 Oct 2014 09:03:06 -0300 Subject: ata: pata_imx: Use the SIMPLE_DEV_PM_OPS() macro Using the SIMPLE_DEV_PM_OPS() macro can make the code shorter and cleaner. Signed-off-by: Fabio Estevam Signed-off-by: Tejun Heo --- drivers/ata/pata_imx.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/pata_imx.c b/drivers/ata/pata_imx.c index af42457..989ff5a 100644 --- a/drivers/ata/pata_imx.c +++ b/drivers/ata/pata_imx.c @@ -221,13 +221,10 @@ static int pata_imx_resume(struct device *dev) return 0; } - -static const struct dev_pm_ops pata_imx_pm_ops = { - .suspend = pata_imx_suspend, - .resume = pata_imx_resume, -}; #endif +static SIMPLE_DEV_PM_OPS(pata_imx_pm_ops, pata_imx_suspend, pata_imx_resume); + static const struct of_device_id imx_pata_dt_ids[] = { { .compatible = "fsl,imx27-pata", @@ -244,9 +241,7 @@ static struct platform_driver pata_imx_driver = { .name = DRV_NAME, .of_match_table = imx_pata_dt_ids, .owner = THIS_MODULE, -#ifdef CONFIG_PM_SLEEP .pm = &pata_imx_pm_ops, -#endif }, }; -- cgit v1.1 From a6849b9fdbffd2492a848df942b39d23bd81ef27 Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Mon, 29 Sep 2014 18:25:57 +0200 Subject: AHCI: Pass SCSI host template as arg to ahci_host_activate() This update is a prerequisite for consolidation of AHCI host activation code within ahci_host_activate() function. Signed-off-by: Alexander Gordeev Signed-off-by: Tejun Heo Cc: linux-ide@vger.kernel.org --- drivers/ata/ahci.c | 10 +++++----- drivers/ata/ahci.h | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index f68a995..fcda5b6 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1230,8 +1230,7 @@ intx: * ahci_host_activate - start AHCI host, request IRQs and register it * @host: target ATA host * @irq: base IRQ number to request - * @irq_handler: irq_handler used when requesting IRQs - * @irq_flags: irq_flags used when requesting IRQs + * @sht: scsi_host_template to use when registering the host * * Similar to ata_host_activate, but requests IRQs according to AHCI-1.1 * when multiple MSIs were allocated. That is one MSI per port, starting @@ -1243,7 +1242,8 @@ intx: * RETURNS: * 0 on success, -errno otherwise. */ -int ahci_host_activate(struct ata_host *host, int irq) +int ahci_host_activate(struct ata_host *host, int irq, + struct scsi_host_template *sht) { int i, rc; @@ -1271,7 +1271,7 @@ int ahci_host_activate(struct ata_host *host, int irq) for (i = 0; i < host->n_ports; i++) ata_port_desc(host->ports[i], "irq %d", irq + i); - rc = ata_host_register(host, &ahci_sht); + rc = ata_host_register(host, sht); if (rc) goto out_free_all_irqs; @@ -1488,7 +1488,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_master(pdev); if (hpriv->flags & AHCI_HFLAG_MULTI_MSI) - return ahci_host_activate(host, pdev->irq); + return ahci_host_activate(host, pdev->irq, &ahci_sht); return ata_host_activate(host, pdev->irq, ahci_interrupt, IRQF_SHARED, &ahci_sht); diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index a074c73..31b4c44 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -392,7 +392,8 @@ irqreturn_t ahci_interrupt(int irq, void *dev_instance); irqreturn_t ahci_hw_interrupt(int irq, void *dev_instance); irqreturn_t ahci_thread_fn(int irq, void *dev_instance); void ahci_print_info(struct ata_host *host, const char *scc_s); -int ahci_host_activate(struct ata_host *host, int irq); +int ahci_host_activate(struct ata_host *host, int irq, + struct scsi_host_template *sht); void ahci_error_handler(struct ata_port *ap); static inline void __iomem *__ahci_port_base(struct ata_host *host, -- cgit v1.1 From 1c62854f5f7321b3ee8c08d34d7c1e615608566d Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Mon, 29 Sep 2014 18:25:58 +0200 Subject: AHCI: Move ahci_host_activate() function to libahci.c This update is a prerequisite for consolidation of AHCI host activation code within ahci_host_activate() function. Signed-off-by: Alexander Gordeev Signed-off-by: Tejun Heo Cc: linux-ide@vger.kernel.org --- drivers/ata/ahci.c | 60 -------------------------------------------------- drivers/ata/libahci.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 60 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index fcda5b6..0b21604 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1226,66 +1226,6 @@ intx: return 0; } -/** - * ahci_host_activate - start AHCI host, request IRQs and register it - * @host: target ATA host - * @irq: base IRQ number to request - * @sht: scsi_host_template to use when registering the host - * - * Similar to ata_host_activate, but requests IRQs according to AHCI-1.1 - * when multiple MSIs were allocated. That is one MSI per port, starting - * from @irq. - * - * LOCKING: - * Inherited from calling layer (may sleep). - * - * RETURNS: - * 0 on success, -errno otherwise. - */ -int ahci_host_activate(struct ata_host *host, int irq, - struct scsi_host_template *sht) -{ - int i, rc; - - rc = ata_host_start(host); - if (rc) - return rc; - - for (i = 0; i < host->n_ports; i++) { - struct ahci_port_priv *pp = host->ports[i]->private_data; - - /* Do not receive interrupts sent by dummy ports */ - if (!pp) { - disable_irq(irq + i); - continue; - } - - rc = devm_request_threaded_irq(host->dev, irq + i, - ahci_hw_interrupt, - ahci_thread_fn, IRQF_SHARED, - pp->irq_desc, host->ports[i]); - if (rc) - goto out_free_irqs; - } - - for (i = 0; i < host->n_ports; i++) - ata_port_desc(host->ports[i], "irq %d", irq + i); - - rc = ata_host_register(host, sht); - if (rc) - goto out_free_all_irqs; - - return 0; - -out_free_all_irqs: - i = host->n_ports; -out_free_irqs: - for (i--; i >= 0; i--) - devm_free_irq(host->dev, irq + i, host->ports[i]); - - return rc; -} - static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { unsigned int board_id = ent->driver_data; diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index b784e9d..21bb427 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -2472,6 +2472,67 @@ void ahci_set_em_messages(struct ahci_host_priv *hpriv, } EXPORT_SYMBOL_GPL(ahci_set_em_messages); +/** + * ahci_host_activate - start AHCI host, request IRQs and register it + * @host: target ATA host + * @irq: base IRQ number to request + * @sht: scsi_host_template to use when registering the host + * + * Similar to ata_host_activate, but requests IRQs according to AHCI-1.1 + * when multiple MSIs were allocated. That is one MSI per port, starting + * from @irq. + * + * LOCKING: + * Inherited from calling layer (may sleep). + * + * RETURNS: + * 0 on success, -errno otherwise. + */ +int ahci_host_activate(struct ata_host *host, int irq, + struct scsi_host_template *sht) +{ + int i, rc; + + rc = ata_host_start(host); + if (rc) + return rc; + + for (i = 0; i < host->n_ports; i++) { + struct ahci_port_priv *pp = host->ports[i]->private_data; + + /* Do not receive interrupts sent by dummy ports */ + if (!pp) { + disable_irq(irq + i); + continue; + } + + rc = devm_request_threaded_irq(host->dev, irq + i, + ahci_hw_interrupt, + ahci_thread_fn, IRQF_SHARED, + pp->irq_desc, host->ports[i]); + if (rc) + goto out_free_irqs; + } + + for (i = 0; i < host->n_ports; i++) + ata_port_desc(host->ports[i], "irq %d", irq + i); + + rc = ata_host_register(host, sht); + if (rc) + goto out_free_all_irqs; + + return 0; + +out_free_all_irqs: + i = host->n_ports; +out_free_irqs: + for (i--; i >= 0; i--) + devm_free_irq(host->dev, irq + i, host->ports[i]); + + return rc; +} +EXPORT_SYMBOL_GPL(ahci_host_activate); + MODULE_AUTHOR("Jeff Garzik"); MODULE_DESCRIPTION("Common AHCI SATA low-level routines"); MODULE_LICENSE("GPL"); -- cgit v1.1 From d1028e2f95b75acab4f1046acae1b1ca7d7b2577 Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Mon, 29 Sep 2014 18:25:59 +0200 Subject: AHCI: Move host activation code into ahci_host_activate() Currently host activation done by calling either function ahci_host_activate() or ata_host_activate(). Consolidate the code by only calling ahci_host_activate() for all AHCI devices. Signed-off-by: Alexander Gordeev Signed-off-by: Tejun Heo Cc: linux-ide@vger.kernel.org --- drivers/ata/acard-ahci.c | 3 +-- drivers/ata/ahci.c | 6 +---- drivers/ata/ahci.h | 3 --- drivers/ata/libahci.c | 59 +++++++++++++++++++++++++----------------- drivers/ata/libahci_platform.c | 3 +-- drivers/ata/sata_highbank.c | 3 +-- 6 files changed, 39 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/acard-ahci.c b/drivers/ata/acard-ahci.c index 25d0ac3..c962886d 100644 --- a/drivers/ata/acard-ahci.c +++ b/drivers/ata/acard-ahci.c @@ -498,8 +498,7 @@ static int acard_ahci_init_one(struct pci_dev *pdev, const struct pci_device_id acard_ahci_pci_print_info(host); pci_set_master(pdev); - return ata_host_activate(host, pdev->irq, ahci_interrupt, IRQF_SHARED, - &acard_ahci_sht); + return ahci_host_activate(host, pdev->irq, &acard_ahci_sht); } module_pci_driver(acard_ahci_pci_driver); diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 0b21604..d0ac38b 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1427,11 +1427,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_master(pdev); - if (hpriv->flags & AHCI_HFLAG_MULTI_MSI) - return ahci_host_activate(host, pdev->irq, &ahci_sht); - - return ata_host_activate(host, pdev->irq, ahci_interrupt, IRQF_SHARED, - &ahci_sht); + return ahci_host_activate(host, pdev->irq, &ahci_sht); } module_pci_driver(ahci_pci_driver); diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index 31b4c44..6a22055 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -388,9 +388,6 @@ int ahci_port_resume(struct ata_port *ap); void ahci_set_em_messages(struct ahci_host_priv *hpriv, struct ata_port_info *pi); int ahci_reset_em(struct ata_host *host); -irqreturn_t ahci_interrupt(int irq, void *dev_instance); -irqreturn_t ahci_hw_interrupt(int irq, void *dev_instance); -irqreturn_t ahci_thread_fn(int irq, void *dev_instance); void ahci_print_info(struct ata_host *host, const char *scc_s); int ahci_host_activate(struct ata_host *host, int irq, struct scsi_host_template *sht); diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 21bb427..0080551 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -1789,7 +1789,7 @@ static void ahci_port_intr(struct ata_port *ap) ahci_handle_port_interrupt(ap, port_mmio, status); } -irqreturn_t ahci_thread_fn(int irq, void *dev_instance) +static irqreturn_t ahci_thread_fn(int irq, void *dev_instance) { struct ata_port *ap = dev_instance; struct ahci_port_priv *pp = ap->private_data; @@ -1809,7 +1809,6 @@ irqreturn_t ahci_thread_fn(int irq, void *dev_instance) return IRQ_HANDLED; } -EXPORT_SYMBOL_GPL(ahci_thread_fn); static void ahci_hw_port_interrupt(struct ata_port *ap) { @@ -1823,7 +1822,7 @@ static void ahci_hw_port_interrupt(struct ata_port *ap) pp->intr_status |= status; } -irqreturn_t ahci_hw_interrupt(int irq, void *dev_instance) +static irqreturn_t ahci_hw_interrupt(int irq, void *dev_instance) { struct ata_port *ap_this = dev_instance; struct ahci_port_priv *pp = ap_this->private_data; @@ -1877,9 +1876,8 @@ irqreturn_t ahci_hw_interrupt(int irq, void *dev_instance) return IRQ_WAKE_THREAD; } -EXPORT_SYMBOL_GPL(ahci_hw_interrupt); -irqreturn_t ahci_interrupt(int irq, void *dev_instance) +static irqreturn_t ahci_interrupt(int irq, void *dev_instance) { struct ata_host *host = dev_instance; struct ahci_host_priv *hpriv; @@ -1938,7 +1936,6 @@ irqreturn_t ahci_interrupt(int irq, void *dev_instance) return IRQ_RETVAL(handled); } -EXPORT_SYMBOL_GPL(ahci_interrupt); unsigned int ahci_qc_issue(struct ata_queued_cmd *qc) { @@ -2472,24 +2469,8 @@ void ahci_set_em_messages(struct ahci_host_priv *hpriv, } EXPORT_SYMBOL_GPL(ahci_set_em_messages); -/** - * ahci_host_activate - start AHCI host, request IRQs and register it - * @host: target ATA host - * @irq: base IRQ number to request - * @sht: scsi_host_template to use when registering the host - * - * Similar to ata_host_activate, but requests IRQs according to AHCI-1.1 - * when multiple MSIs were allocated. That is one MSI per port, starting - * from @irq. - * - * LOCKING: - * Inherited from calling layer (may sleep). - * - * RETURNS: - * 0 on success, -errno otherwise. - */ -int ahci_host_activate(struct ata_host *host, int irq, - struct scsi_host_template *sht) +static int ahci_host_activate_multi_irqs(struct ata_host *host, int irq, + struct scsi_host_template *sht) { int i, rc; @@ -2531,6 +2512,36 @@ out_free_irqs: return rc; } + +/** + * ahci_host_activate - start AHCI host, request IRQs and register it + * @host: target ATA host + * @irq: base IRQ number to request + * @sht: scsi_host_template to use when registering the host + * + * Similar to ata_host_activate, but requests IRQs according to AHCI-1.1 + * when multiple MSIs were allocated. That is one MSI per port, starting + * from @irq. + * + * LOCKING: + * Inherited from calling layer (may sleep). + * + * RETURNS: + * 0 on success, -errno otherwise. + */ +int ahci_host_activate(struct ata_host *host, int irq, + struct scsi_host_template *sht) +{ + struct ahci_host_priv *hpriv = host->private_data; + int rc; + + if (hpriv->flags & AHCI_HFLAG_MULTI_MSI) + rc = ahci_host_activate_multi_irqs(host, irq, sht); + else + rc = ata_host_activate(host, irq, ahci_interrupt, + IRQF_SHARED, sht); + return rc; +} EXPORT_SYMBOL_GPL(ahci_host_activate); MODULE_AUTHOR("Jeff Garzik"); diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c index c7f787e..0b03f90 100644 --- a/drivers/ata/libahci_platform.c +++ b/drivers/ata/libahci_platform.c @@ -493,8 +493,7 @@ int ahci_platform_init_host(struct platform_device *pdev, ahci_init_controller(host); ahci_print_info(host, "platform"); - return ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED, - &ahci_platform_sht); + return ahci_host_activate(host, irq, &ahci_platform_sht); } EXPORT_SYMBOL_GPL(ahci_platform_init_host); diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c index da3bc27..ce2b99a 100644 --- a/drivers/ata/sata_highbank.c +++ b/drivers/ata/sata_highbank.c @@ -568,8 +568,7 @@ static int ahci_highbank_probe(struct platform_device *pdev) ahci_init_controller(host); ahci_print_info(host, "platform"); - rc = ata_host_activate(host, irq, ahci_interrupt, 0, - &ahci_highbank_platform_sht); + rc = ahci_host_activate(host, irq, &ahci_highbank_platform_sht); if (rc) goto err0; -- cgit v1.1 From 5ee1cfd975518bc9cdcd79e0b76552b5ae5c8c1e Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Mon, 29 Sep 2014 18:26:00 +0200 Subject: AHCI: Make few function names more descriptive Signed-off-by: Alexander Gordeev Signed-off-by: Tejun Heo Cc: linux-ide@vger.kernel.org --- drivers/ata/libahci.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 0080551..48175e5 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -1789,7 +1789,7 @@ static void ahci_port_intr(struct ata_port *ap) ahci_handle_port_interrupt(ap, port_mmio, status); } -static irqreturn_t ahci_thread_fn(int irq, void *dev_instance) +static irqreturn_t ahci_port_thread_fn(int irq, void *dev_instance) { struct ata_port *ap = dev_instance; struct ahci_port_priv *pp = ap->private_data; @@ -1810,7 +1810,7 @@ static irqreturn_t ahci_thread_fn(int irq, void *dev_instance) return IRQ_HANDLED; } -static void ahci_hw_port_interrupt(struct ata_port *ap) +static void ahci_update_intr_status(struct ata_port *ap) { void __iomem *port_mmio = ahci_port_base(ap); struct ahci_port_priv *pp = ap->private_data; @@ -1822,7 +1822,7 @@ static void ahci_hw_port_interrupt(struct ata_port *ap) pp->intr_status |= status; } -static irqreturn_t ahci_hw_interrupt(int irq, void *dev_instance) +static irqreturn_t ahci_multi_irqs_intr(int irq, void *dev_instance) { struct ata_port *ap_this = dev_instance; struct ahci_port_priv *pp = ap_this->private_data; @@ -1858,7 +1858,7 @@ static irqreturn_t ahci_hw_interrupt(int irq, void *dev_instance) ap = host->ports[i]; if (ap) { - ahci_hw_port_interrupt(ap); + ahci_update_intr_status(ap); VPRINTK("port %u\n", i); } else { VPRINTK("port %u (no irq)\n", i); @@ -1877,7 +1877,7 @@ static irqreturn_t ahci_hw_interrupt(int irq, void *dev_instance) return IRQ_WAKE_THREAD; } -static irqreturn_t ahci_interrupt(int irq, void *dev_instance) +static irqreturn_t ahci_single_irq_intr(int irq, void *dev_instance) { struct ata_host *host = dev_instance; struct ahci_host_priv *hpriv; @@ -2488,8 +2488,8 @@ static int ahci_host_activate_multi_irqs(struct ata_host *host, int irq, } rc = devm_request_threaded_irq(host->dev, irq + i, - ahci_hw_interrupt, - ahci_thread_fn, IRQF_SHARED, + ahci_multi_irqs_intr, + ahci_port_thread_fn, IRQF_SHARED, pp->irq_desc, host->ports[i]); if (rc) goto out_free_irqs; @@ -2538,7 +2538,7 @@ int ahci_host_activate(struct ata_host *host, int irq, if (hpriv->flags & AHCI_HFLAG_MULTI_MSI) rc = ahci_host_activate_multi_irqs(host, irq, sht); else - rc = ata_host_activate(host, irq, ahci_interrupt, + rc = ata_host_activate(host, irq, ahci_single_irq_intr, IRQF_SHARED, sht); return rc; } -- cgit v1.1 From 227dfb4dbf109596d76a9b842856c4ff68e4efb2 Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Mon, 29 Sep 2014 18:26:01 +0200 Subject: AHCI: Do not read HOST_IRQ_STAT reg in multi-MSI mode As described in AHCI v1.0 specification chapter 10.6.2.2 "Multiple MSI Based Messages" generation of interrupts is not controlled through the HOST_IRQ_STAT register. Considering MMIO access is expensive remove unnecessary reading and writing of HOST_IRQ_STAT register. Further, serializing access to the host data is no longer needed and the interrupt service routine can avoid competing on the host lock. Signed-off-by: Alexander Gordeev Suggested-by: "Jiang, Dave" Signed-off-by: Tejun Heo Cc: "Jiang, Dave" Cc: linux-ide@vger.kernel.org --- drivers/ata/ahci.h | 2 +- drivers/ata/libahci.c | 67 ++++++--------------------------------------------- 2 files changed, 9 insertions(+), 60 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index 6a22055..40f0e34 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -304,7 +304,7 @@ struct ahci_port_priv { unsigned int ncq_saw_d2h:1; unsigned int ncq_saw_dmas:1; unsigned int ncq_saw_sdb:1; - u32 intr_status; /* interrupts to handle */ + atomic_t intr_status; /* interrupts to handle */ spinlock_t lock; /* protects parent ata_port */ u32 intr_mask; /* interrupts to enable */ bool fbs_supported; /* set iff FBS is supported */ diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 48175e5..97683e4 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -1794,14 +1794,11 @@ static irqreturn_t ahci_port_thread_fn(int irq, void *dev_instance) struct ata_port *ap = dev_instance; struct ahci_port_priv *pp = ap->private_data; void __iomem *port_mmio = ahci_port_base(ap); - unsigned long flags; u32 status; - spin_lock_irqsave(&ap->host->lock, flags); - status = pp->intr_status; - if (status) - pp->intr_status = 0; - spin_unlock_irqrestore(&ap->host->lock, flags); + status = atomic_xchg(&pp->intr_status, 0); + if (!status) + return IRQ_NONE; spin_lock_bh(ap->lock); ahci_handle_port_interrupt(ap, port_mmio, status); @@ -1810,67 +1807,19 @@ static irqreturn_t ahci_port_thread_fn(int irq, void *dev_instance) return IRQ_HANDLED; } -static void ahci_update_intr_status(struct ata_port *ap) +static irqreturn_t ahci_multi_irqs_intr(int irq, void *dev_instance) { + struct ata_port *ap = dev_instance; void __iomem *port_mmio = ahci_port_base(ap); struct ahci_port_priv *pp = ap->private_data; u32 status; - status = readl(port_mmio + PORT_IRQ_STAT); - writel(status, port_mmio + PORT_IRQ_STAT); - - pp->intr_status |= status; -} - -static irqreturn_t ahci_multi_irqs_intr(int irq, void *dev_instance) -{ - struct ata_port *ap_this = dev_instance; - struct ahci_port_priv *pp = ap_this->private_data; - struct ata_host *host = ap_this->host; - struct ahci_host_priv *hpriv = host->private_data; - void __iomem *mmio = hpriv->mmio; - unsigned int i; - u32 irq_stat, irq_masked; - VPRINTK("ENTER\n"); - spin_lock(&host->lock); - - irq_stat = readl(mmio + HOST_IRQ_STAT); - - if (!irq_stat) { - u32 status = pp->intr_status; - - spin_unlock(&host->lock); - - VPRINTK("EXIT\n"); - - return status ? IRQ_WAKE_THREAD : IRQ_NONE; - } - - irq_masked = irq_stat & hpriv->port_map; - - for (i = 0; i < host->n_ports; i++) { - struct ata_port *ap; - - if (!(irq_masked & (1 << i))) - continue; - - ap = host->ports[i]; - if (ap) { - ahci_update_intr_status(ap); - VPRINTK("port %u\n", i); - } else { - VPRINTK("port %u (no irq)\n", i); - if (ata_ratelimit()) - dev_warn(host->dev, - "interrupt on disabled port %u\n", i); - } - } - - writel(irq_stat, mmio + HOST_IRQ_STAT); + status = readl(port_mmio + PORT_IRQ_STAT); + writel(status, port_mmio + PORT_IRQ_STAT); - spin_unlock(&host->lock); + atomic_or(status, &pp->intr_status); VPRINTK("EXIT\n"); -- cgit v1.1 From 18dcf433f3ded61eb140a55e7048ec2fef79e723 Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Mon, 6 Oct 2014 16:24:45 +0100 Subject: AHCI: Optimize single IRQ interrupt processing Split interrupt service routine into hardware context handler and threaded context handler. That allows to protect ports with individual locks rather than with a single host-wide lock and move port interrupts handling out of the hardware interrupt context. Testing was done by transferring 8GB on two hard drives in parallel using command 'dd if=/dev/sd{a,b} of=/dev/null'. With lock_stat statistics I measured access times to ata_host::lock spinlock (since interrupt handler code is fully embraced with this lock). The average lock's holdtime decreased eight times while average waittime decreased two times. Both before and after the change the transfer time is the same, while 'perf record -e cycles:k ...' shows 1%-4% CPU time spent in ahci_single_irq_intr() routine before the update and not even sampled/shown ahci_single_irq_intr() after the update. Signed-off-by: Alexander Gordeev Signed-off-by: Tejun Heo Cc: linux-ide@vger.kernel.org --- drivers/ata/libahci.c | 74 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 61 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 97683e4..3ce3d23 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -1778,15 +1778,16 @@ static void ahci_handle_port_interrupt(struct ata_port *ap, } } -static void ahci_port_intr(struct ata_port *ap) +static void ahci_update_intr_status(struct ata_port *ap) { void __iomem *port_mmio = ahci_port_base(ap); + struct ahci_port_priv *pp = ap->private_data; u32 status; status = readl(port_mmio + PORT_IRQ_STAT); writel(status, port_mmio + PORT_IRQ_STAT); - ahci_handle_port_interrupt(ap, port_mmio, status); + atomic_or(status, &pp->intr_status); } static irqreturn_t ahci_port_thread_fn(int irq, void *dev_instance) @@ -1807,6 +1808,34 @@ static irqreturn_t ahci_port_thread_fn(int irq, void *dev_instance) return IRQ_HANDLED; } +irqreturn_t ahci_thread_fn(int irq, void *dev_instance) +{ + struct ata_host *host = dev_instance; + struct ahci_host_priv *hpriv = host->private_data; + u32 irq_masked = hpriv->port_map; + unsigned int i; + + for (i = 0; i < host->n_ports; i++) { + struct ata_port *ap; + + if (!(irq_masked & (1 << i))) + continue; + + ap = host->ports[i]; + if (ap) { + ahci_port_thread_fn(irq, ap); + VPRINTK("port %u\n", i); + } else { + VPRINTK("port %u (no irq)\n", i); + if (ata_ratelimit()) + dev_warn(host->dev, + "interrupt on disabled port %u\n", i); + } + } + + return IRQ_HANDLED; +} + static irqreturn_t ahci_multi_irqs_intr(int irq, void *dev_instance) { struct ata_port *ap = dev_instance; @@ -1856,7 +1885,7 @@ static irqreturn_t ahci_single_irq_intr(int irq, void *dev_instance) ap = host->ports[i]; if (ap) { - ahci_port_intr(ap); + ahci_update_intr_status(ap); VPRINTK("port %u\n", i); } else { VPRINTK("port %u (no irq)\n", i); @@ -1883,7 +1912,7 @@ static irqreturn_t ahci_single_irq_intr(int irq, void *dev_instance) VPRINTK("EXIT\n"); - return IRQ_RETVAL(handled); + return handled ? IRQ_WAKE_THREAD : IRQ_NONE; } unsigned int ahci_qc_issue(struct ata_queued_cmd *qc) @@ -2295,13 +2324,8 @@ static int ahci_port_start(struct ata_port *ap) */ pp->intr_mask = DEF_PORT_IRQ; - /* - * Switch to per-port locking in case each port has its own MSI vector. - */ - if ((hpriv->flags & AHCI_HFLAG_MULTI_MSI)) { - spin_lock_init(&pp->lock); - ap->lock = &pp->lock; - } + spin_lock_init(&pp->lock); + ap->lock = &pp->lock; ap->private_data = pp; @@ -2462,6 +2486,31 @@ out_free_irqs: return rc; } +static int ahci_host_activate_single_irq(struct ata_host *host, int irq, + struct scsi_host_template *sht) +{ + int i, rc; + + rc = ata_host_start(host); + if (rc) + return rc; + + rc = devm_request_threaded_irq(host->dev, irq, ahci_single_irq_intr, + ahci_thread_fn, IRQF_SHARED, + dev_driver_string(host->dev), host); + if (rc) + return rc; + + for (i = 0; i < host->n_ports; i++) + ata_port_desc(host->ports[i], "irq %d", irq); + + rc = ata_host_register(host, sht); + if (rc) + devm_free_irq(host->dev, irq, host); + + return rc; +} + /** * ahci_host_activate - start AHCI host, request IRQs and register it * @host: target ATA host @@ -2487,8 +2536,7 @@ int ahci_host_activate(struct ata_host *host, int irq, if (hpriv->flags & AHCI_HFLAG_MULTI_MSI) rc = ahci_host_activate_multi_irqs(host, irq, sht); else - rc = ata_host_activate(host, irq, ahci_single_irq_intr, - IRQF_SHARED, sht); + rc = ahci_host_activate_single_irq(host, irq, sht); return rc; } EXPORT_SYMBOL_GPL(ahci_host_activate); -- cgit v1.1 From 33fb0d01ce60fe4c0c12c4f0c134c5cdb818ac5a Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Mon, 6 Oct 2014 16:26:35 +0100 Subject: AHCI: Do not acquire ata_host::lock from single IRQ handler There is no need to acquire ata_host::lock spinlock from hardware context single IRQ interrupt handler since the handler does not access host data that could be altered by concurrent processors. Signed-off-by: Alexander Gordeev Signed-off-by: Tejun Heo Cc: linux-ide@vger.kernel.org --- drivers/ata/libahci.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 3ce3d23..5eb61c9 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -1875,8 +1875,6 @@ static irqreturn_t ahci_single_irq_intr(int irq, void *dev_instance) irq_masked = irq_stat & hpriv->port_map; - spin_lock(&host->lock); - for (i = 0; i < host->n_ports; i++) { struct ata_port *ap; @@ -1908,8 +1906,6 @@ static irqreturn_t ahci_single_irq_intr(int irq, void *dev_instance) */ writel(irq_stat, mmio + HOST_IRQ_STAT); - spin_unlock(&host->lock); - VPRINTK("EXIT\n"); return handled ? IRQ_WAKE_THREAD : IRQ_NONE; -- cgit v1.1 From 1c40279960bcd7d52dbdf1d466b20d24b99176c8 Mon Sep 17 00:00:00 2001 From: George Spelvin Date: Tue, 7 Oct 2014 07:26:38 -0400 Subject: libata: Un-break ATA blacklist lib/glob.c provides a new glob_match() function, with arguments in (pattern, string) order. It replaced a private function with arguments in (string, pattern) order, but I didn't swap the call site... The result was the entire ATA blacklist was effectively disabled. The lesson for today is "I f***ed up *how* badly *how* many months ago?", er, I mean "Nobody Tests RC Kernels On Legacy Hardware". This was not a subtle break, but it made it through an entire RC cycle unreported, presumably because all the people doing testing have full-featured hardware. (FWIW, the reason for the argument swap was because fnmatch() does it that way, and for a while implementing a full fnmatch() was being considered.) Fixes: 428ac5fc056e0 (libata: Use glob_match from lib/glob.c) Reported-by: Steven Honeyman Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=71371#c21 Signed-off-by: George Spelvin Cc: # 3.17 Tested-by: Steven Honeyman Signed-off-by: Tejun Heo --- drivers/ata/libata-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index f785ae5..bea6d37 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4261,10 +4261,10 @@ static unsigned long ata_dev_blacklisted(const struct ata_device *dev) ata_id_c_string(dev->id, model_rev, ATA_ID_FW_REV, sizeof(model_rev)); while (ad->model_num) { - if (glob_match(model_num, ad->model_num)) { + if (glob_match(ad->model_num, model_num)) { if (ad->model_rev == NULL) return ad->horkage; - if (glob_match(model_rev, ad->model_rev)) + if (glob_match(ad->model_rev, model_rev)) return ad->horkage; } ad++; -- cgit v1.1 From 37017ac6849e772e67dd187ba2fbd056c4afa533 Mon Sep 17 00:00:00 2001 From: Scott Carter Date: Wed, 24 Sep 2014 18:13:09 -0700 Subject: pata_serverworks: disable 64-KB DMA transfers on Broadcom OSB4 IDE Controller The Broadcom OSB4 IDE Controller (vendor and device IDs: 1166:0211) does not support 64-KB DMA transfers. Whenever a 64-KB DMA transfer is attempted, the transfer fails and messages similar to the following are written to the console log: [ 2431.851125] sr 0:0:0:0: [sr0] Unhandled sense code [ 2431.851139] sr 0:0:0:0: [sr0] Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE [ 2431.851152] sr 0:0:0:0: [sr0] Sense Key : Hardware Error [current] [ 2431.851166] sr 0:0:0:0: [sr0] Add. Sense: Logical unit communication time-out [ 2431.851182] sr 0:0:0:0: [sr0] CDB: Read(10): 28 00 00 00 76 f4 00 00 40 00 [ 2431.851210] end_request: I/O error, dev sr0, sector 121808 When the libata and pata_serverworks modules are recompiled with ATA_DEBUG and ATA_VERBOSE_DEBUG defined in libata.h, the 64-KB transfer size in the scatter-gather list can be seen in the console log: [ 2664.897267] sr 9:0:0:0: [sr0] Send: [ 2664.897274] 0xf63d85e0 [ 2664.897283] sr 9:0:0:0: [sr0] CDB: [ 2664.897288] Read(10): 28 00 00 00 7f b4 00 00 40 00 [ 2664.897319] buffer = 0xf6d6fbc0, bufflen = 131072, queuecommand 0xf81b7700 [ 2664.897331] ata_scsi_dump_cdb: CDB (1:0,0,0) 28 00 00 00 7f b4 00 00 40 [ 2664.897338] ata_scsi_translate: ENTER [ 2664.897345] ata_sg_setup: ENTER, ata1 [ 2664.897356] ata_sg_setup: 3 sg elements mapped [ 2664.897364] ata_bmdma_fill_sg: PRD[0] = (0x66FD2000, 0xE000) [ 2664.897371] ata_bmdma_fill_sg: PRD[1] = (0x65000000, 0x10000) ------------------------------------------------------> ======= [ 2664.897378] ata_bmdma_fill_sg: PRD[2] = (0x66A10000, 0x2000) [ 2664.897386] ata1: ata_dev_select: ENTER, device 0, wait 1 [ 2664.897422] ata_sff_tf_load: feat 0x1 nsect 0x0 lba 0x0 0x0 0xFC [ 2664.897428] ata_sff_tf_load: device 0xA0 [ 2664.897448] ata_sff_exec_command: ata1: cmd 0xA0 [ 2664.897457] ata_scsi_translate: EXIT [ 2664.897462] leaving scsi_dispatch_cmnd() [ 2664.897497] Doing sr request, dev = sr0, block = 0 [ 2664.897507] sr0 : reading 64/256 512 byte blocks. [ 2664.897553] ata_sff_hsm_move: ata1: protocol 7 task_state 1 (dev_stat 0x58) [ 2664.897560] atapi_send_cdb: send cdb [ 2666.910058] ata_bmdma_port_intr: ata1: host_stat 0x64 [ 2666.910079] __ata_sff_port_intr: ata1: protocol 7 task_state 3 [ 2666.910093] ata_sff_hsm_move: ata1: protocol 7 task_state 3 (dev_stat 0x51) [ 2666.910101] ata_sff_hsm_move: ata1: protocol 7 task_state 4 (dev_stat 0x51) [ 2666.910129] sr 9:0:0:0: [sr0] Done: [ 2666.910136] 0xf63d85e0 TIMEOUT lspci shows that the driver used for the Broadcom OSB4 IDE Controller is pata_serverworks: 00:0f.1 IDE interface: Broadcom OSB4 IDE Controller (prog-if 8e [Master SecP SecO PriP]) Flags: bus master, medium devsel, latency 64 [virtual] Memory at 000001f0 (32-bit, non-prefetchable) [size=8] [virtual] Memory at 000003f0 (type 3, non-prefetchable) [size=1] I/O ports at 0170 [size=8] I/O ports at 0374 [size=4] I/O ports at 1440 [size=16] Kernel driver in use: pata_serverworks The pata_serverworks driver supports five distinct device IDs, one being the OSB4 and the other four belonging to the CSB series. The CSB series appears to support 64-KB DMA transfers, as tests on a machine with an SAI2 motherboard containing a Broadcom CSB5 IDE Controller (vendor and device IDs: 1166:0212) showed no problems with 64-KB DMA transfers. This problem was first discovered when attempting to install openSUSE from a DVD on a machine with an STL2 motherboard. Using the pata_serverworks module, older releases of openSUSE will not install at all due to the timeouts. Releases of openSUSE prior to 11.3 can be installed by disabling the pata_serverworks module using the brokenmodules boot parameter, which causes the serverworks module to be used instead. Recent releases of openSUSE (12.2 and later) include better error recovery and will install, though very slowly. On all openSUSE releases, the problem can be recreated on a machine containing a Broadcom OSB4 IDE Controller by mounting an install DVD and running a command similar to the following: find /mnt -type f -print | xargs cat > /dev/null The patch below corrects the problem. Similar to the other ATA drivers that do not support 64-KB DMA transfers, the patch changes the ata_port_operations qc_prep vector to point to a routine that breaks any 64-KB segment into two 32-KB segments and changes the scsi_host_template sg_tablesize element to reduce by half the number of scatter/gather elements allowed. These two changes affect only the OSB4. Signed-off-by: Scott Carter Signed-off-by: Tejun Heo Cc: stable@vger.kernel.org --- drivers/ata/pata_serverworks.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c index fc5f31d..57de021 100644 --- a/drivers/ata/pata_serverworks.c +++ b/drivers/ata/pata_serverworks.c @@ -251,12 +251,18 @@ static void serverworks_set_dmamode(struct ata_port *ap, struct ata_device *adev pci_write_config_byte(pdev, 0x54, ultra_cfg); } -static struct scsi_host_template serverworks_sht = { +static struct scsi_host_template serverworks_osb4_sht = { + ATA_BMDMA_SHT(DRV_NAME), + .sg_tablesize = LIBATA_DUMB_MAX_PRD, +}; + +static struct scsi_host_template serverworks_csb_sht = { ATA_BMDMA_SHT(DRV_NAME), }; static struct ata_port_operations serverworks_osb4_port_ops = { .inherits = &ata_bmdma_port_ops, + .qc_prep = ata_bmdma_dumb_qc_prep, .cable_detect = serverworks_cable_detect, .mode_filter = serverworks_osb4_filter, .set_piomode = serverworks_set_piomode, @@ -265,6 +271,7 @@ static struct ata_port_operations serverworks_osb4_port_ops = { static struct ata_port_operations serverworks_csb_port_ops = { .inherits = &serverworks_osb4_port_ops, + .qc_prep = ata_bmdma_qc_prep, .mode_filter = serverworks_csb_filter, }; @@ -404,6 +411,7 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id } }; const struct ata_port_info *ppi[] = { &info[id->driver_data], NULL }; + struct scsi_host_template *sht = &serverworks_csb_sht; int rc; rc = pcim_enable_device(pdev); @@ -417,6 +425,7 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id /* Select non UDMA capable OSB4 if we can't do fixups */ if (rc < 0) ppi[0] = &info[1]; + sht = &serverworks_osb4_sht; } /* setup CSB5/CSB6 : South Bridge and IDE option RAID */ else if ((pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) || @@ -433,7 +442,7 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id ppi[1] = &ata_dummy_port_info; } - return ata_pci_bmdma_init_one(pdev, ppi, &serverworks_sht, NULL, 0); + return ata_pci_bmdma_init_one(pdev, ppi, sht, NULL, 0); } #ifdef CONFIG_PM_SLEEP -- cgit v1.1