GIT a50f4be64ca7997ec76b77b637128b19f31bcf15 git+ssh://master.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev.git#ALL commit 8e651ab2146366eaf0c996a87dd39fca14178abf Author: Jeff Garzik Date: Sun Feb 25 20:30:30 2007 -0500 [libata] AHCI: get Marvell SATA going (PATA portion of chip not supported) Signed-off-by: Jeff Garzik commit bbaa9bb11c6854781ac13c64954f42bc0e067c09 Author: Mark Lord Date: Fri Feb 2 12:36:25 2007 -0500 RESEND: libata: check cdb len per dev instead of per host Resending, with s/printk/DPRINTK/ as pointed out by Alan. Fix libata to perform CDB len validation per device rather than per host. This way, validation still works when we have a mix of 12-byte and 16-byte devices on a common host interface. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik commit c5c5eec293679e8995ae6d7bc4273bfa7550f310 Author: Alan Date: Fri Mar 2 00:56:15 2007 +0000 libata: dev_config does not need ap and adev passing It used to be impossible to get from ata_device to ata_port but that is no longer true. Various methods have been cleaned up over time but dev_config still takes both and most users don't need both anyway. Tidy this one up Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik commit 90500a5bb801a0bbe1022d4a0309079601277a66 Author: Jeff Garzik Date: Mon Feb 26 01:26:06 2007 -0500 [libata] sata_mv: clean up DMA boundary issues, turn on 64-bit DMA The chips covered by sata_mv have a 32-bit DMA boundary they must not cross, not a 64K boundary. We are merely limited to a 64K maximum segment size. Therefore, the DMA scatter/gather table fill code can be greatly simplified, and we need not cut in half the S/G table size as reported to the SCSI layer. Also, the driver forget to turn on 64-bit DMA at the PCI layer. All other data structures (both hardware and software) have been prepped for 64-bit PCI DMA. It was simply never turned on. let's see if it still works... Signed-off-by: Jeff Garzik commit bbe4cb1c0e404436c260a269663df78bf0036198 Author: Jeff Garzik Date: Sun Feb 25 16:50:52 2007 -0500 [libata] export sata_print_link_status() To be used in sata_mv's exception handling code, and overall is a generally useful function. Signed-off-by: Jeff Garzik commit beba3b15ffd42e620cb9bf85ccb53079a9bdf01a Author: Jeff Garzik Date: Sat Feb 24 21:26:42 2007 -0500 [libata] sata_mv: remove extra braces Signed-off-by: Jeff Garzik drivers/ata/ahci.c | 53 ++++++++++++++++++++ drivers/ata/libata-core.c | 23 ++------- drivers/ata/libata-scsi.c | 5 +- drivers/ata/pata_ali.c | 2 - drivers/ata/pata_it821x.c | 3 - drivers/ata/pata_pdc202xx_old.c | 3 - drivers/ata/sata_inic162x.c | 2 - drivers/ata/sata_mv.c | 103 +++++++++++++++++++++++---------------- drivers/ata/sata_sil.c | 6 +- drivers/ata/sata_sil24.c | 6 +- include/linux/libata.h | 3 + 11 files changed, 133 insertions(+), 76 deletions(-) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 43cc43d..6a4d627 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -80,6 +80,7 @@ enum { board_ahci_pi = 1, board_ahci_vt8251 = 2, board_ahci_ign_iferr = 3, + board_ahci_mv = 4, /* global controller registers */ HOST_CAP = 0x00, /* host capabilities */ @@ -168,6 +169,7 @@ enum { AHCI_FLAG_NO_NCQ = (1 << 24), AHCI_FLAG_IGN_IRQ_IF_ERR = (1 << 25), /* ignore IRQ_IF_ERR */ AHCI_FLAG_HONOR_PI = (1 << 26), /* honor PORTS_IMPL */ + AHCI_FLAG_MV_PATA = (1 << 27), /* PATA port */ }; struct ahci_cmd_hdr { @@ -362,6 +364,17 @@ static const struct ata_port_info ahci_p .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .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_MV_PATA, + .pio_mask = 0x1f, /* pio0-4 */ + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ + .port_ops = &ahci_ops, + }, }; static const struct pci_device_id ahci_pci_tbl[] = { @@ -431,6 +444,9 @@ static const struct pci_device_id ahci_p { 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 }, @@ -697,13 +713,27 @@ static void ahci_init_controller(void __ int n_ports, unsigned int port_flags, struct ahci_host_priv *hpriv) { + void __iomem *port_mmio; int i, rc; u32 tmp; + if (port_flags & AHCI_FLAG_MV_PATA) { + port_mmio = ahci_port_base(mmio, 4); + + 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); + } + for (i = 0; i < n_ports; i++) { - void __iomem *port_mmio = ahci_port_base(mmio, i); const char *emsg = NULL; + port_mmio = ahci_port_base(mmio, i); + if ((port_flags & AHCI_FLAG_HONOR_PI) && !(hpriv->port_map & (1 << i))) continue; @@ -719,6 +749,9 @@ static void ahci_init_controller(void __ VPRINTK("PORT_SCR_ERR 0x%x\n", tmp); writel(tmp, port_mmio + PORT_SCR_ERR); + /* select the IRQ events we're interested in */ + writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK); + /* clear port IRQ */ tmp = readl(port_mmio + PORT_IRQ_STAT); VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp); @@ -1533,6 +1566,24 @@ static int ahci_host_init(struct ata_pro hpriv->port_map = readl(mmio + HOST_PORTS_IMPL); cap_n_ports = ahci_nr_ports(hpriv->cap); + /* + * Temporary Marvell 6145 hack: PATA port presence + * is asserted through the standard AHCI port + * presence register, as bit 4 (counting from 0) + */ + if (probe_ent->port_flags & AHCI_FLAG_MV_PATA) { + dev_printk(KERN_ERR, &pdev->dev, + "MV_AHCI HACK: port_map %x -> %x, cap_n %u -> %u\n", + hpriv->port_map, + hpriv->port_map & 0xf, + cap_n_ports, + (cap_n_ports > 4) ? 4 : cap_n_ports); + + hpriv->port_map &= 0xf; + if (cap_n_ports > 4) + cap_n_ports = 4; + } + VPRINTK("cap 0x%x port_map 0x%x n_ports %d\n", hpriv->cap, hpriv->port_map, cap_n_ports); diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index dc362fa..cd0ce65 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1560,20 +1560,6 @@ static void ata_dev_config_ncq(struct at snprintf(desc, desc_sz, "NCQ (depth %d/%d)", hdepth, ddepth); } -static void ata_set_port_max_cmd_len(struct ata_port *ap) -{ - int i; - - if (ap->scsi_host) { - unsigned int len = 0; - - for (i = 0; i < ATA_MAX_DEVICES; i++) - len = max(len, ap->device[i].cdb_len); - - ap->scsi_host->max_cmd_len = len; - } -} - /** * ata_dev_configure - Configure the specified ATA/ATAPI device * @dev: Target device to configure @@ -1773,8 +1759,6 @@ int ata_dev_configure(struct ata_device } } - ata_set_port_max_cmd_len(ap); - /* limit bridge transfers to udma5, 200 sectors */ if (ata_dev_knobble(dev)) { if (ata_msg_drv(ap) && print_info) @@ -1785,7 +1769,7 @@ int ata_dev_configure(struct ata_device } if (ap->ops->dev_config) - ap->ops->dev_config(ap, dev); + ap->ops->dev_config(dev); if (ata_msg_probe(ap)) ata_dev_printk(dev, KERN_DEBUG, "%s: EXIT, drv_stat = 0x%x\n", @@ -1951,7 +1935,7 @@ void ata_port_probe(struct ata_port *ap) * LOCKING: * None. */ -static void sata_print_link_status(struct ata_port *ap) +void sata_print_link_status(struct ata_port *ap) { u32 sstatus, scontrol, tmp; @@ -5629,7 +5613,7 @@ static void ata_port_init_shost(struct a shost->max_id = 16; shost->max_lun = 1; shost->max_channel = 1; - shost->max_cmd_len = 12; + shost->max_cmd_len = 16; } /** @@ -6315,6 +6299,7 @@ EXPORT_SYMBOL_GPL(ata_tf_load); EXPORT_SYMBOL_GPL(ata_tf_read); EXPORT_SYMBOL_GPL(ata_noop_dev_select); EXPORT_SYMBOL_GPL(ata_std_dev_select); +EXPORT_SYMBOL_GPL(sata_print_link_status); EXPORT_SYMBOL_GPL(ata_tf_to_fis); EXPORT_SYMBOL_GPL(ata_tf_from_fis); EXPORT_SYMBOL_GPL(ata_check_status); diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 6cc817a..684528e 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -2792,8 +2792,9 @@ static inline int __ata_scsi_queuecmd(st { int rc = 0; - if (unlikely(!scmd->cmd_len)) { - ata_dev_printk(dev, KERN_WARNING, "WARNING: zero len CDB\n"); + if (unlikely(!scmd->cmd_len || scmd->cmd_len > dev->cdb_len)) { + DPRINTK("bad CDB len=%u, max=%u\n", + scmd->cmd_len, dev->cdb_len); scmd->result = DID_ERROR << 16; done(scmd); return 0; diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c index 11ea552..7624340 100644 --- a/drivers/ata/pata_ali.c +++ b/drivers/ata/pata_ali.c @@ -324,7 +324,7 @@ static void ali_set_dmamode(struct ata_p * slower PIO methods */ -static void ali_lock_sectors(struct ata_port *ap, struct ata_device *adev) +static void ali_lock_sectors(struct ata_device *adev) { adev->max_sectors = 255; } diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c index 35ecb2b..be8c9ef 100644 --- a/drivers/ata/pata_it821x.c +++ b/drivers/ata/pata_it821x.c @@ -520,7 +520,6 @@ static int it821x_smart_set_mode(struct /** * it821x_dev_config - Called each device identify - * @ap: ATA port * @adev: Device that has just been identified * * Perform the initial setup needed for each device that is chip @@ -531,7 +530,7 @@ static int it821x_smart_set_mode(struct * basically we need to filter commands for this chip. */ -static void it821x_dev_config(struct ata_port *ap, struct ata_device *adev) +static void it821x_dev_config(struct ata_device *adev) { unsigned char model_num[ATA_ID_PROD_LEN + 1]; diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c index 3fb4177..4c5951c 100644 --- a/drivers/ata/pata_pdc202xx_old.c +++ b/drivers/ata/pata_pdc202xx_old.c @@ -238,7 +238,6 @@ static void pdc2026x_bmdma_stop(struct a /** * pdc2026x_dev_config - device setup hook - * @ap: ATA port * @adev: newly found device * * Perform chip specific early setup. We need to lock the transfer @@ -246,7 +245,7 @@ static void pdc2026x_bmdma_stop(struct a * barf. */ -static void pdc2026x_dev_config(struct ata_port *ap, struct ata_device *adev) +static void pdc2026x_dev_config(struct ata_device *adev) { adev->max_sectors = 256; } diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c index 3193a60..6686c22 100644 --- a/drivers/ata/sata_inic162x.c +++ b/drivers/ata/sata_inic162x.c @@ -492,7 +492,7 @@ static void inic_post_internal_cmd(struc inic_reset_port(inic_port_base(qc->ap)); } -static void inic_dev_config(struct ata_port *ap, struct ata_device *dev) +static void inic_dev_config(struct ata_device *dev) { /* inic can only handle upto LBA28 max sectors */ if (dev->max_sectors > ATA_MAX_SECTORS) diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index a65ba63..7b73c73 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -253,10 +253,7 @@ #define IS_GEN_II(hpriv) IS_60XX(hpriv) #define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE) enum { - /* Our DMA boundary is determined by an ePRD being unable to handle - * anything larger than 64KB - */ - MV_DMA_BOUNDARY = 0xffffU, + MV_DMA_BOUNDARY = 0xffffffffU, EDMA_REQ_Q_BASE_LO_MASK = 0xfffffc00U, @@ -384,10 +381,10 @@ static struct scsi_host_template mv_sht .queuecommand = ata_scsi_queuecmd, .can_queue = MV_USE_Q_DEPTH, .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = MV_MAX_SG_CT / 2, + .sg_tablesize = MV_MAX_SG_CT, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, + .use_clustering = 1, .proc_name = DRV_NAME, .dma_boundary = MV_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, @@ -585,6 +582,39 @@ static const struct mv_hw_ops mv6xxx_ops static int msi; /* Use PCI msi; either zero (off, default) or non-zero */ +/* move to PCI layer or libata core? */ +static int pci_go_64(struct pci_dev *pdev) +{ + int rc; + + if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { + rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); + if (rc) { + rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); + if (rc) { + dev_printk(KERN_ERR, &pdev->dev, + "64-bit DMA enable failed\n"); + return rc; + } + } + } else { + rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + if (rc) { + dev_printk(KERN_ERR, &pdev->dev, + "32-bit DMA enable failed\n"); + return rc; + } + rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); + if (rc) { + dev_printk(KERN_ERR, &pdev->dev, + "32-bit consistent DMA enable failed\n"); + return rc; + } + } + + return rc; +} + /* * Functions */ @@ -798,20 +828,18 @@ static u32 mv_scr_read(struct ata_port * { unsigned int ofs = mv_scr_offset(sc_reg_in); - if (0xffffffffU != ofs) { + if (0xffffffffU != ofs) return readl(mv_ap_base(ap) + ofs); - } else { + else return (u32) ofs; - } } static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val) { unsigned int ofs = mv_scr_offset(sc_reg_in); - if (0xffffffffU != ofs) { + if (0xffffffffU != ofs) writelfl(val, mv_ap_base(ap) + ofs); - } } static void mv_edma_cfg(struct mv_host_priv *hpriv, void __iomem *port_mmio) @@ -959,38 +987,30 @@ static void mv_port_stop(struct ata_port * LOCKING: * Inherited from caller. */ -static void mv_fill_sg(struct ata_queued_cmd *qc) +static unsigned int mv_fill_sg(struct ata_queued_cmd *qc) { struct mv_port_priv *pp = qc->ap->private_data; - unsigned int i = 0; + unsigned int n_sg = 0; struct scatterlist *sg; + struct mv_sg *mv_sg; + mv_sg = pp->sg_tbl; ata_for_each_sg(sg, qc) { - dma_addr_t addr; - u32 sg_len, len, offset; - - addr = sg_dma_address(sg); - sg_len = sg_dma_len(sg); - - while (sg_len) { - offset = addr & MV_DMA_BOUNDARY; - len = sg_len; - if ((offset + sg_len) > 0x10000) - len = 0x10000 - offset; + dma_addr_t addr = sg_dma_address(sg); + u32 sg_len = sg_dma_len(sg); - pp->sg_tbl[i].addr = cpu_to_le32(addr & 0xffffffff); - pp->sg_tbl[i].addr_hi = cpu_to_le32((addr >> 16) >> 16); - pp->sg_tbl[i].flags_size = cpu_to_le32(len & 0xffff); + mv_sg->addr = cpu_to_le32(addr & 0xffffffff); + mv_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16); + mv_sg->flags_size = cpu_to_le32(sg_len & 0xffff); - sg_len -= len; - addr += len; + if (ata_sg_is_last(sg, qc)) + mv_sg->flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL); - if (!sg_len && ata_sg_is_last(sg, qc)) - pp->sg_tbl[i].flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL); - - i++; - } + mv_sg++; + n_sg++; } + + return n_sg; } static inline unsigned mv_inc_q_index(unsigned index) @@ -1320,17 +1340,15 @@ static void mv_host_intr(struct ata_host int shift, port, port0, hard_port, handled; unsigned int err_mask; - if (hc == 0) { + if (hc == 0) port0 = 0; - } else { + else port0 = MV_PORTS_PER_HC; - } /* we'll need the HC success int register in most cases */ hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS); - if (hc_irq_cause) { + if (hc_irq_cause) writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS); - } VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n", hc,relevant,hc_irq_cause); @@ -1425,9 +1443,8 @@ static irqreturn_t mv_interrupt(int irq, /* check the cases where we either have nothing pending or have read * a bogus register value which can indicate HW removal or PCI fault */ - if (!irq_stat || (0xffffffffU == irq_stat)) { + if (!irq_stat || (0xffffffffU == irq_stat)) return IRQ_NONE; - } n_hcs = mv_get_hc_count(host->ports[0]->flags); spin_lock(&host->lock); @@ -2332,6 +2349,10 @@ static int mv_init_one(struct pci_dev *p if (rc) return rc; + rc = pci_go_64(pdev); + if (rc) + return rc; + probe_ent = devm_kzalloc(dev, sizeof(*probe_ent), GFP_KERNEL); if (probe_ent == NULL) return -ENOMEM; diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index 917b7ea..170d36e 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -114,7 +114,7 @@ static int sil_init_one (struct pci_dev #ifdef CONFIG_PM static int sil_pci_device_resume(struct pci_dev *pdev); #endif -static void sil_dev_config(struct ata_port *ap, struct ata_device *dev); +static void sil_dev_config(struct ata_device *dev); static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg); static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); static void sil_post_set_mode (struct ata_port *ap); @@ -521,7 +521,6 @@ static void sil_thaw(struct ata_port *ap /** * sil_dev_config - Apply device/host-specific errata fixups - * @ap: Port containing device to be examined * @dev: Device to be examined * * After the IDENTIFY [PACKET] DEVICE step is complete, and a @@ -548,8 +547,9 @@ static void sil_thaw(struct ata_port *ap * appreciated. * - But then again UDMA5 is hardly anything to complain about */ -static void sil_dev_config(struct ata_port *ap, struct ata_device *dev) +static void sil_dev_config(struct ata_device *dev) { + struct ata_port *ap = dev->ap; int print_info = ap->eh_context.i.flags & ATA_EHI_PRINTINFO; unsigned int n, quirks = 0; unsigned char model_num[ATA_ID_PROD_LEN + 1]; diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index 75d9615..7e3242e 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -323,7 +323,7 @@ struct sil24_port_priv { struct ata_taskfile tf; /* Cached taskfile registers */ }; -static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev); +static void sil24_dev_config(struct ata_device *dev); static u8 sil24_check_status(struct ata_port *ap); static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg); static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val); @@ -461,9 +461,9 @@ static int sil24_tag(int tag) return tag; } -static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev) +static void sil24_dev_config(struct ata_device *dev) { - void __iomem *port = ap->ioaddr.cmd_addr; + void __iomem *port = dev->ap->ioaddr.cmd_addr; if (dev->cdb_len == 16) writel(PORT_CS_CDB16, port + PORT_CTRL_STAT); diff --git a/include/linux/libata.h b/include/linux/libata.h index e3f32f3..065f494 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -595,7 +595,7 @@ struct ata_port { struct ata_port_operations { void (*port_disable) (struct ata_port *); - void (*dev_config) (struct ata_port *, struct ata_device *); + void (*dev_config) (struct ata_device *); void (*set_piomode) (struct ata_port *, struct ata_device *); void (*set_dmamode) (struct ata_port *, struct ata_device *); @@ -699,6 +699,7 @@ static inline int ata_port_is_dummy(stru return ap->ops == &ata_dummy_port_ops; } +extern void sata_print_link_status(struct ata_port *ap); extern void ata_port_probe(struct ata_port *); extern void __sata_phy_reset(struct ata_port *ap); extern void sata_phy_reset(struct ata_port *ap);