mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-18 22:14:16 +00:00
Merge branch 'for-3.15-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata
Pull libata fixes from Tejun Heo: "Dan updated tag allocation to accomodate devices which choke when tags jump back and forth. Quite a few ahci MSI related fixes. A couple config dependency fixes and other misc fixes" * 'for-3.15-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata: libata/ahci: accommodate tag ordered controllers ahci: Do not receive interrupts sent by dummy ports ahci: Use pci_enable_msi_exact() instead of pci_enable_msi_range() ahci: Ensure "MSI Revert to Single Message" mode is not enforced ahci: do not request irq for dummy port pata_samsung_cf: fix ata_host_activate() failure handling pata_arasan_cf: fix ata_host_activate() failure handling ata: fix i.MX AHCI driver dependencies pata_at91: fix ata_host_activate() failure handling libata: Update queued trim blacklist for M5x0 drives libata: make AHCI_XGENE depend on PHY_XGENE
This commit is contained in:
commit
fdd324aa5f
8 changed files with 60 additions and 37 deletions
|
@ -116,7 +116,7 @@ config AHCI_ST
|
||||||
|
|
||||||
config AHCI_IMX
|
config AHCI_IMX
|
||||||
tristate "Freescale i.MX AHCI SATA support"
|
tristate "Freescale i.MX AHCI SATA support"
|
||||||
depends on MFD_SYSCON
|
depends on MFD_SYSCON && (ARCH_MXC || COMPILE_TEST)
|
||||||
help
|
help
|
||||||
This option enables support for the Freescale i.MX SoC's
|
This option enables support for the Freescale i.MX SoC's
|
||||||
onboard AHCI SATA.
|
onboard AHCI SATA.
|
||||||
|
@ -134,8 +134,7 @@ config AHCI_SUNXI
|
||||||
|
|
||||||
config AHCI_XGENE
|
config AHCI_XGENE
|
||||||
tristate "APM X-Gene 6.0Gbps AHCI SATA host controller support"
|
tristate "APM X-Gene 6.0Gbps AHCI SATA host controller support"
|
||||||
depends on ARM64 || COMPILE_TEST
|
depends on PHY_XGENE
|
||||||
select PHY_XGENE
|
|
||||||
help
|
help
|
||||||
This option enables support for APM X-Gene SoC SATA host controller.
|
This option enables support for APM X-Gene SoC SATA host controller.
|
||||||
|
|
||||||
|
|
|
@ -1164,9 +1164,9 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports,
|
static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports,
|
||||||
struct ahci_host_priv *hpriv)
|
struct ahci_host_priv *hpriv)
|
||||||
{
|
{
|
||||||
int nvec;
|
int rc, nvec;
|
||||||
|
|
||||||
if (hpriv->flags & AHCI_HFLAG_NO_MSI)
|
if (hpriv->flags & AHCI_HFLAG_NO_MSI)
|
||||||
goto intx;
|
goto intx;
|
||||||
|
@ -1183,12 +1183,19 @@ static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports,
|
||||||
if (nvec < n_ports)
|
if (nvec < n_ports)
|
||||||
goto single_msi;
|
goto single_msi;
|
||||||
|
|
||||||
nvec = pci_enable_msi_range(pdev, nvec, nvec);
|
rc = pci_enable_msi_exact(pdev, nvec);
|
||||||
if (nvec == -ENOSPC)
|
if (rc == -ENOSPC)
|
||||||
goto single_msi;
|
goto single_msi;
|
||||||
else if (nvec < 0)
|
else if (rc < 0)
|
||||||
goto intx;
|
goto intx;
|
||||||
|
|
||||||
|
/* fallback to single MSI mode if the controller enforced MRSM mode */
|
||||||
|
if (readl(hpriv->mmio + HOST_CTL) & HOST_MRSM) {
|
||||||
|
pci_disable_msi(pdev);
|
||||||
|
printk(KERN_INFO "ahci: MRSM is on, fallback to single MSI\n");
|
||||||
|
goto single_msi;
|
||||||
|
}
|
||||||
|
|
||||||
return nvec;
|
return nvec;
|
||||||
|
|
||||||
single_msi:
|
single_msi:
|
||||||
|
@ -1232,18 +1239,18 @@ int ahci_host_activate(struct ata_host *host, int irq, unsigned int n_msis)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
for (i = 0; i < host->n_ports; i++) {
|
for (i = 0; i < host->n_ports; i++) {
|
||||||
const char* desc;
|
|
||||||
struct ahci_port_priv *pp = host->ports[i]->private_data;
|
struct ahci_port_priv *pp = host->ports[i]->private_data;
|
||||||
|
|
||||||
/* pp is NULL for dummy ports */
|
/* Do not receive interrupts sent by dummy ports */
|
||||||
if (pp)
|
if (!pp) {
|
||||||
desc = pp->irq_desc;
|
disable_irq(irq + i);
|
||||||
else
|
continue;
|
||||||
desc = dev_driver_string(host->dev);
|
}
|
||||||
|
|
||||||
rc = devm_request_threaded_irq(host->dev,
|
rc = devm_request_threaded_irq(host->dev, irq + i,
|
||||||
irq + i, ahci_hw_interrupt, ahci_thread_fn, IRQF_SHARED,
|
ahci_hw_interrupt,
|
||||||
desc, host->ports[i]);
|
ahci_thread_fn, IRQF_SHARED,
|
||||||
|
pp->irq_desc, host->ports[i]);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto out_free_irqs;
|
goto out_free_irqs;
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,6 +94,7 @@ enum {
|
||||||
/* HOST_CTL bits */
|
/* HOST_CTL bits */
|
||||||
HOST_RESET = (1 << 0), /* reset controller; self-clear */
|
HOST_RESET = (1 << 0), /* reset controller; self-clear */
|
||||||
HOST_IRQ_EN = (1 << 1), /* global IRQ enable */
|
HOST_IRQ_EN = (1 << 1), /* global IRQ enable */
|
||||||
|
HOST_MRSM = (1 << 2), /* MSI Revert to Single Message */
|
||||||
HOST_AHCI_EN = (1 << 31), /* AHCI enabled */
|
HOST_AHCI_EN = (1 << 31), /* AHCI enabled */
|
||||||
|
|
||||||
/* HOST_CAP bits */
|
/* HOST_CAP bits */
|
||||||
|
|
|
@ -4224,8 +4224,10 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
|
||||||
{ "PIONEER DVD-RW DVR-216D", NULL, ATA_HORKAGE_NOSETXFER },
|
{ "PIONEER DVD-RW DVR-216D", NULL, ATA_HORKAGE_NOSETXFER },
|
||||||
|
|
||||||
/* devices that don't properly handle queued TRIM commands */
|
/* devices that don't properly handle queued TRIM commands */
|
||||||
{ "Micron_M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, },
|
{ "Micron_M500*", "MU0[1-4]*", ATA_HORKAGE_NO_NCQ_TRIM, },
|
||||||
{ "Crucial_CT???M500SSD*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, },
|
{ "Crucial_CT???M500SSD*", "MU0[1-4]*", ATA_HORKAGE_NO_NCQ_TRIM, },
|
||||||
|
{ "Micron_M550*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, },
|
||||||
|
{ "Crucial_CT???M550SSD*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, },
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Some WD SATA-I drives spin up and down erratically when the link
|
* Some WD SATA-I drives spin up and down erratically when the link
|
||||||
|
@ -4792,21 +4794,26 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
|
||||||
static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
|
static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
|
||||||
{
|
{
|
||||||
struct ata_queued_cmd *qc = NULL;
|
struct ata_queued_cmd *qc = NULL;
|
||||||
unsigned int i;
|
unsigned int i, tag;
|
||||||
|
|
||||||
/* no command while frozen */
|
/* no command while frozen */
|
||||||
if (unlikely(ap->pflags & ATA_PFLAG_FROZEN))
|
if (unlikely(ap->pflags & ATA_PFLAG_FROZEN))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* the last tag is reserved for internal command. */
|
for (i = 0; i < ATA_MAX_QUEUE; i++) {
|
||||||
for (i = 0; i < ATA_MAX_QUEUE - 1; i++)
|
tag = (i + ap->last_tag + 1) % ATA_MAX_QUEUE;
|
||||||
if (!test_and_set_bit(i, &ap->qc_allocated)) {
|
|
||||||
qc = __ata_qc_from_tag(ap, i);
|
/* the last tag is reserved for internal command. */
|
||||||
|
if (tag == ATA_TAG_INTERNAL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!test_and_set_bit(tag, &ap->qc_allocated)) {
|
||||||
|
qc = __ata_qc_from_tag(ap, tag);
|
||||||
|
qc->tag = tag;
|
||||||
|
ap->last_tag = tag;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (qc)
|
|
||||||
qc->tag = i;
|
|
||||||
|
|
||||||
return qc;
|
return qc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -898,9 +898,12 @@ static int arasan_cf_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
cf_card_detect(acdev, 0);
|
cf_card_detect(acdev, 0);
|
||||||
|
|
||||||
return ata_host_activate(host, acdev->irq, irq_handler, 0,
|
ret = ata_host_activate(host, acdev->irq, irq_handler, 0,
|
||||||
&arasan_cf_sht);
|
&arasan_cf_sht);
|
||||||
|
if (!ret)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cf_exit(acdev);
|
||||||
free_clk:
|
free_clk:
|
||||||
clk_put(acdev->clk);
|
clk_put(acdev->clk);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -407,12 +407,13 @@ static int pata_at91_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
host->private_data = info;
|
host->private_data = info;
|
||||||
|
|
||||||
return ata_host_activate(host, gpio_is_valid(irq) ? gpio_to_irq(irq) : 0,
|
ret = ata_host_activate(host, gpio_is_valid(irq) ? gpio_to_irq(irq) : 0,
|
||||||
gpio_is_valid(irq) ? ata_sff_interrupt : NULL,
|
gpio_is_valid(irq) ? ata_sff_interrupt : NULL,
|
||||||
irq_flags, &pata_at91_sht);
|
irq_flags, &pata_at91_sht);
|
||||||
|
if (ret)
|
||||||
|
goto err_put;
|
||||||
|
|
||||||
if (!ret)
|
return 0;
|
||||||
return 0;
|
|
||||||
|
|
||||||
err_put:
|
err_put:
|
||||||
clk_put(info->mck);
|
clk_put(info->mck);
|
||||||
|
|
|
@ -594,9 +594,13 @@ static int __init pata_s3c_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
platform_set_drvdata(pdev, host);
|
platform_set_drvdata(pdev, host);
|
||||||
|
|
||||||
return ata_host_activate(host, info->irq,
|
ret = ata_host_activate(host, info->irq,
|
||||||
info->irq ? pata_s3c_irq : NULL,
|
info->irq ? pata_s3c_irq : NULL,
|
||||||
0, &pata_s3c_sht);
|
0, &pata_s3c_sht);
|
||||||
|
if (ret)
|
||||||
|
goto stop_clk;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
stop_clk:
|
stop_clk:
|
||||||
clk_disable(info->clk);
|
clk_disable(info->clk);
|
||||||
|
|
|
@ -822,6 +822,7 @@ struct ata_port {
|
||||||
unsigned long qc_allocated;
|
unsigned long qc_allocated;
|
||||||
unsigned int qc_active;
|
unsigned int qc_active;
|
||||||
int nr_active_links; /* #links with active qcs */
|
int nr_active_links; /* #links with active qcs */
|
||||||
|
unsigned int last_tag; /* track next tag hw expects */
|
||||||
|
|
||||||
struct ata_link link; /* host default link */
|
struct ata_link link; /* host default link */
|
||||||
struct ata_link *slave_link; /* see ata_slave_link_init() */
|
struct ata_link *slave_link; /* see ata_slave_link_init() */
|
||||||
|
|
Loading…
Add table
Reference in a new issue