Skip to content

Commit

Permalink
Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/ker…
Browse files Browse the repository at this point in the history
…nel/git/jgarzik/libata-dev

* 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev: (32 commits)
  [libata] sata_mv: print out additional chip info during probe
  [libata] Use ATA_UDMAx standard masks when filling driver's udma_mask info
  [libata] AHCI: Add support for Marvell AHCI-like chips (initially 6145)
  [libata] Clean up driver udma_mask initializers
  libata: Support chips with 64K PRD quirk
  Add a PCI ID for santa rosa's PATA controller.
  sata_sil24: sil24_interrupt() micro-optimisation
  Add irq_flags to struct pata_platform_info
  sata_promise: cleanups
  [libata] pata_ixp4xx: kill unused var
  ata_piix: fix pio/mwdma programming
  [libata] ahci: minor internal cleanups
  [ATA] Add named constant for ATAPI command DEVICE RESET
  [libata] sata_sx4, sata_via: minor documentation updates
  [libata] ahci: minor internal cleanups
  [libata] ahci: Factor out SATA port init into a separate function
  [libata] pata_sil680: minor cleanups from benh
  [libata] sata_sx4: named constant cleanup
  [libata] pata_ixp4xx: convert to new EH
  [libata] pdc_adma: Reorder initializers with a couple structs
  ...
  • Loading branch information
Linus Torvalds committed Jul 10, 2007
2 parents 0f16639 + c1e4fe7 commit 64b853a
Show file tree
Hide file tree
Showing 61 changed files with 1,052 additions and 919 deletions.
159 changes: 111 additions & 48 deletions drivers/ata/ahci.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,15 @@
#include <linux/libata.h>

#define DRV_NAME "ahci"
#define DRV_VERSION "2.2"
#define DRV_VERSION "2.3"


enum {
AHCI_PCI_BAR = 5,
AHCI_MAX_PORTS = 32,
AHCI_MAX_SG = 168, /* hardware max is 64K */
AHCI_DMA_BOUNDARY = 0xffffffff,
AHCI_USE_CLUSTERING = 0,
AHCI_USE_CLUSTERING = 1,
AHCI_MAX_CMDS = 32,
AHCI_CMD_SZ = 32,
AHCI_CMD_SLOT_SZ = AHCI_MAX_CMDS * AHCI_CMD_SZ,
Expand All @@ -81,6 +81,7 @@ enum {
board_ahci_vt8251 = 2,
board_ahci_ign_iferr = 3,
board_ahci_sb600 = 4,
board_ahci_mv = 5,

/* global controller registers */
HOST_CAP = 0x00, /* host capabilities */
Expand Down Expand Up @@ -171,6 +172,8 @@ enum {
AHCI_FLAG_HONOR_PI = (1 << 26), /* honor PORTS_IMPL */
AHCI_FLAG_IGN_SERR_INTERNAL = (1 << 27), /* ignore SERR_INTERNAL */
AHCI_FLAG_32BIT_ONLY = (1 << 28), /* force 32bit */
AHCI_FLAG_MV_PATA = (1 << 29), /* PATA port */
AHCI_FLAG_NO_MSI = (1 << 30), /* no PCI MSI */

AHCI_FLAG_COMMON = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
Expand Down Expand Up @@ -228,9 +231,12 @@ static void ahci_thaw(struct ata_port *ap);
static void ahci_error_handler(struct ata_port *ap);
static void ahci_vt8251_error_handler(struct ata_port *ap);
static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
static int ahci_port_resume(struct ata_port *ap);
static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl);
static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
u32 opts);
#ifdef CONFIG_PM
static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg);
static int ahci_port_resume(struct ata_port *ap);
static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
static int ahci_pci_device_resume(struct pci_dev *pdev);
#endif
Expand Down Expand Up @@ -327,29 +333,29 @@ static const struct ata_port_info ahci_port_info[] = {
{
.flags = AHCI_FLAG_COMMON,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
.udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops,
},
/* board_ahci_pi */
{
.flags = AHCI_FLAG_COMMON | AHCI_FLAG_HONOR_PI,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
.udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops,
},
/* board_ahci_vt8251 */
{
.flags = AHCI_FLAG_COMMON | ATA_FLAG_HRST_TO_RESUME |
AHCI_FLAG_NO_NCQ,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
.udma_mask = ATA_UDMA6,
.port_ops = &ahci_vt8251_ops,
},
/* board_ahci_ign_iferr */
{
.flags = AHCI_FLAG_COMMON | AHCI_FLAG_IGN_IRQ_IF_ERR,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
.udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops,
},
/* board_ahci_sb600 */
Expand All @@ -358,7 +364,19 @@ static const struct ata_port_info ahci_port_info[] = {
AHCI_FLAG_IGN_SERR_INTERNAL |
AHCI_FLAG_32BIT_ONLY,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
.udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops,
},
/* board_ahci_mv */
{
.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 |
AHCI_FLAG_NO_NCQ | AHCI_FLAG_NO_MSI |
AHCI_FLAG_MV_PATA,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops,
},
};
Expand Down Expand Up @@ -456,6 +474,9 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 966 */
{ PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */

/* Marvell */
{ PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */

/* Generic, PCI class code for AHCI */
{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
Expand All @@ -481,11 +502,17 @@ static inline int ahci_nr_ports(u32 cap)
return (cap & 0x1f) + 1;
}

static inline void __iomem *ahci_port_base(struct ata_port *ap)
static inline void __iomem *__ahci_port_base(struct ata_host *host,
unsigned int port_no)
{
void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
void __iomem *mmio = host->iomap[AHCI_PCI_BAR];

return mmio + 0x100 + (port_no * 0x80);
}

return mmio + 0x100 + (ap->port_no * 0x80);
static inline void __iomem *ahci_port_base(struct ata_port *ap)
{
return __ahci_port_base(ap->host, ap->port_no);
}

/**
Expand Down Expand Up @@ -535,6 +562,20 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
hpriv->saved_port_map = port_map;
}

/*
* Temporary Marvell 6145 hack: PATA port presence
* is asserted through the standard AHCI port
* presence register, as bit 4 (counting from 0)
*/
if (pi->flags & AHCI_FLAG_MV_PATA) {
dev_printk(KERN_ERR, &pdev->dev,
"MV_AHCI HACK: port_map %x -> %x\n",
hpriv->port_map,
hpriv->port_map & 0xf);

port_map &= 0xf;
}

/* cross check port_map and cap.n_ports */
if (pi->flags & AHCI_FLAG_HONOR_PI) {
u32 tmp_port_map = port_map;
Expand Down Expand Up @@ -740,7 +781,7 @@ static void ahci_power_down(struct ata_port *ap)
}
#endif

static void ahci_init_port(struct ata_port *ap)
static void ahci_start_port(struct ata_port *ap)
{
/* enable FIS reception */
ahci_start_fis_rx(ap);
Expand Down Expand Up @@ -814,39 +855,62 @@ static int ahci_reset_controller(struct ata_host *host)
return 0;
}

static void ahci_port_init(struct pci_dev *pdev, struct ata_port *ap,
int port_no, void __iomem *mmio,
void __iomem *port_mmio)
{
const char *emsg = NULL;
int rc;
u32 tmp;

/* make sure port is not active */
rc = ahci_deinit_port(ap, &emsg);
if (rc)
dev_printk(KERN_WARNING, &pdev->dev,
"%s (%d)\n", emsg, rc);

/* clear SError */
tmp = readl(port_mmio + PORT_SCR_ERR);
VPRINTK("PORT_SCR_ERR 0x%x\n", tmp);
writel(tmp, port_mmio + PORT_SCR_ERR);

/* clear port IRQ */
tmp = readl(port_mmio + PORT_IRQ_STAT);
VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
if (tmp)
writel(tmp, port_mmio + PORT_IRQ_STAT);

writel(1 << port_no, mmio + HOST_IRQ_STAT);
}

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;
int i;
void __iomem *port_mmio;
u32 tmp;

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 (ata_port_is_dummy(ap))
continue;

/* make sure port is not active */
rc = ahci_deinit_port(ap, &emsg);
if (rc)
dev_printk(KERN_WARNING, &pdev->dev,
"%s (%d)\n", emsg, rc);
if (host->ports[0]->flags & AHCI_FLAG_MV_PATA) {
port_mmio = __ahci_port_base(host, 4);

/* clear SError */
tmp = readl(port_mmio + PORT_SCR_ERR);
VPRINTK("PORT_SCR_ERR 0x%x\n", tmp);
writel(tmp, port_mmio + PORT_SCR_ERR);
writel(0, port_mmio + PORT_IRQ_MASK);

/* clear port IRQ */
tmp = readl(port_mmio + PORT_IRQ_STAT);
VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
if (tmp)
writel(tmp, port_mmio + PORT_IRQ_STAT);
}

writel(1 << i, mmio + HOST_IRQ_STAT);
for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap = host->ports[i];

port_mmio = ahci_port_base(ap);
if (ata_port_is_dummy(ap))
continue;

ahci_port_init(pdev, ap, i, mmio, port_mmio);
}

tmp = readl(mmio + HOST_CTL);
Expand Down Expand Up @@ -1232,7 +1296,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
ata_port_abort(ap);
}

static void ahci_host_intr(struct ata_port *ap)
static void ahci_port_intr(struct ata_port *ap)
{
void __iomem *port_mmio = ap->ioaddr.cmd_addr;
struct ata_eh_info *ehi = &ap->eh_info;
Expand Down Expand Up @@ -1358,7 +1422,7 @@ static irqreturn_t ahci_interrupt(int irq, void *dev_instance)

ap = host->ports[i];
if (ap) {
ahci_host_intr(ap);
ahci_port_intr(ap);
VPRINTK("port %u\n", i);
} else {
VPRINTK("port %u (no irq)\n", i);
Expand Down Expand Up @@ -1466,7 +1530,7 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
ahci_power_down(ap);
else {
ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc);
ahci_init_port(ap);
ahci_start_port(ap);
}

return rc;
Expand All @@ -1475,7 +1539,7 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
static int ahci_port_resume(struct ata_port *ap)
{
ahci_power_up(ap);
ahci_init_port(ap);
ahci_start_port(ap);

return 0;
}
Expand Down Expand Up @@ -1573,13 +1637,8 @@ static int ahci_port_start(struct ata_port *ap)

ap->private_data = pp;

/* power up port */
ahci_power_up(ap);

/* initialize port */
ahci_init_port(ap);

return 0;
/* engage engines, captain */
return ahci_port_resume(ap);
}

static void ahci_port_stop(struct ata_port *ap)
Expand Down Expand Up @@ -1724,7 +1783,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc)
return rc;

if (pci_enable_msi(pdev))
if ((pi.flags & AHCI_FLAG_NO_MSI) || pci_enable_msi(pdev))
pci_intx(pdev, 1);

hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
Expand All @@ -1745,14 +1804,18 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
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);
struct ata_port *ap = host->ports[i];
void __iomem *port_mmio = ahci_port_base(ap);

/* standard SATA port setup */
if (hpriv->port_map & (1 << i)) {
ap->ioaddr.cmd_addr = port_mmio;
ap->ioaddr.scr_addr = port_mmio + PORT_SCR;
} else
host->ports[i]->ops = &ata_dummy_port_ops;
}

/* disabled/not-implemented port */
else
ap->ops = &ata_dummy_port_ops;
}

/* initialize adapter */
Expand Down
4 changes: 2 additions & 2 deletions drivers/ata/ata_generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,10 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id
u16 command;
static const struct ata_port_info info = {
.sht = &generic_sht,
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = 0x3f,
.udma_mask = ATA_UDMA5,
.port_ops = &generic_port_ops
};
const struct ata_port_info *ppi[] = { &info, NULL };
Expand Down
Loading

0 comments on commit 64b853a

Please sign in to comment.