Skip to content

Commit

Permalink
sata_mv ncq Introduce per-tag SG tables
Browse files Browse the repository at this point in the history
In preparation for supporting NCQ, we must allocate separate SG tables
for each command tag, rather than just a single table per port as before.

Gen-I hardware cannot do NCQ, though, so we still allocate just a single
table for that, but populate it in all 32 slots to avoid special-cases
elsewhere in hotter paths of the code.

Signed-off-by: Mark Lord <mlord@pobox.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
  • Loading branch information
Mark Lord authored and Jeff Garzik committed Feb 1, 2008
1 parent bf7f22b commit eb73d55
Showing 1 changed file with 40 additions and 15 deletions.
55 changes: 40 additions & 15 deletions drivers/ata/sata_mv.c
Original file line number Diff line number Diff line change
Expand Up @@ -398,8 +398,8 @@ struct mv_port_priv {
dma_addr_t crqb_dma;
struct mv_crpb *crpb;
dma_addr_t crpb_dma;
struct mv_sg *sg_tbl;
dma_addr_t sg_tbl_dma;
struct mv_sg *sg_tbl[MV_MAX_Q_DEPTH];
dma_addr_t sg_tbl_dma[MV_MAX_Q_DEPTH];

unsigned int req_idx;
unsigned int resp_idx;
Expand Down Expand Up @@ -483,6 +483,10 @@ static void mv_edma_cfg(struct mv_port_priv *pp, struct mv_host_priv *hpriv,
void __iomem *port_mmio, int want_ncq);
static int __mv_stop_dma(struct ata_port *ap);

/* .sg_tablesize is (MV_MAX_SG_CT / 2) in the structures below
* because we have to allow room for worst case splitting of
* PRDs for 64K boundaries in mv_fill_sg().
*/
static struct scsi_host_template mv5_sht = {
.module = THIS_MODULE,
.name = DRV_NAME,
Expand Down Expand Up @@ -1107,6 +1111,7 @@ static void mv_port_free_dma_mem(struct ata_port *ap)
{
struct mv_host_priv *hpriv = ap->host->private_data;
struct mv_port_priv *pp = ap->private_data;
int tag;

if (pp->crqb) {
dma_pool_free(hpriv->crqb_pool, pp->crqb, pp->crqb_dma);
Expand All @@ -1116,9 +1121,18 @@ static void mv_port_free_dma_mem(struct ata_port *ap)
dma_pool_free(hpriv->crpb_pool, pp->crpb, pp->crpb_dma);
pp->crpb = NULL;
}
if (pp->sg_tbl) {
dma_pool_free(hpriv->sg_tbl_pool, pp->sg_tbl, pp->sg_tbl_dma);
pp->sg_tbl = NULL;
/*
* For GEN_I, there's no NCQ, so we have only a single sg_tbl.
* For later hardware, we have one unique sg_tbl per NCQ tag.
*/
for (tag = 0; tag < MV_MAX_Q_DEPTH; ++tag) {
if (pp->sg_tbl[tag]) {
if (tag == 0 || !IS_GEN_I(hpriv))
dma_pool_free(hpriv->sg_tbl_pool,
pp->sg_tbl[tag],
pp->sg_tbl_dma[tag]);
pp->sg_tbl[tag] = NULL;
}
}
}

Expand All @@ -1139,7 +1153,7 @@ static int mv_port_start(struct ata_port *ap)
struct mv_port_priv *pp;
void __iomem *port_mmio = mv_ap_base(ap);
unsigned long flags;
int rc;
int tag, rc;

pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
if (!pp)
Expand All @@ -1160,10 +1174,21 @@ static int mv_port_start(struct ata_port *ap)
goto out_port_free_dma_mem;
memset(pp->crpb, 0, MV_CRPB_Q_SZ);

pp->sg_tbl = dma_pool_alloc(hpriv->sg_tbl_pool, GFP_KERNEL,
&pp->sg_tbl_dma);
if (!pp->sg_tbl)
goto out_port_free_dma_mem;
/*
* For GEN_I, there's no NCQ, so we only allocate a single sg_tbl.
* For later hardware, we need one unique sg_tbl per NCQ tag.
*/
for (tag = 0; tag < MV_MAX_Q_DEPTH; ++tag) {
if (tag == 0 || !IS_GEN_I(hpriv)) {
pp->sg_tbl[tag] = dma_pool_alloc(hpriv->sg_tbl_pool,
GFP_KERNEL, &pp->sg_tbl_dma[tag]);
if (!pp->sg_tbl[tag])
goto out_port_free_dma_mem;
} else {
pp->sg_tbl[tag] = pp->sg_tbl[0];
pp->sg_tbl_dma[tag] = pp->sg_tbl_dma[0];
}
}

spin_lock_irqsave(&ap->host->lock, flags);

Expand Down Expand Up @@ -1214,7 +1239,7 @@ static void mv_fill_sg(struct ata_queued_cmd *qc)
struct mv_sg *mv_sg, *last_sg = NULL;
unsigned int si;

mv_sg = pp->sg_tbl;
mv_sg = pp->sg_tbl[qc->tag];
for_each_sg(qc->sg, sg, qc->n_elem, si) {
dma_addr_t addr = sg_dma_address(sg);
u32 sg_len = sg_dma_len(sg);
Expand Down Expand Up @@ -1284,9 +1309,9 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;

pp->crqb[in_index].sg_addr =
cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
cpu_to_le32(pp->sg_tbl_dma[qc->tag] & 0xffffffff);
pp->crqb[in_index].sg_addr_hi =
cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
cpu_to_le32((pp->sg_tbl_dma[qc->tag] >> 16) >> 16);
pp->crqb[in_index].ctrl_flags = cpu_to_le16(flags);

cw = &pp->crqb[in_index].ata_cmd[0];
Expand Down Expand Up @@ -1377,8 +1402,8 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
in_index = pp->req_idx & 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->addr = cpu_to_le32(pp->sg_tbl_dma[qc->tag] & 0xffffffff);
crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma[qc->tag] >> 16) >> 16);
crqb->flags = cpu_to_le32(flags);

tf = &qc->tf;
Expand Down

0 comments on commit eb73d55

Please sign in to comment.