162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Private stuff for vfio_ccw driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright IBM Corp. 2017 662306a36Sopenharmony_ci * Copyright Red Hat, Inc. 2019 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com> 962306a36Sopenharmony_ci * Xiao Feng Ren <renxiaof@linux.vnet.ibm.com> 1062306a36Sopenharmony_ci * Cornelia Huck <cohuck@redhat.com> 1162306a36Sopenharmony_ci */ 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#ifndef _VFIO_CCW_PRIVATE_H_ 1462306a36Sopenharmony_ci#define _VFIO_CCW_PRIVATE_H_ 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include <linux/completion.h> 1762306a36Sopenharmony_ci#include <linux/eventfd.h> 1862306a36Sopenharmony_ci#include <linux/workqueue.h> 1962306a36Sopenharmony_ci#include <linux/vfio_ccw.h> 2062306a36Sopenharmony_ci#include <linux/vfio.h> 2162306a36Sopenharmony_ci#include <linux/mdev.h> 2262306a36Sopenharmony_ci#include <asm/crw.h> 2362306a36Sopenharmony_ci#include <asm/debug.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#include "css.h" 2662306a36Sopenharmony_ci#include "vfio_ccw_cp.h" 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#define VFIO_CCW_OFFSET_SHIFT 10 2962306a36Sopenharmony_ci#define VFIO_CCW_OFFSET_TO_INDEX(off) (off >> VFIO_CCW_OFFSET_SHIFT) 3062306a36Sopenharmony_ci#define VFIO_CCW_INDEX_TO_OFFSET(index) ((u64)(index) << VFIO_CCW_OFFSET_SHIFT) 3162306a36Sopenharmony_ci#define VFIO_CCW_OFFSET_MASK (((u64)(1) << VFIO_CCW_OFFSET_SHIFT) - 1) 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci/* capability chain handling similar to vfio-pci */ 3462306a36Sopenharmony_cistruct vfio_ccw_private; 3562306a36Sopenharmony_cistruct vfio_ccw_region; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistruct vfio_ccw_regops { 3862306a36Sopenharmony_ci ssize_t (*read)(struct vfio_ccw_private *private, char __user *buf, 3962306a36Sopenharmony_ci size_t count, loff_t *ppos); 4062306a36Sopenharmony_ci ssize_t (*write)(struct vfio_ccw_private *private, 4162306a36Sopenharmony_ci const char __user *buf, size_t count, loff_t *ppos); 4262306a36Sopenharmony_ci void (*release)(struct vfio_ccw_private *private, 4362306a36Sopenharmony_ci struct vfio_ccw_region *region); 4462306a36Sopenharmony_ci}; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cistruct vfio_ccw_region { 4762306a36Sopenharmony_ci u32 type; 4862306a36Sopenharmony_ci u32 subtype; 4962306a36Sopenharmony_ci const struct vfio_ccw_regops *ops; 5062306a36Sopenharmony_ci void *data; 5162306a36Sopenharmony_ci size_t size; 5262306a36Sopenharmony_ci u32 flags; 5362306a36Sopenharmony_ci}; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ciint vfio_ccw_register_dev_region(struct vfio_ccw_private *private, 5662306a36Sopenharmony_ci unsigned int subtype, 5762306a36Sopenharmony_ci const struct vfio_ccw_regops *ops, 5862306a36Sopenharmony_ci size_t size, u32 flags, void *data); 5962306a36Sopenharmony_civoid vfio_ccw_unregister_dev_regions(struct vfio_ccw_private *private); 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ciint vfio_ccw_register_async_dev_regions(struct vfio_ccw_private *private); 6262306a36Sopenharmony_ciint vfio_ccw_register_schib_dev_regions(struct vfio_ccw_private *private); 6362306a36Sopenharmony_ciint vfio_ccw_register_crw_dev_regions(struct vfio_ccw_private *private); 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistruct vfio_ccw_crw { 6662306a36Sopenharmony_ci struct list_head next; 6762306a36Sopenharmony_ci struct crw crw; 6862306a36Sopenharmony_ci}; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci/** 7162306a36Sopenharmony_ci * struct vfio_ccw_parent 7262306a36Sopenharmony_ci * 7362306a36Sopenharmony_ci * @dev: embedded device struct 7462306a36Sopenharmony_ci * @parent: parent data structures for mdevs created 7562306a36Sopenharmony_ci * @mdev_type(s): identifying information for mdevs created 7662306a36Sopenharmony_ci */ 7762306a36Sopenharmony_cistruct vfio_ccw_parent { 7862306a36Sopenharmony_ci struct device dev; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci struct mdev_parent parent; 8162306a36Sopenharmony_ci struct mdev_type mdev_type; 8262306a36Sopenharmony_ci struct mdev_type *mdev_types[]; 8362306a36Sopenharmony_ci}; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci/** 8662306a36Sopenharmony_ci * struct vfio_ccw_private 8762306a36Sopenharmony_ci * @vdev: Embedded VFIO device 8862306a36Sopenharmony_ci * @state: internal state of the device 8962306a36Sopenharmony_ci * @completion: synchronization helper of the I/O completion 9062306a36Sopenharmony_ci * @io_region: MMIO region to input/output I/O arguments/results 9162306a36Sopenharmony_ci * @io_mutex: protect against concurrent update of I/O regions 9262306a36Sopenharmony_ci * @region: additional regions for other subchannel operations 9362306a36Sopenharmony_ci * @cmd_region: MMIO region for asynchronous I/O commands other than START 9462306a36Sopenharmony_ci * @schib_region: MMIO region for SCHIB information 9562306a36Sopenharmony_ci * @crw_region: MMIO region for getting channel report words 9662306a36Sopenharmony_ci * @num_regions: number of additional regions 9762306a36Sopenharmony_ci * @cp: channel program for the current I/O operation 9862306a36Sopenharmony_ci * @irb: irb info received from interrupt 9962306a36Sopenharmony_ci * @scsw: scsw info 10062306a36Sopenharmony_ci * @io_trigger: eventfd ctx for signaling userspace I/O results 10162306a36Sopenharmony_ci * @crw_trigger: eventfd ctx for signaling userspace CRW information 10262306a36Sopenharmony_ci * @req_trigger: eventfd ctx for signaling userspace to return device 10362306a36Sopenharmony_ci * @io_work: work for deferral process of I/O handling 10462306a36Sopenharmony_ci * @crw_work: work for deferral process of CRW handling 10562306a36Sopenharmony_ci */ 10662306a36Sopenharmony_cistruct vfio_ccw_private { 10762306a36Sopenharmony_ci struct vfio_device vdev; 10862306a36Sopenharmony_ci int state; 10962306a36Sopenharmony_ci struct completion *completion; 11062306a36Sopenharmony_ci struct ccw_io_region *io_region; 11162306a36Sopenharmony_ci struct mutex io_mutex; 11262306a36Sopenharmony_ci struct vfio_ccw_region *region; 11362306a36Sopenharmony_ci struct ccw_cmd_region *cmd_region; 11462306a36Sopenharmony_ci struct ccw_schib_region *schib_region; 11562306a36Sopenharmony_ci struct ccw_crw_region *crw_region; 11662306a36Sopenharmony_ci int num_regions; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci struct channel_program cp; 11962306a36Sopenharmony_ci struct irb irb; 12062306a36Sopenharmony_ci union scsw scsw; 12162306a36Sopenharmony_ci struct list_head crw; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci struct eventfd_ctx *io_trigger; 12462306a36Sopenharmony_ci struct eventfd_ctx *crw_trigger; 12562306a36Sopenharmony_ci struct eventfd_ctx *req_trigger; 12662306a36Sopenharmony_ci struct work_struct io_work; 12762306a36Sopenharmony_ci struct work_struct crw_work; 12862306a36Sopenharmony_ci} __aligned(8); 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ciint vfio_ccw_sch_quiesce(struct subchannel *sch); 13162306a36Sopenharmony_civoid vfio_ccw_sch_io_todo(struct work_struct *work); 13262306a36Sopenharmony_civoid vfio_ccw_crw_todo(struct work_struct *work); 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ciextern struct mdev_driver vfio_ccw_mdev_driver; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci/* 13762306a36Sopenharmony_ci * States of the device statemachine. 13862306a36Sopenharmony_ci */ 13962306a36Sopenharmony_cienum vfio_ccw_state { 14062306a36Sopenharmony_ci VFIO_CCW_STATE_NOT_OPER, 14162306a36Sopenharmony_ci VFIO_CCW_STATE_STANDBY, 14262306a36Sopenharmony_ci VFIO_CCW_STATE_IDLE, 14362306a36Sopenharmony_ci VFIO_CCW_STATE_CP_PROCESSING, 14462306a36Sopenharmony_ci VFIO_CCW_STATE_CP_PENDING, 14562306a36Sopenharmony_ci /* last element! */ 14662306a36Sopenharmony_ci NR_VFIO_CCW_STATES 14762306a36Sopenharmony_ci}; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci/* 15062306a36Sopenharmony_ci * Asynchronous events of the device statemachine. 15162306a36Sopenharmony_ci */ 15262306a36Sopenharmony_cienum vfio_ccw_event { 15362306a36Sopenharmony_ci VFIO_CCW_EVENT_NOT_OPER, 15462306a36Sopenharmony_ci VFIO_CCW_EVENT_IO_REQ, 15562306a36Sopenharmony_ci VFIO_CCW_EVENT_INTERRUPT, 15662306a36Sopenharmony_ci VFIO_CCW_EVENT_ASYNC_REQ, 15762306a36Sopenharmony_ci VFIO_CCW_EVENT_OPEN, 15862306a36Sopenharmony_ci VFIO_CCW_EVENT_CLOSE, 15962306a36Sopenharmony_ci /* last element! */ 16062306a36Sopenharmony_ci NR_VFIO_CCW_EVENTS 16162306a36Sopenharmony_ci}; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci/* 16462306a36Sopenharmony_ci * Action called through jumptable. 16562306a36Sopenharmony_ci */ 16662306a36Sopenharmony_citypedef void (fsm_func_t)(struct vfio_ccw_private *, enum vfio_ccw_event); 16762306a36Sopenharmony_ciextern fsm_func_t *vfio_ccw_jumptable[NR_VFIO_CCW_STATES][NR_VFIO_CCW_EVENTS]; 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_cistatic inline void vfio_ccw_fsm_event(struct vfio_ccw_private *private, 17062306a36Sopenharmony_ci enum vfio_ccw_event event) 17162306a36Sopenharmony_ci{ 17262306a36Sopenharmony_ci struct subchannel *sch = to_subchannel(private->vdev.dev->parent); 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci if (sch) 17562306a36Sopenharmony_ci trace_vfio_ccw_fsm_event(sch->schid, private->state, event); 17662306a36Sopenharmony_ci vfio_ccw_jumptable[private->state][event](private, event); 17762306a36Sopenharmony_ci} 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ciextern struct workqueue_struct *vfio_ccw_work_q; 18062306a36Sopenharmony_ciextern struct kmem_cache *vfio_ccw_io_region; 18162306a36Sopenharmony_ciextern struct kmem_cache *vfio_ccw_cmd_region; 18262306a36Sopenharmony_ciextern struct kmem_cache *vfio_ccw_schib_region; 18362306a36Sopenharmony_ciextern struct kmem_cache *vfio_ccw_crw_region; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci/* s390 debug feature, similar to base cio */ 18662306a36Sopenharmony_ciextern debug_info_t *vfio_ccw_debug_msg_id; 18762306a36Sopenharmony_ciextern debug_info_t *vfio_ccw_debug_trace_id; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci#define VFIO_CCW_TRACE_EVENT(imp, txt) \ 19062306a36Sopenharmony_ci debug_text_event(vfio_ccw_debug_trace_id, imp, txt) 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci#define VFIO_CCW_MSG_EVENT(imp, args...) \ 19362306a36Sopenharmony_ci debug_sprintf_event(vfio_ccw_debug_msg_id, imp, ##args) 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_cistatic inline void VFIO_CCW_HEX_EVENT(int level, void *data, int length) 19662306a36Sopenharmony_ci{ 19762306a36Sopenharmony_ci debug_event(vfio_ccw_debug_trace_id, level, data, length); 19862306a36Sopenharmony_ci} 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci#endif 201