Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 616d4a98 authored by Mark Lord's avatar Mark Lord Committed by Jeff Garzik
Browse files

sata_mv pci features



Some of the GenIIe EDMA optimizations should not be used
for non-PCI (SOC) devices, and nor for certain configurations
of conventional PCI (non PCI-X, PCIe) buses.

Logic taken/simplified from that in the Marvell proprietary driver.

Signed-off-by: default avatarMark Lord <mlord@pobox.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent 8e7decdb
Loading
Loading
Loading
Loading
+36 −3
Original line number Diff line number Diff line
@@ -361,6 +361,7 @@ enum {
	MV_HP_GEN_II		= (1 << 7),	/* Generation II: 60xx */
	MV_HP_GEN_IIE		= (1 << 8),	/* Generation IIE: 6042/7042 */
	MV_HP_PCIE		= (1 << 9),	/* PCIe bus/regs: 7042 */
	MV_HP_CUT_THROUGH	= (1 << 10),	/* can use EDMA cut-through */

	/* Port private flags (pp_flags) */
	MV_PP_FLAG_EDMA_EN	= (1 << 0),	/* is EDMA engine enabled? */
@@ -1110,8 +1111,10 @@ static void mv_edma_cfg(struct ata_port *ap, int want_ncq)
	else if (IS_GEN_IIE(hpriv)) {
		cfg |= (1 << 23);	/* do not mask PM field in rx'd FIS */
		cfg |= (1 << 22);	/* enab 4-entry host queue cache */
		if (HAS_PCI(ap->host))
			cfg |= (1 << 18);	/* enab early completion */
		cfg |= (1 << 17);	/* enab cut-through (dis stor&forwrd) */
		if (hpriv->hp_flags & MV_HP_CUT_THROUGH)
			cfg |= (1 << 17); /* enab cut-thru (dis stor&forwrd) */

		if (want_ncq && sata_pmp_attached(ap)) {
			cfg |= EDMA_CFG_EDMA_FBS; /* FIS-based switching */
@@ -2496,6 +2499,34 @@ static void mv_port_init(struct ata_ioports *port, void __iomem *port_mmio)
		readl(port_mmio + EDMA_ERR_IRQ_MASK_OFS));
}

static unsigned int mv_in_pcix_mode(struct ata_host *host)
{
	struct mv_host_priv *hpriv = host->private_data;
	void __iomem *mmio = hpriv->base;
	u32 reg;

	if (!HAS_PCI(host) || !IS_PCIE(hpriv))
		return 0;	/* not PCI-X capable */
	reg = readl(mmio + MV_PCI_MODE_OFS);
	if ((reg & MV_PCI_MODE_MASK) == 0)
		return 0;	/* conventional PCI mode */
	return 1;	/* chip is in PCI-X mode */
}

static int mv_pci_cut_through_okay(struct ata_host *host)
{
	struct mv_host_priv *hpriv = host->private_data;
	void __iomem *mmio = hpriv->base;
	u32 reg;

	if (!mv_in_pcix_mode(host)) {
		reg = readl(mmio + PCI_COMMAND_OFS);
		if (reg & PCI_COMMAND_MRDTRIG)
			return 0; /* not okay */
	}
	return 1; /* okay */
}

static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
{
	struct pci_dev *pdev = to_pci_dev(host->dev);
@@ -2563,7 +2594,7 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
		break;

	case chip_7042:
		hp_flags |= MV_HP_PCIE;
		hp_flags |= MV_HP_PCIE | MV_HP_CUT_THROUGH;
		if (pdev->vendor == PCI_VENDOR_ID_TTI &&
		    (pdev->device == 0x2300 || pdev->device == 0x2310))
		{
@@ -2597,6 +2628,8 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
	case chip_6042:
		hpriv->ops = &mv6xxx_ops;
		hp_flags |= MV_HP_GEN_IIE;
		if (board_idx == chip_6042 && mv_pci_cut_through_okay(host))
			hp_flags |= MV_HP_CUT_THROUGH;

		switch (pdev->revision) {
		case 0x0: