diff options
author | Mark Lord <liml@rtr.ca> | 2008-05-02 02:08:32 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2008-05-06 11:37:38 -0400 |
commit | 616d4a98ad8749ebe17a8fcac67df65c321350ac (patch) | |
tree | b7b94f059367586ad8bef1bc8db9a536a898f337 /drivers/ata | |
parent | 8e7decdb8b132ee970a2636931b7653dec6af472 (diff) |
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: Mark Lord <mlord@pobox.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/sata_mv.c | 39 |
1 files changed, 36 insertions, 3 deletions
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 4eabb737a48d..10ef9683f048 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c | |||
@@ -361,6 +361,7 @@ enum { | |||
361 | MV_HP_GEN_II = (1 << 7), /* Generation II: 60xx */ | 361 | MV_HP_GEN_II = (1 << 7), /* Generation II: 60xx */ |
362 | MV_HP_GEN_IIE = (1 << 8), /* Generation IIE: 6042/7042 */ | 362 | MV_HP_GEN_IIE = (1 << 8), /* Generation IIE: 6042/7042 */ |
363 | MV_HP_PCIE = (1 << 9), /* PCIe bus/regs: 7042 */ | 363 | MV_HP_PCIE = (1 << 9), /* PCIe bus/regs: 7042 */ |
364 | MV_HP_CUT_THROUGH = (1 << 10), /* can use EDMA cut-through */ | ||
364 | 365 | ||
365 | /* Port private flags (pp_flags) */ | 366 | /* Port private flags (pp_flags) */ |
366 | MV_PP_FLAG_EDMA_EN = (1 << 0), /* is EDMA engine enabled? */ | 367 | 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) | |||
1110 | else if (IS_GEN_IIE(hpriv)) { | 1111 | else if (IS_GEN_IIE(hpriv)) { |
1111 | cfg |= (1 << 23); /* do not mask PM field in rx'd FIS */ | 1112 | cfg |= (1 << 23); /* do not mask PM field in rx'd FIS */ |
1112 | cfg |= (1 << 22); /* enab 4-entry host queue cache */ | 1113 | cfg |= (1 << 22); /* enab 4-entry host queue cache */ |
1113 | cfg |= (1 << 18); /* enab early completion */ | 1114 | if (HAS_PCI(ap->host)) |
1114 | cfg |= (1 << 17); /* enab cut-through (dis stor&forwrd) */ | 1115 | cfg |= (1 << 18); /* enab early completion */ |
1116 | if (hpriv->hp_flags & MV_HP_CUT_THROUGH) | ||
1117 | cfg |= (1 << 17); /* enab cut-thru (dis stor&forwrd) */ | ||
1115 | 1118 | ||
1116 | if (want_ncq && sata_pmp_attached(ap)) { | 1119 | if (want_ncq && sata_pmp_attached(ap)) { |
1117 | cfg |= EDMA_CFG_EDMA_FBS; /* FIS-based switching */ | 1120 | 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) | |||
2496 | readl(port_mmio + EDMA_ERR_IRQ_MASK_OFS)); | 2499 | readl(port_mmio + EDMA_ERR_IRQ_MASK_OFS)); |
2497 | } | 2500 | } |
2498 | 2501 | ||
2502 | static unsigned int mv_in_pcix_mode(struct ata_host *host) | ||
2503 | { | ||
2504 | struct mv_host_priv *hpriv = host->private_data; | ||
2505 | void __iomem *mmio = hpriv->base; | ||
2506 | u32 reg; | ||
2507 | |||
2508 | if (!HAS_PCI(host) || !IS_PCIE(hpriv)) | ||
2509 | return 0; /* not PCI-X capable */ | ||
2510 | reg = readl(mmio + MV_PCI_MODE_OFS); | ||
2511 | if ((reg & MV_PCI_MODE_MASK) == 0) | ||
2512 | return 0; /* conventional PCI mode */ | ||
2513 | return 1; /* chip is in PCI-X mode */ | ||
2514 | } | ||
2515 | |||
2516 | static int mv_pci_cut_through_okay(struct ata_host *host) | ||
2517 | { | ||
2518 | struct mv_host_priv *hpriv = host->private_data; | ||
2519 | void __iomem *mmio = hpriv->base; | ||
2520 | u32 reg; | ||
2521 | |||
2522 | if (!mv_in_pcix_mode(host)) { | ||
2523 | reg = readl(mmio + PCI_COMMAND_OFS); | ||
2524 | if (reg & PCI_COMMAND_MRDTRIG) | ||
2525 | return 0; /* not okay */ | ||
2526 | } | ||
2527 | return 1; /* okay */ | ||
2528 | } | ||
2529 | |||
2499 | static int mv_chip_id(struct ata_host *host, unsigned int board_idx) | 2530 | static int mv_chip_id(struct ata_host *host, unsigned int board_idx) |
2500 | { | 2531 | { |
2501 | struct pci_dev *pdev = to_pci_dev(host->dev); | 2532 | 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) | |||
2563 | break; | 2594 | break; |
2564 | 2595 | ||
2565 | case chip_7042: | 2596 | case chip_7042: |
2566 | hp_flags |= MV_HP_PCIE; | 2597 | hp_flags |= MV_HP_PCIE | MV_HP_CUT_THROUGH; |
2567 | if (pdev->vendor == PCI_VENDOR_ID_TTI && | 2598 | if (pdev->vendor == PCI_VENDOR_ID_TTI && |
2568 | (pdev->device == 0x2300 || pdev->device == 0x2310)) | 2599 | (pdev->device == 0x2300 || pdev->device == 0x2310)) |
2569 | { | 2600 | { |
@@ -2597,6 +2628,8 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx) | |||
2597 | case chip_6042: | 2628 | case chip_6042: |
2598 | hpriv->ops = &mv6xxx_ops; | 2629 | hpriv->ops = &mv6xxx_ops; |
2599 | hp_flags |= MV_HP_GEN_IIE; | 2630 | hp_flags |= MV_HP_GEN_IIE; |
2631 | if (board_idx == chip_6042 && mv_pci_cut_through_okay(host)) | ||
2632 | hp_flags |= MV_HP_CUT_THROUGH; | ||
2600 | 2633 | ||
2601 | switch (pdev->revision) { | 2634 | switch (pdev->revision) { |
2602 | case 0x0: | 2635 | case 0x0: |