mirror of https://gitee.com/openkylin/linux.git
[libata] sata_fsl: Fix broken driver, add port multiplier (PMP) support
The following commit (4c9bf4e799
):
libata: replace tf_read with qc_fill_rtf for non-SFF drivers
Broke the sata_fsl.c driver in 2.6.26-rc. I know the following patch fixes
the issue, it clearly also adds port multipler support. The current
2.6.26-rc driver is broken.
On boot with debug enabled we get something like (w/o this patch):
spurious interrupt!!, CC = 0x1
interrupt status 0x1
xx_scr_read, reg_in = 1
spurious interrupt!!, CC = 0x1
interrupt status 0x1
xx_scr_read, reg_in = 1
spurious interrupt!!, CC = 0x1
interrupt status 0x1
xx_scr_read, reg_in = 1
.. continues for ever.
This change fixes this as a side effect of adding port multiplier support.
Signed-off-by: Ashish Kalra <ashish.kalra@freescale.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
This commit is contained in:
parent
19ef9d5e45
commit
034d8e8f27
|
@ -34,7 +34,7 @@ enum {
|
||||||
|
|
||||||
SATA_FSL_HOST_FLAGS = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
|
SATA_FSL_HOST_FLAGS = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
|
||||||
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
|
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
|
||||||
ATA_FLAG_NCQ),
|
ATA_FLAG_PMP | ATA_FLAG_NCQ),
|
||||||
|
|
||||||
SATA_FSL_MAX_CMDS = SATA_FSL_QUEUE_DEPTH,
|
SATA_FSL_MAX_CMDS = SATA_FSL_QUEUE_DEPTH,
|
||||||
SATA_FSL_CMD_HDR_SIZE = 16, /* 4 DWORDS */
|
SATA_FSL_CMD_HDR_SIZE = 16, /* 4 DWORDS */
|
||||||
|
@ -395,7 +395,7 @@ static void sata_fsl_qc_prep(struct ata_queued_cmd *qc)
|
||||||
cd = (struct command_desc *)pp->cmdentry + tag;
|
cd = (struct command_desc *)pp->cmdentry + tag;
|
||||||
cd_paddr = pp->cmdentry_paddr + tag * SATA_FSL_CMD_DESC_SIZE;
|
cd_paddr = pp->cmdentry_paddr + tag * SATA_FSL_CMD_DESC_SIZE;
|
||||||
|
|
||||||
ata_tf_to_fis(&qc->tf, 0, 1, (u8 *) &cd->cfis);
|
ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, (u8 *) &cd->cfis);
|
||||||
|
|
||||||
VPRINTK("Dumping cfis : 0x%x, 0x%x, 0x%x\n",
|
VPRINTK("Dumping cfis : 0x%x, 0x%x, 0x%x\n",
|
||||||
cd->cfis[0], cd->cfis[1], cd->cfis[2]);
|
cd->cfis[0], cd->cfis[1], cd->cfis[2]);
|
||||||
|
@ -438,6 +438,8 @@ static unsigned int sata_fsl_qc_issue(struct ata_queued_cmd *qc)
|
||||||
ioread32(CA + hcr_base),
|
ioread32(CA + hcr_base),
|
||||||
ioread32(CE + hcr_base), ioread32(CC + hcr_base));
|
ioread32(CE + hcr_base), ioread32(CC + hcr_base));
|
||||||
|
|
||||||
|
iowrite32(qc->dev->link->pmp, CQPMP + hcr_base);
|
||||||
|
|
||||||
/* Simply queue command to the controller/device */
|
/* Simply queue command to the controller/device */
|
||||||
iowrite32(1 << tag, CQ + hcr_base);
|
iowrite32(1 << tag, CQ + hcr_base);
|
||||||
|
|
||||||
|
@ -558,11 +560,36 @@ static void sata_fsl_thaw(struct ata_port *ap)
|
||||||
ioread32(hcr_base + HCONTROL), ioread32(hcr_base + HSTATUS));
|
ioread32(hcr_base + HCONTROL), ioread32(hcr_base + HSTATUS));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void sata_fsl_pmp_attach(struct ata_port *ap)
|
||||||
|
{
|
||||||
|
struct sata_fsl_host_priv *host_priv = ap->host->private_data;
|
||||||
|
void __iomem *hcr_base = host_priv->hcr_base;
|
||||||
|
u32 temp;
|
||||||
|
|
||||||
|
temp = ioread32(hcr_base + HCONTROL);
|
||||||
|
iowrite32((temp | HCONTROL_PMP_ATTACHED), hcr_base + HCONTROL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sata_fsl_pmp_detach(struct ata_port *ap)
|
||||||
|
{
|
||||||
|
struct sata_fsl_host_priv *host_priv = ap->host->private_data;
|
||||||
|
void __iomem *hcr_base = host_priv->hcr_base;
|
||||||
|
u32 temp;
|
||||||
|
|
||||||
|
temp = ioread32(hcr_base + HCONTROL);
|
||||||
|
temp &= ~HCONTROL_PMP_ATTACHED;
|
||||||
|
iowrite32(temp, hcr_base + HCONTROL);
|
||||||
|
|
||||||
|
/* enable interrupts on the controller/port */
|
||||||
|
temp = ioread32(hcr_base + HCONTROL);
|
||||||
|
iowrite32((temp | DEFAULT_PORT_IRQ_ENABLE_MASK), hcr_base + HCONTROL);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static int sata_fsl_port_start(struct ata_port *ap)
|
static int sata_fsl_port_start(struct ata_port *ap)
|
||||||
{
|
{
|
||||||
struct device *dev = ap->host->dev;
|
struct device *dev = ap->host->dev;
|
||||||
struct sata_fsl_port_priv *pp;
|
struct sata_fsl_port_priv *pp;
|
||||||
int retval;
|
|
||||||
void *mem;
|
void *mem;
|
||||||
dma_addr_t mem_dma;
|
dma_addr_t mem_dma;
|
||||||
struct sata_fsl_host_priv *host_priv = ap->host->private_data;
|
struct sata_fsl_host_priv *host_priv = ap->host->private_data;
|
||||||
|
@ -688,12 +715,13 @@ static int sata_fsl_prereset(struct ata_link *link, unsigned long deadline)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sata_fsl_softreset(struct ata_link *link, unsigned int *class,
|
static int sata_fsl_softreset(struct ata_link *link, unsigned int *class,
|
||||||
unsigned long deadline)
|
unsigned long deadline)
|
||||||
{
|
{
|
||||||
struct ata_port *ap = link->ap;
|
struct ata_port *ap = link->ap;
|
||||||
struct sata_fsl_port_priv *pp = ap->private_data;
|
struct sata_fsl_port_priv *pp = ap->private_data;
|
||||||
struct sata_fsl_host_priv *host_priv = ap->host->private_data;
|
struct sata_fsl_host_priv *host_priv = ap->host->private_data;
|
||||||
void __iomem *hcr_base = host_priv->hcr_base;
|
void __iomem *hcr_base = host_priv->hcr_base;
|
||||||
|
int pmp = sata_srst_pmp(link);
|
||||||
u32 temp;
|
u32 temp;
|
||||||
struct ata_taskfile tf;
|
struct ata_taskfile tf;
|
||||||
u8 *cfis;
|
u8 *cfis;
|
||||||
|
@ -703,6 +731,9 @@ static int sata_fsl_softreset(struct ata_link *link, unsigned int *class,
|
||||||
|
|
||||||
DPRINTK("in xx_softreset\n");
|
DPRINTK("in xx_softreset\n");
|
||||||
|
|
||||||
|
if (pmp != SATA_PMP_CTRL_PORT)
|
||||||
|
goto issue_srst;
|
||||||
|
|
||||||
try_offline_again:
|
try_offline_again:
|
||||||
/*
|
/*
|
||||||
* Force host controller to go off-line, aborting current operations
|
* Force host controller to go off-line, aborting current operations
|
||||||
|
@ -746,6 +777,7 @@ static int sata_fsl_softreset(struct ata_link *link, unsigned int *class,
|
||||||
|
|
||||||
temp = ioread32(hcr_base + HCONTROL);
|
temp = ioread32(hcr_base + HCONTROL);
|
||||||
temp |= (HCONTROL_ONLINE_PHY_RST | HCONTROL_SNOOP_ENABLE);
|
temp |= (HCONTROL_ONLINE_PHY_RST | HCONTROL_SNOOP_ENABLE);
|
||||||
|
temp |= HCONTROL_PMP_ATTACHED;
|
||||||
iowrite32(temp, hcr_base + HCONTROL);
|
iowrite32(temp, hcr_base + HCONTROL);
|
||||||
|
|
||||||
temp = ata_wait_register(hcr_base + HSTATUS, ONLINE, 0, 1, 500);
|
temp = ata_wait_register(hcr_base + HSTATUS, ONLINE, 0, 1, 500);
|
||||||
|
@ -771,7 +803,8 @@ static int sata_fsl_softreset(struct ata_link *link, unsigned int *class,
|
||||||
ata_port_printk(ap, KERN_WARNING,
|
ata_port_printk(ap, KERN_WARNING,
|
||||||
"No Device OR PHYRDY change,Hstatus = 0x%x\n",
|
"No Device OR PHYRDY change,Hstatus = 0x%x\n",
|
||||||
ioread32(hcr_base + HSTATUS));
|
ioread32(hcr_base + HSTATUS));
|
||||||
goto err;
|
*class = ATA_DEV_NONE;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -783,7 +816,8 @@ static int sata_fsl_softreset(struct ata_link *link, unsigned int *class,
|
||||||
|
|
||||||
if ((temp & 0xFF) != 0x18) {
|
if ((temp & 0xFF) != 0x18) {
|
||||||
ata_port_printk(ap, KERN_WARNING, "No Signature Update\n");
|
ata_port_printk(ap, KERN_WARNING, "No Signature Update\n");
|
||||||
goto err;
|
*class = ATA_DEV_NONE;
|
||||||
|
goto out;
|
||||||
} else {
|
} else {
|
||||||
ata_port_printk(ap, KERN_INFO,
|
ata_port_printk(ap, KERN_INFO,
|
||||||
"Signature Update detected @ %d msecs\n",
|
"Signature Update detected @ %d msecs\n",
|
||||||
|
@ -798,6 +832,7 @@ static int sata_fsl_softreset(struct ata_link *link, unsigned int *class,
|
||||||
* reached here, we can send a command to the target device
|
* reached here, we can send a command to the target device
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
issue_srst:
|
||||||
DPRINTK("Sending SRST/device reset\n");
|
DPRINTK("Sending SRST/device reset\n");
|
||||||
|
|
||||||
ata_tf_init(link->device, &tf);
|
ata_tf_init(link->device, &tf);
|
||||||
|
@ -808,7 +843,7 @@ static int sata_fsl_softreset(struct ata_link *link, unsigned int *class,
|
||||||
SRST_CMD | CMD_DESC_SNOOP_ENABLE, 0, 0, 5);
|
SRST_CMD | CMD_DESC_SNOOP_ENABLE, 0, 0, 5);
|
||||||
|
|
||||||
tf.ctl |= ATA_SRST; /* setup SRST bit in taskfile control reg */
|
tf.ctl |= ATA_SRST; /* setup SRST bit in taskfile control reg */
|
||||||
ata_tf_to_fis(&tf, 0, 0, cfis);
|
ata_tf_to_fis(&tf, pmp, 0, cfis);
|
||||||
|
|
||||||
DPRINTK("Dumping cfis : 0x%x, 0x%x, 0x%x, 0x%x\n",
|
DPRINTK("Dumping cfis : 0x%x, 0x%x, 0x%x, 0x%x\n",
|
||||||
cfis[0], cfis[1], cfis[2], cfis[3]);
|
cfis[0], cfis[1], cfis[2], cfis[3]);
|
||||||
|
@ -854,8 +889,10 @@ static int sata_fsl_softreset(struct ata_link *link, unsigned int *class,
|
||||||
sata_fsl_setup_cmd_hdr_entry(pp, 0, CMD_DESC_SNOOP_ENABLE, 0, 0, 5);
|
sata_fsl_setup_cmd_hdr_entry(pp, 0, CMD_DESC_SNOOP_ENABLE, 0, 0, 5);
|
||||||
|
|
||||||
tf.ctl &= ~ATA_SRST; /* 2nd H2D Ctl. register FIS */
|
tf.ctl &= ~ATA_SRST; /* 2nd H2D Ctl. register FIS */
|
||||||
ata_tf_to_fis(&tf, 0, 0, cfis);
|
ata_tf_to_fis(&tf, pmp, 0, cfis);
|
||||||
|
|
||||||
|
if (pmp != SATA_PMP_CTRL_PORT)
|
||||||
|
iowrite32(pmp, CQPMP + hcr_base);
|
||||||
iowrite32(1, CQ + hcr_base);
|
iowrite32(1, CQ + hcr_base);
|
||||||
msleep(150); /* ?? */
|
msleep(150); /* ?? */
|
||||||
|
|
||||||
|
@ -886,12 +923,21 @@ static int sata_fsl_softreset(struct ata_link *link, unsigned int *class,
|
||||||
VPRINTK("cereg = 0x%x\n", ioread32(hcr_base + CE));
|
VPRINTK("cereg = 0x%x\n", ioread32(hcr_base + CE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void sata_fsl_error_handler(struct ata_port *ap)
|
||||||
|
{
|
||||||
|
|
||||||
|
DPRINTK("in xx_error_handler\n");
|
||||||
|
sata_pmp_error_handler(ap);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static void sata_fsl_post_internal_cmd(struct ata_queued_cmd *qc)
|
static void sata_fsl_post_internal_cmd(struct ata_queued_cmd *qc)
|
||||||
{
|
{
|
||||||
if (qc->flags & ATA_QCFLAG_FAILED)
|
if (qc->flags & ATA_QCFLAG_FAILED)
|
||||||
|
@ -905,18 +951,21 @@ static void sata_fsl_post_internal_cmd(struct ata_queued_cmd *qc)
|
||||||
|
|
||||||
static void sata_fsl_error_intr(struct ata_port *ap)
|
static void sata_fsl_error_intr(struct ata_port *ap)
|
||||||
{
|
{
|
||||||
struct ata_link *link = &ap->link;
|
|
||||||
struct ata_eh_info *ehi = &link->eh_info;
|
|
||||||
struct sata_fsl_host_priv *host_priv = ap->host->private_data;
|
struct sata_fsl_host_priv *host_priv = ap->host->private_data;
|
||||||
void __iomem *hcr_base = host_priv->hcr_base;
|
void __iomem *hcr_base = host_priv->hcr_base;
|
||||||
u32 hstatus, dereg, cereg = 0, SError = 0;
|
u32 hstatus, dereg=0, cereg = 0, SError = 0;
|
||||||
unsigned int err_mask = 0, action = 0;
|
unsigned int err_mask = 0, action = 0;
|
||||||
struct ata_queued_cmd *qc;
|
int freeze = 0, abort=0;
|
||||||
int freeze = 0;
|
struct ata_link *link = NULL;
|
||||||
|
struct ata_queued_cmd *qc = NULL;
|
||||||
|
struct ata_eh_info *ehi;
|
||||||
|
|
||||||
hstatus = ioread32(hcr_base + HSTATUS);
|
hstatus = ioread32(hcr_base + HSTATUS);
|
||||||
cereg = ioread32(hcr_base + CE);
|
cereg = ioread32(hcr_base + CE);
|
||||||
|
|
||||||
|
/* first, analyze and record host port events */
|
||||||
|
link = &ap->link;
|
||||||
|
ehi = &link->eh_info;
|
||||||
ata_ehi_clear_desc(ehi);
|
ata_ehi_clear_desc(ehi);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -926,12 +975,41 @@ static void sata_fsl_error_intr(struct ata_port *ap)
|
||||||
sata_fsl_scr_read(ap, SCR_ERROR, &SError);
|
sata_fsl_scr_read(ap, SCR_ERROR, &SError);
|
||||||
if (unlikely(SError & 0xFFFF0000)) {
|
if (unlikely(SError & 0xFFFF0000)) {
|
||||||
sata_fsl_scr_write(ap, SCR_ERROR, SError);
|
sata_fsl_scr_write(ap, SCR_ERROR, SError);
|
||||||
err_mask |= AC_ERR_ATA_BUS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINTK("error_intr,hStat=0x%x,CE=0x%x,DE =0x%x,SErr=0x%x\n",
|
DPRINTK("error_intr,hStat=0x%x,CE=0x%x,DE =0x%x,SErr=0x%x\n",
|
||||||
hstatus, cereg, ioread32(hcr_base + DE), SError);
|
hstatus, cereg, ioread32(hcr_base + DE), SError);
|
||||||
|
|
||||||
|
/* handle fatal errors */
|
||||||
|
if (hstatus & FATAL_ERROR_DECODE) {
|
||||||
|
ehi->err_mask |= AC_ERR_ATA_BUS;
|
||||||
|
ehi->action |= ATA_EH_SOFTRESET;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ignore serror in case of fatal errors as we always want
|
||||||
|
* to do a soft-reset of the FSL SATA controller. Analyzing
|
||||||
|
* serror may cause libata to schedule a hard-reset action,
|
||||||
|
* and hard-reset currently does not do controller
|
||||||
|
* offline/online, causing command timeouts and leads to an
|
||||||
|
* un-recoverable state, hence make libATA ignore
|
||||||
|
* autopsy in case of fatal errors.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ehi->flags |= ATA_EHI_NO_AUTOPSY;
|
||||||
|
|
||||||
|
freeze = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle PHYRDY change notification */
|
||||||
|
if (hstatus & INT_ON_PHYRDY_CHG) {
|
||||||
|
DPRINTK("SATA FSL: PHYRDY change indication\n");
|
||||||
|
|
||||||
|
/* Setup a soft-reset EH action */
|
||||||
|
ata_ehi_hotplugged(ehi);
|
||||||
|
ata_ehi_push_desc(ehi, "%s", "PHY RDY changed");
|
||||||
|
freeze = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* handle single device errors */
|
/* handle single device errors */
|
||||||
if (cereg) {
|
if (cereg) {
|
||||||
/*
|
/*
|
||||||
|
@ -943,58 +1021,68 @@ static void sata_fsl_error_intr(struct ata_port *ap)
|
||||||
* clearing the device error, we can issue commands to the
|
* clearing the device error, we can issue commands to the
|
||||||
* device to interrogate it to find the source of the error.
|
* device to interrogate it to find the source of the error.
|
||||||
*/
|
*/
|
||||||
dereg = ioread32(hcr_base + DE);
|
abort = 1;
|
||||||
iowrite32(dereg, hcr_base + DE);
|
|
||||||
iowrite32(cereg, hcr_base + CE);
|
|
||||||
|
|
||||||
DPRINTK("single device error, CE=0x%x, DE=0x%x\n",
|
DPRINTK("single device error, CE=0x%x, DE=0x%x\n",
|
||||||
ioread32(hcr_base + CE), ioread32(hcr_base + DE));
|
ioread32(hcr_base + CE), ioread32(hcr_base + DE));
|
||||||
/*
|
|
||||||
* We should consider this as non fatal error, and TF must
|
|
||||||
* be updated as done below.
|
|
||||||
*/
|
|
||||||
|
|
||||||
err_mask |= AC_ERR_DEV;
|
/* find out the offending link and qc */
|
||||||
}
|
if (ap->nr_pmp_links) {
|
||||||
|
dereg = ioread32(hcr_base + DE);
|
||||||
|
iowrite32(dereg, hcr_base + DE);
|
||||||
|
iowrite32(cereg, hcr_base + CE);
|
||||||
|
|
||||||
/* handle fatal errors */
|
if (dereg < ap->nr_pmp_links) {
|
||||||
if (hstatus & FATAL_ERROR_DECODE) {
|
link = &ap->pmp_link[dereg];
|
||||||
err_mask |= AC_ERR_ATA_BUS;
|
ehi = &link->eh_info;
|
||||||
action |= ATA_EH_RESET;
|
qc = ata_qc_from_tag(ap, link->active_tag);
|
||||||
/* how will fatal error interrupts be completed ?? */
|
/*
|
||||||
freeze = 1;
|
* We should consider this as non fatal error,
|
||||||
}
|
* and TF must be updated as done below.
|
||||||
|
*/
|
||||||
|
|
||||||
/* Handle PHYRDY change notification */
|
err_mask |= AC_ERR_DEV;
|
||||||
if (hstatus & INT_ON_PHYRDY_CHG) {
|
|
||||||
DPRINTK("SATA FSL: PHYRDY change indication\n");
|
|
||||||
|
|
||||||
/* Setup a soft-reset EH action */
|
} else {
|
||||||
ata_ehi_hotplugged(ehi);
|
err_mask |= AC_ERR_HSM;
|
||||||
freeze = 1;
|
action |= ATA_EH_HARDRESET;
|
||||||
|
freeze = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dereg = ioread32(hcr_base + DE);
|
||||||
|
iowrite32(dereg, hcr_base + DE);
|
||||||
|
iowrite32(cereg, hcr_base + CE);
|
||||||
|
|
||||||
|
qc = ata_qc_from_tag(ap, link->active_tag);
|
||||||
|
/*
|
||||||
|
* We should consider this as non fatal error,
|
||||||
|
* and TF must be updated as done below.
|
||||||
|
*/
|
||||||
|
err_mask |= AC_ERR_DEV;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* record error info */
|
/* record error info */
|
||||||
qc = ata_qc_from_tag(ap, link->active_tag);
|
if (qc) {
|
||||||
|
|
||||||
if (qc)
|
|
||||||
qc->err_mask |= err_mask;
|
qc->err_mask |= err_mask;
|
||||||
else
|
} else
|
||||||
ehi->err_mask |= err_mask;
|
ehi->err_mask |= err_mask;
|
||||||
|
|
||||||
ehi->action |= action;
|
ehi->action |= action;
|
||||||
ehi->serror |= SError;
|
|
||||||
|
|
||||||
/* freeze or abort */
|
/* freeze or abort */
|
||||||
if (freeze)
|
if (freeze)
|
||||||
ata_port_freeze(ap);
|
ata_port_freeze(ap);
|
||||||
else
|
else if (abort) {
|
||||||
ata_port_abort(ap);
|
if (qc)
|
||||||
|
ata_link_abort(qc->dev->link);
|
||||||
|
else
|
||||||
|
ata_port_abort(ap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sata_fsl_host_intr(struct ata_port *ap)
|
static void sata_fsl_host_intr(struct ata_port *ap)
|
||||||
{
|
{
|
||||||
struct ata_link *link = &ap->link;
|
|
||||||
struct sata_fsl_host_priv *host_priv = ap->host->private_data;
|
struct sata_fsl_host_priv *host_priv = ap->host->private_data;
|
||||||
void __iomem *hcr_base = host_priv->hcr_base;
|
void __iomem *hcr_base = host_priv->hcr_base;
|
||||||
u32 hstatus, qc_active = 0;
|
u32 hstatus, qc_active = 0;
|
||||||
|
@ -1017,10 +1105,19 @@ static void sata_fsl_host_intr(struct ata_port *ap)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (link->sactive) { /* only true for NCQ commands */
|
/* Read command completed register */
|
||||||
|
qc_active = ioread32(hcr_base + CC);
|
||||||
|
|
||||||
|
VPRINTK("Status of all queues :\n");
|
||||||
|
VPRINTK("qc_active/CC = 0x%x, CA = 0x%x, CE=0x%x,CQ=0x%x,apqa=0x%x\n",
|
||||||
|
qc_active,
|
||||||
|
ioread32(hcr_base + CA),
|
||||||
|
ioread32(hcr_base + CE),
|
||||||
|
ioread32(hcr_base + CQ),
|
||||||
|
ap->qc_active);
|
||||||
|
|
||||||
|
if (qc_active & ap->qc_active) {
|
||||||
int i;
|
int i;
|
||||||
/* Read command completed register */
|
|
||||||
qc_active = ioread32(hcr_base + CC);
|
|
||||||
/* clear CC bit, this will also complete the interrupt */
|
/* clear CC bit, this will also complete the interrupt */
|
||||||
iowrite32(qc_active, hcr_base + CC);
|
iowrite32(qc_active, hcr_base + CC);
|
||||||
|
|
||||||
|
@ -1032,8 +1129,9 @@ static void sata_fsl_host_intr(struct ata_port *ap)
|
||||||
for (i = 0; i < SATA_FSL_QUEUE_DEPTH; i++) {
|
for (i = 0; i < SATA_FSL_QUEUE_DEPTH; i++) {
|
||||||
if (qc_active & (1 << i)) {
|
if (qc_active & (1 << i)) {
|
||||||
qc = ata_qc_from_tag(ap, i);
|
qc = ata_qc_from_tag(ap, i);
|
||||||
if (qc)
|
if (qc) {
|
||||||
ata_qc_complete(qc);
|
ata_qc_complete(qc);
|
||||||
|
}
|
||||||
DPRINTK
|
DPRINTK
|
||||||
("completing ncq cmd,tag=%d,CC=0x%x,CA=0x%x\n",
|
("completing ncq cmd,tag=%d,CC=0x%x,CA=0x%x\n",
|
||||||
i, ioread32(hcr_base + CC),
|
i, ioread32(hcr_base + CC),
|
||||||
|
@ -1042,19 +1140,21 @@ static void sata_fsl_host_intr(struct ata_port *ap)
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
} else if (ap->qc_active) {
|
} else if ((ap->qc_active & (1 << ATA_TAG_INTERNAL))) {
|
||||||
iowrite32(1, hcr_base + CC);
|
iowrite32(1, hcr_base + CC);
|
||||||
qc = ata_qc_from_tag(ap, link->active_tag);
|
qc = ata_qc_from_tag(ap, ATA_TAG_INTERNAL);
|
||||||
|
|
||||||
DPRINTK("completing non-ncq cmd, tag=%d,CC=0x%x\n",
|
DPRINTK("completing non-ncq cmd, CC=0x%x\n",
|
||||||
link->active_tag, ioread32(hcr_base + CC));
|
ioread32(hcr_base + CC));
|
||||||
|
|
||||||
if (qc)
|
if (qc) {
|
||||||
ata_qc_complete(qc);
|
ata_qc_complete(qc);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Spurious Interrupt!! */
|
/* Spurious Interrupt!! */
|
||||||
DPRINTK("spurious interrupt!!, CC = 0x%x\n",
|
DPRINTK("spurious interrupt!!, CC = 0x%x\n",
|
||||||
ioread32(hcr_base + CC));
|
ioread32(hcr_base + CC));
|
||||||
|
iowrite32(qc_active, hcr_base + CC);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1130,9 +1230,6 @@ static int sata_fsl_init_controller(struct ata_host *host)
|
||||||
iowrite32(0x00000FFFF, hcr_base + CE);
|
iowrite32(0x00000FFFF, hcr_base + CE);
|
||||||
iowrite32(0x00000FFFF, hcr_base + DE);
|
iowrite32(0x00000FFFF, hcr_base + DE);
|
||||||
|
|
||||||
/* initially assuming no Port multiplier, set CQPMP to 0 */
|
|
||||||
iowrite32(0x0, hcr_base + CQPMP);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* host controller will be brought on-line, during xx_port_start()
|
* host controller will be brought on-line, during xx_port_start()
|
||||||
* callback, that should also initiate the OOB, COMINIT sequence
|
* callback, that should also initiate the OOB, COMINIT sequence
|
||||||
|
@ -1154,8 +1251,8 @@ static struct scsi_host_template sata_fsl_sht = {
|
||||||
.dma_boundary = ATA_DMA_BOUNDARY,
|
.dma_boundary = ATA_DMA_BOUNDARY,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct ata_port_operations sata_fsl_ops = {
|
static struct ata_port_operations sata_fsl_ops = {
|
||||||
.inherits = &sata_port_ops,
|
.inherits = &sata_pmp_port_ops,
|
||||||
|
|
||||||
.qc_prep = sata_fsl_qc_prep,
|
.qc_prep = sata_fsl_qc_prep,
|
||||||
.qc_issue = sata_fsl_qc_issue,
|
.qc_issue = sata_fsl_qc_issue,
|
||||||
|
@ -1168,10 +1265,15 @@ static const struct ata_port_operations sata_fsl_ops = {
|
||||||
.thaw = sata_fsl_thaw,
|
.thaw = sata_fsl_thaw,
|
||||||
.prereset = sata_fsl_prereset,
|
.prereset = sata_fsl_prereset,
|
||||||
.softreset = sata_fsl_softreset,
|
.softreset = sata_fsl_softreset,
|
||||||
|
.pmp_softreset = sata_fsl_softreset,
|
||||||
|
.error_handler = sata_fsl_error_handler,
|
||||||
.post_internal_cmd = sata_fsl_post_internal_cmd,
|
.post_internal_cmd = sata_fsl_post_internal_cmd,
|
||||||
|
|
||||||
.port_start = sata_fsl_port_start,
|
.port_start = sata_fsl_port_start,
|
||||||
.port_stop = sata_fsl_port_stop,
|
.port_stop = sata_fsl_port_stop,
|
||||||
|
|
||||||
|
.pmp_attach = sata_fsl_pmp_attach,
|
||||||
|
.pmp_detach = sata_fsl_pmp_detach,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct ata_port_info sata_fsl_port_info[] = {
|
static const struct ata_port_info sata_fsl_port_info[] = {
|
||||||
|
|
Loading…
Reference in New Issue