Message ID | 1396541886-10966-4-git-send-email-svarbanov@mm-sol.com (mailing list archive) |
---|---|
State | Superseded, archived |
Headers | show |
Nitworthy comments :). On Thu, Apr 03, 2014 at 07:18:00PM +0300, Stanimir Varbanov wrote: [..] > +++ b/drivers/crypto/qce/dma.c [..] > +int qce_dma_request(struct device *dev, struct qce_dma_data *dma) > +{ > + unsigned int memsize; > + void *va; > + int ret; > + > + dma->txchan = dma_request_slave_channel_reason(dev, "tx"); > + if (IS_ERR(dma->txchan)) { > + ret = PTR_ERR(dma->txchan); > + return ret; > + } > + > + dma->rxchan = dma_request_slave_channel_reason(dev, "rx"); > + if (IS_ERR(dma->rxchan)) { > + ret = PTR_ERR(dma->rxchan); > + goto error_rx; > + } > + > + memsize = QCE_RESULT_BUF_SZ + QCE_IGNORE_BUF_SZ; > + va = kzalloc(memsize, GFP_KERNEL); > + if (!va) { > + ret = -ENOMEM; > + goto error_nomem; > + } > + > + dma->result_buf = va; > + dma->ignore_buf = dma->result_buf + QCE_RESULT_BUF_SZ; > + > + return 0; > +error_nomem: > + if (!IS_ERR(dma->rxchan)) How could this condition ever be false? > + dma_release_channel(dma->rxchan); > +error_rx: > + if (!IS_ERR(dma->txchan)) Same here. > + dma_release_channel(dma->txchan); > + return ret; > +}
On Thu, Apr 03, 2014 at 06:18:00PM +0200, Stanimir Varbanov wrote: > This adds dmaengine and sg-list helper functions used by > other parts of the crypto driver. > > Signed-off-by: Stanimir Varbanov <svarbanov@mm-sol.com> > --- > drivers/crypto/qce/dma.c | 201 +++++++++++++++++++++++++++++++++++++++++++++++ > drivers/crypto/qce/dma.h | 57 ++++++++++++++ > 2 files changed, 258 insertions(+) > create mode 100644 drivers/crypto/qce/dma.c > create mode 100644 drivers/crypto/qce/dma.h More nitpicking, because everyone loves that.... > > diff --git a/drivers/crypto/qce/dma.c b/drivers/crypto/qce/dma.c > new file mode 100644 > index 000000000000..1bad958db2f9 > --- /dev/null > +++ b/drivers/crypto/qce/dma.c > @@ -0,0 +1,201 @@ [...] > +int qce_dma_request(struct device *dev, struct qce_dma_data *dma) > +{ > + unsigned int memsize; > + void *va; > + int ret; > + > + dma->txchan = dma_request_slave_channel_reason(dev, "tx"); > + if (IS_ERR(dma->txchan)) { > + ret = PTR_ERR(dma->txchan); > + return ret; You can just return PTR_ERR(dma->txchan) here, no need to set 'ret'. > + } > + > + dma->rxchan = dma_request_slave_channel_reason(dev, "rx"); > + if (IS_ERR(dma->rxchan)) { > + ret = PTR_ERR(dma->rxchan); > + goto error_rx; > + } > + > + memsize = QCE_RESULT_BUF_SZ + QCE_IGNORE_BUF_SZ; > + va = kzalloc(memsize, GFP_KERNEL); 'memsize' is only used here. Just pass 'QCE_RESULT_BUF_SZ + QCE_IGNORE_BUF_SZ' directly to kzalloc(). Additionally, is there some particular reason why we need to zero this memory? > + if (!va) { > + ret = -ENOMEM; > + goto error_nomem; > + } > + > + dma->result_buf = va; Is there some requirement that we don't set dma->result_buf on error? If not, we can discard the 'va' variable as well. > + dma->ignore_buf = dma->result_buf + QCE_RESULT_BUF_SZ; > + > + return 0; > +error_nomem: > + if (!IS_ERR(dma->rxchan)) > + dma_release_channel(dma->rxchan); > +error_rx: > + if (!IS_ERR(dma->txchan)) > + dma_release_channel(dma->txchan); > + return ret; > +} > + > +void qce_dma_release(struct qce_dma_data *dma) > +{ > + dma_release_channel(dma->txchan); > + dma_release_channel(dma->rxchan); > + kfree(dma->result_buf); > +} > + > +int qce_mapsg(struct device *dev, struct scatterlist *sg, unsigned int nents, > + enum dma_data_direction dir, bool chained) > +{ > + int err; > + > + if (chained) { > + while (sg) { > + err = dma_map_sg(dev, sg, 1, dir); > + if (!err) > + goto error; > + sg = scatterwalk_sg_next(sg); > + } > + } else { > + err = dma_map_sg(dev, sg, nents, dir); > + if (!err) > + goto error; > + } > + > + return nents; > +error: > + return -EFAULT; No need for this label, as there's no cleanup. Just return -EFAULT directly on error. > +} [...] > +struct scatterlist * > +qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl) > +{ > + struct scatterlist *sg = sgt->sgl, *sg_last = NULL; > + > + while (sg) { > + if (!sg_page(sg)) > + break; > + sg = sg_next(sg); > + } > + > + if (!sg) > + goto error; > + > + while (new_sgl && sg) { > + sg_set_page(sg, sg_page(new_sgl), new_sgl->length, > + new_sgl->offset); > + sg_last = sg; > + sg = sg_next(sg); > + new_sgl = sg_next(new_sgl); > + } > + > + if (new_sgl) > + goto error; > + > + return sg_last; > +error: > + return ERR_PTR(-EINVAL); No need for this label, as there's no cleanup. Just return ERR_PTR(-EINVAL) directly on error. > +} > + > +static int qce_dma_prep_sg(struct dma_chan *chan, struct scatterlist *sg, > + int nents, unsigned long flags, > + enum dma_transfer_direction dir, > + dma_async_tx_callback cb, void *cb_param) > +{ > + struct dma_async_tx_descriptor *desc; > + > + if (!sg || !nents) > + return -EINVAL; > + > + desc = dmaengine_prep_slave_sg(chan, sg, nents, dir, flags); > + if (!desc) > + return -EINVAL; > + > + desc->callback = cb; > + desc->callback_param = cb_param; > + dmaengine_submit(desc); Do we not care if there is an error here? dma_cookie_t cookie; ... cookie = dmaengine_submit(desc); return dma_submit_error(cookie); > + return 0; > +} [...] > diff --git a/drivers/crypto/qce/dma.h b/drivers/crypto/qce/dma.h > new file mode 100644 > index 000000000000..932b02fd8f25 > --- /dev/null > +++ b/drivers/crypto/qce/dma.h > @@ -0,0 +1,57 @@ > +/* > + * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 and > + * only version 2 as published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + */ > + > +#ifndef _DMA_H_ > +#define _DMA_H_ > + > +#define QCE_AUTHIV_REGS_CNT 16 > +#define QCE_AUTH_BYTECOUNT_REGS_CNT 4 > +#define QCE_CNTRIV_REGS_CNT 4 > + > +/* result dump format */ > +struct qce_result_dump { > + u32 auth_iv[QCE_AUTHIV_REGS_CNT]; > + u32 auth_byte_count[QCE_AUTH_BYTECOUNT_REGS_CNT]; > + u32 encr_cntr_iv[QCE_CNTRIV_REGS_CNT]; > + u32 status; > + u32 status2; > +}; > + > +#define QCE_IGNORE_BUF_SZ (2 * QCE_BAM_BURST_SIZE) QCE_BAM_BURST_SIZE is defined in common.h in 6/9. Either that file needs to be included from this one, or the definition needs to be moved. -- To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 04/03/2014 09:25 PM, Josh Cartwright wrote: > Nitworthy comments :). > > On Thu, Apr 03, 2014 at 07:18:00PM +0300, Stanimir Varbanov wrote: > [..] >> +++ b/drivers/crypto/qce/dma.c > [..] >> +int qce_dma_request(struct device *dev, struct qce_dma_data *dma) >> +{ >> + unsigned int memsize; >> + void *va; >> + int ret; >> + >> + dma->txchan = dma_request_slave_channel_reason(dev, "tx"); >> + if (IS_ERR(dma->txchan)) { >> + ret = PTR_ERR(dma->txchan); >> + return ret; >> + } >> + >> + dma->rxchan = dma_request_slave_channel_reason(dev, "rx"); >> + if (IS_ERR(dma->rxchan)) { >> + ret = PTR_ERR(dma->rxchan); >> + goto error_rx; >> + } >> + >> + memsize = QCE_RESULT_BUF_SZ + QCE_IGNORE_BUF_SZ; >> + va = kzalloc(memsize, GFP_KERNEL); >> + if (!va) { >> + ret = -ENOMEM; >> + goto error_nomem; >> + } >> + >> + dma->result_buf = va; >> + dma->ignore_buf = dma->result_buf + QCE_RESULT_BUF_SZ; >> + >> + return 0; >> +error_nomem: >> + if (!IS_ERR(dma->rxchan)) > > How could this condition ever be false? Good catch. This is a leftover after error path restructuring. Will fix it on next version.
Hi Courtney, Thanks for the comments! On 04/04/2014 02:15 AM, Courtney Cavin wrote: > On Thu, Apr 03, 2014 at 06:18:00PM +0200, Stanimir Varbanov wrote: >> This adds dmaengine and sg-list helper functions used by >> other parts of the crypto driver. >> >> Signed-off-by: Stanimir Varbanov <svarbanov@mm-sol.com> >> --- >> drivers/crypto/qce/dma.c | 201 +++++++++++++++++++++++++++++++++++++++++++++++ >> drivers/crypto/qce/dma.h | 57 ++++++++++++++ >> 2 files changed, 258 insertions(+) >> create mode 100644 drivers/crypto/qce/dma.c >> create mode 100644 drivers/crypto/qce/dma.h > > More nitpicking, because everyone loves that.... > >> >> diff --git a/drivers/crypto/qce/dma.c b/drivers/crypto/qce/dma.c >> new file mode 100644 >> index 000000000000..1bad958db2f9 >> --- /dev/null >> +++ b/drivers/crypto/qce/dma.c >> @@ -0,0 +1,201 @@ > [...] >> +int qce_dma_request(struct device *dev, struct qce_dma_data *dma) >> +{ >> + unsigned int memsize; >> + void *va; >> + int ret; >> + >> + dma->txchan = dma_request_slave_channel_reason(dev, "tx"); >> + if (IS_ERR(dma->txchan)) { >> + ret = PTR_ERR(dma->txchan); >> + return ret; > > You can just return PTR_ERR(dma->txchan) here, no need to set 'ret'. I think the idea was to have only one exit point from the function, never mind I will return from here. > >> + } >> + >> + dma->rxchan = dma_request_slave_channel_reason(dev, "rx"); >> + if (IS_ERR(dma->rxchan)) { >> + ret = PTR_ERR(dma->rxchan); >> + goto error_rx; >> + } >> + >> + memsize = QCE_RESULT_BUF_SZ + QCE_IGNORE_BUF_SZ; >> + va = kzalloc(memsize, GFP_KERNEL); > > 'memsize' is only used here. Just pass 'QCE_RESULT_BUF_SZ + > QCE_IGNORE_BUF_SZ' directly to kzalloc(). > The only reason to have "memsize" variable is to avoid carry over the new line. The compiler is smart enough to delete this variable. But this is a minor issue and I tend to agree with you. > Additionally, is there some particular reason why we need to zero this > memory? IMO, it makes sense when debugging some issue related to dma to this memory. > >> + if (!va) { >> + ret = -ENOMEM; >> + goto error_nomem; >> + } >> + >> + dma->result_buf = va; > > Is there some requirement that we don't set dma->result_buf on error? > If not, we can discard the 'va' variable as well. No, there is no such requirement, the error is fatal and driver will refuse to .probe. > >> + dma->ignore_buf = dma->result_buf + QCE_RESULT_BUF_SZ; >> + >> + return 0; >> +error_nomem: >> + if (!IS_ERR(dma->rxchan)) >> + dma_release_channel(dma->rxchan); >> +error_rx: >> + if (!IS_ERR(dma->txchan)) >> + dma_release_channel(dma->txchan); >> + return ret; >> +} >> + >> +void qce_dma_release(struct qce_dma_data *dma) >> +{ >> + dma_release_channel(dma->txchan); >> + dma_release_channel(dma->rxchan); >> + kfree(dma->result_buf); >> +} >> + >> +int qce_mapsg(struct device *dev, struct scatterlist *sg, unsigned int nents, >> + enum dma_data_direction dir, bool chained) >> +{ >> + int err; >> + >> + if (chained) { >> + while (sg) { >> + err = dma_map_sg(dev, sg, 1, dir); >> + if (!err) >> + goto error; >> + sg = scatterwalk_sg_next(sg); >> + } >> + } else { >> + err = dma_map_sg(dev, sg, nents, dir); >> + if (!err) >> + goto error; >> + } >> + >> + return nents; >> +error: >> + return -EFAULT; > > No need for this label, as there's no cleanup. Just return > -EFAULT directly on error. Sure, will do. > >> +} > [...] >> +struct scatterlist * >> +qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl) >> +{ >> + struct scatterlist *sg = sgt->sgl, *sg_last = NULL; >> + >> + while (sg) { >> + if (!sg_page(sg)) >> + break; >> + sg = sg_next(sg); >> + } >> + >> + if (!sg) >> + goto error; >> + >> + while (new_sgl && sg) { >> + sg_set_page(sg, sg_page(new_sgl), new_sgl->length, >> + new_sgl->offset); >> + sg_last = sg; >> + sg = sg_next(sg); >> + new_sgl = sg_next(new_sgl); >> + } >> + >> + if (new_sgl) >> + goto error; >> + >> + return sg_last; >> +error: >> + return ERR_PTR(-EINVAL); > > No need for this label, as there's no cleanup. Just return > ERR_PTR(-EINVAL) directly on error. Sure, will fix it. > >> +} >> + >> +static int qce_dma_prep_sg(struct dma_chan *chan, struct scatterlist *sg, >> + int nents, unsigned long flags, >> + enum dma_transfer_direction dir, >> + dma_async_tx_callback cb, void *cb_param) >> +{ >> + struct dma_async_tx_descriptor *desc; >> + >> + if (!sg || !nents) >> + return -EINVAL; >> + >> + desc = dmaengine_prep_slave_sg(chan, sg, nents, dir, flags); >> + if (!desc) >> + return -EINVAL; >> + >> + desc->callback = cb; >> + desc->callback_param = cb_param; >> + dmaengine_submit(desc); > > Do we not care if there is an error here? > > dma_cookie_t cookie; > ... > cookie = dmaengine_submit(desc); > return dma_submit_error(cookie); > Good catch, we should care. Will check the error. Thanks. >> + return 0; >> +} > [...] >> diff --git a/drivers/crypto/qce/dma.h b/drivers/crypto/qce/dma.h >> new file mode 100644 >> index 000000000000..932b02fd8f25 >> --- /dev/null >> +++ b/drivers/crypto/qce/dma.h >> @@ -0,0 +1,57 @@ >> +/* >> + * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. >> + * >> + * This program is free software; you can redistribute it and/or modify >> + * it under the terms of the GNU General Public License version 2 and >> + * only version 2 as published by the Free Software Foundation. >> + * >> + * This program is distributed in the hope that it will be useful, >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >> + * GNU General Public License for more details. >> + */ >> + >> +#ifndef _DMA_H_ >> +#define _DMA_H_ >> + >> +#define QCE_AUTHIV_REGS_CNT 16 >> +#define QCE_AUTH_BYTECOUNT_REGS_CNT 4 >> +#define QCE_CNTRIV_REGS_CNT 4 >> + >> +/* result dump format */ >> +struct qce_result_dump { >> + u32 auth_iv[QCE_AUTHIV_REGS_CNT]; >> + u32 auth_byte_count[QCE_AUTH_BYTECOUNT_REGS_CNT]; >> + u32 encr_cntr_iv[QCE_CNTRIV_REGS_CNT]; >> + u32 status; >> + u32 status2; >> +}; >> + >> +#define QCE_IGNORE_BUF_SZ (2 * QCE_BAM_BURST_SIZE) > > QCE_BAM_BURST_SIZE is defined in common.h in 6/9. Either that file > needs to be included from this one, or the definition needs to be moved. I decided to not include any files in driver private headers. Thus I include the private header files in relevant c files in order.
On Fri, Apr 04, 2014 at 03:07:13PM +0200, Stanimir Varbanov wrote: > >> diff --git a/drivers/crypto/qce/dma.h b/drivers/crypto/qce/dma.h > >> new file mode 100644 > >> index 000000000000..932b02fd8f25 > >> --- /dev/null > >> +++ b/drivers/crypto/qce/dma.h > >> @@ -0,0 +1,57 @@ > >> +/* > >> + * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. > >> + * > >> + * This program is free software; you can redistribute it and/or modify > >> + * it under the terms of the GNU General Public License version 2 and > >> + * only version 2 as published by the Free Software Foundation. > >> + * > >> + * This program is distributed in the hope that it will be useful, > >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of > >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > >> + * GNU General Public License for more details. > >> + */ > >> + > >> +#ifndef _DMA_H_ > >> +#define _DMA_H_ > >> + > >> +#define QCE_AUTHIV_REGS_CNT 16 > >> +#define QCE_AUTH_BYTECOUNT_REGS_CNT 4 > >> +#define QCE_CNTRIV_REGS_CNT 4 > >> + > >> +/* result dump format */ > >> +struct qce_result_dump { > >> + u32 auth_iv[QCE_AUTHIV_REGS_CNT]; > >> + u32 auth_byte_count[QCE_AUTH_BYTECOUNT_REGS_CNT]; > >> + u32 encr_cntr_iv[QCE_CNTRIV_REGS_CNT]; > >> + u32 status; > >> + u32 status2; > >> +}; > >> + > >> +#define QCE_IGNORE_BUF_SZ (2 * QCE_BAM_BURST_SIZE) > > > > QCE_BAM_BURST_SIZE is defined in common.h in 6/9. Either that file > > needs to be included from this one, or the definition needs to be moved. > > I decided to not include any files in driver private headers. Thus I > include the private header files in relevant c files in order. Actually, that is exactly what I was trying to indicate as undesirable. Please modify this so that each individual header file doesn't require you to include another file for usage. -Courtney -- To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi On 04/08/2014 01:42 AM, Courtney Cavin wrote: > On Fri, Apr 04, 2014 at 03:07:13PM +0200, Stanimir Varbanov wrote: >>>> diff --git a/drivers/crypto/qce/dma.h b/drivers/crypto/qce/dma.h >>>> new file mode 100644 >>>> index 000000000000..932b02fd8f25 >>>> --- /dev/null >>>> +++ b/drivers/crypto/qce/dma.h >>>> @@ -0,0 +1,57 @@ >>>> +/* >>>> + * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. >>>> + * >>>> + * This program is free software; you can redistribute it and/or modify >>>> + * it under the terms of the GNU General Public License version 2 and >>>> + * only version 2 as published by the Free Software Foundation. >>>> + * >>>> + * This program is distributed in the hope that it will be useful, >>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >>>> + * GNU General Public License for more details. >>>> + */ >>>> + >>>> +#ifndef _DMA_H_ >>>> +#define _DMA_H_ >>>> + >>>> +#define QCE_AUTHIV_REGS_CNT 16 >>>> +#define QCE_AUTH_BYTECOUNT_REGS_CNT 4 >>>> +#define QCE_CNTRIV_REGS_CNT 4 >>>> + >>>> +/* result dump format */ >>>> +struct qce_result_dump { >>>> + u32 auth_iv[QCE_AUTHIV_REGS_CNT]; >>>> + u32 auth_byte_count[QCE_AUTH_BYTECOUNT_REGS_CNT]; >>>> + u32 encr_cntr_iv[QCE_CNTRIV_REGS_CNT]; >>>> + u32 status; >>>> + u32 status2; >>>> +}; >>>> + >>>> +#define QCE_IGNORE_BUF_SZ (2 * QCE_BAM_BURST_SIZE) >>> >>> QCE_BAM_BURST_SIZE is defined in common.h in 6/9. Either that file >>> needs to be included from this one, or the definition needs to be moved. >> >> I decided to not include any files in driver private headers. Thus I >> include the private header files in relevant c files in order. > > Actually, that is exactly what I was trying to indicate as undesirable. > Please modify this so that each individual header file doesn't require > you to include another file for usage. OK, queued for version 2.
diff --git a/drivers/crypto/qce/dma.c b/drivers/crypto/qce/dma.c new file mode 100644 index 000000000000..1bad958db2f9 --- /dev/null +++ b/drivers/crypto/qce/dma.c @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/interrupt.h> +#include <crypto/algapi.h> +#include <crypto/scatterwalk.h> + +#include "dma.h" +#include "core.h" +#include "common.h" + +int qce_dma_request(struct device *dev, struct qce_dma_data *dma) +{ + unsigned int memsize; + void *va; + int ret; + + dma->txchan = dma_request_slave_channel_reason(dev, "tx"); + if (IS_ERR(dma->txchan)) { + ret = PTR_ERR(dma->txchan); + return ret; + } + + dma->rxchan = dma_request_slave_channel_reason(dev, "rx"); + if (IS_ERR(dma->rxchan)) { + ret = PTR_ERR(dma->rxchan); + goto error_rx; + } + + memsize = QCE_RESULT_BUF_SZ + QCE_IGNORE_BUF_SZ; + va = kzalloc(memsize, GFP_KERNEL); + if (!va) { + ret = -ENOMEM; + goto error_nomem; + } + + dma->result_buf = va; + dma->ignore_buf = dma->result_buf + QCE_RESULT_BUF_SZ; + + return 0; +error_nomem: + if (!IS_ERR(dma->rxchan)) + dma_release_channel(dma->rxchan); +error_rx: + if (!IS_ERR(dma->txchan)) + dma_release_channel(dma->txchan); + return ret; +} + +void qce_dma_release(struct qce_dma_data *dma) +{ + dma_release_channel(dma->txchan); + dma_release_channel(dma->rxchan); + kfree(dma->result_buf); +} + +int qce_mapsg(struct device *dev, struct scatterlist *sg, unsigned int nents, + enum dma_data_direction dir, bool chained) +{ + int err; + + if (chained) { + while (sg) { + err = dma_map_sg(dev, sg, 1, dir); + if (!err) + goto error; + sg = scatterwalk_sg_next(sg); + } + } else { + err = dma_map_sg(dev, sg, nents, dir); + if (!err) + goto error; + } + + return nents; +error: + return -EFAULT; +} + +void qce_unmapsg(struct device *dev, struct scatterlist *sg, int nents, + enum dma_data_direction dir, bool chained) +{ + if (chained) + while (sg) { + dma_unmap_sg(dev, sg, 1, dir); + sg = scatterwalk_sg_next(sg); + } + else + dma_unmap_sg(dev, sg, nents, dir); +} + +int qce_countsg(struct scatterlist *sglist, int nbytes, bool *chained) +{ + struct scatterlist *sg = sglist; + int sg_nents = 0; + + if (chained) + *chained = false; + + while (nbytes > 0 && sg) { + sg_nents++; + nbytes -= sg->length; + if (!sg_is_last(sg) && (sg + 1)->length == 0 && chained) + *chained = true; + sg = scatterwalk_sg_next(sg); + } + + return sg_nents; +} + +struct scatterlist * +qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl) +{ + struct scatterlist *sg = sgt->sgl, *sg_last = NULL; + + while (sg) { + if (!sg_page(sg)) + break; + sg = sg_next(sg); + } + + if (!sg) + goto error; + + while (new_sgl && sg) { + sg_set_page(sg, sg_page(new_sgl), new_sgl->length, + new_sgl->offset); + sg_last = sg; + sg = sg_next(sg); + new_sgl = sg_next(new_sgl); + } + + if (new_sgl) + goto error; + + return sg_last; +error: + return ERR_PTR(-EINVAL); +} + +static int qce_dma_prep_sg(struct dma_chan *chan, struct scatterlist *sg, + int nents, unsigned long flags, + enum dma_transfer_direction dir, + dma_async_tx_callback cb, void *cb_param) +{ + struct dma_async_tx_descriptor *desc; + + if (!sg || !nents) + return -EINVAL; + + desc = dmaengine_prep_slave_sg(chan, sg, nents, dir, flags); + if (!desc) + return -EINVAL; + + desc->callback = cb; + desc->callback_param = cb_param; + dmaengine_submit(desc); + return 0; +} + +int qce_dma_prep_sgs(struct qce_dma_data *dma, struct scatterlist *rx_sg, + int rx_nents, struct scatterlist *tx_sg, int tx_nents, + dma_async_tx_callback cb, void *cb_param) +{ + struct dma_chan *rxchan = dma->rxchan; + struct dma_chan *txchan = dma->txchan; + unsigned long flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK; + int rc; + + rc = qce_dma_prep_sg(rxchan, rx_sg, rx_nents, flags, DMA_MEM_TO_DEV, + NULL, NULL); + if (rc) + return rc; + + rc = qce_dma_prep_sg(txchan, tx_sg, tx_nents, flags, DMA_DEV_TO_MEM, + cb, cb_param); + + return rc; +} + +void qce_dma_issue_pending(struct qce_dma_data *dma) +{ + dma_async_issue_pending(dma->rxchan); + dma_async_issue_pending(dma->txchan); +} + +void qce_dma_terminate_all(struct qce_dma_data *dma) +{ + dmaengine_terminate_all(dma->rxchan); + dmaengine_terminate_all(dma->txchan); +} diff --git a/drivers/crypto/qce/dma.h b/drivers/crypto/qce/dma.h new file mode 100644 index 000000000000..932b02fd8f25 --- /dev/null +++ b/drivers/crypto/qce/dma.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _DMA_H_ +#define _DMA_H_ + +#define QCE_AUTHIV_REGS_CNT 16 +#define QCE_AUTH_BYTECOUNT_REGS_CNT 4 +#define QCE_CNTRIV_REGS_CNT 4 + +/* result dump format */ +struct qce_result_dump { + u32 auth_iv[QCE_AUTHIV_REGS_CNT]; + u32 auth_byte_count[QCE_AUTH_BYTECOUNT_REGS_CNT]; + u32 encr_cntr_iv[QCE_CNTRIV_REGS_CNT]; + u32 status; + u32 status2; +}; + +#define QCE_IGNORE_BUF_SZ (2 * QCE_BAM_BURST_SIZE) +#define QCE_RESULT_BUF_SZ \ + ALIGN(sizeof(struct qce_result_dump), QCE_BAM_BURST_SIZE) + +struct qce_dma_data { + struct dma_chan *txchan; + struct dma_chan *rxchan; + struct qce_result_dump *result_buf; + void *ignore_buf; +}; + +int qce_dma_request(struct device *dev, struct qce_dma_data *dma); +void qce_dma_release(struct qce_dma_data *dma); +int qce_dma_prep_sgs(struct qce_dma_data *dma, struct scatterlist *sg_in, + int in_ents, struct scatterlist *sg_out, int out_ents, + dma_async_tx_callback cb, void *cb_param); +int qce_countsg(struct scatterlist *sg_list, int nbytes, bool *chained); +void qce_unmapsg(struct device *dev, struct scatterlist *sg, int nents, + enum dma_data_direction dir, bool chained); +int qce_mapsg(struct device *dev, struct scatterlist *sg, + unsigned int nents, enum dma_data_direction dir, + bool chained); +struct scatterlist *qce_sgtable_add(struct sg_table *sgt, + struct scatterlist *sg_add); +void qce_dma_issue_pending(struct qce_dma_data *dma); +void qce_dma_terminate_all(struct qce_dma_data *dma); + +#endif /* _DMA_H_ */
This adds dmaengine and sg-list helper functions used by other parts of the crypto driver. Signed-off-by: Stanimir Varbanov <svarbanov@mm-sol.com> --- drivers/crypto/qce/dma.c | 201 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/crypto/qce/dma.h | 57 ++++++++++++++ 2 files changed, 258 insertions(+) create mode 100644 drivers/crypto/qce/dma.c create mode 100644 drivers/crypto/qce/dma.h