xref: /linux/drivers/s390/cio/io_sch.h (revision d39d0ed196aa1685bb24771e92f78633c66ac9cb)
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 	struct {
157 		unsigned int fast:1;	/* post with "channel end" */
158 		unsigned int repall:1;	/* report every interrupt status */
159 		unsigned int pgroup:1;	/* do path grouping */
160 		unsigned int force:1;	/* allow forced online */
161 		unsigned int mpath:1;	/* do multipathing */
162 	} __attribute__ ((packed)) options;
163 	struct {
164 		unsigned int esid:1;	    /* Ext. SenseID supported by HW */
165 		unsigned int dosense:1;	    /* delayed SENSE required */
166 		unsigned int doverify:1;    /* delayed path verification */
167 		unsigned int donotify:1;    /* call notify function */
168 		unsigned int recog_done:1;  /* dev. recog. complete */
169 		unsigned int fake_irb:1;    /* deliver faked irb */
170 		unsigned int resuming:1;    /* recognition while resume */
171 		unsigned int pgroup:1;	    /* pathgroup is set up */
172 		unsigned int mpath:1;	    /* multipathing is set up */
173 		unsigned int initialized:1; /* set if initial reference held */
174 	} __attribute__((packed)) flags;
175 	unsigned long intparm;	/* user interruption parameter */
176 	struct qdio_irq *qdio_data;
177 	struct irb irb;		/* device status */
178 	struct senseid senseid;	/* SenseID info */
179 	struct pgid pgid[8];	/* path group IDs per chpid*/
180 	struct ccw1 iccws[2];	/* ccws for SNID/SID/SPGID commands */
181 	struct work_struct todo_work;
182 	enum cdev_todo todo;
183 	wait_queue_head_t wait_q;
184 	struct timer_list timer;
185 	void *cmb;			/* measurement information */
186 	struct list_head cmb_list;	/* list of measured devices */
187 	u64 cmb_start_time;		/* clock value of cmb reset */
188 	void *cmb_wait;			/* deferred cmb enable/disable */
189 };
190 
191 static inline int ssch(struct subchannel_id schid, union orb *addr)
192 {
193 	register struct subchannel_id reg1 asm("1") = schid;
194 	int ccode = -EIO;
195 
196 	asm volatile(
197 		"	ssch	0(%2)\n"
198 		"0:	ipm	%0\n"
199 		"	srl	%0,28\n"
200 		"1:\n"
201 		EX_TABLE(0b, 1b)
202 		: "+d" (ccode)
203 		: "d" (reg1), "a" (addr), "m" (*addr)
204 		: "cc", "memory");
205 	return ccode;
206 }
207 
208 static inline int rsch(struct subchannel_id schid)
209 {
210 	register struct subchannel_id reg1 asm("1") = schid;
211 	int ccode;
212 
213 	asm volatile(
214 		"	rsch\n"
215 		"	ipm	%0\n"
216 		"	srl	%0,28"
217 		: "=d" (ccode)
218 		: "d" (reg1)
219 		: "cc", "memory");
220 	return ccode;
221 }
222 
223 static inline int csch(struct subchannel_id schid)
224 {
225 	register struct subchannel_id reg1 asm("1") = schid;
226 	int ccode;
227 
228 	asm volatile(
229 		"	csch\n"
230 		"	ipm	%0\n"
231 		"	srl	%0,28"
232 		: "=d" (ccode)
233 		: "d" (reg1)
234 		: "cc");
235 	return ccode;
236 }
237 
238 static inline int hsch(struct subchannel_id schid)
239 {
240 	register struct subchannel_id reg1 asm("1") = schid;
241 	int ccode;
242 
243 	asm volatile(
244 		"	hsch\n"
245 		"	ipm	%0\n"
246 		"	srl	%0,28"
247 		: "=d" (ccode)
248 		: "d" (reg1)
249 		: "cc");
250 	return ccode;
251 }
252 
253 static inline int xsch(struct subchannel_id schid)
254 {
255 	register struct subchannel_id reg1 asm("1") = schid;
256 	int ccode;
257 
258 	asm volatile(
259 		"	.insn	rre,0xb2760000,%1,0\n"
260 		"	ipm	%0\n"
261 		"	srl	%0,28"
262 		: "=d" (ccode)
263 		: "d" (reg1)
264 		: "cc");
265 	return ccode;
266 }
267 
268 #endif
269