aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/crypto')
-rw-r--r--drivers/s390/crypto/ap_bus.c227
-rw-r--r--drivers/s390/crypto/ap_bus.h12
-rw-r--r--drivers/s390/crypto/pkey_api.c45
-rw-r--r--drivers/s390/crypto/zcrypt_api.c66
-rw-r--r--drivers/s390/crypto/zcrypt_api.h2
-rw-r--r--drivers/s390/crypto/zcrypt_card.c13
-rw-r--r--drivers/s390/crypto/zcrypt_cex2a.c2
-rw-r--r--drivers/s390/crypto/zcrypt_cex4.c2
-rw-r--r--drivers/s390/crypto/zcrypt_queue.c6
9 files changed, 310 insertions, 65 deletions
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 485cbfcbf06e..2758d05a802d 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -1,11 +1,12 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * Copyright IBM Corp. 2006, 2012
+ * Copyright IBM Corp. 2006, 2020
* Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
* Martin Schwidefsky <schwidefsky@de.ibm.com>
* Ralph Wuerthner <rwuerthn@de.ibm.com>
* Felix Beck <felix.beck@de.ibm.com>
* Holger Dengler <hd@linux.vnet.ibm.com>
+ * Harald Freudenberger <freude@linux.ibm.com>
*
* Adjunct processor bus.
*/
@@ -73,6 +74,12 @@ EXPORT_SYMBOL(ap_perms);
DEFINE_MUTEX(ap_perms_mutex);
EXPORT_SYMBOL(ap_perms_mutex);
+/* # of bus scans since init */
+static atomic64_t ap_scan_bus_count;
+
+/* completion for initial APQN bindings complete */
+static DECLARE_COMPLETION(ap_init_apqn_bindings_complete);
+
static struct ap_config_info *ap_qci_info;
/*
@@ -577,23 +584,125 @@ static int ap_bus_match(struct device *dev, struct device_driver *drv)
*/
static int ap_uevent(struct device *dev, struct kobj_uevent_env *env)
{
+ int rc;
struct ap_device *ap_dev = to_ap_dev(dev);
- int retval = 0;
- if (!ap_dev)
- return -ENODEV;
+ /* Uevents from ap bus core don't need extensions to the env */
+ if (dev == ap_root_device)
+ return 0;
/* Set up DEV_TYPE environment variable. */
- retval = add_uevent_var(env, "DEV_TYPE=%04X", ap_dev->device_type);
- if (retval)
- return retval;
+ rc = add_uevent_var(env, "DEV_TYPE=%04X", ap_dev->device_type);
+ if (rc)
+ return rc;
/* Add MODALIAS= */
- retval = add_uevent_var(env, "MODALIAS=ap:t%02X", ap_dev->device_type);
+ rc = add_uevent_var(env, "MODALIAS=ap:t%02X", ap_dev->device_type);
+ if (rc)
+ return rc;
+
+ return 0;
+}
+
+static void ap_send_init_scan_done_uevent(void)
+{
+ char *envp[] = { "INITSCAN=done", NULL };
+
+ kobject_uevent_env(&ap_root_device->kobj, KOBJ_CHANGE, envp);
+}
+
+static void ap_send_bindings_complete_uevent(void)
+{
+ char *envp[] = { "BINDINGS=complete", NULL };
+
+ kobject_uevent_env(&ap_root_device->kobj, KOBJ_CHANGE, envp);
+}
+
+/*
+ * calc # of bound APQNs
+ */
- return retval;
+struct __ap_calc_ctrs {
+ unsigned int apqns;
+ unsigned int bound;
+};
+
+static int __ap_calc_helper(struct device *dev, void *arg)
+{
+ struct __ap_calc_ctrs *pctrs = (struct __ap_calc_ctrs *) arg;
+
+ if (is_queue_dev(dev)) {
+ pctrs->apqns++;
+ if ((to_ap_dev(dev))->drv)
+ pctrs->bound++;
+ }
+
+ return 0;
}
+static void ap_calc_bound_apqns(unsigned int *apqns, unsigned int *bound)
+{
+ struct __ap_calc_ctrs ctrs;
+
+ memset(&ctrs, 0, sizeof(ctrs));
+ bus_for_each_dev(&ap_bus_type, NULL, (void *) &ctrs, __ap_calc_helper);
+
+ *apqns = ctrs.apqns;
+ *bound = ctrs.bound;
+}
+
+/*
+ * After initial ap bus scan do check if all existing APQNs are
+ * bound to device drivers.
+ */
+static void ap_check_bindings_complete(void)
+{
+ unsigned int apqns, bound;
+
+ if (atomic64_read(&ap_scan_bus_count) >= 1) {
+ ap_calc_bound_apqns(&apqns, &bound);
+ if (bound == apqns) {
+ if (!completion_done(&ap_init_apqn_bindings_complete)) {
+ complete_all(&ap_init_apqn_bindings_complete);
+ AP_DBF(DBF_INFO, "%s complete\n", __func__);
+ }
+ ap_send_bindings_complete_uevent();
+ }
+ }
+}
+
+/*
+ * Interface to wait for the AP bus to have done one initial ap bus
+ * scan and all detected APQNs have been bound to device drivers.
+ * If these both conditions are not fulfilled, this function blocks
+ * on a condition with wait_for_completion_interruptible_timeout().
+ * If these both conditions are fulfilled (before the timeout hits)
+ * the return value is 0. If the timeout (in jiffies) hits instead
+ * -ETIME is returned. On failures negative return values are
+ * returned to the caller.
+ */
+int ap_wait_init_apqn_bindings_complete(unsigned long timeout)
+{
+ long l;
+
+ if (completion_done(&ap_init_apqn_bindings_complete))
+ return 0;
+
+ if (timeout)
+ l = wait_for_completion_interruptible_timeout(
+ &ap_init_apqn_bindings_complete, timeout);
+ else
+ l = wait_for_completion_interruptible(
+ &ap_init_apqn_bindings_complete);
+ if (l < 0)
+ return l == -ERESTARTSYS ? -EINTR : l;
+ else if (l == 0 && timeout)
+ return -ETIME;
+
+ return 0;
+}
+EXPORT_SYMBOL(ap_wait_init_apqn_bindings_complete);
+
static int __ap_queue_devices_with_id_unregister(struct device *dev, void *data)
{
if (is_queue_dev(dev) &&
@@ -602,12 +711,6 @@ static int __ap_queue_devices_with_id_unregister(struct device *dev, void *data)
return 0;
}
-static struct bus_type ap_bus_type = {
- .name = "ap",
- .match = &ap_bus_match,
- .uevent = &ap_uevent,
-};
-
static int __ap_revise_reserved(struct device *dev, void *dummy)
{
int rc, card, queue, devres, drvres;
@@ -680,7 +783,10 @@ static int ap_device_probe(struct device *dev)
{
struct ap_device *ap_dev = to_ap_dev(dev);
struct ap_driver *ap_drv = to_ap_drv(dev->driver);
- int card, queue, devres, drvres, rc;
+ int card, queue, devres, drvres, rc = -ENODEV;
+
+ if (!get_device(dev))
+ return rc;
if (is_queue_dev(dev)) {
/*
@@ -697,7 +803,7 @@ static int ap_device_probe(struct device *dev)
mutex_unlock(&ap_perms_mutex);
drvres = ap_drv->flags & AP_DRIVER_FLAG_DEFAULT;
if (!!devres != !!drvres)
- return -ENODEV;
+ goto out;
}
/* Add queue/card to list of active queues/cards */
@@ -716,8 +822,12 @@ static int ap_device_probe(struct device *dev)
hash_del(&to_ap_queue(dev)->hnode);
spin_unlock_bh(&ap_queues_lock);
ap_dev->drv = NULL;
- }
+ } else
+ ap_check_bindings_complete();
+out:
+ if (rc)
+ put_device(dev);
return rc;
}
@@ -743,6 +853,9 @@ static int ap_device_remove(struct device *dev)
if (is_queue_dev(dev))
hash_del(&to_ap_queue(dev)->hnode);
spin_unlock_bh(&ap_queues_lock);
+ ap_dev->drv = NULL;
+
+ put_device(dev);
return 0;
}
@@ -1158,21 +1271,55 @@ static ssize_t aqmask_store(struct bus_type *bus, const char *buf,
static BUS_ATTR_RW(aqmask);
-static struct bus_attribute *const ap_bus_attrs[] = {
- &bus_attr_ap_domain,
- &bus_attr_ap_control_domain_mask,
- &bus_attr_ap_usage_domain_mask,
- &bus_attr_ap_adapter_mask,
- &bus_attr_config_time,
- &bus_attr_poll_thread,
- &bus_attr_ap_interrupts,
- &bus_attr_poll_timeout,
- &bus_attr_ap_max_domain_id,
- &bus_attr_ap_max_adapter_id,
- &bus_attr_apmask,
- &bus_attr_aqmask,
+static ssize_t scans_show(struct bus_type *bus, char *buf)
+{
+ return scnprintf(buf, PAGE_SIZE, "%llu\n",
+ atomic64_read(&ap_scan_bus_count));
+}
+
+static BUS_ATTR_RO(scans);
+
+static ssize_t bindings_show(struct bus_type *bus, char *buf)
+{
+ int rc;
+ unsigned int apqns, n;
+
+ ap_calc_bound_apqns(&apqns, &n);
+ if (atomic64_read(&ap_scan_bus_count) >= 1 && n == apqns)
+ rc = scnprintf(buf, PAGE_SIZE, "%u/%u (complete)\n", n, apqns);
+ else
+ rc = scnprintf(buf, PAGE_SIZE, "%u/%u\n", n, apqns);
+
+ return rc;
+}
+
+static BUS_ATTR_RO(bindings);
+
+static struct attribute *ap_bus_attrs[] = {
+ &bus_attr_ap_domain.attr,
+ &bus_attr_ap_control_domain_mask.attr,
+ &bus_attr_ap_usage_domain_mask.attr,
+ &bus_attr_ap_adapter_mask.attr,
+ &bus_attr_config_time.attr,
+ &bus_attr_poll_thread.attr,
+ &bus_attr_ap_interrupts.attr,
+ &bus_attr_poll_timeout.attr,
+ &bus_attr_ap_max_domain_id.attr,
+ &bus_attr_ap_max_adapter_id.attr,
+ &bus_attr_apmask.attr,
+ &bus_attr_aqmask.attr,
+ &bus_attr_scans.attr,
+ &bus_attr_bindings.attr,
NULL,
};
+ATTRIBUTE_GROUPS(ap_bus);
+
+static struct bus_type ap_bus_type = {
+ .name = "ap",
+ .bus_groups = ap_bus_groups,
+ .match = &ap_bus_match,
+ .uevent = &ap_uevent,
+};
/**
* ap_select_domain(): Select an AP domain if possible and we haven't
@@ -1371,6 +1518,8 @@ static inline void ap_scan_domains(struct ap_card *ac)
__func__, ac->id, dom);
goto put_dev_and_continue;
}
+ /* get it and thus adjust reference counter */
+ get_device(dev);
if (decfg)
AP_DBF_INFO("%s(%d,%d) new (decfg) queue device created\n",
__func__, ac->id, dom);
@@ -1598,6 +1747,12 @@ static void ap_scan_bus(struct work_struct *unused)
ap_domain_index);
}
+ if (atomic64_inc_return(&ap_scan_bus_count) == 1) {
+ AP_DBF(DBF_DEBUG, "%s init scan complete\n", __func__);
+ ap_send_init_scan_done_uevent();
+ ap_check_bindings_complete();
+ }
+
mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ);
}
@@ -1645,7 +1800,7 @@ static void __init ap_perms_init(void)
*/
static int __init ap_module_init(void)
{
- int rc, i;
+ int rc;
rc = ap_debug_init();
if (rc)
@@ -1684,17 +1839,13 @@ static int __init ap_module_init(void)
rc = bus_register(&ap_bus_type);
if (rc)
goto out;
- for (i = 0; ap_bus_attrs[i]; i++) {
- rc = bus_create_file(&ap_bus_type, ap_bus_attrs[i]);
- if (rc)
- goto out_bus;
- }
/* Create /sys/devices/ap. */
ap_root_device = root_device_register("ap");
rc = PTR_ERR_OR_ZERO(ap_root_device);
if (rc)
goto out_bus;
+ ap_root_device->bus = &ap_bus_type;
/* Setup the AP bus rescan timer. */
timer_setup(&ap_config_timer, ap_config_timeout, 0);
@@ -1723,8 +1874,6 @@ out_work:
hrtimer_cancel(&ap_poll_timer);
root_device_unregister(ap_root_device);
out_bus:
- while (i--)
- bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
bus_unregister(&ap_bus_type);
out:
if (ap_using_interrupts())
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
index 5029b80132aa..472efd3a755c 100644
--- a/drivers/s390/crypto/ap_bus.h
+++ b/drivers/s390/crypto/ap_bus.h
@@ -350,4 +350,16 @@ int ap_parse_mask_str(const char *str,
unsigned long *bitmap, int bits,
struct mutex *lock);
+/*
+ * Interface to wait for the AP bus to have done one initial ap bus
+ * scan and all detected APQNs have been bound to device drivers.
+ * If these both conditions are not fulfilled, this function blocks
+ * on a condition with wait_for_completion_killable_timeout().
+ * If these both conditions are fulfilled (before the timeout hits)
+ * the return value is 0. If the timeout (in jiffies) hits instead
+ * -ETIME is returned. On failures negative return values are
+ * returned to the caller.
+ */
+int ap_wait_init_apqn_bindings_complete(unsigned long timeout);
+
#endif /* _AP_BUS_H_ */
diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c
index 99cb60ea663d..cf23ce1b1146 100644
--- a/drivers/s390/crypto/pkey_api.c
+++ b/drivers/s390/crypto/pkey_api.c
@@ -35,9 +35,6 @@ MODULE_DESCRIPTION("s390 protected key interface");
#define PROTKEYBLOBBUFSIZE 256 /* protected key buffer size used internal */
#define MAXAPQNSINLIST 64 /* max 64 apqns within a apqn list */
-/* mask of available pckmo subfunctions, fetched once at module init */
-static cpacf_mask_t pckmo_functions;
-
/*
* debug feature data and functions
*/
@@ -91,6 +88,9 @@ static int pkey_clr2protkey(u32 keytype,
const struct pkey_clrkey *clrkey,
struct pkey_protkey *protkey)
{
+ /* mask of available pckmo subfunctions */
+ static cpacf_mask_t pckmo_functions;
+
long fc;
int keysize;
u8 paramblock[64];
@@ -114,11 +114,13 @@ static int pkey_clr2protkey(u32 keytype,
return -EINVAL;
}
- /*
- * Check if the needed pckmo subfunction is available.
- * These subfunctions can be enabled/disabled by customers
- * in the LPAR profile or may even change on the fly.
- */
+ /* Did we already check for PCKMO ? */
+ if (!pckmo_functions.bytes[0]) {
+ /* no, so check now */
+ if (!cpacf_query(CPACF_PCKMO, &pckmo_functions))
+ return -ENODEV;
+ }
+ /* check for the pckmo subfunction we need now */
if (!cpacf_test_func(&pckmo_functions, fc)) {
DEBUG_ERR("%s pckmo functions not available\n", __func__);
return -ENODEV;
@@ -148,6 +150,8 @@ static int pkey_skey2pkey(const u8 *key, struct pkey_protkey *pkey)
u16 cardnr, domain;
struct keytoken_header *hdr = (struct keytoken_header *)key;
+ zcrypt_wait_api_operational();
+
/*
* The cca_xxx2protkey call may fail when a card has been
* addressed where the master key was changed after last fetch
@@ -195,6 +199,8 @@ static int pkey_clr2ep11key(const u8 *clrkey, size_t clrkeylen,
u16 card, dom;
u32 nr_apqns, *apqns = NULL;
+ zcrypt_wait_api_operational();
+
/* build a list of apqns suitable for ep11 keys with cpacf support */
rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF,
ZCRYPT_CEX7, EP11_API_V, NULL);
@@ -228,6 +234,8 @@ static int pkey_ep11key2pkey(const u8 *key, struct pkey_protkey *pkey)
u32 nr_apqns, *apqns = NULL;
struct ep11keyblob *kb = (struct ep11keyblob *) key;
+ zcrypt_wait_api_operational();
+
/* build a list of apqns suitable for this key */
rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF,
ZCRYPT_CEX7, EP11_API_V, kb->wkvp);
@@ -434,6 +442,7 @@ static int pkey_nonccatok2pkey(const u8 *key, u32 keylen,
if (rc == 0)
break;
/* PCKMO failed, so try the CCA secure key way */
+ zcrypt_wait_api_operational();
rc = cca_clr2seckey(0xFFFF, 0xFFFF, t->keytype,
ckey.clrkey, tmpbuf);
if (rc == 0)
@@ -623,6 +632,8 @@ static int pkey_clr2seckey2(const struct pkey_apqn *apqns, size_t nr_apqns,
return -EINVAL;
}
+ zcrypt_wait_api_operational();
+
/* simple try all apqns from the list */
for (i = 0, rc = -ENODEV; i < nr_apqns; i++) {
card = apqns[i].card;
@@ -799,6 +810,8 @@ static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns,
return -EINVAL;
}
+ zcrypt_wait_api_operational();
+
/* simple try all apqns from the list */
for (i = 0, rc = -ENODEV; i < nr_apqns; i++) {
card = apqns[i].card;
@@ -836,6 +849,8 @@ static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags,
if (keylen < sizeof(struct keytoken_header) || flags == 0)
return -EINVAL;
+ zcrypt_wait_api_operational();
+
if (hdr->type == TOKTYPE_NON_CCA
&& (hdr->version == TOKVER_EP11_AES_WITH_HEADER
|| hdr->version == TOKVER_EP11_ECC_WITH_HEADER)
@@ -939,6 +954,8 @@ static int pkey_apqns4keytype(enum pkey_key_type ktype,
int rc;
u32 _nr_apqns, *_apqns = NULL;
+ zcrypt_wait_api_operational();
+
if (ktype == PKEY_TYPE_CCA_DATA || ktype == PKEY_TYPE_CCA_CIPHER) {
u64 cur_mkvp = 0, old_mkvp = 0;
int minhwtype = ZCRYPT_CEX3C;
@@ -2058,7 +2075,7 @@ static struct miscdevice pkey_dev = {
*/
static int __init pkey_init(void)
{
- cpacf_mask_t kmc_functions;
+ cpacf_mask_t func_mask;
/*
* The pckmo instruction should be available - even if we don't
@@ -2066,15 +2083,15 @@ static int __init pkey_init(void)
* is also the minimum level for the kmc instructions which
* are able to work with protected keys.
*/
- if (!cpacf_query(CPACF_PCKMO, &pckmo_functions))
+ if (!cpacf_query(CPACF_PCKMO, &func_mask))
return -ENODEV;
/* check for kmc instructions available */
- if (!cpacf_query(CPACF_KMC, &kmc_functions))
+ if (!cpacf_query(CPACF_KMC, &func_mask))
return -ENODEV;
- if (!cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_128) ||
- !cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_192) ||
- !cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_256))
+ if (!cpacf_test_func(&func_mask, CPACF_KMC_PAES_128) ||
+ !cpacf_test_func(&func_mask, CPACF_KMC_PAES_192) ||
+ !cpacf_test_func(&func_mask, CPACF_KMC_PAES_256))
return -ENODEV;
pkey_debug_init();
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index f60f9fb25214..10206e4498d0 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -1992,6 +1992,72 @@ void zcrypt_rng_device_remove(void)
mutex_unlock(&zcrypt_rng_mutex);
}
+/*
+ * Wait until the zcrypt api is operational.
+ * The AP bus scan and the binding of ap devices to device drivers is
+ * an asynchronous job. This function waits until these initial jobs
+ * are done and so the zcrypt api should be ready to serve crypto
+ * requests - if there are resources available. The function uses an
+ * internal timeout of 60s. The very first caller will either wait for
+ * ap bus bindings complete or the timeout happens. This state will be
+ * remembered for further callers which will only be blocked until a
+ * decision is made (timeout or bindings complete).
+ * On timeout -ETIME is returned, on success the return value is 0.
+ */
+int zcrypt_wait_api_operational(void)
+{
+ static DEFINE_MUTEX(zcrypt_wait_api_lock);
+ static int zcrypt_wait_api_state;
+ int rc;
+
+ rc = mutex_lock_interruptible(&zcrypt_wait_api_lock);
+ if (rc)
+ return rc;
+
+ switch (zcrypt_wait_api_state) {
+ case 0:
+ /* initial state, invoke wait for the ap bus complete */
+ rc = ap_wait_init_apqn_bindings_complete(
+ msecs_to_jiffies(60 * 1000));
+ switch (rc) {
+ case 0:
+ /* ap bus bindings are complete */
+ zcrypt_wait_api_state = 1;
+ break;
+ case -EINTR:
+ /* interrupted, go back to caller */
+ break;
+ case -ETIME:
+ /* timeout */
+ ZCRYPT_DBF(DBF_WARN,
+ "%s ap_wait_init_apqn_bindings_complete() returned with ETIME\n",
+ __func__);
+ zcrypt_wait_api_state = -ETIME;
+ break;
+ default:
+ /* other failure */
+ ZCRYPT_DBF(DBF_DEBUG,
+ "%s ap_wait_init_apqn_bindings_complete() failure rc=%d\n",
+ __func__, rc);
+ break;
+ }
+ break;
+ case 1:
+ /* a previous caller already found ap bus bindings complete */
+ rc = 0;
+ break;
+ default:
+ /* a previous caller had timeout or other failure */
+ rc = zcrypt_wait_api_state;
+ break;
+ }
+
+ mutex_unlock(&zcrypt_wait_api_lock);
+
+ return rc;
+}
+EXPORT_SYMBOL(zcrypt_wait_api_operational);
+
int __init zcrypt_debug_init(void)
{
zcrypt_dbf_info = debug_register("zcrypt", 1, 1,
diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h
index 51c0b8bdef50..16219efb2f61 100644
--- a/drivers/s390/crypto/zcrypt_api.h
+++ b/drivers/s390/crypto/zcrypt_api.h
@@ -162,6 +162,8 @@ void zcrypt_device_status_mask_ext(struct zcrypt_device_status_ext *devstatus);
int zcrypt_device_status_ext(int card, int queue,
struct zcrypt_device_status_ext *devstatus);
+int zcrypt_wait_api_operational(void);
+
static inline unsigned long z_copy_from_user(bool userspace,
void *to,
const void __user *from,
diff --git a/drivers/s390/crypto/zcrypt_card.c b/drivers/s390/crypto/zcrypt_card.c
index e342eb86acd1..33b23884b133 100644
--- a/drivers/s390/crypto/zcrypt_card.c
+++ b/drivers/s390/crypto/zcrypt_card.c
@@ -157,11 +157,6 @@ int zcrypt_card_register(struct zcrypt_card *zc)
{
int rc;
- rc = sysfs_create_group(&zc->card->ap_dev.device.kobj,
- &zcrypt_card_attr_group);
- if (rc)
- return rc;
-
spin_lock(&zcrypt_list_lock);
list_add_tail(&zc->list, &zcrypt_card_list);
spin_unlock(&zcrypt_list_lock);
@@ -170,6 +165,14 @@ int zcrypt_card_register(struct zcrypt_card *zc)
ZCRYPT_DBF(DBF_INFO, "card=%02x register online=1\n", zc->card->id);
+ rc = sysfs_create_group(&zc->card->ap_dev.device.kobj,
+ &zcrypt_card_attr_group);
+ if (rc) {
+ spin_lock(&zcrypt_list_lock);
+ list_del_init(&zc->list);
+ spin_unlock(&zcrypt_list_lock);
+ }
+
return rc;
}
EXPORT_SYMBOL(zcrypt_card_register);
diff --git a/drivers/s390/crypto/zcrypt_cex2a.c b/drivers/s390/crypto/zcrypt_cex2a.c
index 226a5612e855..62ceeb7fc125 100644
--- a/drivers/s390/crypto/zcrypt_cex2a.c
+++ b/drivers/s390/crypto/zcrypt_cex2a.c
@@ -175,7 +175,7 @@ static int zcrypt_cex2a_queue_probe(struct ap_device *ap_dev)
atomic_set(&zq->load, 0);
ap_queue_init_state(aq);
ap_queue_init_reply(aq, &zq->reply);
- aq->request_timeout = CEX2A_CLEANUP_TIME,
+ aq->request_timeout = CEX2A_CLEANUP_TIME;
aq->private = zq;
rc = zcrypt_queue_register(zq);
if (rc) {
diff --git a/drivers/s390/crypto/zcrypt_cex4.c b/drivers/s390/crypto/zcrypt_cex4.c
index f5195bca1d85..f4a6d3744241 100644
--- a/drivers/s390/crypto/zcrypt_cex4.c
+++ b/drivers/s390/crypto/zcrypt_cex4.c
@@ -631,7 +631,7 @@ static int zcrypt_cex4_queue_probe(struct ap_device *ap_dev)
atomic_set(&zq->load, 0);
ap_queue_init_state(aq);
ap_queue_init_reply(aq, &zq->reply);
- aq->request_timeout = CEX4_CLEANUP_TIME,
+ aq->request_timeout = CEX4_CLEANUP_TIME;
aq->private = zq;
rc = zcrypt_queue_register(zq);
if (rc) {
diff --git a/drivers/s390/crypto/zcrypt_queue.c b/drivers/s390/crypto/zcrypt_queue.c
index 3c207066313c..5062eae73d4a 100644
--- a/drivers/s390/crypto/zcrypt_queue.c
+++ b/drivers/s390/crypto/zcrypt_queue.c
@@ -180,7 +180,6 @@ int zcrypt_queue_register(struct zcrypt_queue *zq)
&zcrypt_queue_attr_group);
if (rc)
goto out;
- get_device(&zq->queue->ap_dev.device);
if (zq->ops->rng) {
rc = zcrypt_rng_device_add();
@@ -192,7 +191,6 @@ int zcrypt_queue_register(struct zcrypt_queue *zq)
out_unregister:
sysfs_remove_group(&zq->queue->ap_dev.device.kobj,
&zcrypt_queue_attr_group);
- put_device(&zq->queue->ap_dev.device);
out:
spin_lock(&zcrypt_list_lock);
list_del_init(&zq->list);
@@ -220,12 +218,10 @@ void zcrypt_queue_unregister(struct zcrypt_queue *zq)
list_del_init(&zq->list);
zcrypt_device_count--;
spin_unlock(&zcrypt_list_lock);
- zcrypt_card_put(zc);
if (zq->ops->rng)
zcrypt_rng_device_remove();
sysfs_remove_group(&zq->queue->ap_dev.device.kobj,
&zcrypt_queue_attr_group);
- put_device(&zq->queue->ap_dev.device);
- zcrypt_queue_put(zq);
+ zcrypt_card_put(zc);
}
EXPORT_SYMBOL(zcrypt_queue_unregister);