xref: /openbmc/linux/drivers/s390/cio/vfio_ccw_drv.c (revision a6ca5ac746d104019e76c29e69c2a1fc6dd2b29f)
1 /*
2  * VFIO based Physical Subchannel device driver
3  *
4  * Copyright IBM Corp. 2017
5  *
6  * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
7  *            Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>
8  */
9 
10 #include <linux/module.h>
11 #include <linux/init.h>
12 #include <linux/device.h>
13 #include <linux/slab.h>
14 #include <linux/uuid.h>
15 #include <linux/mdev.h>
16 
17 #include <asm/isc.h>
18 
19 #include "ioasm.h"
20 #include "css.h"
21 #include "vfio_ccw_private.h"
22 
23 struct workqueue_struct *vfio_ccw_work_q;
24 
25 /*
26  * Helpers
27  */
28 int vfio_ccw_sch_quiesce(struct subchannel *sch)
29 {
30 	struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev);
31 	DECLARE_COMPLETION_ONSTACK(completion);
32 	int iretry, ret = 0;
33 
34 	spin_lock_irq(sch->lock);
35 	if (!sch->schib.pmcw.ena)
36 		goto out_unlock;
37 	ret = cio_disable_subchannel(sch);
38 	if (ret != -EBUSY)
39 		goto out_unlock;
40 
41 	do {
42 		iretry = 255;
43 
44 		ret = cio_cancel_halt_clear(sch, &iretry);
45 		while (ret == -EBUSY) {
46 			/*
47 			 * Flush all I/O and wait for
48 			 * cancel/halt/clear completion.
49 			 */
50 			private->completion = &completion;
51 			spin_unlock_irq(sch->lock);
52 
53 			wait_for_completion_timeout(&completion, 3*HZ);
54 
55 			spin_lock_irq(sch->lock);
56 			private->completion = NULL;
57 			flush_workqueue(vfio_ccw_work_q);
58 			ret = cio_cancel_halt_clear(sch, &iretry);
59 		};
60 
61 		ret = cio_disable_subchannel(sch);
62 	} while (ret == -EBUSY);
63 out_unlock:
64 	private->state = VFIO_CCW_STATE_NOT_OPER;
65 	spin_unlock_irq(sch->lock);
66 	return ret;
67 }
68 
69 static void vfio_ccw_sch_io_todo(struct work_struct *work)
70 {
71 	struct vfio_ccw_private *private;
72 	struct subchannel *sch;
73 	struct irb *irb;
74 
75 	private = container_of(work, struct vfio_ccw_private, io_work);
76 	irb = &private->irb;
77 	sch = private->sch;
78 
79 	if (scsw_is_solicited(&irb->scsw)) {
80 		cp_update_scsw(&private->cp, &irb->scsw);
81 		cp_free(&private->cp);
82 	}
83 	memcpy(private->io_region.irb_area, irb, sizeof(*irb));
84 
85 	if (private->io_trigger)
86 		eventfd_signal(private->io_trigger, 1);
87 
88 	if (private->mdev)
89 		private->state = VFIO_CCW_STATE_IDLE;
90 }
91 
92 /*
93  * Sysfs interfaces
94  */
95 static ssize_t chpids_show(struct device *dev,
96 			   struct device_attribute *attr,
97 			   char *buf)
98 {
99 	struct subchannel *sch = to_subchannel(dev);
100 	struct chsc_ssd_info *ssd = &sch->ssd_info;
101 	ssize_t ret = 0;
102 	int chp;
103 	int mask;
104 
105 	for (chp = 0; chp < 8; chp++) {
106 		mask = 0x80 >> chp;
107 		if (ssd->path_mask & mask)
108 			ret += sprintf(buf + ret, "%02x ", ssd->chpid[chp].id);
109 		else
110 			ret += sprintf(buf + ret, "00 ");
111 	}
112 	ret += sprintf(buf+ret, "\n");
113 	return ret;
114 }
115 
116 static ssize_t pimpampom_show(struct device *dev,
117 			      struct device_attribute *attr,
118 			      char *buf)
119 {
120 	struct subchannel *sch = to_subchannel(dev);
121 	struct pmcw *pmcw = &sch->schib.pmcw;
122 
123 	return sprintf(buf, "%02x %02x %02x\n",
124 		       pmcw->pim, pmcw->pam, pmcw->pom);
125 }
126 
127 static DEVICE_ATTR(chpids, 0444, chpids_show, NULL);
128 static DEVICE_ATTR(pimpampom, 0444, pimpampom_show, NULL);
129 
130 static struct attribute *vfio_subchannel_attrs[] = {
131 	&dev_attr_chpids.attr,
132 	&dev_attr_pimpampom.attr,
133 	NULL,
134 };
135 
136 static struct attribute_group vfio_subchannel_attr_group = {
137 	.attrs = vfio_subchannel_attrs,
138 };
139 
140 /*
141  * Css driver callbacks
142  */
143 static void vfio_ccw_sch_irq(struct subchannel *sch)
144 {
145 	struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev);
146 
147 	inc_irq_stat(IRQIO_CIO);
148 	vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_INTERRUPT);
149 }
150 
151 static int vfio_ccw_sch_probe(struct subchannel *sch)
152 {
153 	struct pmcw *pmcw = &sch->schib.pmcw;
154 	struct vfio_ccw_private *private;
155 	int ret;
156 
157 	if (pmcw->qf) {
158 		dev_warn(&sch->dev, "vfio: ccw: does not support QDIO: %s\n",
159 			 dev_name(&sch->dev));
160 		return -ENODEV;
161 	}
162 
163 	private = kzalloc(sizeof(*private), GFP_KERNEL | GFP_DMA);
164 	if (!private)
165 		return -ENOMEM;
166 	private->sch = sch;
167 	dev_set_drvdata(&sch->dev, private);
168 
169 	spin_lock_irq(sch->lock);
170 	private->state = VFIO_CCW_STATE_NOT_OPER;
171 	sch->isc = VFIO_CCW_ISC;
172 	ret = cio_enable_subchannel(sch, (u32)(unsigned long)sch);
173 	spin_unlock_irq(sch->lock);
174 	if (ret)
175 		goto out_free;
176 
177 	ret = sysfs_create_group(&sch->dev.kobj, &vfio_subchannel_attr_group);
178 	if (ret)
179 		goto out_disable;
180 
181 	ret = vfio_ccw_mdev_reg(sch);
182 	if (ret)
183 		goto out_rm_group;
184 
185 	INIT_WORK(&private->io_work, vfio_ccw_sch_io_todo);
186 	atomic_set(&private->avail, 1);
187 	private->state = VFIO_CCW_STATE_STANDBY;
188 
189 	return 0;
190 
191 out_rm_group:
192 	sysfs_remove_group(&sch->dev.kobj, &vfio_subchannel_attr_group);
193 out_disable:
194 	cio_disable_subchannel(sch);
195 out_free:
196 	dev_set_drvdata(&sch->dev, NULL);
197 	kfree(private);
198 	return ret;
199 }
200 
201 static int vfio_ccw_sch_remove(struct subchannel *sch)
202 {
203 	struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev);
204 
205 	vfio_ccw_sch_quiesce(sch);
206 
207 	vfio_ccw_mdev_unreg(sch);
208 
209 	sysfs_remove_group(&sch->dev.kobj, &vfio_subchannel_attr_group);
210 
211 	dev_set_drvdata(&sch->dev, NULL);
212 
213 	kfree(private);
214 
215 	return 0;
216 }
217 
218 static void vfio_ccw_sch_shutdown(struct subchannel *sch)
219 {
220 	vfio_ccw_sch_quiesce(sch);
221 }
222 
223 /**
224  * vfio_ccw_sch_event - process subchannel event
225  * @sch: subchannel
226  * @process: non-zero if function is called in process context
227  *
228  * An unspecified event occurred for this subchannel. Adjust data according
229  * to the current operational state of the subchannel. Return zero when the
230  * event has been handled sufficiently or -EAGAIN when this function should
231  * be called again in process context.
232  */
233 static int vfio_ccw_sch_event(struct subchannel *sch, int process)
234 {
235 	struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev);
236 	unsigned long flags;
237 
238 	spin_lock_irqsave(sch->lock, flags);
239 	if (!device_is_registered(&sch->dev))
240 		goto out_unlock;
241 
242 	if (work_pending(&sch->todo_work))
243 		goto out_unlock;
244 
245 	if (cio_update_schib(sch)) {
246 		vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_NOT_OPER);
247 		goto out_unlock;
248 	}
249 
250 	private = dev_get_drvdata(&sch->dev);
251 	if (private->state == VFIO_CCW_STATE_NOT_OPER) {
252 		private->state = private->mdev ? VFIO_CCW_STATE_IDLE :
253 				 VFIO_CCW_STATE_STANDBY;
254 	}
255 
256 out_unlock:
257 	spin_unlock_irqrestore(sch->lock, flags);
258 
259 	return 0;
260 }
261 
262 static struct css_device_id vfio_ccw_sch_ids[] = {
263 	{ .match_flags = 0x1, .type = SUBCHANNEL_TYPE_IO, },
264 	{ /* end of list */ },
265 };
266 MODULE_DEVICE_TABLE(css, vfio_ccw_sch_ids);
267 
268 static struct css_driver vfio_ccw_sch_driver = {
269 	.drv = {
270 		.name = "vfio_ccw",
271 		.owner = THIS_MODULE,
272 	},
273 	.subchannel_type = vfio_ccw_sch_ids,
274 	.irq = vfio_ccw_sch_irq,
275 	.probe = vfio_ccw_sch_probe,
276 	.remove = vfio_ccw_sch_remove,
277 	.shutdown = vfio_ccw_sch_shutdown,
278 	.sch_event = vfio_ccw_sch_event,
279 };
280 
281 static int __init vfio_ccw_sch_init(void)
282 {
283 	int ret;
284 
285 	vfio_ccw_work_q = create_singlethread_workqueue("vfio-ccw");
286 	if (!vfio_ccw_work_q)
287 		return -ENOMEM;
288 
289 	isc_register(VFIO_CCW_ISC);
290 	ret = css_driver_register(&vfio_ccw_sch_driver);
291 	if (ret) {
292 		isc_unregister(VFIO_CCW_ISC);
293 		destroy_workqueue(vfio_ccw_work_q);
294 	}
295 
296 	return ret;
297 }
298 
299 static void __exit vfio_ccw_sch_exit(void)
300 {
301 	css_driver_unregister(&vfio_ccw_sch_driver);
302 	isc_unregister(VFIO_CCW_ISC);
303 	destroy_workqueue(vfio_ccw_work_q);
304 }
305 module_init(vfio_ccw_sch_init);
306 module_exit(vfio_ccw_sch_exit);
307 
308 MODULE_LICENSE("GPL v2");
309