Add a small memory pool for (pre-)allocating cca info list entries. These entries are rather small and the pool is a simple way to support the xflag ZCRYPT_XFLAG_NOMEMALLOC to avoid mallocs. Signed-off-by: Harald Freudenberger <freude@xxxxxxxxxxxxx> --- drivers/s390/crypto/zcrypt_ccamisc.c | 67 ++++++++++++++++++++-------- drivers/s390/crypto/zcrypt_ccamisc.h | 3 +- drivers/s390/crypto/zcrypt_cex4.c | 4 +- 3 files changed, 53 insertions(+), 21 deletions(-) diff --git a/drivers/s390/crypto/zcrypt_ccamisc.c b/drivers/s390/crypto/zcrypt_ccamisc.c index c1c255e45873..ccf8206ae42d 100644 --- a/drivers/s390/crypto/zcrypt_ccamisc.c +++ b/drivers/s390/crypto/zcrypt_ccamisc.c @@ -41,6 +41,10 @@ struct cca_info_list_entry { static LIST_HEAD(cca_info_list); static DEFINE_SPINLOCK(cca_info_list_lock); +/* memory pool for cca_info_list entries */ +#define INFO_ENTRY_MEMPOOL_MIN_ITEMS 8 +static mempool_t *info_mempool; + /* * Cprb memory pool held for urgend cases where no memory * can be allocated via kmalloc. This pool is only used @@ -1661,7 +1665,7 @@ static int cca_info_cache_fetch(u16 cardnr, u16 domain, struct cca_info *ci) } static void cca_info_cache_update(u16 cardnr, u16 domain, - const struct cca_info *ci) + const struct cca_info *ci, u32 xflags) { int found = 0; struct cca_info_list_entry *ptr; @@ -1676,7 +1680,9 @@ static void cca_info_cache_update(u16 cardnr, u16 domain, } } if (!found) { - ptr = kmalloc(sizeof(*ptr), GFP_ATOMIC); + ptr = (xflags & ZCRYPT_XFLAG_NOMEMALLOC) ? + mempool_alloc_preallocated(info_mempool) : + mempool_alloc(info_mempool, GFP_ATOMIC); if (!ptr) { spin_unlock_bh(&cca_info_list_lock); return; @@ -1698,7 +1704,7 @@ static void cca_info_cache_scrub(u16 cardnr, u16 domain) if (ptr->cardnr == cardnr && ptr->domain == domain) { list_del(&ptr->list); - kfree(ptr); + mempool_free(ptr, info_mempool); break; } } @@ -1712,7 +1718,7 @@ static void __exit mkvp_cache_free(void) spin_lock_bh(&cca_info_list_lock); list_for_each_entry_safe(ptr, pnext, &cca_info_list, list) { list_del(&ptr->list); - kfree(ptr); + mempool_free(ptr, info_mempool); } spin_unlock_bh(&cca_info_list_lock); } @@ -1720,14 +1726,14 @@ static void __exit mkvp_cache_free(void) /* * Fetch cca_info values via query_crypto_facility from adapter. */ -static int fetch_cca_info(u16 cardnr, u16 domain, struct cca_info *ci) +static int fetch_cca_info(u16 cardnr, u16 domain, + struct cca_info *ci, u32 xflags) { void *mem; int rc, found = 0; size_t rlen, vlen; u8 *rarray, *varray; struct zcrypt_device_status_ext devstat; - u32 xflags = 0; memset(ci, 0, sizeof(*ci)); @@ -1801,15 +1807,15 @@ static int fetch_cca_info(u16 cardnr, u16 domain, struct cca_info *ci) /* * Fetch cca information about a CCA queue. */ -int cca_get_info(u16 card, u16 dom, struct cca_info *ci, int verify) +int cca_get_info(u16 card, u16 dom, struct cca_info *ci, int verify, u32 xflags) { int rc; rc = cca_info_cache_fetch(card, dom, ci); if (rc || verify) { - rc = fetch_cca_info(card, dom, ci); + rc = fetch_cca_info(card, dom, ci, xflags); if (rc == 0) - cca_info_cache_update(card, dom, ci); + cca_info_cache_update(card, dom, ci, xflags); } return rc; @@ -1827,6 +1833,7 @@ static int findcard(u64 mkvp, u16 *pcardnr, u16 *pdomain, u16 card, dom; struct cca_info ci; int i, rc, oi = -1; + u32 xflg = 0; /* xflags */ /* mkvp must not be zero, minhwtype needs to be >= 0 */ if (mkvp == 0 || minhwtype < 0) @@ -1856,8 +1863,8 @@ static int findcard(u64 mkvp, u16 *pcardnr, u16 *pdomain, if (!verify) break; /* verify: refresh card info */ - if (fetch_cca_info(card, dom, &ci) == 0) { - cca_info_cache_update(card, dom, &ci); + if (fetch_cca_info(card, dom, &ci, xflg) == 0) { + cca_info_cache_update(card, dom, &ci, xflg); if (ci.hwtype >= minhwtype && ci.cur_aes_mk_state == '2' && ci.cur_aes_mkvp == mkvp) @@ -1879,8 +1886,8 @@ static int findcard(u64 mkvp, u16 *pcardnr, u16 *pdomain, card = AP_QID_CARD(device_status[i].qid); dom = AP_QID_QUEUE(device_status[i].qid); /* fresh fetch mkvp from adapter */ - if (fetch_cca_info(card, dom, &ci) == 0) { - cca_info_cache_update(card, dom, &ci); + if (fetch_cca_info(card, dom, &ci, xflg) == 0) { + cca_info_cache_update(card, dom, &ci, xflg); if (ci.hwtype >= minhwtype && ci.cur_aes_mk_state == '2' && ci.cur_aes_mkvp == mkvp) @@ -1951,6 +1958,7 @@ int cca_findcard2(u32 *apqns, u32 *nr_apqns, u16 cardnr, u16 domain, int i, card, dom, curmatch, oldmatch, rc; struct cca_info ci; u32 _nr_apqns = 0; + u32 xflags = 0; /* occupy the device status memory */ mutex_lock(&dev_status_mem_mutex); @@ -1979,7 +1987,7 @@ int cca_findcard2(u32 *apqns, u32 *nr_apqns, u16 cardnr, u16 domain, if (domain != 0xFFFF && dom != domain) continue; /* get cca info on this apqn */ - if (cca_get_info(card, dom, &ci, verify)) + if (cca_get_info(card, dom, &ci, verify, xflags)) continue; /* current master key needs to be valid */ if (mktype == AES_MK_SET && ci.cur_aes_mk_state != '2') @@ -2030,6 +2038,8 @@ EXPORT_SYMBOL(cca_findcard2); int __init zcrypt_ccamisc_init(void) { + int rc = -ENOMEM; + /* Pre-allocate a small memory pool for cca cprbs. */ cprb_mempool = mempool_create_kmalloc_pool(CPRB_MEMPOOL_MIN_ITEMS, CPRB_MEMPOOL_ITEM_SIZE); @@ -2037,19 +2047,39 @@ int __init zcrypt_ccamisc_init(void) ZCRYPT_DBF_ERR("%s mempool_create(%d,%d) failed: %ld\n", __func__, CPRB_MEMPOOL_MIN_ITEMS, CPRB_MEMPOOL_ITEM_SIZE, PTR_ERR(cprb_mempool)); + rc = PTR_ERR(cprb_mempool); cprb_mempool = NULL; - return -ENOMEM; + goto out; + } + + /* Pre-allocate a small memory pool for cca info list entries */ + info_mempool = mempool_create_kmalloc_pool(INFO_ENTRY_MEMPOOL_MIN_ITEMS, + sizeof(struct cca_info_list_entry)); + if (IS_ERR(info_mempool)) { + ZCRYPT_DBF_ERR("%s info entry mempool_create(%d,%d) failed: %ld\n", + __func__, INFO_ENTRY_MEMPOOL_MIN_ITEMS, + (int)sizeof(struct cca_info_list_entry), + PTR_ERR(info_mempool)); + rc = PTR_ERR(info_mempool); + info_mempool = NULL; + goto out; } /* Pre-allocate one crypto status card struct used in findcard() */ dev_status_mem = kvmalloc(ZCRYPT_DEV_STATUS_EXT2_SIZE, GFP_KERNEL); if (!dev_status_mem) { ZCRYPT_DBF_ERR("%s allocation of dev_status_mem failed\n", __func__); - mempool_destroy(cprb_mempool); - return -ENOMEM; + goto out; } - return 0; + rc = 0; + +out: + if (rc) { + mempool_destroy(cprb_mempool); + mempool_destroy(info_mempool); + } + return rc; } void zcrypt_ccamisc_exit(void) @@ -2057,4 +2087,5 @@ void zcrypt_ccamisc_exit(void) mkvp_cache_free(); kvfree(dev_status_mem); mempool_destroy(cprb_mempool); + mempool_destroy(info_mempool); } diff --git a/drivers/s390/crypto/zcrypt_ccamisc.h b/drivers/s390/crypto/zcrypt_ccamisc.h index bed647a42eb2..966f0eaf3c4c 100644 --- a/drivers/s390/crypto/zcrypt_ccamisc.h +++ b/drivers/s390/crypto/zcrypt_ccamisc.h @@ -268,7 +268,8 @@ struct cca_info { /* * Fetch cca information about an CCA queue. */ -int cca_get_info(u16 card, u16 dom, struct cca_info *ci, int verify); +int cca_get_info(u16 card, u16 dom, struct cca_info *ci, + int verify, u32 xflags); int zcrypt_ccamisc_init(void); void zcrypt_ccamisc_exit(void); diff --git a/drivers/s390/crypto/zcrypt_cex4.c b/drivers/s390/crypto/zcrypt_cex4.c index 64df7d2f6266..49a638d373fa 100644 --- a/drivers/s390/crypto/zcrypt_cex4.c +++ b/drivers/s390/crypto/zcrypt_cex4.c @@ -86,7 +86,7 @@ static ssize_t cca_serialnr_show(struct device *dev, memset(&ci, 0, sizeof(ci)); if (ap_domain_index >= 0) - cca_get_info(ac->id, ap_domain_index, &ci, zc->online); + cca_get_info(ac->id, ap_domain_index, &ci, zc->online, 0); return sysfs_emit(buf, "%s\n", ci.serial); } @@ -120,7 +120,7 @@ static ssize_t cca_mkvps_show(struct device *dev, cca_get_info(AP_QID_CARD(zq->queue->qid), AP_QID_QUEUE(zq->queue->qid), - &ci, zq->online); + &ci, zq->online, 0); if (ci.new_aes_mk_state >= '1' && ci.new_aes_mk_state <= '3') n += sysfs_emit_at(buf, n, "AES NEW: %s 0x%016llx\n", -- 2.43.0