Commit 5fac4115 authored by Jeff Garzik's avatar Jeff Garzik

Merge redhat.com:/spare/repo/linux-2.5

into redhat.com:/spare/repo/libata-2.5
parents e689bf58 1c251ad4
...@@ -1635,8 +1635,8 @@ static void ata_sg_clean(struct ata_queued_cmd *qc) ...@@ -1635,8 +1635,8 @@ static void ata_sg_clean(struct ata_queued_cmd *qc)
if (cmd->use_sg) if (cmd->use_sg)
pci_unmap_sg(ap->host_set->pdev, sg, qc->n_elem, dir); pci_unmap_sg(ap->host_set->pdev, sg, qc->n_elem, dir);
else else
pci_unmap_single(ap->host_set->pdev, sg[0].dma_address, pci_unmap_single(ap->host_set->pdev, sg_dma_address(&sg[0]),
sg[0].length, dir); sg_dma_len(&sg[0]), dir);
qc->flags &= ~ATA_QCFLAG_SG; qc->flags &= ~ATA_QCFLAG_SG;
qc->sg = NULL; qc->sg = NULL;
...@@ -1659,8 +1659,8 @@ void ata_fill_sg(struct ata_queued_cmd *qc) ...@@ -1659,8 +1659,8 @@ void ata_fill_sg(struct ata_queued_cmd *qc)
assert(qc->n_elem > 0); assert(qc->n_elem > 0);
for (i = 0; i < qc->n_elem; i++) { for (i = 0; i < qc->n_elem; i++) {
ap->prd[i].addr = cpu_to_le32(sg[i].dma_address); ap->prd[i].addr = cpu_to_le32(sg_dma_address(&sg[i]));
ap->prd[i].flags_len = cpu_to_le32(sg[i].length); ap->prd[i].flags_len = cpu_to_le32(sg_dma_len(&sg[i]));
VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", VPRINTK("PRD[%u] = (0x%X, 0x%X)\n",
i, le32_to_cpu(ap->prd[i].addr), le32_to_cpu(ap->prd[i].flags_len)); i, le32_to_cpu(ap->prd[i].addr), le32_to_cpu(ap->prd[i].flags_len));
} }
...@@ -1691,12 +1691,12 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc) ...@@ -1691,12 +1691,12 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc)
sg->page = virt_to_page(cmd->request_buffer); sg->page = virt_to_page(cmd->request_buffer);
sg->offset = (unsigned long) cmd->request_buffer & ~PAGE_MASK; sg->offset = (unsigned long) cmd->request_buffer & ~PAGE_MASK;
sg->length = cmd->request_bufflen; sg_dma_len(sg) = cmd->request_bufflen;
if (!have_sg) if (!have_sg)
return 0; return 0;
sg->dma_address = pci_map_single(ap->host_set->pdev, sg_dma_address(sg) = pci_map_single(ap->host_set->pdev,
cmd->request_buffer, cmd->request_buffer,
cmd->request_bufflen, dir); cmd->request_bufflen, dir);
...@@ -1917,7 +1917,7 @@ static void ata_pio_sector(struct ata_port *ap) ...@@ -1917,7 +1917,7 @@ static void ata_pio_sector(struct ata_port *ap)
qc->cursg_ofs++; qc->cursg_ofs++;
if (cmd->use_sg) if (cmd->use_sg)
if ((qc->cursg_ofs * ATA_SECT_SIZE) == sg[qc->cursg].length) { if ((qc->cursg_ofs * ATA_SECT_SIZE) == sg_dma_len(&sg[qc->cursg])) {
qc->cursg++; qc->cursg++;
qc->cursg_ofs = 0; qc->cursg_ofs = 0;
} }
......
...@@ -34,10 +34,8 @@ ...@@ -34,10 +34,8 @@
#include <linux/libata.h> #include <linux/libata.h>
#include <asm/io.h> #include <asm/io.h>
#undef DIRECT_HDMA
#define DRV_NAME "sata_promise" #define DRV_NAME "sata_promise"
#define DRV_VERSION "0.86" #define DRV_VERSION "0.87"
enum { enum {
...@@ -82,6 +80,9 @@ enum { ...@@ -82,6 +80,9 @@ enum {
PDC_FLAG_20621 = (1 << 30), /* we have a 20621 */ PDC_FLAG_20621 = (1 << 30), /* we have a 20621 */
PDC_HDMA_RESET = (1 << 11), /* HDMA reset */ PDC_HDMA_RESET = (1 << 11), /* HDMA reset */
PDC_MAX_HDMA = 32,
PDC_HDMA_Q_MASK = (PDC_MAX_HDMA - 1),
}; };
...@@ -89,6 +90,15 @@ struct pdc_port_priv { ...@@ -89,6 +90,15 @@ struct pdc_port_priv {
u8 dimm_buf[(ATA_PRD_SZ * ATA_MAX_PRD) + 512]; u8 dimm_buf[(ATA_PRD_SZ * ATA_MAX_PRD) + 512];
u8 *pkt; u8 *pkt;
dma_addr_t pkt_dma; dma_addr_t pkt_dma;
unsigned int doing_hdma;
unsigned int hdma_prod;
unsigned int hdma_cons;
struct {
struct ata_queued_cmd *qc;
unsigned int seq;
unsigned long pkt_ofs;
} hdma[32];
}; };
...@@ -256,6 +266,7 @@ static int pdc_port_start(struct ata_port *ap) ...@@ -256,6 +266,7 @@ static int pdc_port_start(struct ata_port *ap)
rc = -ENOMEM; rc = -ENOMEM;
goto err_out; goto err_out;
} }
memset(pp, 0, sizeof(*pp));
pp->pkt = pci_alloc_consistent(pdev, 128, &pp->pkt_dma); pp->pkt = pci_alloc_consistent(pdev, 128, &pp->pkt_dma);
if (!pp->pkt) { if (!pp->pkt) {
...@@ -605,8 +616,8 @@ static void pdc20621_fill_sg(struct ata_queued_cmd *qc) ...@@ -605,8 +616,8 @@ static void pdc20621_fill_sg(struct ata_queued_cmd *qc)
last = qc->n_elem; last = qc->n_elem;
idx = 0; idx = 0;
for (i = 0; i < last; i++) { for (i = 0; i < last; i++) {
buf[idx++] = cpu_to_le32(sg[i].dma_address); buf[idx++] = cpu_to_le32(sg_dma_address(&sg[i]));
buf[idx++] = cpu_to_le32(sg[i].length); buf[idx++] = cpu_to_le32(sg_dma_len(&sg[i]));
total_len += sg[i].length; total_len += sg[i].length;
} }
buf[idx - 1] |= cpu_to_le32(ATA_PRD_EOT); buf[idx - 1] |= cpu_to_le32(ATA_PRD_EOT);
...@@ -643,42 +654,60 @@ static void pdc20621_fill_sg(struct ata_queued_cmd *qc) ...@@ -643,42 +654,60 @@ static void pdc20621_fill_sg(struct ata_queued_cmd *qc)
VPRINTK("ata pkt buf ofs %u, prd size %u, mmio copied\n", i, sgt_len); VPRINTK("ata pkt buf ofs %u, prd size %u, mmio copied\n", i, sgt_len);
} }
#ifdef DIRECT_HDMA static void __pdc20621_push_hdma(struct ata_queued_cmd *qc,
static void pdc20621_push_hdma(struct ata_queued_cmd *qc) unsigned int seq,
u32 pkt_ofs)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
struct ata_host_set *host_set = ap->host_set; struct ata_host_set *host_set = ap->host_set;
unsigned int port_no = ap->port_no;
void *mmio = host_set->mmio_base; void *mmio = host_set->mmio_base;
unsigned int rw = (qc->flags & ATA_QCFLAG_WRITE);
u32 tmp;
unsigned int host_sg = PDC_20621_DIMM_BASE +
(PDC_DIMM_WINDOW_STEP * port_no) +
PDC_DIMM_HOST_PRD;
unsigned int dimm_sg = PDC_20621_DIMM_BASE +
(PDC_DIMM_WINDOW_STEP * port_no) +
PDC_DIMM_HPKT_PRD;
/* hard-code chip #0 */ /* hard-code chip #0 */
mmio += PDC_CHIP0_OFS; mmio += PDC_CHIP0_OFS;
tmp = readl(mmio + PDC_HDMA_CTLSTAT) & 0xffffff00; writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
tmp |= port_no + 1 + 4; /* seq. ID */ readl(mmio + PDC_20621_SEQCTL + (seq * 4)); /* flush */
if (!rw)
tmp |= (1 << 6); /* hdma data direction */
writel(tmp, mmio + PDC_HDMA_CTLSTAT); /* note: stops DMA, if active */
readl(mmio + PDC_HDMA_CTLSTAT); /* flush */
writel(host_sg, mmio + 0x108); writel(pkt_ofs, mmio + PDC_HDMA_PKT_SUBMIT);
writel(dimm_sg, mmio + 0x10C); readl(mmio + PDC_HDMA_PKT_SUBMIT); /* flush */
writel(0, mmio + 0x128); }
tmp |= (1 << 7); static void pdc20621_push_hdma(struct ata_queued_cmd *qc,
writel(tmp, mmio + PDC_HDMA_CTLSTAT); unsigned int seq,
readl(mmio + PDC_HDMA_CTLSTAT); /* flush */ u32 pkt_ofs)
{
struct ata_port *ap = qc->ap;
struct pdc_port_priv *pp = ap->private_data;
unsigned int idx = pp->hdma_prod & PDC_HDMA_Q_MASK;
if (!pp->doing_hdma) {
__pdc20621_push_hdma(qc, seq, pkt_ofs);
pp->doing_hdma = 1;
return;
}
pp->hdma[idx].qc = qc;
pp->hdma[idx].seq = seq;
pp->hdma[idx].pkt_ofs = pkt_ofs;
pp->hdma_prod++;
}
static void pdc20621_pop_hdma(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
struct pdc_port_priv *pp = ap->private_data;
unsigned int idx = pp->hdma_cons & PDC_HDMA_Q_MASK;
/* if nothing on queue, we're done */
if (pp->hdma_prod == pp->hdma_cons) {
pp->doing_hdma = 0;
return;
}
__pdc20621_push_hdma(pp->hdma[idx].qc, pp->hdma[idx].seq,
pp->hdma[idx].pkt_ofs);
pp->hdma_cons++;
} }
#endif
#ifdef ATA_VERBOSE_DEBUG #ifdef ATA_VERBOSE_DEBUG
static void pdc20621_dump_hdma(struct ata_queued_cmd *qc) static void pdc20621_dump_hdma(struct ata_queued_cmd *qc)
...@@ -724,23 +753,17 @@ static void pdc20621_dma_start(struct ata_queued_cmd *qc) ...@@ -724,23 +753,17 @@ static void pdc20621_dma_start(struct ata_queued_cmd *qc)
wmb(); /* flush PRD, pkt writes */ wmb(); /* flush PRD, pkt writes */
writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
readl(mmio + PDC_20621_SEQCTL + (seq * 4)); /* flush */
if (doing_hdma) { if (doing_hdma) {
pdc20621_dump_hdma(qc); pdc20621_dump_hdma(qc);
#ifdef DIRECT_HDMA pdc20621_push_hdma(qc, seq, port_ofs + PDC_DIMM_HOST_PKT);
pdc20621_push_hdma(qc); VPRINTK("queued ofs 0x%x (%u), seq %u\n",
#else
writel(port_ofs + PDC_DIMM_HOST_PKT,
mmio + PDC_HDMA_PKT_SUBMIT);
readl(mmio + PDC_HDMA_PKT_SUBMIT); /* flush */
#endif
VPRINTK("submitted ofs 0x%x (%u), seq %u\n",
port_ofs + PDC_DIMM_HOST_PKT, port_ofs + PDC_DIMM_HOST_PKT,
port_ofs + PDC_DIMM_HOST_PKT, port_ofs + PDC_DIMM_HOST_PKT,
seq); seq);
} else { } else {
writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
readl(mmio + PDC_20621_SEQCTL + (seq * 4)); /* flush */
writel(port_ofs + PDC_DIMM_ATA_PKT, writel(port_ofs + PDC_DIMM_ATA_PKT,
(void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); (void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
...@@ -771,6 +794,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap, ...@@ -771,6 +794,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id, VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id,
readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT)); readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
pdc_dma_complete(ap, qc); pdc_dma_complete(ap, qc);
pdc20621_pop_hdma(qc);
} }
/* step one - exec ATA command */ /* step one - exec ATA command */
...@@ -781,15 +805,8 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap, ...@@ -781,15 +805,8 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
/* submit hdma pkt */ /* submit hdma pkt */
pdc20621_dump_hdma(qc); pdc20621_dump_hdma(qc);
writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4)); pdc20621_push_hdma(qc, seq,
readl(mmio + PDC_20621_SEQCTL + (seq * 4)); port_ofs + PDC_DIMM_HOST_PKT);
#ifdef DIRECT_HDMA
pdc20621_push_hdma(qc);
#else
writel(port_ofs + PDC_DIMM_HOST_PKT,
mmio + PDC_HDMA_PKT_SUBMIT);
readl(mmio + PDC_HDMA_PKT_SUBMIT);
#endif
} }
handled = 1; handled = 1;
break; break;
...@@ -814,6 +831,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap, ...@@ -814,6 +831,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id, VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id,
readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT)); readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
pdc_dma_complete(ap, qc); pdc_dma_complete(ap, qc);
pdc20621_pop_hdma(qc);
} }
handled = 1; handled = 1;
break; break;
......
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