Currently, conversion of SW S/G table into HW S/G layout relies on nents returned by sg_nents_for_len(sg, len). However this leaves the possibility of HW S/G referencing more data then needed: since buffer length in HW S/G entries is filled using sg_dma_len(sg), the last entry in HW S/G table might have a length that is bigger than needed for the crypto request. This way of S/G table conversion is fine, unless after converting a table more entries have to be appended to the HW S/G table. In this case, crypto engine would access data from the S/G entry having the incorrect length, instead of advancing in the S/G table. This situation doesn't exist, but the upcoming implementation of IV update for skcipher algorithms needs to add a S/G entry after req->dst S/G (corresponding to output IV). Signed-off-by: Horia Geantă <horia.geanta@nxp.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
		
			
				
	
	
		
			58 lines
		
	
	
		
			1.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			58 lines
		
	
	
		
			1.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
 | |
| /*
 | |
|  * Copyright 2015-2016 Freescale Semiconductor, Inc.
 | |
|  * Copyright 2017 NXP
 | |
|  */
 | |
| 
 | |
| #ifndef _SG_SW_QM2_H_
 | |
| #define _SG_SW_QM2_H_
 | |
| 
 | |
| #include <soc/fsl/dpaa2-fd.h>
 | |
| 
 | |
| static inline void dma_to_qm_sg_one(struct dpaa2_sg_entry *qm_sg_ptr,
 | |
| 				    dma_addr_t dma, u32 len, u16 offset)
 | |
| {
 | |
| 	dpaa2_sg_set_addr(qm_sg_ptr, dma);
 | |
| 	dpaa2_sg_set_format(qm_sg_ptr, dpaa2_sg_single);
 | |
| 	dpaa2_sg_set_final(qm_sg_ptr, false);
 | |
| 	dpaa2_sg_set_len(qm_sg_ptr, len);
 | |
| 	dpaa2_sg_set_bpid(qm_sg_ptr, 0);
 | |
| 	dpaa2_sg_set_offset(qm_sg_ptr, offset);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * convert scatterlist to h/w link table format
 | |
|  * but does not have final bit; instead, returns last entry
 | |
|  */
 | |
| static inline struct dpaa2_sg_entry *
 | |
| sg_to_qm_sg(struct scatterlist *sg, int len,
 | |
| 	    struct dpaa2_sg_entry *qm_sg_ptr, u16 offset)
 | |
| {
 | |
| 	int ent_len;
 | |
| 
 | |
| 	while (len) {
 | |
| 		ent_len = min_t(int, sg_dma_len(sg), len);
 | |
| 
 | |
| 		dma_to_qm_sg_one(qm_sg_ptr, sg_dma_address(sg), ent_len,
 | |
| 				 offset);
 | |
| 		qm_sg_ptr++;
 | |
| 		sg = sg_next(sg);
 | |
| 		len -= ent_len;
 | |
| 	}
 | |
| 	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 len,
 | |
| 				    struct dpaa2_sg_entry *qm_sg_ptr,
 | |
| 				    u16 offset)
 | |
| {
 | |
| 	qm_sg_ptr = sg_to_qm_sg(sg, len, qm_sg_ptr, offset);
 | |
| 	dpaa2_sg_set_final(qm_sg_ptr, true);
 | |
| }
 | |
| 
 | |
| #endif /* _SG_SW_QM2_H_ */
 |