2 * VFIO based Physical Subchannel device driver
4 * Copyright IBM Corp. 2017
6 * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
7 * Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>
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>
21 #include "vfio_ccw_private.h"
23 struct workqueue_struct *vfio_ccw_work_q;
28 int vfio_ccw_sch_quiesce(struct subchannel *sch)
30 struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev);
31 DECLARE_COMPLETION_ONSTACK(completion);
34 spin_lock_irq(sch->lock);
35 if (!sch->schib.pmcw.ena)
37 ret = cio_disable_subchannel(sch);
44 ret = cio_cancel_halt_clear(sch, &iretry);
47 pr_err("vfio_ccw: could not quiesce subchannel 0.%x.%04x!\n",
48 sch->schid.ssid, sch->schid.sch_no);
53 * Flush all I/O and wait for
54 * cancel/halt/clear completion.
56 private->completion = &completion;
57 spin_unlock_irq(sch->lock);
60 wait_for_completion_timeout(&completion, 3*HZ);
62 private->completion = NULL;
63 flush_workqueue(vfio_ccw_work_q);
64 spin_lock_irq(sch->lock);
65 ret = cio_disable_subchannel(sch);
66 } while (ret == -EBUSY);
68 private->state = VFIO_CCW_STATE_NOT_OPER;
69 spin_unlock_irq(sch->lock);
73 static void vfio_ccw_sch_io_todo(struct work_struct *work)
75 struct vfio_ccw_private *private;
79 private = container_of(work, struct vfio_ccw_private, io_work);
82 is_final = !(scsw_actl(&irb->scsw) &
83 (SCSW_ACTL_DEVACT | SCSW_ACTL_SCHACT));
84 if (scsw_is_solicited(&irb->scsw)) {
85 cp_update_scsw(&private->cp, &irb->scsw);
87 cp_free(&private->cp);
89 memcpy(private->io_region.irb_area, irb, sizeof(*irb));
91 if (private->io_trigger)
92 eventfd_signal(private->io_trigger, 1);
94 if (private->mdev && is_final)
95 private->state = VFIO_CCW_STATE_IDLE;
99 * Css driver callbacks
101 static void vfio_ccw_sch_irq(struct subchannel *sch)
103 struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev);
105 inc_irq_stat(IRQIO_CIO);
106 vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_INTERRUPT);
109 static int vfio_ccw_sch_probe(struct subchannel *sch)
111 struct pmcw *pmcw = &sch->schib.pmcw;
112 struct vfio_ccw_private *private;
116 dev_warn(&sch->dev, "vfio: ccw: does not support QDIO: %s\n",
117 dev_name(&sch->dev));
121 private = kzalloc(sizeof(*private), GFP_KERNEL | GFP_DMA);
125 dev_set_drvdata(&sch->dev, private);
127 spin_lock_irq(sch->lock);
128 private->state = VFIO_CCW_STATE_NOT_OPER;
129 sch->isc = VFIO_CCW_ISC;
130 ret = cio_enable_subchannel(sch, (u32)(unsigned long)sch);
131 spin_unlock_irq(sch->lock);
135 ret = vfio_ccw_mdev_reg(sch);
139 INIT_WORK(&private->io_work, vfio_ccw_sch_io_todo);
140 atomic_set(&private->avail, 1);
141 private->state = VFIO_CCW_STATE_STANDBY;
146 cio_disable_subchannel(sch);
148 dev_set_drvdata(&sch->dev, NULL);
153 static int vfio_ccw_sch_remove(struct subchannel *sch)
155 struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev);
157 vfio_ccw_sch_quiesce(sch);
159 vfio_ccw_mdev_unreg(sch);
161 dev_set_drvdata(&sch->dev, NULL);
168 static void vfio_ccw_sch_shutdown(struct subchannel *sch)
170 vfio_ccw_sch_quiesce(sch);
174 * vfio_ccw_sch_event - process subchannel event
176 * @process: non-zero if function is called in process context
178 * An unspecified event occurred for this subchannel. Adjust data according
179 * to the current operational state of the subchannel. Return zero when the
180 * event has been handled sufficiently or -EAGAIN when this function should
181 * be called again in process context.
183 static int vfio_ccw_sch_event(struct subchannel *sch, int process)
185 struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev);
189 spin_lock_irqsave(sch->lock, flags);
190 if (!device_is_registered(&sch->dev))
193 if (work_pending(&sch->todo_work))
196 if (cio_update_schib(sch)) {
197 vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_NOT_OPER);
202 private = dev_get_drvdata(&sch->dev);
203 if (private->state == VFIO_CCW_STATE_NOT_OPER) {
204 private->state = private->mdev ? VFIO_CCW_STATE_IDLE :
205 VFIO_CCW_STATE_STANDBY;
210 spin_unlock_irqrestore(sch->lock, flags);
215 static struct css_device_id vfio_ccw_sch_ids[] = {
216 { .match_flags = 0x1, .type = SUBCHANNEL_TYPE_IO, },
217 { /* end of list */ },
219 MODULE_DEVICE_TABLE(css, vfio_ccw_sch_ids);
221 static struct css_driver vfio_ccw_sch_driver = {
224 .owner = THIS_MODULE,
226 .subchannel_type = vfio_ccw_sch_ids,
227 .irq = vfio_ccw_sch_irq,
228 .probe = vfio_ccw_sch_probe,
229 .remove = vfio_ccw_sch_remove,
230 .shutdown = vfio_ccw_sch_shutdown,
231 .sch_event = vfio_ccw_sch_event,
234 static int __init vfio_ccw_sch_init(void)
238 vfio_ccw_work_q = create_singlethread_workqueue("vfio-ccw");
239 if (!vfio_ccw_work_q)
242 isc_register(VFIO_CCW_ISC);
243 ret = css_driver_register(&vfio_ccw_sch_driver);
245 isc_unregister(VFIO_CCW_ISC);
246 destroy_workqueue(vfio_ccw_work_q);
252 static void __exit vfio_ccw_sch_exit(void)
254 css_driver_unregister(&vfio_ccw_sch_driver);
255 isc_unregister(VFIO_CCW_ISC);
256 destroy_workqueue(vfio_ccw_work_q);
258 module_init(vfio_ccw_sch_init);
259 module_exit(vfio_ccw_sch_exit);
261 MODULE_LICENSE("GPL v2");