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/qm - add reference counting to queues for tfm kernel reuse

Add reference counting to queues. When all queues are occupied, tfm
will reuse queues with the same algorithm type that have already
been allocated in the kernel. The corresponding queue will be
released when the reference count reaches 1.

Reviewed-by: Longfang Liu <liulongfang@huawei.com>
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
47054897 72f3bbeb

+52 -14
+51 -14
drivers/crypto/hisilicon/qm.c
··· 2002 2002 *addr = 0; 2003 2003 } 2004 2004 2005 - static struct hisi_qp *qm_create_qp_nolock(struct hisi_qm *qm, u8 alg_type) 2005 + static struct hisi_qp *find_shareable_qp(struct hisi_qm *qm, u8 alg_type, bool is_in_kernel) 2006 + { 2007 + struct device *dev = &qm->pdev->dev; 2008 + struct hisi_qp *share_qp = NULL; 2009 + struct hisi_qp *qp; 2010 + u32 ref_count = ~0; 2011 + int i; 2012 + 2013 + if (!is_in_kernel) 2014 + goto queues_busy; 2015 + 2016 + for (i = 0; i < qm->qp_num; i++) { 2017 + qp = &qm->qp_array[i]; 2018 + if (qp->is_in_kernel && qp->alg_type == alg_type && qp->ref_count < ref_count) { 2019 + ref_count = qp->ref_count; 2020 + share_qp = qp; 2021 + } 2022 + } 2023 + 2024 + if (share_qp) { 2025 + share_qp->ref_count++; 2026 + return share_qp; 2027 + } 2028 + 2029 + queues_busy: 2030 + dev_info_ratelimited(dev, "All %u queues of QM are busy and no shareable queue\n", 2031 + qm->qp_num); 2032 + atomic64_inc(&qm->debug.dfx.create_qp_err_cnt); 2033 + return ERR_PTR(-EBUSY); 2034 + } 2035 + 2036 + static struct hisi_qp *qm_create_qp_nolock(struct hisi_qm *qm, u8 alg_type, bool is_in_kernel) 2006 2037 { 2007 2038 struct device *dev = &qm->pdev->dev; 2008 2039 struct hisi_qp *qp; ··· 2044 2013 return ERR_PTR(-EPERM); 2045 2014 } 2046 2015 2047 - if (qm->qp_in_used == qm->qp_num) { 2048 - dev_info_ratelimited(dev, "All %u queues of QM are busy!\n", 2049 - qm->qp_num); 2050 - atomic64_inc(&qm->debug.dfx.create_qp_err_cnt); 2051 - return ERR_PTR(-EBUSY); 2052 - } 2016 + /* Try to find a shareable queue when all queues are busy */ 2017 + if (qm->qp_in_used == qm->qp_num) 2018 + return find_shareable_qp(qm, alg_type, is_in_kernel); 2053 2019 2054 2020 qp_id = idr_alloc_cyclic(&qm->qp_idr, NULL, 0, qm->qp_num, GFP_ATOMIC); 2055 2021 if (qp_id < 0) { ··· 2062 2034 2063 2035 qp->event_cb = NULL; 2064 2036 qp->req_cb = NULL; 2065 - qp->qp_id = qp_id; 2066 2037 qp->alg_type = alg_type; 2067 - qp->is_in_kernel = true; 2038 + qp->is_in_kernel = is_in_kernel; 2068 2039 qm->qp_in_used++; 2040 + qp->ref_count = 1; 2069 2041 2070 2042 return qp; 2071 2043 } ··· 2087 2059 return ERR_PTR(ret); 2088 2060 2089 2061 down_write(&qm->qps_lock); 2090 - qp = qm_create_qp_nolock(qm, alg_type); 2062 + qp = qm_create_qp_nolock(qm, alg_type, false); 2091 2063 up_write(&qm->qps_lock); 2092 2064 2093 2065 if (IS_ERR(qp)) ··· 2486 2458 qp->uacce_q = q; 2487 2459 qp->event_cb = qm_qp_event_notifier; 2488 2460 qp->pasid = arg; 2489 - qp->is_in_kernel = false; 2490 2461 2491 2462 return 0; 2492 2463 } ··· 3584 3557 { 3585 3558 struct hisi_qm *qm = qp->qm; 3586 3559 3560 + if (--qp->ref_count) 3561 + return; 3562 + 3587 3563 qm->qp_in_used--; 3588 3564 idr_remove(&qm->qp_idr, qp->qp_id); 3589 3565 } ··· 3606 3576 down_write(&qps[0]->qm->qps_lock); 3607 3577 3608 3578 for (i = qp_num - 1; i >= 0; i--) { 3609 - qm_stop_qp_nolock(qps[i]); 3579 + if (qps[i]->ref_count == 1) 3580 + qm_stop_qp_nolock(qps[i]); 3581 + 3610 3582 qm_release_qp_nolock(qps[i]); 3611 3583 } 3612 3584 ··· 3637 3605 3638 3606 down_write(&qm->qps_lock); 3639 3607 for (i = 0; i < qp_num; i++) { 3640 - qps[i] = qm_create_qp_nolock(qm, alg_type[i]); 3608 + qps[i] = qm_create_qp_nolock(qm, alg_type[i], true); 3641 3609 if (IS_ERR(qps[i])) { 3642 3610 ret = -ENODEV; 3643 3611 goto stop_and_free; 3644 3612 } 3613 + 3614 + if (qps[i]->ref_count != 1) 3615 + continue; 3645 3616 3646 3617 ret = qm_start_qp_nolock(qps[i], 0); 3647 3618 if (ret) { ··· 3658 3623 3659 3624 stop_and_free: 3660 3625 for (i--; i >= 0; i--) { 3661 - qm_stop_qp_nolock(qps[i]); 3626 + if (qps[i]->ref_count == 1) 3627 + qm_stop_qp_nolock(qps[i]); 3628 + 3662 3629 qm_release_qp_nolock(qps[i]); 3663 3630 } 3664 3631 up_write(&qm->qps_lock);
+1
include/linux/hisi_acc_qm.h
··· 475 475 u16 pasid; 476 476 struct uacce_queue *uacce_q; 477 477 478 + u32 ref_count; 478 479 spinlock_t qp_lock; 479 480 struct instance_backlog backlog; 480 481 const void **msg;