xref: /openbmc/linux/drivers/s390/cio/io_sch.h (revision 7dd65feb)
1 #ifndef S390_IO_SCH_H
2 #define S390_IO_SCH_H
3 
4 #include <linux/types.h>
5 #include <asm/schid.h>
6 #include <asm/ccwdev.h>
7 #include "css.h"
8 
9 /*
10  * command-mode operation request block
11  */
12 struct cmd_orb {
13 	u32 intparm;	/* interruption parameter */
14 	u32 key  : 4;	/* flags, like key, suspend control, etc. */
15 	u32 spnd : 1;	/* suspend control */
16 	u32 res1 : 1;	/* reserved */
17 	u32 mod  : 1;	/* modification control */
18 	u32 sync : 1;	/* synchronize control */
19 	u32 fmt  : 1;	/* format control */
20 	u32 pfch : 1;	/* prefetch control */
21 	u32 isic : 1;	/* initial-status-interruption control */
22 	u32 alcc : 1;	/* address-limit-checking control */
23 	u32 ssic : 1;	/* suppress-suspended-interr. control */
24 	u32 res2 : 1;	/* reserved */
25 	u32 c64  : 1;	/* IDAW/QDIO 64 bit control  */
26 	u32 i2k  : 1;	/* IDAW 2/4kB block size control */
27 	u32 lpm  : 8;	/* logical path mask */
28 	u32 ils  : 1;	/* incorrect length */
29 	u32 zero : 6;	/* reserved zeros */
30 	u32 orbx : 1;	/* ORB extension control */
31 	u32 cpa;	/* channel program address */
32 }  __attribute__ ((packed, aligned(4)));
33 
34 /*
35  * transport-mode operation request block
36  */
37 struct tm_orb {
38 	u32 intparm;
39 	u32 key:4;
40 	u32 :9;
41 	u32 b:1;
42 	u32 :2;
43 	u32 lpm:8;
44 	u32 :7;
45 	u32 x:1;
46 	u32 tcw;
47 	u32 prio:8;
48 	u32 :8;
49 	u32 rsvpgm:8;
50 	u32 :8;
51 	u32 :32;
52 	u32 :32;
53 	u32 :32;
54 	u32 :32;
55 }  __attribute__ ((packed, aligned(4)));
56 
57 union orb {
58 	struct cmd_orb cmd;
59 	struct tm_orb tm;
60 }  __attribute__ ((packed, aligned(4)));
61 
62 struct io_subchannel_private {
63 	union orb orb;		/* operation request block */
64 	struct ccw1 sense_ccw;	/* static ccw for sense command */
65 } __attribute__ ((aligned(8)));
66 
67 #define to_io_private(n) ((struct io_subchannel_private *)n->private)
68 #define sch_get_cdev(n) (dev_get_drvdata(&n->dev))
69 #define sch_set_cdev(n, c) (dev_set_drvdata(&n->dev, c))
70 
71 #define MAX_CIWS 8
72 
73 /*
74  * Possible status values for a CCW request's I/O.
75  */
76 enum io_status {
77 	IO_DONE,
78 	IO_RUNNING,
79 	IO_STATUS_ERROR,
80 	IO_PATH_ERROR,
81 	IO_REJECTED,
82 	IO_KILLED
83 };
84 
85 /**
86  * ccw_request - Internal CCW request.
87  * @cp: channel program to start
88  * @timeout: maximum allowable time in jiffies between start I/O and interrupt
89  * @maxretries: number of retries per I/O operation and path
90  * @lpm: mask of paths to use
91  * @check: optional callback that determines if results are final
92  * @filter: optional callback to adjust request status based on IRB data
93  * @callback: final callback
94  * @data: user-defined pointer passed to all callbacks
95  * @mask: current path mask
96  * @retries: current number of retries
97  * @drc: delayed return code
98  * @cancel: non-zero if request was cancelled
99  * @done: non-zero if request was finished
100  */
101 struct ccw_request {
102 	struct ccw1 *cp;
103 	unsigned long timeout;
104 	u16 maxretries;
105 	u8 lpm;
106 	int (*check)(struct ccw_device *, void *);
107 	enum io_status (*filter)(struct ccw_device *, void *, struct irb *,
108 				 enum io_status);
109 	void (*callback)(struct ccw_device *, void *, int);
110 	void *data;
111 	/* These fields are used internally. */
112 	u16 mask;
113 	u16 retries;
114 	int drc;
115 	int cancel:1;
116 	int done:1;
117 } __attribute__((packed));
118 
119 /*
120  * sense-id response buffer layout
121  */
122 struct senseid {
123 	/* common part */
124 	u8  reserved;	/* always 0x'FF' */
125 	u16 cu_type;	/* control unit type */
126 	u8  cu_model;	/* control unit model */
127 	u16 dev_type;	/* device type */
128 	u8  dev_model;	/* device model */
129 	u8  unused;	/* padding byte */
130 	/* extended part */
131 	struct ciw ciw[MAX_CIWS];	/* variable # of CIWs */
132 }  __attribute__ ((packed, aligned(4)));
133 
134 enum cdev_todo {
135 	CDEV_TODO_NOTHING,
136 	CDEV_TODO_ENABLE_CMF,
137 	CDEV_TODO_REBIND,
138 	CDEV_TODO_REGISTER,
139 	CDEV_TODO_UNREG,
140 	CDEV_TODO_UNREG_EVAL,
141 };
142 
143 struct ccw_device_private {
144 	struct ccw_device *cdev;
145 	struct subchannel *sch;
146 	int state;		/* device state */
147 	atomic_t onoff;
148 	struct ccw_dev_id dev_id;	/* device id */
149 	struct subchannel_id schid;	/* subchannel number */
150 	struct ccw_request req;		/* internal I/O request */
151 	int iretry;
152 	u8 pgid_valid_mask;		/* mask of valid PGIDs */
153 	u8 pgid_todo_mask;		/* mask of PGIDs to be adjusted */
154 	struct {
155 		unsigned int fast:1;	/* post with "channel end" */
156 		unsigned int repall:1;	/* report every interrupt status */
157 		unsigned int pgroup:1;	/* do path grouping */
158 		unsigned int force:1;	/* allow forced online */
159 		unsigned int mpath:1;	/* do multipathing */
160 	} __attribute__ ((packed)) options;
161 	struct {
162 		unsigned int esid:1;	    /* Ext. SenseID supported by HW */
163 		unsigned int dosense:1;	    /* delayed SENSE required */
164 		unsigned int doverify:1;    /* delayed path verification */
165 		unsigned int donotify:1;    /* call notify function */
166 		unsigned int recog_done:1;  /* dev. recog. complete */
167 		unsigned int fake_irb:1;    /* deliver faked irb */
168 		unsigned int resuming:1;    /* recognition while resume */
169 		unsigned int pgroup:1;	    /* pathgroup is set up */
170 		unsigned int mpath:1;	    /* multipathing is set up */
171 		unsigned int initialized:1; /* set if initial reference held */
172 	} __attribute__((packed)) flags;
173 	unsigned long intparm;	/* user interruption parameter */
174 	struct qdio_irq *qdio_data;
175 	struct irb irb;		/* device status */
176 	struct senseid senseid;	/* SenseID info */
177 	struct pgid pgid[8];	/* path group IDs per chpid*/
178 	struct ccw1 iccws[2];	/* ccws for SNID/SID/SPGID commands */
179 	struct work_struct todo_work;
180 	enum cdev_todo todo;
181 	wait_queue_head_t wait_q;
182 	struct timer_list timer;
183 	void *cmb;			/* measurement information */
184 	struct list_head cmb_list;	/* list of measured devices */
185 	u64 cmb_start_time;		/* clock value of cmb reset */
186 	void *cmb_wait;			/* deferred cmb enable/disable */
187 };
188 
189 static inline int ssch(struct subchannel_id schid, union orb *addr)
190 {
191 	register struct subchannel_id reg1 asm("1") = schid;
192 	int ccode = -EIO;
193 
194 	asm volatile(
195 		"	ssch	0(%2)\n"
196 		"0:	ipm	%0\n"
197 		"	srl	%0,28\n"
198 		"1:\n"
199 		EX_TABLE(0b, 1b)
200 		: "+d" (ccode)
201 		: "d" (reg1), "a" (addr), "m" (*addr)
202 		: "cc", "memory");
203 	return ccode;
204 }
205 
206 static inline int rsch(struct subchannel_id schid)
207 {
208 	register struct subchannel_id reg1 asm("1") = schid;
209 	int ccode;
210 
211 	asm volatile(
212 		"	rsch\n"
213 		"	ipm	%0\n"
214 		"	srl	%0,28"
215 		: "=d" (ccode)
216 		: "d" (reg1)
217 		: "cc", "memory");
218 	return ccode;
219 }
220 
221 static inline int csch(struct subchannel_id schid)
222 {
223 	register struct subchannel_id reg1 asm("1") = schid;
224 	int ccode;
225 
226 	asm volatile(
227 		"	csch\n"
228 		"	ipm	%0\n"
229 		"	srl	%0,28"
230 		: "=d" (ccode)
231 		: "d" (reg1)
232 		: "cc");
233 	return ccode;
234 }
235 
236 static inline int hsch(struct subchannel_id schid)
237 {
238 	register struct subchannel_id reg1 asm("1") = schid;
239 	int ccode;
240 
241 	asm volatile(
242 		"	hsch\n"
243 		"	ipm	%0\n"
244 		"	srl	%0,28"
245 		: "=d" (ccode)
246 		: "d" (reg1)
247 		: "cc");
248 	return ccode;
249 }
250 
251 static inline int xsch(struct subchannel_id schid)
252 {
253 	register struct subchannel_id reg1 asm("1") = schid;
254 	int ccode;
255 
256 	asm volatile(
257 		"	.insn	rre,0xb2760000,%1,0\n"
258 		"	ipm	%0\n"
259 		"	srl	%0,28"
260 		: "=d" (ccode)
261 		: "d" (reg1)
262 		: "cc");
263 	return ccode;
264 }
265 
266 #endif
267