struct crypto_scomp *scomp = *tfm_ctx;
        void **ctx = acomp_request_ctx(req);
        struct scomp_scratch *scratch;
+       void *src, *dst;
        unsigned int dlen;
        int ret;
 
        scratch = raw_cpu_ptr(&scomp_scratch);
        spin_lock(&scratch->lock);
 
-       scatterwalk_map_and_copy(scratch->src, req->src, 0, req->slen, 0);
+       if (sg_nents(req->src) == 1 && !PageHighMem(sg_page(req->src))) {
+               src = page_to_virt(sg_page(req->src)) + req->src->offset;
+       } else {
+               scatterwalk_map_and_copy(scratch->src, req->src, 0,
+                                        req->slen, 0);
+               src = scratch->src;
+       }
+
+       if (req->dst && sg_nents(req->dst) == 1 && !PageHighMem(sg_page(req->dst)))
+               dst = page_to_virt(sg_page(req->dst)) + req->dst->offset;
+       else
+               dst = scratch->dst;
+
        if (dir)
-               ret = crypto_scomp_compress(scomp, scratch->src, req->slen,
-                                           scratch->dst, &req->dlen, *ctx);
+               ret = crypto_scomp_compress(scomp, src, req->slen,
+                                           dst, &req->dlen, *ctx);
        else
-               ret = crypto_scomp_decompress(scomp, scratch->src, req->slen,
-                                             scratch->dst, &req->dlen, *ctx);
+               ret = crypto_scomp_decompress(scomp, src, req->slen,
+                                             dst, &req->dlen, *ctx);
        if (!ret) {
                if (!req->dst) {
                        req->dst = sgl_alloc(req->dlen, GFP_ATOMIC, NULL);
                        ret = -ENOSPC;
                        goto out;
                }
-               scatterwalk_map_and_copy(scratch->dst, req->dst, 0, req->dlen,
-                                        1);
+               if (dst == scratch->dst) {
+                       scatterwalk_map_and_copy(scratch->dst, req->dst, 0,
+                                                req->dlen, 1);
+               } else {
+                       int nr_pages = DIV_ROUND_UP(req->dst->offset + req->dlen, PAGE_SIZE);
+                       int i;
+                       struct page *dst_page = sg_page(req->dst);
+
+                       for (i = 0; i < nr_pages; i++)
+                               flush_dcache_page(dst_page + i);
+               }
        }
 out:
        spin_unlock(&scratch->lock);