From: Jeff Garzik <jgarzik@pobox.com>
To: Mark Lord <liml@rtr.ca>
Cc: IDE/ATA development list <linux-ide@vger.kernel.org>
Subject: Re: [PATCH 10/14] sata_mv Use DMA memory pools for hardware memory tables
Date: Fri, 25 Jan 2008 23:25:29 -0500 [thread overview]
Message-ID: <479AB639.5020108@pobox.com> (raw)
In-Reply-To: <4798FCE1.30702@rtr.ca>
Mark Lord wrote:
> sata_mv Use DMA memory pools for hardware memory tables.
>
> Create module-owned DMA memory pools, for use in allocating/freeing
> per-port
> command/response queues and SG tables. This gives us a way to guarantee we
> meet the hardware address alignment requirements, and also reduces
> memory that
> might otherwise be wasted on alignment gaps.
>
> Signed-off-by: Mark Lord <mlord@pobox.com>
>
> --- old/drivers/ata/sata_mv.c 2008-01-24 12:40:10.000000000 -0500
> +++ new/drivers/ata/sata_mv.c 2008-01-24 14:17:39.000000000 -0500
> @@ -107,14 +107,12 @@
>
> /* CRQB needs alignment on a 1KB boundary. Size == 1KB
> * CRPB needs alignment on a 256B boundary. Size == 256B
> - * SG count of 176 leads to MV_PORT_PRIV_DMA_SZ == 4KB
> * ePRD (SG) entries need alignment on a 16B boundary. Size == 16B
> */
> MV_CRQB_Q_SZ = (32 * MV_MAX_Q_DEPTH),
> MV_CRPB_Q_SZ = (8 * MV_MAX_Q_DEPTH),
> - MV_MAX_SG_CT = 176,
> + MV_MAX_SG_CT = 256,
> MV_SG_TBL_SZ = (16 * MV_MAX_SG_CT),
> - MV_PORT_PRIV_DMA_SZ = (MV_CRQB_Q_SZ + MV_CRPB_Q_SZ + MV_SG_TBL_SZ),
>
> MV_PORTS_PER_HC = 4,
> /* == (port / MV_PORTS_PER_HC) to determine HC from 0-7 port */
> @@ -701,6 +699,33 @@
> */
> static int msi; /* Use PCI msi; either zero (off, default) or
> non-zero */
>
> +/*
> + * These consistent DMA memory pools are owned by this module,
> + * and shared among all device instances. This gives us guaranteed
> + * alignment for hardware-accessed data structures, and low memory
> + * waste in accomplishing the alignment.
> + */
> +static struct dma_pool *mv_crpb_pool;
> +static struct dma_pool *mv_crqb_pool;
> +static struct dma_pool *mv_sg_tbl_pool;
> +
> +static void mv_free_pool_items(struct ata_port *ap)
> +{
> + struct mv_port_priv *pp = ap->private_data;
> +
> + if (pp->sg_tbl) {
> + dma_pool_free(mv_sg_tbl_pool, pp->sg_tbl, pp->sg_tbl_dma);
> + pp->sg_tbl = NULL;
> + }
> + if (pp->crqb) {
> + dma_pool_free(mv_crqb_pool, pp->crqb, pp->crqb_dma);
> + pp->crpb = NULL;
> + }
> + if (pp->crqb) {
> + dma_pool_free(mv_crqb_pool, pp->crqb, pp->crqb_dma);
> + pp->crqb = NULL;
> + }
> +}
>
> /* move to PCI layer or libata core? */
> static int pci_go_64(struct pci_dev *pdev)
> @@ -1110,8 +1135,6 @@
> struct mv_host_priv *hpriv = ap->host->private_data;
> struct mv_port_priv *pp;
> void __iomem *port_mmio = mv_ap_base(ap);
> - void *mem;
> - dma_addr_t mem_dma;
> unsigned long flags;
> int rc;
>
> @@ -1119,37 +1142,21 @@
> if (!pp)
> return -ENOMEM;
>
> - mem = dmam_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma,
> - GFP_KERNEL);
> - if (!mem)
> - return -ENOMEM;
> - memset(mem, 0, MV_PORT_PRIV_DMA_SZ);
> -
> rc = ata_pad_alloc(ap, dev);
> if (rc)
> return rc;
>
> - /* First item in chunk of DMA memory:
> - * 32-slot command request table (CRQB), 32 bytes each in size
> - */
> - pp->crqb = mem;
> - pp->crqb_dma = mem_dma;
> - mem += MV_CRQB_Q_SZ;
> - mem_dma += MV_CRQB_Q_SZ;
> -
> - /* Second item:
> - * 32-slot command response table (CRPB), 8 bytes each in size
> - */
> - pp->crpb = mem;
> - pp->crpb_dma = mem_dma;
> - mem += MV_CRPB_Q_SZ;
> - mem_dma += MV_CRPB_Q_SZ;
> -
> - /* Third item:
> - * Table of scatter-gather descriptors (ePRD), 16 bytes each
> - */
> - pp->sg_tbl = mem;
> - pp->sg_tbl_dma = mem_dma;
> + pp->crqb = dma_pool_alloc(mv_crqb_pool, GFP_KERNEL, &pp->crqb_dma);
> + if (!pp->crqb)
> + goto out_alloc_failed;
> +
> + pp->crpb = dma_pool_alloc(mv_crpb_pool, GFP_KERNEL, &pp->crpb_dma);
> + if (!pp->crpb)
> + goto out_alloc_failed;
> +
> + pp->sg_tbl = dma_pool_alloc(mv_sg_tbl_pool, GFP_KERNEL,
> &pp->sg_tbl_dma);
> + if (!pp->sg_tbl)
> + goto out_alloc_failed;
>
> spin_lock_irqsave(&ap->host->lock, flags);
>
> @@ -1165,6 +1172,10 @@
> */
> ap->private_data = pp;
> return 0;
> +
> +out_alloc_failed:
> + mv_free_pool_items(ap);
> + return -ENOMEM;
> }
>
> /**
> @@ -1179,6 +1190,7 @@
> static void mv_port_stop(struct ata_port *ap)
> {
> mv_stop_dma(ap);
> + mv_free_pool_items(ap);
> }
>
> /**
> @@ -2825,14 +2837,39 @@
> IS_GEN_I(hpriv) ? &mv5_sht : &mv6_sht);
> }
>
> +static void mv_destroy_pools(void)
> +{
> + if (mv_sg_tbl_pool)
> + dma_pool_destroy(mv_sg_tbl_pool);
> + if (mv_crpb_pool)
> + dma_pool_destroy(mv_crpb_pool);
> + if (mv_crqb_pool)
> + dma_pool_destroy(mv_crqb_pool);
> +}
> +
> static int __init mv_init(void)
> {
> + /* Ideally, a device (second parameter) would "own" these pools.
> + * But for maximum memory efficiency, we really need one global
> + * set of each, shared among all like devices. As below.
> + */
> + mv_crqb_pool = dma_pool_create("mv_crqb_q", NULL, MV_CRQB_Q_SZ,
> + MV_CRQB_Q_SZ, 0);
> + mv_crpb_pool = dma_pool_create("mv_crpb_q", NULL, MV_CRPB_Q_SZ,
> + MV_CRPB_Q_SZ, 0);
> + mv_sg_tbl_pool = dma_pool_create("mv_sg_tbl", NULL, MV_SG_TBL_SZ,
> + MV_SG_TBL_SZ, 0);
Sorry, I would far rather waste a tiny bit of memory than this.
The main objection is that DMA allocation should /always/ be associated
with a struct device, as that is where most of the connectivity with the
DMA mask/boundary/etc. and private IOMMU hooks live.
The amount of memory used in the pre-existing configuration is small, it
is already allocated on a per-device basis, and it is statically
allocated -- meaning no worry about allocations failing inside of
interrupts or similar nastiness.
Jeff
next prev parent reply other threads:[~2008-01-26 4:25 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-01-24 20:56 [PATCH 00/12] sata_mv NCQ support Mark Lord
2008-01-24 20:57 ` [PATCH 01/14] sata_mv EH fixes Mark Lord
2008-01-26 4:09 ` Jeff Garzik
2008-01-24 20:57 ` [PATCH 02/14] sata_mv Mask transient IRQs Mark Lord
2008-01-26 4:10 ` Jeff Garzik
2008-01-26 15:11 ` Mark Lord
2008-01-24 20:58 ` [PATCH 03/14] sata_mv Clear queue indexes on chip restart Mark Lord
2008-01-24 20:59 ` [PATCH 04/14] sata_mv rename base to port_mmio Mark Lord
2008-01-26 4:11 ` Jeff Garzik
2008-01-24 20:59 ` [PATCH 05/14] sata_mv Fix EDMA configuration Mark Lord
2008-01-26 4:17 ` Jeff Garzik
2008-01-26 15:12 ` Mark Lord
2008-01-24 21:00 ` [PATCH 06/14] sata_mv Add want_ncq parameter for " Mark Lord
2008-01-26 4:18 ` Jeff Garzik
2008-01-24 21:00 ` [PATCH 07/14] sata_mv Use hqtag instead of ioid Mark Lord
2008-01-26 4:19 ` Jeff Garzik
2008-01-26 15:14 ` Mark Lord
2008-01-24 21:01 ` [PATCH 08/14] sata_mv Ignore response status LSB on NCQ Mark Lord
2008-01-24 21:01 ` [PATCH 09/14] sata_mv Restrict max_sectors to 8-bits on GenII NCQ Mark Lord
2008-01-26 4:21 ` Jeff Garzik
2008-01-24 21:02 ` [PATCH 10/14] sata_mv Use DMA memory pools for hardware memory tables Mark Lord
2008-01-26 4:25 ` Jeff Garzik [this message]
2008-01-26 15:18 ` Mark Lord
2008-01-26 15:30 ` Mark Lord
2008-01-26 15:45 ` Jeff Garzik
2008-01-26 18:27 ` Mark Lord
2008-01-26 15:20 ` Mark Lord
2008-01-24 21:02 ` [PATCH 11/12] sata_mv Introduce per-tag SG tables Mark Lord
2008-01-26 4:26 ` Jeff Garzik
2008-01-24 21:03 ` [PATCH 12/14] sata_mv Enable NCQ operation Mark Lord
2008-01-26 4:26 ` Jeff Garzik
2008-01-24 21:03 ` [PATCH 13/14] sata_mv No soft resets Mark Lord
2008-01-26 4:28 ` Jeff Garzik
2008-01-26 15:21 ` Mark Lord
2008-01-24 21:04 ` [PATCH 14/14] sata_mv Comments and version bump Mark Lord
2008-01-25 19:38 ` [PATCH 14/14] sata_mv Comments and version bump (v.2) Mark Lord
2008-01-24 21:06 ` [PATCH 00/12] sata_mv NCQ support Mark Lord
2008-01-25 0:04 ` [PATCH 15/14] " Mark Lord
2008-01-25 0:08 ` Tejun Heo
2008-01-26 4:28 ` Jeff Garzik
2008-01-26 4:14 ` [PATCH 00/12] " Jeff Garzik
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=479AB639.5020108@pobox.com \
--to=jgarzik@pobox.com \
--cc=liml@rtr.ca \
--cc=linux-ide@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).