s390/zcrypt: add support for EP11 coprocessor cards
This feature extends the generic cryptographic device driver (zcrypt) with a new capability to service EP11 requests for the Crypto Express4S card in EP11 (Enterprise PKCS#11 mode) coprocessor mode. Signed-off-by: Ingo Tuchscherer <ingo.tuchscherer@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:

committed by
Martin Schwidefsky

parent
9efe4f2992
commit
91f3e3eaba
@@ -44,6 +44,8 @@
|
||||
#include "zcrypt_debug.h"
|
||||
#include "zcrypt_api.h"
|
||||
|
||||
#include "zcrypt_msgtype6.h"
|
||||
|
||||
/*
|
||||
* Module description.
|
||||
*/
|
||||
@@ -554,9 +556,9 @@ static long zcrypt_send_cprb(struct ica_xcRB *xcRB)
|
||||
spin_lock_bh(&zcrypt_device_lock);
|
||||
list_for_each_entry(zdev, &zcrypt_device_list, list) {
|
||||
if (!zdev->online || !zdev->ops->send_cprb ||
|
||||
(xcRB->user_defined != AUTOSELECT &&
|
||||
AP_QID_DEVICE(zdev->ap_dev->qid) != xcRB->user_defined)
|
||||
)
|
||||
(zdev->ops->variant == MSGTYPE06_VARIANT_EP11) ||
|
||||
(xcRB->user_defined != AUTOSELECT &&
|
||||
AP_QID_DEVICE(zdev->ap_dev->qid) != xcRB->user_defined))
|
||||
continue;
|
||||
zcrypt_device_get(zdev);
|
||||
get_device(&zdev->ap_dev->device);
|
||||
@@ -581,6 +583,90 @@ static long zcrypt_send_cprb(struct ica_xcRB *xcRB)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
struct ep11_target_dev_list {
|
||||
unsigned short targets_num;
|
||||
struct ep11_target_dev *targets;
|
||||
};
|
||||
|
||||
static bool is_desired_ep11dev(unsigned int dev_qid,
|
||||
struct ep11_target_dev_list dev_list)
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < dev_list.targets_num; n++, dev_list.targets++) {
|
||||
if ((AP_QID_DEVICE(dev_qid) == dev_list.targets->ap_id) &&
|
||||
(AP_QID_QUEUE(dev_qid) == dev_list.targets->dom_id)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb)
|
||||
{
|
||||
struct zcrypt_device *zdev;
|
||||
bool autoselect = false;
|
||||
int rc;
|
||||
struct ep11_target_dev_list ep11_dev_list = {
|
||||
.targets_num = 0x00,
|
||||
.targets = NULL,
|
||||
};
|
||||
|
||||
ep11_dev_list.targets_num = (unsigned short) xcrb->targets_num;
|
||||
|
||||
/* empty list indicates autoselect (all available targets) */
|
||||
if (ep11_dev_list.targets_num == 0)
|
||||
autoselect = true;
|
||||
else {
|
||||
ep11_dev_list.targets = kcalloc((unsigned short)
|
||||
xcrb->targets_num,
|
||||
sizeof(struct ep11_target_dev),
|
||||
GFP_KERNEL);
|
||||
if (!ep11_dev_list.targets)
|
||||
return -ENOMEM;
|
||||
|
||||
if (copy_from_user(ep11_dev_list.targets,
|
||||
(struct ep11_target_dev *)xcrb->targets,
|
||||
xcrb->targets_num *
|
||||
sizeof(struct ep11_target_dev)))
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
spin_lock_bh(&zcrypt_device_lock);
|
||||
list_for_each_entry(zdev, &zcrypt_device_list, list) {
|
||||
/* check if device is eligible */
|
||||
if (!zdev->online ||
|
||||
zdev->ops->variant != MSGTYPE06_VARIANT_EP11)
|
||||
continue;
|
||||
|
||||
/* check if device is selected as valid target */
|
||||
if (!is_desired_ep11dev(zdev->ap_dev->qid, ep11_dev_list) &&
|
||||
!autoselect)
|
||||
continue;
|
||||
|
||||
zcrypt_device_get(zdev);
|
||||
get_device(&zdev->ap_dev->device);
|
||||
zdev->request_count++;
|
||||
__zcrypt_decrease_preference(zdev);
|
||||
if (try_module_get(zdev->ap_dev->drv->driver.owner)) {
|
||||
spin_unlock_bh(&zcrypt_device_lock);
|
||||
rc = zdev->ops->send_ep11_cprb(zdev, xcrb);
|
||||
spin_lock_bh(&zcrypt_device_lock);
|
||||
module_put(zdev->ap_dev->drv->driver.owner);
|
||||
} else {
|
||||
rc = -EAGAIN;
|
||||
}
|
||||
zdev->request_count--;
|
||||
__zcrypt_increase_preference(zdev);
|
||||
put_device(&zdev->ap_dev->device);
|
||||
zcrypt_device_put(zdev);
|
||||
spin_unlock_bh(&zcrypt_device_lock);
|
||||
return rc;
|
||||
}
|
||||
spin_unlock_bh(&zcrypt_device_lock);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static long zcrypt_rng(char *buffer)
|
||||
{
|
||||
struct zcrypt_device *zdev;
|
||||
@@ -784,6 +870,23 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd,
|
||||
return -EFAULT;
|
||||
return rc;
|
||||
}
|
||||
case ZSENDEP11CPRB: {
|
||||
struct ep11_urb __user *uxcrb = (void __user *)arg;
|
||||
struct ep11_urb xcrb;
|
||||
if (copy_from_user(&xcrb, uxcrb, sizeof(xcrb)))
|
||||
return -EFAULT;
|
||||
do {
|
||||
rc = zcrypt_send_ep11_cprb(&xcrb);
|
||||
} while (rc == -EAGAIN);
|
||||
/* on failure: retry once again after a requested rescan */
|
||||
if ((rc == -ENODEV) && (zcrypt_process_rescan()))
|
||||
do {
|
||||
rc = zcrypt_send_ep11_cprb(&xcrb);
|
||||
} while (rc == -EAGAIN);
|
||||
if (copy_to_user(uxcrb, &xcrb, sizeof(xcrb)))
|
||||
return -EFAULT;
|
||||
return rc;
|
||||
}
|
||||
case Z90STAT_STATUS_MASK: {
|
||||
char status[AP_DEVICES];
|
||||
zcrypt_status_mask(status);
|
||||
|
Reference in New Issue
Block a user