xref: /titanic_50/usr/src/uts/common/sys/mdi_impldefs.h (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #ifndef	_SYS_MDI_IMPLDEFS_H
28 #define	_SYS_MDI_IMPLDEFS_H
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 #include <sys/note.h>
33 #include <sys/sunmdi.h>
34 
35 #ifdef	__cplusplus
36 extern "C" {
37 #endif
38 
39 #ifdef _KERNEL
40 
41 /*
42  * Multipath Driver Interfaces
43  *
44  * The multipathing framework is provided in two modules.  The 'mpxio' misc.
45  * module provides the core multipath framework and the 'scsi_vhci' nexus
46  * driver provides the SCSI-III command set driver functionality for
47  * managing Fibre-Channel storage devices.
48  *
49  * As in any multipathing solution there are three major problems to solve:
50  *
51  * 1) Identification and enumeration of multipath client devices.
52  * 2) Optimal path selection when routing I/O requests.
53  * 3) Observability interfaces to snapshot the multipath configuration,
54  *    and infrastructure to provide performance and error statistics.
55  *
56  * The mpxio framework consists of several major components:
57  *
58  * 1) The MDI is the Multiplexed Device Interface; this is the core glue which
59  *    holds the following components together.
60  * 2) vHCI (Virtual Host Controller Interconnect) drivers provide multipathing
61  *    services for a given bus technology (example: 'scsi_vhci' provides
62  *    multipathing support for SCSI-III fibre-channel devices).
63  * 3) pHCI (Physical Host Controller Interconnect) drivers provide transport
64  *    services for a given host controller (example: 'fcp' provides transport
65  *    for fibre-channel devices).
66  * 4) Client Devices are standard Solaris target (or leaf) drivers
67  *    (example: 'ssd' is the standard disk driver for fibre-channel arrays).
68  * 5) Multipath information nodes ('pathinfo' nodes) connect client device
69  *    nodes and pHCI device nodes in the device tree.
70  *
71  * With the scsi_vhci, a QLC card, and mpxio enabled, the device tree might
72  * look like this:
73  *
74  *	+-----------+   +-----------+
75  *      | scsi_vhci |   |  pci@1f,0 |
76  *      +-----------+   +-----------+
77  *         /     \               \
78  * +----------+ +-----------+    +-------------+
79  * | ssd1     | | ssd2	    |    | qlc@0,0     |
80  * +----------+ +-----------+    +-------------+
81  *   |          |                  /        \
82  *   |          |        +-------------+   +------------+
83  *   |          |        | pHCI 1      |   |  pHCI 2    |
84  *   |          |        +-------------+   +------------+
85  *   |          |          /        |      /          |
86  *   |          |    +------+       |    +------+     |
87  *   |          |    |  ssd |       |    |  ssd |     |
88  *   |          |    | (OBP)|       |    | (OBP)|     |
89  *   |          |    +------+       |    +------+     |
90  *   |          |                   |                 |
91  *   |          |               +-------+           +--------+
92  *   |          +-------------->| path  |---------->| path   |
93  *   |                          | info  |           | info   |
94  *   |                          | node 1|           | node 3 |
95  *   |                          +-------+           +--------+
96  *   |                              |                 |
97  *   |                          +-------+           +--------+
98  *   +------------------------->| path  |---------->| path   |
99  *                              | info  |           | info   |
100  *                              | node 2|           | node 4 |
101  *                              +-------+           +--------+
102  *
103  * The multipath information nodes (mdi_pathinfo nodes) establish the
104  * relationship between the pseudo client driver instance nodes and the
105  * physical host controller interconnect (pHCI drivers) forming a matrix
106  * structure.
107  *
108  * The mpxio module implements locking at multiple granularity levels to
109  * support the needs of various consumers.  The multipath matrix can be
110  * globally locked, column locked, or row locked depending on the consumer.
111  * The intention is to balance simplicity and performance.
112  *
113  * Locking:
114  *
115  * The current implementation utilizes the following locks:
116  *
117  *   mdi_mutex: protects the vHCI list, per-vHCI structure and the
118  *   list of pHCIs and Client devices registered against them (protection
119  *   against multi-threaded add/remove).
120  *
121  *   devinfo_tree_lock (rw): protects system wide creation/removal of
122  *   mdi_pathinfo nodes into the multipath matrix.  Consumers (like the devinfo
123  *   driver) can freeze the configuration by acquiring this as a reader.
124  *
125  *   per-pHCI (mutex) lock: protects the column (pHCI-mdi_pathinfo node list)
126  *   and per-pHCI structure fields.  mdi_pathinfo node creation, deletion and
127  *   child mdi_pathinfo node state changes are serialized on per pHCI basis
128  *   (Protection against DR).
129  *
130  *   per-client (mutex) lock: protects the row (client-mdi_pathinfo node list)
131  *   and per-client structure fields.  The client-mdi_pathinfo node list is
132  *   typically walked to select an optimal path when routing I/O requests.
133  *
134  *   per-mdi_pathinfo (mutex) lock: protects the mdi_pathinfo node structure
135  *   fields.
136  *
137  * Note that per-Client structure and per-pHCI fields are freely readable when
138  * corresponding mdi_pathinfo locks are held, since holding an mdi_pathinfo
139  * node guarantees that its corresponding client and pHCI devices will not be
140  * freed.
141  */
142 
143 /*
144  * MDI Client global unique identifier property name string definition
145  */
146 extern const char			*mdi_client_guid_prop;
147 #define	MDI_CLIENT_GUID_PROP		(char *)mdi_client_guid_prop
148 
149 /*
150  * MDI Client load balancing policy definitions
151  *
152  * Load balancing policies are determined on a per-vHCI basis and are
153  * configurable via the vHCI's driver.conf file.
154  */
155 typedef enum {
156 	LOAD_BALANCE_NONE,		/* Alternate pathing		*/
157 	LOAD_BALANCE_RR,		/* Round Robin			*/
158 	LOAD_BALANCE_LBA		/* Logical Block Addressing	*/
159 } client_lb_t;
160 
161 typedef struct {
162 	int region_size;
163 }client_lb_args_t;
164 
165 /*
166  * MDI client load balancing property name/value string definitions
167  */
168 extern const char			*mdi_load_balance;
169 extern const char			*mdi_load_balance_none;
170 extern const char			*mdi_load_balance_ap;
171 extern const char			*mdi_load_balance_rr;
172 extern const char			*mdi_load_balance_lba;
173 
174 #define	LOAD_BALANCE_PROP		(char *)mdi_load_balance
175 #define	LOAD_BALANCE_PROP_NONE		(char *)mdi_load_balance_none
176 #define	LOAD_BALANCE_PROP_AP		(char *)mdi_load_balance_ap
177 #define	LOAD_BALANCE_PROP_RR		(char *)mdi_load_balance_rr
178 #define	LOAD_BALANCE_PROP_LBA		(char *)mdi_load_balance_lba
179 
180 /* default for region size */
181 #define	LOAD_BALANCE_DEFAULT_REGION_SIZE	18
182 
183 /*
184  * vHCI drivers:
185  *
186  * vHCI drivers are pseudo nexus drivers which implement multipath services
187  * for a specific command set or bus architecture ('class').  There is a
188  * single instance of the vHCI driver for each command set which supports
189  * multipath devices.
190  *
191  * Each vHCI driver registers the following callbacks from attach(9e).
192  */
193 #define	MDI_VHCI_OPS_REV_1		1
194 /*
195  * Change MDI_VHCI_OPS_REV_NAME as per MDI_VHCI_OPS_REV
196  */
197 #define	MDI_VHCI_OPS_REV	MDI_VHCI_OPS_REV_1
198 #define	MDI_VHCI_OPS_REV_NAME	"1"
199 
200 typedef struct mdi_vhci_ops {
201 	/* revision management */
202 	int	vo_revision;
203 
204 	/* mdi_pathinfo node init callback */
205 	int	(*vo_pi_init)(dev_info_t *vdip, mdi_pathinfo_t *pip, int flags);
206 
207 	/* mdi_pathinfo node uninit callback */
208 	int	(*vo_pi_uninit)(dev_info_t *vdip, mdi_pathinfo_t *pip,
209 		    int flags);
210 
211 	/* mdi_pathinfo node state change callback */
212 	int	(*vo_pi_state_change)(dev_info_t *vdip, mdi_pathinfo_t *pip,
213 		    mdi_pathinfo_state_t state, uint32_t, int flags);
214 
215 	/* Client path failover callback */
216 	int	(*vo_failover)(dev_info_t *vdip, dev_info_t *cdip, int flags);
217 } mdi_vhci_ops_t;
218 
219 /*
220  * phci bus config structure - one for for each phci bus config operation that
221  * we initiate on behalf of a vhci.
222  */
223 typedef struct mdi_phci_config {
224 	struct mdi_vhci_config	*phc_vhc;	/* vhci bus config */
225 	struct mdi_phci_config	*phc_next;	/* next one on this list */
226 	dev_info_t	*phc_parent_dip;	/* parent of the phci */
227 	char		phc_devnm[MAXNAMELEN];	/* /name@addr of the phci */
228 } mdi_phci_config_t;
229 
230 /* vhci bus config structure - one for vhci instance */
231 typedef struct mdi_vhci_config {
232 	volatile ddi_bus_config_op_t vhc_op;	/* bus config - op type */
233 	major_t			vhc_major;	/* bus config - major */
234 	int			vhc_flags;	/* bus config - flags */
235 	volatile int64_t	vhc_start_time;	/* bus config start time */
236 	int64_t			vhc_cutoff_time; /* end time + some timeout */
237 	taskq_t			*vhc_taskq;
238 	kcondvar_t		vhc_cv;		/* mutex is mdi_mutex */
239 	mdi_phci_config_t	*vhc_phc;	/* phci bus config list */
240 	int			vhc_phc_cnt;	/* # of phcs on vhc_phc list */
241 } mdi_vhci_config_t;
242 
243 /*
244  * An mdi_vhci structure is created and bound to the devinfo node of every
245  * registered vHCI class driver; this happens when a vHCI registers itself from
246  * attach(9e).  This structure is unbound and freed when the vHCI unregisters
247  * at detach(9e) time;
248  *
249  * Each vHCI driver is associated with a vHCI class name; this is the handle
250  * used to register and unregister pHCI drivers for a given transport.
251  *
252  * Locking: This structure is guarded by the mdi_mutex; however, depending
253  * on the context, some of the fields can be freely read without holding any
254  * locks (ex. holding a child's lock also guarantees that the vHCI (parent)
255  * cannot be unexpectedly freed).
256  */
257 typedef struct mdi_vhci {
258 	struct mdi_vhci		*vh_next;	/* next link		*/
259 	struct mdi_vhci		*vh_prev;	/* prev link		*/
260 	int			vh_flags;	/* Operation flags	*/
261 	dev_info_t		*vh_dip;	/* devi handle		*/
262 	char			*vh_class;	/* Class name		*/
263 	struct mdi_vhci_ops	*vh_ops;	/* Callback vectors	*/
264 	client_lb_t		vh_lb;		/* Global cache		*/
265 	int			vh_phci_count;	/* pHCI device count	*/
266 	struct mdi_phci		*vh_phci_head;	/* pHCI list head	*/
267 	struct mdi_phci		*vh_phci_tail;	/* pHCI list tail	*/
268 	int			vh_client_count;	/* Client count	*/
269 	struct client_hash	*vh_client_table;	/* Client hash	*/
270 	mdi_vhci_config_t	vh_bus_config;
271 } mdi_vhci_t;
272 
273 /*
274  * GUID Hash definitions
275  *
276  * Since all the mpxio managed devices for a given class are enumerated under
277  * the single vHCI instance for that class, sequentially walking through the
278  * client device link to find a client would be prohibitively slow.
279  */
280 
281 #define	CLIENT_HASH_TABLE_SIZE	(32)	/* GUID hash */
282 
283 /*
284  * Client hash table structure
285  */
286 struct client_hash {
287 	struct mdi_client	*ct_hash_head;	/* Client hash head	*/
288 	int			ct_hash_count;	/* Client hash count	*/
289 };
290 
291 
292 /*
293  * pHCI Drivers:
294  *
295  * Physical HBA drivers provide transport services for mpxio-managed devices.
296  * As each pHCI instance is attached, it must register itself with the mpxio
297  * framework using mdi_phci_register().  When the pHCI is detached it must
298  * similarly call mdi_phci_unregister().
299  *
300  * The framework maintains a list of registered pHCI device instances for each
301  * vHCI.  This list is vHCI->vh_phci_count, vHCI->vh_phci_head,
302  * vHCI->vh_phci_tail and pHCI->ph_next.  This list is protected by the global
303  * mdi_mutex.
304  *
305  * Locking order:
306  *
307  * _NOTE(LOCK_ORDER(mdi_mutex, mdi_phci::ph_mutex))
308  * _NOTE(LOCK_ORDER(mdi_phci::ph_mutex devinfo_tree_lock))
309  */
310 typedef struct mdi_phci {
311 	kmutex_t		ph_mutex;	/* per-pHCI mutex	*/
312 	struct mdi_phci		*ph_next;	/* next link		*/
313 	struct mdi_phci		*ph_prev;	/* prev link		*/
314 	dev_info_t		*ph_dip;	/* devi handle		*/
315 	struct mdi_vhci 	*ph_vhci;	/* back ref. to vHCI	*/
316 	int			ph_flags;	/* pHCI operation flags	*/
317 	int			ph_path_count;	/* child pi count	*/
318 	mdi_pathinfo_t		*ph_path_head;	/* pi list head		*/
319 	mdi_pathinfo_t		*ph_path_tail;	/* pi list tail		*/
320 	int			ph_unstable;	/* Paths in transient state */
321 	kcondvar_t		ph_unstable_cv;	/* Paths in transient state */
322 	kcondvar_t		ph_powerchange_cv;
323 						/* Paths in transient state */
324 	void			*ph_vprivate;	/* vHCI driver private	*/
325 } mdi_phci_t;
326 
327 /*
328  * A pHCI device is 'unstable' while one or more paths are in a transitional
329  * state.  Hotplugging is prevented during this state.
330  */
331 #define	MDI_PHCI_UNSTABLE(ph)		(ph)->ph_unstable++;
332 #define	MDI_PHCI_STABLE(ph) { \
333 	(ph)->ph_unstable--; \
334 	if ((ph)->ph_unstable == 0) { \
335 		cv_broadcast(&(ph)->ph_unstable_cv); \
336 	} \
337 }
338 
339 /*
340  * per-pHCI lock macros
341  */
342 #define	MDI_PHCI_LOCK(ph)		mutex_enter(&((ph))->ph_mutex)
343 #define	MDI_PHCI_TRYLOCK(ph)		mutex_tryenter(&((ph))->ph_mutex)
344 #define	MDI_PHCI_UNLOCK(ph)		mutex_exit(&((ph))->ph_mutex)
345 
346 /*
347  * pHCI state definitions and macros to track the pHCI driver instance state
348  */
349 #define	MDI_PHCI_FLAGS_OFFLINE		0x1	/* pHCI is offline */
350 #define	MDI_PHCI_FLAGS_SUSPEND		0x2	/* pHCI is suspended */
351 #define	MDI_PHCI_FLAGS_POWER_DOWN	0x4	/* pHCI is power down */
352 #define	MDI_PHCI_FLAGS_DETACH		0x8	/* pHCI is detached */
353 #define	MDI_PHCI_FLAGS_USER_DISABLE	0x10	/* pHCI is disabled,user */
354 #define	MDI_PHCI_FLAGS_D_DISABLE	0x20	/* pHCI is disabled,driver */
355 #define	MDI_PHCI_FLAGS_D_DISABLE_TRANS	0x40	/* pHCI is disabled,transient */
356 #define	MDI_PHCI_FLAGS_POWER_TRANSITION	0x80	/* pHCI is power transition */
357 
358 #define	MDI_PHCI_DISABLE_MASK	(~(MDI_PHCI_FLAGS_USER_DISABLE | \
359 				MDI_PHCI_FLAGS_D_DISABLE | \
360 				MDI_PHCI_FLAGS_D_DISABLE_TRANS))
361 #define	MDI_PHCI_IS_READY(ph) \
362 	(((ph)->ph_flags &  (MDI_PHCI_DISABLE_MASK)) == 0)
363 
364 #define	MDI_PHCI_SET_OFFLINE(ph) \
365 	    ((ph)->ph_flags |= MDI_PHCI_FLAGS_OFFLINE)
366 
367 #define	MDI_PHCI_SET_ONLINE(ph) \
368 	    ((ph)->ph_flags &= ~MDI_PHCI_FLAGS_OFFLINE)
369 
370 #define	MDI_PHCI_SET_SUSPEND(ph) \
371 	    ((ph)->ph_flags |= MDI_PHCI_FLAGS_SUSPEND)
372 
373 #define	MDI_PHCI_SET_RESUME(ph) \
374 	    ((ph)->ph_flags &= ~MDI_PHCI_FLAGS_SUSPEND)
375 
376 #define	MDI_PHCI_IS_OFFLINE(ph) \
377 	    ((ph)->ph_flags & MDI_PHCI_FLAGS_OFFLINE)
378 
379 #define	MDI_PHCI_IS_SUSPENDED(ph) \
380 	    ((ph)->ph_flags & MDI_PHCI_FLAGS_SUSPEND)
381 
382 #define	MDI_PHCI_SET_DETACH(ph) \
383 	    ((ph)->ph_flags |= MDI_PHCI_FLAGS_DETACH)
384 
385 #define	MDI_PHCI_SET_ATTACH(ph) \
386 	    ((ph)->ph_flags &= ~MDI_PHCI_FLAGS_DETACH)
387 
388 #define	MDI_PHCI_SET_POWER_DOWN(ph) \
389 	    ((ph)->ph_flags |= MDI_PHCI_FLAGS_POWER_DOWN)
390 
391 #define	MDI_PHCI_SET_POWER_UP(ph) \
392 	    ((ph)->ph_flags &= ~MDI_PHCI_FLAGS_POWER_DOWN)
393 
394 #define	MDI_PHCI_SET_USER_ENABLE(ph) \
395 		((ph)->ph_flags &= ~MDI_PHCI_FLAGS_USER_DISABLE)
396 
397 #define	MDI_PHCI_SET_USER_DISABLE(ph) \
398 		((ph)->ph_flags |= MDI_PHCI_FLAGS_USER_DISABLE)
399 
400 #define	MDI_PHCI_SET_DRV_ENABLE(ph)	\
401 		((ph)->ph_flags &= ~MDI_PHCI_FLAGS_D_DISABLE)
402 
403 #define	MDI_PHCI_SET_DRV_DISABLE(ph)	\
404 		((ph)->ph_flags |= MDI_PHCI_FLAGS_D_DISABLE)
405 
406 #define	MDI_PHCI_SET_DRV_ENABLE_TRANSIENT(ph)	\
407 		((ph)->ph_flags &= ~MDI_PHCI_FLAGS_D_DISABLE_TRANS)
408 
409 #define	MDI_PHCI_SET_DRV_DISABLE_TRANSIENT(ph)	\
410 		((ph)->ph_flags |= MDI_PHCI_FLAGS_D_DISABLE_TRANS)
411 
412 #define	MDI_PHCI_IS_USER_DISABLED(ph) \
413 		((ph)->ph_flags & MDI_PHCI_FLAGS_USER_DISABLE)
414 
415 #define	MDI_PHCI_IS_DRV_DISABLED_TRANSIENT(ph)	\
416 		((ph)->ph_flags & MDI_PHCI_FLAGS_D_DISABLE_TRANS)
417 
418 #define	MDI_PHCI_IS_DRV_DISABLED(ph)	\
419 		((ph)->ph_flags & MDI_PHCI_FLAGS_D_DISABLE)
420 
421 #define	MDI_PHCI_IS_POWERED_DOWN(ph) \
422 	    ((ph)->ph_flags & MDI_PHCI_FLAGS_POWER_DOWN)
423 
424 #define	MDI_PHCI_SET_POWER_TRANSITION(ph) \
425 	    ((ph)->ph_flags |= MDI_PHCI_FLAGS_POWER_TRANSITION)
426 
427 #define	MDI_PHCI_CLEAR_POWER_TRANSITION(ph) \
428 	    ((ph)->ph_flags &= ~MDI_PHCI_FLAGS_POWER_TRANSITION)
429 
430 #define	MDI_PHCI_IS_POWER_TRANSITION(ph) \
431 	    ((ph)->ph_flags & MDI_PHCI_FLAGS_POWER_TRANSITION)
432 
433 /*
434  * mpxio Managed Clients:
435  *
436  * This framework creates a struct mdi_client for every client device created
437  * by the framework as a result of self-enumeration of target devices by the
438  * registered pHCI devices.  This structure is bound to client device dev_info
439  * node at the time of client device allocation (ndi_devi_alloc(9e)). This
440  * structure is unbound from the dev_info node when mpxio framework removes a
441  * client device node from the system.
442  *
443  * This structure is created when a first path is enumerated and removed when
444  * last path is de-enumerated from the system.
445  *
446  * Multipath client devices are instantiated as children of corresponding vHCI
447  * driver instance. Each client device is uniquely identified by a GUID
448  * provided by target device itself.  The parent vHCI device also maintains a
449  * hashed list of client devices, protected by the global mdi_mutex.
450  *
451  * Typically pHCI devices self-enumerate their child devices using taskq,
452  * resulting in multiple paths to the same client device to be enumerated by
453  * competing threads.  mdi_mutex is also used to serialize the client device
454  * creation.
455  *
456  * Currently this framework supports two kinds of load-balancing policy
457  * configurable through the vHCI driver configuration files.
458  *
459  * NONE		- Legacy AP mode
460  * Round Robin	- Balance the pHCI load in a Round Robin fashion.
461  *
462  * This framework identifies the client device in three distinct states:
463  *
464  * OPTIMAL	- Client device has atleast one redundant path.
465  * DEGRADED	- No redundant paths (critical).  Failure in the current active
466  *                path would result in data access failures.
467  * FAILED 	- No paths are available to access this device.
468  *
469  * Locking order:
470  *
471  * _NOTE(LOCK_ORDER(mdi_mutex, mdi_client::ct_mutex))
472  * _NOTE(LOCK_ORDER(mdi_client::ct_mutex devinfo_tree_lock))
473  */
474 typedef struct mdi_client {
475 	kmutex_t		ct_mutex;	/* per-client mutex	*/
476 	struct mdi_client	*ct_hnext;	/* next client		*/
477 	struct mdi_client	*ct_hprev;	/* prev client		*/
478 	dev_info_t		*ct_dip;	/* client devi handle	*/
479 	struct mdi_vhci		*ct_vhci;	/* vHCI back ref	*/
480 	char			*ct_drvname;	/* client driver name	*/
481 	char			*ct_guid;	/* client guid		*/
482 	void			*ct_cprivate;	/* client driver private */
483 	client_lb_t		ct_lb;		/* load balancing scheme */
484 	client_lb_args_t	*ct_lb_args; 	/* load balancing args */
485 	int			ct_flags;	/* Driver op. flags	*/
486 	int			ct_state;	/* state information	*/
487 	int			ct_failover_flags;	/* Failover args */
488 	int			ct_failover_status;	/* last fo status */
489 	kcondvar_t		ct_failover_cv;	/* Failover status cv	*/
490 	int			ct_path_count;	/* multi path count	*/
491 	mdi_pathinfo_t		*ct_path_head;	/* multi path list head	*/
492 	mdi_pathinfo_t		*ct_path_tail;	/* multi path list tail	*/
493 	mdi_pathinfo_t		*ct_path_last;	/* last path used for i/o */
494 	int			ct_unstable;	/* Paths in transient state */
495 	kcondvar_t		ct_unstable_cv;	/* Paths in transient state */
496 	int			ct_power_cnt;	/* Hold count on parent power */
497 	kcondvar_t		ct_powerchange_cv;
498 					/* Paths in power transient state */
499 	int			ct_powercnt_held;
500 					/* ct_power_cnt held in pre_unconfig */
501 	int			ct_powercnt_reset;
502 					/* ct_power_cnt was resetted */
503 	void			*ct_vprivate;	/* vHCI driver private	*/
504 } mdi_client_t;
505 
506 /*
507  * per-Client device locking definitions
508  */
509 #define	MDI_CLIENT_LOCK(ct)		mutex_enter(&((ct))->ct_mutex)
510 #define	MDI_CLIENT_TRYLOCK(ct)		mutex_tryenter(&((ct))->ct_mutex)
511 #define	MDI_CLIENT_UNLOCK(ct)		mutex_exit(&((ct))->ct_mutex)
512 
513 /*
514  * A Client device is in unstable while one or more paths are in transitional
515  * state.  We do not allow failover to take place while paths are in transient
516  * state. Similarly we do not allow state transition while client device
517  * failover is in progress.
518  */
519 #define	MDI_CLIENT_UNSTABLE(ct)		(ct)->ct_unstable++;
520 #define	MDI_CLIENT_STABLE(ct) { \
521 	(ct)->ct_unstable--; \
522 	if ((ct)->ct_unstable == 0) { \
523 		cv_broadcast(&(ct)->ct_unstable_cv); \
524 	} \
525 }
526 
527 /*
528  * Client driver instance state definitions:
529  */
530 #define	MDI_CLIENT_FLAGS_OFFLINE		0x00000001
531 #define	MDI_CLIENT_FLAGS_SUSPEND		0x00000002
532 #define	MDI_CLIENT_FLAGS_POWER_DOWN		0x00000004
533 #define	MDI_CLIENT_FLAGS_DETACH			0x00000008
534 #define	MDI_CLIENT_FLAGS_FAILOVER		0x00000010
535 #define	MDI_CLIENT_FLAGS_REPORT_DEV		0x00000020
536 #define	MDI_CLIENT_FLAGS_PATH_FREE_IN_PROGRESS	0x00000040
537 #define	MDI_CLIENT_FLAGS_ASYNC_FREE		0x00000080
538 #define	MDI_CLIENT_FLAGS_DEV_NOT_SUPPORTED	0x00000100
539 #define	MDI_CLIENT_FLAGS_POWER_TRANSITION	0x00000200
540 
541 #define	MDI_CLIENT_SET_OFFLINE(ct) \
542 	    ((ct)->ct_flags |= MDI_CLIENT_FLAGS_OFFLINE)
543 
544 #define	MDI_CLIENT_SET_ONLINE(ct) \
545 	    ((ct)->ct_flags &= ~MDI_CLIENT_FLAGS_OFFLINE)
546 
547 #define	MDI_CLIENT_IS_OFFLINE(ct) \
548 	    ((ct)->ct_flags & MDI_CLIENT_FLAGS_OFFLINE)
549 
550 #define	MDI_CLIENT_SET_SUSPEND(ct) \
551 	    ((ct)->ct_flags |= MDI_CLIENT_FLAGS_SUSPEND)
552 
553 #define	MDI_CLIENT_SET_RESUME(ct) \
554 	    ((ct)->ct_flags &= ~MDI_CLIENT_FLAGS_SUSPEND)
555 
556 #define	MDI_CLIENT_IS_SUSPENDED(ct) \
557 	    ((ct)->ct_flags & MDI_CLIENT_FLAGS_SUSPEND)
558 
559 #define	MDI_CLIENT_SET_POWER_DOWN(ct) \
560 	    ((ct)->ct_flags |= MDI_CLIENT_FLAGS_POWER_DOWN)
561 
562 #define	MDI_CLIENT_SET_POWER_UP(ct) \
563 	    ((ct)->ct_flags &= ~MDI_CLIENT_FLAGS_POWER_DOWN)
564 
565 #define	MDI_CLIENT_IS_POWERED_DOWN(ct) \
566 	    ((ct)->ct_flags & MDI_CLIENT_FLAGS_POWER_DOWN)
567 
568 #define	MDI_CLIENT_SET_POWER_TRANSITION(ct) \
569 	    ((ct)->ct_flags |= MDI_CLIENT_FLAGS_POWER_TRANSITION)
570 
571 #define	MDI_CLIENT_CLEAR_POWER_TRANSITION(ct) \
572 	    ((ct)->ct_flags &= ~MDI_CLIENT_FLAGS_POWER_TRANSITION)
573 
574 #define	MDI_CLIENT_IS_POWER_TRANSITION(ct) \
575 	    ((ct)->ct_flags & MDI_CLIENT_FLAGS_POWER_TRANSITION)
576 
577 #define	MDI_CLIENT_SET_DETACH(ct) \
578 	    ((ct)->ct_flags |= MDI_CLIENT_FLAGS_DETACH)
579 
580 #define	MDI_CLIENT_SET_ATTACH(ct) \
581 	    ((ct)->ct_flags &= ~MDI_CLIENT_FLAGS_DETACH)
582 
583 #define	MDI_CLIENT_IS_DETACHED(ct) \
584 	    ((ct)->ct_flags & MDI_CLIENT_FLAGS_DETACH)
585 
586 #define	MDI_CLIENT_SET_FAILOVER_IN_PROGRESS(ct) \
587 	    ((ct)->ct_flags |= MDI_CLIENT_FLAGS_FAILOVER)
588 
589 #define	MDI_CLIENT_CLEAR_FAILOVER_IN_PROGRESS(ct) \
590 	    ((ct)->ct_flags &= ~MDI_CLIENT_FLAGS_FAILOVER)
591 
592 #define	MDI_CLIENT_IS_FAILOVER_IN_PROGRESS(ct) \
593 	    ((ct)->ct_flags & MDI_CLIENT_FLAGS_FAILOVER)
594 
595 #define	MDI_CLIENT_SET_REPORT_DEV_NEEDED(ct) \
596 	    ((ct)->ct_flags |= MDI_CLIENT_FLAGS_REPORT_DEV)
597 
598 #define	MDI_CLIENT_CLEAR_REPORT_DEV_NEEDED(ct) \
599 	    ((ct)->ct_flags &= ~MDI_CLIENT_FLAGS_REPORT_DEV)
600 
601 #define	MDI_CLIENT_IS_REPORT_DEV_NEEDED(ct) \
602 	    ((ct)->ct_flags & MDI_CLIENT_FLAGS_REPORT_DEV)
603 
604 #define	MDI_CLIENT_SET_PATH_FREE_IN_PROGRESS(ct) \
605 	    ((ct)->ct_flags |= MDI_CLIENT_FLAGS_PATH_FREE_IN_PROGRESS)
606 
607 #define	MDI_CLIENT_CLEAR_PATH_FREE_IN_PROGRESS(ct) \
608 	    ((ct)->ct_flags &= ~MDI_CLIENT_FLAGS_PATH_FREE_IN_PROGRESS)
609 
610 #define	MDI_CLIENT_IS_PATH_FREE_IN_PROGRESS(ct) \
611 	    ((ct)->ct_flags & MDI_CLIENT_FLAGS_PATH_FREE_IN_PROGRESS)
612 
613 #define	MDI_CLIENT_SET_DEV_NOT_SUPPORTED(ct) \
614 	    ((ct)->ct_flags |= MDI_CLIENT_FLAGS_DEV_NOT_SUPPORTED)
615 
616 #define	MDI_CLIENT_IS_DEV_NOT_SUPPORTED(ct) \
617 	    ((ct)->ct_flags & MDI_CLIENT_FLAGS_DEV_NOT_SUPPORTED)
618 
619 /*
620  * Client operating states.
621  */
622 #define	MDI_CLIENT_STATE_OPTIMAL	1
623 #define	MDI_CLIENT_STATE_DEGRADED	2
624 #define	MDI_CLIENT_STATE_FAILED		3
625 
626 #define	MDI_CLIENT_STATE(ct) ((ct)->ct_state)
627 #define	MDI_CLIENT_SET_STATE(ct, state) ((ct)->ct_state = state)
628 
629 #define	MDI_CLIENT_IS_FAILED(ct) \
630 	    ((ct)->ct_state == MDI_CLIENT_STATE_FAILED)
631 
632 /*
633  * mdi_pathinfo nodes:
634  *
635  * From this framework's perspective, a 'path' is a tuple consisting of a
636  * client or end device, a host controller which provides device
637  * identification and transport services (pHCI), and bus specific unit
638  * addressing information.  A path may be decorated with properties which
639  * describe the capabilities of the path; such properties are analogous to
640  * device node and minor node properties.
641  *
642  * The framework maintains link list of mdi_pathinfo nodes created by every
643  * pHCI driver instance via the pi_phci_link linkage; this is used (for example)
644  * to make sure that all relevant pathinfo nodes are freed before the pHCI
645  * is unregistered.
646  *
647  * Locking order:
648  *
649  * _NOTE(LOCK_ORDER(mdi_phci::ph_mutex mdi_pathinfo::pi_mutex))
650  * _NOTE(LOCK_ORDER(mdi_client::ct_mutex mdi_pathinfo::pi_mutex))
651  * _NOTE(LOCK_ORDER(mdi_phci::ph_mutex mdi_client::ct_mutex))
652  * _NOTE(LOCK_ORDER(devinfo_tree_lock mdi_pathinfo::pi_mutex))
653  *
654  * mdi_pathinfo node structure definition
655  */
656 struct mdi_pathinfo {
657 	kmutex_t		pi_mutex;	/* per path mutex	*/
658 	mdi_pathinfo_state_t	pi_state;	/* path state		*/
659 	mdi_pathinfo_state_t	pi_old_state;	/* path state		*/
660 	kcondvar_t		pi_state_cv;	/* path state condvar	*/
661 	mdi_client_t		*pi_client;	/* client		*/
662 	mdi_phci_t		*pi_phci;	/* pHCI dev_info node	*/
663 	char			*pi_addr;	/* path unit address	*/
664 	nvlist_t		*pi_prop;	/* Properties		*/
665 	void			*pi_cprivate;	/* client private info	*/
666 	void			*pi_pprivate;	/* phci private info	*/
667 	struct mdi_pathinfo	*pi_client_link; /* next path in client list */
668 	struct mdi_pathinfo	*pi_phci_link;	 /* next path in phci list */
669 	int			pi_ref_cnt;	/* pi reference count	*/
670 	kcondvar_t		pi_ref_cv;	/* condition variable	*/
671 	struct mdi_pi_kstats	*pi_kstats;	/* aggregate kstats */
672 	int			pi_pm_held;	/* phci's kidsup incremented */
673 	int			pi_preferred;	/* Preferred path 	*/
674 	void			*pi_vprivate;	/* vhci private info	*/
675 };
676 
677 /*
678  * pathinfo statistics:
679  *
680  * The mpxio architecture allows for multiple pathinfo nodes for each
681  * client-pHCI combination.  For statistics purposes, these statistics are
682  * aggregated into a single client-pHCI set of kstats.
683  */
684 struct mdi_pi_kstats {
685 	int	pi_kstat_ref;		/* # paths aggregated, also a ref cnt */
686 	kstat_t	*pi_kstat_iostats;	/* mdi:iopath statistic set */
687 	kstat_t *pi_kstat_errstats;	/* error statistics */
688 };
689 
690 /*
691  * pathinfo error kstat
692  */
693 struct pi_errs {
694 	struct kstat_named pi_softerrs;		/* "Soft" Error */
695 	struct kstat_named pi_harderrs;		/* "Hard" Error */
696 	struct kstat_named pi_transerrs;	/* Transport Errors */
697 	struct kstat_named pi_icnt_busy;	/* Interconnect Busy */
698 	struct kstat_named pi_icnt_errors;	/* Interconnect Errors */
699 	struct kstat_named pi_phci_rsrc;	/* pHCI No Resources */
700 	struct kstat_named pi_phci_localerr;	/* pHCI Local Errors */
701 	struct kstat_named pi_phci_invstate;	/* pHCI Invalid State */
702 	struct kstat_named pi_failedfrom;	/* Failover: Failed From */
703 	struct kstat_named pi_failedto;		/* Failover: Failed To */
704 };
705 
706 /*
707  * increment an error counter
708  */
709 #define	MDI_PI_ERRSTAT(pip, x) { \
710 	if (MDI_PI((pip))->pi_kstats != NULL) { \
711 		struct pi_errs *pep; \
712 		pep = MDI_PI(pip)->pi_kstats->pi_kstat_errstats->ks_data; \
713 		pep->x.value.ui32++; \
714 	} \
715 }
716 
717 /*
718  * error codes which can be passed to MDI_PI_ERRSTAT
719  */
720 #define	MDI_PI_SOFTERR	pi_softerrs
721 #define	MDI_PI_HARDERR	pi_harderrs
722 #define	MDI_PI_TRANSERR	pi_transerrs
723 #define	MDI_PI_ICNTBUSY	pi_icnt_busy
724 #define	MDI_PI_ICNTERR	pi_icnt_errors
725 #define	MDI_PI_PHCIRSRC	pi_phci_rsrc
726 #define	MDI_PI_PHCILOCL	pi_phci_localerr
727 #define	MDI_PI_PHCIINVS	pi_phci_invstate
728 #define	MDI_PI_FAILFROM	pi_failedfrom
729 #define	MDI_PI_FAILTO	pi_failedto
730 
731 #define	MDI_PI(type)			((struct mdi_pathinfo *)(type))
732 
733 #define	MDI_PI_LOCK(pip)		mutex_enter(&MDI_PI((pip))->pi_mutex)
734 #define	MDI_PI_UNLOCK(pip)		mutex_exit(&MDI_PI((pip))->pi_mutex)
735 #define	MDI_PI_HOLD(pip)		(++MDI_PI((pip))->pi_ref_cnt)
736 #define	MDI_PI_RELE(pip)		(--MDI_PI((pip))->pi_ref_cnt)
737 
738 #define	MDI_EXT_STATE_CHANGE		0x10000000
739 
740 
741 #define	MDI_DISABLE_OP			0x1
742 #define	MDI_ENABLE_OP			0x2
743 #define	MDI_BEFORE_STATE_CHANGE		0x4
744 #define	MDI_AFTER_STATE_CHANGE		0x8
745 #define	MDI_SYNC_FLAG			0x10
746 
747 #define	MDI_PI_STATE(pip) \
748 	    (MDI_PI((pip))->pi_state & MDI_PATHINFO_STATE_MASK)
749 
750 #define	MDI_PI_OLD_STATE(pip) \
751 	    (MDI_PI((pip))->pi_old_state & MDI_PATHINFO_STATE_MASK)
752 
753 #define	MDI_PI_EXT_STATE(pip) \
754 		(MDI_PI((pip))->pi_state & MDI_PATHINFO_EXT_STATE_MASK)
755 
756 #define	MDI_PI_OLD_EXT_STATE(pip) \
757 		(MDI_PI((pip))->pi_old_state & MDI_PATHINFO_EXT_STATE_MASK)
758 
759 #define	MDI_PI_SET_TRANSIENT(pip) \
760 	    (MDI_PI(pip)->pi_state |= MDI_PATHINFO_STATE_TRANSIENT)
761 
762 #define	MDI_PI_CLEAR_TRANSIENT(pip) \
763 	    (MDI_PI(pip)->pi_state &= ~MDI_PATHINFO_STATE_TRANSIENT)
764 
765 #define	MDI_PI_IS_TRANSIENT(pip) \
766 	(MDI_PI(pip)->pi_state & MDI_PATHINFO_STATE_TRANSIENT)
767 
768 #define	MDI_PI_SET_USER_DISABLE(pip) \
769 	(MDI_PI(pip)->pi_state |= MDI_PATHINFO_STATE_USER_DISABLE)
770 
771 #define	MDI_PI_SET_DRV_DISABLE(pip) \
772 	(MDI_PI(pip)->pi_state |= MDI_PATHINFO_STATE_DRV_DISABLE)
773 
774 #define	MDI_PI_SET_DRV_DISABLE_TRANS(pip) \
775 	(MDI_PI(pip)->pi_state |= MDI_PATHINFO_STATE_DRV_DISABLE_TRANSIENT)
776 
777 #define	MDI_PI_SET_USER_ENABLE(pip) \
778 	(MDI_PI(pip)->pi_state &= ~MDI_PATHINFO_STATE_USER_DISABLE)
779 
780 #define	MDI_PI_SET_DRV_ENABLE(pip) \
781 	(MDI_PI(pip)->pi_state &= ~MDI_PATHINFO_STATE_DRV_DISABLE)
782 
783 #define	MDI_PI_SET_DRV_ENABLE_TRANS(pip) \
784 	(MDI_PI(pip)->pi_state &= ~MDI_PATHINFO_STATE_DRV_DISABLE_TRANSIENT)
785 
786 #define	MDI_PI_IS_USER_DISABLE(pip)	\
787 	(MDI_PI(pip)->pi_state & MDI_PATHINFO_STATE_USER_DISABLE)
788 
789 #define	MDI_PI_IS_DRV_DISABLE(pip)	\
790 	(MDI_PI(pip)->pi_state & MDI_PATHINFO_STATE_DRV_DISABLE)
791 
792 #define	MDI_PI_IS_DRV_DISABLE_TRANSIENT(pip)	\
793 	(MDI_PI(pip)->pi_state & MDI_PATHINFO_STATE_DRV_DISABLE_TRANSIENT)
794 
795 #define	MDI_PI_IS_DISABLE(pip)	\
796 	(MDI_PI_IS_USER_DISABLE(pip) || \
797 	MDI_PI_IS_DRV_DISABLE(pip) || \
798 	MDI_PI_IS_DRV_DISABLE_TRANSIENT(pip))
799 
800 #define	MDI_PI_IS_INIT(pip) \
801 	    ((MDI_PI(pip)->pi_state & MDI_PATHINFO_STATE_MASK) == \
802 		MDI_PATHINFO_STATE_INIT)
803 
804 #define	MDI_PI_IS_INITING(pip) \
805 	    ((MDI_PI(pip)->pi_state & ~MDI_PATHINFO_EXT_STATE_MASK) == \
806 		(MDI_PATHINFO_STATE_INIT | MDI_PATHINFO_STATE_TRANSIENT))
807 
808 #define	MDI_PI_SET_INIT(pip) \
809 	    (MDI_PI(pip)->pi_state = MDI_PATHINFO_STATE_INIT)
810 
811 #define	MDI_PI_SET_ONLINING(pip) { \
812 	uint32_t	ext_state; \
813 	ext_state = MDI_PI(pip)->pi_state & MDI_PATHINFO_EXT_STATE_MASK; \
814 	MDI_PI(pip)->pi_old_state = MDI_PI_STATE(pip); \
815 	MDI_PI(pip)->pi_state = \
816 	(MDI_PATHINFO_STATE_ONLINE | MDI_PATHINFO_STATE_TRANSIENT); \
817 	MDI_PI(pip)->pi_state |= ext_state; \
818 }
819 
820 #define	MDI_PI_IS_ONLINING(pip) \
821 	((MDI_PI(pip)->pi_state & ~MDI_PATHINFO_EXT_STATE_MASK) == \
822 	(MDI_PATHINFO_STATE_ONLINE | MDI_PATHINFO_STATE_TRANSIENT))
823 
824 #define	MDI_PI_SET_ONLINE(pip) { \
825 	uint32_t	ext_state; \
826 	ext_state = MDI_PI(pip)->pi_state & MDI_PATHINFO_EXT_STATE_MASK; \
827 	MDI_PI(pip)->pi_state = MDI_PATHINFO_STATE_ONLINE; \
828 	MDI_PI(pip)->pi_state |= ext_state; \
829 }
830 
831 
832 #define	MDI_PI_IS_ONLINE(pip) \
833 	((MDI_PI(pip)->pi_state & MDI_PATHINFO_STATE_MASK) == \
834 	MDI_PATHINFO_STATE_ONLINE)
835 
836 #define	MDI_PI_SET_OFFLINING(pip) { \
837 	uint32_t	ext_state; \
838 	ext_state = MDI_PI(pip)->pi_state & MDI_PATHINFO_EXT_STATE_MASK; \
839 	MDI_PI(pip)->pi_old_state = MDI_PI_STATE(pip); \
840 	MDI_PI(pip)->pi_state = \
841 	(MDI_PATHINFO_STATE_OFFLINE | MDI_PATHINFO_STATE_TRANSIENT); \
842 	MDI_PI(pip)->pi_state |= ext_state; \
843 }
844 
845 #define	MDI_PI_IS_OFFLINING(pip) \
846 	    ((MDI_PI(pip)->pi_state & ~MDI_PATHINFO_EXT_STATE_MASK) == \
847 	    (MDI_PATHINFO_STATE_OFFLINE | MDI_PATHINFO_STATE_TRANSIENT))
848 
849 #define	MDI_PI_SET_OFFLINE(pip) { \
850 	uint32_t	ext_state; \
851 	ext_state = MDI_PI(pip)->pi_state & MDI_PATHINFO_EXT_STATE_MASK; \
852 	MDI_PI(pip)->pi_state = MDI_PATHINFO_STATE_OFFLINE; \
853 	MDI_PI(pip)->pi_state |= ext_state; \
854 }
855 
856 #define	MDI_PI_IS_OFFLINE(pip) \
857 	    ((MDI_PI(pip)->pi_state & MDI_PATHINFO_STATE_MASK) == \
858 		MDI_PATHINFO_STATE_OFFLINE)
859 
860 #define	MDI_PI_SET_STANDBYING(pip) { \
861 	uint32_t	ext_state; \
862 	ext_state = MDI_PI(pip)->pi_state & MDI_PATHINFO_EXT_STATE_MASK; \
863 	MDI_PI(pip)->pi_old_state = MDI_PI_STATE(pip); \
864 	MDI_PI(pip)->pi_state = \
865 	(MDI_PATHINFO_STATE_STANDBY | MDI_PATHINFO_STATE_TRANSIENT); \
866 	MDI_PI(pip)->pi_state |= ext_state; \
867 }
868 
869 #define	MDI_PI_SET_STANDBY(pip) { \
870 	uint32_t	ext_state; \
871 	ext_state = MDI_PI(pip)->pi_state & MDI_PATHINFO_EXT_STATE_MASK; \
872 	MDI_PI(pip)->pi_state = MDI_PATHINFO_STATE_STANDBY; \
873 	MDI_PI(pip)->pi_state |= ext_state; \
874 }
875 
876 #define	MDI_PI_IS_STANDBY(pip) \
877 	((MDI_PI(pip)->pi_state & MDI_PATHINFO_STATE_MASK) == \
878 	MDI_PATHINFO_STATE_STANDBY)
879 
880 #define	MDI_PI_SET_FAULTING(pip) { \
881 	uint32_t	ext_state; \
882 	ext_state = MDI_PI(pip)->pi_state & MDI_PATHINFO_EXT_STATE_MASK; \
883 	MDI_PI(pip)->pi_old_state = MDI_PI_STATE(pip); \
884 	MDI_PI(pip)->pi_state = \
885 	    (MDI_PATHINFO_STATE_FAULT | MDI_PATHINFO_STATE_TRANSIENT); \
886 	MDI_PI(pip)->pi_state |= ext_state; \
887 }
888 
889 #define	MDI_PI_SET_FAULT(pip) { \
890 	uint32_t	ext_state; \
891 	ext_state = MDI_PI(pip)->pi_state & MDI_PATHINFO_EXT_STATE_MASK; \
892 	MDI_PI(pip)->pi_state = MDI_PATHINFO_STATE_FAULT; \
893 	MDI_PI(pip)->pi_state |= ext_state; \
894 }
895 
896 #define	MDI_PI_IS_FAULT(pip) \
897 	((MDI_PI(pip)->pi_state & MDI_PATHINFO_STATE_MASK) == \
898 	MDI_PATHINFO_STATE_FAULT)
899 
900 #define	MDI_PI_IS_SUSPENDED(pip) \
901 	    ((MDI_PI(pip))->pi_phci->ph_flags & MDI_PHCI_FLAGS_SUSPEND)
902 
903 /*
904  * vHCI driver instance registration/unregistration
905  *
906  * mdi_vhci_register() is called by a vHCI driver to register itself as the
907  * manager of devices from a particular 'class'.  This should be called from
908  * attach(9e).
909  *
910  * mdi_vhci_unregister() is called from detach(9E) to unregister a vHCI
911  * instance from the framework.
912  */
913 int		mdi_vhci_register(char *, dev_info_t *, mdi_vhci_ops_t *, int);
914 int		mdi_vhci_unregister(dev_info_t *, int);
915 
916 /*
917  * Utility functions
918  */
919 int		mdi_phci_get_path_count(dev_info_t *);
920 dev_info_t	*mdi_phci_path2devinfo(dev_info_t *, caddr_t);
921 
922 
923 /*
924  * Path Selection Functions:
925  *
926  * mdi_select_path() is called by a vHCI driver to select to which path an
927  * I/O request should be routed.  The caller passes the 'buf' structure as
928  * one of the parameters.  The mpxio framework uses the buf's contents to
929  * maintain per path statistics (total I/O size / count pending).  If more
930  * than one online path is available, the framework automatically selects
931  * a suitable one.  If a failover operation is active for this client device
932  * the call fails, returning MDI_BUSY.
933  *
934  * By default this function returns a suitable path in the 'online' state,
935  * based on the current load balancing policy.  Currently we support
936  * LOAD_BALANCE_NONE (Previously selected online path will continue to be
937  * used as long as the path is usable) and LOAD_BALANCE_RR (Online paths
938  * will be selected in a round robin fashion).  The load balancing scheme
939  * can be configured in the vHCI driver's configuration file (driver.conf).
940  *
941  * vHCI drivers may override this default behaviour by specifying appropriate
942  * flags.  If start_pip is specified (non NULL), it is used as the routine's
943  * starting point; it starts walking from there to find the next appropriate
944  * path.
945  *
946  * The following values for 'flags' are currently defined:
947  *
948  * 	MDI_SELECT_ONLINE_PATH: select an ONLINE path
949  *	MDI_SELECT_STANDBY_PATH: select a STANDBY path
950  *
951  * The selected paths are returned in a held state (ref_cnt) and caller should
952  * release the hold by calling mdi_rele_path() at the end of operation.
953  */
954 int		mdi_select_path(dev_info_t *, struct buf *, int,
955 		    mdi_pathinfo_t *, mdi_pathinfo_t **);
956 void		mdi_hold_path(mdi_pathinfo_t *);
957 void		mdi_rele_path(mdi_pathinfo_t *);
958 int		mdi_set_lb_policy(dev_info_t *, client_lb_t);
959 int		mdi_set_lb_region_size(dev_info_t *, int);
960 client_lb_t	mdi_get_lb_policy(dev_info_t *);
961 
962 /*
963  * flags for mdi_select_path() routine
964  */
965 #define	MDI_SELECT_ONLINE_PATH		0x0001
966 #define	MDI_SELECT_STANDBY_PATH		0x0002
967 
968 /*
969  * MDI client device utility functions
970  */
971 int		mdi_client_get_path_count(dev_info_t *);
972 dev_info_t	*mdi_client_path2devinfo(dev_info_t *, caddr_t);
973 
974 /*
975  * Failover:
976  *
977  * The vHCI driver calls mdi_failover() to initiate a failover operation.
978  * mdi_failover() calls back into the vHCI driver's vo_failover()
979  * entry point to perform the actual failover operation.  The reason
980  * for requiring the vHCI driver to initiate failover by calling
981  * mdi_failover(), instead of directly executing vo_failover() itself,
982  * is to ensure that the mdi framework can keep track of the client
983  * state properly.  Additionally, mdi_failover() provides as a
984  * convenience the option of performing the failover operation
985  * synchronously or asynchronously
986  *
987  * Upon successful completion of the failover operation, the paths that were
988  * previously ONLINE will be in the STANDBY state, and the newly activated
989  * paths will be in the ONLINE state.
990  *
991  * The flags modifier determines whether the activation is done synchronously
992  */
993 int mdi_failover(dev_info_t *, dev_info_t *, int);
994 
995 /*
996  * Client device failover mode of operation
997  */
998 #define	MDI_FAILOVER_SYNC	1	/* Syncronous Failover		*/
999 #define	MDI_FAILOVER_ASYNC	2	/* Asyncronous Failover		*/
1000 
1001 /*
1002  * mdi_pathinfo node state change functions.
1003  */
1004 void mdi_pi_kstat_iosupdate(mdi_pathinfo_t *, struct buf *);
1005 
1006 /*
1007  * mdi_pathinfo node extended state change functions.
1008  */
1009 int mdi_pi_get_state2(mdi_pathinfo_t *, mdi_pathinfo_state_t *, uint32_t *);
1010 int mdi_pi_get_preferred(mdi_pathinfo_t *);
1011 
1012 /*
1013  * mdi_pathinfo node member functions
1014  */
1015 void *mdi_pi_get_client_private(mdi_pathinfo_t *);
1016 void mdi_pi_set_client_private(mdi_pathinfo_t *, void *);
1017 void mdi_pi_set_state(mdi_pathinfo_t *, mdi_pathinfo_state_t);
1018 void mdi_pi_set_preferred(mdi_pathinfo_t *, int);
1019 
1020 /* get/set vhci private data */
1021 void *mdi_client_get_vhci_private(dev_info_t *);
1022 void mdi_client_set_vhci_private(dev_info_t *, void *);
1023 void *mdi_phci_get_vhci_private(dev_info_t *);
1024 void mdi_phci_set_vhci_private(dev_info_t *, void *);
1025 void *mdi_pi_get_vhci_private(mdi_pathinfo_t *);
1026 void mdi_pi_set_vhci_private(mdi_pathinfo_t *, void *);
1027 
1028 /*
1029  * mdi_pathinfo Property utilities
1030  */
1031 int mdi_prop_size(mdi_pathinfo_t *, size_t *);
1032 int mdi_prop_pack(mdi_pathinfo_t *, char **, uint_t);
1033 
1034 /* obsolete interface, to be removed */
1035 void mdi_get_next_path(dev_info_t *, mdi_pathinfo_t *, mdi_pathinfo_t **);
1036 int mdi_get_component_type(dev_info_t *);
1037 
1038 #endif	/* _KERNEL */
1039 
1040 #ifdef	__cplusplus
1041 }
1042 #endif
1043 
1044 #endif	/* _SYS_MDI_IMPLDEFS_H */
1045