xref: /linux/drivers/s390/block/dasd_int.h (revision ab24fbd35a6ee77a58c24bd50582c51610a194f0)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
31da177e4SLinus Torvalds  *		    Horst Hummel <Horst.Hummel@de.ibm.com>
41da177e4SLinus Torvalds  *		    Martin Schwidefsky <schwidefsky@de.ibm.com>
51da177e4SLinus Torvalds  * Bugreports.to..: <Linux390@de.ibm.com>
6d41dd122SStefan Haberland  * Copyright IBM Corp. 1999, 2009
71da177e4SLinus Torvalds  */
81da177e4SLinus Torvalds 
91da177e4SLinus Torvalds #ifndef DASD_INT_H
101da177e4SLinus Torvalds #define DASD_INT_H
111da177e4SLinus Torvalds 
121da177e4SLinus Torvalds /* we keep old device allocation scheme; IOW, minors are still in 0..255 */
131da177e4SLinus Torvalds #define DASD_PER_MAJOR (1U << (MINORBITS - DASD_PARTN_BITS))
141da177e4SLinus Torvalds #define DASD_PARTN_MASK ((1 << DASD_PARTN_BITS) - 1)
151da177e4SLinus Torvalds 
161da177e4SLinus Torvalds /*
171da177e4SLinus Torvalds  * States a dasd device can have:
181da177e4SLinus Torvalds  *   new: the dasd_device structure is allocated.
191da177e4SLinus Torvalds  *   known: the discipline for the device is identified.
201da177e4SLinus Torvalds  *   basic: the device can do basic i/o.
2190f0094dSHorst Hummel  *   unfmt: the device could not be analyzed (format is unknown).
221da177e4SLinus Torvalds  *   ready: partition detection is done and the device is can do block io.
231da177e4SLinus Torvalds  *   online: the device accepts requests from the block device queue.
241da177e4SLinus Torvalds  *
251da177e4SLinus Torvalds  * Things to do for startup state transitions:
261da177e4SLinus Torvalds  *   new -> known: find discipline for the device and create devfs entries.
271da177e4SLinus Torvalds  *   known -> basic: request irq line for the device.
281da177e4SLinus Torvalds  *   basic -> ready: do the initial analysis, e.g. format detection,
291da177e4SLinus Torvalds  *                   do block device setup and detect partitions.
301da177e4SLinus Torvalds  *   ready -> online: schedule the device tasklet.
311da177e4SLinus Torvalds  * Things to do for shutdown state transitions:
321da177e4SLinus Torvalds  *   online -> ready: just set the new device state.
331da177e4SLinus Torvalds  *   ready -> basic: flush requests from the block device layer, clear
341da177e4SLinus Torvalds  *                   partition information and reset format information.
351da177e4SLinus Torvalds  *   basic -> known: terminate all requests and free irq.
361da177e4SLinus Torvalds  *   known -> new: remove devfs entries and forget discipline.
371da177e4SLinus Torvalds  */
381da177e4SLinus Torvalds 
391da177e4SLinus Torvalds #define DASD_STATE_NEW	  0
401da177e4SLinus Torvalds #define DASD_STATE_KNOWN  1
411da177e4SLinus Torvalds #define DASD_STATE_BASIC  2
4290f0094dSHorst Hummel #define DASD_STATE_UNFMT  3
4390f0094dSHorst Hummel #define DASD_STATE_READY  4
4490f0094dSHorst Hummel #define DASD_STATE_ONLINE 5
451da177e4SLinus Torvalds 
461da177e4SLinus Torvalds #include <linux/module.h>
471da177e4SLinus Torvalds #include <linux/wait.h>
481da177e4SLinus Torvalds #include <linux/blkdev.h>
491da177e4SLinus Torvalds #include <linux/genhd.h>
501da177e4SLinus Torvalds #include <linux/hdreg.h>
511da177e4SLinus Torvalds #include <linux/interrupt.h>
52e108cebbSvignesh babu #include <linux/log2.h>
531da177e4SLinus Torvalds #include <asm/ccwdev.h>
541da177e4SLinus Torvalds #include <linux/workqueue.h>
551da177e4SLinus Torvalds #include <asm/debug.h>
561da177e4SLinus Torvalds #include <asm/dasd.h>
571da177e4SLinus Torvalds #include <asm/idals.h>
58c9346151SStefan Haberland #include <linux/bitops.h>
591da177e4SLinus Torvalds 
6068b781feSStefan Haberland /* DASD discipline magic */
6168b781feSStefan Haberland #define DASD_ECKD_MAGIC 0xC5C3D2C4
6268b781feSStefan Haberland #define DASD_DIAG_MAGIC 0xC4C9C1C7
6368b781feSStefan Haberland #define DASD_FBA_MAGIC 0xC6C2C140
6468b781feSStefan Haberland 
651da177e4SLinus Torvalds /*
661da177e4SLinus Torvalds  * SECTION: Type definitions
671da177e4SLinus Torvalds  */
681da177e4SLinus Torvalds struct dasd_device;
698e09f215SStefan Weinhuber struct dasd_block;
701da177e4SLinus Torvalds 
711da177e4SLinus Torvalds /* BIT DEFINITIONS FOR SENSE DATA */
721da177e4SLinus Torvalds #define DASD_SENSE_BIT_0 0x80
731da177e4SLinus Torvalds #define DASD_SENSE_BIT_1 0x40
741da177e4SLinus Torvalds #define DASD_SENSE_BIT_2 0x20
751da177e4SLinus Torvalds #define DASD_SENSE_BIT_3 0x10
761da177e4SLinus Torvalds 
77f60c768cSStefan Haberland /* BIT DEFINITIONS FOR SIM SENSE */
78f60c768cSStefan Haberland #define DASD_SIM_SENSE 0x0F
79f60c768cSStefan Haberland #define DASD_SIM_MSG_TO_OP 0x03
80f60c768cSStefan Haberland #define DASD_SIM_LOG 0x0C
81f60c768cSStefan Haberland 
822dedf0d9SStefan Haberland /* lock class for nested cdev lock */
832dedf0d9SStefan Haberland #define CDEV_NESTED_FIRST 1
842dedf0d9SStefan Haberland #define CDEV_NESTED_SECOND 2
852dedf0d9SStefan Haberland 
861da177e4SLinus Torvalds /*
871da177e4SLinus Torvalds  * SECTION: MACROs for klogd and s390 debug feature (dbf)
881da177e4SLinus Torvalds  */
891da177e4SLinus Torvalds #define DBF_DEV_EVENT(d_level, d_device, d_str, d_data...) \
901da177e4SLinus Torvalds do { \
911da177e4SLinus Torvalds 	debug_sprintf_event(d_device->debug_area, \
921da177e4SLinus Torvalds 			    d_level, \
931da177e4SLinus Torvalds 			    d_str "\n", \
941da177e4SLinus Torvalds 			    d_data); \
951da177e4SLinus Torvalds } while(0)
961da177e4SLinus Torvalds 
971da177e4SLinus Torvalds #define DBF_DEV_EXC(d_level, d_device, d_str, d_data...) \
981da177e4SLinus Torvalds do { \
991da177e4SLinus Torvalds 	debug_sprintf_exception(d_device->debug_area, \
1001da177e4SLinus Torvalds 				d_level, \
1011da177e4SLinus Torvalds 				d_str "\n", \
1021da177e4SLinus Torvalds 				d_data); \
1031da177e4SLinus Torvalds } while(0)
1041da177e4SLinus Torvalds 
1051da177e4SLinus Torvalds #define DBF_EVENT(d_level, d_str, d_data...)\
1061da177e4SLinus Torvalds do { \
1071da177e4SLinus Torvalds 	debug_sprintf_event(dasd_debug_area, \
1081da177e4SLinus Torvalds 			    d_level,\
1091da177e4SLinus Torvalds 			    d_str "\n", \
1101da177e4SLinus Torvalds 			    d_data); \
1111da177e4SLinus Torvalds } while(0)
1121da177e4SLinus Torvalds 
113b8ed5dd5SStefan Haberland #define DBF_EVENT_DEVID(d_level, d_cdev, d_str, d_data...)	\
114b8ed5dd5SStefan Haberland do { \
115b8ed5dd5SStefan Haberland 	struct ccw_dev_id __dev_id;			\
116b8ed5dd5SStefan Haberland 	ccw_device_get_id(d_cdev, &__dev_id);		\
117b8ed5dd5SStefan Haberland 	debug_sprintf_event(dasd_debug_area,		\
118b8ed5dd5SStefan Haberland 			    d_level,					\
119b8ed5dd5SStefan Haberland 			    "0.%x.%04x " d_str "\n",			\
120b8ed5dd5SStefan Haberland 			    __dev_id.ssid, __dev_id.devno, d_data);	\
121b8ed5dd5SStefan Haberland } while (0)
122b8ed5dd5SStefan Haberland 
1231da177e4SLinus Torvalds #define DBF_EXC(d_level, d_str, d_data...)\
1241da177e4SLinus Torvalds do { \
1251da177e4SLinus Torvalds 	debug_sprintf_exception(dasd_debug_area, \
1261da177e4SLinus Torvalds 				d_level,\
1271da177e4SLinus Torvalds 				d_str "\n", \
1281da177e4SLinus Torvalds 				d_data); \
1291da177e4SLinus Torvalds } while(0)
1301da177e4SLinus Torvalds 
131fc19f381SStefan Haberland /* limit size for an errorstring */
132fc19f381SStefan Haberland #define ERRORLENGTH 30
133fc19f381SStefan Haberland 
1341da177e4SLinus Torvalds /* definition of dbf debug levels */
1351da177e4SLinus Torvalds #define	DBF_EMERG	0	/* system is unusable			*/
1361da177e4SLinus Torvalds #define	DBF_ALERT	1	/* action must be taken immediately	*/
1371da177e4SLinus Torvalds #define	DBF_CRIT	2	/* critical conditions			*/
1381da177e4SLinus Torvalds #define	DBF_ERR		3	/* error conditions			*/
1391da177e4SLinus Torvalds #define	DBF_WARNING	4	/* warning conditions			*/
1401da177e4SLinus Torvalds #define	DBF_NOTICE	5	/* normal but significant condition	*/
1411da177e4SLinus Torvalds #define	DBF_INFO	6	/* informational			*/
1421da177e4SLinus Torvalds #define	DBF_DEBUG	6	/* debug-level messages			*/
1431da177e4SLinus Torvalds 
1441da177e4SLinus Torvalds /* messages to be written via klogd and dbf */
1451da177e4SLinus Torvalds #define DEV_MESSAGE(d_loglevel,d_device,d_string,d_args...)\
1461da177e4SLinus Torvalds do { \
1471da177e4SLinus Torvalds 	printk(d_loglevel PRINTK_HEADER " %s: " d_string "\n", \
1482a0217d5SKay Sievers 	       dev_name(&d_device->cdev->dev), d_args); \
1491da177e4SLinus Torvalds 	DBF_DEV_EVENT(DBF_ALERT, d_device, d_string, d_args); \
1501da177e4SLinus Torvalds } while(0)
1511da177e4SLinus Torvalds 
1521da177e4SLinus Torvalds #define MESSAGE(d_loglevel,d_string,d_args...)\
1531da177e4SLinus Torvalds do { \
1541da177e4SLinus Torvalds 	printk(d_loglevel PRINTK_HEADER " " d_string "\n", d_args); \
1551da177e4SLinus Torvalds 	DBF_EVENT(DBF_ALERT, d_string, d_args); \
1561da177e4SLinus Torvalds } while(0)
1571da177e4SLinus Torvalds 
1581da177e4SLinus Torvalds /* messages to be written via klogd only */
1591da177e4SLinus Torvalds #define DEV_MESSAGE_LOG(d_loglevel,d_device,d_string,d_args...)\
1601da177e4SLinus Torvalds do { \
1611da177e4SLinus Torvalds 	printk(d_loglevel PRINTK_HEADER " %s: " d_string "\n", \
1622a0217d5SKay Sievers 	       dev_name(&d_device->cdev->dev), d_args); \
1631da177e4SLinus Torvalds } while(0)
1641da177e4SLinus Torvalds 
1651da177e4SLinus Torvalds #define MESSAGE_LOG(d_loglevel,d_string,d_args...)\
1661da177e4SLinus Torvalds do { \
1671da177e4SLinus Torvalds 	printk(d_loglevel PRINTK_HEADER " " d_string "\n", d_args); \
1681da177e4SLinus Torvalds } while(0)
1691da177e4SLinus Torvalds 
1701da177e4SLinus Torvalds struct dasd_ccw_req {
1711da177e4SLinus Torvalds 	unsigned int magic;		/* Eye catcher */
1728e09f215SStefan Weinhuber 	struct list_head devlist;	/* for dasd_device request queue */
1738e09f215SStefan Weinhuber 	struct list_head blocklist;	/* for dasd_block request queue */
1741da177e4SLinus Torvalds 
1751da177e4SLinus Torvalds 	/* Where to execute what... */
1768e09f215SStefan Weinhuber 	struct dasd_block *block;	/* the originating block device */
1778e09f215SStefan Weinhuber 	struct dasd_device *memdev;	/* the device used to allocate this */
1788e09f215SStefan Weinhuber 	struct dasd_device *startdev;	/* device the request is started on */
17929b8dd9dSStefan Haberland 	struct dasd_device *basedev;	/* base device if no block->base */
180f3eb5384SStefan Weinhuber 	void *cpaddr;			/* address of ccw or tcw */
181f3eb5384SStefan Weinhuber 	unsigned char cpmode;		/* 0 = cmd mode, 1 = itcw */
1821da177e4SLinus Torvalds 	char status;			/* status of this request */
1831da177e4SLinus Torvalds 	short retries;			/* A retry counter */
1841da177e4SLinus Torvalds 	unsigned long flags;        	/* flags of this request */
1851da177e4SLinus Torvalds 
1861da177e4SLinus Torvalds 	/* ... and how */
1871da177e4SLinus Torvalds 	unsigned long starttime;	/* jiffies time of request start */
1887c8faa86SStefan Haberland 	unsigned long expires;		/* expiration period in jiffies */
1891da177e4SLinus Torvalds 	char lpm;			/* logical path mask */
1901da177e4SLinus Torvalds 	void *data;			/* pointer to data area */
1911da177e4SLinus Torvalds 
1921da177e4SLinus Torvalds 	/* these are important for recovering erroneous requests          */
1936cc7f168SStefan Weinhuber 	int intrc;			/* internal error, e.g. from start_IO */
1941da177e4SLinus Torvalds 	struct irb irb;			/* device status in case of an error */
1951da177e4SLinus Torvalds 	struct dasd_ccw_req *refers;	/* ERP-chain queueing. */
1961da177e4SLinus Torvalds 	void *function; 		/* originating ERP action */
1971da177e4SLinus Torvalds 
1981da177e4SLinus Torvalds 	/* these are for statistics only */
1991da177e4SLinus Torvalds 	unsigned long long buildclk;	/* TOD-clock of request generation */
2001da177e4SLinus Torvalds 	unsigned long long startclk;	/* TOD-clock of request start */
2011da177e4SLinus Torvalds 	unsigned long long stopclk;	/* TOD-clock of request interrupt */
2021da177e4SLinus Torvalds 	unsigned long long endclk;	/* TOD-clock of request termination */
2031da177e4SLinus Torvalds 
2041da177e4SLinus Torvalds         /* Callback that is called after reaching final status. */
2051da177e4SLinus Torvalds 	void (*callback)(struct dasd_ccw_req *, void *data);
2061da177e4SLinus Torvalds 	void *callback_data;
2071da177e4SLinus Torvalds };
2081da177e4SLinus Torvalds 
2091da177e4SLinus Torvalds /*
2101da177e4SLinus Torvalds  * dasd_ccw_req -> status can be:
2111da177e4SLinus Torvalds  */
2121da177e4SLinus Torvalds #define DASD_CQR_FILLED 	0x00	/* request is ready to be processed */
2138e09f215SStefan Weinhuber #define DASD_CQR_DONE		0x01	/* request is completed successfully */
2148e09f215SStefan Weinhuber #define DASD_CQR_NEED_ERP	0x02	/* request needs recovery action */
2158e09f215SStefan Weinhuber #define DASD_CQR_IN_ERP 	0x03	/* request is in recovery */
2168e09f215SStefan Weinhuber #define DASD_CQR_FAILED 	0x04	/* request is finally failed */
2178e09f215SStefan Weinhuber #define DASD_CQR_TERMINATED	0x05	/* request was stopped by driver */
2188e09f215SStefan Weinhuber 
2198e09f215SStefan Weinhuber #define DASD_CQR_QUEUED 	0x80	/* request is queued to be processed */
2208e09f215SStefan Weinhuber #define DASD_CQR_IN_IO		0x81	/* request is currently in IO */
2218e09f215SStefan Weinhuber #define DASD_CQR_ERROR		0x82	/* request is completed with error */
2228e09f215SStefan Weinhuber #define DASD_CQR_CLEAR_PENDING	0x83	/* request is clear pending */
2238e09f215SStefan Weinhuber #define DASD_CQR_CLEARED	0x84	/* request was cleared */
22473ac36eaSColy Li #define DASD_CQR_SUCCESS	0x85	/* request was successful */
2258e09f215SStefan Weinhuber 
2267c8faa86SStefan Haberland /* default expiration time*/
2277c8faa86SStefan Haberland #define DASD_EXPIRES	  300
2287c8faa86SStefan Haberland #define DASD_EXPIRES_MAX  40000000
2291f1ee9adSHannes Reinecke #define DASD_RETRIES	  256
2301f1ee9adSHannes Reinecke #define DASD_RETRIES_MAX  32768
2311da177e4SLinus Torvalds 
2321da177e4SLinus Torvalds /* per dasd_ccw_req flags */
2331da177e4SLinus Torvalds #define DASD_CQR_FLAGS_USE_ERP   0	/* use ERP for this request */
2341c01b8a5SHorst Hummel #define DASD_CQR_FLAGS_FAILFAST  1	/* FAILFAST */
235a4d26c6aSStefan Weinhuber #define DASD_CQR_VERIFY_PATH	 2	/* path verification request */
2365a27e60dSStefan Weinhuber #define DASD_CQR_ALLOW_SLOCK	 3	/* Try this request even when lock was
2375a27e60dSStefan Weinhuber 					 * stolen. Should not be combined with
2385a27e60dSStefan Weinhuber 					 * DASD_CQR_FLAGS_USE_ERP
2395a27e60dSStefan Weinhuber 					 */
2408fd57520SJan Höppner /*
2418fd57520SJan Höppner  * The following flags are used to suppress output of certain errors.
2428fd57520SJan Höppner  */
2438fd57520SJan Höppner #define DASD_CQR_SUPPRESS_NRF	4	/* Suppress 'No Record Found' error */
2448fd57520SJan Höppner #define DASD_CQR_SUPPRESS_FP	5	/* Suppress 'File Protected' error*/
2458fd57520SJan Höppner #define DASD_CQR_SUPPRESS_IL	6	/* Suppress 'Incorrect Length' error */
246*ab24fbd3SStefan Haberland #define DASD_CQR_SUPPRESS_CR	7	/* Suppress 'Command Reject' error */
2471da177e4SLinus Torvalds 
2481da177e4SLinus Torvalds /* Signature for error recovery functions. */
2491da177e4SLinus Torvalds typedef struct dasd_ccw_req *(*dasd_erp_fn_t) (struct dasd_ccw_req *);
2501da177e4SLinus Torvalds 
2511da177e4SLinus Torvalds /*
25246d1c03cSJan Höppner  * A single CQR can only contain a maximum of 255 CCWs. It is limited by
25346d1c03cSJan Höppner  * the locate record and locate record extended count value which can only hold
25446d1c03cSJan Höppner  * 1 Byte max.
25546d1c03cSJan Höppner  */
25646d1c03cSJan Höppner #define DASD_CQR_MAX_CCW 255
25746d1c03cSJan Höppner 
25846d1c03cSJan Höppner /*
2592dedf0d9SStefan Haberland  * Unique identifier for dasd device.
2602dedf0d9SStefan Haberland  */
2612dedf0d9SStefan Haberland #define UA_NOT_CONFIGURED  0x00
2622dedf0d9SStefan Haberland #define UA_BASE_DEVICE	   0x01
2632dedf0d9SStefan Haberland #define UA_BASE_PAV_ALIAS  0x02
2642dedf0d9SStefan Haberland #define UA_HYPER_PAV_ALIAS 0x03
2652dedf0d9SStefan Haberland 
2662dedf0d9SStefan Haberland struct dasd_uid {
2672dedf0d9SStefan Haberland 	__u8 type;
2682dedf0d9SStefan Haberland 	char vendor[4];
2692dedf0d9SStefan Haberland 	char serial[15];
2702dedf0d9SStefan Haberland 	__u16 ssid;
2712dedf0d9SStefan Haberland 	__u8 real_unit_addr;
2722dedf0d9SStefan Haberland 	__u8 base_unit_addr;
2732dedf0d9SStefan Haberland 	char vduit[33];
2742dedf0d9SStefan Haberland };
2752dedf0d9SStefan Haberland 
2762dedf0d9SStefan Haberland /*
2771da177e4SLinus Torvalds  * the struct dasd_discipline is
2781da177e4SLinus Torvalds  * sth like a table of virtual functions, if you think of dasd_eckd
2791da177e4SLinus Torvalds  * inheriting dasd...
2801da177e4SLinus Torvalds  * no, currently we are not planning to reimplement the driver in C++
2811da177e4SLinus Torvalds  */
2821da177e4SLinus Torvalds struct dasd_discipline {
2831da177e4SLinus Torvalds 	struct module *owner;
2841da177e4SLinus Torvalds 	char ebcname[8];	/* a name used for tagging and printks */
2851da177e4SLinus Torvalds 	char name[8];		/* a name used for tagging and printks */
2861da177e4SLinus Torvalds 	int max_blocks;		/* maximum number of blocks to be chained */
2871da177e4SLinus Torvalds 
2881da177e4SLinus Torvalds 	struct list_head list;	/* used for list of disciplines */
2891da177e4SLinus Torvalds 
2901da177e4SLinus Torvalds 	/*
2911da177e4SLinus Torvalds 	 * Device recognition functions. check_device is used to verify
2921da177e4SLinus Torvalds 	 * the sense data and the information returned by read device
2931da177e4SLinus Torvalds 	 * characteristics. It returns 0 if the discipline can be used
2948e09f215SStefan Weinhuber 	 * for the device in question. uncheck_device is called during
2958e09f215SStefan Weinhuber 	 * device shutdown to deregister a device from its discipline.
2968e09f215SStefan Weinhuber 	 */
2978e09f215SStefan Weinhuber 	int (*check_device) (struct dasd_device *);
2988e09f215SStefan Weinhuber 	void (*uncheck_device) (struct dasd_device *);
2998e09f215SStefan Weinhuber 
3008e09f215SStefan Weinhuber 	/*
3011da177e4SLinus Torvalds 	 * do_analysis is used in the step from device state "basic" to
3021da177e4SLinus Torvalds 	 * state "accept". It returns 0 if the device can be made ready,
3031da177e4SLinus Torvalds 	 * it returns -EMEDIUMTYPE if the device can't be made ready or
3041da177e4SLinus Torvalds 	 * -EAGAIN if do_analysis started a ccw that needs to complete
3051da177e4SLinus Torvalds 	 * before the analysis may be repeated.
3061da177e4SLinus Torvalds 	 */
3078e09f215SStefan Weinhuber 	int (*do_analysis) (struct dasd_block *);
3088e09f215SStefan Weinhuber 
3098e09f215SStefan Weinhuber 	/*
310a4d26c6aSStefan Weinhuber 	 * This function is called, when new paths become available.
311a4d26c6aSStefan Weinhuber 	 * Disciplins may use this callback to do necessary setup work,
312a4d26c6aSStefan Weinhuber 	 * e.g. verify that new path is compatible with the current
313a4d26c6aSStefan Weinhuber 	 * configuration.
314a4d26c6aSStefan Weinhuber 	 */
315a4d26c6aSStefan Weinhuber 	int (*verify_path)(struct dasd_device *, __u8);
316a4d26c6aSStefan Weinhuber 
317a4d26c6aSStefan Weinhuber 	/*
3188e09f215SStefan Weinhuber 	 * Last things to do when a device is set online, and first things
3198e09f215SStefan Weinhuber 	 * when it is set offline.
3208e09f215SStefan Weinhuber 	 */
321d42e1712SStefan Haberland 	int (*basic_to_ready) (struct dasd_device *);
3228e09f215SStefan Weinhuber 	int (*online_to_ready) (struct dasd_device *);
323daa991bfSStefan Haberland 	int (*basic_to_known)(struct dasd_device *);
3241da177e4SLinus Torvalds 
325d42e1712SStefan Haberland 	/* (struct dasd_device *);
3261da177e4SLinus Torvalds 	 * Device operation functions. build_cp creates a ccw chain for
3271da177e4SLinus Torvalds 	 * a block device request, start_io starts the request and
3281da177e4SLinus Torvalds 	 * term_IO cancels it (e.g. in case of a timeout). format_device
3298fd57520SJan Höppner 	 * formats the device and check_device_format compares the format of
3308fd57520SJan Höppner 	 * a device with the expected format_data.
3318e09f215SStefan Weinhuber 	 * handle_terminated_request allows to examine a cqr and prepare
3328e09f215SStefan Weinhuber 	 * it for retry.
3331da177e4SLinus Torvalds 	 */
3341da177e4SLinus Torvalds 	struct dasd_ccw_req *(*build_cp) (struct dasd_device *,
3358e09f215SStefan Weinhuber 					  struct dasd_block *,
3361da177e4SLinus Torvalds 					  struct request *);
3371da177e4SLinus Torvalds 	int (*start_IO) (struct dasd_ccw_req *);
3381da177e4SLinus Torvalds 	int (*term_IO) (struct dasd_ccw_req *);
3398e09f215SStefan Weinhuber 	void (*handle_terminated_request) (struct dasd_ccw_req *);
340d42e1712SStefan Haberland 	int (*format_device) (struct dasd_device *,
3418fd57520SJan Höppner 			      struct format_data_t *, int);
3428fd57520SJan Höppner 	int (*check_device_format)(struct dasd_device *,
3438fd57520SJan Höppner 				   struct format_check_t *, int);
3441da177e4SLinus Torvalds 	int (*free_cp) (struct dasd_ccw_req *, struct request *);
3458e09f215SStefan Weinhuber 
3461da177e4SLinus Torvalds 	/*
3471da177e4SLinus Torvalds 	 * Error recovery functions. examine_error() returns a value that
3481da177e4SLinus Torvalds 	 * indicates what to do for an error condition. If examine_error()
3491da177e4SLinus Torvalds 	 * returns 'dasd_era_recover' erp_action() is called to create a
3501da177e4SLinus Torvalds 	 * special error recovery ccw. erp_postaction() is called after
3511da177e4SLinus Torvalds 	 * an error recovery ccw has finished its execution. dump_sense
3521da177e4SLinus Torvalds 	 * is called for every error condition to print the sense data
3531da177e4SLinus Torvalds 	 * to the console.
3541da177e4SLinus Torvalds 	 */
3551da177e4SLinus Torvalds 	dasd_erp_fn_t(*erp_action) (struct dasd_ccw_req *);
3561da177e4SLinus Torvalds 	dasd_erp_fn_t(*erp_postaction) (struct dasd_ccw_req *);
3571da177e4SLinus Torvalds 	void (*dump_sense) (struct dasd_device *, struct dasd_ccw_req *,
3581da177e4SLinus Torvalds 			    struct irb *);
359aeec92caSStefan Haberland 	void (*dump_sense_dbf) (struct dasd_device *, struct irb *, char *);
3605a27e60dSStefan Weinhuber 	void (*check_for_device_change) (struct dasd_device *,
3615a27e60dSStefan Weinhuber 					 struct dasd_ccw_req *,
3628e09f215SStefan Weinhuber 					 struct irb *);
3638e09f215SStefan Weinhuber 
3641da177e4SLinus Torvalds         /* i/o control functions. */
3658e09f215SStefan Weinhuber 	int (*fill_geometry) (struct dasd_block *, struct hd_geometry *);
3661da177e4SLinus Torvalds 	int (*fill_info) (struct dasd_device *, struct dasd_information2_t *);
3678e09f215SStefan Weinhuber 	int (*ioctl) (struct dasd_block *, unsigned int, void __user *);
368d41dd122SStefan Haberland 
369d41dd122SStefan Haberland 	/* suspend/resume functions */
370d41dd122SStefan Haberland 	int (*freeze) (struct dasd_device *);
371d41dd122SStefan Haberland 	int (*restore) (struct dasd_device *);
372501183f2SStefan Haberland 
373501183f2SStefan Haberland 	/* reload device after state change */
374501183f2SStefan Haberland 	int (*reload) (struct dasd_device *);
3752dedf0d9SStefan Haberland 
3762dedf0d9SStefan Haberland 	int (*get_uid) (struct dasd_device *, struct dasd_uid *);
377f1633031SStefan Haberland 	void (*kick_validate) (struct dasd_device *);
3785db8440cSStefan Haberland 	int (*check_attention)(struct dasd_device *, __u8);
3795a3b7b11SStefan Haberland 	int (*host_access_count)(struct dasd_device *);
3805a3b7b11SStefan Haberland 	int (*hosts_print)(struct dasd_device *, struct seq_file *);
381a521b048SStefan Haberland 	void (*handle_hpf_error)(struct dasd_device *, struct irb *);
382a521b048SStefan Haberland 	void (*disable_hpf)(struct dasd_device *);
383a521b048SStefan Haberland 	int (*hpf_enabled)(struct dasd_device *);
384a521b048SStefan Haberland 	void (*reset_path)(struct dasd_device *, __u8);
3851da177e4SLinus Torvalds };
3861da177e4SLinus Torvalds 
3871da177e4SLinus Torvalds extern struct dasd_discipline *dasd_diag_discipline_pointer;
3881da177e4SLinus Torvalds 
3893d052595SHorst Hummel /*
39020c64468SStefan Weinhuber  * Notification numbers for extended error reporting notifications:
39120c64468SStefan Weinhuber  * The DASD_EER_DISABLE notification is sent before a dasd_device (and it's
39220c64468SStefan Weinhuber  * eer pointer) is freed. The error reporting module needs to do all necessary
39320c64468SStefan Weinhuber  * cleanup steps.
39420c64468SStefan Weinhuber  * The DASD_EER_TRIGGER notification sends the actual error reports (triggers).
39520c64468SStefan Weinhuber  */
39620c64468SStefan Weinhuber #define DASD_EER_DISABLE 0
39720c64468SStefan Weinhuber #define DASD_EER_TRIGGER 1
39820c64468SStefan Weinhuber 
39920c64468SStefan Weinhuber /* Trigger IDs for extended error reporting DASD_EER_TRIGGER notification */
40020c64468SStefan Weinhuber #define DASD_EER_FATALERROR  1
40120c64468SStefan Weinhuber #define DASD_EER_NOPATH      2
40220c64468SStefan Weinhuber #define DASD_EER_STATECHANGE 3
40320c64468SStefan Weinhuber #define DASD_EER_PPRCSUSPEND 4
40420c64468SStefan Weinhuber 
405c9346151SStefan Haberland /* DASD path handling */
406c9346151SStefan Haberland 
407c9346151SStefan Haberland #define DASD_PATH_OPERATIONAL  1
408c9346151SStefan Haberland #define DASD_PATH_TBV	       2
409c9346151SStefan Haberland #define DASD_PATH_PP	       3
410c9346151SStefan Haberland #define DASD_PATH_NPP	       4
411c9346151SStefan Haberland #define DASD_PATH_MISCABLED    5
412c9346151SStefan Haberland #define DASD_PATH_NOHPF        6
413c9346151SStefan Haberland #define DASD_PATH_CUIR	       7
414a521b048SStefan Haberland #define DASD_PATH_IFCC	       8
415c9346151SStefan Haberland 
416a521b048SStefan Haberland #define DASD_THRHLD_MAX		4294967295U
417a521b048SStefan Haberland #define DASD_INTERVAL_MAX	4294967295U
418c9346151SStefan Haberland 
419a4d26c6aSStefan Weinhuber struct dasd_path {
420c9346151SStefan Haberland 	unsigned long flags;
421a521b048SStefan Haberland 	u8 cssid;
422a521b048SStefan Haberland 	u8 ssid;
423a521b048SStefan Haberland 	u8 chpid;
424c9346151SStefan Haberland 	struct dasd_conf_data *conf_data;
425a521b048SStefan Haberland 	atomic_t error_count;
426a521b048SStefan Haberland 	unsigned long long errorclk;
427a4d26c6aSStefan Weinhuber };
428a4d26c6aSStefan Weinhuber 
429c9346151SStefan Haberland 
4304fa52aa7SStefan Weinhuber struct dasd_profile_info {
4314fa52aa7SStefan Weinhuber 	/* legacy part of profile data, as in dasd_profile_info_t */
4324fa52aa7SStefan Weinhuber 	unsigned int dasd_io_reqs;	 /* number of requests processed */
4334fa52aa7SStefan Weinhuber 	unsigned int dasd_io_sects;	 /* number of sectors processed */
4344fa52aa7SStefan Weinhuber 	unsigned int dasd_io_secs[32];	 /* histogram of request's sizes */
4354fa52aa7SStefan Weinhuber 	unsigned int dasd_io_times[32];	 /* histogram of requests's times */
4364fa52aa7SStefan Weinhuber 	unsigned int dasd_io_timps[32];	 /* h. of requests's times per sector */
4374fa52aa7SStefan Weinhuber 	unsigned int dasd_io_time1[32];	 /* hist. of time from build to start */
4384fa52aa7SStefan Weinhuber 	unsigned int dasd_io_time2[32];	 /* hist. of time from start to irq */
4394fa52aa7SStefan Weinhuber 	unsigned int dasd_io_time2ps[32]; /* hist. of time from start to irq */
4404fa52aa7SStefan Weinhuber 	unsigned int dasd_io_time3[32];	 /* hist. of time from irq to end */
4414fa52aa7SStefan Weinhuber 	unsigned int dasd_io_nr_req[32]; /* hist. of # of requests in chanq */
4424fa52aa7SStefan Weinhuber 
4434fa52aa7SStefan Weinhuber 	/* new data */
4444fa52aa7SStefan Weinhuber 	struct timespec starttod;	   /* time of start or last reset */
4454fa52aa7SStefan Weinhuber 	unsigned int dasd_io_alias;	   /* requests using an alias */
4464fa52aa7SStefan Weinhuber 	unsigned int dasd_io_tpm;	   /* requests using transport mode */
4474fa52aa7SStefan Weinhuber 	unsigned int dasd_read_reqs;	   /* total number of read  requests */
4484fa52aa7SStefan Weinhuber 	unsigned int dasd_read_sects;	   /* total number read sectors */
4494fa52aa7SStefan Weinhuber 	unsigned int dasd_read_alias;	   /* read request using an alias */
4504fa52aa7SStefan Weinhuber 	unsigned int dasd_read_tpm;	   /* read requests in transport mode */
4514fa52aa7SStefan Weinhuber 	unsigned int dasd_read_secs[32];   /* histogram of request's sizes */
4524fa52aa7SStefan Weinhuber 	unsigned int dasd_read_times[32];  /* histogram of requests's times */
4534fa52aa7SStefan Weinhuber 	unsigned int dasd_read_time1[32];  /* hist. time from build to start */
4544fa52aa7SStefan Weinhuber 	unsigned int dasd_read_time2[32];  /* hist. of time from start to irq */
4554fa52aa7SStefan Weinhuber 	unsigned int dasd_read_time3[32];  /* hist. of time from irq to end */
4564fa52aa7SStefan Weinhuber 	unsigned int dasd_read_nr_req[32]; /* hist. of # of requests in chanq */
4574fa52aa7SStefan Weinhuber };
4584fa52aa7SStefan Weinhuber 
4594fa52aa7SStefan Weinhuber struct dasd_profile {
4604fa52aa7SStefan Weinhuber 	struct dentry *dentry;
4614fa52aa7SStefan Weinhuber 	struct dasd_profile_info *data;
4624fa52aa7SStefan Weinhuber 	spinlock_t lock;
4634fa52aa7SStefan Weinhuber };
4644fa52aa7SStefan Weinhuber 
4651da177e4SLinus Torvalds struct dasd_device {
4661da177e4SLinus Torvalds 	/* Block device stuff. */
4678e09f215SStefan Weinhuber 	struct dasd_block *block;
4688e09f215SStefan Weinhuber 
4691da177e4SLinus Torvalds         unsigned int devindex;
4701da177e4SLinus Torvalds 	unsigned long flags;	   /* per device flags */
471c6eb7b77SHorst Hummel 	unsigned short features;   /* copy of devmap-features (read-only!) */
4721da177e4SLinus Torvalds 
47320c64468SStefan Weinhuber 	/* extended error reporting stuff (eer) */
47420c64468SStefan Weinhuber 	struct dasd_ccw_req *eer_cqr;
47520c64468SStefan Weinhuber 
4761da177e4SLinus Torvalds 	/* Device discipline stuff. */
4771da177e4SLinus Torvalds 	struct dasd_discipline *discipline;
478aa88861fSPeter Oberparleiter 	struct dasd_discipline *base_discipline;
479543691a4SSebastian Ott 	void *private;
480c9346151SStefan Haberland 	struct dasd_path path[8];
481c9346151SStefan Haberland 	__u8 opm;
4821da177e4SLinus Torvalds 
4831da177e4SLinus Torvalds 	/* Device state and target state. */
4841da177e4SLinus Torvalds 	int state, target;
4859eb25122SStefan Haberland 	struct mutex state_mutex;
4861da177e4SLinus Torvalds 	int stopped;		/* device (ccw_device_start) was stopped */
4871da177e4SLinus Torvalds 
4888e09f215SStefan Weinhuber 	/* reference count. */
4891da177e4SLinus Torvalds         atomic_t ref_count;
4901da177e4SLinus Torvalds 
4911da177e4SLinus Torvalds 	/* ccw queue and memory for static ccw/erp buffers. */
4921da177e4SLinus Torvalds 	struct list_head ccw_queue;
4931da177e4SLinus Torvalds 	spinlock_t mem_lock;
4941da177e4SLinus Torvalds 	void *ccw_mem;
4951da177e4SLinus Torvalds 	void *erp_mem;
4961da177e4SLinus Torvalds 	struct list_head ccw_chunks;
4971da177e4SLinus Torvalds 	struct list_head erp_chunks;
4981da177e4SLinus Torvalds 
4991da177e4SLinus Torvalds 	atomic_t tasklet_scheduled;
5001da177e4SLinus Torvalds         struct tasklet_struct tasklet;
5011da177e4SLinus Torvalds 	struct work_struct kick_work;
502d41dd122SStefan Haberland 	struct work_struct restore_device;
503501183f2SStefan Haberland 	struct work_struct reload_device;
504f1633031SStefan Haberland 	struct work_struct kick_validate;
50559a9ed5fSStefan Haberland 	struct work_struct suc_work;
506a521b048SStefan Haberland 	struct work_struct requeue_requests;
5071da177e4SLinus Torvalds 	struct timer_list timer;
5081da177e4SLinus Torvalds 
5091da177e4SLinus Torvalds 	debug_info_t *debug_area;
5101da177e4SLinus Torvalds 
5111da177e4SLinus Torvalds 	struct ccw_device *cdev;
5121da177e4SLinus Torvalds 
5138e09f215SStefan Weinhuber 	/* hook for alias management */
5148e09f215SStefan Weinhuber 	struct list_head alias_list;
5157c8faa86SStefan Haberland 
5167c8faa86SStefan Haberland 	/* default expiration time in s */
5177c8faa86SStefan Haberland 	unsigned long default_expires;
5181f1ee9adSHannes Reinecke 	unsigned long default_retries;
5194fa52aa7SStefan Weinhuber 
5203d71ad32SHannes Reinecke 	unsigned long blk_timeout;
5213d71ad32SHannes Reinecke 
522a521b048SStefan Haberland 	unsigned long path_thrhld;
523a521b048SStefan Haberland 	unsigned long path_interval;
524a521b048SStefan Haberland 
5254fa52aa7SStefan Weinhuber 	struct dentry *debugfs_dentry;
5265a3b7b11SStefan Haberland 	struct dentry *hosts_dentry;
5274fa52aa7SStefan Weinhuber 	struct dasd_profile profile;
5288e09f215SStefan Weinhuber };
5298e09f215SStefan Weinhuber 
5308e09f215SStefan Weinhuber struct dasd_block {
5318e09f215SStefan Weinhuber 	/* Block device stuff. */
5328e09f215SStefan Weinhuber 	struct gendisk *gdp;
5338e09f215SStefan Weinhuber 	struct request_queue *request_queue;
5348e09f215SStefan Weinhuber 	spinlock_t request_queue_lock;
5358e09f215SStefan Weinhuber 	struct block_device *bdev;
5368e09f215SStefan Weinhuber 	atomic_t open_count;
5378e09f215SStefan Weinhuber 
538b44b0ab3SStefan Weinhuber 	unsigned long long blocks; /* size of volume in blocks */
5398e09f215SStefan Weinhuber 	unsigned int bp_block;	   /* bytes per block */
5408e09f215SStefan Weinhuber 	unsigned int s2b_shift;	   /* log2 (bp_block/512) */
5418e09f215SStefan Weinhuber 
5428e09f215SStefan Weinhuber 	struct dasd_device *base;
5438e09f215SStefan Weinhuber 	struct list_head ccw_queue;
5448e09f215SStefan Weinhuber 	spinlock_t queue_lock;
5458e09f215SStefan Weinhuber 
5468e09f215SStefan Weinhuber 	atomic_t tasklet_scheduled;
5478e09f215SStefan Weinhuber 	struct tasklet_struct tasklet;
5488e09f215SStefan Weinhuber 	struct timer_list timer;
5498e09f215SStefan Weinhuber 
5504fa52aa7SStefan Weinhuber 	struct dentry *debugfs_dentry;
5514fa52aa7SStefan Weinhuber 	struct dasd_profile profile;
5521da177e4SLinus Torvalds };
5531da177e4SLinus Torvalds 
5545db8440cSStefan Haberland struct dasd_attention_data {
5555db8440cSStefan Haberland 	struct dasd_device *device;
5565db8440cSStefan Haberland 	__u8 lpum;
5575db8440cSStefan Haberland };
5588e09f215SStefan Weinhuber 
5591da177e4SLinus Torvalds /* reasons why device (ccw_device_start) was stopped */
5601da177e4SLinus Torvalds #define DASD_STOPPED_NOT_ACC 1         /* not accessible */
5611da177e4SLinus Torvalds #define DASD_STOPPED_QUIESCE 2         /* Quiesced */
5621da177e4SLinus Torvalds #define DASD_STOPPED_PENDING 4         /* long busy */
5631da177e4SLinus Torvalds #define DASD_STOPPED_DC_WAIT 8         /* disconnected, wait */
5648e09f215SStefan Weinhuber #define DASD_STOPPED_SU      16        /* summary unit check handling */
565d41dd122SStefan Haberland #define DASD_STOPPED_PM      32        /* pm state transition */
566d41dd122SStefan Haberland #define DASD_UNRESUMED_PM    64        /* pm resume failed state */
5671da177e4SLinus Torvalds 
5681da177e4SLinus Torvalds /* per device flags */
5691da177e4SLinus Torvalds #define DASD_FLAG_OFFLINE	3	/* device is in offline processing */
57020c64468SStefan Weinhuber #define DASD_FLAG_EER_SNSS	4	/* A SNSS is required */
57120c64468SStefan Weinhuber #define DASD_FLAG_EER_IN_USE	5	/* A SNSS request is running */
57233b62a30SStefan Weinhuber #define DASD_FLAG_DEVICE_RO	6	/* The device itself is read-only. Don't
57333b62a30SStefan Weinhuber 					 * confuse this with the user specified
57433b62a30SStefan Weinhuber 					 * read-only feature.
57533b62a30SStefan Weinhuber 					 */
5765a27e60dSStefan Weinhuber #define DASD_FLAG_IS_RESERVED	7	/* The device is reserved */
5775a27e60dSStefan Weinhuber #define DASD_FLAG_LOCK_STOLEN	8	/* The device lock was stolen */
578c8d1c0ffSStefan Haberland #define DASD_FLAG_SUSPENDED	9	/* The device was suspended */
579d07dc5d8SStefan Haberland #define DASD_FLAG_SAFE_OFFLINE	10	/* safe offline processing requested*/
580d07dc5d8SStefan Haberland #define DASD_FLAG_SAFE_OFFLINE_RUNNING	11	/* safe offline running */
5815ea34a01SHannes Reinecke #define DASD_FLAG_ABORTALL	12	/* Abort all noretry requests */
5821eb38023SStefan Haberland #define DASD_FLAG_PATH_VERIFY	13	/* Path verification worker running */
58359a9ed5fSStefan Haberland #define DASD_FLAG_SUC		14	/* unhandled summary unit check */
5845a27e60dSStefan Weinhuber 
5855ea34a01SHannes Reinecke #define DASD_SLEEPON_START_TAG	((void *) 1)
5865ea34a01SHannes Reinecke #define DASD_SLEEPON_END_TAG	((void *) 2)
5871da177e4SLinus Torvalds 
5881da177e4SLinus Torvalds void dasd_put_device_wake(struct dasd_device *);
5891da177e4SLinus Torvalds 
5901da177e4SLinus Torvalds /*
5911da177e4SLinus Torvalds  * Reference count inliners
5921da177e4SLinus Torvalds  */
5931da177e4SLinus Torvalds static inline void
5941da177e4SLinus Torvalds dasd_get_device(struct dasd_device *device)
5951da177e4SLinus Torvalds {
5961da177e4SLinus Torvalds 	atomic_inc(&device->ref_count);
5971da177e4SLinus Torvalds }
5981da177e4SLinus Torvalds 
5991da177e4SLinus Torvalds static inline void
6001da177e4SLinus Torvalds dasd_put_device(struct dasd_device *device)
6011da177e4SLinus Torvalds {
6021da177e4SLinus Torvalds 	if (atomic_dec_return(&device->ref_count) == 0)
6031da177e4SLinus Torvalds 		dasd_put_device_wake(device);
6041da177e4SLinus Torvalds }
6051da177e4SLinus Torvalds 
6061da177e4SLinus Torvalds /*
6071da177e4SLinus Torvalds  * The static memory in ccw_mem and erp_mem is managed by a sorted
6081da177e4SLinus Torvalds  * list of free memory chunks.
6091da177e4SLinus Torvalds  */
6101da177e4SLinus Torvalds struct dasd_mchunk
6111da177e4SLinus Torvalds {
6121da177e4SLinus Torvalds 	struct list_head list;
6131da177e4SLinus Torvalds 	unsigned long size;
6141da177e4SLinus Torvalds } __attribute__ ((aligned(8)));
6151da177e4SLinus Torvalds 
6161da177e4SLinus Torvalds static inline void
6171da177e4SLinus Torvalds dasd_init_chunklist(struct list_head *chunk_list, void *mem,
6181da177e4SLinus Torvalds 		    unsigned long size)
6191da177e4SLinus Torvalds {
6201da177e4SLinus Torvalds 	struct dasd_mchunk *chunk;
6211da177e4SLinus Torvalds 
6221da177e4SLinus Torvalds 	INIT_LIST_HEAD(chunk_list);
6231da177e4SLinus Torvalds 	chunk = (struct dasd_mchunk *) mem;
6241da177e4SLinus Torvalds 	chunk->size = size - sizeof(struct dasd_mchunk);
6251da177e4SLinus Torvalds 	list_add(&chunk->list, chunk_list);
6261da177e4SLinus Torvalds }
6271da177e4SLinus Torvalds 
6281da177e4SLinus Torvalds static inline void *
6291da177e4SLinus Torvalds dasd_alloc_chunk(struct list_head *chunk_list, unsigned long size)
6301da177e4SLinus Torvalds {
6311da177e4SLinus Torvalds 	struct dasd_mchunk *chunk, *tmp;
6321da177e4SLinus Torvalds 
6331da177e4SLinus Torvalds 	size = (size + 7L) & -8L;
6341da177e4SLinus Torvalds 	list_for_each_entry(chunk, chunk_list, list) {
6351da177e4SLinus Torvalds 		if (chunk->size < size)
6361da177e4SLinus Torvalds 			continue;
6371da177e4SLinus Torvalds 		if (chunk->size > size + sizeof(struct dasd_mchunk)) {
6381da177e4SLinus Torvalds 			char *endaddr = (char *) (chunk + 1) + chunk->size;
6391da177e4SLinus Torvalds 			tmp = (struct dasd_mchunk *) (endaddr - size) - 1;
6401da177e4SLinus Torvalds 			tmp->size = size;
6411da177e4SLinus Torvalds 			chunk->size -= size + sizeof(struct dasd_mchunk);
6421da177e4SLinus Torvalds 			chunk = tmp;
6431da177e4SLinus Torvalds 		} else
6441da177e4SLinus Torvalds 			list_del(&chunk->list);
6451da177e4SLinus Torvalds 		return (void *) (chunk + 1);
6461da177e4SLinus Torvalds 	}
6471da177e4SLinus Torvalds 	return NULL;
6481da177e4SLinus Torvalds }
6491da177e4SLinus Torvalds 
6501da177e4SLinus Torvalds static inline void
6511da177e4SLinus Torvalds dasd_free_chunk(struct list_head *chunk_list, void *mem)
6521da177e4SLinus Torvalds {
6531da177e4SLinus Torvalds 	struct dasd_mchunk *chunk, *tmp;
6541da177e4SLinus Torvalds 	struct list_head *p, *left;
6551da177e4SLinus Torvalds 
6561da177e4SLinus Torvalds 	chunk = (struct dasd_mchunk *)
6571da177e4SLinus Torvalds 		((char *) mem - sizeof(struct dasd_mchunk));
6581da177e4SLinus Torvalds 	/* Find out the left neighbour in chunk_list. */
6591da177e4SLinus Torvalds 	left = chunk_list;
6601da177e4SLinus Torvalds 	list_for_each(p, chunk_list) {
6611da177e4SLinus Torvalds 		if (list_entry(p, struct dasd_mchunk, list) > chunk)
6621da177e4SLinus Torvalds 			break;
6631da177e4SLinus Torvalds 		left = p;
6641da177e4SLinus Torvalds 	}
6651da177e4SLinus Torvalds 	/* Try to merge with right neighbour = next element from left. */
6661da177e4SLinus Torvalds 	if (left->next != chunk_list) {
6671da177e4SLinus Torvalds 		tmp = list_entry(left->next, struct dasd_mchunk, list);
6681da177e4SLinus Torvalds 		if ((char *) (chunk + 1) + chunk->size == (char *) tmp) {
6691da177e4SLinus Torvalds 			list_del(&tmp->list);
6701da177e4SLinus Torvalds 			chunk->size += tmp->size + sizeof(struct dasd_mchunk);
6711da177e4SLinus Torvalds 		}
6721da177e4SLinus Torvalds 	}
6731da177e4SLinus Torvalds 	/* Try to merge with left neighbour. */
6741da177e4SLinus Torvalds 	if (left != chunk_list) {
6751da177e4SLinus Torvalds 		tmp = list_entry(left, struct dasd_mchunk, list);
6761da177e4SLinus Torvalds 		if ((char *) (tmp + 1) + tmp->size == (char *) chunk) {
6771da177e4SLinus Torvalds 			tmp->size += chunk->size + sizeof(struct dasd_mchunk);
6781da177e4SLinus Torvalds 			return;
6791da177e4SLinus Torvalds 		}
6801da177e4SLinus Torvalds 	}
6811da177e4SLinus Torvalds 	__list_add(&chunk->list, left, left->next);
6821da177e4SLinus Torvalds }
6831da177e4SLinus Torvalds 
6841da177e4SLinus Torvalds /*
6851da177e4SLinus Torvalds  * Check if bsize is in { 512, 1024, 2048, 4096 }
6861da177e4SLinus Torvalds  */
6871da177e4SLinus Torvalds static inline int
6881da177e4SLinus Torvalds dasd_check_blocksize(int bsize)
6891da177e4SLinus Torvalds {
690e108cebbSvignesh babu 	if (bsize < 512 || bsize > 4096 || !is_power_of_2(bsize))
6911da177e4SLinus Torvalds 		return -EMEDIUMTYPE;
6921da177e4SLinus Torvalds 	return 0;
6931da177e4SLinus Torvalds }
6941da177e4SLinus Torvalds 
6951da177e4SLinus Torvalds /* externals in dasd.c */
6961da177e4SLinus Torvalds #define DASD_PROFILE_OFF	 0
6974fa52aa7SStefan Weinhuber #define DASD_PROFILE_ON 	 1
6984fa52aa7SStefan Weinhuber #define DASD_PROFILE_GLOBAL_ONLY 2
6991da177e4SLinus Torvalds 
7001da177e4SLinus Torvalds extern debug_info_t *dasd_debug_area;
7018ea55c95SSebastian Ott extern struct dasd_profile dasd_global_profile;
7024fa52aa7SStefan Weinhuber extern unsigned int dasd_global_profile_level;
70383d5cde4SAlexey Dobriyan extern const struct block_device_operations dasd_device_operations;
7041da177e4SLinus Torvalds 
705e18b890bSChristoph Lameter extern struct kmem_cache *dasd_page_cache;
7061da177e4SLinus Torvalds 
7071da177e4SLinus Torvalds struct dasd_ccw_req *
70868b781feSStefan Haberland dasd_kmalloc_request(int , int, int, struct dasd_device *);
7091da177e4SLinus Torvalds struct dasd_ccw_req *
71068b781feSStefan Haberland dasd_smalloc_request(int , int, int, struct dasd_device *);
7111da177e4SLinus Torvalds void dasd_kfree_request(struct dasd_ccw_req *, struct dasd_device *);
7121da177e4SLinus Torvalds void dasd_sfree_request(struct dasd_ccw_req *, struct dasd_device *);
7135915a873SStefan Haberland void dasd_wakeup_cb(struct dasd_ccw_req *, void *);
7141da177e4SLinus Torvalds 
7151da177e4SLinus Torvalds static inline int
7161da177e4SLinus Torvalds dasd_kmalloc_set_cda(struct ccw1 *ccw, void *cda, struct dasd_device *device)
7171da177e4SLinus Torvalds {
7181da177e4SLinus Torvalds 	return set_normalized_cda(ccw, cda);
7191da177e4SLinus Torvalds }
7201da177e4SLinus Torvalds 
7211da177e4SLinus Torvalds struct dasd_device *dasd_alloc_device(void);
7221da177e4SLinus Torvalds void dasd_free_device(struct dasd_device *);
7231da177e4SLinus Torvalds 
7248e09f215SStefan Weinhuber struct dasd_block *dasd_alloc_block(void);
7258e09f215SStefan Weinhuber void dasd_free_block(struct dasd_block *);
7268e09f215SStefan Weinhuber 
7273d71ad32SHannes Reinecke enum blk_eh_timer_return dasd_times_out(struct request *req);
7283d71ad32SHannes Reinecke 
7291da177e4SLinus Torvalds void dasd_enable_device(struct dasd_device *);
7301da177e4SLinus Torvalds void dasd_set_target_state(struct dasd_device *, int);
7311da177e4SLinus Torvalds void dasd_kick_device(struct dasd_device *);
732d41dd122SStefan Haberland void dasd_restore_device(struct dasd_device *);
733501183f2SStefan Haberland void dasd_reload_device(struct dasd_device *);
734a521b048SStefan Haberland void dasd_schedule_requeue(struct dasd_device *);
7351da177e4SLinus Torvalds 
7361da177e4SLinus Torvalds void dasd_add_request_head(struct dasd_ccw_req *);
7371da177e4SLinus Torvalds void dasd_add_request_tail(struct dasd_ccw_req *);
7381da177e4SLinus Torvalds int  dasd_start_IO(struct dasd_ccw_req *);
7391da177e4SLinus Torvalds int  dasd_term_IO(struct dasd_ccw_req *);
7408e09f215SStefan Weinhuber void dasd_schedule_device_bh(struct dasd_device *);
7418e09f215SStefan Weinhuber void dasd_schedule_block_bh(struct dasd_block *);
7421da177e4SLinus Torvalds int  dasd_sleep_on(struct dasd_ccw_req *);
743d42e1712SStefan Haberland int  dasd_sleep_on_queue(struct list_head *);
7441da177e4SLinus Torvalds int  dasd_sleep_on_immediatly(struct dasd_ccw_req *);
7451da177e4SLinus Torvalds int  dasd_sleep_on_interruptible(struct dasd_ccw_req *);
7468e09f215SStefan Weinhuber void dasd_device_set_timer(struct dasd_device *, int);
7478e09f215SStefan Weinhuber void dasd_device_clear_timer(struct dasd_device *);
7488e09f215SStefan Weinhuber void dasd_block_set_timer(struct dasd_block *, int);
7498e09f215SStefan Weinhuber void dasd_block_clear_timer(struct dasd_block *);
7501da177e4SLinus Torvalds int  dasd_cancel_req(struct dasd_ccw_req *);
7518e09f215SStefan Weinhuber int dasd_flush_device_queue(struct dasd_device *);
7521da177e4SLinus Torvalds int dasd_generic_probe (struct ccw_device *, struct dasd_discipline *);
753c020d722SStefan Haberland void dasd_generic_free_discipline(struct dasd_device *);
7541da177e4SLinus Torvalds void dasd_generic_remove (struct ccw_device *cdev);
7551da177e4SLinus Torvalds int dasd_generic_set_online(struct ccw_device *, struct dasd_discipline *);
7561da177e4SLinus Torvalds int dasd_generic_set_offline (struct ccw_device *cdev);
7571da177e4SLinus Torvalds int dasd_generic_notify(struct ccw_device *, int);
758a4d26c6aSStefan Weinhuber int dasd_generic_last_path_gone(struct dasd_device *);
759a4d26c6aSStefan Weinhuber int dasd_generic_path_operational(struct dasd_device *);
7604679e893SStefan Haberland void dasd_generic_shutdown(struct ccw_device *);
761a4d26c6aSStefan Weinhuber 
7628e09f215SStefan Weinhuber void dasd_generic_handle_state_change(struct dasd_device *);
763d41dd122SStefan Haberland int dasd_generic_pm_freeze(struct ccw_device *);
764d41dd122SStefan Haberland int dasd_generic_restore_device(struct ccw_device *);
765a23ed009SStefan Haberland enum uc_todo dasd_generic_uc_handler(struct ccw_device *, struct irb *);
766a4d26c6aSStefan Weinhuber void dasd_generic_path_event(struct ccw_device *, int *);
767a4d26c6aSStefan Weinhuber int dasd_generic_verify_path(struct dasd_device *, __u8);
7681da177e4SLinus Torvalds 
76968b781feSStefan Haberland int dasd_generic_read_dev_chars(struct dasd_device *, int, void *, int);
770f3eb5384SStefan Weinhuber char *dasd_get_sense(struct irb *);
77117283b56SCornelia Huck 
772eb6e199bSStefan Weinhuber void dasd_device_set_stop_bits(struct dasd_device *, int);
773eb6e199bSStefan Weinhuber void dasd_device_remove_stop_bits(struct dasd_device *, int);
774eb6e199bSStefan Weinhuber 
77533b62a30SStefan Weinhuber int dasd_device_is_ro(struct dasd_device *);
77633b62a30SStefan Weinhuber 
7774fa52aa7SStefan Weinhuber void dasd_profile_reset(struct dasd_profile *);
7784fa52aa7SStefan Weinhuber int dasd_profile_on(struct dasd_profile *);
7794fa52aa7SStefan Weinhuber void dasd_profile_off(struct dasd_profile *);
7804fa52aa7SStefan Weinhuber char *dasd_get_user_string(const char __user *, size_t);
78133b62a30SStefan Weinhuber 
7821da177e4SLinus Torvalds /* externals in dasd_devmap.c */
7831da177e4SLinus Torvalds extern int dasd_max_devindex;
7841da177e4SLinus Torvalds extern int dasd_probeonly;
7851da177e4SLinus Torvalds extern int dasd_autodetect;
78640545573SHorst Hummel extern int dasd_nopav;
787f3eb5384SStefan Weinhuber extern int dasd_nofcx;
7881da177e4SLinus Torvalds 
7891da177e4SLinus Torvalds int dasd_devmap_init(void);
7901da177e4SLinus Torvalds void dasd_devmap_exit(void);
7911da177e4SLinus Torvalds 
7921da177e4SLinus Torvalds struct dasd_device *dasd_create_device(struct ccw_device *);
7931da177e4SLinus Torvalds void dasd_delete_device(struct dasd_device *);
7941da177e4SLinus Torvalds 
795f24acd45SHorst Hummel int dasd_get_feature(struct ccw_device *, int);
796f24acd45SHorst Hummel int dasd_set_feature(struct ccw_device *, int, int);
797f24acd45SHorst Hummel 
7981da177e4SLinus Torvalds int dasd_add_sysfs_files(struct ccw_device *);
7991da177e4SLinus Torvalds void dasd_remove_sysfs_files(struct ccw_device *);
8001da177e4SLinus Torvalds 
8011da177e4SLinus Torvalds struct dasd_device *dasd_device_from_cdev(struct ccw_device *);
802a00bfd71SMartin Schwidefsky struct dasd_device *dasd_device_from_cdev_locked(struct ccw_device *);
8031da177e4SLinus Torvalds struct dasd_device *dasd_device_from_devindex(int);
8041da177e4SLinus Torvalds 
80565f8da47SStefan Weinhuber void dasd_add_link_to_gendisk(struct gendisk *, struct dasd_device *);
80665f8da47SStefan Weinhuber struct dasd_device *dasd_device_from_gendisk(struct gendisk *);
80765f8da47SStefan Weinhuber 
8083b1bea01SJan Höppner int dasd_parse(void) __init;
80969f90f6aSCornelia Huck int dasd_busid_known(const char *);
8101da177e4SLinus Torvalds 
8111da177e4SLinus Torvalds /* externals in dasd_gendisk.c */
8121da177e4SLinus Torvalds int  dasd_gendisk_init(void);
8131da177e4SLinus Torvalds void dasd_gendisk_exit(void);
8148e09f215SStefan Weinhuber int dasd_gendisk_alloc(struct dasd_block *);
8158e09f215SStefan Weinhuber void dasd_gendisk_free(struct dasd_block *);
8168e09f215SStefan Weinhuber int dasd_scan_partitions(struct dasd_block *);
8178e09f215SStefan Weinhuber void dasd_destroy_partitions(struct dasd_block *);
8181da177e4SLinus Torvalds 
8191da177e4SLinus Torvalds /* externals in dasd_ioctl.c */
82057a7c0bcSAl Viro int  dasd_ioctl(struct block_device *, fmode_t, unsigned int, unsigned long);
8211da177e4SLinus Torvalds 
8221da177e4SLinus Torvalds /* externals in dasd_proc.c */
8231da177e4SLinus Torvalds int dasd_proc_init(void);
8241da177e4SLinus Torvalds void dasd_proc_exit(void);
8251da177e4SLinus Torvalds 
8261da177e4SLinus Torvalds /* externals in dasd_erp.c */
8271da177e4SLinus Torvalds struct dasd_ccw_req *dasd_default_erp_action(struct dasd_ccw_req *);
8281da177e4SLinus Torvalds struct dasd_ccw_req *dasd_default_erp_postaction(struct dasd_ccw_req *);
8291da177e4SLinus Torvalds struct dasd_ccw_req *dasd_alloc_erp_request(char *, int, int,
8301da177e4SLinus Torvalds 					    struct dasd_device *);
8311da177e4SLinus Torvalds void dasd_free_erp_request(struct dasd_ccw_req *, struct dasd_device *);
8321da177e4SLinus Torvalds void dasd_log_sense(struct dasd_ccw_req *, struct irb *);
833fc19f381SStefan Haberland void dasd_log_sense_dbf(struct dasd_ccw_req *cqr, struct irb *irb);
8341da177e4SLinus Torvalds 
8351da177e4SLinus Torvalds /* externals in dasd_3990_erp.c */
8361da177e4SLinus Torvalds struct dasd_ccw_req *dasd_3990_erp_action(struct dasd_ccw_req *);
837f60c768cSStefan Haberland void dasd_3990_erp_handle_sim(struct dasd_device *, char *);
8381da177e4SLinus Torvalds 
83920c64468SStefan Weinhuber /* externals in dasd_eer.c */
84020c64468SStefan Weinhuber #ifdef CONFIG_DASD_EER
84120c64468SStefan Weinhuber int dasd_eer_init(void);
84220c64468SStefan Weinhuber void dasd_eer_exit(void);
84320c64468SStefan Weinhuber int dasd_eer_enable(struct dasd_device *);
84420c64468SStefan Weinhuber void dasd_eer_disable(struct dasd_device *);
84520c64468SStefan Weinhuber void dasd_eer_write(struct dasd_device *, struct dasd_ccw_req *cqr,
84620c64468SStefan Weinhuber 		    unsigned int id);
84720c64468SStefan Weinhuber void dasd_eer_snss(struct dasd_device *);
84820c64468SStefan Weinhuber 
84920c64468SStefan Weinhuber static inline int dasd_eer_enabled(struct dasd_device *device)
85020c64468SStefan Weinhuber {
85120c64468SStefan Weinhuber 	return device->eer_cqr != NULL;
85220c64468SStefan Weinhuber }
85320c64468SStefan Weinhuber #else
85420c64468SStefan Weinhuber #define dasd_eer_init()		(0)
85520c64468SStefan Weinhuber #define dasd_eer_exit()		do { } while (0)
85620c64468SStefan Weinhuber #define dasd_eer_enable(d)	(0)
85720c64468SStefan Weinhuber #define dasd_eer_disable(d)	do { } while (0)
85820c64468SStefan Weinhuber #define dasd_eer_write(d,c,i)	do { } while (0)
85920c64468SStefan Weinhuber #define dasd_eer_snss(d)	do { } while (0)
86020c64468SStefan Weinhuber #define dasd_eer_enabled(d)	(0)
86120c64468SStefan Weinhuber #endif	/* CONFIG_DASD_ERR */
86220c64468SStefan Weinhuber 
863c9346151SStefan Haberland 
864c9346151SStefan Haberland /* DASD path handling functions */
865c9346151SStefan Haberland 
866c9346151SStefan Haberland /*
867c9346151SStefan Haberland  * helper functions to modify bit masks for a given channel path for a device
868c9346151SStefan Haberland  */
869c9346151SStefan Haberland static inline int dasd_path_is_operational(struct dasd_device *device, int chp)
870c9346151SStefan Haberland {
871c9346151SStefan Haberland 	return test_bit(DASD_PATH_OPERATIONAL, &device->path[chp].flags);
872c9346151SStefan Haberland }
873c9346151SStefan Haberland 
874c9346151SStefan Haberland static inline int dasd_path_need_verify(struct dasd_device *device, int chp)
875c9346151SStefan Haberland {
876c9346151SStefan Haberland 	return test_bit(DASD_PATH_TBV, &device->path[chp].flags);
877c9346151SStefan Haberland }
878c9346151SStefan Haberland 
879c9346151SStefan Haberland static inline void dasd_path_verify(struct dasd_device *device, int chp)
880c9346151SStefan Haberland {
881c9346151SStefan Haberland 	__set_bit(DASD_PATH_TBV, &device->path[chp].flags);
882c9346151SStefan Haberland }
883c9346151SStefan Haberland 
884c9346151SStefan Haberland static inline void dasd_path_clear_verify(struct dasd_device *device, int chp)
885c9346151SStefan Haberland {
886c9346151SStefan Haberland 	__clear_bit(DASD_PATH_TBV, &device->path[chp].flags);
887c9346151SStefan Haberland }
888c9346151SStefan Haberland 
889c9346151SStefan Haberland static inline void dasd_path_clear_all_verify(struct dasd_device *device)
890c9346151SStefan Haberland {
891c9346151SStefan Haberland 	int chp;
892c9346151SStefan Haberland 
893c9346151SStefan Haberland 	for (chp = 0; chp < 8; chp++)
894c9346151SStefan Haberland 		dasd_path_clear_verify(device, chp);
895c9346151SStefan Haberland }
896c9346151SStefan Haberland 
897c9346151SStefan Haberland static inline void dasd_path_operational(struct dasd_device *device, int chp)
898c9346151SStefan Haberland {
899c9346151SStefan Haberland 	__set_bit(DASD_PATH_OPERATIONAL, &device->path[chp].flags);
900c9346151SStefan Haberland 	device->opm |= (0x80 >> chp);
901c9346151SStefan Haberland }
902c9346151SStefan Haberland 
903c9346151SStefan Haberland static inline void dasd_path_nonpreferred(struct dasd_device *device, int chp)
904c9346151SStefan Haberland {
905c9346151SStefan Haberland 	__set_bit(DASD_PATH_NPP, &device->path[chp].flags);
906c9346151SStefan Haberland }
907c9346151SStefan Haberland 
908c9346151SStefan Haberland static inline int dasd_path_is_nonpreferred(struct dasd_device *device, int chp)
909c9346151SStefan Haberland {
910c9346151SStefan Haberland 	return test_bit(DASD_PATH_NPP, &device->path[chp].flags);
911c9346151SStefan Haberland }
912c9346151SStefan Haberland 
913c9346151SStefan Haberland static inline void dasd_path_clear_nonpreferred(struct dasd_device *device,
914c9346151SStefan Haberland 						int chp)
915c9346151SStefan Haberland {
916c9346151SStefan Haberland 	__clear_bit(DASD_PATH_NPP, &device->path[chp].flags);
917c9346151SStefan Haberland }
918c9346151SStefan Haberland 
919c9346151SStefan Haberland static inline void dasd_path_preferred(struct dasd_device *device, int chp)
920c9346151SStefan Haberland {
921c9346151SStefan Haberland 	__set_bit(DASD_PATH_PP, &device->path[chp].flags);
922c9346151SStefan Haberland }
923c9346151SStefan Haberland 
924c9346151SStefan Haberland static inline int dasd_path_is_preferred(struct dasd_device *device, int chp)
925c9346151SStefan Haberland {
926c9346151SStefan Haberland 	return test_bit(DASD_PATH_PP, &device->path[chp].flags);
927c9346151SStefan Haberland }
928c9346151SStefan Haberland 
929c9346151SStefan Haberland static inline void dasd_path_clear_preferred(struct dasd_device *device,
930c9346151SStefan Haberland 					     int chp)
931c9346151SStefan Haberland {
932c9346151SStefan Haberland 	__clear_bit(DASD_PATH_PP, &device->path[chp].flags);
933c9346151SStefan Haberland }
934c9346151SStefan Haberland 
935c9346151SStefan Haberland static inline void dasd_path_clear_oper(struct dasd_device *device, int chp)
936c9346151SStefan Haberland {
937c9346151SStefan Haberland 	__clear_bit(DASD_PATH_OPERATIONAL, &device->path[chp].flags);
938c9346151SStefan Haberland 	device->opm &= ~(0x80 >> chp);
939c9346151SStefan Haberland }
940c9346151SStefan Haberland 
941c9346151SStefan Haberland static inline void dasd_path_clear_cable(struct dasd_device *device, int chp)
942c9346151SStefan Haberland {
943c9346151SStefan Haberland 	__clear_bit(DASD_PATH_MISCABLED, &device->path[chp].flags);
944c9346151SStefan Haberland }
945c9346151SStefan Haberland 
946c9346151SStefan Haberland static inline void dasd_path_cuir(struct dasd_device *device, int chp)
947c9346151SStefan Haberland {
948c9346151SStefan Haberland 	__set_bit(DASD_PATH_CUIR, &device->path[chp].flags);
949c9346151SStefan Haberland }
950c9346151SStefan Haberland 
951c9346151SStefan Haberland static inline int dasd_path_is_cuir(struct dasd_device *device, int chp)
952c9346151SStefan Haberland {
953c9346151SStefan Haberland 	return test_bit(DASD_PATH_CUIR, &device->path[chp].flags);
954c9346151SStefan Haberland }
955c9346151SStefan Haberland 
956c9346151SStefan Haberland static inline void dasd_path_clear_cuir(struct dasd_device *device, int chp)
957c9346151SStefan Haberland {
958c9346151SStefan Haberland 	__clear_bit(DASD_PATH_CUIR, &device->path[chp].flags);
959c9346151SStefan Haberland }
960c9346151SStefan Haberland 
961a521b048SStefan Haberland static inline void dasd_path_ifcc(struct dasd_device *device, int chp)
962a521b048SStefan Haberland {
963a521b048SStefan Haberland 	set_bit(DASD_PATH_IFCC, &device->path[chp].flags);
964a521b048SStefan Haberland }
965a521b048SStefan Haberland 
966a521b048SStefan Haberland static inline int dasd_path_is_ifcc(struct dasd_device *device, int chp)
967a521b048SStefan Haberland {
968a521b048SStefan Haberland 	return test_bit(DASD_PATH_IFCC, &device->path[chp].flags);
969a521b048SStefan Haberland }
970a521b048SStefan Haberland 
971a521b048SStefan Haberland static inline void dasd_path_clear_ifcc(struct dasd_device *device, int chp)
972a521b048SStefan Haberland {
973a521b048SStefan Haberland 	clear_bit(DASD_PATH_IFCC, &device->path[chp].flags);
974a521b048SStefan Haberland }
975a521b048SStefan Haberland 
976c9346151SStefan Haberland static inline void dasd_path_clear_nohpf(struct dasd_device *device, int chp)
977c9346151SStefan Haberland {
978c9346151SStefan Haberland 	__clear_bit(DASD_PATH_NOHPF, &device->path[chp].flags);
979c9346151SStefan Haberland }
980c9346151SStefan Haberland 
981c9346151SStefan Haberland static inline void dasd_path_miscabled(struct dasd_device *device, int chp)
982c9346151SStefan Haberland {
983c9346151SStefan Haberland 	__set_bit(DASD_PATH_MISCABLED, &device->path[chp].flags);
984c9346151SStefan Haberland }
985c9346151SStefan Haberland 
986c9346151SStefan Haberland static inline int dasd_path_is_miscabled(struct dasd_device *device, int chp)
987c9346151SStefan Haberland {
988c9346151SStefan Haberland 	return test_bit(DASD_PATH_MISCABLED, &device->path[chp].flags);
989c9346151SStefan Haberland }
990c9346151SStefan Haberland 
991c9346151SStefan Haberland static inline void dasd_path_nohpf(struct dasd_device *device, int chp)
992c9346151SStefan Haberland {
993c9346151SStefan Haberland 	__set_bit(DASD_PATH_NOHPF, &device->path[chp].flags);
994c9346151SStefan Haberland }
995c9346151SStefan Haberland 
996c9346151SStefan Haberland static inline int dasd_path_is_nohpf(struct dasd_device *device, int chp)
997c9346151SStefan Haberland {
998c9346151SStefan Haberland 	return test_bit(DASD_PATH_NOHPF, &device->path[chp].flags);
999c9346151SStefan Haberland }
1000c9346151SStefan Haberland 
1001c9346151SStefan Haberland /*
1002c9346151SStefan Haberland  * get functions for path masks
1003c9346151SStefan Haberland  * will return a path masks for the given device
1004c9346151SStefan Haberland  */
1005c9346151SStefan Haberland 
1006c9346151SStefan Haberland static inline __u8 dasd_path_get_opm(struct dasd_device *device)
1007c9346151SStefan Haberland {
1008c9346151SStefan Haberland 	return device->opm;
1009c9346151SStefan Haberland }
1010c9346151SStefan Haberland 
1011c9346151SStefan Haberland static inline __u8 dasd_path_get_tbvpm(struct dasd_device *device)
1012c9346151SStefan Haberland {
1013c9346151SStefan Haberland 	int chp;
1014c9346151SStefan Haberland 	__u8 tbvpm = 0x00;
1015c9346151SStefan Haberland 
1016c9346151SStefan Haberland 	for (chp = 0; chp < 8; chp++)
1017c9346151SStefan Haberland 		if (dasd_path_need_verify(device, chp))
1018c9346151SStefan Haberland 			tbvpm |= 0x80 >> chp;
1019c9346151SStefan Haberland 	return tbvpm;
1020c9346151SStefan Haberland }
1021c9346151SStefan Haberland 
1022c9346151SStefan Haberland static inline __u8 dasd_path_get_nppm(struct dasd_device *device)
1023c9346151SStefan Haberland {
1024c9346151SStefan Haberland 	int chp;
1025c9346151SStefan Haberland 	__u8 npm = 0x00;
1026c9346151SStefan Haberland 
1027c9346151SStefan Haberland 	for (chp = 0; chp < 8; chp++) {
1028c9346151SStefan Haberland 		if (dasd_path_is_nonpreferred(device, chp))
1029c9346151SStefan Haberland 			npm |= 0x80 >> chp;
1030c9346151SStefan Haberland 	}
1031c9346151SStefan Haberland 	return npm;
1032c9346151SStefan Haberland }
1033c9346151SStefan Haberland 
1034c9346151SStefan Haberland static inline __u8 dasd_path_get_ppm(struct dasd_device *device)
1035c9346151SStefan Haberland {
1036c9346151SStefan Haberland 	int chp;
1037c9346151SStefan Haberland 	__u8 ppm = 0x00;
1038c9346151SStefan Haberland 
1039c9346151SStefan Haberland 	for (chp = 0; chp < 8; chp++)
1040c9346151SStefan Haberland 		if (dasd_path_is_preferred(device, chp))
1041c9346151SStefan Haberland 			ppm |= 0x80 >> chp;
1042c9346151SStefan Haberland 	return ppm;
1043c9346151SStefan Haberland }
1044c9346151SStefan Haberland 
1045c9346151SStefan Haberland static inline __u8 dasd_path_get_cablepm(struct dasd_device *device)
1046c9346151SStefan Haberland {
1047c9346151SStefan Haberland 	int chp;
1048c9346151SStefan Haberland 	__u8 cablepm = 0x00;
1049c9346151SStefan Haberland 
1050c9346151SStefan Haberland 	for (chp = 0; chp < 8; chp++)
1051c9346151SStefan Haberland 		if (dasd_path_is_miscabled(device, chp))
1052c9346151SStefan Haberland 			cablepm |= 0x80 >> chp;
1053c9346151SStefan Haberland 	return cablepm;
1054c9346151SStefan Haberland }
1055c9346151SStefan Haberland 
1056c9346151SStefan Haberland static inline __u8 dasd_path_get_cuirpm(struct dasd_device *device)
1057c9346151SStefan Haberland {
1058c9346151SStefan Haberland 	int chp;
1059c9346151SStefan Haberland 	__u8 cuirpm = 0x00;
1060c9346151SStefan Haberland 
1061c9346151SStefan Haberland 	for (chp = 0; chp < 8; chp++)
1062c9346151SStefan Haberland 		if (dasd_path_is_cuir(device, chp))
1063c9346151SStefan Haberland 			cuirpm |= 0x80 >> chp;
1064c9346151SStefan Haberland 	return cuirpm;
1065c9346151SStefan Haberland }
1066c9346151SStefan Haberland 
1067a521b048SStefan Haberland static inline __u8 dasd_path_get_ifccpm(struct dasd_device *device)
1068a521b048SStefan Haberland {
1069a521b048SStefan Haberland 	int chp;
1070a521b048SStefan Haberland 	__u8 ifccpm = 0x00;
1071a521b048SStefan Haberland 
1072a521b048SStefan Haberland 	for (chp = 0; chp < 8; chp++)
1073a521b048SStefan Haberland 		if (dasd_path_is_ifcc(device, chp))
1074a521b048SStefan Haberland 			ifccpm |= 0x80 >> chp;
1075a521b048SStefan Haberland 	return ifccpm;
1076a521b048SStefan Haberland }
1077a521b048SStefan Haberland 
1078c9346151SStefan Haberland static inline __u8 dasd_path_get_hpfpm(struct dasd_device *device)
1079c9346151SStefan Haberland {
1080c9346151SStefan Haberland 	int chp;
1081c9346151SStefan Haberland 	__u8 hpfpm = 0x00;
1082c9346151SStefan Haberland 
1083c9346151SStefan Haberland 	for (chp = 0; chp < 8; chp++)
1084c9346151SStefan Haberland 		if (dasd_path_is_nohpf(device, chp))
1085c9346151SStefan Haberland 			hpfpm |= 0x80 >> chp;
1086c9346151SStefan Haberland 	return hpfpm;
1087c9346151SStefan Haberland }
1088c9346151SStefan Haberland 
1089c9346151SStefan Haberland /*
1090c9346151SStefan Haberland  * add functions for path masks
1091c9346151SStefan Haberland  * the existing path mask will be extended by the given path mask
1092c9346151SStefan Haberland  */
1093c9346151SStefan Haberland static inline void dasd_path_add_tbvpm(struct dasd_device *device, __u8 pm)
1094c9346151SStefan Haberland {
1095c9346151SStefan Haberland 	int chp;
1096c9346151SStefan Haberland 
1097c9346151SStefan Haberland 	for (chp = 0; chp < 8; chp++)
1098c9346151SStefan Haberland 		if (pm & (0x80 >> chp))
1099c9346151SStefan Haberland 			dasd_path_verify(device, chp);
1100c9346151SStefan Haberland }
1101c9346151SStefan Haberland 
1102a521b048SStefan Haberland static inline __u8 dasd_path_get_notoperpm(struct dasd_device *device)
1103a521b048SStefan Haberland {
1104a521b048SStefan Haberland 	int chp;
1105a521b048SStefan Haberland 	__u8 nopm = 0x00;
1106a521b048SStefan Haberland 
1107a521b048SStefan Haberland 	for (chp = 0; chp < 8; chp++)
1108a521b048SStefan Haberland 		if (dasd_path_is_nohpf(device, chp) ||
1109a521b048SStefan Haberland 		    dasd_path_is_ifcc(device, chp) ||
1110a521b048SStefan Haberland 		    dasd_path_is_cuir(device, chp) ||
1111a521b048SStefan Haberland 		    dasd_path_is_miscabled(device, chp))
1112a521b048SStefan Haberland 			nopm |= 0x80 >> chp;
1113a521b048SStefan Haberland 	return nopm;
1114a521b048SStefan Haberland }
1115a521b048SStefan Haberland 
1116c9346151SStefan Haberland static inline void dasd_path_add_opm(struct dasd_device *device, __u8 pm)
1117c9346151SStefan Haberland {
1118c9346151SStefan Haberland 	int chp;
1119c9346151SStefan Haberland 
1120c9346151SStefan Haberland 	for (chp = 0; chp < 8; chp++)
1121c9346151SStefan Haberland 		if (pm & (0x80 >> chp)) {
1122c9346151SStefan Haberland 			dasd_path_operational(device, chp);
1123c9346151SStefan Haberland 			/*
1124c9346151SStefan Haberland 			 * if the path is used
1125c9346151SStefan Haberland 			 * it should not be in one of the negative lists
1126c9346151SStefan Haberland 			 */
1127c9346151SStefan Haberland 			dasd_path_clear_nohpf(device, chp);
1128c9346151SStefan Haberland 			dasd_path_clear_cuir(device, chp);
1129c9346151SStefan Haberland 			dasd_path_clear_cable(device, chp);
1130a521b048SStefan Haberland 			dasd_path_clear_ifcc(device, chp);
1131c9346151SStefan Haberland 		}
1132c9346151SStefan Haberland }
1133c9346151SStefan Haberland 
1134c9346151SStefan Haberland static inline void dasd_path_add_cablepm(struct dasd_device *device, __u8 pm)
1135c9346151SStefan Haberland {
1136c9346151SStefan Haberland 	int chp;
1137c9346151SStefan Haberland 
1138c9346151SStefan Haberland 	for (chp = 0; chp < 8; chp++)
1139c9346151SStefan Haberland 		if (pm & (0x80 >> chp))
1140c9346151SStefan Haberland 			dasd_path_miscabled(device, chp);
1141c9346151SStefan Haberland }
1142c9346151SStefan Haberland 
1143c9346151SStefan Haberland static inline void dasd_path_add_cuirpm(struct dasd_device *device, __u8 pm)
1144c9346151SStefan Haberland {
1145c9346151SStefan Haberland 	int chp;
1146c9346151SStefan Haberland 
1147c9346151SStefan Haberland 	for (chp = 0; chp < 8; chp++)
1148c9346151SStefan Haberland 		if (pm & (0x80 >> chp))
1149c9346151SStefan Haberland 			dasd_path_cuir(device, chp);
1150c9346151SStefan Haberland }
1151c9346151SStefan Haberland 
1152a521b048SStefan Haberland static inline void dasd_path_add_ifccpm(struct dasd_device *device, __u8 pm)
1153a521b048SStefan Haberland {
1154a521b048SStefan Haberland 	int chp;
1155a521b048SStefan Haberland 
1156a521b048SStefan Haberland 	for (chp = 0; chp < 8; chp++)
1157a521b048SStefan Haberland 		if (pm & (0x80 >> chp))
1158a521b048SStefan Haberland 			dasd_path_ifcc(device, chp);
1159a521b048SStefan Haberland }
1160a521b048SStefan Haberland 
1161c9346151SStefan Haberland static inline void dasd_path_add_nppm(struct dasd_device *device, __u8 pm)
1162c9346151SStefan Haberland {
1163c9346151SStefan Haberland 	int chp;
1164c9346151SStefan Haberland 
1165c9346151SStefan Haberland 	for (chp = 0; chp < 8; chp++)
1166c9346151SStefan Haberland 		if (pm & (0x80 >> chp))
1167c9346151SStefan Haberland 			dasd_path_nonpreferred(device, chp);
1168c9346151SStefan Haberland }
1169c9346151SStefan Haberland 
1170c9346151SStefan Haberland static inline void dasd_path_add_nohpfpm(struct dasd_device *device, __u8 pm)
1171c9346151SStefan Haberland {
1172c9346151SStefan Haberland 	int chp;
1173c9346151SStefan Haberland 
1174c9346151SStefan Haberland 	for (chp = 0; chp < 8; chp++)
1175c9346151SStefan Haberland 		if (pm & (0x80 >> chp))
1176c9346151SStefan Haberland 			dasd_path_nohpf(device, chp);
1177c9346151SStefan Haberland }
1178c9346151SStefan Haberland 
1179c9346151SStefan Haberland static inline void dasd_path_add_ppm(struct dasd_device *device, __u8 pm)
1180c9346151SStefan Haberland {
1181c9346151SStefan Haberland 	int chp;
1182c9346151SStefan Haberland 
1183c9346151SStefan Haberland 	for (chp = 0; chp < 8; chp++)
1184c9346151SStefan Haberland 		if (pm & (0x80 >> chp))
1185c9346151SStefan Haberland 			dasd_path_preferred(device, chp);
1186c9346151SStefan Haberland }
1187c9346151SStefan Haberland 
1188c9346151SStefan Haberland /*
1189c9346151SStefan Haberland  * set functions for path masks
1190c9346151SStefan Haberland  * the existing path mask will be replaced by the given path mask
1191c9346151SStefan Haberland  */
1192c9346151SStefan Haberland static inline void dasd_path_set_tbvpm(struct dasd_device *device, __u8 pm)
1193c9346151SStefan Haberland {
1194c9346151SStefan Haberland 	int chp;
1195c9346151SStefan Haberland 
1196c9346151SStefan Haberland 	for (chp = 0; chp < 8; chp++)
1197c9346151SStefan Haberland 		if (pm & (0x80 >> chp))
1198c9346151SStefan Haberland 			dasd_path_verify(device, chp);
1199c9346151SStefan Haberland 		else
1200c9346151SStefan Haberland 			dasd_path_clear_verify(device, chp);
1201c9346151SStefan Haberland }
1202c9346151SStefan Haberland 
1203c9346151SStefan Haberland static inline void dasd_path_set_opm(struct dasd_device *device, __u8 pm)
1204c9346151SStefan Haberland {
1205c9346151SStefan Haberland 	int chp;
1206c9346151SStefan Haberland 
1207c9346151SStefan Haberland 	for (chp = 0; chp < 8; chp++) {
1208c9346151SStefan Haberland 		dasd_path_clear_oper(device, chp);
1209c9346151SStefan Haberland 		if (pm & (0x80 >> chp)) {
1210c9346151SStefan Haberland 			dasd_path_operational(device, chp);
1211c9346151SStefan Haberland 			/*
1212c9346151SStefan Haberland 			 * if the path is used
1213c9346151SStefan Haberland 			 * it should not be in one of the negative lists
1214c9346151SStefan Haberland 			 */
1215c9346151SStefan Haberland 			dasd_path_clear_nohpf(device, chp);
1216c9346151SStefan Haberland 			dasd_path_clear_cuir(device, chp);
1217c9346151SStefan Haberland 			dasd_path_clear_cable(device, chp);
1218a521b048SStefan Haberland 			dasd_path_clear_ifcc(device, chp);
1219c9346151SStefan Haberland 		}
1220c9346151SStefan Haberland 	}
1221c9346151SStefan Haberland }
1222c9346151SStefan Haberland 
1223c9346151SStefan Haberland /*
1224c9346151SStefan Haberland  * remove functions for path masks
1225c9346151SStefan Haberland  * the existing path mask will be cleared with the given path mask
1226c9346151SStefan Haberland  */
1227c9346151SStefan Haberland static inline void dasd_path_remove_opm(struct dasd_device *device, __u8 pm)
1228c9346151SStefan Haberland {
1229c9346151SStefan Haberland 	int chp;
1230c9346151SStefan Haberland 
1231c9346151SStefan Haberland 	for (chp = 0; chp < 8; chp++) {
1232c9346151SStefan Haberland 		if (pm & (0x80 >> chp))
1233c9346151SStefan Haberland 			dasd_path_clear_oper(device, chp);
1234c9346151SStefan Haberland 	}
1235c9346151SStefan Haberland }
1236c9346151SStefan Haberland 
1237c9346151SStefan Haberland /*
1238c9346151SStefan Haberland  * add the newly available path to the to be verified pm and remove it from
1239c9346151SStefan Haberland  * normal operation until it is verified
1240c9346151SStefan Haberland  */
1241c9346151SStefan Haberland static inline void dasd_path_available(struct dasd_device *device, int chp)
1242c9346151SStefan Haberland {
1243c9346151SStefan Haberland 	dasd_path_clear_oper(device, chp);
1244c9346151SStefan Haberland 	dasd_path_verify(device, chp);
1245c9346151SStefan Haberland }
1246c9346151SStefan Haberland 
1247c9346151SStefan Haberland static inline void dasd_path_notoper(struct dasd_device *device, int chp)
1248c9346151SStefan Haberland {
1249c9346151SStefan Haberland 	dasd_path_clear_oper(device, chp);
1250c9346151SStefan Haberland 	dasd_path_clear_preferred(device, chp);
1251c9346151SStefan Haberland 	dasd_path_clear_nonpreferred(device, chp);
1252c9346151SStefan Haberland }
1253c9346151SStefan Haberland 
1254c9346151SStefan Haberland /*
1255c9346151SStefan Haberland  * remove all paths from normal operation
1256c9346151SStefan Haberland  */
1257c9346151SStefan Haberland static inline void dasd_path_no_path(struct dasd_device *device)
1258c9346151SStefan Haberland {
1259c9346151SStefan Haberland 	int chp;
1260c9346151SStefan Haberland 
1261c9346151SStefan Haberland 	for (chp = 0; chp < 8; chp++)
1262c9346151SStefan Haberland 		dasd_path_notoper(device, chp);
1263c9346151SStefan Haberland 
1264c9346151SStefan Haberland 	dasd_path_clear_all_verify(device);
1265c9346151SStefan Haberland }
1266c9346151SStefan Haberland 
1267c9346151SStefan Haberland /* end - path handling */
1268c9346151SStefan Haberland 
12691da177e4SLinus Torvalds #endif				/* DASD_H */
1270