Merge branch 'for-3.18-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata

Pull libata fixes from Tejun Heo:
 "The most notable is the revert of lock splitting optimization in ahci.
  This also made the IRQ handling threaded even when there's only one
  IRQ in use.  The conversion missed IRFQ_SHARED leading to screaming
  IRQs problem in some cases and the threaded IRQ handling showed
  performance regression in some LKP test cases.  The changes are
  reverted for now.  It'll probably be retried once threaded IRQ
  handling is removed from ahci.

  Other than that, there's one fix for ahci and several patches adding
  device IDs"

* 'for-3.18-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata:
  ahci: fix AHCI parameters not taken into account
  ata: sata_rcar: Add r8a7793 device support
  ahci: Add Device IDs for Intel Sunrise Point PCH
  ahci: disable MSI instead of NCQ on Samsung pci-e SSDs on macbooks
  Revert "AHCI: Optimize single IRQ interrupt processing"
  Revert "AHCI: Do not acquire ata_host::lock from single IRQ handler"
  ata: sata_rcar: Disable DIPM mode for r8a7790 ES1
This commit is contained in:
Linus Torvalds 2014-11-14 14:09:19 -08:00
commit e57c641ffb
4 changed files with 55 additions and 72 deletions

View File

@ -3,8 +3,10 @@
Required properties: Required properties:
- compatible : should contain one of the following: - compatible : should contain one of the following:
- "renesas,sata-r8a7779" for R-Car H1 - "renesas,sata-r8a7779" for R-Car H1
- "renesas,sata-r8a7790" for R-Car H2 - "renesas,sata-r8a7790-es1" for R-Car H2 ES1
- "renesas,sata-r8a7791" for R-Car M2 - "renesas,sata-r8a7790" for R-Car H2 other than ES1
- "renesas,sata-r8a7791" for R-Car M2-W
- "renesas,sata-r8a7793" for R-Car M2-N
- reg : address and length of the SATA registers; - reg : address and length of the SATA registers;
- interrupts : must consist of one interrupt specifier. - interrupts : must consist of one interrupt specifier.

View File

@ -60,6 +60,7 @@ enum board_ids {
/* board IDs by feature in alphabetical order */ /* board IDs by feature in alphabetical order */
board_ahci, board_ahci,
board_ahci_ign_iferr, board_ahci_ign_iferr,
board_ahci_nomsi,
board_ahci_noncq, board_ahci_noncq,
board_ahci_nosntf, board_ahci_nosntf,
board_ahci_yes_fbs, board_ahci_yes_fbs,
@ -121,6 +122,13 @@ static const struct ata_port_info ahci_port_info[] = {
.udma_mask = ATA_UDMA6, .udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops, .port_ops = &ahci_ops,
}, },
[board_ahci_nomsi] = {
AHCI_HFLAGS (AHCI_HFLAG_NO_MSI),
.flags = AHCI_FLAG_COMMON,
.pio_mask = ATA_PIO4,
.udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops,
},
[board_ahci_noncq] = { [board_ahci_noncq] = {
AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ), AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ),
.flags = AHCI_FLAG_COMMON, .flags = AHCI_FLAG_COMMON,
@ -313,6 +321,11 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, 0x8c87), board_ahci }, /* 9 Series RAID */ { PCI_VDEVICE(INTEL, 0x8c87), board_ahci }, /* 9 Series RAID */
{ PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */ { PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */
{ PCI_VDEVICE(INTEL, 0x8c8f), board_ahci }, /* 9 Series RAID */ { PCI_VDEVICE(INTEL, 0x8c8f), board_ahci }, /* 9 Series RAID */
{ PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H AHCI */
{ PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H RAID */
{ PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */
{ PCI_VDEVICE(INTEL, 0xa107), board_ahci }, /* Sunrise Point-H RAID */
{ PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */
/* JMicron 360/1/3/5/6, match class to avoid IDE function */ /* JMicron 360/1/3/5/6, match class to avoid IDE function */
{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
@ -475,10 +488,10 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */
/* /*
* Samsung SSDs found on some macbooks. NCQ times out. * Samsung SSDs found on some macbooks. NCQ times out if MSI is
* https://bugzilla.kernel.org/show_bug.cgi?id=60731 * enabled. https://bugzilla.kernel.org/show_bug.cgi?id=60731
*/ */
{ PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_noncq }, { PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_nomsi },
/* Enmotus */ /* Enmotus */
{ PCI_DEVICE(0x1c44, 0x8000), board_ahci }, { PCI_DEVICE(0x1c44, 0x8000), board_ahci },
@ -514,12 +527,9 @@ MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)");
static void ahci_pci_save_initial_config(struct pci_dev *pdev, static void ahci_pci_save_initial_config(struct pci_dev *pdev,
struct ahci_host_priv *hpriv) struct ahci_host_priv *hpriv)
{ {
unsigned int force_port_map = 0;
unsigned int mask_port_map = 0;
if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) { if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) {
dev_info(&pdev->dev, "JMB361 has only one port\n"); dev_info(&pdev->dev, "JMB361 has only one port\n");
force_port_map = 1; hpriv->force_port_map = 1;
} }
/* /*
@ -529,9 +539,9 @@ static void ahci_pci_save_initial_config(struct pci_dev *pdev,
*/ */
if (hpriv->flags & AHCI_HFLAG_MV_PATA) { if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
if (pdev->device == 0x6121) if (pdev->device == 0x6121)
mask_port_map = 0x3; hpriv->mask_port_map = 0x3;
else else
mask_port_map = 0xf; hpriv->mask_port_map = 0xf;
dev_info(&pdev->dev, dev_info(&pdev->dev,
"Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n"); "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
} }

View File

@ -1778,16 +1778,15 @@ static void ahci_handle_port_interrupt(struct ata_port *ap,
} }
} }
static void ahci_update_intr_status(struct ata_port *ap) static void ahci_port_intr(struct ata_port *ap)
{ {
void __iomem *port_mmio = ahci_port_base(ap); void __iomem *port_mmio = ahci_port_base(ap);
struct ahci_port_priv *pp = ap->private_data;
u32 status; u32 status;
status = readl(port_mmio + PORT_IRQ_STAT); status = readl(port_mmio + PORT_IRQ_STAT);
writel(status, port_mmio + PORT_IRQ_STAT); writel(status, port_mmio + PORT_IRQ_STAT);
atomic_or(status, &pp->intr_status); ahci_handle_port_interrupt(ap, port_mmio, status);
} }
static irqreturn_t ahci_port_thread_fn(int irq, void *dev_instance) static irqreturn_t ahci_port_thread_fn(int irq, void *dev_instance)
@ -1808,34 +1807,6 @@ static irqreturn_t ahci_port_thread_fn(int irq, void *dev_instance)
return IRQ_HANDLED; 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) static irqreturn_t ahci_multi_irqs_intr(int irq, void *dev_instance)
{ {
struct ata_port *ap = dev_instance; struct ata_port *ap = dev_instance;
@ -1875,6 +1846,8 @@ static irqreturn_t ahci_single_irq_intr(int irq, void *dev_instance)
irq_masked = irq_stat & hpriv->port_map; irq_masked = irq_stat & hpriv->port_map;
spin_lock(&host->lock);
for (i = 0; i < host->n_ports; i++) { for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap; struct ata_port *ap;
@ -1883,7 +1856,7 @@ static irqreturn_t ahci_single_irq_intr(int irq, void *dev_instance)
ap = host->ports[i]; ap = host->ports[i];
if (ap) { if (ap) {
ahci_update_intr_status(ap); ahci_port_intr(ap);
VPRINTK("port %u\n", i); VPRINTK("port %u\n", i);
} else { } else {
VPRINTK("port %u (no irq)\n", i); VPRINTK("port %u (no irq)\n", i);
@ -1906,9 +1879,11 @@ static irqreturn_t ahci_single_irq_intr(int irq, void *dev_instance)
*/ */
writel(irq_stat, mmio + HOST_IRQ_STAT); writel(irq_stat, mmio + HOST_IRQ_STAT);
spin_unlock(&host->lock);
VPRINTK("EXIT\n"); VPRINTK("EXIT\n");
return handled ? IRQ_WAKE_THREAD : IRQ_NONE; return IRQ_RETVAL(handled);
} }
unsigned int ahci_qc_issue(struct ata_queued_cmd *qc) unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
@ -2320,8 +2295,13 @@ static int ahci_port_start(struct ata_port *ap)
*/ */
pp->intr_mask = DEF_PORT_IRQ; 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); spin_lock_init(&pp->lock);
ap->lock = &pp->lock; ap->lock = &pp->lock;
}
ap->private_data = pp; ap->private_data = pp;
@ -2482,31 +2462,6 @@ out_free_irqs:
return rc; 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 * ahci_host_activate - start AHCI host, request IRQs and register it
* @host: target ATA host * @host: target ATA host
@ -2532,7 +2487,8 @@ int ahci_host_activate(struct ata_host *host, int irq,
if (hpriv->flags & AHCI_HFLAG_MULTI_MSI) if (hpriv->flags & AHCI_HFLAG_MULTI_MSI)
rc = ahci_host_activate_multi_irqs(host, irq, sht); rc = ahci_host_activate_multi_irqs(host, irq, sht);
else else
rc = ahci_host_activate_single_irq(host, irq, sht); rc = ata_host_activate(host, irq, ahci_single_irq_intr,
IRQF_SHARED, sht);
return rc; return rc;
} }
EXPORT_SYMBOL_GPL(ahci_host_activate); EXPORT_SYMBOL_GPL(ahci_host_activate);

View File

@ -146,6 +146,7 @@
enum sata_rcar_type { enum sata_rcar_type {
RCAR_GEN1_SATA, RCAR_GEN1_SATA,
RCAR_GEN2_SATA, RCAR_GEN2_SATA,
RCAR_R8A7790_ES1_SATA,
}; };
struct sata_rcar_priv { struct sata_rcar_priv {
@ -763,6 +764,9 @@ static void sata_rcar_setup_port(struct ata_host *host)
ap->udma_mask = ATA_UDMA6; ap->udma_mask = ATA_UDMA6;
ap->flags |= ATA_FLAG_SATA; ap->flags |= ATA_FLAG_SATA;
if (priv->type == RCAR_R8A7790_ES1_SATA)
ap->flags |= ATA_FLAG_NO_DIPM;
ioaddr->cmd_addr = base + SDATA_REG; ioaddr->cmd_addr = base + SDATA_REG;
ioaddr->ctl_addr = base + SSDEVCON_REG; ioaddr->ctl_addr = base + SSDEVCON_REG;
ioaddr->scr_addr = base + SCRSSTS_REG; ioaddr->scr_addr = base + SCRSSTS_REG;
@ -792,6 +796,7 @@ static void sata_rcar_init_controller(struct ata_host *host)
sata_rcar_gen1_phy_init(priv); sata_rcar_gen1_phy_init(priv);
break; break;
case RCAR_GEN2_SATA: case RCAR_GEN2_SATA:
case RCAR_R8A7790_ES1_SATA:
sata_rcar_gen2_phy_init(priv); sata_rcar_gen2_phy_init(priv);
break; break;
default: default:
@ -837,10 +842,18 @@ static struct of_device_id sata_rcar_match[] = {
.compatible = "renesas,sata-r8a7790", .compatible = "renesas,sata-r8a7790",
.data = (void *)RCAR_GEN2_SATA .data = (void *)RCAR_GEN2_SATA
}, },
{
.compatible = "renesas,sata-r8a7790-es1",
.data = (void *)RCAR_R8A7790_ES1_SATA
},
{ {
.compatible = "renesas,sata-r8a7791", .compatible = "renesas,sata-r8a7791",
.data = (void *)RCAR_GEN2_SATA .data = (void *)RCAR_GEN2_SATA
}, },
{
.compatible = "renesas,sata-r8a7793",
.data = (void *)RCAR_GEN2_SATA
},
{ }, { },
}; };
MODULE_DEVICE_TABLE(of, sata_rcar_match); MODULE_DEVICE_TABLE(of, sata_rcar_match);
@ -849,7 +862,9 @@ static const struct platform_device_id sata_rcar_id_table[] = {
{ "sata_rcar", RCAR_GEN1_SATA }, /* Deprecated by "sata-r8a7779" */ { "sata_rcar", RCAR_GEN1_SATA }, /* Deprecated by "sata-r8a7779" */
{ "sata-r8a7779", RCAR_GEN1_SATA }, { "sata-r8a7779", RCAR_GEN1_SATA },
{ "sata-r8a7790", RCAR_GEN2_SATA }, { "sata-r8a7790", RCAR_GEN2_SATA },
{ "sata-r8a7790-es1", RCAR_R8A7790_ES1_SATA },
{ "sata-r8a7791", RCAR_GEN2_SATA }, { "sata-r8a7791", RCAR_GEN2_SATA },
{ "sata-r8a7793", RCAR_GEN2_SATA },
{ }, { },
}; };
MODULE_DEVICE_TABLE(platform, sata_rcar_id_table); MODULE_DEVICE_TABLE(platform, sata_rcar_id_table);