xref: /openbmc/linux/drivers/s390/cio/io_sch.h (revision df2634f43f5106947f3735a0b61a6527a4b278cd)
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  * @singlepath: if set, use only one path from @lpm per start I/O
96  * @cancel: non-zero if request was cancelled
97  * @done: non-zero if request was finished
98  * @mask: current path mask
99  * @retries: current number of retries
100  * @drc: delayed return code
101  */
102 struct ccw_request {
103 	struct ccw1 *cp;
104 	unsigned long timeout;
105 	u16 maxretries;
106 	u8 lpm;
107 	int (*check)(struct ccw_device *, void *);
108 	enum io_status (*filter)(struct ccw_device *, void *, struct irb *,
109 				 enum io_status);
110 	void (*callback)(struct ccw_device *, void *, int);
111 	void *data;
112 	unsigned int singlepath:1;
113 	/* These fields are used internally. */
114 	unsigned int cancel:1;
115 	unsigned int done:1;
116 	u16 mask;
117 	u16 retries;
118 	int drc;
119 } __attribute__((packed));
120 
121 /*
122  * sense-id response buffer layout
123  */
124 struct senseid {
125 	/* common part */
126 	u8  reserved;	/* always 0x'FF' */
127 	u16 cu_type;	/* control unit type */
128 	u8  cu_model;	/* control unit model */
129 	u16 dev_type;	/* device type */
130 	u8  dev_model;	/* device model */
131 	u8  unused;	/* padding byte */
132 	/* extended part */
133 	struct ciw ciw[MAX_CIWS];	/* variable # of CIWs */
134 }  __attribute__ ((packed, aligned(4)));
135 
136 enum cdev_todo {
137 	CDEV_TODO_NOTHING,
138 	CDEV_TODO_ENABLE_CMF,
139 	CDEV_TODO_REBIND,
140 	CDEV_TODO_REGISTER,
141 	CDEV_TODO_UNREG,
142 	CDEV_TODO_UNREG_EVAL,
143 };
144 
145 struct ccw_device_private {
146 	struct ccw_device *cdev;
147 	struct subchannel *sch;
148 	int state;		/* device state */
149 	atomic_t onoff;
150 	struct ccw_dev_id dev_id;	/* device id */
151 	struct subchannel_id schid;	/* subchannel number */
152 	struct ccw_request req;		/* internal I/O request */
153 	int iretry;
154 	u8 pgid_valid_mask;	/* mask of valid PGIDs */
155 	u8 pgid_todo_mask;	/* mask of PGIDs to be adjusted */
156 	u8 pgid_reset_mask;	/* mask of PGIDs which were reset */
157 	u8 path_gone_mask;	/* mask of paths, that became unavailable */
158 	u8 path_new_mask;	/* mask of paths, that became available */
159 	struct {
160 		unsigned int fast:1;	/* post with "channel end" */
161 		unsigned int repall:1;	/* report every interrupt status */
162 		unsigned int pgroup:1;	/* do path grouping */
163 		unsigned int force:1;	/* allow forced online */
164 		unsigned int mpath:1;	/* do multipathing */
165 	} __attribute__ ((packed)) options;
166 	struct {
167 		unsigned int esid:1;	    /* Ext. SenseID supported by HW */
168 		unsigned int dosense:1;	    /* delayed SENSE required */
169 		unsigned int doverify:1;    /* delayed path verification */
170 		unsigned int donotify:1;    /* call notify function */
171 		unsigned int recog_done:1;  /* dev. recog. complete */
172 		unsigned int fake_irb:1;    /* deliver faked irb */
173 		unsigned int resuming:1;    /* recognition while resume */
174 		unsigned int pgroup:1;	    /* pathgroup is set up */
175 		unsigned int mpath:1;	    /* multipathing is set up */
176 		unsigned int initialized:1; /* set if initial reference held */
177 	} __attribute__((packed)) flags;
178 	unsigned long intparm;	/* user interruption parameter */
179 	struct qdio_irq *qdio_data;
180 	struct irb irb;		/* device status */
181 	struct senseid senseid;	/* SenseID info */
182 	struct pgid pgid[8];	/* path group IDs per chpid*/
183 	struct ccw1 iccws[2];	/* ccws for SNID/SID/SPGID commands */
184 	struct work_struct todo_work;
185 	enum cdev_todo todo;
186 	wait_queue_head_t wait_q;
187 	struct timer_list timer;
188 	void *cmb;			/* measurement information */
189 	struct list_head cmb_list;	/* list of measured devices */
190 	u64 cmb_start_time;		/* clock value of cmb reset */
191 	void *cmb_wait;			/* deferred cmb enable/disable */
192 };
193 
194 static inline int ssch(struct subchannel_id schid, union orb *addr)
195 {
196 	register struct subchannel_id reg1 asm("1") = schid;
197 	int ccode = -EIO;
198 
199 	asm volatile(
200 		"	ssch	0(%2)\n"
201 		"0:	ipm	%0\n"
202 		"	srl	%0,28\n"
203 		"1:\n"
204 		EX_TABLE(0b, 1b)
205 		: "+d" (ccode)
206 		: "d" (reg1), "a" (addr), "m" (*addr)
207 		: "cc", "memory");
208 	return ccode;
209 }
210 
211 static inline int rsch(struct subchannel_id schid)
212 {
213 	register struct subchannel_id reg1 asm("1") = schid;
214 	int ccode;
215 
216 	asm volatile(
217 		"	rsch\n"
218 		"	ipm	%0\n"
219 		"	srl	%0,28"
220 		: "=d" (ccode)
221 		: "d" (reg1)
222 		: "cc", "memory");
223 	return ccode;
224 }
225 
226 static inline int csch(struct subchannel_id schid)
227 {
228 	register struct subchannel_id reg1 asm("1") = schid;
229 	int ccode;
230 
231 	asm volatile(
232 		"	csch\n"
233 		"	ipm	%0\n"
234 		"	srl	%0,28"
235 		: "=d" (ccode)
236 		: "d" (reg1)
237 		: "cc");
238 	return ccode;
239 }
240 
241 static inline int hsch(struct subchannel_id schid)
242 {
243 	register struct subchannel_id reg1 asm("1") = schid;
244 	int ccode;
245 
246 	asm volatile(
247 		"	hsch\n"
248 		"	ipm	%0\n"
249 		"	srl	%0,28"
250 		: "=d" (ccode)
251 		: "d" (reg1)
252 		: "cc");
253 	return ccode;
254 }
255 
256 static inline int xsch(struct subchannel_id schid)
257 {
258 	register struct subchannel_id reg1 asm("1") = schid;
259 	int ccode;
260 
261 	asm volatile(
262 		"	.insn	rre,0xb2760000,%1,0\n"
263 		"	ipm	%0\n"
264 		"	srl	%0,28"
265 		: "=d" (ccode)
266 		: "d" (reg1)
267 		: "cc");
268 	return ccode;
269 }
270 
271 #endif
272