s390/zcrypt: simplify cca_findcard2 loop code

Instead of two times go through the list of available AP devices
(which may be up to 256 * 256 entries) this patch reworks the code do
only run through once.  The price is instead of reporting all possible
devices to the caller only the first 256 devices are collected.
However, having to choose from 256 AP devices is plenty of resources
and should fulfill the caller's requirements. On the other side
the loop code is much simplier and more easy to maintain.

Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Reviewed-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
This commit is contained in:
Harald Freudenberger 2020-09-09 12:02:46 +02:00 committed by Vasily Gorbik
parent 180a4c42e5
commit 0d574ad33e

View File

@ -1685,12 +1685,10 @@ int cca_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
int minhwtype, u64 cur_mkvp, u64 old_mkvp, int verify)
{
struct zcrypt_device_status_ext *device_status;
int i, n, card, dom, curmatch, oldmatch, rc = 0;
u32 *_apqns = NULL, _nr_apqns = 0;
int i, card, dom, curmatch, oldmatch, rc = 0;
struct cca_info ci;
*apqns = NULL;
*nr_apqns = 0;
/* fetch status of all crypto cards */
device_status = kmalloc_array(MAX_ZDEV_ENTRIES_EXT,
sizeof(struct zcrypt_device_status_ext),
@ -1699,67 +1697,64 @@ int cca_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
return -ENOMEM;
zcrypt_device_status_mask_ext(device_status);
/* loop two times: first gather eligible apqns, then store them */
while (1) {
n = 0;
/* walk through all the crypto cards */
for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) {
card = AP_QID_CARD(device_status[i].qid);
dom = AP_QID_QUEUE(device_status[i].qid);
/* check online state */
if (!device_status[i].online)
/* allocate 1k space for up to 256 apqns */
_apqns = kmalloc_array(256, sizeof(u32), GFP_KERNEL);
if (!_apqns) {
kvfree(device_status);
return -ENOMEM;
}
/* walk through all the crypto apqnss */
for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) {
card = AP_QID_CARD(device_status[i].qid);
dom = AP_QID_QUEUE(device_status[i].qid);
/* check online state */
if (!device_status[i].online)
continue;
/* check for cca functions */
if (!(device_status[i].functions & 0x04))
continue;
/* check cardnr */
if (cardnr != 0xFFFF && card != cardnr)
continue;
/* check domain */
if (domain != 0xFFFF && dom != domain)
continue;
/* get cca info on this apqn */
if (cca_get_info(card, dom, &ci, verify))
continue;
/* current master key needs to be valid */
if (ci.cur_mk_state != '2')
continue;
/* check min hardware type */
if (minhwtype > 0 && minhwtype > ci.hwtype)
continue;
if (cur_mkvp || old_mkvp) {
/* check mkvps */
curmatch = oldmatch = 0;
if (cur_mkvp && cur_mkvp == ci.cur_mkvp)
curmatch = 1;
if (old_mkvp && ci.old_mk_state == '2' &&
old_mkvp == ci.old_mkvp)
oldmatch = 1;
if ((cur_mkvp || old_mkvp) &&
(curmatch + oldmatch < 1))
continue;
/* check for cca functions */
if (!(device_status[i].functions & 0x04))
continue;
/* check cardnr */
if (cardnr != 0xFFFF && card != cardnr)
continue;
/* check domain */
if (domain != 0xFFFF && dom != domain)
continue;
/* get cca info on this apqn */
if (cca_get_info(card, dom, &ci, verify))
continue;
/* current master key needs to be valid */
if (ci.cur_mk_state != '2')
continue;
/* check min hardware type */
if (minhwtype > 0 && minhwtype > ci.hwtype)
continue;
if (cur_mkvp || old_mkvp) {
/* check mkvps */
curmatch = oldmatch = 0;
if (cur_mkvp && cur_mkvp == ci.cur_mkvp)
curmatch = 1;
if (old_mkvp && ci.old_mk_state == '2' &&
old_mkvp == ci.old_mkvp)
oldmatch = 1;
if ((cur_mkvp || old_mkvp) &&
(curmatch + oldmatch < 1))
continue;
}
/* apqn passed all filtering criterons */
if (*apqns && n < *nr_apqns)
(*apqns)[n] = (((u16)card) << 16) | ((u16) dom);
n++;
}
/* loop 2nd time: array has been filled */
if (*apqns)
break;
/* loop 1st time: have # of eligible apqns in n */
if (!n) {
rc = -ENODEV; /* no eligible apqns found */
break;
}
*nr_apqns = n;
/* allocate array to store n apqns into */
*apqns = kmalloc_array(n, sizeof(u32), GFP_KERNEL);
if (!*apqns) {
rc = -ENOMEM;
break;
}
verify = 0;
/* apqn passed all filtering criterons, add to the array */
if (_nr_apqns < 256)
_apqns[_nr_apqns++] = (((u16)card) << 16) | ((u16) dom);
}
/* nothing found ? */
if (!_nr_apqns) {
kfree(_apqns);
rc = -ENODEV;
} else {
/* no re-allocation, simple return the _apqns array */
*apqns = _apqns;
*nr_apqns = _nr_apqns;
rc = 0;
}
kfree(device_status);