Commit 049e8e04 authored by Tejun Heo's avatar Tejun Heo Committed by Jeff Garzik

sata_inic162x: use IDMA for non DMA ATA commands

Use IDMA for PIO and non-data commands.  This allows sata_inic162x to
safely drive LBA48 devices.  Kill inic_dev_config() which contains
code to reject LBA48 devices.

With this change, status checking in inic_qc_issue() to avoid hard
lock up after hotplug can go away too.
Signed-off-by: default avatarTejun Heo <htejun@gmail.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent ab5b0235
...@@ -356,12 +356,12 @@ static void inic_host_intr(struct ata_port *ap) ...@@ -356,12 +356,12 @@ static void inic_host_intr(struct ata_port *ap)
if (unlikely((irq_stat & PIRQ_ERR) || (idma_stat & IDMA_STAT_ERR))) if (unlikely((irq_stat & PIRQ_ERR) || (idma_stat & IDMA_STAT_ERR)))
inic_host_err_intr(ap, irq_stat, idma_stat); inic_host_err_intr(ap, irq_stat, idma_stat);
if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) { if (unlikely(!qc)) {
ap->ops->sff_check_status(ap); /* clear ATA interrupt */ ap->ops->sff_check_status(ap); /* clear ATA interrupt */
goto spurious; goto spurious;
} }
if (qc->tf.protocol == ATA_PROT_DMA) { if (!ata_is_atapi(qc->tf.protocol)) {
if (likely(idma_stat & IDMA_STAT_DONE)) { if (likely(idma_stat & IDMA_STAT_DONE)) {
inic_stop_idma(ap); inic_stop_idma(ap);
...@@ -425,11 +425,14 @@ static void inic_fill_sg(struct inic_prd *prd, struct ata_queued_cmd *qc) ...@@ -425,11 +425,14 @@ static void inic_fill_sg(struct inic_prd *prd, struct ata_queued_cmd *qc)
{ {
struct scatterlist *sg; struct scatterlist *sg;
unsigned int si; unsigned int si;
u8 flags = PRD_DMA; u8 flags = 0;
if (qc->tf.flags & ATA_TFLAG_WRITE) if (qc->tf.flags & ATA_TFLAG_WRITE)
flags |= PRD_WRITE; flags |= PRD_WRITE;
if (ata_is_dma(qc->tf.protocol))
flags |= PRD_DMA;
for_each_sg(qc->sg, sg, qc->n_elem, si) { for_each_sg(qc->sg, sg, qc->n_elem, si) {
prd->mad = cpu_to_le32(sg_dma_address(sg)); prd->mad = cpu_to_le32(sg_dma_address(sg));
prd->len = cpu_to_le16(sg_dma_len(sg)); prd->len = cpu_to_le16(sg_dma_len(sg));
...@@ -447,16 +450,20 @@ static void inic_qc_prep(struct ata_queued_cmd *qc) ...@@ -447,16 +450,20 @@ static void inic_qc_prep(struct ata_queued_cmd *qc)
struct inic_pkt *pkt = pp->pkt; struct inic_pkt *pkt = pp->pkt;
struct inic_cpb *cpb = &pkt->cpb; struct inic_cpb *cpb = &pkt->cpb;
struct inic_prd *prd = pkt->prd; struct inic_prd *prd = pkt->prd;
bool is_atapi = ata_is_atapi(qc->tf.protocol);
bool is_data = ata_is_data(qc->tf.protocol);
VPRINTK("ENTER\n"); VPRINTK("ENTER\n");
if (qc->tf.protocol != ATA_PROT_DMA) if (is_atapi)
return; return;
/* prepare packet, based on initio driver */ /* prepare packet, based on initio driver */
memset(pkt, 0, sizeof(struct inic_pkt)); memset(pkt, 0, sizeof(struct inic_pkt));
cpb->ctl_flags = CPB_CTL_VALID | CPB_CTL_IEN | CPB_CTL_DATA; cpb->ctl_flags = CPB_CTL_VALID | CPB_CTL_IEN;
if (is_data)
cpb->ctl_flags |= CPB_CTL_DATA;
cpb->len = cpu_to_le32(qc->nbytes); cpb->len = cpu_to_le32(qc->nbytes);
cpb->prd = cpu_to_le32(pp->pkt_dma + offsetof(struct inic_pkt, prd)); cpb->prd = cpu_to_le32(pp->pkt_dma + offsetof(struct inic_pkt, prd));
...@@ -480,6 +487,7 @@ static void inic_qc_prep(struct ata_queued_cmd *qc) ...@@ -480,6 +487,7 @@ static void inic_qc_prep(struct ata_queued_cmd *qc)
/* don't load ctl - dunno why. it's like that in the initio driver */ /* don't load ctl - dunno why. it's like that in the initio driver */
/* setup sg table */ /* setup sg table */
if (is_data)
inic_fill_sg(prd, qc); inic_fill_sg(prd, qc);
pp->cpb_tbl[0] = pp->pkt_dma; pp->cpb_tbl[0] = pp->pkt_dma;
...@@ -490,7 +498,7 @@ static unsigned int inic_qc_issue(struct ata_queued_cmd *qc) ...@@ -490,7 +498,7 @@ static unsigned int inic_qc_issue(struct ata_queued_cmd *qc)
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
void __iomem *port_base = inic_port_base(ap); void __iomem *port_base = inic_port_base(ap);
if (qc->tf.protocol == ATA_PROT_DMA) { if (!ata_is_atapi(qc->tf.protocol)) {
/* fire up the ADMA engine */ /* fire up the ADMA engine */
writew(HCTL_FTHD0, port_base + HOST_CTL); writew(HCTL_FTHD0, port_base + HOST_CTL);
writew(IDMA_CTL_GO, port_base + PORT_IDMA_CTL); writew(IDMA_CTL_GO, port_base + PORT_IDMA_CTL);
...@@ -499,18 +507,6 @@ static unsigned int inic_qc_issue(struct ata_queued_cmd *qc) ...@@ -499,18 +507,6 @@ static unsigned int inic_qc_issue(struct ata_queued_cmd *qc)
return 0; return 0;
} }
/* Issuing a command to yet uninitialized port locks up the
* controller. Most of the time, this happens for the first
* command after reset which are ATA and ATAPI IDENTIFYs.
* Fast fail if stat is 0x7f or 0xff for those commands.
*/
if (unlikely(qc->tf.command == ATA_CMD_ID_ATA ||
qc->tf.command == ATA_CMD_ID_ATAPI)) {
u8 stat = ap->ops->sff_check_status(ap);
if (stat == 0x7f || stat == 0xff)
return AC_ERR_HSM;
}
return ata_sff_qc_issue(qc); return ata_sff_qc_issue(qc);
} }
...@@ -647,20 +643,6 @@ static void inic_post_internal_cmd(struct ata_queued_cmd *qc) ...@@ -647,20 +643,6 @@ static void inic_post_internal_cmd(struct ata_queued_cmd *qc)
inic_reset_port(inic_port_base(qc->ap)); inic_reset_port(inic_port_base(qc->ap));
} }
static void inic_dev_config(struct ata_device *dev)
{
/* inic can only handle upto LBA28 max sectors */
if (dev->max_sectors > ATA_MAX_SECTORS)
dev->max_sectors = ATA_MAX_SECTORS;
if (dev->n_sectors >= 1 << 28) {
ata_dev_printk(dev, KERN_ERR,
"ERROR: This driver doesn't support LBA48 yet and may cause\n"
" data corruption on such devices. Disabling.\n");
ata_dev_disable(dev);
}
}
static void init_port(struct ata_port *ap) static void init_port(struct ata_port *ap)
{ {
void __iomem *port_base = inic_port_base(ap); void __iomem *port_base = inic_port_base(ap);
...@@ -726,7 +708,6 @@ static struct ata_port_operations inic_port_ops = { ...@@ -726,7 +708,6 @@ static struct ata_port_operations inic_port_ops = {
.hardreset = inic_hardreset, .hardreset = inic_hardreset,
.error_handler = inic_error_handler, .error_handler = inic_error_handler,
.post_internal_cmd = inic_post_internal_cmd, .post_internal_cmd = inic_post_internal_cmd,
.dev_config = inic_dev_config,
.scr_read = inic_scr_read, .scr_read = inic_scr_read,
.scr_write = inic_scr_write, .scr_write = inic_scr_write,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment