summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/s390/crypto/zcrypt_ep11misc.c46
1 files changed, 36 insertions, 10 deletions
diff --git a/drivers/s390/crypto/zcrypt_ep11misc.c b/drivers/s390/crypto/zcrypt_ep11misc.c
index af6582a6ca48..df50b38dc7b9 100644
--- a/drivers/s390/crypto/zcrypt_ep11misc.c
+++ b/drivers/s390/crypto/zcrypt_ep11misc.c
@@ -39,6 +39,22 @@ static const u8 def_iv[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
#define CPRB_MEMPOOL_ITEM_SIZE (8 * 1024)
static mempool_t *cprb_mempool;
+/*
+ * This is a pre-allocated memory for the device status array
+ * used within the ep11_findcard2() function. It is currently
+ * 128 * 128 * 4 bytes = 64 KB big. Usage of this memory is
+ * controlled via dev_status_mem_mutex. Needs adaption if more
+ * than 128 cards or domains to be are supported.
+ */
+#define ZCRYPT_DEV_STATUS_CARD_MAX 128
+#define ZCRYPT_DEV_STATUS_QUEUE_MAX 128
+#define ZCRYPT_DEV_STATUS_ENTRIES (ZCRYPT_DEV_STATUS_CARD_MAX * \
+ ZCRYPT_DEV_STATUS_QUEUE_MAX)
+#define ZCRYPT_DEV_STATUS_EXT_SIZE (ZCRYPT_DEV_STATUS_ENTRIES * \
+ sizeof(struct zcrypt_device_status_ext))
+static void *dev_status_mem;
+static DEFINE_MUTEX(dev_status_mem_mutex);
+
/* ep11 card info cache */
struct card_list_entry {
struct list_head list;
@@ -1602,16 +1618,15 @@ int ep11_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
struct ep11_domain_info edi;
struct ep11_card_info eci;
- /* fetch status of all crypto cards */
- device_status = kvcalloc(MAX_ZDEV_ENTRIES_EXT,
- sizeof(struct zcrypt_device_status_ext),
- GFP_KERNEL);
- if (!device_status)
- return -ENOMEM;
+ /* occupy the device status memory */
+ mutex_lock(&dev_status_mem_mutex);
+ memset(dev_status_mem, 0, ZCRYPT_DEV_STATUS_EXT_SIZE);
+ device_status = (struct zcrypt_device_status_ext *)dev_status_mem;
+ /* fetch crypto device status into this struct */
zcrypt_device_status_mask_ext(device_status,
- MAX_ZDEV_CARDIDS_EXT,
- MAX_ZDEV_DOMAINS_EXT);
+ ZCRYPT_DEV_STATUS_CARD_MAX,
+ ZCRYPT_DEV_STATUS_QUEUE_MAX);
/* allocate 1k space for up to 256 apqns */
_apqns = kmalloc_array(256, sizeof(u32), GFP_KERNEL);
@@ -1621,7 +1636,7 @@ int ep11_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
}
/* walk through all the crypto apqnss */
- for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) {
+ for (i = 0; i < ZCRYPT_DEV_STATUS_ENTRIES; i++) {
card = AP_QID_CARD(device_status[i].qid);
dom = AP_QID_QUEUE(device_status[i].qid);
/* check online state */
@@ -1672,7 +1687,8 @@ int ep11_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
}
out:
- kvfree(device_status);
+ mutex_unlock(&dev_status_mem_mutex);
+
return rc;
}
EXPORT_SYMBOL(ep11_findcard2);
@@ -1685,11 +1701,21 @@ int __init zcrypt_ep11misc_init(void)
if (!cprb_mempool)
return -ENOMEM;
+ /* Pre-allocate one crypto status card struct used in ep11_findcard2() */
+ dev_status_mem = kvmalloc(ZCRYPT_DEV_STATUS_EXT_SIZE, GFP_KERNEL);
+ if (!dev_status_mem) {
+ mempool_destroy(cprb_mempool);
+ return -ENOMEM;
+ }
+
return 0;
}
void zcrypt_ep11misc_exit(void)
{
card_cache_free();
+ mutex_lock(&dev_status_mem_mutex);
+ kvfree(dev_status_mem);
+ mutex_unlock(&dev_status_mem_mutex);
mempool_destroy(cprb_mempool);
}