#include <asm/io.h>
#define DRV_NAME "sata_mv"
-#define DRV_VERSION "0.6"
+#define DRV_VERSION "0.7"
enum {
/* BAR's are enumerated in terms of pci_resource_start() terms */
MV_FLAG_IRQ_COALESCE = (1 << 29), /* IRQ coalescing capability */
MV_COMMON_FLAGS = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
- ATA_FLAG_NO_ATAPI),
+ ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING),
MV_6XXX_FLAGS = MV_FLAG_IRQ_COALESCE,
CRQB_FLAG_READ = (1 << 0),
/* Command ReQuest Block: 32B */
struct mv_crqb {
- u32 sg_addr;
- u32 sg_addr_hi;
- u16 ctrl_flags;
- u16 ata_cmd[11];
+ __le32 sg_addr;
+ __le32 sg_addr_hi;
+ __le16 ctrl_flags;
+ __le16 ata_cmd[11];
};
struct mv_crqb_iie {
- u32 addr;
- u32 addr_hi;
- u32 flags;
- u32 len;
- u32 ata_cmd[4];
+ __le32 addr;
+ __le32 addr_hi;
+ __le32 flags;
+ __le32 len;
+ __le32 ata_cmd[4];
};
/* Command ResPonse Block: 8B */
struct mv_crpb {
- u16 id;
- u16 flags;
- u32 tmstmp;
+ __le16 id;
+ __le16 flags;
+ __le32 tmstmp;
};
/* EDMA Physical Region Descriptor (ePRD); A.K.A. SG */
struct mv_sg {
- u32 addr;
- u32 flags_size;
- u32 addr_hi;
- u32 reserved;
+ __le32 addr;
+ __le32 flags_size;
+ __le32 addr_hi;
+ __le32 reserved;
};
struct mv_port_priv {
dma_addr_t crpb_dma;
struct mv_sg *sg_tbl;
dma_addr_t sg_tbl_dma;
-
- unsigned req_producer; /* cp of req_in_ptr */
- unsigned rsp_consumer; /* cp of rsp_out_ptr */
u32 pp_flags;
};
.proc_name = DRV_NAME,
.dma_boundary = MV_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
.qc_prep = mv_qc_prep,
.qc_issue = mv_qc_issue,
+ .data_xfer = ata_mmio_data_xfer,
.eng_timeout = mv_eng_timeout,
.qc_prep = mv_qc_prep,
.qc_issue = mv_qc_issue,
+ .data_xfer = ata_mmio_data_xfer,
.eng_timeout = mv_eng_timeout,
}
if (EDMA_EN & reg) {
- printk(KERN_ERR "ata%u: Unable to stop eDMA\n", ap->id);
+ ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n");
/* FIXME: Consider doing a reset here to recover */
}
}
writelfl(pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK,
port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
- pp->req_producer = pp->rsp_consumer = 0;
-
/* Don't turn on EDMA here...do it before DMA commands only. Else
* we'll be unable to send non-data, PIO, etc due to restricted access
* to shadow regs.
}
}
-static inline unsigned mv_inc_q_index(unsigned *index)
+static inline unsigned mv_inc_q_index(unsigned index)
{
- *index = (*index + 1) & MV_MAX_Q_DEPTH_MASK;
- return *index;
+ return (index + 1) & MV_MAX_Q_DEPTH_MASK;
}
-static inline void mv_crqb_pack_cmd(u16 *cmdw, u8 data, u8 addr, unsigned last)
+static inline void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last)
{
- *cmdw = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
+ u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
(last ? CRQB_CMD_LAST : 0);
+ *cmdw = cpu_to_le16(tmp);
}
/**
{
struct ata_port *ap = qc->ap;
struct mv_port_priv *pp = ap->private_data;
- u16 *cw;
+ __le16 *cw;
struct ata_taskfile *tf;
u16 flags = 0;
+ unsigned in_index;
if (ATA_PROT_DMA != qc->tf.protocol)
return;
- /* the req producer index should be the same as we remember it */
- WARN_ON(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >>
- EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
- pp->req_producer);
-
/* Fill in command request block
*/
if (!(qc->tf.flags & ATA_TFLAG_WRITE))
WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
flags |= qc->tag << CRQB_TAG_SHIFT;
- pp->crqb[pp->req_producer].sg_addr =
+ /* get current queue index from hardware */
+ in_index = (readl(mv_ap_base(ap) + EDMA_REQ_Q_IN_PTR_OFS)
+ >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
+
+ pp->crqb[in_index].sg_addr =
cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
- pp->crqb[pp->req_producer].sg_addr_hi =
+ pp->crqb[in_index].sg_addr_hi =
cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
- pp->crqb[pp->req_producer].ctrl_flags = cpu_to_le16(flags);
+ pp->crqb[in_index].ctrl_flags = cpu_to_le16(flags);
- cw = &pp->crqb[pp->req_producer].ata_cmd[0];
+ cw = &pp->crqb[in_index].ata_cmd[0];
tf = &qc->tf;
/* Sadly, the CRQB cannot accomodate all registers--there are
struct mv_port_priv *pp = ap->private_data;
struct mv_crqb_iie *crqb;
struct ata_taskfile *tf;
+ unsigned in_index;
u32 flags = 0;
if (ATA_PROT_DMA != qc->tf.protocol)
return;
- /* the req producer index should be the same as we remember it */
- WARN_ON(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >>
- EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
- pp->req_producer);
-
/* Fill in Gen IIE command request block
*/
if (!(qc->tf.flags & ATA_TFLAG_WRITE))
WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
flags |= qc->tag << CRQB_TAG_SHIFT;
- crqb = (struct mv_crqb_iie *) &pp->crqb[pp->req_producer];
+ /* get current queue index from hardware */
+ in_index = (readl(mv_ap_base(ap) + EDMA_REQ_Q_IN_PTR_OFS)
+ >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
+
+ crqb = (struct mv_crqb_iie *) &pp->crqb[in_index];
crqb->addr = cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
crqb->flags = cpu_to_le32(flags);
{
void __iomem *port_mmio = mv_ap_base(qc->ap);
struct mv_port_priv *pp = qc->ap->private_data;
+ unsigned in_index;
u32 in_ptr;
if (ATA_PROT_DMA != qc->tf.protocol) {
return ata_qc_issue_prot(qc);
}
- in_ptr = readl(port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
+ in_ptr = readl(port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
+ in_index = (in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
- /* the req producer index should be the same as we remember it */
- WARN_ON(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
- pp->req_producer);
/* until we do queuing, the queue should be empty at this point */
- WARN_ON(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
- ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS) >>
- EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
+ WARN_ON(in_index != ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS)
+ >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
- mv_inc_q_index(&pp->req_producer); /* now incr producer index */
+ in_index = mv_inc_q_index(in_index); /* now incr producer index */
mv_start_dma(port_mmio, pp);
/* and write the request in pointer to kick the EDMA to life */
in_ptr &= EDMA_REQ_Q_BASE_LO_MASK;
- in_ptr |= pp->req_producer << EDMA_REQ_Q_PTR_SHIFT;
+ in_ptr |= in_index << EDMA_REQ_Q_PTR_SHIFT;
writelfl(in_ptr, port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
return 0;
{
void __iomem *port_mmio = mv_ap_base(ap);
struct mv_port_priv *pp = ap->private_data;
+ unsigned out_index;
u32 out_ptr;
u8 ata_status;
- out_ptr = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
+ out_ptr = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
+ out_index = (out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
- /* the response consumer index should be the same as we remember it */
- WARN_ON(((out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
- pp->rsp_consumer);
-
- ata_status = pp->crpb[pp->rsp_consumer].flags >> CRPB_FLAG_STATUS_SHIFT;
+ ata_status = le16_to_cpu(pp->crpb[out_index].flags)
+ >> CRPB_FLAG_STATUS_SHIFT;
/* increment our consumer index... */
- pp->rsp_consumer = mv_inc_q_index(&pp->rsp_consumer);
+ out_index = mv_inc_q_index(out_index);
/* and, until we do NCQ, there should only be 1 CRPB waiting */
- WARN_ON(((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS) >>
- EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) !=
- pp->rsp_consumer);
+ WARN_ON(out_index != ((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS)
+ >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
/* write out our inc'd consumer index so EDMA knows we're caught up */
out_ptr &= EDMA_RSP_Q_BASE_LO_MASK;
- out_ptr |= pp->rsp_consumer << EDMA_RSP_Q_PTR_SHIFT;
+ out_ptr |= out_index << EDMA_RSP_Q_PTR_SHIFT;
writelfl(out_ptr, port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
/* Return ATA status register for completed CRPB */
edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
if (EDMA_ERR_SERR & edma_err_cause) {
- serr = scr_read(ap, SCR_ERROR);
- scr_write_flush(ap, SCR_ERROR, serr);
+ sata_scr_read(ap, SCR_ERROR, &serr);
+ sata_scr_write_flush(ap, SCR_ERROR, serr);
}
if (EDMA_ERR_SELF_DIS & edma_err_cause) {
struct mv_port_priv *pp = ap->private_data;
/* Note that DEV_IRQ might happen spuriously during EDMA,
* and should be ignored in such cases.
* The cause of this is still under investigation.
- */
+ */
if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
/* EDMA: check for response queue interrupt */
if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) {
}
}
- if (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))
+ if (ap && (ap->flags & ATA_FLAG_DISABLED))
continue;
err_mask = ac_err_mask(ata_status);
VPRINTK("port %u IRQ found for qc, "
"ata_status 0x%x\n", port,ata_status);
/* mark qc status appropriately */
- if (!(qc->tf.ctl & ATA_NIEN)) {
+ if (!(qc->tf.flags & ATA_TFLAG_POLLING)) {
qc->err_mask |= err_mask;
ata_qc_complete(qc);
}
/* Issue COMRESET via SControl */
comreset_retry:
- scr_write_flush(ap, SCR_CONTROL, 0x301);
+ sata_scr_write_flush(ap, SCR_CONTROL, 0x301);
__msleep(1, can_sleep);
- scr_write_flush(ap, SCR_CONTROL, 0x300);
+ sata_scr_write_flush(ap, SCR_CONTROL, 0x300);
__msleep(20, can_sleep);
timeout = jiffies + msecs_to_jiffies(200);
do {
- sstatus = scr_read(ap, SCR_STATUS) & 0x3;
+ sata_scr_read(ap, SCR_STATUS, &sstatus);
+ sstatus &= 0x3;
if ((sstatus == 3) || (sstatus == 0))
break;
"SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
- if (sata_dev_present(ap)) {
+ if (ata_port_online(ap)) {
ata_port_probe(ap);
} else {
- printk(KERN_INFO "ata%u: no device found (phy stat %08x)\n",
- ap->id, scr_read(ap, SCR_STATUS));
+ sata_scr_read(ap, SCR_STATUS, &sstatus);
+ ata_port_printk(ap, KERN_INFO,
+ "no device found (phy stat %08x)\n", sstatus);
ata_port_disable(ap);
return;
}
tf.nsect = readb((void __iomem *) ap->ioaddr.nsect_addr);
dev->class = ata_dev_classify(&tf);
- if (!ata_dev_present(dev)) {
+ if (!ata_dev_enabled(dev)) {
VPRINTK("Port disabled post-sig: No device present.\n");
ata_port_disable(ap);
}
static void mv_eng_timeout(struct ata_port *ap)
{
struct ata_queued_cmd *qc;
+ unsigned long flags;
- printk(KERN_ERR "ata%u: Entering mv_eng_timeout\n",ap->id);
+ ata_port_printk(ap, KERN_ERR, "Entering mv_eng_timeout\n");
DPRINTK("All regs @ start of eng_timeout\n");
mv_dump_all_regs(ap->host_set->mmio_base, ap->port_no,
to_pci_dev(ap->host_set->dev));
ap->host_set->mmio_base, ap, qc, qc->scsicmd,
&qc->scsicmd->cmnd);
+ spin_lock_irqsave(&ap->host_set->lock, flags);
mv_err_intr(ap, 0);
mv_stop_and_reset(ap);
+ spin_unlock_irqrestore(&ap->host_set->lock, flags);
WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE));
if (qc->flags & ATA_QCFLAG_ACTIVE) {