* [PATCH v3 0/3] dmaengine: add slave sg transfer capabilities api
@ 2013-02-04 19:47 ` Matt Porter
0 siblings, 0 replies; 12+ messages in thread
From: Matt Porter @ 2013-02-04 19:47 UTC (permalink / raw)
To: Vinod Koul
Cc: Dan Williams, Chris Ball, Grant Likely,
Linux DaVinci Kernel List, Linux Kernel Mailing List,
Linux MMC List
Changes since v2:
- Change to a separate slave sg specific api. Drop the
generic per-channel capabilities api that is not used.
Changes since v1:
- Use the existing dma_transaction_type enums instead of
adding the mostly duplicated dmaengine_apis enums
This series adds a new dmaengine api, dma_get_slave_sg_caps(), which
may be used by a client driver to get slave SG transfer capabilities
for a particular channel. At this time, these include the max number
of segments and max length of a segment that a channel can handle for
a SG transfer.
Along with the API implementation, this series implements the backend
device_slave_sg_caps() in the EDMA DMA Engine driver and converts the
davinci_mmc driver to use dma_get_slave_sg_caps() to replace hardcoded
limits.
This is tested on the AM1808-EVM.
Matt Porter (3):
dmaengine: add dma_get_slave_sg_caps()
dma: edma: add device_slave_sg_caps() support
mmc: davinci: get SG segment limits with dma_get_slave_sg_caps()
drivers/dma/edma.c | 17 ++++++++++++
drivers/mmc/host/davinci_mmc.c | 37 ++++++++------------------
include/linux/dmaengine.h | 40 +++++++++++++++++++++++++++++
include/linux/platform_data/mmc-davinci.h | 3 ---
4 files changed, 67 insertions(+), 30 deletions(-)
--
1.7.9.5
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v3 0/3] dmaengine: add slave sg transfer capabilities api
@ 2013-02-04 19:47 ` Matt Porter
0 siblings, 0 replies; 12+ messages in thread
From: Matt Porter @ 2013-02-04 19:47 UTC (permalink / raw)
To: Vinod Koul
Cc: Dan Williams, Chris Ball, Grant Likely,
Linux DaVinci Kernel List, Linux Kernel Mailing List,
Linux MMC List
Changes since v2:
- Change to a separate slave sg specific api. Drop the
generic per-channel capabilities api that is not used.
Changes since v1:
- Use the existing dma_transaction_type enums instead of
adding the mostly duplicated dmaengine_apis enums
This series adds a new dmaengine api, dma_get_slave_sg_caps(), which
may be used by a client driver to get slave SG transfer capabilities
for a particular channel. At this time, these include the max number
of segments and max length of a segment that a channel can handle for
a SG transfer.
Along with the API implementation, this series implements the backend
device_slave_sg_caps() in the EDMA DMA Engine driver and converts the
davinci_mmc driver to use dma_get_slave_sg_caps() to replace hardcoded
limits.
This is tested on the AM1808-EVM.
Matt Porter (3):
dmaengine: add dma_get_slave_sg_caps()
dma: edma: add device_slave_sg_caps() support
mmc: davinci: get SG segment limits with dma_get_slave_sg_caps()
drivers/dma/edma.c | 17 ++++++++++++
drivers/mmc/host/davinci_mmc.c | 37 ++++++++------------------
include/linux/dmaengine.h | 40 +++++++++++++++++++++++++++++
include/linux/platform_data/mmc-davinci.h | 3 ---
4 files changed, 67 insertions(+), 30 deletions(-)
--
1.7.9.5
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v3 1/3] dmaengine: add dma_get_slave_sg_caps()
2013-02-04 19:47 ` Matt Porter
@ 2013-02-04 19:47 ` Matt Porter
-1 siblings, 0 replies; 12+ messages in thread
From: Matt Porter @ 2013-02-04 19:47 UTC (permalink / raw)
To: Vinod Koul
Cc: Dan Williams, Chris Ball, Grant Likely,
Linux DaVinci Kernel List, Linux Kernel Mailing List,
Linux MMC List
Add a dmaengine API to retrieve slave SG transfer capabilities.
The API is optionally implemented by dmaengine drivers and when
unimplemented will return a NULL pointer. A client driver using
this API provides the required dma channel, address width, and
burst size of the transfer. dma_get_slave_sg_caps() returns an
SG caps structure with the maximum number and size of SG segments
that the given channel can handle.
Signed-off-by: Matt Porter <mporter@ti.com>
---
include/linux/dmaengine.h | 40 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 40 insertions(+)
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index d3201e4..5b5b220 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -371,6 +371,19 @@ struct dma_slave_config {
unsigned int slave_id;
};
+/* struct dma_slave_sg_caps - expose SG transfer capability of a
+ * channel.
+ *
+ * @max_seg_nr: maximum number of SG segments supported on a SG/SLAVE
+ * channel (0 for no maximum or not a SG/SLAVE channel)
+ * @max_seg_len: maximum length of SG segments supported on a SG/SLAVE
+ * channel (0 for no maximum or not a SG/SLAVE channel)
+ */
+struct dma_slave_sg_caps {
+ u32 max_seg_nr;
+ u32 max_seg_len;
+};
+
static inline const char *dma_chan_name(struct dma_chan *chan)
{
return dev_name(&chan->dev->device);
@@ -534,6 +547,7 @@ struct dma_tx_state {
* struct with auxiliary transfer status information, otherwise the call
* will just return a simple status code
* @device_issue_pending: push pending transactions to hardware
+ * @device_slave_sg_caps: return the slave SG capabilities
*/
struct dma_device {
@@ -602,6 +616,9 @@ struct dma_device {
dma_cookie_t cookie,
struct dma_tx_state *txstate);
void (*device_issue_pending)(struct dma_chan *chan);
+ struct dma_slave_sg_caps *(*device_slave_sg_caps)(
+ struct dma_chan *chan, enum dma_slave_buswidth addr_width,
+ u32 maxburst);
};
static inline int dmaengine_device_control(struct dma_chan *chan,
@@ -969,6 +986,29 @@ dma_set_tx_state(struct dma_tx_state *st, dma_cookie_t last, dma_cookie_t used,
}
}
+/**
+ * dma_get_slave_sg_caps - get DMAC SG transfer capabilities
+ * @chan: target DMA channel
+ * @addr_width: address width of the DMA transfer
+ * @maxburst: maximum DMA transfer burst size
+ *
+ * Get SG transfer capabilities for a specified channel. If the dmaengine
+ * driver does not implement SG transfer capabilities then NULL is
+ * returned.
+ */
+static inline struct dma_slave_sg_caps
+*dma_get_slave_sg_caps(struct dma_chan *chan,
+ enum dma_slave_buswidth addr_width,
+ u32 maxburst)
+{
+ if (chan->device->device_slave_sg_caps)
+ return chan->device->device_slave_sg_caps(chan,
+ addr_width,
+ maxburst);
+
+ return NULL;
+}
+
enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie);
#ifdef CONFIG_DMA_ENGINE
enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v3 1/3] dmaengine: add dma_get_slave_sg_caps()
@ 2013-02-04 19:47 ` Matt Porter
0 siblings, 0 replies; 12+ messages in thread
From: Matt Porter @ 2013-02-04 19:47 UTC (permalink / raw)
To: Vinod Koul
Cc: Dan Williams, Chris Ball, Grant Likely,
Linux DaVinci Kernel List, Linux Kernel Mailing List,
Linux MMC List
Add a dmaengine API to retrieve slave SG transfer capabilities.
The API is optionally implemented by dmaengine drivers and when
unimplemented will return a NULL pointer. A client driver using
this API provides the required dma channel, address width, and
burst size of the transfer. dma_get_slave_sg_caps() returns an
SG caps structure with the maximum number and size of SG segments
that the given channel can handle.
Signed-off-by: Matt Porter <mporter@ti.com>
---
include/linux/dmaengine.h | 40 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 40 insertions(+)
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index d3201e4..5b5b220 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -371,6 +371,19 @@ struct dma_slave_config {
unsigned int slave_id;
};
+/* struct dma_slave_sg_caps - expose SG transfer capability of a
+ * channel.
+ *
+ * @max_seg_nr: maximum number of SG segments supported on a SG/SLAVE
+ * channel (0 for no maximum or not a SG/SLAVE channel)
+ * @max_seg_len: maximum length of SG segments supported on a SG/SLAVE
+ * channel (0 for no maximum or not a SG/SLAVE channel)
+ */
+struct dma_slave_sg_caps {
+ u32 max_seg_nr;
+ u32 max_seg_len;
+};
+
static inline const char *dma_chan_name(struct dma_chan *chan)
{
return dev_name(&chan->dev->device);
@@ -534,6 +547,7 @@ struct dma_tx_state {
* struct with auxiliary transfer status information, otherwise the call
* will just return a simple status code
* @device_issue_pending: push pending transactions to hardware
+ * @device_slave_sg_caps: return the slave SG capabilities
*/
struct dma_device {
@@ -602,6 +616,9 @@ struct dma_device {
dma_cookie_t cookie,
struct dma_tx_state *txstate);
void (*device_issue_pending)(struct dma_chan *chan);
+ struct dma_slave_sg_caps *(*device_slave_sg_caps)(
+ struct dma_chan *chan, enum dma_slave_buswidth addr_width,
+ u32 maxburst);
};
static inline int dmaengine_device_control(struct dma_chan *chan,
@@ -969,6 +986,29 @@ dma_set_tx_state(struct dma_tx_state *st, dma_cookie_t last, dma_cookie_t used,
}
}
+/**
+ * dma_get_slave_sg_caps - get DMAC SG transfer capabilities
+ * @chan: target DMA channel
+ * @addr_width: address width of the DMA transfer
+ * @maxburst: maximum DMA transfer burst size
+ *
+ * Get SG transfer capabilities for a specified channel. If the dmaengine
+ * driver does not implement SG transfer capabilities then NULL is
+ * returned.
+ */
+static inline struct dma_slave_sg_caps
+*dma_get_slave_sg_caps(struct dma_chan *chan,
+ enum dma_slave_buswidth addr_width,
+ u32 maxburst)
+{
+ if (chan->device->device_slave_sg_caps)
+ return chan->device->device_slave_sg_caps(chan,
+ addr_width,
+ maxburst);
+
+ return NULL;
+}
+
enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie);
#ifdef CONFIG_DMA_ENGINE
enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v3 2/3] dma: edma: add device_slave_sg_caps() support
2013-02-04 19:47 ` Matt Porter
@ 2013-02-04 19:47 ` Matt Porter
-1 siblings, 0 replies; 12+ messages in thread
From: Matt Porter @ 2013-02-04 19:47 UTC (permalink / raw)
To: Vinod Koul
Cc: Dan Williams, Chris Ball, Grant Likely,
Linux DaVinci Kernel List, Linux Kernel Mailing List,
Linux MMC List
Implement device_slave_sg_caps().
EDMA has a finite set of PaRAM slots available for linking a
multi-segment SG transfer. In order to prevent any one channel
from consuming all PaRAM slots to fulfill a large SG transfer,
the driver reports a static per-channel max number of SG segments
it will handle.
The maximum size of an SG segment is limited by the addr_width
and maxburst of a given transfer request. These values are
provided by the client driver and used to calculate and return
the maximum segment length.
Signed-off-by: Matt Porter <mporter@ti.com>
---
drivers/dma/edma.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
index f424298..b779cee 100644
--- a/drivers/dma/edma.c
+++ b/drivers/dma/edma.c
@@ -72,6 +72,7 @@ struct edma_chan {
dma_addr_t addr;
int addr_width;
int maxburst;
+ struct dma_slave_sg_caps sg_caps;
};
struct edma_cc {
@@ -463,6 +464,20 @@ static void edma_issue_pending(struct dma_chan *chan)
spin_unlock_irqrestore(&echan->vchan.lock, flags);
}
+static struct dma_slave_sg_caps
+*edma_get_slave_sg_caps(struct dma_chan *chan,
+ enum dma_slave_buswidth addr_width,
+ u32 maxburst)
+{
+ struct edma_chan *echan;
+
+ echan = to_edma_chan(chan);
+ echan->sg_caps.max_seg_len =
+ (SZ_64K - 1) * addr_width * maxburst;
+
+ return &echan->sg_caps;
+}
+
static size_t edma_desc_size(struct edma_desc *edesc)
{
int i;
@@ -522,6 +537,7 @@ static void __init edma_chan_init(struct edma_cc *ecc,
echan->ch_num = EDMA_CTLR_CHAN(ecc->ctlr, i);
echan->ecc = ecc;
echan->vchan.desc_free = edma_desc_free;
+ echan->sg_caps.max_seg_nr = MAX_NR_SG;
vchan_init(&echan->vchan, dma);
@@ -538,6 +554,7 @@ static void edma_dma_init(struct edma_cc *ecc, struct dma_device *dma,
dma->device_alloc_chan_resources = edma_alloc_chan_resources;
dma->device_free_chan_resources = edma_free_chan_resources;
dma->device_issue_pending = edma_issue_pending;
+ dma->device_slave_sg_caps = edma_get_slave_sg_caps;
dma->device_tx_status = edma_tx_status;
dma->device_control = edma_control;
dma->dev = dev;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v3 2/3] dma: edma: add device_slave_sg_caps() support
@ 2013-02-04 19:47 ` Matt Porter
0 siblings, 0 replies; 12+ messages in thread
From: Matt Porter @ 2013-02-04 19:47 UTC (permalink / raw)
To: Vinod Koul
Cc: Dan Williams, Chris Ball, Grant Likely,
Linux DaVinci Kernel List, Linux Kernel Mailing List,
Linux MMC List
Implement device_slave_sg_caps().
EDMA has a finite set of PaRAM slots available for linking a
multi-segment SG transfer. In order to prevent any one channel
from consuming all PaRAM slots to fulfill a large SG transfer,
the driver reports a static per-channel max number of SG segments
it will handle.
The maximum size of an SG segment is limited by the addr_width
and maxburst of a given transfer request. These values are
provided by the client driver and used to calculate and return
the maximum segment length.
Signed-off-by: Matt Porter <mporter@ti.com>
---
drivers/dma/edma.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
index f424298..b779cee 100644
--- a/drivers/dma/edma.c
+++ b/drivers/dma/edma.c
@@ -72,6 +72,7 @@ struct edma_chan {
dma_addr_t addr;
int addr_width;
int maxburst;
+ struct dma_slave_sg_caps sg_caps;
};
struct edma_cc {
@@ -463,6 +464,20 @@ static void edma_issue_pending(struct dma_chan *chan)
spin_unlock_irqrestore(&echan->vchan.lock, flags);
}
+static struct dma_slave_sg_caps
+*edma_get_slave_sg_caps(struct dma_chan *chan,
+ enum dma_slave_buswidth addr_width,
+ u32 maxburst)
+{
+ struct edma_chan *echan;
+
+ echan = to_edma_chan(chan);
+ echan->sg_caps.max_seg_len =
+ (SZ_64K - 1) * addr_width * maxburst;
+
+ return &echan->sg_caps;
+}
+
static size_t edma_desc_size(struct edma_desc *edesc)
{
int i;
@@ -522,6 +537,7 @@ static void __init edma_chan_init(struct edma_cc *ecc,
echan->ch_num = EDMA_CTLR_CHAN(ecc->ctlr, i);
echan->ecc = ecc;
echan->vchan.desc_free = edma_desc_free;
+ echan->sg_caps.max_seg_nr = MAX_NR_SG;
vchan_init(&echan->vchan, dma);
@@ -538,6 +554,7 @@ static void edma_dma_init(struct edma_cc *ecc, struct dma_device *dma,
dma->device_alloc_chan_resources = edma_alloc_chan_resources;
dma->device_free_chan_resources = edma_free_chan_resources;
dma->device_issue_pending = edma_issue_pending;
+ dma->device_slave_sg_caps = edma_get_slave_sg_caps;
dma->device_tx_status = edma_tx_status;
dma->device_control = edma_control;
dma->dev = dev;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v3 3/3] mmc: davinci: get SG segment limits with dma_get_slave_sg_caps()
2013-02-04 19:47 ` Matt Porter
@ 2013-02-04 19:47 ` Matt Porter
-1 siblings, 0 replies; 12+ messages in thread
From: Matt Porter @ 2013-02-04 19:47 UTC (permalink / raw)
To: Vinod Koul
Cc: Dan Williams, Chris Ball, Grant Likely,
Linux DaVinci Kernel List, Linux Kernel Mailing List,
Linux MMC List
Replace the hardcoded values used to set max_segs/max_seg_size with
a dma_get_slave_sg_caps() query to the dmaengine driver.
Signed-off-by: Matt Porter <mporter@ti.com>
---
drivers/mmc/host/davinci_mmc.c | 37 ++++++++---------------------
include/linux/platform_data/mmc-davinci.h | 3 ---
2 files changed, 10 insertions(+), 30 deletions(-)
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
index 2063677..583cbd0 100644
--- a/drivers/mmc/host/davinci_mmc.c
+++ b/drivers/mmc/host/davinci_mmc.c
@@ -144,18 +144,6 @@
/* MMCSD Init clock in Hz in opendrain mode */
#define MMCSD_INIT_CLOCK 200000
-/*
- * One scatterlist dma "segment" is at most MAX_CCNT rw_threshold units,
- * and we handle up to MAX_NR_SG segments. MMC_BLOCK_BOUNCE kicks in only
- * for drivers with max_segs == 1, making the segments bigger (64KB)
- * than the page or two that's otherwise typical. nr_sg (passed from
- * platform data) == 16 gives at least the same throughput boost, using
- * EDMA transfer linkage instead of spending CPU time copying pages.
- */
-#define MAX_CCNT ((1 << 16) - 1)
-
-#define MAX_NR_SG 16
-
static unsigned rw_threshold = 32;
module_param(rw_threshold, uint, S_IRUGO);
MODULE_PARM_DESC(rw_threshold,
@@ -216,8 +204,6 @@ struct mmc_davinci_host {
u8 version;
/* for ns in one cycle calculation */
unsigned ns_in_one_cycle;
- /* Number of sg segments */
- u8 nr_sg;
#ifdef CONFIG_CPU_FREQ
struct notifier_block freq_transition;
#endif
@@ -1165,6 +1151,7 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev)
struct resource *r, *mem = NULL;
int ret = 0, irq = 0;
size_t mem_size;
+ struct dma_slave_sg_caps *dma_sg_caps;
/* REVISIT: when we're fully converted, fail if pdata is NULL */
@@ -1214,12 +1201,6 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev)
init_mmcsd_host(host);
- if (pdata->nr_sg)
- host->nr_sg = pdata->nr_sg - 1;
-
- if (host->nr_sg > MAX_NR_SG || !host->nr_sg)
- host->nr_sg = MAX_NR_SG;
-
host->use_dma = use_dma;
host->mmc_irq = irq;
host->sdio_irq = platform_get_irq(pdev, 1);
@@ -1248,14 +1229,16 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev)
mmc->caps |= pdata->caps;
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
- /* With no iommu coalescing pages, each phys_seg is a hw_seg.
- * Each hw_seg uses one EDMA parameter RAM slot, always one
- * channel and then usually some linked slots.
- */
- mmc->max_segs = MAX_NR_SG;
+ /* Just check one channel for the DMA SG limits */
+ dma_sg_caps = dma_get_slave_sg_caps(
+ host->dma_tx,
+ DMA_SLAVE_BUSWIDTH_4_BYTES,
+ rw_threshold / DMA_SLAVE_BUSWIDTH_4_BYTES);
- /* EDMA limit per hw segment (one or two MBytes) */
- mmc->max_seg_size = MAX_CCNT * rw_threshold;
+ if (dma_sg_caps) {
+ mmc->max_segs = dma_sg_caps->max_seg_nr;
+ mmc->max_seg_size = dma_sg_caps->max_seg_len;
+ }
/* MMC/SD controller limits for multiblock requests */
mmc->max_blk_size = 4095; /* BLEN is 12 bits */
diff --git a/include/linux/platform_data/mmc-davinci.h b/include/linux/platform_data/mmc-davinci.h
index 5ba6b22..6910209 100644
--- a/include/linux/platform_data/mmc-davinci.h
+++ b/include/linux/platform_data/mmc-davinci.h
@@ -25,9 +25,6 @@ struct davinci_mmc_config {
/* Version of the MMC/SD controller */
u8 version;
-
- /* Number of sg segments */
- u8 nr_sg;
};
void davinci_setup_mmc(int module, struct davinci_mmc_config *config);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v3 3/3] mmc: davinci: get SG segment limits with dma_get_slave_sg_caps()
@ 2013-02-04 19:47 ` Matt Porter
0 siblings, 0 replies; 12+ messages in thread
From: Matt Porter @ 2013-02-04 19:47 UTC (permalink / raw)
To: Vinod Koul
Cc: Dan Williams, Chris Ball, Grant Likely,
Linux DaVinci Kernel List, Linux Kernel Mailing List,
Linux MMC List
Replace the hardcoded values used to set max_segs/max_seg_size with
a dma_get_slave_sg_caps() query to the dmaengine driver.
Signed-off-by: Matt Porter <mporter@ti.com>
---
drivers/mmc/host/davinci_mmc.c | 37 ++++++++---------------------
include/linux/platform_data/mmc-davinci.h | 3 ---
2 files changed, 10 insertions(+), 30 deletions(-)
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
index 2063677..583cbd0 100644
--- a/drivers/mmc/host/davinci_mmc.c
+++ b/drivers/mmc/host/davinci_mmc.c
@@ -144,18 +144,6 @@
/* MMCSD Init clock in Hz in opendrain mode */
#define MMCSD_INIT_CLOCK 200000
-/*
- * One scatterlist dma "segment" is at most MAX_CCNT rw_threshold units,
- * and we handle up to MAX_NR_SG segments. MMC_BLOCK_BOUNCE kicks in only
- * for drivers with max_segs == 1, making the segments bigger (64KB)
- * than the page or two that's otherwise typical. nr_sg (passed from
- * platform data) == 16 gives at least the same throughput boost, using
- * EDMA transfer linkage instead of spending CPU time copying pages.
- */
-#define MAX_CCNT ((1 << 16) - 1)
-
-#define MAX_NR_SG 16
-
static unsigned rw_threshold = 32;
module_param(rw_threshold, uint, S_IRUGO);
MODULE_PARM_DESC(rw_threshold,
@@ -216,8 +204,6 @@ struct mmc_davinci_host {
u8 version;
/* for ns in one cycle calculation */
unsigned ns_in_one_cycle;
- /* Number of sg segments */
- u8 nr_sg;
#ifdef CONFIG_CPU_FREQ
struct notifier_block freq_transition;
#endif
@@ -1165,6 +1151,7 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev)
struct resource *r, *mem = NULL;
int ret = 0, irq = 0;
size_t mem_size;
+ struct dma_slave_sg_caps *dma_sg_caps;
/* REVISIT: when we're fully converted, fail if pdata is NULL */
@@ -1214,12 +1201,6 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev)
init_mmcsd_host(host);
- if (pdata->nr_sg)
- host->nr_sg = pdata->nr_sg - 1;
-
- if (host->nr_sg > MAX_NR_SG || !host->nr_sg)
- host->nr_sg = MAX_NR_SG;
-
host->use_dma = use_dma;
host->mmc_irq = irq;
host->sdio_irq = platform_get_irq(pdev, 1);
@@ -1248,14 +1229,16 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev)
mmc->caps |= pdata->caps;
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
- /* With no iommu coalescing pages, each phys_seg is a hw_seg.
- * Each hw_seg uses one EDMA parameter RAM slot, always one
- * channel and then usually some linked slots.
- */
- mmc->max_segs = MAX_NR_SG;
+ /* Just check one channel for the DMA SG limits */
+ dma_sg_caps = dma_get_slave_sg_caps(
+ host->dma_tx,
+ DMA_SLAVE_BUSWIDTH_4_BYTES,
+ rw_threshold / DMA_SLAVE_BUSWIDTH_4_BYTES);
- /* EDMA limit per hw segment (one or two MBytes) */
- mmc->max_seg_size = MAX_CCNT * rw_threshold;
+ if (dma_sg_caps) {
+ mmc->max_segs = dma_sg_caps->max_seg_nr;
+ mmc->max_seg_size = dma_sg_caps->max_seg_len;
+ }
/* MMC/SD controller limits for multiblock requests */
mmc->max_blk_size = 4095; /* BLEN is 12 bits */
diff --git a/include/linux/platform_data/mmc-davinci.h b/include/linux/platform_data/mmc-davinci.h
index 5ba6b22..6910209 100644
--- a/include/linux/platform_data/mmc-davinci.h
+++ b/include/linux/platform_data/mmc-davinci.h
@@ -25,9 +25,6 @@ struct davinci_mmc_config {
/* Version of the MMC/SD controller */
u8 version;
-
- /* Number of sg segments */
- u8 nr_sg;
};
void davinci_setup_mmc(int module, struct davinci_mmc_config *config);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v3 1/3] dmaengine: add dma_get_slave_sg_caps()
2013-02-04 19:47 ` Matt Porter
@ 2013-02-12 17:08 ` Vinod Koul
-1 siblings, 0 replies; 12+ messages in thread
From: Vinod Koul @ 2013-02-12 17:08 UTC (permalink / raw)
To: Matt Porter
Cc: Dan Williams, Chris Ball, Grant Likely,
Linux DaVinci Kernel List, Linux Kernel Mailing List,
Linux MMC List
On Mon, Feb 04, 2013 at 02:47:02PM -0500, Matt Porter wrote:
> Add a dmaengine API to retrieve slave SG transfer capabilities.
>
> The API is optionally implemented by dmaengine drivers and when
> unimplemented will return a NULL pointer. A client driver using
> this API provides the required dma channel, address width, and
> burst size of the transfer. dma_get_slave_sg_caps() returns an
> SG caps structure with the maximum number and size of SG segments
> that the given channel can handle.
Okay this sounds much better :-)
few points though:
- you added API for caps, but is actually calculating for given configuration
the max allowed range. IMHO that is not caps, perhaps renaming to get_max_sg
/some_better_name would be more apt.
- Still I like the idea of caps, but it should give H/W support capablity. If
you want to add that, pls develop on same line...
--
~Vinod
>
> Signed-off-by: Matt Porter <mporter@ti.com>
> ---
> include/linux/dmaengine.h | 40 ++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 40 insertions(+)
>
> diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
> index d3201e4..5b5b220 100644
> --- a/include/linux/dmaengine.h
> +++ b/include/linux/dmaengine.h
> @@ -371,6 +371,19 @@ struct dma_slave_config {
> unsigned int slave_id;
> };
>
> +/* struct dma_slave_sg_caps - expose SG transfer capability of a
> + * channel.
> + *
> + * @max_seg_nr: maximum number of SG segments supported on a SG/SLAVE
> + * channel (0 for no maximum or not a SG/SLAVE channel)
> + * @max_seg_len: maximum length of SG segments supported on a SG/SLAVE
> + * channel (0 for no maximum or not a SG/SLAVE channel)
> + */
> +struct dma_slave_sg_caps {
> + u32 max_seg_nr;
> + u32 max_seg_len;
> +};
> +
> static inline const char *dma_chan_name(struct dma_chan *chan)
> {
> return dev_name(&chan->dev->device);
> @@ -534,6 +547,7 @@ struct dma_tx_state {
> * struct with auxiliary transfer status information, otherwise the call
> * will just return a simple status code
> * @device_issue_pending: push pending transactions to hardware
> + * @device_slave_sg_caps: return the slave SG capabilities
> */
> struct dma_device {
>
> @@ -602,6 +616,9 @@ struct dma_device {
> dma_cookie_t cookie,
> struct dma_tx_state *txstate);
> void (*device_issue_pending)(struct dma_chan *chan);
> + struct dma_slave_sg_caps *(*device_slave_sg_caps)(
> + struct dma_chan *chan, enum dma_slave_buswidth addr_width,
> + u32 maxburst);
> };
>
> static inline int dmaengine_device_control(struct dma_chan *chan,
> @@ -969,6 +986,29 @@ dma_set_tx_state(struct dma_tx_state *st, dma_cookie_t last, dma_cookie_t used,
> }
> }
>
> +/**
> + * dma_get_slave_sg_caps - get DMAC SG transfer capabilities
> + * @chan: target DMA channel
> + * @addr_width: address width of the DMA transfer
> + * @maxburst: maximum DMA transfer burst size
> + *
> + * Get SG transfer capabilities for a specified channel. If the dmaengine
> + * driver does not implement SG transfer capabilities then NULL is
> + * returned.
> + */
> +static inline struct dma_slave_sg_caps
> +*dma_get_slave_sg_caps(struct dma_chan *chan,
> + enum dma_slave_buswidth addr_width,
> + u32 maxburst)
> +{
> + if (chan->device->device_slave_sg_caps)
> + return chan->device->device_slave_sg_caps(chan,
> + addr_width,
> + maxburst);
> +
> + return NULL;
> +}
> +
> enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie);
> #ifdef CONFIG_DMA_ENGINE
> enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx);
> --
> 1.7.9.5
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v3 1/3] dmaengine: add dma_get_slave_sg_caps()
@ 2013-02-12 17:08 ` Vinod Koul
0 siblings, 0 replies; 12+ messages in thread
From: Vinod Koul @ 2013-02-12 17:08 UTC (permalink / raw)
To: Matt Porter
Cc: Dan Williams, Chris Ball, Grant Likely,
Linux DaVinci Kernel List, Linux Kernel Mailing List,
Linux MMC List
On Mon, Feb 04, 2013 at 02:47:02PM -0500, Matt Porter wrote:
> Add a dmaengine API to retrieve slave SG transfer capabilities.
>
> The API is optionally implemented by dmaengine drivers and when
> unimplemented will return a NULL pointer. A client driver using
> this API provides the required dma channel, address width, and
> burst size of the transfer. dma_get_slave_sg_caps() returns an
> SG caps structure with the maximum number and size of SG segments
> that the given channel can handle.
Okay this sounds much better :-)
few points though:
- you added API for caps, but is actually calculating for given configuration
the max allowed range. IMHO that is not caps, perhaps renaming to get_max_sg
/some_better_name would be more apt.
- Still I like the idea of caps, but it should give H/W support capablity. If
you want to add that, pls develop on same line...
--
~Vinod
>
> Signed-off-by: Matt Porter <mporter@ti.com>
> ---
> include/linux/dmaengine.h | 40 ++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 40 insertions(+)
>
> diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
> index d3201e4..5b5b220 100644
> --- a/include/linux/dmaengine.h
> +++ b/include/linux/dmaengine.h
> @@ -371,6 +371,19 @@ struct dma_slave_config {
> unsigned int slave_id;
> };
>
> +/* struct dma_slave_sg_caps - expose SG transfer capability of a
> + * channel.
> + *
> + * @max_seg_nr: maximum number of SG segments supported on a SG/SLAVE
> + * channel (0 for no maximum or not a SG/SLAVE channel)
> + * @max_seg_len: maximum length of SG segments supported on a SG/SLAVE
> + * channel (0 for no maximum or not a SG/SLAVE channel)
> + */
> +struct dma_slave_sg_caps {
> + u32 max_seg_nr;
> + u32 max_seg_len;
> +};
> +
> static inline const char *dma_chan_name(struct dma_chan *chan)
> {
> return dev_name(&chan->dev->device);
> @@ -534,6 +547,7 @@ struct dma_tx_state {
> * struct with auxiliary transfer status information, otherwise the call
> * will just return a simple status code
> * @device_issue_pending: push pending transactions to hardware
> + * @device_slave_sg_caps: return the slave SG capabilities
> */
> struct dma_device {
>
> @@ -602,6 +616,9 @@ struct dma_device {
> dma_cookie_t cookie,
> struct dma_tx_state *txstate);
> void (*device_issue_pending)(struct dma_chan *chan);
> + struct dma_slave_sg_caps *(*device_slave_sg_caps)(
> + struct dma_chan *chan, enum dma_slave_buswidth addr_width,
> + u32 maxburst);
> };
>
> static inline int dmaengine_device_control(struct dma_chan *chan,
> @@ -969,6 +986,29 @@ dma_set_tx_state(struct dma_tx_state *st, dma_cookie_t last, dma_cookie_t used,
> }
> }
>
> +/**
> + * dma_get_slave_sg_caps - get DMAC SG transfer capabilities
> + * @chan: target DMA channel
> + * @addr_width: address width of the DMA transfer
> + * @maxburst: maximum DMA transfer burst size
> + *
> + * Get SG transfer capabilities for a specified channel. If the dmaengine
> + * driver does not implement SG transfer capabilities then NULL is
> + * returned.
> + */
> +static inline struct dma_slave_sg_caps
> +*dma_get_slave_sg_caps(struct dma_chan *chan,
> + enum dma_slave_buswidth addr_width,
> + u32 maxburst)
> +{
> + if (chan->device->device_slave_sg_caps)
> + return chan->device->device_slave_sg_caps(chan,
> + addr_width,
> + maxburst);
> +
> + return NULL;
> +}
> +
> enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie);
> #ifdef CONFIG_DMA_ENGINE
> enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx);
> --
> 1.7.9.5
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v3 1/3] dmaengine: add dma_get_slave_sg_caps()
[not found] ` <8b3455d3f1aa42818e917d47fd993ea1@DFLE72.ent.ti.com>
@ 2013-03-06 19:58 ` Matt Porter
0 siblings, 0 replies; 12+ messages in thread
From: Matt Porter @ 2013-03-06 19:58 UTC (permalink / raw)
To: Vinod Koul
Cc: Dan Williams, Chris Ball, Grant Likely,
Linux DaVinci Kernel List, Linux Kernel Mailing List,
Linux MMC List
On Tue, Feb 12, 2013 at 05:08:44PM +0000, Vinod Koul wrote:
> On Mon, Feb 04, 2013 at 02:47:02PM -0500, Matt Porter wrote:
> > Add a dmaengine API to retrieve slave SG transfer capabilities.
> >
> > The API is optionally implemented by dmaengine drivers and when
> > unimplemented will return a NULL pointer. A client driver using
> > this API provides the required dma channel, address width, and
> > burst size of the transfer. dma_get_slave_sg_caps() returns an
> > SG caps structure with the maximum number and size of SG segments
> > that the given channel can handle.
> Okay this sounds much better :-)
>
> few points though:
> - you added API for caps, but is actually calculating for given configuration
> the max allowed range. IMHO that is not caps, perhaps renaming to get_max_sg
> /some_better_name would be more apt.
I went with get_slave_sg_limits(), seemed pretty descriptive. Just
posted v4 with that change.
> - Still I like the idea of caps, but it should give H/W support capablity. If
> you want to add that, pls develop on same line...
Ok, seems like a good separate submission.
-Matt
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v3 1/3] dmaengine: add dma_get_slave_sg_caps()
@ 2013-03-06 19:58 ` Matt Porter
0 siblings, 0 replies; 12+ messages in thread
From: Matt Porter @ 2013-03-06 19:58 UTC (permalink / raw)
To: Vinod Koul
Cc: Dan Williams, Chris Ball, Grant Likely,
Linux DaVinci Kernel List, Linux Kernel Mailing List,
Linux MMC List
On Tue, Feb 12, 2013 at 05:08:44PM +0000, Vinod Koul wrote:
> On Mon, Feb 04, 2013 at 02:47:02PM -0500, Matt Porter wrote:
> > Add a dmaengine API to retrieve slave SG transfer capabilities.
> >
> > The API is optionally implemented by dmaengine drivers and when
> > unimplemented will return a NULL pointer. A client driver using
> > this API provides the required dma channel, address width, and
> > burst size of the transfer. dma_get_slave_sg_caps() returns an
> > SG caps structure with the maximum number and size of SG segments
> > that the given channel can handle.
> Okay this sounds much better :-)
>
> few points though:
> - you added API for caps, but is actually calculating for given configuration
> the max allowed range. IMHO that is not caps, perhaps renaming to get_max_sg
> /some_better_name would be more apt.
I went with get_slave_sg_limits(), seemed pretty descriptive. Just
posted v4 with that change.
> - Still I like the idea of caps, but it should give H/W support capablity. If
> you want to add that, pls develop on same line...
Ok, seems like a good separate submission.
-Matt
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2013-03-06 19:57 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-04 19:47 [PATCH v3 0/3] dmaengine: add slave sg transfer capabilities api Matt Porter
2013-02-04 19:47 ` Matt Porter
2013-02-04 19:47 ` [PATCH v3 1/3] dmaengine: add dma_get_slave_sg_caps() Matt Porter
2013-02-04 19:47 ` Matt Porter
2013-02-12 17:08 ` Vinod Koul
2013-02-12 17:08 ` Vinod Koul
[not found] ` <8b3455d3f1aa42818e917d47fd993ea1@DFLE72.ent.ti.com>
2013-03-06 19:58 ` Matt Porter
2013-03-06 19:58 ` Matt Porter
2013-02-04 19:47 ` [PATCH v3 2/3] dma: edma: add device_slave_sg_caps() support Matt Porter
2013-02-04 19:47 ` Matt Porter
2013-02-04 19:47 ` [PATCH v3 3/3] mmc: davinci: get SG segment limits with dma_get_slave_sg_caps() Matt Porter
2013-02-04 19:47 ` Matt Porter
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.