xref: /openbmc/linux/drivers/s390/cio/vfio_ccw_fsm.c (revision d5afd5d135c8cc43bd2568361b4c91f0bd488c3f)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2bbe37e4cSDong Jia Shi /*
3bbe37e4cSDong Jia Shi  * Finite state machine for vfio-ccw device handling
4bbe37e4cSDong Jia Shi  *
5bbe37e4cSDong Jia Shi  * Copyright IBM Corp. 2017
6*d5afd5d1SCornelia Huck  * Copyright Red Hat, Inc. 2019
7bbe37e4cSDong Jia Shi  *
8bbe37e4cSDong Jia Shi  * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
9*d5afd5d1SCornelia Huck  *            Cornelia Huck <cohuck@redhat.com>
10bbe37e4cSDong Jia Shi  */
11bbe37e4cSDong Jia Shi 
12bbe37e4cSDong Jia Shi #include <linux/vfio.h>
13bbe37e4cSDong Jia Shi #include <linux/mdev.h>
14bbe37e4cSDong Jia Shi 
15bbe37e4cSDong Jia Shi #include "ioasm.h"
16bbe37e4cSDong Jia Shi #include "vfio_ccw_private.h"
17bbe37e4cSDong Jia Shi 
183cd90214SHalil Pasic #define CREATE_TRACE_POINTS
193cd90214SHalil Pasic #include "vfio_ccw_trace.h"
203cd90214SHalil Pasic 
21bbe37e4cSDong Jia Shi static int fsm_io_helper(struct vfio_ccw_private *private)
22bbe37e4cSDong Jia Shi {
23bbe37e4cSDong Jia Shi 	struct subchannel *sch;
24bbe37e4cSDong Jia Shi 	union orb *orb;
25bbe37e4cSDong Jia Shi 	int ccode;
26bbe37e4cSDong Jia Shi 	__u8 lpm;
27bbe37e4cSDong Jia Shi 	unsigned long flags;
283368e547SCornelia Huck 	int ret;
29bbe37e4cSDong Jia Shi 
30bbe37e4cSDong Jia Shi 	sch = private->sch;
31bbe37e4cSDong Jia Shi 
32bbe37e4cSDong Jia Shi 	spin_lock_irqsave(sch->lock, flags);
33bbe37e4cSDong Jia Shi 
34bbe37e4cSDong Jia Shi 	orb = cp_get_orb(&private->cp, (u32)(addr_t)sch, sch->lpm);
3571189f26SCornelia Huck 	if (!orb) {
3671189f26SCornelia Huck 		ret = -EIO;
3771189f26SCornelia Huck 		goto out;
3871189f26SCornelia Huck 	}
39bbe37e4cSDong Jia Shi 
40bbe37e4cSDong Jia Shi 	/* Issue "Start Subchannel" */
41bbe37e4cSDong Jia Shi 	ccode = ssch(sch->schid, orb);
42bbe37e4cSDong Jia Shi 
43bbe37e4cSDong Jia Shi 	switch (ccode) {
44bbe37e4cSDong Jia Shi 	case 0:
45bbe37e4cSDong Jia Shi 		/*
46bbe37e4cSDong Jia Shi 		 * Initialize device status information
47bbe37e4cSDong Jia Shi 		 */
48bbe37e4cSDong Jia Shi 		sch->schib.scsw.cmd.actl |= SCSW_ACTL_START_PEND;
493368e547SCornelia Huck 		ret = 0;
50690f6a15SCornelia Huck 		private->state = VFIO_CCW_STATE_CP_PENDING;
513368e547SCornelia Huck 		break;
52bbe37e4cSDong Jia Shi 	case 1:		/* Status pending */
53bbe37e4cSDong Jia Shi 	case 2:		/* Busy */
543368e547SCornelia Huck 		ret = -EBUSY;
553368e547SCornelia Huck 		break;
56bbe37e4cSDong Jia Shi 	case 3:		/* Device/path not operational */
57bbe37e4cSDong Jia Shi 	{
58bbe37e4cSDong Jia Shi 		lpm = orb->cmd.lpm;
59bbe37e4cSDong Jia Shi 		if (lpm != 0)
60bbe37e4cSDong Jia Shi 			sch->lpm &= ~lpm;
61bbe37e4cSDong Jia Shi 		else
62bbe37e4cSDong Jia Shi 			sch->lpm = 0;
63bbe37e4cSDong Jia Shi 
64bbe37e4cSDong Jia Shi 		if (cio_update_schib(sch))
653368e547SCornelia Huck 			ret = -ENODEV;
663368e547SCornelia Huck 		else
673368e547SCornelia Huck 			ret = sch->lpm ? -EACCES : -ENODEV;
683368e547SCornelia Huck 		break;
69bbe37e4cSDong Jia Shi 	}
70bbe37e4cSDong Jia Shi 	default:
713368e547SCornelia Huck 		ret = ccode;
72bbe37e4cSDong Jia Shi 	}
7371189f26SCornelia Huck out:
743368e547SCornelia Huck 	spin_unlock_irqrestore(sch->lock, flags);
753368e547SCornelia Huck 	return ret;
76bbe37e4cSDong Jia Shi }
77bbe37e4cSDong Jia Shi 
78*d5afd5d1SCornelia Huck static int fsm_do_halt(struct vfio_ccw_private *private)
79*d5afd5d1SCornelia Huck {
80*d5afd5d1SCornelia Huck 	struct subchannel *sch;
81*d5afd5d1SCornelia Huck 	unsigned long flags;
82*d5afd5d1SCornelia Huck 	int ccode;
83*d5afd5d1SCornelia Huck 	int ret;
84*d5afd5d1SCornelia Huck 
85*d5afd5d1SCornelia Huck 	sch = private->sch;
86*d5afd5d1SCornelia Huck 
87*d5afd5d1SCornelia Huck 	spin_lock_irqsave(sch->lock, flags);
88*d5afd5d1SCornelia Huck 
89*d5afd5d1SCornelia Huck 	/* Issue "Halt Subchannel" */
90*d5afd5d1SCornelia Huck 	ccode = hsch(sch->schid);
91*d5afd5d1SCornelia Huck 
92*d5afd5d1SCornelia Huck 	switch (ccode) {
93*d5afd5d1SCornelia Huck 	case 0:
94*d5afd5d1SCornelia Huck 		/*
95*d5afd5d1SCornelia Huck 		 * Initialize device status information
96*d5afd5d1SCornelia Huck 		 */
97*d5afd5d1SCornelia Huck 		sch->schib.scsw.cmd.actl |= SCSW_ACTL_HALT_PEND;
98*d5afd5d1SCornelia Huck 		ret = 0;
99*d5afd5d1SCornelia Huck 		break;
100*d5afd5d1SCornelia Huck 	case 1:		/* Status pending */
101*d5afd5d1SCornelia Huck 	case 2:		/* Busy */
102*d5afd5d1SCornelia Huck 		ret = -EBUSY;
103*d5afd5d1SCornelia Huck 		break;
104*d5afd5d1SCornelia Huck 	case 3:		/* Device not operational */
105*d5afd5d1SCornelia Huck 		ret = -ENODEV;
106*d5afd5d1SCornelia Huck 		break;
107*d5afd5d1SCornelia Huck 	default:
108*d5afd5d1SCornelia Huck 		ret = ccode;
109*d5afd5d1SCornelia Huck 	}
110*d5afd5d1SCornelia Huck 	spin_unlock_irqrestore(sch->lock, flags);
111*d5afd5d1SCornelia Huck 	return ret;
112*d5afd5d1SCornelia Huck }
113*d5afd5d1SCornelia Huck 
114*d5afd5d1SCornelia Huck static int fsm_do_clear(struct vfio_ccw_private *private)
115*d5afd5d1SCornelia Huck {
116*d5afd5d1SCornelia Huck 	struct subchannel *sch;
117*d5afd5d1SCornelia Huck 	unsigned long flags;
118*d5afd5d1SCornelia Huck 	int ccode;
119*d5afd5d1SCornelia Huck 	int ret;
120*d5afd5d1SCornelia Huck 
121*d5afd5d1SCornelia Huck 	sch = private->sch;
122*d5afd5d1SCornelia Huck 
123*d5afd5d1SCornelia Huck 	spin_lock_irqsave(sch->lock, flags);
124*d5afd5d1SCornelia Huck 
125*d5afd5d1SCornelia Huck 	/* Issue "Clear Subchannel" */
126*d5afd5d1SCornelia Huck 	ccode = csch(sch->schid);
127*d5afd5d1SCornelia Huck 
128*d5afd5d1SCornelia Huck 	switch (ccode) {
129*d5afd5d1SCornelia Huck 	case 0:
130*d5afd5d1SCornelia Huck 		/*
131*d5afd5d1SCornelia Huck 		 * Initialize device status information
132*d5afd5d1SCornelia Huck 		 */
133*d5afd5d1SCornelia Huck 		sch->schib.scsw.cmd.actl = SCSW_ACTL_CLEAR_PEND;
134*d5afd5d1SCornelia Huck 		/* TODO: check what else we might need to clear */
135*d5afd5d1SCornelia Huck 		ret = 0;
136*d5afd5d1SCornelia Huck 		break;
137*d5afd5d1SCornelia Huck 	case 3:		/* Device not operational */
138*d5afd5d1SCornelia Huck 		ret = -ENODEV;
139*d5afd5d1SCornelia Huck 		break;
140*d5afd5d1SCornelia Huck 	default:
141*d5afd5d1SCornelia Huck 		ret = ccode;
142*d5afd5d1SCornelia Huck 	}
143*d5afd5d1SCornelia Huck 	spin_unlock_irqrestore(sch->lock, flags);
144*d5afd5d1SCornelia Huck 	return ret;
145*d5afd5d1SCornelia Huck }
146*d5afd5d1SCornelia Huck 
147bbe37e4cSDong Jia Shi static void fsm_notoper(struct vfio_ccw_private *private,
148bbe37e4cSDong Jia Shi 			enum vfio_ccw_event event)
149bbe37e4cSDong Jia Shi {
150bbe37e4cSDong Jia Shi 	struct subchannel *sch = private->sch;
151bbe37e4cSDong Jia Shi 
152bbe37e4cSDong Jia Shi 	/*
153bbe37e4cSDong Jia Shi 	 * TODO:
154bbe37e4cSDong Jia Shi 	 * Probably we should send the machine check to the guest.
155bbe37e4cSDong Jia Shi 	 */
156bbe37e4cSDong Jia Shi 	css_sched_sch_todo(sch, SCH_TODO_UNREG);
157bbe37e4cSDong Jia Shi 	private->state = VFIO_CCW_STATE_NOT_OPER;
158bbe37e4cSDong Jia Shi }
159bbe37e4cSDong Jia Shi 
160bbe37e4cSDong Jia Shi /*
161bbe37e4cSDong Jia Shi  * No operation action.
162bbe37e4cSDong Jia Shi  */
163bbe37e4cSDong Jia Shi static void fsm_nop(struct vfio_ccw_private *private,
164bbe37e4cSDong Jia Shi 		    enum vfio_ccw_event event)
165bbe37e4cSDong Jia Shi {
166bbe37e4cSDong Jia Shi }
167bbe37e4cSDong Jia Shi 
168bbe37e4cSDong Jia Shi static void fsm_io_error(struct vfio_ccw_private *private,
169bbe37e4cSDong Jia Shi 			 enum vfio_ccw_event event)
170bbe37e4cSDong Jia Shi {
171bbe37e4cSDong Jia Shi 	pr_err("vfio-ccw: FSM: I/O request from state:%d\n", private->state);
172c98e16b2SEric Farman 	private->io_region->ret_code = -EIO;
173bbe37e4cSDong Jia Shi }
174bbe37e4cSDong Jia Shi 
175bbe37e4cSDong Jia Shi static void fsm_io_busy(struct vfio_ccw_private *private,
176bbe37e4cSDong Jia Shi 			enum vfio_ccw_event event)
177bbe37e4cSDong Jia Shi {
178c98e16b2SEric Farman 	private->io_region->ret_code = -EBUSY;
179bbe37e4cSDong Jia Shi }
180bbe37e4cSDong Jia Shi 
181690f6a15SCornelia Huck static void fsm_io_retry(struct vfio_ccw_private *private,
182690f6a15SCornelia Huck 			 enum vfio_ccw_event event)
183690f6a15SCornelia Huck {
184690f6a15SCornelia Huck 	private->io_region->ret_code = -EAGAIN;
185690f6a15SCornelia Huck }
186690f6a15SCornelia Huck 
187*d5afd5d1SCornelia Huck static void fsm_async_error(struct vfio_ccw_private *private,
188*d5afd5d1SCornelia Huck 			    enum vfio_ccw_event event)
189*d5afd5d1SCornelia Huck {
190*d5afd5d1SCornelia Huck 	struct ccw_cmd_region *cmd_region = private->cmd_region;
191*d5afd5d1SCornelia Huck 
192*d5afd5d1SCornelia Huck 	pr_err("vfio-ccw: FSM: %s request from state:%d\n",
193*d5afd5d1SCornelia Huck 	       cmd_region->command == VFIO_CCW_ASYNC_CMD_HSCH ? "halt" :
194*d5afd5d1SCornelia Huck 	       cmd_region->command == VFIO_CCW_ASYNC_CMD_CSCH ? "clear" :
195*d5afd5d1SCornelia Huck 	       "<unknown>", private->state);
196*d5afd5d1SCornelia Huck 	cmd_region->ret_code = -EIO;
197*d5afd5d1SCornelia Huck }
198*d5afd5d1SCornelia Huck 
199*d5afd5d1SCornelia Huck static void fsm_async_retry(struct vfio_ccw_private *private,
200*d5afd5d1SCornelia Huck 			    enum vfio_ccw_event event)
201*d5afd5d1SCornelia Huck {
202*d5afd5d1SCornelia Huck 	private->cmd_region->ret_code = -EAGAIN;
203*d5afd5d1SCornelia Huck }
204*d5afd5d1SCornelia Huck 
205bbe37e4cSDong Jia Shi static void fsm_disabled_irq(struct vfio_ccw_private *private,
206bbe37e4cSDong Jia Shi 			     enum vfio_ccw_event event)
207bbe37e4cSDong Jia Shi {
208bbe37e4cSDong Jia Shi 	struct subchannel *sch = private->sch;
209bbe37e4cSDong Jia Shi 
210bbe37e4cSDong Jia Shi 	/*
211bbe37e4cSDong Jia Shi 	 * An interrupt in a disabled state means a previous disable was not
212bbe37e4cSDong Jia Shi 	 * successful - should not happen, but we try to disable again.
213bbe37e4cSDong Jia Shi 	 */
214bbe37e4cSDong Jia Shi 	cio_disable_subchannel(sch);
215bbe37e4cSDong Jia Shi }
2163cd90214SHalil Pasic inline struct subchannel_id get_schid(struct vfio_ccw_private *p)
2173cd90214SHalil Pasic {
2183cd90214SHalil Pasic 	return p->sch->schid;
2193cd90214SHalil Pasic }
220bbe37e4cSDong Jia Shi 
221bbe37e4cSDong Jia Shi /*
222bbe37e4cSDong Jia Shi  * Deal with the ccw command request from the userspace.
223bbe37e4cSDong Jia Shi  */
224bbe37e4cSDong Jia Shi static void fsm_io_request(struct vfio_ccw_private *private,
225bbe37e4cSDong Jia Shi 			   enum vfio_ccw_event event)
226bbe37e4cSDong Jia Shi {
227bbe37e4cSDong Jia Shi 	union orb *orb;
228bbe37e4cSDong Jia Shi 	union scsw *scsw = &private->scsw;
229c98e16b2SEric Farman 	struct ccw_io_region *io_region = private->io_region;
230bbe37e4cSDong Jia Shi 	struct mdev_device *mdev = private->mdev;
2313cd90214SHalil Pasic 	char *errstr = "request";
232bbe37e4cSDong Jia Shi 
233690f6a15SCornelia Huck 	private->state = VFIO_CCW_STATE_CP_PROCESSING;
234bbe37e4cSDong Jia Shi 	memcpy(scsw, io_region->scsw_area, sizeof(*scsw));
235bbe37e4cSDong Jia Shi 
236bbe37e4cSDong Jia Shi 	if (scsw->cmd.fctl & SCSW_FCTL_START_FUNC) {
237bbe37e4cSDong Jia Shi 		orb = (union orb *)io_region->orb_area;
238bbe37e4cSDong Jia Shi 
2399851bc77SCornelia Huck 		/* Don't try to build a cp if transport mode is specified. */
2409851bc77SCornelia Huck 		if (orb->tm.b) {
2419851bc77SCornelia Huck 			io_region->ret_code = -EOPNOTSUPP;
2423cd90214SHalil Pasic 			errstr = "transport mode";
2439851bc77SCornelia Huck 			goto err_out;
2449851bc77SCornelia Huck 		}
245bbe37e4cSDong Jia Shi 		io_region->ret_code = cp_init(&private->cp, mdev_dev(mdev),
246bbe37e4cSDong Jia Shi 					      orb);
2473cd90214SHalil Pasic 		if (io_region->ret_code) {
2483cd90214SHalil Pasic 			errstr = "cp init";
249bbe37e4cSDong Jia Shi 			goto err_out;
2503cd90214SHalil Pasic 		}
251bbe37e4cSDong Jia Shi 
252bbe37e4cSDong Jia Shi 		io_region->ret_code = cp_prefetch(&private->cp);
253bbe37e4cSDong Jia Shi 		if (io_region->ret_code) {
2543cd90214SHalil Pasic 			errstr = "cp prefetch";
255bbe37e4cSDong Jia Shi 			cp_free(&private->cp);
256bbe37e4cSDong Jia Shi 			goto err_out;
257bbe37e4cSDong Jia Shi 		}
258bbe37e4cSDong Jia Shi 
259bbe37e4cSDong Jia Shi 		/* Start channel program and wait for I/O interrupt. */
260bbe37e4cSDong Jia Shi 		io_region->ret_code = fsm_io_helper(private);
261bbe37e4cSDong Jia Shi 		if (io_region->ret_code) {
2623cd90214SHalil Pasic 			errstr = "cp fsm_io_helper";
263bbe37e4cSDong Jia Shi 			cp_free(&private->cp);
264bbe37e4cSDong Jia Shi 			goto err_out;
265bbe37e4cSDong Jia Shi 		}
266bbe37e4cSDong Jia Shi 		return;
267bbe37e4cSDong Jia Shi 	} else if (scsw->cmd.fctl & SCSW_FCTL_HALT_FUNC) {
268*d5afd5d1SCornelia Huck 		/* halt is handled via the async cmd region */
269bbe37e4cSDong Jia Shi 		io_region->ret_code = -EOPNOTSUPP;
270bbe37e4cSDong Jia Shi 		goto err_out;
271bbe37e4cSDong Jia Shi 	} else if (scsw->cmd.fctl & SCSW_FCTL_CLEAR_FUNC) {
272*d5afd5d1SCornelia Huck 		/* clear is handled via the async cmd region */
273bbe37e4cSDong Jia Shi 		io_region->ret_code = -EOPNOTSUPP;
274bbe37e4cSDong Jia Shi 		goto err_out;
275bbe37e4cSDong Jia Shi 	}
276bbe37e4cSDong Jia Shi 
277bbe37e4cSDong Jia Shi err_out:
2783cd90214SHalil Pasic 	trace_vfio_ccw_io_fctl(scsw->cmd.fctl, get_schid(private),
2793cd90214SHalil Pasic 			       io_region->ret_code, errstr);
280bbe37e4cSDong Jia Shi }
281bbe37e4cSDong Jia Shi 
282bbe37e4cSDong Jia Shi /*
283*d5afd5d1SCornelia Huck  * Deal with an async request from userspace.
284*d5afd5d1SCornelia Huck  */
285*d5afd5d1SCornelia Huck static void fsm_async_request(struct vfio_ccw_private *private,
286*d5afd5d1SCornelia Huck 			      enum vfio_ccw_event event)
287*d5afd5d1SCornelia Huck {
288*d5afd5d1SCornelia Huck 	struct ccw_cmd_region *cmd_region = private->cmd_region;
289*d5afd5d1SCornelia Huck 
290*d5afd5d1SCornelia Huck 	switch (cmd_region->command) {
291*d5afd5d1SCornelia Huck 	case VFIO_CCW_ASYNC_CMD_HSCH:
292*d5afd5d1SCornelia Huck 		cmd_region->ret_code = fsm_do_halt(private);
293*d5afd5d1SCornelia Huck 		break;
294*d5afd5d1SCornelia Huck 	case VFIO_CCW_ASYNC_CMD_CSCH:
295*d5afd5d1SCornelia Huck 		cmd_region->ret_code = fsm_do_clear(private);
296*d5afd5d1SCornelia Huck 		break;
297*d5afd5d1SCornelia Huck 	default:
298*d5afd5d1SCornelia Huck 		/* should not happen? */
299*d5afd5d1SCornelia Huck 		cmd_region->ret_code = -EINVAL;
300*d5afd5d1SCornelia Huck 	}
301*d5afd5d1SCornelia Huck }
302*d5afd5d1SCornelia Huck 
303*d5afd5d1SCornelia Huck /*
304bbe37e4cSDong Jia Shi  * Got an interrupt for a normal io (state busy).
305bbe37e4cSDong Jia Shi  */
306bbe37e4cSDong Jia Shi static void fsm_irq(struct vfio_ccw_private *private,
307bbe37e4cSDong Jia Shi 		    enum vfio_ccw_event event)
308bbe37e4cSDong Jia Shi {
309c9c31b07SDong Jia Shi 	struct irb *irb = this_cpu_ptr(&cio_irb);
310bbe37e4cSDong Jia Shi 
311bbe37e4cSDong Jia Shi 	memcpy(&private->irb, irb, sizeof(*irb));
312bbe37e4cSDong Jia Shi 
313bbe37e4cSDong Jia Shi 	queue_work(vfio_ccw_work_q, &private->io_work);
314bbe37e4cSDong Jia Shi 
315bbe37e4cSDong Jia Shi 	if (private->completion)
316bbe37e4cSDong Jia Shi 		complete(private->completion);
317bbe37e4cSDong Jia Shi }
318bbe37e4cSDong Jia Shi 
319bbe37e4cSDong Jia Shi /*
320bbe37e4cSDong Jia Shi  * Device statemachine
321bbe37e4cSDong Jia Shi  */
322bbe37e4cSDong Jia Shi fsm_func_t *vfio_ccw_jumptable[NR_VFIO_CCW_STATES][NR_VFIO_CCW_EVENTS] = {
323bbe37e4cSDong Jia Shi 	[VFIO_CCW_STATE_NOT_OPER] = {
324bbe37e4cSDong Jia Shi 		[VFIO_CCW_EVENT_NOT_OPER]	= fsm_nop,
325bbe37e4cSDong Jia Shi 		[VFIO_CCW_EVENT_IO_REQ]		= fsm_io_error,
326*d5afd5d1SCornelia Huck 		[VFIO_CCW_EVENT_ASYNC_REQ]	= fsm_async_error,
327bbe37e4cSDong Jia Shi 		[VFIO_CCW_EVENT_INTERRUPT]	= fsm_disabled_irq,
328bbe37e4cSDong Jia Shi 	},
329bbe37e4cSDong Jia Shi 	[VFIO_CCW_STATE_STANDBY] = {
330bbe37e4cSDong Jia Shi 		[VFIO_CCW_EVENT_NOT_OPER]	= fsm_notoper,
331bbe37e4cSDong Jia Shi 		[VFIO_CCW_EVENT_IO_REQ]		= fsm_io_error,
332*d5afd5d1SCornelia Huck 		[VFIO_CCW_EVENT_ASYNC_REQ]	= fsm_async_error,
333bbe37e4cSDong Jia Shi 		[VFIO_CCW_EVENT_INTERRUPT]	= fsm_irq,
334bbe37e4cSDong Jia Shi 	},
335bbe37e4cSDong Jia Shi 	[VFIO_CCW_STATE_IDLE] = {
336bbe37e4cSDong Jia Shi 		[VFIO_CCW_EVENT_NOT_OPER]	= fsm_notoper,
337bbe37e4cSDong Jia Shi 		[VFIO_CCW_EVENT_IO_REQ]		= fsm_io_request,
338*d5afd5d1SCornelia Huck 		[VFIO_CCW_EVENT_ASYNC_REQ]	= fsm_async_request,
339bbe37e4cSDong Jia Shi 		[VFIO_CCW_EVENT_INTERRUPT]	= fsm_irq,
340bbe37e4cSDong Jia Shi 	},
341690f6a15SCornelia Huck 	[VFIO_CCW_STATE_CP_PROCESSING] = {
342690f6a15SCornelia Huck 		[VFIO_CCW_EVENT_NOT_OPER]	= fsm_notoper,
343690f6a15SCornelia Huck 		[VFIO_CCW_EVENT_IO_REQ]		= fsm_io_retry,
344*d5afd5d1SCornelia Huck 		[VFIO_CCW_EVENT_ASYNC_REQ]	= fsm_async_retry,
345690f6a15SCornelia Huck 		[VFIO_CCW_EVENT_INTERRUPT]	= fsm_irq,
346690f6a15SCornelia Huck 	},
347690f6a15SCornelia Huck 	[VFIO_CCW_STATE_CP_PENDING] = {
348bbe37e4cSDong Jia Shi 		[VFIO_CCW_EVENT_NOT_OPER]	= fsm_notoper,
349bbe37e4cSDong Jia Shi 		[VFIO_CCW_EVENT_IO_REQ]		= fsm_io_busy,
350*d5afd5d1SCornelia Huck 		[VFIO_CCW_EVENT_ASYNC_REQ]	= fsm_async_request,
351bbe37e4cSDong Jia Shi 		[VFIO_CCW_EVENT_INTERRUPT]	= fsm_irq,
352bbe37e4cSDong Jia Shi 	},
353bbe37e4cSDong Jia Shi };
354