diff options
Diffstat (limited to 'crypto/scatterwalk.c')
| -rw-r--r-- | crypto/scatterwalk.c | 45 | 
1 files changed, 34 insertions, 11 deletions
diff --git a/crypto/scatterwalk.c b/crypto/scatterwalk.c index 3bd749c7bb70..ea5815c5e128 100644 --- a/crypto/scatterwalk.c +++ b/crypto/scatterwalk.c @@ -54,7 +54,11 @@ static void scatterwalk_pagedone(struct scatter_walk *walk, int out,  		struct page *page;  		page = sg_page(walk->sg) + ((walk->offset - 1) >> PAGE_SHIFT); -		if (!PageSlab(page)) +		/* Test ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE first as +		 * PageSlab cannot be optimised away per se due to +		 * use of volatile pointer. +		 */ +		if (ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE && !PageSlab(page))  			flush_dcache_page(page);  	} @@ -104,22 +108,18 @@ void scatterwalk_map_and_copy(void *buf, struct scatterlist *sg,  			      unsigned int start, unsigned int nbytes, int out)  {  	struct scatter_walk walk; -	unsigned int offset = 0; +	struct scatterlist tmp[2];  	if (!nbytes)  		return; -	for (;;) { -		scatterwalk_start(&walk, sg); - -		if (start < offset + sg->length) -			break; +	sg = scatterwalk_ffwd(tmp, sg, start); -		offset += sg->length; -		sg = sg_next(sg); -	} +	if (sg_page(sg) == virt_to_page(buf) && +	    sg->offset == offset_in_page(buf)) +		return; -	scatterwalk_advance(&walk, start - offset); +	scatterwalk_start(&walk, sg);  	scatterwalk_copychunks(buf, &walk, nbytes, out);  	scatterwalk_done(&walk, out, 0);  } @@ -146,3 +146,26 @@ int scatterwalk_bytes_sglen(struct scatterlist *sg, int num_bytes)  	return n;  }  EXPORT_SYMBOL_GPL(scatterwalk_bytes_sglen); + +struct scatterlist *scatterwalk_ffwd(struct scatterlist dst[2], +				     struct scatterlist *src, +				     unsigned int len) +{ +	for (;;) { +		if (!len) +			return src; + +		if (src->length > len) +			break; + +		len -= src->length; +		src = sg_next(src); +	} + +	sg_init_table(dst, 2); +	sg_set_page(dst, sg_page(src), src->length - len, src->offset + len); +	scatterwalk_crypto_chain(dst, sg_next(src), 0, 2); + +	return dst; +} +EXPORT_SYMBOL_GPL(scatterwalk_ffwd);  |