aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/crypto/zcrypt_api.c
diff options
context:
space:
mode:
authorIngo Tuchscherer <ingo.tuchscherer@de.ibm.com>2013-11-20 04:47:13 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2013-12-18 11:37:15 -0500
commit91f3e3eaba4413e76ce8e12e3ef10525a889142f (patch)
treee4cef25c9b51388a462776c6a8e642571fa2f19b /drivers/s390/crypto/zcrypt_api.c
parent9efe4f2992025c3a4027c60bf36ae9d710ca3781 (diff)
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>
Diffstat (limited to 'drivers/s390/crypto/zcrypt_api.c')
-rw-r--r--drivers/s390/crypto/zcrypt_api.c109
1 files changed, 106 insertions, 3 deletions
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index 31cfaa556072..4b824b15194f 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -44,6 +44,8 @@
44#include "zcrypt_debug.h" 44#include "zcrypt_debug.h"
45#include "zcrypt_api.h" 45#include "zcrypt_api.h"
46 46
47#include "zcrypt_msgtype6.h"
48
47/* 49/*
48 * Module description. 50 * Module description.
49 */ 51 */
@@ -554,9 +556,9 @@ static long zcrypt_send_cprb(struct ica_xcRB *xcRB)
554 spin_lock_bh(&zcrypt_device_lock); 556 spin_lock_bh(&zcrypt_device_lock);
555 list_for_each_entry(zdev, &zcrypt_device_list, list) { 557 list_for_each_entry(zdev, &zcrypt_device_list, list) {
556 if (!zdev->online || !zdev->ops->send_cprb || 558 if (!zdev->online || !zdev->ops->send_cprb ||
557 (xcRB->user_defined != AUTOSELECT && 559 (zdev->ops->variant == MSGTYPE06_VARIANT_EP11) ||
558 AP_QID_DEVICE(zdev->ap_dev->qid) != xcRB->user_defined) 560 (xcRB->user_defined != AUTOSELECT &&
559 ) 561 AP_QID_DEVICE(zdev->ap_dev->qid) != xcRB->user_defined))
560 continue; 562 continue;
561 zcrypt_device_get(zdev); 563 zcrypt_device_get(zdev);
562 get_device(&zdev->ap_dev->device); 564 get_device(&zdev->ap_dev->device);
@@ -581,6 +583,90 @@ static long zcrypt_send_cprb(struct ica_xcRB *xcRB)
581 return -ENODEV; 583 return -ENODEV;
582} 584}
583 585
586struct ep11_target_dev_list {
587 unsigned short targets_num;
588 struct ep11_target_dev *targets;
589};
590
591static bool is_desired_ep11dev(unsigned int dev_qid,
592 struct ep11_target_dev_list dev_list)
593{
594 int n;
595
596 for (n = 0; n < dev_list.targets_num; n++, dev_list.targets++) {
597 if ((AP_QID_DEVICE(dev_qid) == dev_list.targets->ap_id) &&
598 (AP_QID_QUEUE(dev_qid) == dev_list.targets->dom_id)) {
599 return true;
600 }
601 }
602 return false;
603}
604
605static long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb)
606{
607 struct zcrypt_device *zdev;
608 bool autoselect = false;
609 int rc;
610 struct ep11_target_dev_list ep11_dev_list = {
611 .targets_num = 0x00,
612 .targets = NULL,
613 };
614
615 ep11_dev_list.targets_num = (unsigned short) xcrb->targets_num;
616
617 /* empty list indicates autoselect (all available targets) */
618 if (ep11_dev_list.targets_num == 0)
619 autoselect = true;
620 else {
621 ep11_dev_list.targets = kcalloc((unsigned short)
622 xcrb->targets_num,
623 sizeof(struct ep11_target_dev),
624 GFP_KERNEL);
625 if (!ep11_dev_list.targets)
626 return -ENOMEM;
627
628 if (copy_from_user(ep11_dev_list.targets,
629 (struct ep11_target_dev *)xcrb->targets,
630 xcrb->targets_num *
631 sizeof(struct ep11_target_dev)))
632 return -EFAULT;
633 }
634
635 spin_lock_bh(&zcrypt_device_lock);
636 list_for_each_entry(zdev, &zcrypt_device_list, list) {
637 /* check if device is eligible */
638 if (!zdev->online ||
639 zdev->ops->variant != MSGTYPE06_VARIANT_EP11)
640 continue;
641
642 /* check if device is selected as valid target */
643 if (!is_desired_ep11dev(zdev->ap_dev->qid, ep11_dev_list) &&
644 !autoselect)
645 continue;
646
647 zcrypt_device_get(zdev);
648 get_device(&zdev->ap_dev->device);
649 zdev->request_count++;
650 __zcrypt_decrease_preference(zdev);
651 if (try_module_get(zdev->ap_dev->drv->driver.owner)) {
652 spin_unlock_bh(&zcrypt_device_lock);
653 rc = zdev->ops->send_ep11_cprb(zdev, xcrb);
654 spin_lock_bh(&zcrypt_device_lock);
655 module_put(zdev->ap_dev->drv->driver.owner);
656 } else {
657 rc = -EAGAIN;
658 }
659 zdev->request_count--;
660 __zcrypt_increase_preference(zdev);
661 put_device(&zdev->ap_dev->device);
662 zcrypt_device_put(zdev);
663 spin_unlock_bh(&zcrypt_device_lock);
664 return rc;
665 }
666 spin_unlock_bh(&zcrypt_device_lock);
667 return -ENODEV;
668}
669
584static long zcrypt_rng(char *buffer) 670static long zcrypt_rng(char *buffer)
585{ 671{
586 struct zcrypt_device *zdev; 672 struct zcrypt_device *zdev;
@@ -784,6 +870,23 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd,
784 return -EFAULT; 870 return -EFAULT;
785 return rc; 871 return rc;
786 } 872 }
873 case ZSENDEP11CPRB: {
874 struct ep11_urb __user *uxcrb = (void __user *)arg;
875 struct ep11_urb xcrb;
876 if (copy_from_user(&xcrb, uxcrb, sizeof(xcrb)))
877 return -EFAULT;
878 do {
879 rc = zcrypt_send_ep11_cprb(&xcrb);
880 } while (rc == -EAGAIN);
881 /* on failure: retry once again after a requested rescan */
882 if ((rc == -ENODEV) && (zcrypt_process_rescan()))
883 do {
884 rc = zcrypt_send_ep11_cprb(&xcrb);
885 } while (rc == -EAGAIN);
886 if (copy_to_user(uxcrb, &xcrb, sizeof(xcrb)))
887 return -EFAULT;
888 return rc;
889 }
787 case Z90STAT_STATUS_MASK: { 890 case Z90STAT_STATUS_MASK: {
788 char status[AP_DEVICES]; 891 char status[AP_DEVICES];
789 zcrypt_status_mask(status); 892 zcrypt_status_mask(status);