|
@@ -211,7 +211,6 @@ static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg);
|
|
|
static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
|
|
|
static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
|
|
|
static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
|
|
|
-static irqreturn_t ahci_interrupt (int irq, void *dev_instance);
|
|
|
static void ahci_irq_clear(struct ata_port *ap);
|
|
|
static int ahci_port_start(struct ata_port *ap);
|
|
|
static void ahci_port_stop(struct ata_port *ap);
|
|
@@ -265,7 +264,6 @@ static const struct ata_port_operations ahci_ops = {
|
|
|
.qc_prep = ahci_qc_prep,
|
|
|
.qc_issue = ahci_qc_issue,
|
|
|
|
|
|
- .irq_handler = ahci_interrupt,
|
|
|
.irq_clear = ahci_irq_clear,
|
|
|
.irq_on = ata_dummy_irq_on,
|
|
|
.irq_ack = ata_dummy_irq_ack,
|
|
@@ -300,7 +298,6 @@ static const struct ata_port_operations ahci_vt8251_ops = {
|
|
|
.qc_prep = ahci_qc_prep,
|
|
|
.qc_issue = ahci_qc_issue,
|
|
|
|
|
|
- .irq_handler = ahci_interrupt,
|
|
|
.irq_clear = ahci_irq_clear,
|
|
|
.irq_on = ata_dummy_irq_on,
|
|
|
.irq_ack = ata_dummy_irq_ack,
|
|
@@ -326,7 +323,6 @@ static const struct ata_port_operations ahci_vt8251_ops = {
|
|
|
static const struct ata_port_info ahci_port_info[] = {
|
|
|
/* board_ahci */
|
|
|
{
|
|
|
- .sht = &ahci_sht,
|
|
|
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
|
|
|
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
|
|
|
ATA_FLAG_SKIP_D2H_BSY,
|
|
@@ -336,7 +332,6 @@ static const struct ata_port_info ahci_port_info[] = {
|
|
|
},
|
|
|
/* board_ahci_pi */
|
|
|
{
|
|
|
- .sht = &ahci_sht,
|
|
|
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
|
|
|
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
|
|
|
ATA_FLAG_SKIP_D2H_BSY | AHCI_FLAG_HONOR_PI,
|
|
@@ -346,7 +341,6 @@ static const struct ata_port_info ahci_port_info[] = {
|
|
|
},
|
|
|
/* board_ahci_vt8251 */
|
|
|
{
|
|
|
- .sht = &ahci_sht,
|
|
|
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
|
|
|
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
|
|
|
ATA_FLAG_SKIP_D2H_BSY |
|
|
@@ -357,7 +351,6 @@ static const struct ata_port_info ahci_port_info[] = {
|
|
|
},
|
|
|
/* board_ahci_ign_iferr */
|
|
|
{
|
|
|
- .sht = &ahci_sht,
|
|
|
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
|
|
|
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
|
|
|
ATA_FLAG_SKIP_D2H_BSY |
|
|
@@ -473,15 +466,18 @@ static inline int ahci_nr_ports(u32 cap)
|
|
|
return (cap & 0x1f) + 1;
|
|
|
}
|
|
|
|
|
|
-static inline void __iomem *ahci_port_base(void __iomem *base,
|
|
|
- unsigned int port)
|
|
|
+static inline void __iomem *ahci_port_base(struct ata_port *ap)
|
|
|
{
|
|
|
- return base + 0x100 + (port * 0x80);
|
|
|
+ void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
|
|
|
+
|
|
|
+ return mmio + 0x100 + (ap->port_no * 0x80);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* ahci_save_initial_config - Save and fixup initial config values
|
|
|
- * @probe_ent: probe_ent of target device
|
|
|
+ * @pdev: target PCI device
|
|
|
+ * @pi: associated ATA port info
|
|
|
+ * @hpriv: host private area to store config values
|
|
|
*
|
|
|
* Some registers containing configuration info might be setup by
|
|
|
* BIOS and might be cleared on reset. This function saves the
|
|
@@ -493,10 +489,11 @@ static inline void __iomem *ahci_port_base(void __iomem *base,
|
|
|
* LOCKING:
|
|
|
* None.
|
|
|
*/
|
|
|
-static void ahci_save_initial_config(struct ata_probe_ent *probe_ent)
|
|
|
+static void ahci_save_initial_config(struct pci_dev *pdev,
|
|
|
+ const struct ata_port_info *pi,
|
|
|
+ struct ahci_host_priv *hpriv)
|
|
|
{
|
|
|
- struct ahci_host_priv *hpriv = probe_ent->private_data;
|
|
|
- void __iomem *mmio = probe_ent->iomap[AHCI_PCI_BAR];
|
|
|
+ void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR];
|
|
|
u32 cap, port_map;
|
|
|
int i;
|
|
|
|
|
@@ -509,7 +506,7 @@ static void ahci_save_initial_config(struct ata_probe_ent *probe_ent)
|
|
|
/* fixup zero port_map */
|
|
|
if (!port_map) {
|
|
|
port_map = (1 << ahci_nr_ports(hpriv->cap)) - 1;
|
|
|
- dev_printk(KERN_WARNING, probe_ent->dev,
|
|
|
+ dev_printk(KERN_WARNING, &pdev->dev,
|
|
|
"PORTS_IMPL is zero, forcing 0x%x\n", port_map);
|
|
|
|
|
|
/* write the fixed up value to the PI register */
|
|
@@ -517,7 +514,7 @@ static void ahci_save_initial_config(struct ata_probe_ent *probe_ent)
|
|
|
}
|
|
|
|
|
|
/* cross check port_map and cap.n_ports */
|
|
|
- if (probe_ent->port_flags & AHCI_FLAG_HONOR_PI) {
|
|
|
+ if (pi->flags & AHCI_FLAG_HONOR_PI) {
|
|
|
u32 tmp_port_map = port_map;
|
|
|
int n_ports = ahci_nr_ports(cap);
|
|
|
|
|
@@ -532,7 +529,7 @@ static void ahci_save_initial_config(struct ata_probe_ent *probe_ent)
|
|
|
* port_map is used to determine number of ports.
|
|
|
*/
|
|
|
if (n_ports || tmp_port_map)
|
|
|
- dev_printk(KERN_WARNING, probe_ent->dev,
|
|
|
+ dev_printk(KERN_WARNING, &pdev->dev,
|
|
|
"nr_ports (%u) and implemented port map "
|
|
|
"(0x%x) don't match\n",
|
|
|
ahci_nr_ports(cap), port_map);
|
|
@@ -548,17 +545,18 @@ static void ahci_save_initial_config(struct ata_probe_ent *probe_ent)
|
|
|
|
|
|
/**
|
|
|
* ahci_restore_initial_config - Restore initial config
|
|
|
- * @mmio: MMIO base for the host
|
|
|
- * @hpriv: host private data
|
|
|
+ * @host: target ATA host
|
|
|
*
|
|
|
* Restore initial config stored by ahci_save_initial_config().
|
|
|
*
|
|
|
* LOCKING:
|
|
|
* None.
|
|
|
*/
|
|
|
-static void ahci_restore_initial_config(void __iomem *mmio,
|
|
|
- struct ahci_host_priv *hpriv)
|
|
|
+static void ahci_restore_initial_config(struct ata_host *host)
|
|
|
{
|
|
|
+ struct ahci_host_priv *hpriv = host->private_data;
|
|
|
+ void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
|
|
|
+
|
|
|
writel(hpriv->saved_cap, mmio + HOST_CAP);
|
|
|
writel(hpriv->saved_port_map, mmio + HOST_PORTS_IMPL);
|
|
|
(void) readl(mmio + HOST_PORTS_IMPL); /* flush */
|
|
@@ -598,8 +596,9 @@ static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg_in,
|
|
|
writel(val, ap->ioaddr.scr_addr + (sc_reg * 4));
|
|
|
}
|
|
|
|
|
|
-static void ahci_start_engine(void __iomem *port_mmio)
|
|
|
+static void ahci_start_engine(struct ata_port *ap)
|
|
|
{
|
|
|
+ void __iomem *port_mmio = ahci_port_base(ap);
|
|
|
u32 tmp;
|
|
|
|
|
|
/* start DMA */
|
|
@@ -609,8 +608,9 @@ static void ahci_start_engine(void __iomem *port_mmio)
|
|
|
readl(port_mmio + PORT_CMD); /* flush */
|
|
|
}
|
|
|
|
|
|
-static int ahci_stop_engine(void __iomem *port_mmio)
|
|
|
+static int ahci_stop_engine(struct ata_port *ap)
|
|
|
{
|
|
|
+ void __iomem *port_mmio = ahci_port_base(ap);
|
|
|
u32 tmp;
|
|
|
|
|
|
tmp = readl(port_mmio + PORT_CMD);
|
|
@@ -632,19 +632,23 @@ static int ahci_stop_engine(void __iomem *port_mmio)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static void ahci_start_fis_rx(void __iomem *port_mmio, u32 cap,
|
|
|
- dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma)
|
|
|
+static void ahci_start_fis_rx(struct ata_port *ap)
|
|
|
{
|
|
|
+ void __iomem *port_mmio = ahci_port_base(ap);
|
|
|
+ struct ahci_host_priv *hpriv = ap->host->private_data;
|
|
|
+ struct ahci_port_priv *pp = ap->private_data;
|
|
|
u32 tmp;
|
|
|
|
|
|
/* set FIS registers */
|
|
|
- if (cap & HOST_CAP_64)
|
|
|
- writel((cmd_slot_dma >> 16) >> 16, port_mmio + PORT_LST_ADDR_HI);
|
|
|
- writel(cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR);
|
|
|
+ if (hpriv->cap & HOST_CAP_64)
|
|
|
+ writel((pp->cmd_slot_dma >> 16) >> 16,
|
|
|
+ port_mmio + PORT_LST_ADDR_HI);
|
|
|
+ writel(pp->cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR);
|
|
|
|
|
|
- if (cap & HOST_CAP_64)
|
|
|
- writel((rx_fis_dma >> 16) >> 16, port_mmio + PORT_FIS_ADDR_HI);
|
|
|
- writel(rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR);
|
|
|
+ if (hpriv->cap & HOST_CAP_64)
|
|
|
+ writel((pp->rx_fis_dma >> 16) >> 16,
|
|
|
+ port_mmio + PORT_FIS_ADDR_HI);
|
|
|
+ writel(pp->rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR);
|
|
|
|
|
|
/* enable FIS reception */
|
|
|
tmp = readl(port_mmio + PORT_CMD);
|
|
@@ -655,8 +659,9 @@ static void ahci_start_fis_rx(void __iomem *port_mmio, u32 cap,
|
|
|
readl(port_mmio + PORT_CMD);
|
|
|
}
|
|
|
|
|
|
-static int ahci_stop_fis_rx(void __iomem *port_mmio)
|
|
|
+static int ahci_stop_fis_rx(struct ata_port *ap)
|
|
|
{
|
|
|
+ void __iomem *port_mmio = ahci_port_base(ap);
|
|
|
u32 tmp;
|
|
|
|
|
|
/* disable FIS reception */
|
|
@@ -673,14 +678,16 @@ static int ahci_stop_fis_rx(void __iomem *port_mmio)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static void ahci_power_up(void __iomem *port_mmio, u32 cap)
|
|
|
+static void ahci_power_up(struct ata_port *ap)
|
|
|
{
|
|
|
+ struct ahci_host_priv *hpriv = ap->host->private_data;
|
|
|
+ void __iomem *port_mmio = ahci_port_base(ap);
|
|
|
u32 cmd;
|
|
|
|
|
|
cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
|
|
|
|
|
|
/* spin up device */
|
|
|
- if (cap & HOST_CAP_SSS) {
|
|
|
+ if (hpriv->cap & HOST_CAP_SSS) {
|
|
|
cmd |= PORT_CMD_SPIN_UP;
|
|
|
writel(cmd, port_mmio + PORT_CMD);
|
|
|
}
|
|
@@ -690,11 +697,13 @@ static void ahci_power_up(void __iomem *port_mmio, u32 cap)
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_PM
|
|
|
-static void ahci_power_down(void __iomem *port_mmio, u32 cap)
|
|
|
+static void ahci_power_down(struct ata_port *ap)
|
|
|
{
|
|
|
+ struct ahci_host_priv *hpriv = ap->host->private_data;
|
|
|
+ void __iomem *port_mmio = ahci_port_base(ap);
|
|
|
u32 cmd, scontrol;
|
|
|
|
|
|
- if (!(cap & HOST_CAP_SSS))
|
|
|
+ if (!(hpriv->cap & HOST_CAP_SSS))
|
|
|
return;
|
|
|
|
|
|
/* put device into listen mode, first set PxSCTL.DET to 0 */
|
|
@@ -709,29 +718,28 @@ static void ahci_power_down(void __iomem *port_mmio, u32 cap)
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
-static void ahci_init_port(void __iomem *port_mmio, u32 cap,
|
|
|
- dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma)
|
|
|
+static void ahci_init_port(struct ata_port *ap)
|
|
|
{
|
|
|
/* enable FIS reception */
|
|
|
- ahci_start_fis_rx(port_mmio, cap, cmd_slot_dma, rx_fis_dma);
|
|
|
+ ahci_start_fis_rx(ap);
|
|
|
|
|
|
/* enable DMA */
|
|
|
- ahci_start_engine(port_mmio);
|
|
|
+ ahci_start_engine(ap);
|
|
|
}
|
|
|
|
|
|
-static int ahci_deinit_port(void __iomem *port_mmio, u32 cap, const char **emsg)
|
|
|
+static int ahci_deinit_port(struct ata_port *ap, const char **emsg)
|
|
|
{
|
|
|
int rc;
|
|
|
|
|
|
/* disable DMA */
|
|
|
- rc = ahci_stop_engine(port_mmio);
|
|
|
+ rc = ahci_stop_engine(ap);
|
|
|
if (rc) {
|
|
|
*emsg = "failed to stop engine";
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
|
/* disable FIS reception */
|
|
|
- rc = ahci_stop_fis_rx(port_mmio);
|
|
|
+ rc = ahci_stop_fis_rx(ap);
|
|
|
if (rc) {
|
|
|
*emsg = "failed stop FIS RX";
|
|
|
return rc;
|
|
@@ -740,9 +748,10 @@ static int ahci_deinit_port(void __iomem *port_mmio, u32 cap, const char **emsg)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev,
|
|
|
- struct ahci_host_priv *hpriv)
|
|
|
+static int ahci_reset_controller(struct ata_host *host)
|
|
|
{
|
|
|
+ struct pci_dev *pdev = to_pci_dev(host->dev);
|
|
|
+ void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
|
|
|
u32 tmp;
|
|
|
|
|
|
/* global controller reset */
|
|
@@ -759,7 +768,7 @@ static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev,
|
|
|
|
|
|
tmp = readl(mmio + HOST_CTL);
|
|
|
if (tmp & HOST_RESET) {
|
|
|
- dev_printk(KERN_ERR, &pdev->dev,
|
|
|
+ dev_printk(KERN_ERR, host->dev,
|
|
|
"controller reset failed (0x%x)\n", tmp);
|
|
|
return -EIO;
|
|
|
}
|
|
@@ -769,7 +778,7 @@ static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev,
|
|
|
(void) readl(mmio + HOST_CTL); /* flush */
|
|
|
|
|
|
/* some registers might be cleared on reset. restore initial values */
|
|
|
- ahci_restore_initial_config(mmio, hpriv);
|
|
|
+ ahci_restore_initial_config(host);
|
|
|
|
|
|
if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
|
|
|
u16 tmp16;
|
|
@@ -783,23 +792,23 @@ static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static void ahci_init_controller(void __iomem *mmio, struct pci_dev *pdev,
|
|
|
- int n_ports, unsigned int port_flags,
|
|
|
- struct ahci_host_priv *hpriv)
|
|
|
+static void ahci_init_controller(struct ata_host *host)
|
|
|
{
|
|
|
+ struct pci_dev *pdev = to_pci_dev(host->dev);
|
|
|
+ void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
|
|
|
int i, rc;
|
|
|
u32 tmp;
|
|
|
|
|
|
- for (i = 0; i < n_ports; i++) {
|
|
|
- void __iomem *port_mmio = ahci_port_base(mmio, i);
|
|
|
+ for (i = 0; i < host->n_ports; i++) {
|
|
|
+ struct ata_port *ap = host->ports[i];
|
|
|
+ void __iomem *port_mmio = ahci_port_base(ap);
|
|
|
const char *emsg = NULL;
|
|
|
|
|
|
- if ((port_flags & AHCI_FLAG_HONOR_PI) &&
|
|
|
- !(hpriv->port_map & (1 << i)))
|
|
|
+ if (ata_port_is_dummy(ap))
|
|
|
continue;
|
|
|
|
|
|
/* make sure port is not active */
|
|
|
- rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
|
|
|
+ rc = ahci_deinit_port(ap, &emsg);
|
|
|
if (rc)
|
|
|
dev_printk(KERN_WARNING, &pdev->dev,
|
|
|
"%s (%d)\n", emsg, rc);
|
|
@@ -827,7 +836,7 @@ static void ahci_init_controller(void __iomem *mmio, struct pci_dev *pdev,
|
|
|
|
|
|
static unsigned int ahci_dev_classify(struct ata_port *ap)
|
|
|
{
|
|
|
- void __iomem *port_mmio = ap->ioaddr.cmd_addr;
|
|
|
+ void __iomem *port_mmio = ahci_port_base(ap);
|
|
|
struct ata_taskfile tf;
|
|
|
u32 tmp;
|
|
|
|
|
@@ -877,8 +886,7 @@ static int ahci_clo(struct ata_port *ap)
|
|
|
static int ahci_softreset(struct ata_port *ap, unsigned int *class)
|
|
|
{
|
|
|
struct ahci_port_priv *pp = ap->private_data;
|
|
|
- void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
|
|
|
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
|
|
+ void __iomem *port_mmio = ahci_port_base(ap);
|
|
|
const u32 cmd_fis_len = 5; /* five dwords */
|
|
|
const char *reason = NULL;
|
|
|
struct ata_taskfile tf;
|
|
@@ -895,7 +903,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class)
|
|
|
}
|
|
|
|
|
|
/* prepare for SRST (AHCI-1.1 10.4.1) */
|
|
|
- rc = ahci_stop_engine(port_mmio);
|
|
|
+ rc = ahci_stop_engine(ap);
|
|
|
if (rc) {
|
|
|
reason = "failed to stop engine";
|
|
|
goto fail_restart;
|
|
@@ -915,7 +923,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class)
|
|
|
}
|
|
|
|
|
|
/* restart engine */
|
|
|
- ahci_start_engine(port_mmio);
|
|
|
+ ahci_start_engine(ap);
|
|
|
|
|
|
ata_tf_init(ap->device, &tf);
|
|
|
fis = pp->cmd_tbl;
|
|
@@ -974,7 +982,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class)
|
|
|
return 0;
|
|
|
|
|
|
fail_restart:
|
|
|
- ahci_start_engine(port_mmio);
|
|
|
+ ahci_start_engine(ap);
|
|
|
fail:
|
|
|
ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason);
|
|
|
return rc;
|
|
@@ -985,13 +993,11 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
|
|
|
struct ahci_port_priv *pp = ap->private_data;
|
|
|
u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
|
|
|
struct ata_taskfile tf;
|
|
|
- void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
|
|
|
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
|
|
int rc;
|
|
|
|
|
|
DPRINTK("ENTER\n");
|
|
|
|
|
|
- ahci_stop_engine(port_mmio);
|
|
|
+ ahci_stop_engine(ap);
|
|
|
|
|
|
/* clear D2H reception area to properly wait for D2H FIS */
|
|
|
ata_tf_init(ap->device, &tf);
|
|
@@ -1000,7 +1006,7 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
|
|
|
|
|
|
rc = sata_std_hardreset(ap, class);
|
|
|
|
|
|
- ahci_start_engine(port_mmio);
|
|
|
+ ahci_start_engine(ap);
|
|
|
|
|
|
if (rc == 0 && ata_port_online(ap))
|
|
|
*class = ahci_dev_classify(ap);
|
|
@@ -1013,20 +1019,18 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
|
|
|
|
|
|
static int ahci_vt8251_hardreset(struct ata_port *ap, unsigned int *class)
|
|
|
{
|
|
|
- void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
|
|
|
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
|
|
int rc;
|
|
|
|
|
|
DPRINTK("ENTER\n");
|
|
|
|
|
|
- ahci_stop_engine(port_mmio);
|
|
|
+ ahci_stop_engine(ap);
|
|
|
|
|
|
rc = sata_port_hardreset(ap, sata_ehc_deb_timing(&ap->eh_context));
|
|
|
|
|
|
/* vt8251 needs SError cleared for the port to operate */
|
|
|
ahci_scr_write(ap, SCR_ERROR, ahci_scr_read(ap, SCR_ERROR));
|
|
|
|
|
|
- ahci_start_engine(port_mmio);
|
|
|
+ ahci_start_engine(ap);
|
|
|
|
|
|
DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
|
|
|
|
|
@@ -1038,7 +1042,7 @@ static int ahci_vt8251_hardreset(struct ata_port *ap, unsigned int *class)
|
|
|
|
|
|
static void ahci_postreset(struct ata_port *ap, unsigned int *class)
|
|
|
{
|
|
|
- void __iomem *port_mmio = ap->ioaddr.cmd_addr;
|
|
|
+ void __iomem *port_mmio = ahci_port_base(ap);
|
|
|
u32 new_tmp, tmp;
|
|
|
|
|
|
ata_std_postreset(ap, class);
|
|
@@ -1206,8 +1210,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
|
|
|
|
|
|
static void ahci_host_intr(struct ata_port *ap)
|
|
|
{
|
|
|
- void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
|
|
|
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
|
|
+ void __iomem *port_mmio = ap->ioaddr.cmd_addr;
|
|
|
struct ata_eh_info *ehi = &ap->eh_info;
|
|
|
struct ahci_port_priv *pp = ap->private_data;
|
|
|
u32 status, qc_active;
|
|
@@ -1358,7 +1361,7 @@ static irqreturn_t ahci_interrupt(int irq, void *dev_instance)
|
|
|
static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
|
|
|
{
|
|
|
struct ata_port *ap = qc->ap;
|
|
|
- void __iomem *port_mmio = ap->ioaddr.cmd_addr;
|
|
|
+ void __iomem *port_mmio = ahci_port_base(ap);
|
|
|
|
|
|
if (qc->tf.protocol == ATA_PROT_NCQ)
|
|
|
writel(1 << qc->tag, port_mmio + PORT_SCR_ACT);
|
|
@@ -1370,8 +1373,7 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
|
|
|
|
|
|
static void ahci_freeze(struct ata_port *ap)
|
|
|
{
|
|
|
- void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
|
|
|
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
|
|
+ void __iomem *port_mmio = ahci_port_base(ap);
|
|
|
|
|
|
/* turn IRQ off */
|
|
|
writel(0, port_mmio + PORT_IRQ_MASK);
|
|
@@ -1380,7 +1382,7 @@ static void ahci_freeze(struct ata_port *ap)
|
|
|
static void ahci_thaw(struct ata_port *ap)
|
|
|
{
|
|
|
void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
|
|
|
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
|
|
+ void __iomem *port_mmio = ahci_port_base(ap);
|
|
|
u32 tmp;
|
|
|
|
|
|
/* clear IRQ */
|
|
@@ -1394,13 +1396,10 @@ static void ahci_thaw(struct ata_port *ap)
|
|
|
|
|
|
static void ahci_error_handler(struct ata_port *ap)
|
|
|
{
|
|
|
- void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
|
|
|
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
|
|
-
|
|
|
if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
|
|
|
/* restart engine */
|
|
|
- ahci_stop_engine(port_mmio);
|
|
|
- ahci_start_engine(port_mmio);
|
|
|
+ ahci_stop_engine(ap);
|
|
|
+ ahci_start_engine(ap);
|
|
|
}
|
|
|
|
|
|
/* perform recovery */
|
|
@@ -1410,13 +1409,10 @@ static void ahci_error_handler(struct ata_port *ap)
|
|
|
|
|
|
static void ahci_vt8251_error_handler(struct ata_port *ap)
|
|
|
{
|
|
|
- void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
|
|
|
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
|
|
-
|
|
|
if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
|
|
|
/* restart engine */
|
|
|
- ahci_stop_engine(port_mmio);
|
|
|
- ahci_start_engine(port_mmio);
|
|
|
+ ahci_stop_engine(ap);
|
|
|
+ ahci_start_engine(ap);
|
|
|
}
|
|
|
|
|
|
/* perform recovery */
|
|
@@ -1427,33 +1423,26 @@ static void ahci_vt8251_error_handler(struct ata_port *ap)
|
|
|
static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
|
|
|
{
|
|
|
struct ata_port *ap = qc->ap;
|
|
|
- void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
|
|
|
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
|
|
|
|
|
if (qc->flags & ATA_QCFLAG_FAILED) {
|
|
|
/* make DMA engine forget about the failed command */
|
|
|
- ahci_stop_engine(port_mmio);
|
|
|
- ahci_start_engine(port_mmio);
|
|
|
+ ahci_stop_engine(ap);
|
|
|
+ ahci_start_engine(ap);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_PM
|
|
|
static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
|
|
|
{
|
|
|
- struct ahci_host_priv *hpriv = ap->host->private_data;
|
|
|
- struct ahci_port_priv *pp = ap->private_data;
|
|
|
- void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
|
|
|
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
|
|
const char *emsg = NULL;
|
|
|
int rc;
|
|
|
|
|
|
- rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
|
|
|
+ rc = ahci_deinit_port(ap, &emsg);
|
|
|
if (rc == 0)
|
|
|
- ahci_power_down(port_mmio, hpriv->cap);
|
|
|
+ ahci_power_down(ap);
|
|
|
else {
|
|
|
ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc);
|
|
|
- ahci_init_port(port_mmio, hpriv->cap,
|
|
|
- pp->cmd_slot_dma, pp->rx_fis_dma);
|
|
|
+ ahci_init_port(ap);
|
|
|
}
|
|
|
|
|
|
return rc;
|
|
@@ -1461,13 +1450,8 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
|
|
|
|
|
|
static int ahci_port_resume(struct ata_port *ap)
|
|
|
{
|
|
|
- struct ahci_port_priv *pp = ap->private_data;
|
|
|
- struct ahci_host_priv *hpriv = ap->host->private_data;
|
|
|
- void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
|
|
|
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
|
|
-
|
|
|
- ahci_power_up(port_mmio, hpriv->cap);
|
|
|
- ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma);
|
|
|
+ ahci_power_up(ap);
|
|
|
+ ahci_init_port(ap);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -1495,8 +1479,6 @@ static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
|
|
|
static int ahci_pci_device_resume(struct pci_dev *pdev)
|
|
|
{
|
|
|
struct ata_host *host = dev_get_drvdata(&pdev->dev);
|
|
|
- struct ahci_host_priv *hpriv = host->private_data;
|
|
|
- void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
|
|
|
int rc;
|
|
|
|
|
|
rc = ata_pci_device_do_resume(pdev);
|
|
@@ -1504,12 +1486,11 @@ static int ahci_pci_device_resume(struct pci_dev *pdev)
|
|
|
return rc;
|
|
|
|
|
|
if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
|
|
|
- rc = ahci_reset_controller(mmio, pdev, hpriv);
|
|
|
+ rc = ahci_reset_controller(host);
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
|
|
|
- ahci_init_controller(mmio, pdev, host->n_ports,
|
|
|
- host->ports[0]->flags, hpriv);
|
|
|
+ ahci_init_controller(host);
|
|
|
}
|
|
|
|
|
|
ata_host_resume(host);
|
|
@@ -1521,10 +1502,7 @@ static int ahci_pci_device_resume(struct pci_dev *pdev)
|
|
|
static int ahci_port_start(struct ata_port *ap)
|
|
|
{
|
|
|
struct device *dev = ap->host->dev;
|
|
|
- struct ahci_host_priv *hpriv = ap->host->private_data;
|
|
|
struct ahci_port_priv *pp;
|
|
|
- void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
|
|
|
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
|
|
void *mem;
|
|
|
dma_addr_t mem_dma;
|
|
|
int rc;
|
|
@@ -1572,60 +1550,29 @@ static int ahci_port_start(struct ata_port *ap)
|
|
|
ap->private_data = pp;
|
|
|
|
|
|
/* power up port */
|
|
|
- ahci_power_up(port_mmio, hpriv->cap);
|
|
|
+ ahci_power_up(ap);
|
|
|
|
|
|
/* initialize port */
|
|
|
- ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma);
|
|
|
+ ahci_init_port(ap);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
static void ahci_port_stop(struct ata_port *ap)
|
|
|
{
|
|
|
- struct ahci_host_priv *hpriv = ap->host->private_data;
|
|
|
- void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
|
|
|
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
|
|
|
const char *emsg = NULL;
|
|
|
int rc;
|
|
|
|
|
|
/* de-initialize port */
|
|
|
- rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
|
|
|
+ rc = ahci_deinit_port(ap, &emsg);
|
|
|
if (rc)
|
|
|
ata_port_printk(ap, KERN_WARNING, "%s (%d)\n", emsg, rc);
|
|
|
}
|
|
|
|
|
|
-static void ahci_setup_port(struct ata_ioports *port, void __iomem *base,
|
|
|
- unsigned int port_idx)
|
|
|
+static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
|
|
|
{
|
|
|
- VPRINTK("ENTER, base==0x%lx, port_idx %u\n", base, port_idx);
|
|
|
- base = ahci_port_base(base, port_idx);
|
|
|
- VPRINTK("base now==0x%lx\n", base);
|
|
|
-
|
|
|
- port->cmd_addr = base;
|
|
|
- port->scr_addr = base + PORT_SCR;
|
|
|
-
|
|
|
- VPRINTK("EXIT\n");
|
|
|
-}
|
|
|
-
|
|
|
-static int ahci_host_init(struct ata_probe_ent *probe_ent)
|
|
|
-{
|
|
|
- struct ahci_host_priv *hpriv = probe_ent->private_data;
|
|
|
- struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
|
|
|
- void __iomem *mmio = probe_ent->iomap[AHCI_PCI_BAR];
|
|
|
- unsigned int i, using_dac;
|
|
|
int rc;
|
|
|
|
|
|
- rc = ahci_reset_controller(mmio, pdev, hpriv);
|
|
|
- if (rc)
|
|
|
- return rc;
|
|
|
-
|
|
|
- probe_ent->n_ports = fls(hpriv->port_map);
|
|
|
- probe_ent->dummy_port_mask = ~hpriv->port_map;
|
|
|
-
|
|
|
- VPRINTK("cap 0x%x port_map 0x%x n_ports %d\n",
|
|
|
- hpriv->cap, hpriv->port_map, probe_ent->n_ports);
|
|
|
-
|
|
|
- using_dac = hpriv->cap & HOST_CAP_64;
|
|
|
if (using_dac &&
|
|
|
!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
|
|
|
rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
|
|
@@ -1651,23 +1598,14 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
|
|
|
return rc;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- for (i = 0; i < probe_ent->n_ports; i++)
|
|
|
- ahci_setup_port(&probe_ent->port[i], mmio, i);
|
|
|
-
|
|
|
- ahci_init_controller(mmio, pdev, probe_ent->n_ports,
|
|
|
- probe_ent->port_flags, hpriv);
|
|
|
-
|
|
|
- pci_set_master(pdev);
|
|
|
-
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static void ahci_print_info(struct ata_probe_ent *probe_ent)
|
|
|
+static void ahci_print_info(struct ata_host *host)
|
|
|
{
|
|
|
- struct ahci_host_priv *hpriv = probe_ent->private_data;
|
|
|
- struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
|
|
|
- void __iomem *mmio = probe_ent->iomap[AHCI_PCI_BAR];
|
|
|
+ struct ahci_host_priv *hpriv = host->private_data;
|
|
|
+ struct pci_dev *pdev = to_pci_dev(host->dev);
|
|
|
+ void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
|
|
|
u32 vers, cap, impl, speed;
|
|
|
const char *speed_s;
|
|
|
u16 cc;
|
|
@@ -1737,11 +1675,12 @@ static void ahci_print_info(struct ata_probe_ent *probe_ent)
|
|
|
static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
|
{
|
|
|
static int printed_version;
|
|
|
- unsigned int board_idx = (unsigned int) ent->driver_data;
|
|
|
+ struct ata_port_info pi = ahci_port_info[ent->driver_data];
|
|
|
+ const struct ata_port_info *ppi[] = { &pi, NULL };
|
|
|
struct device *dev = &pdev->dev;
|
|
|
- struct ata_probe_ent *probe_ent;
|
|
|
struct ahci_host_priv *hpriv;
|
|
|
- int rc;
|
|
|
+ struct ata_host *host;
|
|
|
+ int i, rc;
|
|
|
|
|
|
VPRINTK("ENTER\n");
|
|
|
|
|
@@ -1750,6 +1689,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
|
if (!printed_version++)
|
|
|
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
|
|
|
|
|
|
+ /* acquire resources */
|
|
|
rc = pcim_enable_device(pdev);
|
|
|
if (rc)
|
|
|
return rc;
|
|
@@ -1763,46 +1703,49 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
|
if (pci_enable_msi(pdev))
|
|
|
pci_intx(pdev, 1);
|
|
|
|
|
|
- probe_ent = devm_kzalloc(dev, sizeof(*probe_ent), GFP_KERNEL);
|
|
|
- if (probe_ent == NULL)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- probe_ent->dev = pci_dev_to_dev(pdev);
|
|
|
- INIT_LIST_HEAD(&probe_ent->node);
|
|
|
-
|
|
|
hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
|
|
|
if (!hpriv)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- probe_ent->sht = ahci_port_info[board_idx].sht;
|
|
|
- probe_ent->port_flags = ahci_port_info[board_idx].flags;
|
|
|
- probe_ent->pio_mask = ahci_port_info[board_idx].pio_mask;
|
|
|
- probe_ent->udma_mask = ahci_port_info[board_idx].udma_mask;
|
|
|
- probe_ent->port_ops = ahci_port_info[board_idx].port_ops;
|
|
|
+ /* save initial config */
|
|
|
+ ahci_save_initial_config(pdev, &pi, hpriv);
|
|
|
|
|
|
- probe_ent->irq = pdev->irq;
|
|
|
- probe_ent->irq_flags = IRQF_SHARED;
|
|
|
- probe_ent->iomap = pcim_iomap_table(pdev);
|
|
|
- probe_ent->private_data = hpriv;
|
|
|
+ /* prepare host */
|
|
|
+ if (!(pi.flags & AHCI_FLAG_NO_NCQ) && (hpriv->cap & HOST_CAP_NCQ))
|
|
|
+ pi.flags |= ATA_FLAG_NCQ;
|
|
|
|
|
|
- /* initialize adapter */
|
|
|
- ahci_save_initial_config(probe_ent);
|
|
|
+ host = ata_host_alloc_pinfo(&pdev->dev, ppi, fls(hpriv->port_map));
|
|
|
+ if (!host)
|
|
|
+ return -ENOMEM;
|
|
|
+ host->iomap = pcim_iomap_table(pdev);
|
|
|
+ host->private_data = hpriv;
|
|
|
+
|
|
|
+ for (i = 0; i < host->n_ports; i++) {
|
|
|
+ if (hpriv->port_map & (1 << i)) {
|
|
|
+ struct ata_port *ap = host->ports[i];
|
|
|
+ void __iomem *port_mmio = ahci_port_base(ap);
|
|
|
+
|
|
|
+ ap->ioaddr.cmd_addr = port_mmio;
|
|
|
+ ap->ioaddr.scr_addr = port_mmio + PORT_SCR;
|
|
|
+ } else
|
|
|
+ host->ports[i]->ops = &ata_dummy_port_ops;
|
|
|
+ }
|
|
|
|
|
|
- rc = ahci_host_init(probe_ent);
|
|
|
+ /* initialize adapter */
|
|
|
+ rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64);
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
|
|
|
- if (!(probe_ent->port_flags & AHCI_FLAG_NO_NCQ) &&
|
|
|
- (hpriv->cap & HOST_CAP_NCQ))
|
|
|
- probe_ent->port_flags |= ATA_FLAG_NCQ;
|
|
|
-
|
|
|
- ahci_print_info(probe_ent);
|
|
|
+ rc = ahci_reset_controller(host);
|
|
|
+ if (rc)
|
|
|
+ return rc;
|
|
|
|
|
|
- if (!ata_device_add(probe_ent))
|
|
|
- return -ENODEV;
|
|
|
+ ahci_init_controller(host);
|
|
|
+ ahci_print_info(host);
|
|
|
|
|
|
- devm_kfree(dev, probe_ent);
|
|
|
- return 0;
|
|
|
+ pci_set_master(pdev);
|
|
|
+ return ata_host_activate(host, pdev->irq, ahci_interrupt, IRQF_SHARED,
|
|
|
+ &ahci_sht);
|
|
|
}
|
|
|
|
|
|
static int __init ahci_init(void)
|