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

Configure Feed

Select the types of activity you want to include in your feed.

crypto: hisilicon/sec - move backlog management to qp and store sqe in qp for callback

When multiple tfm use a same qp, the backlog data should be managed
centrally by the qp, rather than in the qp_ctx of each req.

Additionally, since SEC_BD_TYPE1 and SEC_BD_TYPE2 cannot use the
tag of the sqe to carry the virtual address of the req, the sent
sqe is stored in the qp. This allows the callback function to get
the req address. To handle the differences between hardware types,
the callback functions are split into two separate implementations.

Fixes: f0ae287c5045 ("crypto: hisilicon/sec2 - implement full backlog mode for sec")
Signed-off-by: Chenghai Huang <huangchenghai2@huawei.com>
Signed-off-by: Weili Qian <qianweili@huawei.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Chenghai Huang and committed by
Herbert Xu
08eb67d2 19c2475c

+71 -56
+16 -4
drivers/crypto/hisilicon/qm.c
··· 2219 2219 for (i = 0; i < qp_used; i++) { 2220 2220 pos = (i + cur_head) % sq_depth; 2221 2221 qp->req_cb(qp, qp->sqe + (u32)(qm->sqe_size * pos)); 2222 + qm_cq_head_update(qp); 2222 2223 atomic_dec(&qp->qp_status.used); 2223 2224 } 2224 2225 } ··· 2384 2383 return -EBUSY; 2385 2384 2386 2385 memcpy(sqe, msg, qp->qm->sqe_size); 2386 + qp->msg[sq_tail] = msg; 2387 2387 2388 2388 qm_db(qp->qm, qp->qp_id, QM_DOORBELL_CMD_SQ, sq_tail_next, 0); 2389 2389 atomic_inc(&qp->qp_status.used); ··· 2921 2919 static void hisi_qp_memory_uninit(struct hisi_qm *qm, int num) 2922 2920 { 2923 2921 struct device *dev = &qm->pdev->dev; 2924 - struct qm_dma *qdma; 2922 + struct hisi_qp *qp; 2925 2923 int i; 2926 2924 2927 2925 for (i = num - 1; i >= 0; i--) { 2928 - qdma = &qm->qp_array[i].qdma; 2929 - dma_free_coherent(dev, qdma->size, qdma->va, qdma->dma); 2926 + qp = &qm->qp_array[i]; 2927 + dma_free_coherent(dev, qp->qdma.size, qp->qdma.va, qp->qdma.dma); 2928 + kfree(qp->msg); 2930 2929 kfree(qm->poll_data[i].qp_finish_id); 2931 2930 } 2932 2931 ··· 2949 2946 return -ENOMEM; 2950 2947 2951 2948 qp = &qm->qp_array[id]; 2949 + qp->msg = kmalloc_array(sq_depth, sizeof(void *), GFP_KERNEL); 2950 + if (!qp->msg) 2951 + goto err_free_qp_finish_id; 2952 + 2952 2953 qp->qdma.va = dma_alloc_coherent(dev, dma_size, &qp->qdma.dma, 2953 2954 GFP_KERNEL); 2954 2955 if (!qp->qdma.va) 2955 - goto err_free_qp_finish_id; 2956 + goto err_free_qp_msg; 2956 2957 2957 2958 qp->sqe = qp->qdma.va; 2958 2959 qp->sqe_dma = qp->qdma.dma; ··· 2968 2961 qp->qm = qm; 2969 2962 qp->qp_id = id; 2970 2963 2964 + spin_lock_init(&qp->backlog.lock); 2965 + INIT_LIST_HEAD(&qp->backlog.list); 2966 + 2971 2967 return 0; 2972 2968 2969 + err_free_qp_msg: 2970 + kfree(qp->msg); 2973 2971 err_free_qp_finish_id: 2974 2972 kfree(qm->poll_data[id].qp_finish_id); 2975 2973 return ret;
-7
drivers/crypto/hisilicon/sec2/sec.h
··· 82 82 __u8 out_mac_buf[SEC_MAX_MAC_LEN]; 83 83 }; 84 84 85 - struct sec_instance_backlog { 86 - struct list_head list; 87 - spinlock_t lock; 88 - }; 89 - 90 85 /* SEC request of Crypto */ 91 86 struct sec_req { 92 87 union { ··· 107 112 bool use_pbuf; 108 113 109 114 struct list_head list; 110 - struct sec_instance_backlog *backlog; 111 115 struct sec_request_buf buf; 112 116 }; 113 117 ··· 166 172 spinlock_t id_lock; 167 173 struct hisi_acc_sgl_pool *c_in_pool; 168 174 struct hisi_acc_sgl_pool *c_out_pool; 169 - struct sec_instance_backlog backlog; 170 175 u16 send_head; 171 176 }; 172 177
+47 -45
drivers/crypto/hisilicon/sec2/sec_crypto.c
··· 54 54 #define SEC_AUTH_CIPHER_V3 0x40 55 55 #define SEC_FLAG_OFFSET 7 56 56 #define SEC_FLAG_MASK 0x0780 57 - #define SEC_TYPE_MASK 0x0F 58 57 #define SEC_DONE_MASK 0x0001 59 58 #define SEC_ICV_MASK 0x000E 60 59 ··· 147 148 spin_unlock_bh(&qp_ctx->id_lock); 148 149 } 149 150 150 - static u8 pre_parse_finished_bd(struct bd_status *status, void *resp) 151 + static void pre_parse_finished_bd(struct bd_status *status, void *resp) 151 152 { 152 153 struct sec_sqe *bd = resp; 153 154 ··· 157 158 SEC_FLAG_MASK) >> SEC_FLAG_OFFSET; 158 159 status->tag = le16_to_cpu(bd->type2.tag); 159 160 status->err_type = bd->type2.error_type; 160 - 161 - return bd->type_cipher_auth & SEC_TYPE_MASK; 162 161 } 163 162 164 - static u8 pre_parse_finished_bd3(struct bd_status *status, void *resp) 163 + static void pre_parse_finished_bd3(struct bd_status *status, void *resp) 165 164 { 166 165 struct sec_sqe3 *bd3 = resp; 167 166 ··· 169 172 SEC_FLAG_MASK) >> SEC_FLAG_OFFSET; 170 173 status->tag = le64_to_cpu(bd3->tag); 171 174 status->err_type = bd3->error_type; 172 - 173 - return le32_to_cpu(bd3->bd_param) & SEC_TYPE_MASK; 174 175 } 175 176 176 177 static int sec_cb_status_check(struct sec_req *req, ··· 239 244 struct sec_req *req, *tmp; 240 245 int ret; 241 246 242 - list_for_each_entry_safe(req, tmp, &qp_ctx->backlog.list, list) { 247 + list_for_each_entry_safe(req, tmp, &qp_ctx->qp->backlog.list, list) { 243 248 list_del(&req->list); 244 249 ctx->req_op->buf_unmap(ctx, req); 245 250 if (req->req_id >= 0) ··· 260 265 261 266 static void sec_alg_send_backlog(struct sec_ctx *ctx, struct sec_qp_ctx *qp_ctx) 262 267 { 268 + struct hisi_qp *qp = qp_ctx->qp; 263 269 struct sec_req *req, *tmp; 264 270 int ret; 265 271 266 - spin_lock_bh(&qp_ctx->backlog.lock); 267 - list_for_each_entry_safe(req, tmp, &qp_ctx->backlog.list, list) { 272 + spin_lock_bh(&qp->backlog.lock); 273 + list_for_each_entry_safe(req, tmp, &qp->backlog.list, list) { 268 274 ret = qp_send_message(req); 269 275 switch (ret) { 270 276 case -EINPROGRESS: ··· 283 287 } 284 288 285 289 unlock: 286 - spin_unlock_bh(&qp_ctx->backlog.lock); 290 + spin_unlock_bh(&qp->backlog.lock); 287 291 } 288 292 289 293 static void sec_req_cb(struct hisi_qp *qp, void *resp) 290 294 { 291 - struct sec_qp_ctx *qp_ctx = qp->qp_ctx; 292 - struct sec_dfx *dfx = &qp_ctx->ctx->sec->debug.dfx; 293 - u8 type_supported = qp_ctx->ctx->type_supported; 295 + const struct sec_sqe *sqe = qp->msg[qp->qp_status.cq_head]; 296 + struct sec_req *req = container_of(sqe, struct sec_req, sec_sqe); 297 + struct sec_ctx *ctx = req->ctx; 298 + struct sec_dfx *dfx = &ctx->sec->debug.dfx; 294 299 struct bd_status status; 295 - struct sec_ctx *ctx; 296 - struct sec_req *req; 297 300 int err; 298 - u8 type; 299 301 300 - if (type_supported == SEC_BD_TYPE2) { 301 - type = pre_parse_finished_bd(&status, resp); 302 - req = qp_ctx->req_list[status.tag]; 303 - } else { 304 - type = pre_parse_finished_bd3(&status, resp); 305 - req = (void *)(uintptr_t)status.tag; 306 - } 307 - 308 - if (unlikely(type != type_supported)) { 309 - atomic64_inc(&dfx->err_bd_cnt); 310 - pr_err("err bd type [%u]\n", type); 311 - return; 312 - } 313 - 314 - if (unlikely(!req)) { 315 - atomic64_inc(&dfx->invalid_req_cnt); 316 - atomic_inc(&qp->qp_status.used); 317 - return; 318 - } 302 + pre_parse_finished_bd(&status, resp); 319 303 320 304 req->err_type = status.err_type; 321 - ctx = req->ctx; 322 305 err = sec_cb_status_check(req, &status); 323 306 if (err) 324 307 atomic64_inc(&dfx->done_flag_cnt); ··· 305 330 atomic64_inc(&dfx->recv_cnt); 306 331 307 332 ctx->req_op->buf_unmap(ctx, req); 333 + ctx->req_op->callback(ctx, req, err); 334 + } 308 335 336 + static void sec_req_cb3(struct hisi_qp *qp, void *resp) 337 + { 338 + struct bd_status status; 339 + struct sec_ctx *ctx; 340 + struct sec_dfx *dfx; 341 + struct sec_req *req; 342 + int err; 343 + 344 + pre_parse_finished_bd3(&status, resp); 345 + 346 + req = (void *)(uintptr_t)status.tag; 347 + req->err_type = status.err_type; 348 + ctx = req->ctx; 349 + dfx = &ctx->sec->debug.dfx; 350 + 351 + err = sec_cb_status_check(req, &status); 352 + if (err) 353 + atomic64_inc(&dfx->done_flag_cnt); 354 + 355 + atomic64_inc(&dfx->recv_cnt); 356 + 357 + ctx->req_op->buf_unmap(ctx, req); 309 358 ctx->req_op->callback(ctx, req, err); 310 359 } 311 360 ··· 347 348 348 349 static int sec_alg_try_enqueue(struct sec_req *req) 349 350 { 351 + struct hisi_qp *qp = req->qp_ctx->qp; 352 + 350 353 /* Check if any request is already backlogged */ 351 - if (!list_empty(&req->backlog->list)) 354 + if (!list_empty(&qp->backlog.list)) 352 355 return -EBUSY; 353 356 354 357 /* Try to enqueue to HW ring */ ··· 360 359 361 360 static int sec_alg_send_message_maybacklog(struct sec_req *req) 362 361 { 362 + struct hisi_qp *qp = req->qp_ctx->qp; 363 363 int ret; 364 364 365 365 ret = sec_alg_try_enqueue(req); 366 366 if (ret != -EBUSY) 367 367 return ret; 368 368 369 - spin_lock_bh(&req->backlog->lock); 369 + spin_lock_bh(&qp->backlog.lock); 370 370 ret = sec_alg_try_enqueue(req); 371 371 if (ret == -EBUSY) 372 - list_add_tail(&req->list, &req->backlog->list); 373 - spin_unlock_bh(&req->backlog->lock); 372 + list_add_tail(&req->list, &qp->backlog.list); 373 + spin_unlock_bh(&qp->backlog.lock); 374 374 375 375 return ret; 376 376 } ··· 631 629 qp_ctx->qp = qp; 632 630 qp_ctx->ctx = ctx; 633 631 634 - qp->req_cb = sec_req_cb; 632 + if (ctx->type_supported == SEC_BD_TYPE3) 633 + qp->req_cb = sec_req_cb3; 634 + else 635 + qp->req_cb = sec_req_cb; 635 636 636 637 spin_lock_init(&qp_ctx->req_lock); 637 638 idr_init(&qp_ctx->req_idr); 638 - spin_lock_init(&qp_ctx->backlog.lock); 639 639 spin_lock_init(&qp_ctx->id_lock); 640 - INIT_LIST_HEAD(&qp_ctx->backlog.list); 641 640 qp_ctx->send_head = 0; 642 641 643 642 ret = sec_alloc_qp_ctx_resource(ctx, qp_ctx); ··· 1955 1952 } while (req->req_id < 0 && ++i < ctx->sec->ctx_q_num); 1956 1953 1957 1954 req->qp_ctx = qp_ctx; 1958 - req->backlog = &qp_ctx->backlog; 1959 1955 1960 1956 return 0; 1961 1957 }
+8
include/linux/hisi_acc_qm.h
··· 447 447 int (*fill_sqe)(void *sqe, void *q_parm, void *d_parm); 448 448 }; 449 449 450 + struct instance_backlog { 451 + struct list_head list; 452 + spinlock_t lock; 453 + }; 454 + 450 455 struct hisi_qp { 451 456 u32 qp_id; 452 457 u16 sq_depth; ··· 476 471 bool is_in_kernel; 477 472 u16 pasid; 478 473 struct uacce_queue *uacce_q; 474 + 475 + struct instance_backlog backlog; 476 + const void **msg; 479 477 }; 480 478 481 479 static inline int vfs_num_set(const char *val, const struct kernel_param *kp)