From: Ludovic Barre <redacted>
This patch internalizes the dma_inprogress into mmci dma interfaces.
This allows to simplify and prepare the next dma callbacks
for mmci host ops. __dma_inprogress is called in mmci_dma_data_error
and mmci_dma_finalize.
Signed-off-by: Ludovic Barre <redacted>
---
drivers/mmc/host/mmci.c | 16 ++++++++++------
drivers/mmc/host/mmci.h | 4 +---
2 files changed, 11 insertions(+), 9 deletions(-)
@@ -512,6 +515,9 @@ static void mmci_dma_finalize(struct mmci_host *host, struct mmc_data *data)u32status;inti;+if(!__dma_inprogress(dmae))+return;+/* Wait up to 1ms for the DMA to complete */for(i=0;;i++){status=readl(host->base+MMCISTATUS);
@@ -903,8 +909,7 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,u32remain,success;/* Terminate the DMA transfer */-if(dma_inprogress(host))-mmci_dma_data_error(host);+mmci_dma_data_error(host);/**Calculatehowfarweareintothetransfer.Notethat
On 1 August 2018 at 11:36, Ludovic Barre [off-list ref] wrote:
From: Ludovic Barre <redacted>
This patch internalizes the dma_inprogress into mmci dma interfaces.
This allows to simplify and prepare the next dma callbacks
for mmci host ops. __dma_inprogress is called in mmci_dma_data_error
and mmci_dma_finalize.
Signed-off-by: Ludovic Barre <redacted>
@@ -651,22 +684,21 @@ static int __mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data,return-ENOMEM;}-staticinlineintmmci_dma_prepare_data(structmmci_host*host,-structmmc_data*data,-boolnext)+intmmci_dmae_prepare_data(structmmci_host*host,+structmmc_data*data,boolnext){structdmaengine_priv*dmae=host->dma_priv;structdmaengine_next*nd=&dmae->next_data;if(next)-return__mmci_dma_prep_data(host,data,&nd->dma_chan,+return__mmci_dmae_prep_data(host,data,&nd->dma_chan,&nd->dma_desc);/* Check if next job is already prepared. */if(dmae->dma_current&&dmae->dma_desc_current)return0;/* No job were prepared thus do it now. */-return__mmci_dma_prep_data(host,data,&dmae->dma_current,+return__mmci_dmae_prep_data(host,data,&dmae->dma_current,&dmae->dma_desc_current);}
@@ -676,7 +708,7 @@ static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)structmmc_data*data=host->data;intret;-ret=mmci_dma_prepare_data(host,host->data,false);+ret=mmci_prepare_data(host,host->data,false);if(ret)returnret;
@@ -769,10 +779,13 @@ static void mmci_post_request(struct mmc_host *mmc, struct mmc_request *mrq,next->dma_desc=NULL;next->dma_chan=NULL;-data->host_cookie=0;}}+staticstructmmci_host_opsmmci_variant_ops={+.prepare_data=mmci_dmae_prepare_data,+.unprepare_data=mmci_dmae_unprepare_data,+};#else/* Blank functions if the DMA engine is not available */staticvoidmmci_get_next_data(structmmci_host*host,structmmc_data*data)
@@ -802,11 +815,42 @@ static inline int mmci_dma_start_data(struct mmci_host *host, unsigned int datacreturn-ENOSYS;}-#define mmci_pre_request NULL-#define mmci_post_request NULL-+staticstructmmci_host_opsmmci_variant_ops={};#endif+voidmmci_variant_init(structmmci_host*host)+{+host->ops=&mmci_variant_ops;+}++staticvoidmmci_pre_request(structmmc_host*mmc,structmmc_request*mrq)+{+structmmci_host*host=mmc_priv(mmc);+structmmc_data*data=mrq->data;++if(!data)+return;++WARN_ON(data->host_cookie);++if(mmci_validate_data(host,data))+return;++mmci_prepare_data(host,data,true);+}++staticvoidmmci_post_request(structmmc_host*mmc,structmmc_request*mrq,+interr)+{+structmmci_host*host=mmc_priv(mmc);+structmmc_data*data=mrq->data;++if(!data||!data->host_cookie)+return;++mmci_unprepare_data(host,data,err);+}+staticvoidmmci_start_data(structmmci_host*host,structmmc_data*data){structvariant_data*variant=host->variant;
I think we need to agree on naming rules for functions, as I think
this becomes a bit hard to follow when you decide to rename and pick
new names.
First, let's strive towards keeping existing names and in cases when a
subset of a function is re-used and called from the original function,
then name it with the same name, but add "__" or "_" as prefixes.
So for this one it should be:
mmci_dma_prep_data()
_mmci_dma_prep_data()
__mmci_dma_prep_data().
That should also decrease the number lines of code you need to change
and thus also make the review easier. Can you please try this?
+{
+ int err;
+
+ if (!host->ops || !host->ops->prepare_data)
+ return 0;
Is the host->ops optional and so also the ->prepare_data() callback in it?
Ahh, now I see why you need the mmci_host_ops to be optional, earlier above.
However, I have been thinking on what granularity we should pick for
the mmci host ops callbacks. Honestly I am not sure, but let me
through out an idea and see what you think about it.
So, having callbacks for dealing with dma_map|unmap() kind of
operations, becomes rather fine-grained and not very flexible.
Instead, what do you think of allowing the variant init function to
dynamically assign the ->pre_req() and the ->post_req() callbacks in
the struct mmc_host_ops. Common mmci functions to manage these
operations can instead be shared via mmci.h and called by the
variants.
The point is, following that scheme may improve flexibility, but
possibly also decrease the number of needed mmci specific host ops
callbacks, don't you think?
From: Ludovic Barre <redacted>
This patch creates a generic mmci_dma_setup which calls
dma_setup callback and manages common next_cookie.
This patch is needed for sdmmc variant which has a different
dma settings.
Signed-off-by: Ludovic Barre <redacted>
---
drivers/mmc/host/mmci.c | 25 +++++++++++++------------
drivers/mmc/host/mmci.h | 1 +
drivers/mmc/host/mmci_qcom_dml.c | 2 ++
3 files changed, 16 insertions(+), 12 deletions(-)
@@ -488,9 +499,6 @@ static int mmci_dma_setup(struct mmci_host *host)dmae->dma_tx_channel=dma_request_slave_channel(mmc_dev(host->mmc),"tx");-/* initialize pre request cookie */-host->next_cookie=1;-/**IfonlyanRXchannelisspecified,thedriverwill*attempttouseitbidirectionally,howeverifitis
@@ -531,9 +539,6 @@ static int mmci_dma_setup(struct mmci_host *host)host->mmc->max_seg_size=max_seg_size;}-if(host->ops&&host->ops->dma_setup)-returnhost->ops->dma_setup(host);-return0;}
@@ -793,14 +798,10 @@ static struct mmci_host_ops mmci_variant_ops = {.prepare_data=mmci_dmae_prepare_data,.unprepare_data=mmci_dmae_unprepare_data,.get_next_data=mmci_dmae_get_next_data,+.dma_setup=mmci_dmae_setup,};#else/* Blank functions if the DMA engine is not available */-staticinlineintmmci_dma_setup(structmmci_host*host)-{-return0;-}-staticinlinevoidmmci_dma_release(structmmci_host*host){}
@@ -415,6 +415,38 @@ void mmci_dma_release(struct mmci_host *host)host->ops->dma_release(host);}+intmmci_dma_start(structmmci_host*host,unsignedintdatactrl)+{+structmmc_data*data=host->data;+intret;++ret=mmci_prepare_data(host,data,false);+if(ret)+returnret;++if(!host->ops||!host->ops->dma_start)+return-EINVAL;++/* Okay, go for it. */+dev_vdbg(mmc_dev(host->mmc),+"Submit MMCI DMA job, sglen %d blksz %04x blks %04x flags %08x\n",+data->sg_len,data->blksz,data->blocks,data->flags);++host->ops->dma_start(host,&datactrl);++/* Trigger the DMA transfer */+mmci_write_datactrlreg(host,datactrl);++/*+*LettheMMCIsaywhenthedataisendedandit'stime+*tofirenextDMArequest.Whenthathappens,MMCIwill+*callmmci_data_end()+*/+writel(readl(host->base+MMCIMASK0)|MCI_DATAENDMASK,+host->base+MMCIMASK0);+return0;+}+staticvoidmmci_request_end(structmmci_host*host,structmmc_request*mrq){
@@ -721,20 +753,11 @@ int mmci_dmae_prepare_data(struct mmci_host *host,&dmae->dma_desc_current);}-staticintmmci_dma_start_data(structmmci_host*host,unsignedintdatactrl)+intmmci_dmae_start(structmmci_host*host,unsignedint*datactrl){structdmaengine_priv*dmae=host->dma_priv;structmmc_data*data=host->data;-intret;--ret=mmci_prepare_data(host,host->data,false);-if(ret)-returnret;-/* Okay, go for it. */-dev_vdbg(mmc_dev(host->mmc),-"Submit MMCI DMA job, sglen %d blksz %04x blks %04x flags %08x\n",-data->sg_len,data->blksz,data->blocks,data->flags);dmae->dma_in_progress=true;dmaengine_submit(dmae->dma_desc_current);dma_async_issue_pending(dmae->dma_current);
@@ -742,18 +765,8 @@ static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)if(host->variant->qcom_dml)dml_start_xfer(host,data);-datactrl|=MCI_DPSM_DMAENABLE;--/* Trigger the DMA transfer */-mmci_write_datactrlreg(host,datactrl);+*datactrl|=MCI_DPSM_DMAENABLE;-/*-*LettheMMCIsaywhenthedataisendedandit'stime-*tofirenextDMArequest.Whenthathappens,MMCIwill-*callmmci_data_end()-*/-writel(readl(host->base+MMCIMASK0)|MCI_DATAENDMASK,-host->base+MMCIMASK0);return0;}
@@ -806,6 +819,7 @@ static struct mmci_host_ops mmci_variant_ops = {.get_next_data=mmci_dmae_get_next_data,.dma_setup=mmci_dmae_setup,.dma_release=mmci_dmae_release,+.dma_start=mmci_dmae_start,};#else/* Blank functions if the DMA engine is not available */
@@ -820,14 +826,10 @@ static struct mmci_host_ops mmci_variant_ops = {.dma_setup=mmci_dmae_setup,.dma_release=mmci_dmae_release,.dma_start=mmci_dmae_start,+.dma_finalize=mmci_dmae_finalize,};#else/* Blank functions if the DMA engine is not available */-staticinlinevoidmmci_dma_finalize(structmmci_host*host,-structmmc_data*data)-{-}-staticinlinevoidmmci_dma_data_error(structmmci_host*host){}
From: Ludovic Barre <redacted>
This patch introduces dma_priv pointer to define specific
needs for each dma engine. This patch is needed to prepare
sdmmc variant with internal dma which not use dmaengine API.
Signed-off-by: Ludovic Barre <redacted>
---
drivers/mmc/host/mmci.c | 165 +++++++++++++++++++++++++--------------
drivers/mmc/host/mmci.h | 20 +----
drivers/mmc/host/mmci_qcom_dml.c | 6 +-
3 files changed, 112 insertions(+), 79 deletions(-)
@@ -497,25 +528,28 @@ static void __mmci_dma_unmap(struct mmci_host *host, struct mmc_data *data)staticvoidmmci_dma_data_error(structmmci_host*host){-if(!__dma_inprogress(host))+structdmaengine_priv*dmae=host->dma_priv;++if(!__dmae_inprogress(dmae))return;dev_err(mmc_dev(host->mmc),"error during DMA transfer!\n");-dmaengine_terminate_all(host->dma_current);-host->dma_in_progress=false;-host->dma_current=NULL;-host->dma_desc_current=NULL;+dmaengine_terminate_all(dmae->dma_current);+dmae->dma_in_progress=false;+dmae->dma_current=NULL;+dmae->dma_desc_current=NULL;host->data->host_cookie=0;-__mmci_dma_unmap(host,host->data);+__mmci_dmae_unmap(host,host->data);}staticvoidmmci_dma_finalize(structmmci_host*host,structmmc_data*data){+structdmaengine_priv*dmae=host->dma_priv;u32status;inti;-if(!__dma_inprogress(dmae))+if(!__dmae_inprogress(dmae))return;/* Wait up to 1ms for the DMA to complete */
@@ -577,10 +612,10 @@ static int __mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data,if(data->flags&MMC_DATA_READ){conf.direction=DMA_DEV_TO_MEM;-chan=host->dma_rx_channel;+chan=dmae->dma_rx_channel;}else{conf.direction=DMA_MEM_TO_DEV;-chan=host->dma_tx_channel;+chan=dmae->dma_tx_channel;}/* If there's no DMA channel, fall back to PIO */
@@ -620,26 +655,31 @@ static int __mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data,staticinlineintmmci_dma_prep_data(structmmci_host*host,structmmc_data*data){+structdmaengine_priv*dmae=host->dma_priv;+/* Check if next job is already prepared. */-if(host->dma_current&&host->dma_desc_current)+if(dmae->dma_current&&dmae->dma_desc_current)return0;/* No job were prepared thus do it now. */-return__mmci_dma_prep_data(host,data,&host->dma_current,-&host->dma_desc_current);+return__mmci_dma_prep_data(host,data,&dmae->dma_current,+&dmae->dma_desc_current);}staticinlineintmmci_dma_prep_next(structmmci_host*host,structmmc_data*data){-structmmci_host_next*nd=&host->next_data;+structdmaengine_priv*dmae=host->dma_priv;+structdmaengine_next*nd=&dmae->next_data;+return__mmci_dma_prep_data(host,data,&nd->dma_chan,&nd->dma_desc);}staticintmmci_dma_start_data(structmmci_host*host,unsignedintdatactrl){-intret;+structdmaengine_priv*dmae=host->dma_priv;structmmc_data*data=host->data;+intret;ret=mmci_dma_prep_data(host,host->data);if(ret)
On 1 August 2018 at 11:36, Ludovic Barre [off-list ref] wrote:
From: Ludovic Barre <redacted>
This patch introduces dma_priv pointer to define specific
needs for each dma engine. This patch is needed to prepare
sdmmc variant with internal dma which not use dmaengine API.
Overall this looks good, however a couple a few things below, mostly nitpicks.
I would rather rename this struct to something along the lines of
"mmci_dma_next", that should follow how most of the data structures
are named in mmci.
For these two, I think you should remove the "dma_" prefix from their
names. At least to me, it's of obvious they are about dma if they are
part of a struct used (and named) used solely for that purpose.
How about naming this to mmci_dma_inprogress() instead?
BTW, in general it looks like you are a bit fond of using "__" as
function name prefix for internally called functions. Please try to
avoid that, but rather try to pick names that explains what the
functions do.
quoted hunk
+
+static int mmci_dma_setup(struct mmci_host *host)
{
const char *rxname, *txname;
+ struct dmaengine_priv *dmae;
- host->dma_rx_channel = dma_request_slave_channel(mmc_dev(host->mmc), "rx");
- host->dma_tx_channel = dma_request_slave_channel(mmc_dev(host->mmc), "tx");
+ dmae = devm_kzalloc(mmc_dev(host->mmc), sizeof(*dmae), GFP_KERNEL);
+ if (!dmae)
+ return -ENOMEM;
+
+ host->dma_priv = dmae;
+
+ dmae->dma_rx_channel = dma_request_slave_channel(mmc_dev(host->mmc),
+ "rx");
+ dmae->dma_tx_channel = dma_request_slave_channel(mmc_dev(host->mmc),
+ "tx");
/* initialize pre request cookie */
- host->next_data.cookie = 1;
+ dmae->next_data.cookie = 1;
/*
* If only an RX channel is specified, the driver will
* attempt to use it bidirectionally, however if it is
* is specified but cannot be located, DMA will be disabled.
*/
- if (host->dma_rx_channel && !host->dma_tx_channel)
- host->dma_tx_channel = host->dma_rx_channel;
+ if (dmae->dma_rx_channel && !dmae->dma_tx_channel)
+ dmae->dma_tx_channel = dmae->dma_rx_channel;
- if (host->dma_rx_channel)
- rxname = dma_chan_name(host->dma_rx_channel);
+ if (dmae->dma_rx_channel)
+ rxname = dma_chan_name(dmae->dma_rx_channel);
else
rxname = "none";
- if (host->dma_tx_channel)
- txname = dma_chan_name(host->dma_tx_channel);
+ if (dmae->dma_tx_channel)
+ txname = dma_chan_name(dmae->dma_tx_channel);
else
txname = "none";
@@ -450,15 +476,15 @@ static void mmci_dma_setup(struct mmci_host *host) * Limit the maximum segment size in any SG entry according to * the parameters of the DMA engine device. */- if (host->dma_tx_channel) {- struct device *dev = host->dma_tx_channel->device->dev;+ if (dmae->dma_tx_channel) {+ struct device *dev = dmae->dma_tx_channel->device->dev; unsigned int max_seg_size = dma_get_max_seg_size(dev); if (max_seg_size < host->mmc->max_seg_size) host->mmc->max_seg_size = max_seg_size; }- if (host->dma_rx_channel) {- struct device *dev = host->dma_rx_channel->device->dev;+ if (dmae->dma_rx_channel) {+ struct device *dev = dmae->dma_rx_channel->device->dev; unsigned int max_seg_size = dma_get_max_seg_size(dev); if (max_seg_size < host->mmc->max_seg_size)
I agree that converting the ->dma_setup() callback to return an int makes sense.
However, please make that a separate change and while doing that,
don't forget to implement the error path, as that is missing here.
@@ -409,6 +409,12 @@ int mmci_dma_setup(struct mmci_host *host)returnhost->ops->dma_setup(host);}+voidmmci_dma_release(structmmci_host*host)+{+if(host->ops&&host->ops->dma_release)+host->ops->dma_release(host);+}+staticvoidmmci_request_end(structmmci_host*host,structmmc_request*mrq){
@@ -546,7 +552,7 @@ int mmci_dmae_setup(struct mmci_host *host)*Thisisusedinorsoinlineit*soitcanbediscarded.*/-staticinlinevoidmmci_dma_release(structmmci_host*host)+voidmmci_dmae_release(structmmci_host*host){structdmaengine_priv*dmae=host->dma_priv;
@@ -799,13 +805,10 @@ static struct mmci_host_ops mmci_variant_ops = {.unprepare_data=mmci_dmae_unprepare_data,.get_next_data=mmci_dmae_get_next_data,.dma_setup=mmci_dmae_setup,+.dma_release=mmci_dmae_release,};#else/* Blank functions if the DMA engine is not available */-staticinlinevoidmmci_dma_release(structmmci_host*host)-{-}-staticinlinevoidmmci_dma_finalize(structmmci_host*host,structmmc_data*data){
@@ -827,13 +833,9 @@ static struct mmci_host_ops mmci_variant_ops = {.dma_release=mmci_dmae_release,.dma_start=mmci_dmae_start,.dma_finalize=mmci_dmae_finalize,+.dma_error=mmci_dmae_error,};#else-/* Blank functions if the DMA engine is not available */-staticinlinevoidmmci_dma_data_error(structmmci_host*host)-{-}-staticstructmmci_host_opsmmci_variant_ops={};#endif
@@ -1011,7 +1013,7 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,u32remain,success;/* Terminate the DMA transfer */-mmci_dma_data_error(host);+mmci_dma_error(host);/**Calculatehowfarweareintothetransfer.Notethat
@@ -1157,7 +1159,7 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,if((!sbc&&!cmd->data)||cmd->error){if(host->data){/* Terminate the DMA transfer */-mmci_dma_data_error(host);+mmci_dma_error(host);mmci_stop_data(host);}
From: Ludovic Barre <redacted>
This patch internalizes the management of dma map/unmap into
mmci dma interfaces. This allows to simplify and prepare the next dma
callbacks for mmci host ops.
mmci_dma_unmap was called in mmci_data_irq & mmci_cmd_irq functions
and can be integrated in mmci_dma_data_error.
Signed-off-by: Ludovic Barre <redacted>
---
drivers/mmc/host/mmci.c | 44 +++++++++++++++++++-------------------------
1 file changed, 19 insertions(+), 25 deletions(-)
On 1 August 2018 at 11:36, Ludovic Barre [off-list ref] wrote:
quoted hunk
From: Ludovic Barre <redacted>
This patch internalizes the management of dma map/unmap into
mmci dma interfaces. This allows to simplify and prepare the next dma
callbacks for mmci host ops.
mmci_dma_unmap was called in mmci_data_irq & mmci_cmd_irq functions
and can be integrated in mmci_dma_data_error.
Signed-off-by: Ludovic Barre <redacted>
---
drivers/mmc/host/mmci.c | 44 +++++++++++++++++++-------------------------
1 file changed, 19 insertions(+), 25 deletions(-)
The renaming of the function seems irrelevant to this change. Can you
please keep the existing name?
[...]
Besides the minor thing above, this looks good to me!
Kind regards
Uffe
@@ -738,12 +746,11 @@ static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)return0;}-staticvoidmmci_get_next_data(structmmci_host*host,structmmc_data*data)+voidmmci_dmae_get_next_data(structmmci_host*host,structmmc_data*data){structdmaengine_priv*dmae=host->dma_priv;structdmaengine_next*next=&dmae->next_data;-WARN_ON(data->host_cookie&&data->host_cookie!=host->next_cookie);WARN_ON(!data->host_cookie&&(next->dma_desc||next->dma_chan));dmae->dma_desc_current=next->dma_desc;
@@ -785,13 +792,10 @@ void mmci_dmae_unprepare_data(struct mmci_host *host,staticstructmmci_host_opsmmci_variant_ops={.prepare_data=mmci_dmae_prepare_data,.unprepare_data=mmci_dmae_unprepare_data,+.get_next_data=mmci_dmae_get_next_data,};#else/* Blank functions if the DMA engine is not available */-staticvoidmmci_get_next_data(structmmci_host*host,structmmc_data*data)-{-}-staticinlineintmmci_dma_setup(structmmci_host*host){return0;
From: Ludovic Barre <redacted>
This patch merges the prepare data functions.
This allows to define a single access to prepare data service.
This prepares integration for mmci host ops.
Signed-off-by: Ludovic Barre <redacted>
---
drivers/mmc/host/mmci.c | 22 +++++++++-------------
1 file changed, 9 insertions(+), 13 deletions(-)
@@ -651,11 +651,16 @@ static int __mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data,return-ENOMEM;}-staticinlineintmmci_dma_prep_data(structmmci_host*host,-structmmc_data*data)+staticinlineintmmci_dma_prepare_data(structmmci_host*host,+structmmc_data*data,+boolnext){structdmaengine_priv*dmae=host->dma_priv;+structdmaengine_next*nd=&dmae->next_data;+if(next)+return__mmci_dma_prep_data(host,data,&nd->dma_chan,+&nd->dma_desc);/* Check if next job is already prepared. */if(dmae->dma_current&&dmae->dma_desc_current)return0;
@@ -665,22 +670,13 @@ static inline int mmci_dma_prep_data(struct mmci_host *host,&dmae->dma_desc_current);}-staticinlineintmmci_dma_prep_next(structmmci_host*host,-structmmc_data*data)-{-structdmaengine_priv*dmae=host->dma_priv;-structdmaengine_next*nd=&dmae->next_data;--return__mmci_dma_prep_data(host,data,&nd->dma_chan,&nd->dma_desc);-}-staticintmmci_dma_start_data(structmmci_host*host,unsignedintdatactrl){structdmaengine_priv*dmae=host->dma_priv;structmmc_data*data=host->data;intret;-ret=mmci_dma_prep_data(host,host->data);+ret=mmci_dma_prepare_data(host,host->data,false);if(ret)returnret;
On 1 August 2018 at 11:36, Ludovic Barre [off-list ref] wrote:
quoted hunk
From: Ludovic Barre <redacted>
This patch merges the prepare data functions.
This allows to define a single access to prepare data service.
This prepares integration for mmci host ops.
Signed-off-by: Ludovic Barre <redacted>
---
drivers/mmc/host/mmci.c | 22 +++++++++-------------
1 file changed, 9 insertions(+), 13 deletions(-)
From: Ludovic Barre <redacted>
This patch fixes qcom dma issue during mmci init.
Like init callback of qcom variant is not set, the qcom dma
is not correctly initialized and fail while dma transfer
("buggy DMA detected. Taking evasive action").
Signed-off-by: Ludovic Barre <redacted>
---
drivers/mmc/host/mmci.c | 1 +
drivers/mmc/host/mmci.h | 1 +
2 files changed, 2 insertions(+)
On 1 August 2018 at 11:36, Ludovic Barre [off-list ref] wrote:
quoted hunk
From: Ludovic Barre <redacted>
This patch fixes qcom dma issue during mmci init.
Like init callback of qcom variant is not set, the qcom dma
is not correctly initialized and fail while dma transfer
("buggy DMA detected. Taking evasive action").
Signed-off-by: Ludovic Barre <redacted>
---
drivers/mmc/host/mmci.c | 1 +
drivers/mmc/host/mmci.h | 1 +
2 files changed, 2 insertions(+)
On 1 August 2018 at 11:36, Ludovic Barre [off-list ref] wrote:
From: Ludovic Barre <redacted>
This patch series prepares and adds callbacks for dma transfert at
mmci_host_ops. This series is composed of 3 parts:
-Internalize specific needs of legacy dmaengine.
-Create and setup dma_priv pointer
-Create generic callbacks which share some features
(like cookie...) and call specific needs
I have now reviewed part of this series and provided you with some
comments, but will stop at this point.
Overall, the comments are about renaming and picking better function
names. Those comments should be easy to address in a new version.
However, the other more important point is the number of variant
callbacks you are adding. It's of course a balance to pick the right
level, to get both flexibility but also to avoid open coding. In the
end we don't want to get too many callbacks, but then it's better to
share common mmci code for variants, through mmci.h.
Finally, I would like to see a patch on top adding the support for the
new ST variant, so I can see how the callbacks and changes really are
being used. Can you please add that?
This patch series must be applied on top of
"mmc: mmci: Add and implement a ->dma_setup() callback for qcom dml"
Ludovic Barre (14):
mmc: mmci: fix qcom dma issue during mmci init with new dma_setup
callback
mmc: mmci: internalize dma map/unmap into mmci dma functions
mmc: mmci: internalize dma_inprogress into mmci dma functions
mmc: mmci: introduce dma_priv pointer to mmci_host
mmc: mmci: move mmci next cookie to mci host
mmc: mmci: merge prepare data functions
mmc: mmci: add prepare/unprepare_data callbacks
mmc: mmci: add get_next_data callback
mmc: mmci: modify dma_setup callback
mmc: mmci: add dma_release callback
mmc: mmci: add dma_start callback
mmc: mmci: add dma_finalize callback
mmc: mmci: add dma_error callback
mmc: mmci: add validate_data callback
drivers/mmc/host/mmci.c | 458 ++++++++++++++++++++++++---------------
drivers/mmc/host/mmci.h | 45 ++--
drivers/mmc/host/mmci_qcom_dml.c | 15 +-
3 files changed, 322 insertions(+), 196 deletions(-)
--
2.7.4
On 1 August 2018 at 11:36, Ludovic Barre [off-list ref] wrote:
quoted
From: Ludovic Barre <redacted>
This patch series prepares and adds callbacks for dma transfert at
mmci_host_ops. This series is composed of 3 parts:
-Internalize specific needs of legacy dmaengine.
-Create and setup dma_priv pointer
-Create generic callbacks which share some features
(like cookie...) and call specific needs
I have now reviewed part of this series and provided you with some
comments, but will stop at this point.
thanks for your review
Overall, the comments are about renaming and picking better function
names. Those comments should be easy to address in a new version.
yes, there is no problem for the naming, I will change following your
recommendations.
However, the other more important point is the number of variant
callbacks you are adding. It's of course a balance to pick the right
level, to get both flexibility but also to avoid open coding. In the
end we don't want to get too many callbacks, but then it's better to
share common mmci code for variants, through mmci.h.
Finally, I would like to see a patch on top adding the support for the
new ST variant, so I can see how the callbacks and changes really are
being used. Can you please add that?
yes, I prepare a patch with sdmmc variant to show how callbacks are used.
About comment on patch 07/14:
> So, having callbacks for dealing with dma_map|unmap() kind of
> operations, becomes rather fine-grained and not very flexible.
> Instead, what do you think of allowing the variant init function to
> dynamically assign the ->pre_req() and the ->post_req() callbacks in
> the struct mmc_host_ops. Common mmci functions to manage these
> operations can instead be shared via mmci.h and called by the
> variants.
I think we have the same goal or idea, regroup the common needs to avoid
too much specific drift.
I will try to describe the functions which are commons and the link to
specific mmci_host_ops callbacks.
(I use function names of this series, but it's just for this example)
commons function used by mmci core:
-mmci_pre_request:
check data and cookie, call common mmci_validate_data
and mmci_prepare_data.
-mmci_post_request:
check data and cookie then call common mmci_unprepare_data
-mmci_validate_data:
check the common constraint of variants, call specific
validate_data if defined.
-mmci_prepare_data:
setup common next cookie, call specific prepare data if defined
-mmci_unprepare_data:
clear the common cookie, call specific unprepare data if defined
-mmci_get_next_data:
check cookie, call specific get_next_data if defined
-mmci_dma_setup:
initialize common next_cookie, call specific dma_setup if defined
-mmci_dma_release
just call dma_release if defined
-mmci_dma_start
call common prepare data if not yet done (by next)
call specific dma_start
write common registers to start transfer and setup mmci mask
-mmci_dma_finalize:
just call dma_finalize if defined
-mmci_dma_error
just call dma_error if defined
mmci_host_ops specific:
struct mmci_host_ops
validate_data: could be use to check specific constraint of variant.
sdmmc has constraints on base & size for each element
excepted the last element which has no constraint on
size.
prepare_data: specific needs to prepare current or next data request.
mmci: dma_map_sg on channel, use dmaengine api
"dmaengine_prep_slave_sg" to queue a transfer
sdmmc: dma_map_sg on sdmmc device and prepare the link
list of internal dma
unprepare_data: specific needs to unprepare the data of request
mmci: dma_unmap_sg on channel, use dmaengine api to
terminate transfert.
sdmmc: just unmap on sdmmc device.
get_next_data: manage specific needs to move on next data
mmci: get next dmaengine descriptor and channel
sdmmc: today, nothing
dma_setup: setup specific need if you use a Direct Memory Access
mmci: use dmaengine api to request slave channel.
sdmmc: alloc memory for link list, and define specific
mmc->max_segs and mmc->max_seg_size.
dma_release: release specific resource if you use a Direct Memory
access.
mmci: use dmaengine api to release channel
sdmmc: nothing
dma_start: set specific needs to start dma request
mmci: use dmaengine api to submit and pending a dma
transfert.
sdmmc: set specific sdmmc registers to start an internal
dma transfert
dma_finalize: set specific needs to finalize a request
mmci: specific check on fifo status and
channel/descriptor management.
sdmmc: just clear a specific register of sdmmc
dma_error: specific error management.
mmci: dmaengine api to terminate a transfer
sdmmc: nothing
BR
Ludo
quoted
This patch series must be applied on top of
"mmc: mmci: Add and implement a ->dma_setup() callback for qcom dml"
Ludovic Barre (14):
mmc: mmci: fix qcom dma issue during mmci init with new dma_setup
callback
mmc: mmci: internalize dma map/unmap into mmci dma functions
mmc: mmci: internalize dma_inprogress into mmci dma functions
mmc: mmci: introduce dma_priv pointer to mmci_host
mmc: mmci: move mmci next cookie to mci host
mmc: mmci: merge prepare data functions
mmc: mmci: add prepare/unprepare_data callbacks
mmc: mmci: add get_next_data callback
mmc: mmci: modify dma_setup callback
mmc: mmci: add dma_release callback
mmc: mmci: add dma_start callback
mmc: mmci: add dma_finalize callback
mmc: mmci: add dma_error callback
mmc: mmci: add validate_data callback
drivers/mmc/host/mmci.c | 458 ++++++++++++++++++++++++---------------
drivers/mmc/host/mmci.h | 45 ++--
drivers/mmc/host/mmci_qcom_dml.c | 15 +-
3 files changed, 322 insertions(+), 196 deletions(-)
--
2.7.4
On 5 September 2018 at 11:13, Ludovic BARRE [off-list ref] wrote:
On 09/04/2018 12:00 PM, Ulf Hansson wrote:
quoted
On 1 August 2018 at 11:36, Ludovic Barre [off-list ref] wrote:
quoted
From: Ludovic Barre <redacted>
This patch series prepares and adds callbacks for dma transfert at
mmci_host_ops. This series is composed of 3 parts:
-Internalize specific needs of legacy dmaengine.
-Create and setup dma_priv pointer
-Create generic callbacks which share some features
(like cookie...) and call specific needs
I have now reviewed part of this series and provided you with some
comments, but will stop at this point.
thanks for your review
quoted
Overall, the comments are about renaming and picking better function
names. Those comments should be easy to address in a new version.
yes, there is no problem for the naming, I will change following your
recommendations.
quoted
However, the other more important point is the number of variant
callbacks you are adding. It's of course a balance to pick the right
level, to get both flexibility but also to avoid open coding. In the
end we don't want to get too many callbacks, but then it's better to
share common mmci code for variants, through mmci.h.
Finally, I would like to see a patch on top adding the support for the
new ST variant, so I can see how the callbacks and changes really are
being used. Can you please add that?
yes, I prepare a patch with sdmmc variant to show how callbacks are used.
About comment on patch 07/14:
quoted
So, having callbacks for dealing with dma_map|unmap() kind of
operations, becomes rather fine-grained and not very flexible.
Instead, what do you think of allowing the variant init function to
dynamically assign the ->pre_req() and the ->post_req() callbacks in
the struct mmc_host_ops. Common mmci functions to manage these
operations can instead be shared via mmci.h and called by the
variants.
I think we have the same goal or idea, regroup the common needs to avoid
too much specific drift.
I will try to describe the functions which are commons and the link to
specific mmci_host_ops callbacks.
(I use function names of this series, but it's just for this example)
commons function used by mmci core:
-mmci_pre_request:
check data and cookie, call common mmci_validate_data
and mmci_prepare_data.
-mmci_post_request:
check data and cookie then call common mmci_unprepare_data
-mmci_validate_data:
check the common constraint of variants, call specific
validate_data if defined.
-mmci_prepare_data:
setup common next cookie, call specific prepare data if defined
-mmci_unprepare_data:
clear the common cookie, call specific unprepare data if defined
-mmci_get_next_data:
check cookie, call specific get_next_data if defined
-mmci_dma_setup:
initialize common next_cookie, call specific dma_setup if defined
-mmci_dma_release
just call dma_release if defined
-mmci_dma_start
call common prepare data if not yet done (by next)
call specific dma_start
write common registers to start transfer and setup mmci mask
-mmci_dma_finalize:
just call dma_finalize if defined
-mmci_dma_error
just call dma_error if defined
mmci_host_ops specific:
struct mmci_host_ops
validate_data: could be use to check specific constraint of variant.
sdmmc has constraints on base & size for each element
excepted the last element which has no constraint on
size.
prepare_data: specific needs to prepare current or next data request.
mmci: dma_map_sg on channel, use dmaengine api
"dmaengine_prep_slave_sg" to queue a transfer
sdmmc: dma_map_sg on sdmmc device and prepare the link
list of internal dma
unprepare_data: specific needs to unprepare the data of request
mmci: dma_unmap_sg on channel, use dmaengine api to
terminate transfert.
sdmmc: just unmap on sdmmc device.
get_next_data: manage specific needs to move on next data
mmci: get next dmaengine descriptor and channel
sdmmc: today, nothing
dma_setup: setup specific need if you use a Direct Memory Access
mmci: use dmaengine api to request slave channel.
sdmmc: alloc memory for link list, and define specific
mmc->max_segs and mmc->max_seg_size.
dma_release: release specific resource if you use a Direct Memory
access.
mmci: use dmaengine api to release channel
sdmmc: nothing
dma_start: set specific needs to start dma request
mmci: use dmaengine api to submit and pending a dma
transfert.
sdmmc: set specific sdmmc registers to start an internal
dma transfert
dma_finalize: set specific needs to finalize a request
mmci: specific check on fifo status and
channel/descriptor management.
sdmmc: just clear a specific register of sdmmc
dma_error: specific error management.
mmci: dmaengine api to terminate a transfer
sdmmc: nothing
Ludo, thanks for the detailed explanation and summary!
Following this, it looks like it makes sense to keep the callbacks as
on the level you have suggested. At least, I don't want to delay you
from getting this upstream, by just giving some vague ideas of how to
change the number of callbacks.
So, I am fine if you stick to the existing approach! Then, if we later
on realizes that it makes sense to share more common code through
mmci.h, to get rid of some callback, we can always do that on top.
[...]
Kind regards
Uffe