summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/ata/qcom-sata.txt48
-rw-r--r--arch/blackfin/mach-bf537/boards/cm_bf537e.c3
-rw-r--r--arch/blackfin/mach-bf537/boards/cm_bf537u.c3
-rw-r--r--arch/blackfin/mach-bf537/boards/stamp.c3
-rw-r--r--arch/blackfin/mach-bf537/boards/tcm_bf537.c3
-rw-r--r--arch/blackfin/mach-bf561/boards/cm_bf561.c3
-rw-r--r--drivers/ata/acard-ahci.c3
-rw-r--r--drivers/ata/ahci.c82
-rw-r--r--drivers/ata/ahci.h10
-rw-r--r--drivers/ata/ahci_platform.c18
-rw-r--r--drivers/ata/ahci_xgene.c10
-rw-r--r--drivers/ata/libahci.c195
-rw-r--r--drivers/ata/libahci_platform.c32
-rw-r--r--drivers/ata/libata-core.c41
-rw-r--r--drivers/ata/libata-sff.c20
-rw-r--r--drivers/ata/pata_imx.c9
-rw-r--r--drivers/ata/pata_of_platform.c24
-rw-r--r--drivers/ata/pata_platform.c4
-rw-r--r--drivers/ata/pata_serverworks.c13
-rw-r--r--drivers/ata/sata_highbank.c3
-rw-r--r--include/linux/ahci_platform.h13
-rw-r--r--include/linux/ata_platform.h5
-rw-r--r--include/linux/libata.h12
23 files changed, 259 insertions, 298 deletions
diff --git a/Documentation/devicetree/bindings/ata/qcom-sata.txt b/Documentation/devicetree/bindings/ata/qcom-sata.txt
new file mode 100644
index 00000000000..094de91cd9f
--- /dev/null
+++ b/Documentation/devicetree/bindings/ata/qcom-sata.txt
@@ -0,0 +1,48 @@
+* Qualcomm AHCI SATA Controller
+
+SATA nodes are defined to describe on-chip Serial ATA controllers.
+Each SATA controller should have its own node.
+
+Required properties:
+- compatible : compatible list, must contain "generic-ahci"
+- interrupts : <interrupt mapping for SATA IRQ>
+- reg : <registers mapping>
+- phys : Must contain exactly one entry as specified
+ in phy-bindings.txt
+- phy-names : Must be "sata-phy"
+
+Required properties for "qcom,ipq806x-ahci" compatible:
+- clocks : Must contain an entry for each entry in clock-names.
+- clock-names : Shall be:
+ "slave_iface" - Fabric port AHB clock for SATA
+ "iface" - AHB clock
+ "core" - core clock
+ "rxoob" - RX out-of-band clock
+ "pmalive" - Power Module Alive clock
+- assigned-clocks : Shall be:
+ SATA_RXOOB_CLK
+ SATA_PMALIVE_CLK
+- assigned-clock-rates : Shall be:
+ 100Mhz (100000000) for SATA_RXOOB_CLK
+ 100Mhz (100000000) for SATA_PMALIVE_CLK
+
+Example:
+ sata@29000000 {
+ compatible = "qcom,ipq806x-ahci", "generic-ahci";
+ reg = <0x29000000 0x180>;
+
+ interrupts = <0 209 0x0>;
+
+ clocks = <&gcc SFAB_SATA_S_H_CLK>,
+ <&gcc SATA_H_CLK>,
+ <&gcc SATA_A_CLK>,
+ <&gcc SATA_RXOOB_CLK>,
+ <&gcc SATA_PMALIVE_CLK>;
+ clock-names = "slave_iface", "iface", "core",
+ "rxoob", "pmalive";
+ assigned-clocks = <&gcc SATA_RXOOB_CLK>, <&gcc SATA_PMALIVE_CLK>;
+ assigned-clock-rates = <100000000>, <100000000>;
+
+ phys = <&sata_phy>;
+ phy-names = "sata-phy";
+ };
diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537e.c b/arch/blackfin/mach-bf537/boards/cm_bf537e.c
index 1e7290ef352..1e1014df5e9 100644
--- a/arch/blackfin/mach-bf537/boards/cm_bf537e.c
+++ b/arch/blackfin/mach-bf537/boards/cm_bf537e.c
@@ -733,7 +733,6 @@ static struct platform_device bfin_mac_device = {
static struct pata_platform_info bfin_pata_platform_data = {
.ioport_shift = 2,
- .irq_type = IRQF_TRIGGER_HIGH,
};
static struct resource bfin_pata_resources[] = {
@@ -750,7 +749,7 @@ static struct resource bfin_pata_resources[] = {
{
.start = PATA_INT,
.end = PATA_INT,
- .flags = IORESOURCE_IRQ,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
},
};
diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537u.c b/arch/blackfin/mach-bf537/boards/cm_bf537u.c
index c7495dc7469..d056db9e559 100644
--- a/arch/blackfin/mach-bf537/boards/cm_bf537u.c
+++ b/arch/blackfin/mach-bf537/boards/cm_bf537u.c
@@ -587,7 +587,6 @@ static struct platform_device bfin_mac_device = {
static struct pata_platform_info bfin_pata_platform_data = {
.ioport_shift = 2,
- .irq_type = IRQF_TRIGGER_HIGH,
};
static struct resource bfin_pata_resources[] = {
@@ -604,7 +603,7 @@ static struct resource bfin_pata_resources[] = {
{
.start = PATA_INT,
.end = PATA_INT,
- .flags = IORESOURCE_IRQ,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
},
};
diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c
index de19b8a5600..88a19fc9844 100644
--- a/arch/blackfin/mach-bf537/boards/stamp.c
+++ b/arch/blackfin/mach-bf537/boards/stamp.c
@@ -2462,7 +2462,6 @@ static struct platform_device bfin_sport0_device = {
#define PATA_INT IRQ_PF5
static struct pata_platform_info bfin_pata_platform_data = {
.ioport_shift = 1,
- .irq_flags = IRQF_TRIGGER_HIGH,
};
static struct resource bfin_pata_resources[] = {
@@ -2479,7 +2478,7 @@ static struct resource bfin_pata_resources[] = {
{
.start = PATA_INT,
.end = PATA_INT,
- .flags = IORESOURCE_IRQ,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
},
};
#elif defined(CF_IDE_NAND_CARD_USE_CF_IN_COMMON_MEMORY_MODE)
diff --git a/arch/blackfin/mach-bf537/boards/tcm_bf537.c b/arch/blackfin/mach-bf537/boards/tcm_bf537.c
index 6b988ad653d..ed309c9a62b 100644
--- a/arch/blackfin/mach-bf537/boards/tcm_bf537.c
+++ b/arch/blackfin/mach-bf537/boards/tcm_bf537.c
@@ -589,7 +589,6 @@ static struct platform_device bfin_mac_device = {
static struct pata_platform_info bfin_pata_platform_data = {
.ioport_shift = 2,
- .irq_type = IRQF_TRIGGER_HIGH,
};
static struct resource bfin_pata_resources[] = {
@@ -606,7 +605,7 @@ static struct resource bfin_pata_resources[] = {
{
.start = PATA_INT,
.end = PATA_INT,
- .flags = IORESOURCE_IRQ,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
},
};
diff --git a/arch/blackfin/mach-bf561/boards/cm_bf561.c b/arch/blackfin/mach-bf561/boards/cm_bf561.c
index e862f7823e6..c6db52ba3a0 100644
--- a/arch/blackfin/mach-bf561/boards/cm_bf561.c
+++ b/arch/blackfin/mach-bf561/boards/cm_bf561.c
@@ -354,7 +354,6 @@ static struct platform_device bfin_sir0_device = {
static struct pata_platform_info bfin_pata_platform_data = {
.ioport_shift = 2,
- .irq_type = IRQF_TRIGGER_HIGH,
};
static struct resource bfin_pata_resources[] = {
@@ -371,7 +370,7 @@ static struct resource bfin_pata_resources[] = {
{
.start = PATA_INT,
.end = PATA_INT,
- .flags = IORESOURCE_IRQ,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
},
};
diff --git a/drivers/ata/acard-ahci.c b/drivers/ata/acard-ahci.c
index 25d0ac32e72..c962886d7e7 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 a0cc0edafc7..5f039f19106 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -790,7 +790,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 = {
@@ -1221,6 +1221,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:
@@ -1233,71 +1236,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
- * @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
- *
- * 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, unsigned int n_msis)
-{
- 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;
-
- 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, &ahci_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;
@@ -1306,7 +1244,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");
@@ -1459,9 +1397,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)
@@ -1513,11 +1449,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 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 59ae0ee0014..40f0e34f17a 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,
@@ -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 */
@@ -388,11 +388,9 @@ 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, unsigned int n_msis);
+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,
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index f61ddb9146d..06f1d59fa67 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/ahci_xgene.c b/drivers/ata/ahci_xgene.c
index f03aab187f4..0f8538f238b 100644
--- a/drivers/ata/ahci_xgene.c
+++ b/drivers/ata/ahci_xgene.c
@@ -434,7 +434,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);
@@ -484,7 +484,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);
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index b784e9de426..5eb61c9e63d 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -1778,30 +1778,28 @@ 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);
}
-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;
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);
@@ -1809,47 +1807,13 @@ 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)
-{
- 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;
-}
-
-irqreturn_t ahci_hw_interrupt(int irq, void *dev_instance)
+irqreturn_t ahci_thread_fn(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 ata_host *host = dev_instance;
struct ahci_host_priv *hpriv = host->private_data;
- void __iomem *mmio = hpriv->mmio;
+ u32 irq_masked = hpriv->port_map;
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;
@@ -1859,7 +1823,7 @@ irqreturn_t ahci_hw_interrupt(int irq, void *dev_instance)
ap = host->ports[i];
if (ap) {
- ahci_hw_port_interrupt(ap);
+ ahci_port_thread_fn(irq, ap);
VPRINTK("port %u\n", i);
} else {
VPRINTK("port %u (no irq)\n", i);
@@ -1869,17 +1833,29 @@ irqreturn_t ahci_hw_interrupt(int irq, void *dev_instance)
}
}
- writel(irq_stat, mmio + HOST_IRQ_STAT);
+ return IRQ_HANDLED;
+}
- spin_unlock(&host->lock);
+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;
+
+ VPRINTK("ENTER\n");
+
+ status = readl(port_mmio + PORT_IRQ_STAT);
+ writel(status, port_mmio + PORT_IRQ_STAT);
+
+ atomic_or(status, &pp->intr_status);
VPRINTK("EXIT\n");
return IRQ_WAKE_THREAD;
}
-EXPORT_SYMBOL_GPL(ahci_hw_interrupt);
-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;
@@ -1899,8 +1875,6 @@ irqreturn_t ahci_interrupt(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;
@@ -1909,7 +1883,7 @@ irqreturn_t ahci_interrupt(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);
@@ -1932,13 +1906,10 @@ irqreturn_t ahci_interrupt(int irq, void *dev_instance)
*/
writel(irq_stat, mmio + HOST_IRQ_STAT);
- spin_unlock(&host->lock);
-
VPRINTK("EXIT\n");
- return IRQ_RETVAL(handled);
+ return handled ? IRQ_WAKE_THREAD : IRQ_NONE;
}
-EXPORT_SYMBOL_GPL(ahci_interrupt);
unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
{
@@ -2349,13 +2320,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;
@@ -2472,6 +2438,105 @@ void ahci_set_em_messages(struct ahci_host_priv *hpriv,
}
EXPORT_SYMBOL_GPL(ahci_set_em_messages);
+static int ahci_host_activate_multi_irqs(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_multi_irqs_intr,
+ ahci_port_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_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
+ * @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 = ahci_host_activate_single_irq(host, irq, sht);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(ahci_host_activate);
+
MODULE_AUTHOR("Jeff Garzik");
MODULE_DESCRIPTION("Common AHCI SATA low-level routines");
MODULE_LICENSE("GPL");
diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
index 5b92c290e6c..0b03f905669 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
@@ -495,20 +493,14 @@ 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);
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 +584,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 +592,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 +610,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 +618,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;
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index f3e7b9f894c..c5ba15af87d 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++;
@@ -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;
@@ -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);
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 1121153f1ec..db90aa35cb7 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))
diff --git a/drivers/ata/pata_imx.c b/drivers/ata/pata_imx.c
index af424573c2f..989ff5ac69e 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
},
};
diff --git a/drivers/ata/pata_of_platform.c b/drivers/ata/pata_of_platform.c
index a7e95a54c78..64965398914 100644
--- a/drivers/ata/pata_of_platform.c
+++ b/drivers/ata/pata_of_platform.c
@@ -35,25 +35,14 @@ 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);
- if (irq_res)
- irq_res->flags = 0;
prop = of_get_property(dn, "reg-shift", NULL);
if (prop)
@@ -79,8 +68,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);
diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c
index a5579b55e33..f8cff3e247c 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,
diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c
index fc5f31d4828..57de02123c4 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
diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c
index da3bc2709c6..ce2b99a1ed7 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;
diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h
index 09a947e8bc8..642d6ae4030 100644
--- a/include/linux/ahci_platform.h
+++ b/include/linux/ahci_platform.h
@@ -22,19 +22,6 @@ struct ata_port_info;
struct ahci_host_priv;
struct platform_device;
-/*
- * Note ahci_platform_data is deprecated, it is only kept around for use
- * by the old da850 and spear13xx ahci code.
- * New drivers should instead declare their own platform_driver struct, and
- * use ahci_platform* functions in their own probe, suspend and resume methods.
- */
-struct ahci_platform_data {
- int (*init)(struct device *dev, void __iomem *addr);
- void (*exit)(struct device *dev);
- int (*suspend)(struct device *dev);
- int (*resume)(struct device *dev);
-};
-
int ahci_platform_enable_clks(struct ahci_host_priv *hpriv);
void ahci_platform_disable_clks(struct ahci_host_priv *hpriv);
int ahci_platform_enable_resources(struct ahci_host_priv *hpriv);
diff --git a/include/linux/ata_platform.h b/include/linux/ata_platform.h
index b9fde17f767..5c618a08422 100644
--- a/include/linux/ata_platform.h
+++ b/include/linux/ata_platform.h
@@ -8,11 +8,6 @@ struct pata_platform_info {
* spacing used by ata_std_ports().
*/
unsigned int ioport_shift;
- /*
- * Indicate platform specific irq types and initial
- * IRQ flags when call request_irq()
- */
- unsigned int irq_flags;
};
extern int __pata_platform_probe(struct device *dev,
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 92abb497ab1..bd5fefeaf54 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -1404,14 +1404,14 @@ static inline int sata_srst_pmp(struct ata_link *link)
* printk helpers
*/
__printf(3, 4)
-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, ...);
__printf(3, 4)
-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, ...);
__printf(3, 4)
-int ata_dev_printk(const struct ata_device *dev, const char *level,
- const char *fmt, ...);
+void ata_dev_printk(const struct ata_device *dev, const char *level,
+ const char *fmt, ...);
#define ata_port_err(ap, fmt, ...) \
ata_port_printk(ap, KERN_ERR, fmt, ##__VA_ARGS__)