18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef S390_IO_SCH_H
38c2ecf20Sopenharmony_ci#define S390_IO_SCH_H
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include <linux/types.h>
68c2ecf20Sopenharmony_ci#include <asm/schid.h>
78c2ecf20Sopenharmony_ci#include <asm/ccwdev.h>
88c2ecf20Sopenharmony_ci#include <asm/irq.h>
98c2ecf20Sopenharmony_ci#include "css.h"
108c2ecf20Sopenharmony_ci#include "orb.h"
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_cistruct io_subchannel_dma_area {
138c2ecf20Sopenharmony_ci	struct ccw1 sense_ccw;	/* static ccw for sense command */
148c2ecf20Sopenharmony_ci};
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_cistruct io_subchannel_private {
178c2ecf20Sopenharmony_ci	union orb orb;		/* operation request block */
188c2ecf20Sopenharmony_ci	struct ccw_device *cdev;/* pointer to the child ccw device */
198c2ecf20Sopenharmony_ci	struct {
208c2ecf20Sopenharmony_ci		unsigned int suspend:1;	/* allow suspend */
218c2ecf20Sopenharmony_ci		unsigned int prefetch:1;/* deny prefetch */
228c2ecf20Sopenharmony_ci		unsigned int inter:1;	/* suppress intermediate interrupts */
238c2ecf20Sopenharmony_ci	} __packed options;
248c2ecf20Sopenharmony_ci	struct io_subchannel_dma_area *dma_area;
258c2ecf20Sopenharmony_ci	dma_addr_t dma_area_dma;
268c2ecf20Sopenharmony_ci} __aligned(8);
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci#define to_io_private(n) ((struct io_subchannel_private *) \
298c2ecf20Sopenharmony_ci			  dev_get_drvdata(&(n)->dev))
308c2ecf20Sopenharmony_ci#define set_io_private(n, p) (dev_set_drvdata(&(n)->dev, p))
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_cistatic inline struct ccw_device *sch_get_cdev(struct subchannel *sch)
338c2ecf20Sopenharmony_ci{
348c2ecf20Sopenharmony_ci	struct io_subchannel_private *priv = to_io_private(sch);
358c2ecf20Sopenharmony_ci	return priv ? priv->cdev : NULL;
368c2ecf20Sopenharmony_ci}
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_cistatic inline void sch_set_cdev(struct subchannel *sch,
398c2ecf20Sopenharmony_ci				struct ccw_device *cdev)
408c2ecf20Sopenharmony_ci{
418c2ecf20Sopenharmony_ci	struct io_subchannel_private *priv = to_io_private(sch);
428c2ecf20Sopenharmony_ci	if (priv)
438c2ecf20Sopenharmony_ci		priv->cdev = cdev;
448c2ecf20Sopenharmony_ci}
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci#define MAX_CIWS 8
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci/*
498c2ecf20Sopenharmony_ci * Possible status values for a CCW request's I/O.
508c2ecf20Sopenharmony_ci */
518c2ecf20Sopenharmony_cienum io_status {
528c2ecf20Sopenharmony_ci	IO_DONE,
538c2ecf20Sopenharmony_ci	IO_RUNNING,
548c2ecf20Sopenharmony_ci	IO_STATUS_ERROR,
558c2ecf20Sopenharmony_ci	IO_PATH_ERROR,
568c2ecf20Sopenharmony_ci	IO_REJECTED,
578c2ecf20Sopenharmony_ci	IO_KILLED
588c2ecf20Sopenharmony_ci};
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci/**
618c2ecf20Sopenharmony_ci * ccw_request - Internal CCW request.
628c2ecf20Sopenharmony_ci * @cp: channel program to start
638c2ecf20Sopenharmony_ci * @timeout: maximum allowable time in jiffies between start I/O and interrupt
648c2ecf20Sopenharmony_ci * @maxretries: number of retries per I/O operation and path
658c2ecf20Sopenharmony_ci * @lpm: mask of paths to use
668c2ecf20Sopenharmony_ci * @check: optional callback that determines if results are final
678c2ecf20Sopenharmony_ci * @filter: optional callback to adjust request status based on IRB data
688c2ecf20Sopenharmony_ci * @callback: final callback
698c2ecf20Sopenharmony_ci * @data: user-defined pointer passed to all callbacks
708c2ecf20Sopenharmony_ci * @singlepath: if set, use only one path from @lpm per start I/O
718c2ecf20Sopenharmony_ci * @cancel: non-zero if request was cancelled
728c2ecf20Sopenharmony_ci * @done: non-zero if request was finished
738c2ecf20Sopenharmony_ci * @mask: current path mask
748c2ecf20Sopenharmony_ci * @retries: current number of retries
758c2ecf20Sopenharmony_ci * @drc: delayed return code
768c2ecf20Sopenharmony_ci */
778c2ecf20Sopenharmony_cistruct ccw_request {
788c2ecf20Sopenharmony_ci	struct ccw1 *cp;
798c2ecf20Sopenharmony_ci	unsigned long timeout;
808c2ecf20Sopenharmony_ci	u16 maxretries;
818c2ecf20Sopenharmony_ci	u8 lpm;
828c2ecf20Sopenharmony_ci	int (*check)(struct ccw_device *, void *);
838c2ecf20Sopenharmony_ci	enum io_status (*filter)(struct ccw_device *, void *, struct irb *,
848c2ecf20Sopenharmony_ci				 enum io_status);
858c2ecf20Sopenharmony_ci	void (*callback)(struct ccw_device *, void *, int);
868c2ecf20Sopenharmony_ci	void *data;
878c2ecf20Sopenharmony_ci	unsigned int singlepath:1;
888c2ecf20Sopenharmony_ci	/* These fields are used internally. */
898c2ecf20Sopenharmony_ci	unsigned int cancel:1;
908c2ecf20Sopenharmony_ci	unsigned int done:1;
918c2ecf20Sopenharmony_ci	u16 mask;
928c2ecf20Sopenharmony_ci	u16 retries;
938c2ecf20Sopenharmony_ci	int drc;
948c2ecf20Sopenharmony_ci} __attribute__((packed));
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci/*
978c2ecf20Sopenharmony_ci * sense-id response buffer layout
988c2ecf20Sopenharmony_ci */
998c2ecf20Sopenharmony_cistruct senseid {
1008c2ecf20Sopenharmony_ci	/* common part */
1018c2ecf20Sopenharmony_ci	u8  reserved;	/* always 0x'FF' */
1028c2ecf20Sopenharmony_ci	u16 cu_type;	/* control unit type */
1038c2ecf20Sopenharmony_ci	u8  cu_model;	/* control unit model */
1048c2ecf20Sopenharmony_ci	u16 dev_type;	/* device type */
1058c2ecf20Sopenharmony_ci	u8  dev_model;	/* device model */
1068c2ecf20Sopenharmony_ci	u8  unused;	/* padding byte */
1078c2ecf20Sopenharmony_ci	/* extended part */
1088c2ecf20Sopenharmony_ci	struct ciw ciw[MAX_CIWS];	/* variable # of CIWs */
1098c2ecf20Sopenharmony_ci}  __attribute__ ((packed, aligned(4)));
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_cienum cdev_todo {
1128c2ecf20Sopenharmony_ci	CDEV_TODO_NOTHING,
1138c2ecf20Sopenharmony_ci	CDEV_TODO_ENABLE_CMF,
1148c2ecf20Sopenharmony_ci	CDEV_TODO_REBIND,
1158c2ecf20Sopenharmony_ci	CDEV_TODO_REGISTER,
1168c2ecf20Sopenharmony_ci	CDEV_TODO_UNREG,
1178c2ecf20Sopenharmony_ci	CDEV_TODO_UNREG_EVAL,
1188c2ecf20Sopenharmony_ci};
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci#define FAKE_CMD_IRB	1
1218c2ecf20Sopenharmony_ci#define FAKE_TM_IRB	2
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_cistruct ccw_device_dma_area {
1248c2ecf20Sopenharmony_ci	struct senseid senseid;	/* SenseID info */
1258c2ecf20Sopenharmony_ci	struct ccw1 iccws[2];	/* ccws for SNID/SID/SPGID commands */
1268c2ecf20Sopenharmony_ci	struct irb irb;		/* device status */
1278c2ecf20Sopenharmony_ci	struct pgid pgid[8];	/* path group IDs per chpid*/
1288c2ecf20Sopenharmony_ci};
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_cistruct ccw_device_private {
1318c2ecf20Sopenharmony_ci	struct ccw_device *cdev;
1328c2ecf20Sopenharmony_ci	struct subchannel *sch;
1338c2ecf20Sopenharmony_ci	int state;		/* device state */
1348c2ecf20Sopenharmony_ci	atomic_t onoff;
1358c2ecf20Sopenharmony_ci	struct ccw_dev_id dev_id;	/* device id */
1368c2ecf20Sopenharmony_ci	struct ccw_request req;		/* internal I/O request */
1378c2ecf20Sopenharmony_ci	int iretry;
1388c2ecf20Sopenharmony_ci	u8 pgid_valid_mask;	/* mask of valid PGIDs */
1398c2ecf20Sopenharmony_ci	u8 pgid_todo_mask;	/* mask of PGIDs to be adjusted */
1408c2ecf20Sopenharmony_ci	u8 pgid_reset_mask;	/* mask of PGIDs which were reset */
1418c2ecf20Sopenharmony_ci	u8 path_noirq_mask;	/* mask of paths for which no irq was
1428c2ecf20Sopenharmony_ci				   received */
1438c2ecf20Sopenharmony_ci	u8 path_notoper_mask;	/* mask of paths which were found
1448c2ecf20Sopenharmony_ci				   not operable */
1458c2ecf20Sopenharmony_ci	u8 path_gone_mask;	/* mask of paths, that became unavailable */
1468c2ecf20Sopenharmony_ci	u8 path_new_mask;	/* mask of paths, that became available */
1478c2ecf20Sopenharmony_ci	u8 path_broken_mask;	/* mask of paths, which were found to be
1488c2ecf20Sopenharmony_ci				   unusable */
1498c2ecf20Sopenharmony_ci	struct {
1508c2ecf20Sopenharmony_ci		unsigned int fast:1;	/* post with "channel end" */
1518c2ecf20Sopenharmony_ci		unsigned int repall:1;	/* report every interrupt status */
1528c2ecf20Sopenharmony_ci		unsigned int pgroup:1;	/* do path grouping */
1538c2ecf20Sopenharmony_ci		unsigned int force:1;	/* allow forced online */
1548c2ecf20Sopenharmony_ci		unsigned int mpath:1;	/* do multipathing */
1558c2ecf20Sopenharmony_ci	} __attribute__ ((packed)) options;
1568c2ecf20Sopenharmony_ci	struct {
1578c2ecf20Sopenharmony_ci		unsigned int esid:1;	    /* Ext. SenseID supported by HW */
1588c2ecf20Sopenharmony_ci		unsigned int dosense:1;	    /* delayed SENSE required */
1598c2ecf20Sopenharmony_ci		unsigned int doverify:1;    /* delayed path verification */
1608c2ecf20Sopenharmony_ci		unsigned int donotify:1;    /* call notify function */
1618c2ecf20Sopenharmony_ci		unsigned int recog_done:1;  /* dev. recog. complete */
1628c2ecf20Sopenharmony_ci		unsigned int fake_irb:2;    /* deliver faked irb */
1638c2ecf20Sopenharmony_ci		unsigned int resuming:1;    /* recognition while resume */
1648c2ecf20Sopenharmony_ci		unsigned int pgroup:1;	    /* pathgroup is set up */
1658c2ecf20Sopenharmony_ci		unsigned int mpath:1;	    /* multipathing is set up */
1668c2ecf20Sopenharmony_ci		unsigned int pgid_unknown:1;/* unknown pgid state */
1678c2ecf20Sopenharmony_ci		unsigned int initialized:1; /* set if initial reference held */
1688c2ecf20Sopenharmony_ci	} __attribute__((packed)) flags;
1698c2ecf20Sopenharmony_ci	unsigned long intparm;	/* user interruption parameter */
1708c2ecf20Sopenharmony_ci	struct qdio_irq *qdio_data;
1718c2ecf20Sopenharmony_ci	int async_kill_io_rc;
1728c2ecf20Sopenharmony_ci	struct work_struct todo_work;
1738c2ecf20Sopenharmony_ci	enum cdev_todo todo;
1748c2ecf20Sopenharmony_ci	wait_queue_head_t wait_q;
1758c2ecf20Sopenharmony_ci	struct timer_list timer;
1768c2ecf20Sopenharmony_ci	void *cmb;			/* measurement information */
1778c2ecf20Sopenharmony_ci	struct list_head cmb_list;	/* list of measured devices */
1788c2ecf20Sopenharmony_ci	u64 cmb_start_time;		/* clock value of cmb reset */
1798c2ecf20Sopenharmony_ci	void *cmb_wait;			/* deferred cmb enable/disable */
1808c2ecf20Sopenharmony_ci	struct gen_pool *dma_pool;
1818c2ecf20Sopenharmony_ci	struct ccw_device_dma_area *dma_area;
1828c2ecf20Sopenharmony_ci	enum interruption_class int_class;
1838c2ecf20Sopenharmony_ci};
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci#endif
186