mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 19:29:37 +00:00
sata_mv ncq Fix EDMA configuration
Simplify and fix EDMA configuration setup to match Marvell specificiations. The chip documentation gives a specific (re)init sequence, which we now follow. Signed-off-by: Mark Lord <mlord@pobox.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
This commit is contained in:
parent
f630d56282
commit
0c58912e19
1 changed files with 34 additions and 20 deletions
|
@ -210,6 +210,7 @@ enum {
|
|||
/* SATA registers */
|
||||
SATA_STATUS_OFS = 0x300, /* ctrl, err regs follow status */
|
||||
SATA_ACTIVE_OFS = 0x350,
|
||||
SATA_FIS_IRQ_CAUSE_OFS = 0x364,
|
||||
PHY_MODE3 = 0x310,
|
||||
PHY_MODE4 = 0x314,
|
||||
PHY_MODE2 = 0x330,
|
||||
|
@ -222,11 +223,11 @@ enum {
|
|||
|
||||
/* Port registers */
|
||||
EDMA_CFG_OFS = 0,
|
||||
EDMA_CFG_Q_DEPTH = 0, /* queueing disabled */
|
||||
EDMA_CFG_NCQ = (1 << 5),
|
||||
EDMA_CFG_NCQ_GO_ON_ERR = (1 << 14), /* continue on error */
|
||||
EDMA_CFG_RD_BRST_EXT = (1 << 11), /* read burst 512B */
|
||||
EDMA_CFG_WR_BUFF_LEN = (1 << 13), /* write buffer 512B */
|
||||
EDMA_CFG_Q_DEPTH = 0x1f, /* max device queue depth */
|
||||
EDMA_CFG_NCQ = (1 << 5), /* for R/W FPDMA queued */
|
||||
EDMA_CFG_NCQ_GO_ON_ERR = (1 << 14), /* continue on error */
|
||||
EDMA_CFG_RD_BRST_EXT = (1 << 11), /* read burst 512B */
|
||||
EDMA_CFG_WR_BUFF_LEN = (1 << 13), /* write buffer 512B */
|
||||
|
||||
EDMA_ERR_IRQ_CAUSE_OFS = 0x8,
|
||||
EDMA_ERR_IRQ_MASK_OFS = 0xc,
|
||||
|
@ -470,6 +471,8 @@ static void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
|
|||
static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio);
|
||||
static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
|
||||
unsigned int port_no);
|
||||
static void mv_edma_cfg(struct ata_port *ap, struct mv_host_priv *hpriv,
|
||||
void __iomem *port_mmio);
|
||||
|
||||
static struct scsi_host_template mv5_sht = {
|
||||
.module = THIS_MODULE,
|
||||
|
@ -834,13 +837,33 @@ static void mv_set_edma_ptrs(void __iomem *port_mmio,
|
|||
* LOCKING:
|
||||
* Inherited from caller.
|
||||
*/
|
||||
static void mv_start_dma(void __iomem *port_mmio, struct mv_host_priv *hpriv,
|
||||
static void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio,
|
||||
struct mv_port_priv *pp)
|
||||
{
|
||||
if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) {
|
||||
struct mv_host_priv *hpriv = ap->host->private_data;
|
||||
int hard_port = mv_hardport_from_port(ap->port_no);
|
||||
void __iomem *hc_mmio = mv_hc_base_from_port(
|
||||
ap->host->iomap[MV_PRIMARY_BAR], hard_port);
|
||||
u32 hc_irq_cause, ipending;
|
||||
|
||||
/* clear EDMA event indicators, if any */
|
||||
writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
|
||||
|
||||
/* clear EDMA interrupt indicator, if any */
|
||||
hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
|
||||
ipending = (DEV_IRQ << hard_port) |
|
||||
(CRPB_DMA_DONE << hard_port);
|
||||
if (hc_irq_cause & ipending) {
|
||||
writelfl(hc_irq_cause & ~ipending,
|
||||
hc_mmio + HC_IRQ_CAUSE_OFS);
|
||||
}
|
||||
|
||||
mv_edma_cfg(ap, hpriv, port_mmio);
|
||||
|
||||
/* clear FIS IRQ Cause */
|
||||
writelfl(0, port_mmio + SATA_FIS_IRQ_CAUSE_OFS);
|
||||
|
||||
mv_set_edma_ptrs(port_mmio, hpriv, pp);
|
||||
|
||||
writelfl(EDMA_EN, port_mmio + EDMA_CMD_OFS);
|
||||
|
@ -1025,30 +1048,22 @@ static int mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
|
|||
static void mv_edma_cfg(struct ata_port *ap, struct mv_host_priv *hpriv,
|
||||
void __iomem *port_mmio)
|
||||
{
|
||||
u32 cfg = readl(port_mmio + EDMA_CFG_OFS);
|
||||
u32 cfg;
|
||||
|
||||
/* set up non-NCQ EDMA configuration */
|
||||
cfg &= ~(1 << 9); /* disable eQue */
|
||||
cfg = EDMA_CFG_Q_DEPTH; /* always 0x1f for *all* chips */
|
||||
|
||||
if (IS_GEN_I(hpriv)) {
|
||||
cfg &= ~0x1f; /* clear queue depth */
|
||||
if (IS_GEN_I(hpriv))
|
||||
cfg |= (1 << 8); /* enab config burst size mask */
|
||||
}
|
||||
|
||||
else if (IS_GEN_II(hpriv)) {
|
||||
cfg &= ~0x1f; /* clear queue depth */
|
||||
else if (IS_GEN_II(hpriv))
|
||||
cfg |= EDMA_CFG_RD_BRST_EXT | EDMA_CFG_WR_BUFF_LEN;
|
||||
cfg &= ~(EDMA_CFG_NCQ | EDMA_CFG_NCQ_GO_ON_ERR); /* clear 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 */
|
||||
cfg &= ~(1 << 19); /* dis 128-entry queue (for now?) */
|
||||
cfg |= (1 << 18); /* enab early completion */
|
||||
cfg |= (1 << 17); /* enab cut-through (dis stor&forwrd) */
|
||||
cfg &= ~(1 << 16); /* dis FIS-based switching (for now) */
|
||||
cfg &= ~(EDMA_CFG_NCQ); /* clear NCQ */
|
||||
}
|
||||
|
||||
writelfl(cfg, port_mmio + EDMA_CFG_OFS);
|
||||
|
@ -1370,7 +1385,6 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
|
|||
struct ata_port *ap = qc->ap;
|
||||
void __iomem *port_mmio = mv_ap_base(ap);
|
||||
struct mv_port_priv *pp = ap->private_data;
|
||||
struct mv_host_priv *hpriv = ap->host->private_data;
|
||||
u32 in_index;
|
||||
|
||||
if (qc->tf.protocol != ATA_PROT_DMA) {
|
||||
|
@ -1382,7 +1396,7 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
|
|||
return ata_qc_issue_prot(qc);
|
||||
}
|
||||
|
||||
mv_start_dma(port_mmio, hpriv, pp);
|
||||
mv_start_dma(ap, port_mmio, pp);
|
||||
|
||||
in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
|
||||
|
||||
|
|
Loading…
Reference in a new issue