| 
									
										
										
										
											2008-01-26 14:10:43 +01:00
										 |  |  | #ifndef S390_IO_SCH_H
 | 
					
						
							|  |  |  | #define S390_IO_SCH_H
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-07 12:51:25 +01:00
										 |  |  | #include <linux/types.h>
 | 
					
						
							| 
									
										
										
										
											2008-07-14 09:59:05 +02:00
										 |  |  | #include <asm/schid.h>
 | 
					
						
							| 
									
										
										
										
											2009-12-07 12:51:25 +01:00
										 |  |  | #include <asm/ccwdev.h>
 | 
					
						
							| 
									
										
										
										
											2011-10-30 15:16:04 +01:00
										 |  |  | #include <asm/irq.h>
 | 
					
						
							| 
									
										
										
										
											2009-12-07 12:51:25 +01:00
										 |  |  | #include "css.h"
 | 
					
						
							| 
									
										
										
										
											2011-03-15 17:08:23 +01:00
										 |  |  | #include "orb.h"
 | 
					
						
							| 
									
										
										
										
											2008-07-14 09:58:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-26 14:10:43 +01:00
										 |  |  | struct io_subchannel_private { | 
					
						
							| 
									
										
										
										
											2008-07-14 09:58:51 +02:00
										 |  |  | 	union orb orb;		/* operation request block */ | 
					
						
							| 
									
										
										
										
											2008-01-26 14:10:43 +01:00
										 |  |  | 	struct ccw1 sense_ccw;	/* static ccw for sense command */ | 
					
						
							| 
									
										
										
										
											2011-03-15 17:08:26 +01:00
										 |  |  | 	struct ccw_device *cdev;/* pointer to the child ccw device */ | 
					
						
							| 
									
										
										
										
											2011-03-15 17:08:25 +01:00
										 |  |  | 	struct { | 
					
						
							|  |  |  | 		unsigned int suspend:1;	/* allow suspend */ | 
					
						
							|  |  |  | 		unsigned int prefetch:1;/* deny prefetch */ | 
					
						
							|  |  |  | 		unsigned int inter:1;	/* suppress intermediate interrupts */ | 
					
						
							|  |  |  | 	} __packed options; | 
					
						
							|  |  |  | } __aligned(8); | 
					
						
							| 
									
										
										
										
											2008-01-26 14:10:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-15 17:08:27 +01:00
										 |  |  | #define to_io_private(n) ((struct io_subchannel_private *) \
 | 
					
						
							|  |  |  | 			  dev_get_drvdata(&(n)->dev)) | 
					
						
							|  |  |  | #define set_io_private(n, p) (dev_set_drvdata(&(n)->dev, p))
 | 
					
						
							| 
									
										
										
										
											2011-03-15 17:08:26 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | static inline struct ccw_device *sch_get_cdev(struct subchannel *sch) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct io_subchannel_private *priv = to_io_private(sch); | 
					
						
							|  |  |  | 	return priv ? priv->cdev : NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline void sch_set_cdev(struct subchannel *sch, | 
					
						
							|  |  |  | 				struct ccw_device *cdev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct io_subchannel_private *priv = to_io_private(sch); | 
					
						
							|  |  |  | 	if (priv) | 
					
						
							|  |  |  | 		priv->cdev = cdev; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-01-26 14:10:43 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define MAX_CIWS 8
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-07 12:51:25 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Possible status values for a CCW request's I/O. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | enum io_status { | 
					
						
							|  |  |  | 	IO_DONE, | 
					
						
							|  |  |  | 	IO_RUNNING, | 
					
						
							|  |  |  | 	IO_STATUS_ERROR, | 
					
						
							|  |  |  | 	IO_PATH_ERROR, | 
					
						
							|  |  |  | 	IO_REJECTED, | 
					
						
							|  |  |  | 	IO_KILLED | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * ccw_request - Internal CCW request. | 
					
						
							|  |  |  |  * @cp: channel program to start | 
					
						
							|  |  |  |  * @timeout: maximum allowable time in jiffies between start I/O and interrupt | 
					
						
							|  |  |  |  * @maxretries: number of retries per I/O operation and path | 
					
						
							|  |  |  |  * @lpm: mask of paths to use | 
					
						
							|  |  |  |  * @check: optional callback that determines if results are final | 
					
						
							|  |  |  |  * @filter: optional callback to adjust request status based on IRB data | 
					
						
							|  |  |  |  * @callback: final callback | 
					
						
							|  |  |  |  * @data: user-defined pointer passed to all callbacks | 
					
						
							| 
									
										
										
										
											2010-08-09 18:12:53 +02:00
										 |  |  |  * @singlepath: if set, use only one path from @lpm per start I/O | 
					
						
							|  |  |  |  * @cancel: non-zero if request was cancelled | 
					
						
							|  |  |  |  * @done: non-zero if request was finished | 
					
						
							| 
									
										
										
										
											2009-12-07 12:51:25 +01:00
										 |  |  |  * @mask: current path mask | 
					
						
							|  |  |  |  * @retries: current number of retries | 
					
						
							|  |  |  |  * @drc: delayed return code | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | struct ccw_request { | 
					
						
							|  |  |  | 	struct ccw1 *cp; | 
					
						
							|  |  |  | 	unsigned long timeout; | 
					
						
							|  |  |  | 	u16 maxretries; | 
					
						
							|  |  |  | 	u8 lpm; | 
					
						
							|  |  |  | 	int (*check)(struct ccw_device *, void *); | 
					
						
							|  |  |  | 	enum io_status (*filter)(struct ccw_device *, void *, struct irb *, | 
					
						
							|  |  |  | 				 enum io_status); | 
					
						
							|  |  |  | 	void (*callback)(struct ccw_device *, void *, int); | 
					
						
							|  |  |  | 	void *data; | 
					
						
							| 
									
										
										
										
											2010-08-09 18:12:53 +02:00
										 |  |  | 	unsigned int singlepath:1; | 
					
						
							| 
									
										
										
										
											2009-12-07 12:51:25 +01:00
										 |  |  | 	/* These fields are used internally. */ | 
					
						
							| 
									
										
										
										
											2010-08-09 18:12:53 +02:00
										 |  |  | 	unsigned int cancel:1; | 
					
						
							|  |  |  | 	unsigned int done:1; | 
					
						
							| 
									
										
										
										
											2009-12-07 12:51:40 +01:00
										 |  |  | 	u16 mask; | 
					
						
							| 
									
										
										
										
											2009-12-07 12:51:25 +01:00
										 |  |  | 	u16 retries; | 
					
						
							|  |  |  | 	int drc; | 
					
						
							|  |  |  | } __attribute__((packed)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-26 14:10:43 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * sense-id response buffer layout | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | struct senseid { | 
					
						
							|  |  |  | 	/* common part */ | 
					
						
							|  |  |  | 	u8  reserved;	/* always 0x'FF' */ | 
					
						
							|  |  |  | 	u16 cu_type;	/* control unit type */ | 
					
						
							|  |  |  | 	u8  cu_model;	/* control unit model */ | 
					
						
							|  |  |  | 	u16 dev_type;	/* device type */ | 
					
						
							|  |  |  | 	u8  dev_model;	/* device model */ | 
					
						
							|  |  |  | 	u8  unused;	/* padding byte */ | 
					
						
							|  |  |  | 	/* extended part */ | 
					
						
							|  |  |  | 	struct ciw ciw[MAX_CIWS];	/* variable # of CIWs */ | 
					
						
							|  |  |  | }  __attribute__ ((packed, aligned(4))); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-07 12:51:19 +01:00
										 |  |  | enum cdev_todo { | 
					
						
							|  |  |  | 	CDEV_TODO_NOTHING, | 
					
						
							|  |  |  | 	CDEV_TODO_ENABLE_CMF, | 
					
						
							|  |  |  | 	CDEV_TODO_REBIND, | 
					
						
							|  |  |  | 	CDEV_TODO_REGISTER, | 
					
						
							|  |  |  | 	CDEV_TODO_UNREG, | 
					
						
							|  |  |  | 	CDEV_TODO_UNREG_EVAL, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-01 13:32:21 +01:00
										 |  |  | #define FAKE_CMD_IRB	1
 | 
					
						
							|  |  |  | #define FAKE_TM_IRB	2
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-26 14:10:43 +01:00
										 |  |  | struct ccw_device_private { | 
					
						
							|  |  |  | 	struct ccw_device *cdev; | 
					
						
							|  |  |  | 	struct subchannel *sch; | 
					
						
							|  |  |  | 	int state;		/* device state */ | 
					
						
							|  |  |  | 	atomic_t onoff; | 
					
						
							|  |  |  | 	struct ccw_dev_id dev_id;	/* device id */ | 
					
						
							|  |  |  | 	struct subchannel_id schid;	/* subchannel number */ | 
					
						
							| 
									
										
										
										
											2009-12-07 12:51:25 +01:00
										 |  |  | 	struct ccw_request req;		/* internal I/O request */ | 
					
						
							| 
									
										
										
										
											2009-12-07 12:51:27 +01:00
										 |  |  | 	int iretry; | 
					
						
							| 
									
										
										
										
											2010-10-25 16:10:34 +02:00
										 |  |  | 	u8 pgid_valid_mask;	/* mask of valid PGIDs */ | 
					
						
							|  |  |  | 	u8 pgid_todo_mask;	/* mask of PGIDs to be adjusted */ | 
					
						
							|  |  |  | 	u8 pgid_reset_mask;	/* mask of PGIDs which were reset */ | 
					
						
							| 
									
										
										
										
											2013-01-28 19:29:43 +01:00
										 |  |  | 	u8 path_noirq_mask;	/* mask of paths for which no irq was
 | 
					
						
							|  |  |  | 				   received */ | 
					
						
							|  |  |  | 	u8 path_notoper_mask;	/* mask of paths which were found
 | 
					
						
							|  |  |  | 				   not operable */ | 
					
						
							| 
									
										
										
										
											2010-10-25 16:10:34 +02:00
										 |  |  | 	u8 path_gone_mask;	/* mask of paths, that became unavailable */ | 
					
						
							|  |  |  | 	u8 path_new_mask;	/* mask of paths, that became available */ | 
					
						
							| 
									
										
										
										
											2008-01-26 14:10:43 +01:00
										 |  |  | 	struct { | 
					
						
							|  |  |  | 		unsigned int fast:1;	/* post with "channel end" */ | 
					
						
							|  |  |  | 		unsigned int repall:1;	/* report every interrupt status */ | 
					
						
							|  |  |  | 		unsigned int pgroup:1;	/* do path grouping */ | 
					
						
							|  |  |  | 		unsigned int force:1;	/* allow forced online */ | 
					
						
							| 
									
										
										
										
											2009-12-07 12:51:30 +01:00
										 |  |  | 		unsigned int mpath:1;	/* do multipathing */ | 
					
						
							| 
									
										
										
										
											2008-01-26 14:10:43 +01:00
										 |  |  | 	} __attribute__ ((packed)) options; | 
					
						
							|  |  |  | 	struct { | 
					
						
							|  |  |  | 		unsigned int esid:1;	    /* Ext. SenseID supported by HW */ | 
					
						
							|  |  |  | 		unsigned int dosense:1;	    /* delayed SENSE required */ | 
					
						
							|  |  |  | 		unsigned int doverify:1;    /* delayed path verification */ | 
					
						
							|  |  |  | 		unsigned int donotify:1;    /* call notify function */ | 
					
						
							|  |  |  | 		unsigned int recog_done:1;  /* dev. recog. complete */ | 
					
						
							| 
									
										
										
										
											2011-12-01 13:32:21 +01:00
										 |  |  | 		unsigned int fake_irb:2;    /* deliver faked irb */ | 
					
						
							| 
									
										
										
										
											2009-06-16 10:30:20 +02:00
										 |  |  | 		unsigned int resuming:1;    /* recognition while resume */ | 
					
						
							| 
									
										
										
										
											2009-12-07 12:51:30 +01:00
										 |  |  | 		unsigned int pgroup:1;	    /* pathgroup is set up */ | 
					
						
							|  |  |  | 		unsigned int mpath:1;	    /* multipathing is set up */ | 
					
						
							| 
									
										
										
										
											2013-01-28 19:29:43 +01:00
										 |  |  | 		unsigned int pgid_unknown:1;/* unknown pgid state */ | 
					
						
							| 
									
										
										
										
											2009-12-07 12:51:34 +01:00
										 |  |  | 		unsigned int initialized:1; /* set if initial reference held */ | 
					
						
							| 
									
										
										
										
											2008-01-26 14:10:43 +01:00
										 |  |  | 	} __attribute__((packed)) flags; | 
					
						
							|  |  |  | 	unsigned long intparm;	/* user interruption parameter */ | 
					
						
							|  |  |  | 	struct qdio_irq *qdio_data; | 
					
						
							|  |  |  | 	struct irb irb;		/* device status */ | 
					
						
							|  |  |  | 	struct senseid senseid;	/* SenseID info */ | 
					
						
							|  |  |  | 	struct pgid pgid[8];	/* path group IDs per chpid*/ | 
					
						
							|  |  |  | 	struct ccw1 iccws[2];	/* ccws for SNID/SID/SPGID commands */ | 
					
						
							| 
									
										
										
										
											2009-12-07 12:51:19 +01:00
										 |  |  | 	struct work_struct todo_work; | 
					
						
							|  |  |  | 	enum cdev_todo todo; | 
					
						
							| 
									
										
										
										
											2008-01-26 14:10:43 +01:00
										 |  |  | 	wait_queue_head_t wait_q; | 
					
						
							|  |  |  | 	struct timer_list timer; | 
					
						
							|  |  |  | 	void *cmb;			/* measurement information */ | 
					
						
							|  |  |  | 	struct list_head cmb_list;	/* list of measured devices */ | 
					
						
							|  |  |  | 	u64 cmb_start_time;		/* clock value of cmb reset */ | 
					
						
							|  |  |  | 	void *cmb_wait;			/* deferred cmb enable/disable */ | 
					
						
							| 
									
										
										
										
											2011-10-30 15:16:04 +01:00
										 |  |  | 	enum interruption_class int_class; | 
					
						
							| 
									
										
										
										
											2008-01-26 14:10:43 +01:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline int rsch(struct subchannel_id schid) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	register struct subchannel_id reg1 asm("1") = schid; | 
					
						
							|  |  |  | 	int ccode; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	asm volatile( | 
					
						
							|  |  |  | 		"	rsch\n" | 
					
						
							|  |  |  | 		"	ipm	%0\n" | 
					
						
							|  |  |  | 		"	srl	%0,28" | 
					
						
							| 
									
										
										
										
											2008-10-10 21:33:15 +02:00
										 |  |  | 		: "=d" (ccode) | 
					
						
							|  |  |  | 		: "d" (reg1) | 
					
						
							|  |  |  | 		: "cc", "memory"); | 
					
						
							| 
									
										
										
										
											2008-01-26 14:10:43 +01:00
										 |  |  | 	return ccode; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline int hsch(struct subchannel_id schid) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	register struct subchannel_id reg1 asm("1") = schid; | 
					
						
							|  |  |  | 	int ccode; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	asm volatile( | 
					
						
							|  |  |  | 		"	hsch\n" | 
					
						
							|  |  |  | 		"	ipm	%0\n" | 
					
						
							|  |  |  | 		"	srl	%0,28" | 
					
						
							| 
									
										
										
										
											2008-10-10 21:33:15 +02:00
										 |  |  | 		: "=d" (ccode) | 
					
						
							|  |  |  | 		: "d" (reg1) | 
					
						
							|  |  |  | 		: "cc"); | 
					
						
							| 
									
										
										
										
											2008-01-26 14:10:43 +01:00
										 |  |  | 	return ccode; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline int xsch(struct subchannel_id schid) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	register struct subchannel_id reg1 asm("1") = schid; | 
					
						
							|  |  |  | 	int ccode; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	asm volatile( | 
					
						
							|  |  |  | 		"	.insn	rre,0xb2760000,%1,0\n" | 
					
						
							|  |  |  | 		"	ipm	%0\n" | 
					
						
							|  |  |  | 		"	srl	%0,28" | 
					
						
							| 
									
										
										
										
											2008-10-10 21:33:15 +02:00
										 |  |  | 		: "=d" (ccode) | 
					
						
							|  |  |  | 		: "d" (reg1) | 
					
						
							|  |  |  | 		: "cc"); | 
					
						
							| 
									
										
										
										
											2008-01-26 14:10:43 +01:00
										 |  |  | 	return ccode; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 |