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>
This commit is contained in:
parent
8e7decdb8b
commit
616d4a98ad
1 changed files with 36 additions and 3 deletions
|
@ -361,6 +361,7 @@ enum {
|
||||||
MV_HP_GEN_II = (1 << 7), /* Generation II: 60xx */
|
MV_HP_GEN_II = (1 << 7), /* Generation II: 60xx */
|
||||||
MV_HP_GEN_IIE = (1 << 8), /* Generation IIE: 6042/7042 */
|
MV_HP_GEN_IIE = (1 << 8), /* Generation IIE: 6042/7042 */
|
||||||
MV_HP_PCIE = (1 << 9), /* PCIe bus/regs: 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) */
|
/* Port private flags (pp_flags) */
|
||||||
MV_PP_FLAG_EDMA_EN = (1 << 0), /* is EDMA engine enabled? */
|
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)) {
|
else if (IS_GEN_IIE(hpriv)) {
|
||||||
cfg |= (1 << 23); /* do not mask PM field in rx'd FIS */
|
cfg |= (1 << 23); /* do not mask PM field in rx'd FIS */
|
||||||
cfg |= (1 << 22); /* enab 4-entry host queue cache */
|
cfg |= (1 << 22); /* enab 4-entry host queue cache */
|
||||||
cfg |= (1 << 18); /* enab early completion */
|
if (HAS_PCI(ap->host))
|
||||||
cfg |= (1 << 17); /* enab cut-through (dis stor&forwrd) */
|
cfg |= (1 << 18); /* enab early completion */
|
||||||
|
if (hpriv->hp_flags & MV_HP_CUT_THROUGH)
|
||||||
|
cfg |= (1 << 17); /* enab cut-thru (dis stor&forwrd) */
|
||||||
|
|
||||||
if (want_ncq && sata_pmp_attached(ap)) {
|
if (want_ncq && sata_pmp_attached(ap)) {
|
||||||
cfg |= EDMA_CFG_EDMA_FBS; /* FIS-based switching */
|
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));
|
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)
|
static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
|
||||||
{
|
{
|
||||||
struct pci_dev *pdev = to_pci_dev(host->dev);
|
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;
|
break;
|
||||||
|
|
||||||
case chip_7042:
|
case chip_7042:
|
||||||
hp_flags |= MV_HP_PCIE;
|
hp_flags |= MV_HP_PCIE | MV_HP_CUT_THROUGH;
|
||||||
if (pdev->vendor == PCI_VENDOR_ID_TTI &&
|
if (pdev->vendor == PCI_VENDOR_ID_TTI &&
|
||||||
(pdev->device == 0x2300 || pdev->device == 0x2310))
|
(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:
|
case chip_6042:
|
||||||
hpriv->ops = &mv6xxx_ops;
|
hpriv->ops = &mv6xxx_ops;
|
||||||
hp_flags |= MV_HP_GEN_IIE;
|
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) {
|
switch (pdev->revision) {
|
||||||
case 0x0:
|
case 0x0:
|
||||||
|
|
Loading…
Reference in a new issue