xref: /OK3568_Linux_fs/kernel/arch/s390/include/asm/ccwdev.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright IBM Corp. 2002, 2009
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Author(s): Arnd Bergmann <arndb@de.ibm.com>
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Interface for CCW device drivers
8*4882a593Smuzhiyun  */
9*4882a593Smuzhiyun #ifndef _S390_CCWDEV_H_
10*4882a593Smuzhiyun #define _S390_CCWDEV_H_
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun #include <linux/device.h>
13*4882a593Smuzhiyun #include <linux/mod_devicetable.h>
14*4882a593Smuzhiyun #include <asm/chsc.h>
15*4882a593Smuzhiyun #include <asm/fcx.h>
16*4882a593Smuzhiyun #include <asm/irq.h>
17*4882a593Smuzhiyun #include <asm/schid.h>
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun /* structs from asm/cio.h */
20*4882a593Smuzhiyun struct irb;
21*4882a593Smuzhiyun struct ccw1;
22*4882a593Smuzhiyun struct ccw_dev_id;
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun /* simplified initializers for struct ccw_device:
25*4882a593Smuzhiyun  * CCW_DEVICE and CCW_DEVICE_DEVTYPE initialize one
26*4882a593Smuzhiyun  * entry in your MODULE_DEVICE_TABLE and set the match_flag correctly */
27*4882a593Smuzhiyun #define CCW_DEVICE(cu, cum) 						\
28*4882a593Smuzhiyun 	.cu_type=(cu), .cu_model=(cum),					\
29*4882a593Smuzhiyun 	.match_flags=(CCW_DEVICE_ID_MATCH_CU_TYPE			\
30*4882a593Smuzhiyun 		   | (cum ? CCW_DEVICE_ID_MATCH_CU_MODEL : 0))
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun #define CCW_DEVICE_DEVTYPE(cu, cum, dev, devm)				\
33*4882a593Smuzhiyun 	.cu_type=(cu), .cu_model=(cum), .dev_type=(dev), .dev_model=(devm),\
34*4882a593Smuzhiyun 	.match_flags=CCW_DEVICE_ID_MATCH_CU_TYPE			\
35*4882a593Smuzhiyun 		   | ((cum) ? CCW_DEVICE_ID_MATCH_CU_MODEL : 0) 	\
36*4882a593Smuzhiyun 		   | CCW_DEVICE_ID_MATCH_DEVICE_TYPE			\
37*4882a593Smuzhiyun 		   | ((devm) ? CCW_DEVICE_ID_MATCH_DEVICE_MODEL : 0)
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun /* scan through an array of device ids and return the first
40*4882a593Smuzhiyun  * entry that matches the device.
41*4882a593Smuzhiyun  *
42*4882a593Smuzhiyun  * the array must end with an entry containing zero match_flags
43*4882a593Smuzhiyun  */
44*4882a593Smuzhiyun static inline const struct ccw_device_id *
ccw_device_id_match(const struct ccw_device_id * array,const struct ccw_device_id * match)45*4882a593Smuzhiyun ccw_device_id_match(const struct ccw_device_id *array,
46*4882a593Smuzhiyun 			const struct ccw_device_id *match)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun 	const struct ccw_device_id *id = array;
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 	for (id = array; id->match_flags; id++) {
51*4882a593Smuzhiyun 		if ((id->match_flags & CCW_DEVICE_ID_MATCH_CU_TYPE)
52*4882a593Smuzhiyun 		    && (id->cu_type != match->cu_type))
53*4882a593Smuzhiyun 			continue;
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 		if ((id->match_flags & CCW_DEVICE_ID_MATCH_CU_MODEL)
56*4882a593Smuzhiyun 		    && (id->cu_model != match->cu_model))
57*4882a593Smuzhiyun 			continue;
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun 		if ((id->match_flags & CCW_DEVICE_ID_MATCH_DEVICE_TYPE)
60*4882a593Smuzhiyun 		    && (id->dev_type != match->dev_type))
61*4882a593Smuzhiyun 			continue;
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 		if ((id->match_flags & CCW_DEVICE_ID_MATCH_DEVICE_MODEL)
64*4882a593Smuzhiyun 		    && (id->dev_model != match->dev_model))
65*4882a593Smuzhiyun 			continue;
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 		return id;
68*4882a593Smuzhiyun 	}
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	return NULL;
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun /**
74*4882a593Smuzhiyun  * struct ccw_device - channel attached device
75*4882a593Smuzhiyun  * @ccwlock: pointer to device lock
76*4882a593Smuzhiyun  * @id: id of this device
77*4882a593Smuzhiyun  * @drv: ccw driver for this device
78*4882a593Smuzhiyun  * @dev: embedded device structure
79*4882a593Smuzhiyun  * @online: online status of device
80*4882a593Smuzhiyun  * @handler: interrupt handler
81*4882a593Smuzhiyun  *
82*4882a593Smuzhiyun  * @handler is a member of the device rather than the driver since a driver
83*4882a593Smuzhiyun  * can have different interrupt handlers for different ccw devices
84*4882a593Smuzhiyun  * (multi-subchannel drivers).
85*4882a593Smuzhiyun  */
86*4882a593Smuzhiyun struct ccw_device {
87*4882a593Smuzhiyun 	spinlock_t *ccwlock;
88*4882a593Smuzhiyun /* private: */
89*4882a593Smuzhiyun 	struct ccw_device_private *private;	/* cio private information */
90*4882a593Smuzhiyun /* public: */
91*4882a593Smuzhiyun 	struct ccw_device_id id;
92*4882a593Smuzhiyun 	struct ccw_driver *drv;
93*4882a593Smuzhiyun 	struct device dev;
94*4882a593Smuzhiyun 	int online;
95*4882a593Smuzhiyun 	void (*handler) (struct ccw_device *, unsigned long, struct irb *);
96*4882a593Smuzhiyun };
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun /*
99*4882a593Smuzhiyun  * Possible events used by the path_event notifier.
100*4882a593Smuzhiyun  */
101*4882a593Smuzhiyun #define PE_NONE				0x0
102*4882a593Smuzhiyun #define PE_PATH_GONE			0x1 /* A path is no longer available. */
103*4882a593Smuzhiyun #define PE_PATH_AVAILABLE		0x2 /* A path has become available and
104*4882a593Smuzhiyun 					       was successfully verified. */
105*4882a593Smuzhiyun #define PE_PATHGROUP_ESTABLISHED	0x4 /* A pathgroup was reset and had
106*4882a593Smuzhiyun 					       to be established again. */
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun /*
109*4882a593Smuzhiyun  * Possible CIO actions triggered by the unit check handler.
110*4882a593Smuzhiyun  */
111*4882a593Smuzhiyun enum uc_todo {
112*4882a593Smuzhiyun 	UC_TODO_RETRY,
113*4882a593Smuzhiyun 	UC_TODO_RETRY_ON_NEW_PATH,
114*4882a593Smuzhiyun 	UC_TODO_STOP
115*4882a593Smuzhiyun };
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun /**
118*4882a593Smuzhiyun  * struct ccw driver - device driver for channel attached devices
119*4882a593Smuzhiyun  * @ids: ids supported by this driver
120*4882a593Smuzhiyun  * @probe: function called on probe
121*4882a593Smuzhiyun  * @remove: function called on remove
122*4882a593Smuzhiyun  * @set_online: called when setting device online
123*4882a593Smuzhiyun  * @set_offline: called when setting device offline
124*4882a593Smuzhiyun  * @notify: notify driver of device state changes
125*4882a593Smuzhiyun  * @path_event: notify driver of channel path events
126*4882a593Smuzhiyun  * @shutdown: called at device shutdown
127*4882a593Smuzhiyun  * @prepare: prepare for pm state transition
128*4882a593Smuzhiyun  * @complete: undo work done in @prepare
129*4882a593Smuzhiyun  * @freeze: callback for freezing during hibernation snapshotting
130*4882a593Smuzhiyun  * @thaw: undo work done in @freeze
131*4882a593Smuzhiyun  * @restore: callback for restoring after hibernation
132*4882a593Smuzhiyun  * @uc_handler: callback for unit check handler
133*4882a593Smuzhiyun  * @driver: embedded device driver structure
134*4882a593Smuzhiyun  * @int_class: interruption class to use for accounting interrupts
135*4882a593Smuzhiyun  */
136*4882a593Smuzhiyun struct ccw_driver {
137*4882a593Smuzhiyun 	struct ccw_device_id *ids;
138*4882a593Smuzhiyun 	int (*probe) (struct ccw_device *);
139*4882a593Smuzhiyun 	void (*remove) (struct ccw_device *);
140*4882a593Smuzhiyun 	int (*set_online) (struct ccw_device *);
141*4882a593Smuzhiyun 	int (*set_offline) (struct ccw_device *);
142*4882a593Smuzhiyun 	int (*notify) (struct ccw_device *, int);
143*4882a593Smuzhiyun 	void (*path_event) (struct ccw_device *, int *);
144*4882a593Smuzhiyun 	void (*shutdown) (struct ccw_device *);
145*4882a593Smuzhiyun 	int (*prepare) (struct ccw_device *);
146*4882a593Smuzhiyun 	void (*complete) (struct ccw_device *);
147*4882a593Smuzhiyun 	int (*freeze)(struct ccw_device *);
148*4882a593Smuzhiyun 	int (*thaw) (struct ccw_device *);
149*4882a593Smuzhiyun 	int (*restore)(struct ccw_device *);
150*4882a593Smuzhiyun 	enum uc_todo (*uc_handler) (struct ccw_device *, struct irb *);
151*4882a593Smuzhiyun 	struct device_driver driver;
152*4882a593Smuzhiyun 	enum interruption_class int_class;
153*4882a593Smuzhiyun };
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun extern struct ccw_device *get_ccwdev_by_busid(struct ccw_driver *cdrv,
156*4882a593Smuzhiyun 					      const char *bus_id);
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun /* devices drivers call these during module load and unload.
159*4882a593Smuzhiyun  * When a driver is registered, its probe method is called
160*4882a593Smuzhiyun  * when new devices for its type pop up */
161*4882a593Smuzhiyun extern int  ccw_driver_register   (struct ccw_driver *driver);
162*4882a593Smuzhiyun extern void ccw_driver_unregister (struct ccw_driver *driver);
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun struct ccw1;
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun extern int ccw_device_set_options_mask(struct ccw_device *, unsigned long);
167*4882a593Smuzhiyun extern int ccw_device_set_options(struct ccw_device *, unsigned long);
168*4882a593Smuzhiyun extern void ccw_device_clear_options(struct ccw_device *, unsigned long);
169*4882a593Smuzhiyun int ccw_device_is_pathgroup(struct ccw_device *cdev);
170*4882a593Smuzhiyun int ccw_device_is_multipath(struct ccw_device *cdev);
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun /* Allow for i/o completion notification after primary interrupt status. */
173*4882a593Smuzhiyun #define CCWDEV_EARLY_NOTIFICATION	0x0001
174*4882a593Smuzhiyun /* Report all interrupt conditions. */
175*4882a593Smuzhiyun #define CCWDEV_REPORT_ALL	 	0x0002
176*4882a593Smuzhiyun /* Try to perform path grouping. */
177*4882a593Smuzhiyun #define CCWDEV_DO_PATHGROUP             0x0004
178*4882a593Smuzhiyun /* Allow forced onlining of boxed devices. */
179*4882a593Smuzhiyun #define CCWDEV_ALLOW_FORCE              0x0008
180*4882a593Smuzhiyun /* Try to use multipath mode. */
181*4882a593Smuzhiyun #define CCWDEV_DO_MULTIPATH		0x0010
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun extern int ccw_device_start(struct ccw_device *, struct ccw1 *,
184*4882a593Smuzhiyun 			    unsigned long, __u8, unsigned long);
185*4882a593Smuzhiyun extern int ccw_device_start_timeout(struct ccw_device *, struct ccw1 *,
186*4882a593Smuzhiyun 				    unsigned long, __u8, unsigned long, int);
187*4882a593Smuzhiyun extern int ccw_device_start_key(struct ccw_device *, struct ccw1 *,
188*4882a593Smuzhiyun 				unsigned long, __u8, __u8, unsigned long);
189*4882a593Smuzhiyun extern int ccw_device_start_timeout_key(struct ccw_device *, struct ccw1 *,
190*4882a593Smuzhiyun 					unsigned long, __u8, __u8,
191*4882a593Smuzhiyun 					unsigned long, int);
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun extern int ccw_device_resume(struct ccw_device *);
195*4882a593Smuzhiyun extern int ccw_device_halt(struct ccw_device *, unsigned long);
196*4882a593Smuzhiyun extern int ccw_device_clear(struct ccw_device *, unsigned long);
197*4882a593Smuzhiyun int ccw_device_tm_start_key(struct ccw_device *cdev, struct tcw *tcw,
198*4882a593Smuzhiyun 			    unsigned long intparm, u8 lpm, u8 key);
199*4882a593Smuzhiyun int ccw_device_tm_start_key(struct ccw_device *, struct tcw *,
200*4882a593Smuzhiyun 			    unsigned long, u8, u8);
201*4882a593Smuzhiyun int ccw_device_tm_start_timeout_key(struct ccw_device *, struct tcw *,
202*4882a593Smuzhiyun 			    unsigned long, u8, u8, int);
203*4882a593Smuzhiyun int ccw_device_tm_start(struct ccw_device *, struct tcw *,
204*4882a593Smuzhiyun 			    unsigned long, u8);
205*4882a593Smuzhiyun int ccw_device_tm_start_timeout(struct ccw_device *, struct tcw *,
206*4882a593Smuzhiyun 			    unsigned long, u8, int);
207*4882a593Smuzhiyun int ccw_device_tm_intrg(struct ccw_device *cdev);
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun int ccw_device_get_mdc(struct ccw_device *cdev, u8 mask);
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun extern int ccw_device_set_online(struct ccw_device *cdev);
212*4882a593Smuzhiyun extern int ccw_device_set_offline(struct ccw_device *cdev);
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun extern struct ciw *ccw_device_get_ciw(struct ccw_device *, __u32 cmd);
216*4882a593Smuzhiyun extern __u8 ccw_device_get_path_mask(struct ccw_device *);
217*4882a593Smuzhiyun extern void ccw_device_get_id(struct ccw_device *, struct ccw_dev_id *);
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun #define get_ccwdev_lock(x) (x)->ccwlock
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun #define to_ccwdev(n) container_of(n, struct ccw_device, dev)
222*4882a593Smuzhiyun #define to_ccwdrv(n) container_of(n, struct ccw_driver, driver)
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun extern struct ccw_device *ccw_device_create_console(struct ccw_driver *);
225*4882a593Smuzhiyun extern void ccw_device_destroy_console(struct ccw_device *);
226*4882a593Smuzhiyun extern int ccw_device_enable_console(struct ccw_device *);
227*4882a593Smuzhiyun extern void ccw_device_wait_idle(struct ccw_device *);
228*4882a593Smuzhiyun extern int ccw_device_force_console(struct ccw_device *);
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun extern void *ccw_device_dma_zalloc(struct ccw_device *cdev, size_t size);
231*4882a593Smuzhiyun extern void ccw_device_dma_free(struct ccw_device *cdev,
232*4882a593Smuzhiyun 				void *cpu_addr, size_t size);
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun int ccw_device_siosl(struct ccw_device *);
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun extern void ccw_device_get_schid(struct ccw_device *, struct subchannel_id *);
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun struct channel_path_desc_fmt0 *ccw_device_get_chp_desc(struct ccw_device *, int);
239*4882a593Smuzhiyun u8 *ccw_device_get_util_str(struct ccw_device *cdev, int chp_idx);
240*4882a593Smuzhiyun int ccw_device_pnso(struct ccw_device *cdev,
241*4882a593Smuzhiyun 		    struct chsc_pnso_area *pnso_area, u8 oc,
242*4882a593Smuzhiyun 		    struct chsc_pnso_resume_token resume_token, int cnc);
243*4882a593Smuzhiyun int ccw_device_get_cssid(struct ccw_device *cdev, u8 *cssid);
244*4882a593Smuzhiyun int ccw_device_get_iid(struct ccw_device *cdev, u8 *iid);
245*4882a593Smuzhiyun int ccw_device_get_chpid(struct ccw_device *cdev, int chp_idx, u8 *chpid);
246*4882a593Smuzhiyun int ccw_device_get_chid(struct ccw_device *cdev, int chp_idx, u16 *chid);
247*4882a593Smuzhiyun #endif /* _S390_CCWDEV_H_ */
248