forked from mirrors/linux
		
	crypto: caam/qi - add ablkcipher and authenc algorithms
Add support to submit ablkcipher and authenc algorithms
via the QI backend:
-ablkcipher:
cbc({aes,des,des3_ede})
ctr(aes), rfc3686(ctr(aes))
xts(aes)
-authenc:
authenc(hmac(md5),cbc({aes,des,des3_ede}))
authenc(hmac(sha*),cbc({aes,des,des3_ede}))
caam/qi being a new driver, let's wait some time to settle down without
interfering with existing caam/jr driver.
Accordingly, for now all caam/qi algorithms (caamalg_qi module) are
marked to be of lower priority than caam/jr ones (caamalg module).
Signed-off-by: Vakul Garg <vakul.garg@nxp.com>
Signed-off-by: Alex Porosanu <alexandru.porosanu@nxp.com>
Signed-off-by: Horia Geantă <horia.geanta@nxp.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
			
			
This commit is contained in:
		
							parent
							
								
									67c2315def
								
							
						
					
					
						commit
						b189817cf7
					
				
					 7 changed files with 2601 additions and 16 deletions
				
			
		| 
						 | 
				
			
			@ -87,6 +87,23 @@ config CRYPTO_DEV_FSL_CAAM_CRYPTO_API
 | 
			
		|||
	  To compile this as a module, choose M here: the module
 | 
			
		||||
	  will be called caamalg.
 | 
			
		||||
 | 
			
		||||
config CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI
 | 
			
		||||
	tristate "Queue Interface as Crypto API backend"
 | 
			
		||||
	depends on CRYPTO_DEV_FSL_CAAM_JR && FSL_DPAA && NET
 | 
			
		||||
	default y
 | 
			
		||||
	select CRYPTO_AUTHENC
 | 
			
		||||
	select CRYPTO_BLKCIPHER
 | 
			
		||||
	help
 | 
			
		||||
	  Selecting this will use CAAM Queue Interface (QI) for sending
 | 
			
		||||
	  & receiving crypto jobs to/from CAAM. This gives better performance
 | 
			
		||||
	  than job ring interface when the number of cores are more than the
 | 
			
		||||
	  number of job rings assigned to the kernel. The number of portals
 | 
			
		||||
	  assigned to the kernel should also be more than the number of
 | 
			
		||||
	  job rings.
 | 
			
		||||
 | 
			
		||||
	  To compile this as a module, choose M here: the module
 | 
			
		||||
	  will be called caamalg_qi.
 | 
			
		||||
 | 
			
		||||
config CRYPTO_DEV_FSL_CAAM_AHASH_API
 | 
			
		||||
	tristate "Register hash algorithm implementations with Crypto API"
 | 
			
		||||
	depends on CRYPTO_DEV_FSL_CAAM_JR
 | 
			
		||||
| 
						 | 
				
			
			@ -136,4 +153,5 @@ config CRYPTO_DEV_FSL_CAAM_DEBUG
 | 
			
		|||
	  information in the CAAM driver.
 | 
			
		||||
 | 
			
		||||
config CRYPTO_DEV_FSL_CAAM_CRYPTO_API_DESC
 | 
			
		||||
	def_tristate CRYPTO_DEV_FSL_CAAM_CRYPTO_API
 | 
			
		||||
	def_tristate (CRYPTO_DEV_FSL_CAAM_CRYPTO_API || \
 | 
			
		||||
		      CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,7 @@ endif
 | 
			
		|||
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += caam.o
 | 
			
		||||
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_JR) += caam_jr.o
 | 
			
		||||
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API) += caamalg.o
 | 
			
		||||
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI) += caamalg_qi.o
 | 
			
		||||
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_DESC) += caamalg_desc.o
 | 
			
		||||
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o
 | 
			
		||||
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -266,8 +266,9 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
 | 
			
		|||
 | 
			
		||||
	/* aead_encrypt shared descriptor */
 | 
			
		||||
	desc = ctx->sh_desc_enc;
 | 
			
		||||
	cnstr_shdsc_aead_encap(desc, &ctx->cdata, &ctx->adata, ctx->authsize,
 | 
			
		||||
			       is_rfc3686, nonce, ctx1_iv_off);
 | 
			
		||||
	cnstr_shdsc_aead_encap(desc, &ctx->cdata, &ctx->adata, ivsize,
 | 
			
		||||
			       ctx->authsize, is_rfc3686, nonce, ctx1_iv_off,
 | 
			
		||||
			       false);
 | 
			
		||||
	dma_sync_single_for_device(jrdev, ctx->sh_desc_enc_dma,
 | 
			
		||||
				   desc_bytes(desc), DMA_TO_DEVICE);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -299,7 +300,7 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
 | 
			
		|||
	desc = ctx->sh_desc_dec;
 | 
			
		||||
	cnstr_shdsc_aead_decap(desc, &ctx->cdata, &ctx->adata, ivsize,
 | 
			
		||||
			       ctx->authsize, alg->caam.geniv, is_rfc3686,
 | 
			
		||||
			       nonce, ctx1_iv_off);
 | 
			
		||||
			       nonce, ctx1_iv_off, false);
 | 
			
		||||
	dma_sync_single_for_device(jrdev, ctx->sh_desc_dec_dma,
 | 
			
		||||
				   desc_bytes(desc), DMA_TO_DEVICE);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -333,7 +334,7 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
 | 
			
		|||
	desc = ctx->sh_desc_enc;
 | 
			
		||||
	cnstr_shdsc_aead_givencap(desc, &ctx->cdata, &ctx->adata, ivsize,
 | 
			
		||||
				  ctx->authsize, is_rfc3686, nonce,
 | 
			
		||||
				  ctx1_iv_off);
 | 
			
		||||
				  ctx1_iv_off, false);
 | 
			
		||||
	dma_sync_single_for_device(jrdev, ctx->sh_desc_enc_dma,
 | 
			
		||||
				   desc_bytes(desc), DMA_TO_DEVICE);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -265,17 +265,19 @@ static void init_sh_desc_key_aead(u32 * const desc,
 | 
			
		|||
 *         split key is to be used, the size of the split key itself is
 | 
			
		||||
 *         specified. Valid algorithm values - one of OP_ALG_ALGSEL_{MD5, SHA1,
 | 
			
		||||
 *         SHA224, SHA256, SHA384, SHA512} ANDed with OP_ALG_AAI_HMAC_PRECOMP.
 | 
			
		||||
 * @ivsize: initialization vector size
 | 
			
		||||
 * @icvsize: integrity check value (ICV) size (truncated or full)
 | 
			
		||||
 * @is_rfc3686: true when ctr(aes) is wrapped by rfc3686 template
 | 
			
		||||
 * @nonce: pointer to rfc3686 nonce
 | 
			
		||||
 * @ctx1_iv_off: IV offset in CONTEXT1 register
 | 
			
		||||
 * @is_qi: true when called from caam/qi
 | 
			
		||||
 *
 | 
			
		||||
 * Note: Requires an MDHA split key.
 | 
			
		||||
 */
 | 
			
		||||
void cnstr_shdsc_aead_encap(u32 * const desc, struct alginfo *cdata,
 | 
			
		||||
			    struct alginfo *adata, unsigned int icvsize,
 | 
			
		||||
			    const bool is_rfc3686, u32 *nonce,
 | 
			
		||||
			    const u32 ctx1_iv_off)
 | 
			
		||||
			    struct alginfo *adata, unsigned int ivsize,
 | 
			
		||||
			    unsigned int icvsize, const bool is_rfc3686,
 | 
			
		||||
			    u32 *nonce, const u32 ctx1_iv_off, const bool is_qi)
 | 
			
		||||
{
 | 
			
		||||
	/* Note: Context registers are saved. */
 | 
			
		||||
	init_sh_desc_key_aead(desc, cdata, adata, is_rfc3686, nonce);
 | 
			
		||||
| 
						 | 
				
			
			@ -284,6 +286,25 @@ void cnstr_shdsc_aead_encap(u32 * const desc, struct alginfo *cdata,
 | 
			
		|||
	append_operation(desc, adata->algtype | OP_ALG_AS_INITFINAL |
 | 
			
		||||
			 OP_ALG_ENCRYPT);
 | 
			
		||||
 | 
			
		||||
	if (is_qi) {
 | 
			
		||||
		u32 *wait_load_cmd;
 | 
			
		||||
 | 
			
		||||
		/* REG3 = assoclen */
 | 
			
		||||
		append_seq_load(desc, 4, LDST_CLASS_DECO |
 | 
			
		||||
				LDST_SRCDST_WORD_DECO_MATH3 |
 | 
			
		||||
				(4 << LDST_OFFSET_SHIFT));
 | 
			
		||||
 | 
			
		||||
		wait_load_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
 | 
			
		||||
					    JUMP_COND_CALM | JUMP_COND_NCP |
 | 
			
		||||
					    JUMP_COND_NOP | JUMP_COND_NIP |
 | 
			
		||||
					    JUMP_COND_NIFP);
 | 
			
		||||
		set_jump_tgt_here(desc, wait_load_cmd);
 | 
			
		||||
 | 
			
		||||
		append_seq_load(desc, ivsize, LDST_CLASS_1_CCB |
 | 
			
		||||
				LDST_SRCDST_BYTE_CONTEXT |
 | 
			
		||||
				(ctx1_iv_off << LDST_OFFSET_SHIFT));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Read and write assoclen bytes */
 | 
			
		||||
	append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
 | 
			
		||||
	append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
 | 
			
		||||
| 
						 | 
				
			
			@ -338,6 +359,7 @@ EXPORT_SYMBOL(cnstr_shdsc_aead_encap);
 | 
			
		|||
 * @is_rfc3686: true when ctr(aes) is wrapped by rfc3686 template
 | 
			
		||||
 * @nonce: pointer to rfc3686 nonce
 | 
			
		||||
 * @ctx1_iv_off: IV offset in CONTEXT1 register
 | 
			
		||||
 * @is_qi: true when called from caam/qi
 | 
			
		||||
 *
 | 
			
		||||
 * Note: Requires an MDHA split key.
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -345,7 +367,7 @@ void cnstr_shdsc_aead_decap(u32 * const desc, struct alginfo *cdata,
 | 
			
		|||
			    struct alginfo *adata, unsigned int ivsize,
 | 
			
		||||
			    unsigned int icvsize, const bool geniv,
 | 
			
		||||
			    const bool is_rfc3686, u32 *nonce,
 | 
			
		||||
			    const u32 ctx1_iv_off)
 | 
			
		||||
			    const u32 ctx1_iv_off, const bool is_qi)
 | 
			
		||||
{
 | 
			
		||||
	/* Note: Context registers are saved. */
 | 
			
		||||
	init_sh_desc_key_aead(desc, cdata, adata, is_rfc3686, nonce);
 | 
			
		||||
| 
						 | 
				
			
			@ -354,6 +376,26 @@ void cnstr_shdsc_aead_decap(u32 * const desc, struct alginfo *cdata,
 | 
			
		|||
	append_operation(desc, adata->algtype | OP_ALG_AS_INITFINAL |
 | 
			
		||||
			 OP_ALG_DECRYPT | OP_ALG_ICV_ON);
 | 
			
		||||
 | 
			
		||||
	if (is_qi) {
 | 
			
		||||
		u32 *wait_load_cmd;
 | 
			
		||||
 | 
			
		||||
		/* REG3 = assoclen */
 | 
			
		||||
		append_seq_load(desc, 4, LDST_CLASS_DECO |
 | 
			
		||||
				LDST_SRCDST_WORD_DECO_MATH3 |
 | 
			
		||||
				(4 << LDST_OFFSET_SHIFT));
 | 
			
		||||
 | 
			
		||||
		wait_load_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
 | 
			
		||||
					    JUMP_COND_CALM | JUMP_COND_NCP |
 | 
			
		||||
					    JUMP_COND_NOP | JUMP_COND_NIP |
 | 
			
		||||
					    JUMP_COND_NIFP);
 | 
			
		||||
		set_jump_tgt_here(desc, wait_load_cmd);
 | 
			
		||||
 | 
			
		||||
		if (!geniv)
 | 
			
		||||
			append_seq_load(desc, ivsize, LDST_CLASS_1_CCB |
 | 
			
		||||
					LDST_SRCDST_BYTE_CONTEXT |
 | 
			
		||||
					(ctx1_iv_off << LDST_OFFSET_SHIFT));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Read and write assoclen bytes */
 | 
			
		||||
	append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
 | 
			
		||||
	if (geniv)
 | 
			
		||||
| 
						 | 
				
			
			@ -423,21 +465,44 @@ EXPORT_SYMBOL(cnstr_shdsc_aead_decap);
 | 
			
		|||
 * @is_rfc3686: true when ctr(aes) is wrapped by rfc3686 template
 | 
			
		||||
 * @nonce: pointer to rfc3686 nonce
 | 
			
		||||
 * @ctx1_iv_off: IV offset in CONTEXT1 register
 | 
			
		||||
 * @is_qi: true when called from caam/qi
 | 
			
		||||
 *
 | 
			
		||||
 * Note: Requires an MDHA split key.
 | 
			
		||||
 */
 | 
			
		||||
void cnstr_shdsc_aead_givencap(u32 * const desc, struct alginfo *cdata,
 | 
			
		||||
			       struct alginfo *adata, unsigned int ivsize,
 | 
			
		||||
			       unsigned int icvsize, const bool is_rfc3686,
 | 
			
		||||
			       u32 *nonce, const u32 ctx1_iv_off)
 | 
			
		||||
			       u32 *nonce, const u32 ctx1_iv_off,
 | 
			
		||||
			       const bool is_qi)
 | 
			
		||||
{
 | 
			
		||||
	u32 geniv, moveiv;
 | 
			
		||||
 | 
			
		||||
	/* Note: Context registers are saved. */
 | 
			
		||||
	init_sh_desc_key_aead(desc, cdata, adata, is_rfc3686, nonce);
 | 
			
		||||
 | 
			
		||||
	if (is_rfc3686)
 | 
			
		||||
	if (is_qi) {
 | 
			
		||||
		u32 *wait_load_cmd;
 | 
			
		||||
 | 
			
		||||
		/* REG3 = assoclen */
 | 
			
		||||
		append_seq_load(desc, 4, LDST_CLASS_DECO |
 | 
			
		||||
				LDST_SRCDST_WORD_DECO_MATH3 |
 | 
			
		||||
				(4 << LDST_OFFSET_SHIFT));
 | 
			
		||||
 | 
			
		||||
		wait_load_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
 | 
			
		||||
					    JUMP_COND_CALM | JUMP_COND_NCP |
 | 
			
		||||
					    JUMP_COND_NOP | JUMP_COND_NIP |
 | 
			
		||||
					    JUMP_COND_NIFP);
 | 
			
		||||
		set_jump_tgt_here(desc, wait_load_cmd);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (is_rfc3686) {
 | 
			
		||||
		if (is_qi)
 | 
			
		||||
			append_seq_load(desc, ivsize, LDST_CLASS_1_CCB |
 | 
			
		||||
					LDST_SRCDST_BYTE_CONTEXT |
 | 
			
		||||
					(ctx1_iv_off << LDST_OFFSET_SHIFT));
 | 
			
		||||
 | 
			
		||||
		goto copy_iv;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Generate IV */
 | 
			
		||||
	geniv = NFIFOENTRY_STYPE_PAD | NFIFOENTRY_DEST_DECO |
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,9 @@
 | 
			
		|||
#define DESC_AEAD_ENC_LEN		(DESC_AEAD_BASE + 11 * CAAM_CMD_SZ)
 | 
			
		||||
#define DESC_AEAD_DEC_LEN		(DESC_AEAD_BASE + 15 * CAAM_CMD_SZ)
 | 
			
		||||
#define DESC_AEAD_GIVENC_LEN		(DESC_AEAD_ENC_LEN + 7 * CAAM_CMD_SZ)
 | 
			
		||||
#define DESC_QI_AEAD_ENC_LEN		(DESC_AEAD_ENC_LEN + 3 * CAAM_CMD_SZ)
 | 
			
		||||
#define DESC_QI_AEAD_DEC_LEN		(DESC_AEAD_DEC_LEN + 3 * CAAM_CMD_SZ)
 | 
			
		||||
#define DESC_QI_AEAD_GIVENC_LEN		(DESC_AEAD_GIVENC_LEN + 3 * CAAM_CMD_SZ)
 | 
			
		||||
 | 
			
		||||
/* Note: Nonce is counted in cdata.keylen */
 | 
			
		||||
#define DESC_AEAD_CTR_RFC3686_LEN	(4 * CAAM_CMD_SZ)
 | 
			
		||||
| 
						 | 
				
			
			@ -45,20 +48,22 @@ void cnstr_shdsc_aead_null_decap(u32 * const desc, struct alginfo *adata,
 | 
			
		|||
				 unsigned int icvsize);
 | 
			
		||||
 | 
			
		||||
void cnstr_shdsc_aead_encap(u32 * const desc, struct alginfo *cdata,
 | 
			
		||||
			    struct alginfo *adata, unsigned int icvsize,
 | 
			
		||||
			    const bool is_rfc3686, u32 *nonce,
 | 
			
		||||
			    const u32 ctx1_iv_off);
 | 
			
		||||
			    struct alginfo *adata, unsigned int ivsize,
 | 
			
		||||
			    unsigned int icvsize, const bool is_rfc3686,
 | 
			
		||||
			    u32 *nonce, const u32 ctx1_iv_off,
 | 
			
		||||
			    const bool is_qi);
 | 
			
		||||
 | 
			
		||||
void cnstr_shdsc_aead_decap(u32 * const desc, struct alginfo *cdata,
 | 
			
		||||
			    struct alginfo *adata, unsigned int ivsize,
 | 
			
		||||
			    unsigned int icvsize, const bool geniv,
 | 
			
		||||
			    const bool is_rfc3686, u32 *nonce,
 | 
			
		||||
			    const u32 ctx1_iv_off);
 | 
			
		||||
			    const u32 ctx1_iv_off, const bool is_qi);
 | 
			
		||||
 | 
			
		||||
void cnstr_shdsc_aead_givencap(u32 * const desc, struct alginfo *cdata,
 | 
			
		||||
			       struct alginfo *adata, unsigned int ivsize,
 | 
			
		||||
			       unsigned int icvsize, const bool is_rfc3686,
 | 
			
		||||
			       u32 *nonce, const u32 ctx1_iv_off);
 | 
			
		||||
			       u32 *nonce, const u32 ctx1_iv_off,
 | 
			
		||||
			       const bool is_qi);
 | 
			
		||||
 | 
			
		||||
void cnstr_shdsc_gcm_encap(u32 * const desc, struct alginfo *cdata,
 | 
			
		||||
			   unsigned int icvsize);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2387
									
								
								drivers/crypto/caam/caamalg_qi.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2387
									
								
								drivers/crypto/caam/caamalg_qi.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										108
									
								
								drivers/crypto/caam/sg_sw_qm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								drivers/crypto/caam/sg_sw_qm.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,108 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright 2013-2016 Freescale Semiconductor, Inc.
 | 
			
		||||
 * Copyright 2016-2017 NXP
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 *     * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *       notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *     * Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *       notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *       documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *     * Neither the name of Freescale Semiconductor nor the
 | 
			
		||||
 *       names of its contributors may be used to endorse or promote products
 | 
			
		||||
 *       derived from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 * ALTERNATIVELY, this software may be distributed under the terms of the
 | 
			
		||||
 * GNU General Public License ("GPL") as published by the Free Software
 | 
			
		||||
 * Foundation, either version 2 of that License or (at your option) any
 | 
			
		||||
 * later version.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
 | 
			
		||||
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
			
		||||
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
			
		||||
 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
 | 
			
		||||
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 | 
			
		||||
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
			
		||||
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 | 
			
		||||
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
			
		||||
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __SG_SW_QM_H
 | 
			
		||||
#define __SG_SW_QM_H
 | 
			
		||||
 | 
			
		||||
#include <soc/fsl/qman.h>
 | 
			
		||||
#include "regs.h"
 | 
			
		||||
 | 
			
		||||
static inline void __dma_to_qm_sg(struct qm_sg_entry *qm_sg_ptr, dma_addr_t dma,
 | 
			
		||||
				  u16 offset)
 | 
			
		||||
{
 | 
			
		||||
	qm_sg_entry_set64(qm_sg_ptr, dma);
 | 
			
		||||
	qm_sg_ptr->__reserved2 = 0;
 | 
			
		||||
	qm_sg_ptr->bpid = 0;
 | 
			
		||||
	qm_sg_ptr->offset = cpu_to_be16(offset & QM_SG_OFF_MASK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void dma_to_qm_sg_one(struct qm_sg_entry *qm_sg_ptr,
 | 
			
		||||
				    dma_addr_t dma, u32 len, u16 offset)
 | 
			
		||||
{
 | 
			
		||||
	__dma_to_qm_sg(qm_sg_ptr, dma, offset);
 | 
			
		||||
	qm_sg_entry_set_len(qm_sg_ptr, len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void dma_to_qm_sg_one_last(struct qm_sg_entry *qm_sg_ptr,
 | 
			
		||||
					 dma_addr_t dma, u32 len, u16 offset)
 | 
			
		||||
{
 | 
			
		||||
	__dma_to_qm_sg(qm_sg_ptr, dma, offset);
 | 
			
		||||
	qm_sg_entry_set_f(qm_sg_ptr, len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void dma_to_qm_sg_one_ext(struct qm_sg_entry *qm_sg_ptr,
 | 
			
		||||
					dma_addr_t dma, u32 len, u16 offset)
 | 
			
		||||
{
 | 
			
		||||
	__dma_to_qm_sg(qm_sg_ptr, dma, offset);
 | 
			
		||||
	qm_sg_ptr->cfg = cpu_to_be32(QM_SG_EXT | (len & QM_SG_LEN_MASK));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void dma_to_qm_sg_one_last_ext(struct qm_sg_entry *qm_sg_ptr,
 | 
			
		||||
					     dma_addr_t dma, u32 len,
 | 
			
		||||
					     u16 offset)
 | 
			
		||||
{
 | 
			
		||||
	__dma_to_qm_sg(qm_sg_ptr, dma, offset);
 | 
			
		||||
	qm_sg_ptr->cfg = cpu_to_be32(QM_SG_EXT | QM_SG_FIN |
 | 
			
		||||
				     (len & QM_SG_LEN_MASK));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * convert scatterlist to h/w link table format
 | 
			
		||||
 * but does not have final bit; instead, returns last entry
 | 
			
		||||
 */
 | 
			
		||||
static inline struct qm_sg_entry *
 | 
			
		||||
sg_to_qm_sg(struct scatterlist *sg, int sg_count,
 | 
			
		||||
	    struct qm_sg_entry *qm_sg_ptr, u16 offset)
 | 
			
		||||
{
 | 
			
		||||
	while (sg_count && sg) {
 | 
			
		||||
		dma_to_qm_sg_one(qm_sg_ptr, sg_dma_address(sg),
 | 
			
		||||
				 sg_dma_len(sg), offset);
 | 
			
		||||
		qm_sg_ptr++;
 | 
			
		||||
		sg = sg_next(sg);
 | 
			
		||||
		sg_count--;
 | 
			
		||||
	}
 | 
			
		||||
	return qm_sg_ptr - 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * convert scatterlist to h/w link table format
 | 
			
		||||
 * scatterlist must have been previously dma mapped
 | 
			
		||||
 */
 | 
			
		||||
static inline void sg_to_qm_sg_last(struct scatterlist *sg, int sg_count,
 | 
			
		||||
				    struct qm_sg_entry *qm_sg_ptr, u16 offset)
 | 
			
		||||
{
 | 
			
		||||
	qm_sg_ptr = sg_to_qm_sg(sg, sg_count, qm_sg_ptr, offset);
 | 
			
		||||
	qm_sg_entry_set_f(qm_sg_ptr, qm_sg_entry_get_len(qm_sg_ptr));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* __SG_SW_QM_H */
 | 
			
		||||
		Loading…
	
		Reference in a new issue