Commit 0d574ad3 authored by Harald Freudenberger's avatar Harald Freudenberger Committed by Vasily Gorbik

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: default avatarHarald Freudenberger <freude@linux.ibm.com>
Reviewed-by: default avatarIngo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
parent 180a4c42
......@@ -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)
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)
/* 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;
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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment