xref: /openbmc/linux/drivers/s390/crypto/zcrypt_queue.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
1812141a9SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0+
2e28d2af4SIngo Tuchscherer /*
3e28d2af4SIngo Tuchscherer  *  Copyright IBM Corp. 2001, 2012
4e28d2af4SIngo Tuchscherer  *  Author(s): Robert Burroughs
5e28d2af4SIngo Tuchscherer  *	       Eric Rossman (edrossma@us.ibm.com)
6e28d2af4SIngo Tuchscherer  *	       Cornelia Huck <cornelia.huck@de.ibm.com>
7e28d2af4SIngo Tuchscherer  *
8e28d2af4SIngo Tuchscherer  *  Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com)
9e28d2af4SIngo Tuchscherer  *  Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com>
10e28d2af4SIngo Tuchscherer  *				  Ralph Wuerthner <rwuerthn@de.ibm.com>
11e28d2af4SIngo Tuchscherer  *  MSGTYPE restruct:		  Holger Dengler <hd@linux.vnet.ibm.com>
12e28d2af4SIngo Tuchscherer  */
13e28d2af4SIngo Tuchscherer 
14e28d2af4SIngo Tuchscherer #include <linux/module.h>
15e28d2af4SIngo Tuchscherer #include <linux/init.h>
16e28d2af4SIngo Tuchscherer #include <linux/interrupt.h>
17e28d2af4SIngo Tuchscherer #include <linux/miscdevice.h>
18e28d2af4SIngo Tuchscherer #include <linux/fs.h>
19e28d2af4SIngo Tuchscherer #include <linux/proc_fs.h>
20e28d2af4SIngo Tuchscherer #include <linux/seq_file.h>
21e28d2af4SIngo Tuchscherer #include <linux/compat.h>
22e28d2af4SIngo Tuchscherer #include <linux/slab.h>
23e28d2af4SIngo Tuchscherer #include <linux/atomic.h>
24e28d2af4SIngo Tuchscherer #include <linux/uaccess.h>
25e28d2af4SIngo Tuchscherer #include <linux/hw_random.h>
26e28d2af4SIngo Tuchscherer #include <linux/debugfs.h>
27e28d2af4SIngo Tuchscherer #include <asm/debug.h>
28e28d2af4SIngo Tuchscherer 
29e28d2af4SIngo Tuchscherer #include "zcrypt_debug.h"
30e28d2af4SIngo Tuchscherer #include "zcrypt_api.h"
31e28d2af4SIngo Tuchscherer 
32e28d2af4SIngo Tuchscherer #include "zcrypt_msgtype6.h"
33e28d2af4SIngo Tuchscherer #include "zcrypt_msgtype50.h"
34e28d2af4SIngo Tuchscherer 
35e28d2af4SIngo Tuchscherer /*
36e28d2af4SIngo Tuchscherer  * Device attributes common for all crypto queue devices.
37e28d2af4SIngo Tuchscherer  */
38e28d2af4SIngo Tuchscherer 
online_show(struct device * dev,struct device_attribute * attr,char * buf)39ac2b96f3SHarald Freudenberger static ssize_t online_show(struct device *dev,
40e28d2af4SIngo Tuchscherer 			   struct device_attribute *attr,
41e28d2af4SIngo Tuchscherer 			   char *buf)
42e28d2af4SIngo Tuchscherer {
43b5adbbf8SJulian Wiedmann 	struct zcrypt_queue *zq = dev_get_drvdata(dev);
444f2fcccdSHarald Freudenberger 	struct ap_queue *aq = to_ap_queue(dev);
454f2fcccdSHarald Freudenberger 	int online = aq->config && zq->online ? 1 : 0;
46e28d2af4SIngo Tuchscherer 
47*964d581dSHarald Freudenberger 	return sysfs_emit(buf, "%d\n", online);
48e28d2af4SIngo Tuchscherer }
49e28d2af4SIngo Tuchscherer 
online_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)50ac2b96f3SHarald Freudenberger static ssize_t online_store(struct device *dev,
51e28d2af4SIngo Tuchscherer 			    struct device_attribute *attr,
52e28d2af4SIngo Tuchscherer 			    const char *buf, size_t count)
53e28d2af4SIngo Tuchscherer {
54b5adbbf8SJulian Wiedmann 	struct zcrypt_queue *zq = dev_get_drvdata(dev);
554f2fcccdSHarald Freudenberger 	struct ap_queue *aq = to_ap_queue(dev);
56e28d2af4SIngo Tuchscherer 	struct zcrypt_card *zc = zq->zcard;
57e28d2af4SIngo Tuchscherer 	int online;
58e28d2af4SIngo Tuchscherer 
59e28d2af4SIngo Tuchscherer 	if (sscanf(buf, "%d\n", &online) != 1 || online < 0 || online > 1)
60e28d2af4SIngo Tuchscherer 		return -EINVAL;
61e28d2af4SIngo Tuchscherer 
624f2fcccdSHarald Freudenberger 	if (online && (!aq->config || !aq->card->config))
634f2fcccdSHarald Freudenberger 		return -ENODEV;
64e28d2af4SIngo Tuchscherer 	if (online && !zc->online)
65e28d2af4SIngo Tuchscherer 		return -EINVAL;
66e28d2af4SIngo Tuchscherer 	zq->online = online;
67cccd85bfSHarald Freudenberger 
683f74eb5fSHarald Freudenberger 	ZCRYPT_DBF_INFO("%s queue=%02x.%04x online=%d\n",
693f74eb5fSHarald Freudenberger 			__func__, AP_QID_CARD(zq->queue->qid),
703f74eb5fSHarald Freudenberger 			AP_QID_QUEUE(zq->queue->qid), online);
71cccd85bfSHarald Freudenberger 
72df6f508cSHarald Freudenberger 	ap_send_online_uevent(&aq->ap_dev, online);
73df6f508cSHarald Freudenberger 
74e28d2af4SIngo Tuchscherer 	if (!online)
75e28d2af4SIngo Tuchscherer 		ap_flush_queue(zq->queue);
76e28d2af4SIngo Tuchscherer 	return count;
77e28d2af4SIngo Tuchscherer }
78e28d2af4SIngo Tuchscherer 
79ac2b96f3SHarald Freudenberger static DEVICE_ATTR_RW(online);
80e28d2af4SIngo Tuchscherer 
load_show(struct device * dev,struct device_attribute * attr,char * buf)81ac2b96f3SHarald Freudenberger static ssize_t load_show(struct device *dev,
824a07750bSHarald Freudenberger 			 struct device_attribute *attr,
834a07750bSHarald Freudenberger 			 char *buf)
844a07750bSHarald Freudenberger {
85b5adbbf8SJulian Wiedmann 	struct zcrypt_queue *zq = dev_get_drvdata(dev);
864a07750bSHarald Freudenberger 
87*964d581dSHarald Freudenberger 	return sysfs_emit(buf, "%d\n", atomic_read(&zq->load));
884a07750bSHarald Freudenberger }
894a07750bSHarald Freudenberger 
90ac2b96f3SHarald Freudenberger static DEVICE_ATTR_RO(load);
914a07750bSHarald Freudenberger 
92e28d2af4SIngo Tuchscherer static struct attribute *zcrypt_queue_attrs[] = {
93e28d2af4SIngo Tuchscherer 	&dev_attr_online.attr,
944a07750bSHarald Freudenberger 	&dev_attr_load.attr,
95e28d2af4SIngo Tuchscherer 	NULL,
96e28d2af4SIngo Tuchscherer };
97e28d2af4SIngo Tuchscherer 
989920decdSArvind Yadav static const struct attribute_group zcrypt_queue_attr_group = {
99e28d2af4SIngo Tuchscherer 	.attrs = zcrypt_queue_attrs,
100e28d2af4SIngo Tuchscherer };
101e28d2af4SIngo Tuchscherer 
zcrypt_queue_force_online(struct zcrypt_queue * zq,int online)102df6f508cSHarald Freudenberger bool zcrypt_queue_force_online(struct zcrypt_queue *zq, int online)
103e28d2af4SIngo Tuchscherer {
104df6f508cSHarald Freudenberger 	if (!!zq->online != !!online) {
105e28d2af4SIngo Tuchscherer 		zq->online = online;
106e28d2af4SIngo Tuchscherer 		if (!online)
107e28d2af4SIngo Tuchscherer 			ap_flush_queue(zq->queue);
108df6f508cSHarald Freudenberger 		return true;
109df6f508cSHarald Freudenberger 	}
110df6f508cSHarald Freudenberger 	return false;
111e28d2af4SIngo Tuchscherer }
112e28d2af4SIngo Tuchscherer 
zcrypt_queue_alloc(size_t reply_buf_size)113bd39654aSHarald Freudenberger struct zcrypt_queue *zcrypt_queue_alloc(size_t reply_buf_size)
114e28d2af4SIngo Tuchscherer {
115e28d2af4SIngo Tuchscherer 	struct zcrypt_queue *zq;
116e28d2af4SIngo Tuchscherer 
1172004b57cSHarald Freudenberger 	zq = kzalloc(sizeof(*zq), GFP_KERNEL);
118e28d2af4SIngo Tuchscherer 	if (!zq)
119e28d2af4SIngo Tuchscherer 		return NULL;
120bd39654aSHarald Freudenberger 	zq->reply.msg = kmalloc(reply_buf_size, GFP_KERNEL);
12174ecbef7SHarald Freudenberger 	if (!zq->reply.msg)
122e28d2af4SIngo Tuchscherer 		goto out_free;
123bd39654aSHarald Freudenberger 	zq->reply.bufsize = reply_buf_size;
124e28d2af4SIngo Tuchscherer 	INIT_LIST_HEAD(&zq->list);
125e28d2af4SIngo Tuchscherer 	kref_init(&zq->refcount);
126e28d2af4SIngo Tuchscherer 	return zq;
127e28d2af4SIngo Tuchscherer 
128e28d2af4SIngo Tuchscherer out_free:
129e28d2af4SIngo Tuchscherer 	kfree(zq);
130e28d2af4SIngo Tuchscherer 	return NULL;
131e28d2af4SIngo Tuchscherer }
132e28d2af4SIngo Tuchscherer EXPORT_SYMBOL(zcrypt_queue_alloc);
133e28d2af4SIngo Tuchscherer 
zcrypt_queue_free(struct zcrypt_queue * zq)134e28d2af4SIngo Tuchscherer void zcrypt_queue_free(struct zcrypt_queue *zq)
135e28d2af4SIngo Tuchscherer {
13674ecbef7SHarald Freudenberger 	kfree(zq->reply.msg);
137e28d2af4SIngo Tuchscherer 	kfree(zq);
138e28d2af4SIngo Tuchscherer }
139e28d2af4SIngo Tuchscherer EXPORT_SYMBOL(zcrypt_queue_free);
140e28d2af4SIngo Tuchscherer 
zcrypt_queue_release(struct kref * kref)141e28d2af4SIngo Tuchscherer static void zcrypt_queue_release(struct kref *kref)
142e28d2af4SIngo Tuchscherer {
143e28d2af4SIngo Tuchscherer 	struct zcrypt_queue *zq =
144e28d2af4SIngo Tuchscherer 		container_of(kref, struct zcrypt_queue, refcount);
145e28d2af4SIngo Tuchscherer 	zcrypt_queue_free(zq);
146e28d2af4SIngo Tuchscherer }
147e28d2af4SIngo Tuchscherer 
zcrypt_queue_get(struct zcrypt_queue * zq)148e28d2af4SIngo Tuchscherer void zcrypt_queue_get(struct zcrypt_queue *zq)
149e28d2af4SIngo Tuchscherer {
150e28d2af4SIngo Tuchscherer 	kref_get(&zq->refcount);
151e28d2af4SIngo Tuchscherer }
152e28d2af4SIngo Tuchscherer EXPORT_SYMBOL(zcrypt_queue_get);
153e28d2af4SIngo Tuchscherer 
zcrypt_queue_put(struct zcrypt_queue * zq)154e28d2af4SIngo Tuchscherer int zcrypt_queue_put(struct zcrypt_queue *zq)
155e28d2af4SIngo Tuchscherer {
156e28d2af4SIngo Tuchscherer 	return kref_put(&zq->refcount, zcrypt_queue_release);
157e28d2af4SIngo Tuchscherer }
158e28d2af4SIngo Tuchscherer EXPORT_SYMBOL(zcrypt_queue_put);
159e28d2af4SIngo Tuchscherer 
160e28d2af4SIngo Tuchscherer /**
161e28d2af4SIngo Tuchscherer  * zcrypt_queue_register() - Register a crypto queue device.
162e28d2af4SIngo Tuchscherer  * @zq: Pointer to a crypto queue device
163e28d2af4SIngo Tuchscherer  *
164e28d2af4SIngo Tuchscherer  * Register a crypto queue device. Returns 0 if successful.
165e28d2af4SIngo Tuchscherer  */
zcrypt_queue_register(struct zcrypt_queue * zq)166e28d2af4SIngo Tuchscherer int zcrypt_queue_register(struct zcrypt_queue *zq)
167e28d2af4SIngo Tuchscherer {
168e28d2af4SIngo Tuchscherer 	struct zcrypt_card *zc;
169e28d2af4SIngo Tuchscherer 	int rc;
170e28d2af4SIngo Tuchscherer 
171e28d2af4SIngo Tuchscherer 	spin_lock(&zcrypt_list_lock);
172b5adbbf8SJulian Wiedmann 	zc = dev_get_drvdata(&zq->queue->card->ap_dev.device);
173e28d2af4SIngo Tuchscherer 	zcrypt_card_get(zc);
174e28d2af4SIngo Tuchscherer 	zq->zcard = zc;
175e28d2af4SIngo Tuchscherer 	zq->online = 1;	/* New devices are online by default. */
176cccd85bfSHarald Freudenberger 
1773f74eb5fSHarald Freudenberger 	ZCRYPT_DBF_INFO("%s queue=%02x.%04x register online=1\n",
1783f74eb5fSHarald Freudenberger 			__func__, AP_QID_CARD(zq->queue->qid),
1793f74eb5fSHarald Freudenberger 			AP_QID_QUEUE(zq->queue->qid));
180cccd85bfSHarald Freudenberger 
181e28d2af4SIngo Tuchscherer 	list_add_tail(&zq->list, &zc->zqueues);
182e28d2af4SIngo Tuchscherer 	spin_unlock(&zcrypt_list_lock);
183e28d2af4SIngo Tuchscherer 
184e28d2af4SIngo Tuchscherer 	rc = sysfs_create_group(&zq->queue->ap_dev.device.kobj,
185e28d2af4SIngo Tuchscherer 				&zcrypt_queue_attr_group);
186e28d2af4SIngo Tuchscherer 	if (rc)
187e28d2af4SIngo Tuchscherer 		goto out;
188e28d2af4SIngo Tuchscherer 
189e28d2af4SIngo Tuchscherer 	if (zq->ops->rng) {
190e28d2af4SIngo Tuchscherer 		rc = zcrypt_rng_device_add();
191e28d2af4SIngo Tuchscherer 		if (rc)
192e28d2af4SIngo Tuchscherer 			goto out_unregister;
193e28d2af4SIngo Tuchscherer 	}
194e28d2af4SIngo Tuchscherer 	return 0;
195e28d2af4SIngo Tuchscherer 
196e28d2af4SIngo Tuchscherer out_unregister:
197e28d2af4SIngo Tuchscherer 	sysfs_remove_group(&zq->queue->ap_dev.device.kobj,
198e28d2af4SIngo Tuchscherer 			   &zcrypt_queue_attr_group);
199e28d2af4SIngo Tuchscherer out:
200e28d2af4SIngo Tuchscherer 	spin_lock(&zcrypt_list_lock);
201e28d2af4SIngo Tuchscherer 	list_del_init(&zq->list);
202e28d2af4SIngo Tuchscherer 	spin_unlock(&zcrypt_list_lock);
203e28d2af4SIngo Tuchscherer 	zcrypt_card_put(zc);
204e28d2af4SIngo Tuchscherer 	return rc;
205e28d2af4SIngo Tuchscherer }
206e28d2af4SIngo Tuchscherer EXPORT_SYMBOL(zcrypt_queue_register);
207e28d2af4SIngo Tuchscherer 
208e28d2af4SIngo Tuchscherer /**
209e28d2af4SIngo Tuchscherer  * zcrypt_queue_unregister(): Unregister a crypto queue device.
210e28d2af4SIngo Tuchscherer  * @zq: Pointer to crypto queue device
211e28d2af4SIngo Tuchscherer  *
212e28d2af4SIngo Tuchscherer  * Unregister a crypto queue device.
213e28d2af4SIngo Tuchscherer  */
zcrypt_queue_unregister(struct zcrypt_queue * zq)214e28d2af4SIngo Tuchscherer void zcrypt_queue_unregister(struct zcrypt_queue *zq)
215e28d2af4SIngo Tuchscherer {
216e28d2af4SIngo Tuchscherer 	struct zcrypt_card *zc;
217e28d2af4SIngo Tuchscherer 
2183f74eb5fSHarald Freudenberger 	ZCRYPT_DBF_INFO("%s queue=%02x.%04x unregister\n",
2193f74eb5fSHarald Freudenberger 			__func__, AP_QID_CARD(zq->queue->qid),
2203f74eb5fSHarald Freudenberger 			AP_QID_QUEUE(zq->queue->qid));
221cccd85bfSHarald Freudenberger 
222e28d2af4SIngo Tuchscherer 	zc = zq->zcard;
223e28d2af4SIngo Tuchscherer 	spin_lock(&zcrypt_list_lock);
224e28d2af4SIngo Tuchscherer 	list_del_init(&zq->list);
225e28d2af4SIngo Tuchscherer 	spin_unlock(&zcrypt_list_lock);
226e28d2af4SIngo Tuchscherer 	if (zq->ops->rng)
227e28d2af4SIngo Tuchscherer 		zcrypt_rng_device_remove();
228e28d2af4SIngo Tuchscherer 	sysfs_remove_group(&zq->queue->ap_dev.device.kobj,
229e28d2af4SIngo Tuchscherer 			   &zcrypt_queue_attr_group);
23029c2680fSHarald Freudenberger 	zcrypt_card_put(zc);
23170fac808SHarald Freudenberger 	zcrypt_queue_put(zq);
232e28d2af4SIngo Tuchscherer }
233e28d2af4SIngo Tuchscherer EXPORT_SYMBOL(zcrypt_queue_unregister);
234