Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: acomp - Add async nondma fallback

Add support for passing non-DMA virtual addresses to async drivers
by passing them along to the fallback software algorithm.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

+41 -28
+41 -28
crypto/acompress.c
··· 152 152 } 153 153 EXPORT_SYMBOL_GPL(crypto_alloc_acomp_node); 154 154 155 - static bool acomp_request_has_nondma(struct acomp_req *req) 156 - { 157 - struct acomp_req *r2; 158 - 159 - if (acomp_request_isnondma(req)) 160 - return true; 161 - 162 - list_for_each_entry(r2, &req->base.list, base.list) 163 - if (acomp_request_isnondma(r2)) 164 - return true; 165 - 166 - return false; 167 - } 168 - 169 155 static void acomp_save_req(struct acomp_req *req, crypto_completion_t cplt) 170 156 { 171 157 struct crypto_acomp *tfm = crypto_acomp_reqtfm(req); ··· 220 234 } 221 235 } 222 236 237 + static int acomp_do_nondma(struct acomp_req_chain *state, 238 + struct acomp_req *req) 239 + { 240 + u32 keep = CRYPTO_ACOMP_REQ_SRC_VIRT | 241 + CRYPTO_ACOMP_REQ_SRC_NONDMA | 242 + CRYPTO_ACOMP_REQ_DST_VIRT | 243 + CRYPTO_ACOMP_REQ_DST_NONDMA; 244 + ACOMP_REQUEST_ON_STACK(fbreq, crypto_acomp_reqtfm(req)); 245 + int err; 246 + 247 + acomp_request_set_callback(fbreq, req->base.flags, NULL, NULL); 248 + fbreq->base.flags &= ~keep; 249 + fbreq->base.flags |= req->base.flags & keep; 250 + fbreq->src = req->src; 251 + fbreq->dst = req->dst; 252 + fbreq->slen = req->slen; 253 + fbreq->dlen = req->dlen; 254 + 255 + if (state->op == crypto_acomp_reqtfm(req)->compress) 256 + err = crypto_acomp_compress(fbreq); 257 + else 258 + err = crypto_acomp_decompress(fbreq); 259 + 260 + req->dlen = fbreq->dlen; 261 + return err; 262 + } 263 + 264 + static int acomp_do_one_req(struct acomp_req_chain *state, 265 + struct acomp_req *req) 266 + { 267 + state->cur = req; 268 + 269 + if (acomp_request_isnondma(req)) 270 + return acomp_do_nondma(state, req); 271 + 272 + acomp_virt_to_sg(req); 273 + return state->op(req); 274 + } 275 + 223 276 static int acomp_reqchain_finish(struct acomp_req_chain *state, 224 277 int err, u32 mask) 225 278 { ··· 277 252 req->base.flags &= mask; 278 253 req->base.complete = acomp_reqchain_done; 279 254 req->base.data = state; 280 - state->cur = req; 281 255 282 - acomp_virt_to_sg(req); 283 - err = state->op(req); 256 + err = acomp_do_one_req(state, req); 284 257 285 258 if (err == -EINPROGRESS) { 286 259 if (!list_empty(&state->head)) ··· 331 308 (!acomp_request_chained(req) && !acomp_request_isvirt(req))) 332 309 return op(req); 333 310 334 - /* 335 - * There are no in-kernel users that do this. If and ever 336 - * such users come into being then we could add a fall-back 337 - * path. 338 - */ 339 - if (acomp_request_has_nondma(req)) 340 - return -EINVAL; 341 - 342 311 if (acomp_is_async(tfm)) { 343 312 acomp_save_req(req, acomp_reqchain_done); 344 313 state = req->base.data; 345 314 } 346 315 347 316 state->op = op; 348 - state->cur = req; 349 317 state->src = NULL; 350 318 INIT_LIST_HEAD(&state->head); 351 319 list_splice_init(&req->base.list, &state->head); 352 320 353 - acomp_virt_to_sg(req); 354 - err = op(req); 321 + err = acomp_do_one_req(state, req); 355 322 if (err == -EBUSY || err == -EINPROGRESS) 356 323 return -EBUSY; 357 324