xref: /titanic_50/usr/src/uts/common/sys/mdi_impldefs.h (revision 4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5ee28b439Scm136836  * Common Development and Distribution License (the "License").
6ee28b439Scm136836  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
2255e592a2SRandall Ralphs  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #ifndef	_SYS_MDI_IMPLDEFS_H
277c478bd9Sstevel@tonic-gate #define	_SYS_MDI_IMPLDEFS_H
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #include <sys/note.h>
313c34adc5Sramat #include <sys/types.h>
327c478bd9Sstevel@tonic-gate #include <sys/sunmdi.h>
333c34adc5Sramat #include <sys/modhash.h>
343c34adc5Sramat #include <sys/callb.h>
3555e592a2SRandall Ralphs #include <sys/devctl.h>
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
387c478bd9Sstevel@tonic-gate extern "C" {
397c478bd9Sstevel@tonic-gate #endif
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate #ifdef _KERNEL
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate /*
447c478bd9Sstevel@tonic-gate  * Multipath Driver Interfaces
457c478bd9Sstevel@tonic-gate  *
467c478bd9Sstevel@tonic-gate  * The multipathing framework is provided in two modules.  The 'mpxio' misc.
477c478bd9Sstevel@tonic-gate  * module provides the core multipath framework and the 'scsi_vhci' nexus
487c478bd9Sstevel@tonic-gate  * driver provides the SCSI-III command set driver functionality for
497c478bd9Sstevel@tonic-gate  * managing Fibre-Channel storage devices.
507c478bd9Sstevel@tonic-gate  *
517c478bd9Sstevel@tonic-gate  * As in any multipathing solution there are three major problems to solve:
527c478bd9Sstevel@tonic-gate  *
537c478bd9Sstevel@tonic-gate  * 1) Identification and enumeration of multipath client devices.
547c478bd9Sstevel@tonic-gate  * 2) Optimal path selection when routing I/O requests.
557c478bd9Sstevel@tonic-gate  * 3) Observability interfaces to snapshot the multipath configuration,
567c478bd9Sstevel@tonic-gate  *    and infrastructure to provide performance and error statistics.
577c478bd9Sstevel@tonic-gate  *
587c478bd9Sstevel@tonic-gate  * The mpxio framework consists of several major components:
597c478bd9Sstevel@tonic-gate  *
607c478bd9Sstevel@tonic-gate  * 1) The MDI is the Multiplexed Device Interface; this is the core glue which
617c478bd9Sstevel@tonic-gate  *    holds the following components together.
627c478bd9Sstevel@tonic-gate  * 2) vHCI (Virtual Host Controller Interconnect) drivers provide multipathing
637c478bd9Sstevel@tonic-gate  *    services for a given bus technology (example: 'scsi_vhci' provides
647c478bd9Sstevel@tonic-gate  *    multipathing support for SCSI-III fibre-channel devices).
657c478bd9Sstevel@tonic-gate  * 3) pHCI (Physical Host Controller Interconnect) drivers provide transport
667c478bd9Sstevel@tonic-gate  *    services for a given host controller (example: 'fcp' provides transport
677c478bd9Sstevel@tonic-gate  *    for fibre-channel devices).
687c478bd9Sstevel@tonic-gate  * 4) Client Devices are standard Solaris target (or leaf) drivers
697c478bd9Sstevel@tonic-gate  *    (example: 'ssd' is the standard disk driver for fibre-channel arrays).
707c478bd9Sstevel@tonic-gate  * 5) Multipath information nodes ('pathinfo' nodes) connect client device
717c478bd9Sstevel@tonic-gate  *    nodes and pHCI device nodes in the device tree.
727c478bd9Sstevel@tonic-gate  *
737c478bd9Sstevel@tonic-gate  * With the scsi_vhci, a QLC card, and mpxio enabled, the device tree might
747c478bd9Sstevel@tonic-gate  * look like this:
757c478bd9Sstevel@tonic-gate  *
765e3986cbScth  *              /\
775e3986cbScth  *             /  ............
785e3986cbScth  *     <vHCI>:/               \
797c478bd9Sstevel@tonic-gate  *      +-----------+   +-----------+
807c478bd9Sstevel@tonic-gate  *      | scsi_vhci |   |  pci@1f,0 |
817c478bd9Sstevel@tonic-gate  *      +-----------+   +-----------+
827c478bd9Sstevel@tonic-gate  *            /   \               \
835e3986cbScth  * <Client>: /     \ :<Client>     \ :parent(pHCI)
847c478bd9Sstevel@tonic-gate  *  +----------+ +-----------+    +-------------+
857c478bd9Sstevel@tonic-gate  *  | ssd 1    | | ssd 2     |    | qlc@0,0     |
867c478bd9Sstevel@tonic-gate  *  +----------+ +-----------+    +-------------+
877c478bd9Sstevel@tonic-gate  *   |            |                /        \
885e3986cbScth  *   |            |       <pHCI>: /          \ :<pHCI>
895e3986cbScth  *   |            |      +-------------+   +-------------+
905e3986cbScth  *   |            |      | pHCI 1 (fp) |   | pHCI 2 (fp) |
915e3986cbScth  *   |            |      +-------------+   +-------------+
927c478bd9Sstevel@tonic-gate  *   |            |          /        |      /          |
937c478bd9Sstevel@tonic-gate  *   |            |    +------+       |    +------+     |
945e3986cbScth  *   |            |    | ssd 3|       |    | ssd  |     |
955e3986cbScth  *   |            |    |!mpxio|       |    | (OBP)|     |
967c478bd9Sstevel@tonic-gate  *   |            |    +------+       |    +------+     |
977c478bd9Sstevel@tonic-gate  *   |            |                   |                 |
985e3986cbScth  *   |            |       <pathinfo>: |                 |
997c478bd9Sstevel@tonic-gate  *   |            |               +-------+         +--------+
1005e3986cbScth  *   |            +-------------->| path  |-------->| path   |
1017c478bd9Sstevel@tonic-gate  *   |                            | info  |         | info   |
1027c478bd9Sstevel@tonic-gate  *   |                            | node 1|         | node 3 |
1037c478bd9Sstevel@tonic-gate  *   |                            +-------+         +--------+
1047c478bd9Sstevel@tonic-gate  *   |                                |               |
1055e3986cbScth  *   |                                |            +~~~~~~~~+
1065e3986cbScth  *   |                            +-------+        :+--------+
1075e3986cbScth  *   +--------------------------->| path  |-------->| path   |
1085e3986cbScth  *                                | info  |        :| info   |
1095e3986cbScth  *                                | node 2|        +| node 4 |
1107c478bd9Sstevel@tonic-gate  *                                +-------+         +--------+
1117c478bd9Sstevel@tonic-gate  *
1127c478bd9Sstevel@tonic-gate  * The multipath information nodes (mdi_pathinfo nodes) establish the
1135e3986cbScth  * relationship between the pseudo client driver instance nodes (children
1145e3986cbScth  * of the vHCI) and the physical host controller interconnect (pHCI
1155e3986cbScth  * drivers) forming a matrix structure.
1167c478bd9Sstevel@tonic-gate  *
1177c478bd9Sstevel@tonic-gate  * The mpxio module implements locking at multiple granularity levels to
1187c478bd9Sstevel@tonic-gate  * support the needs of various consumers.  The multipath matrix can be
1195e3986cbScth  * column locked, or row locked depending on the consumer. The intention
1205e3986cbScth  * is to balance simplicity and performance.
1217c478bd9Sstevel@tonic-gate  *
1227c478bd9Sstevel@tonic-gate  * Locking:
1237c478bd9Sstevel@tonic-gate  *
1245e3986cbScth  * The devinfo locking still applies:
1257c478bd9Sstevel@tonic-gate  *
1265e3986cbScth  *   1) An ndi_devi_enter of a parent protects linkage/state of children.
1275e3986cbScth  *   2) state >= DS_INITIALIZED adds devi_ref of parent
1285e3986cbScth  *   3) devi_ref at state >= DS_ATTACHED prevents detach(9E).
1297c478bd9Sstevel@tonic-gate  *
1305e3986cbScth  * The ordering of 1) is (vHCI, pHCI). For a DEBUG kernel this ordering
1315e3986cbScth  * is asserted by the ndi_devi_enter() implementation.  There is also an
1325e3986cbScth  * ndi_devi_enter(Client), which is atypical since the client is a leaf.
1335e3986cbScth  * This is done to synchronize pathinfo nodes during devinfo snapshot (see
1345e3986cbScth  * di_register_pip) by pretending that the pathinfo nodes are children
1355e3986cbScth  * of the client.
1367c478bd9Sstevel@tonic-gate  *
1375e3986cbScth  * In addition to devinfo locking the current implementation utilizes
1385e3986cbScth  * the following locks:
1397c478bd9Sstevel@tonic-gate  *
1405e3986cbScth  *   mdi_mutex: protects the global list of vHCIs.
1417c478bd9Sstevel@tonic-gate  *
1425e3986cbScth  *   vh_phci_mutex: per-vHCI (mutex) lock: protects list of pHCIs registered
1435e3986cbScth  *   with vHCI.
1445e3986cbScth  *
1455e3986cbScth  *   vh_client_mutex: per-vHCI (mutex) lock: protects list/hash of Clients
1465e3986cbScth  *   associated with vHCI.
1475e3986cbScth  *
1485e3986cbScth  *   ph_mutex: per-pHCI (mutex) lock: protects the column (pHCI-mdi_pathinfo
1495e3986cbScth  *   node list) and per-pHCI structure fields.  mdi_pathinfo node creation,
1505e3986cbScth  *   deletion and child mdi_pathinfo node state changes are serialized on per
1515e3986cbScth  *   pHCI basis (Protection against DR).
1525e3986cbScth  *
1535e3986cbScth  *   ct_mutex: per-client (mutex) lock: protects the row (client-mdi_pathinfo
1545e3986cbScth  *   node list) and per-client structure fields.  The client-mdi_pathinfo node
1555e3986cbScth  *   list is typically walked to select an optimal path when routing I/O
1565e3986cbScth  *   requests.
1575e3986cbScth  *
1585e3986cbScth  *   pi_mutex: per-mdi_pathinfo (mutex) lock: protects the mdi_pathinfo node
1595e3986cbScth  *   structure fields.
1607c478bd9Sstevel@tonic-gate  *
1617c478bd9Sstevel@tonic-gate  * Note that per-Client structure and per-pHCI fields are freely readable when
1627c478bd9Sstevel@tonic-gate  * corresponding mdi_pathinfo locks are held, since holding an mdi_pathinfo
1637c478bd9Sstevel@tonic-gate  * node guarantees that its corresponding client and pHCI devices will not be
1647c478bd9Sstevel@tonic-gate  * freed.
1657c478bd9Sstevel@tonic-gate  */
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate /*
1687c478bd9Sstevel@tonic-gate  * MDI Client global unique identifier property name string definition
1697c478bd9Sstevel@tonic-gate  */
1707c478bd9Sstevel@tonic-gate extern const char			*mdi_client_guid_prop;
1717c478bd9Sstevel@tonic-gate #define	MDI_CLIENT_GUID_PROP		(char *)mdi_client_guid_prop
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate /*
1747c478bd9Sstevel@tonic-gate  * MDI Client load balancing policy definitions
1757c478bd9Sstevel@tonic-gate  *
1767c478bd9Sstevel@tonic-gate  * Load balancing policies are determined on a per-vHCI basis and are
1777c478bd9Sstevel@tonic-gate  * configurable via the vHCI's driver.conf file.
1787c478bd9Sstevel@tonic-gate  */
1797c478bd9Sstevel@tonic-gate typedef enum {
1807c478bd9Sstevel@tonic-gate 	LOAD_BALANCE_NONE,		/* Alternate pathing		*/
1817c478bd9Sstevel@tonic-gate 	LOAD_BALANCE_RR,		/* Round Robin			*/
1827c478bd9Sstevel@tonic-gate 	LOAD_BALANCE_LBA		/* Logical Block Addressing	*/
1837c478bd9Sstevel@tonic-gate } client_lb_t;
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate typedef struct {
1867c478bd9Sstevel@tonic-gate 	int region_size;
1877c478bd9Sstevel@tonic-gate }client_lb_args_t;
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate /*
1907c478bd9Sstevel@tonic-gate  * MDI client load balancing property name/value string definitions
1917c478bd9Sstevel@tonic-gate  */
1927c478bd9Sstevel@tonic-gate extern const char			*mdi_load_balance;
1937c478bd9Sstevel@tonic-gate extern const char			*mdi_load_balance_none;
1947c478bd9Sstevel@tonic-gate extern const char			*mdi_load_balance_ap;
1957c478bd9Sstevel@tonic-gate extern const char			*mdi_load_balance_rr;
1967c478bd9Sstevel@tonic-gate extern const char			*mdi_load_balance_lba;
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate #define	LOAD_BALANCE_PROP		(char *)mdi_load_balance
1997c478bd9Sstevel@tonic-gate #define	LOAD_BALANCE_PROP_NONE		(char *)mdi_load_balance_none
2007c478bd9Sstevel@tonic-gate #define	LOAD_BALANCE_PROP_AP		(char *)mdi_load_balance_ap
2017c478bd9Sstevel@tonic-gate #define	LOAD_BALANCE_PROP_RR		(char *)mdi_load_balance_rr
2027c478bd9Sstevel@tonic-gate #define	LOAD_BALANCE_PROP_LBA		(char *)mdi_load_balance_lba
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate /* default for region size */
2057c478bd9Sstevel@tonic-gate #define	LOAD_BALANCE_DEFAULT_REGION_SIZE	18
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate /*
2087c478bd9Sstevel@tonic-gate  * vHCI drivers:
2097c478bd9Sstevel@tonic-gate  *
2107c478bd9Sstevel@tonic-gate  * vHCI drivers are pseudo nexus drivers which implement multipath services
2117c478bd9Sstevel@tonic-gate  * for a specific command set or bus architecture ('class').  There is a
2127c478bd9Sstevel@tonic-gate  * single instance of the vHCI driver for each command set which supports
2137c478bd9Sstevel@tonic-gate  * multipath devices.
2147c478bd9Sstevel@tonic-gate  *
2157c478bd9Sstevel@tonic-gate  * Each vHCI driver registers the following callbacks from attach(9e).
2167c478bd9Sstevel@tonic-gate  */
2177c478bd9Sstevel@tonic-gate #define	MDI_VHCI_OPS_REV_1		1
2187c478bd9Sstevel@tonic-gate #define	MDI_VHCI_OPS_REV		MDI_VHCI_OPS_REV_1
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate typedef struct mdi_vhci_ops {
2217c478bd9Sstevel@tonic-gate 	/* revision management */
2227c478bd9Sstevel@tonic-gate 	int	vo_revision;
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 	/* mdi_pathinfo node init callback */
2257c478bd9Sstevel@tonic-gate 	int	(*vo_pi_init)(dev_info_t *vdip, mdi_pathinfo_t *pip, int flags);
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	/* mdi_pathinfo node uninit callback */
2287c478bd9Sstevel@tonic-gate 	int	(*vo_pi_uninit)(dev_info_t *vdip, mdi_pathinfo_t *pip,
2297c478bd9Sstevel@tonic-gate 		    int flags);
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate 	/* mdi_pathinfo node state change callback */
2327c478bd9Sstevel@tonic-gate 	int	(*vo_pi_state_change)(dev_info_t *vdip, mdi_pathinfo_t *pip,
2337c478bd9Sstevel@tonic-gate 		    mdi_pathinfo_state_t state, uint32_t, int flags);
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 	/* Client path failover callback */
2367c478bd9Sstevel@tonic-gate 	int	(*vo_failover)(dev_info_t *vdip, dev_info_t *cdip, int flags);
23737fbbce5Scth 
23837fbbce5Scth 	/* Client attached callback */
23937fbbce5Scth 	void	(*vo_client_attached)(dev_info_t *cdip);
24055e592a2SRandall Ralphs 
24155e592a2SRandall Ralphs 	/* Ask vHCI if 'cinfo' device is support as a client */
24255e592a2SRandall Ralphs 	int	(*vo_is_dev_supported)(dev_info_t *vdip, dev_info_t *pdip,
24355e592a2SRandall Ralphs 		    void *cinfo);
2447c478bd9Sstevel@tonic-gate } mdi_vhci_ops_t;
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate /*
2477c478bd9Sstevel@tonic-gate  * An mdi_vhci structure is created and bound to the devinfo node of every
2487c478bd9Sstevel@tonic-gate  * registered vHCI class driver; this happens when a vHCI registers itself from
2497c478bd9Sstevel@tonic-gate  * attach(9e).  This structure is unbound and freed when the vHCI unregisters
2507c478bd9Sstevel@tonic-gate  * at detach(9e) time;
2517c478bd9Sstevel@tonic-gate  *
2527c478bd9Sstevel@tonic-gate  * Each vHCI driver is associated with a vHCI class name; this is the handle
2537c478bd9Sstevel@tonic-gate  * used to register and unregister pHCI drivers for a given transport.
2547c478bd9Sstevel@tonic-gate  *
2555e3986cbScth  * Locking: Different parts of this structure are guarded by different
2565e3986cbScth  * locks: global threading of multiple vHCIs and initialization is protected
2575e3986cbScth  * by mdi_mutex, the list of pHCIs associated with a vHCI is protected by
2585e3986cbScth  * vh_phci_mutex, and Clients are protected by vh_client_mutex.
2595e3986cbScth  *
2605e3986cbScth  * XXX Depending on the context, some of the fields can be freely read without
2615e3986cbScth  * holding any locks (ex. holding vh_client_mutex lock also guarantees that
2625e3986cbScth  * the vHCI (parent) cannot be unexpectedly freed).
2637c478bd9Sstevel@tonic-gate  */
2647c478bd9Sstevel@tonic-gate typedef struct mdi_vhci {
2655e3986cbScth 	/* protected by mdi_mutex... */
2665e3986cbScth 	struct mdi_vhci		*vh_next;	/* next vHCI link	*/
2675e3986cbScth 	struct mdi_vhci		*vh_prev;	/* prev vHCI link	*/
2685e3986cbScth 	char			*vh_class;	/* vHCI class name	*/
2695e3986cbScth 	dev_info_t		*vh_dip;	/* vHCI devi handle	*/
2705e3986cbScth 	int			vh_refcnt;	/* vHCI reference count	*/
2715e3986cbScth 	struct mdi_vhci_config	*vh_config;	/* vHCI config		*/
2725e3986cbScth 	client_lb_t		vh_lb;		/* vHCI load-balancing	*/
2735e3986cbScth 	struct mdi_vhci_ops	*vh_ops;	/* vHCI callback vectors */
2745e3986cbScth 
2755e3986cbScth 	/* protected by MDI_VHCI_PHCI_LOCK vh_phci_mutex... */
2765e3986cbScth 	kmutex_t		vh_phci_mutex;	/* pHCI mutex		*/
2777c478bd9Sstevel@tonic-gate 	int			vh_phci_count;	/* pHCI device count	*/
2787c478bd9Sstevel@tonic-gate 	struct mdi_phci		*vh_phci_head;	/* pHCI list head	*/
2797c478bd9Sstevel@tonic-gate 	struct mdi_phci		*vh_phci_tail;	/* pHCI list tail	*/
2805e3986cbScth 
2815e3986cbScth 	/* protected by MDI_VHCI_CLIENT_LOCK vh_client_mutex... */
2825e3986cbScth 	kmutex_t		vh_client_mutex; /* Client mutex	*/
2837c478bd9Sstevel@tonic-gate 	int			vh_client_count; /* Client count	*/
2847c478bd9Sstevel@tonic-gate 	struct client_hash	*vh_client_table; /* Client hash	*/
2857c478bd9Sstevel@tonic-gate } mdi_vhci_t;
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate /*
2885e3986cbScth  * per-vHCI lock macros
2895e3986cbScth  */
2905e3986cbScth #define	MDI_VHCI_PHCI_LOCK(vh)		mutex_enter(&(vh)->vh_phci_mutex)
2915e3986cbScth #define	MDI_VHCI_PHCI_TRYLOCK(vh)	mutex_tryenter(&(vh)->vh_phci_mutex)
2925e3986cbScth #define	MDI_VHCI_PHCI_UNLOCK(vh)	mutex_exit(&(vh)->vh_phci_mutex)
2935e3986cbScth #ifdef	DEBUG
2945e3986cbScth #define	MDI_VHCI_PCHI_LOCKED(vh)	MUTEX_HELD(&(vh)->vh_phci_mutex)
2955e3986cbScth #endif	/* DEBUG */
2965e3986cbScth #define	MDI_VHCI_CLIENT_LOCK(vh)	mutex_enter(&(vh)->vh_client_mutex)
2975e3986cbScth #define	MDI_VHCI_CLIENT_TRYLOCK(vh)	mutex_tryenter(&(vh)->vh_client_mutex)
2985e3986cbScth #define	MDI_VHCI_CLIENT_UNLOCK(vh)	mutex_exit(&(vh)->vh_client_mutex)
2995e3986cbScth #ifdef	DEBUG
3005e3986cbScth #define	MDI_VHCI_CLIENT_LOCKED(vh)	MUTEX_HELD(&(vh)->vh_client_mutex)
3015e3986cbScth #endif	/* DEBUG */
3025e3986cbScth 
3035e3986cbScth 
3045e3986cbScth /*
3057c478bd9Sstevel@tonic-gate  * GUID Hash definitions
3067c478bd9Sstevel@tonic-gate  *
3077c478bd9Sstevel@tonic-gate  * Since all the mpxio managed devices for a given class are enumerated under
3087c478bd9Sstevel@tonic-gate  * the single vHCI instance for that class, sequentially walking through the
3097c478bd9Sstevel@tonic-gate  * client device link to find a client would be prohibitively slow.
3107c478bd9Sstevel@tonic-gate  */
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate #define	CLIENT_HASH_TABLE_SIZE	(32)	/* GUID hash */
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate /*
3157c478bd9Sstevel@tonic-gate  * Client hash table structure
3167c478bd9Sstevel@tonic-gate  */
3177c478bd9Sstevel@tonic-gate struct client_hash {
3187c478bd9Sstevel@tonic-gate 	struct mdi_client	*ct_hash_head;	/* Client hash head	*/
3197c478bd9Sstevel@tonic-gate 	int			ct_hash_count;	/* Client hash count	*/
3207c478bd9Sstevel@tonic-gate };
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate /*
3247c478bd9Sstevel@tonic-gate  * pHCI Drivers:
3257c478bd9Sstevel@tonic-gate  *
3267c478bd9Sstevel@tonic-gate  * Physical HBA drivers provide transport services for mpxio-managed devices.
3277c478bd9Sstevel@tonic-gate  * As each pHCI instance is attached, it must register itself with the mpxio
3287c478bd9Sstevel@tonic-gate  * framework using mdi_phci_register().  When the pHCI is detached it must
3297c478bd9Sstevel@tonic-gate  * similarly call mdi_phci_unregister().
3307c478bd9Sstevel@tonic-gate  *
3317c478bd9Sstevel@tonic-gate  * The framework maintains a list of registered pHCI device instances for each
3325e3986cbScth  * vHCI.  This list involves (vh_phci_count, vh_phci_head, vh_phci_tail) and
3335e3986cbScth  * (ph_next, ph_prev, ph_vhci) and is protected by vh_phci_mutex.
3347c478bd9Sstevel@tonic-gate  *
3357c478bd9Sstevel@tonic-gate  * Locking order:
3367c478bd9Sstevel@tonic-gate  *
3375e3986cbScth  * _NOTE(LOCK_ORDER(mdi_mutex, mdi_phci::ph_mutex))		XXX
3385e3986cbScth  * _NOTE(LOCK_ORDER(mdi_phci::ph_mutex devinfo_tree_lock))		XXX
3397c478bd9Sstevel@tonic-gate  */
3407c478bd9Sstevel@tonic-gate typedef struct mdi_phci {
3415e3986cbScth 	/* protected by MDI_VHCI_PHCI_LOCK vh_phci_mutex... */
3425e3986cbScth 	struct mdi_phci		*ph_next;	/* next pHCI link	*/
3435e3986cbScth 	struct mdi_phci		*ph_prev;	/* prev pHCI link	*/
3445e3986cbScth 	dev_info_t		*ph_dip;	/* pHCI devi handle	*/
3455e3986cbScth 	struct mdi_vhci		*ph_vhci;	/* pHCI back ref. to vHCI */
3465e3986cbScth 
3475e3986cbScth 	/* protected by MDI_PHCI_LOCK ph_mutex... */
3487c478bd9Sstevel@tonic-gate 	kmutex_t		ph_mutex;	/* per-pHCI mutex	*/
3495e3986cbScth 	int			ph_path_count;	/* pi count		*/
3507c478bd9Sstevel@tonic-gate 	mdi_pathinfo_t		*ph_path_head;	/* pi list head		*/
3517c478bd9Sstevel@tonic-gate 	mdi_pathinfo_t		*ph_path_tail;	/* pi list tail		*/
3525e3986cbScth 	int			ph_flags;	/* pHCI operation flags	*/
3537c478bd9Sstevel@tonic-gate 	int			ph_unstable;	/* Paths in transient state */
3547c478bd9Sstevel@tonic-gate 	kcondvar_t		ph_unstable_cv;	/* Paths in transient state */
3555e3986cbScth 
3565e3986cbScth 	/* protected by mdi_phci_[gs]et_vhci_private caller... */
3577c478bd9Sstevel@tonic-gate 	void			*ph_vprivate;	/* vHCI driver private	*/
3587c478bd9Sstevel@tonic-gate } mdi_phci_t;
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate /*
3617c478bd9Sstevel@tonic-gate  * A pHCI device is 'unstable' while one or more paths are in a transitional
3627c478bd9Sstevel@tonic-gate  * state.  Hotplugging is prevented during this state.
3637c478bd9Sstevel@tonic-gate  */
3647c478bd9Sstevel@tonic-gate #define	MDI_PHCI_UNSTABLE(ph)		(ph)->ph_unstable++;
3657c478bd9Sstevel@tonic-gate #define	MDI_PHCI_STABLE(ph) { \
3667c478bd9Sstevel@tonic-gate 	(ph)->ph_unstable--; \
3677c478bd9Sstevel@tonic-gate 	if ((ph)->ph_unstable == 0) { \
3687c478bd9Sstevel@tonic-gate 		cv_broadcast(&(ph)->ph_unstable_cv); \
3697c478bd9Sstevel@tonic-gate 	} \
3707c478bd9Sstevel@tonic-gate }
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate /*
3737c478bd9Sstevel@tonic-gate  * per-pHCI lock macros
3747c478bd9Sstevel@tonic-gate  */
3755e3986cbScth #define	MDI_PHCI_LOCK(ph)		mutex_enter(&(ph)->ph_mutex)
3765e3986cbScth #define	MDI_PHCI_TRYLOCK(ph)		mutex_tryenter(&(ph)->ph_mutex)
3775e3986cbScth #define	MDI_PHCI_UNLOCK(ph)		mutex_exit(&(ph)->ph_mutex)
3785e3986cbScth #ifdef	DEBUG
3795e3986cbScth #define	MDI_PHCI_LOCKED(vh)		MUTEX_HELD(&(ph)->ph_mutex)
3805e3986cbScth #endif	/* DEBUG */
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate /*
3837c478bd9Sstevel@tonic-gate  * pHCI state definitions and macros to track the pHCI driver instance state
3847c478bd9Sstevel@tonic-gate  */
3857c478bd9Sstevel@tonic-gate #define	MDI_PHCI_FLAGS_OFFLINE		0x1	/* pHCI is offline */
3867c478bd9Sstevel@tonic-gate #define	MDI_PHCI_FLAGS_SUSPEND		0x2	/* pHCI is suspended */
3877c478bd9Sstevel@tonic-gate #define	MDI_PHCI_FLAGS_POWER_DOWN	0x4	/* pHCI is power down */
3887c478bd9Sstevel@tonic-gate #define	MDI_PHCI_FLAGS_DETACH		0x8	/* pHCI is detached */
3897c478bd9Sstevel@tonic-gate #define	MDI_PHCI_FLAGS_USER_DISABLE	0x10	/* pHCI is disabled,user */
3907c478bd9Sstevel@tonic-gate #define	MDI_PHCI_FLAGS_D_DISABLE	0x20	/* pHCI is disabled,driver */
3917c478bd9Sstevel@tonic-gate #define	MDI_PHCI_FLAGS_D_DISABLE_TRANS	0x40	/* pHCI is disabled,transient */
3927c478bd9Sstevel@tonic-gate #define	MDI_PHCI_FLAGS_POWER_TRANSITION	0x80	/* pHCI is power transition */
3937c478bd9Sstevel@tonic-gate 
3945e3986cbScth #define	MDI_PHCI_DISABLE_MASK						\
3955e3986cbScth 	    (MDI_PHCI_FLAGS_USER_DISABLE | MDI_PHCI_FLAGS_D_DISABLE |	\
3965e3986cbScth 	    MDI_PHCI_FLAGS_D_DISABLE_TRANS)
3975e3986cbScth 
3987c478bd9Sstevel@tonic-gate #define	MDI_PHCI_IS_READY(ph)						\
3995e3986cbScth 	    (((ph)->ph_flags & MDI_PHCI_DISABLE_MASK) == 0)
4007c478bd9Sstevel@tonic-gate 
4015e3986cbScth #define	MDI_PHCI_SET_OFFLINE(ph)					{\
4025e3986cbScth 	    ASSERT(MDI_PHCI_LOCKED(ph));				\
4035e3986cbScth 	    (ph)->ph_flags |= MDI_PHCI_FLAGS_OFFLINE;			}
4045e3986cbScth #define	MDI_PHCI_SET_ONLINE(ph)						{\
4055e3986cbScth 	    ASSERT(MDI_PHCI_LOCKED(ph));				\
4065e3986cbScth 	    (ph)->ph_flags &= ~MDI_PHCI_FLAGS_OFFLINE;			}
4077c478bd9Sstevel@tonic-gate #define	MDI_PHCI_IS_OFFLINE(ph)						\
4087c478bd9Sstevel@tonic-gate 	    ((ph)->ph_flags & MDI_PHCI_FLAGS_OFFLINE)
4097c478bd9Sstevel@tonic-gate 
4105e3986cbScth #define	MDI_PHCI_SET_SUSPEND(ph)					{\
4115e3986cbScth 	    ASSERT(MDI_PHCI_LOCKED(ph));				\
4125e3986cbScth 	    (ph)->ph_flags |= MDI_PHCI_FLAGS_SUSPEND;			}
4135e3986cbScth #define	MDI_PHCI_SET_RESUME(ph)						{\
4145e3986cbScth 	    ASSERT(MDI_PHCI_LOCKED(ph));				\
4155e3986cbScth 	    (ph)->ph_flags &= ~MDI_PHCI_FLAGS_SUSPEND;			}
4167c478bd9Sstevel@tonic-gate #define	MDI_PHCI_IS_SUSPENDED(ph)					\
4177c478bd9Sstevel@tonic-gate 	    ((ph)->ph_flags & MDI_PHCI_FLAGS_SUSPEND)
4187c478bd9Sstevel@tonic-gate 
4195e3986cbScth #define	MDI_PHCI_SET_DETACH(ph)						{\
4205e3986cbScth 	    ASSERT(MDI_PHCI_LOCKED(ph));				\
4215e3986cbScth 	    (ph)->ph_flags |= MDI_PHCI_FLAGS_DETACH;			}
4225e3986cbScth #define	MDI_PHCI_SET_ATTACH(ph)						{\
4235e3986cbScth 	    ASSERT(MDI_PHCI_LOCKED(ph));				\
4245e3986cbScth 	    (ph)->ph_flags &= ~MDI_PHCI_FLAGS_DETACH;			}
4257c478bd9Sstevel@tonic-gate 
4265e3986cbScth #define	MDI_PHCI_SET_POWER_DOWN(ph)					{\
4275e3986cbScth 	    ASSERT(MDI_PHCI_LOCKED(ph));				\
4285e3986cbScth 	    (ph)->ph_flags |= MDI_PHCI_FLAGS_POWER_DOWN;		}
4295e3986cbScth #define	MDI_PHCI_SET_POWER_UP(ph)					{\
4305e3986cbScth 	    ASSERT(MDI_PHCI_LOCKED(ph));				\
4315e3986cbScth 	    (ph)->ph_flags &= ~MDI_PHCI_FLAGS_POWER_DOWN;		}
432c73a93f2Sdm120769 #define	MDI_PHCI_IS_POWERED_DOWN(ph)					\
433c73a93f2Sdm120769 	    ((ph)->ph_flags & MDI_PHCI_FLAGS_POWER_DOWN)
434c73a93f2Sdm120769 
4355e3986cbScth #define	MDI_PHCI_SET_USER_ENABLE(ph)					{\
4365e3986cbScth 	    ASSERT(MDI_PHCI_LOCKED(ph));				\
4375e3986cbScth 	    (ph)->ph_flags &= ~MDI_PHCI_FLAGS_USER_DISABLE;		}
4385e3986cbScth #define	MDI_PHCI_SET_USER_DISABLE(ph)					{\
4395e3986cbScth 	    ASSERT(MDI_PHCI_LOCKED(ph));				\
4405e3986cbScth 	    (ph)->ph_flags |= MDI_PHCI_FLAGS_USER_DISABLE;		}
4415e3986cbScth #define	MDI_PHCI_IS_USER_DISABLED(ph)					\
4425e3986cbScth 	    ((ph)->ph_flags & MDI_PHCI_FLAGS_USER_DISABLE)
443c73a93f2Sdm120769 
4445e3986cbScth #define	MDI_PHCI_SET_DRV_ENABLE(ph)					{\
4455e3986cbScth 	    ASSERT(MDI_PHCI_LOCKED(ph));				\
4465e3986cbScth 	    (ph)->ph_flags &= ~MDI_PHCI_FLAGS_D_DISABLE;		}
4475e3986cbScth #define	MDI_PHCI_SET_DRV_DISABLE(ph)					{\
4485e3986cbScth 	    ASSERT(MDI_PHCI_LOCKED(ph));				\
4495e3986cbScth 	    (ph)->ph_flags |= MDI_PHCI_FLAGS_D_DISABLE;			}
4505e3986cbScth #define	MDI_PHCI_IS_DRV_DISABLED(ph)					\
4515e3986cbScth 	    ((ph)->ph_flags & MDI_PHCI_FLAGS_D_DISABLE)
452c73a93f2Sdm120769 
4535e3986cbScth #define	MDI_PHCI_SET_DRV_ENABLE_TRANSIENT(ph)				{\
4545e3986cbScth 	    ASSERT(MDI_PHCI_LOCKED(ph));				\
4555e3986cbScth 	    (ph)->ph_flags &= ~MDI_PHCI_FLAGS_D_DISABLE_TRANS;		}
4565e3986cbScth #define	MDI_PHCI_SET_DRV_DISABLE_TRANSIENT(ph)				{\
4575e3986cbScth 	    ASSERT(MDI_PHCI_LOCKED(ph));				\
4585e3986cbScth 	    (ph)->ph_flags |= MDI_PHCI_FLAGS_D_DISABLE_TRANS;		}
4595e3986cbScth #define	MDI_PHCI_IS_DRV_DISABLED_TRANSIENT(ph)				\
4605e3986cbScth 	    ((ph)->ph_flags & MDI_PHCI_FLAGS_D_DISABLE_TRANS)
4615e3986cbScth 
4625e3986cbScth #define	MDI_PHCI_SET_POWER_TRANSITION(ph)				{\
4635e3986cbScth 	    ASSERT(MDI_PHCI_LOCKED(ph));				\
4645e3986cbScth 	    (ph)->ph_flags |= MDI_PHCI_FLAGS_POWER_TRANSITION;		}
4655e3986cbScth #define	MDI_PHCI_CLEAR_POWER_TRANSITION(ph)				{\
4665e3986cbScth 	    ASSERT(MDI_PHCI_LOCKED(ph));				\
4675e3986cbScth 	    (ph)->ph_flags &= ~MDI_PHCI_FLAGS_POWER_TRANSITION;		}
4687c478bd9Sstevel@tonic-gate #define	MDI_PHCI_IS_POWER_TRANSITION(ph)				\
4697c478bd9Sstevel@tonic-gate 	    ((ph)->ph_flags & MDI_PHCI_FLAGS_POWER_TRANSITION)
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate /*
4727c478bd9Sstevel@tonic-gate  * mpxio Managed Clients:
4737c478bd9Sstevel@tonic-gate  *
4747c478bd9Sstevel@tonic-gate  * This framework creates a struct mdi_client for every client device created
4757c478bd9Sstevel@tonic-gate  * by the framework as a result of self-enumeration of target devices by the
4767c478bd9Sstevel@tonic-gate  * registered pHCI devices.  This structure is bound to client device dev_info
4777c478bd9Sstevel@tonic-gate  * node at the time of client device allocation (ndi_devi_alloc(9e)). This
4787c478bd9Sstevel@tonic-gate  * structure is unbound from the dev_info node when mpxio framework removes a
4797c478bd9Sstevel@tonic-gate  * client device node from the system.
4807c478bd9Sstevel@tonic-gate  *
4817c478bd9Sstevel@tonic-gate  * This structure is created when a first path is enumerated and removed when
4827c478bd9Sstevel@tonic-gate  * last path is de-enumerated from the system.
4837c478bd9Sstevel@tonic-gate  *
4847c478bd9Sstevel@tonic-gate  * Multipath client devices are instantiated as children of corresponding vHCI
4857c478bd9Sstevel@tonic-gate  * driver instance. Each client device is uniquely identified by a GUID
4867c478bd9Sstevel@tonic-gate  * provided by target device itself.  The parent vHCI device also maintains a
4875e3986cbScth  * hashed list of client devices, protected by vh_client_mutex.
4887c478bd9Sstevel@tonic-gate  *
4897c478bd9Sstevel@tonic-gate  * Typically pHCI devices self-enumerate their child devices using taskq,
4907c478bd9Sstevel@tonic-gate  * resulting in multiple paths to the same client device to be enumerated by
4915e3986cbScth  * competing threads.
4927c478bd9Sstevel@tonic-gate  *
4937c478bd9Sstevel@tonic-gate  * Currently this framework supports two kinds of load-balancing policy
4947c478bd9Sstevel@tonic-gate  * configurable through the vHCI driver configuration files.
4957c478bd9Sstevel@tonic-gate  *
4967c478bd9Sstevel@tonic-gate  * NONE		- Legacy AP mode
4977c478bd9Sstevel@tonic-gate  * Round Robin	- Balance the pHCI load in a Round Robin fashion.
4987c478bd9Sstevel@tonic-gate  *
4997c478bd9Sstevel@tonic-gate  * This framework identifies the client device in three distinct states:
5007c478bd9Sstevel@tonic-gate  *
5017c478bd9Sstevel@tonic-gate  * OPTIMAL	- Client device has at least one redundant path.
5027c478bd9Sstevel@tonic-gate  * DEGRADED	- No redundant paths (critical).  Failure in the current active
5037c478bd9Sstevel@tonic-gate  *		  path would result in data access failures.
5047c478bd9Sstevel@tonic-gate  * FAILED	- No paths are available to access this device.
5057c478bd9Sstevel@tonic-gate  *
5067c478bd9Sstevel@tonic-gate  * Locking order:
5077c478bd9Sstevel@tonic-gate  *
5085e3986cbScth  * _NOTE(LOCK_ORDER(mdi_mutex, mdi_client::ct_mutex))			XXX
5095e3986cbScth  * _NOTE(LOCK_ORDER(mdi_client::ct_mutex devinfo_tree_lock))		XXX
5107c478bd9Sstevel@tonic-gate  */
5117c478bd9Sstevel@tonic-gate typedef struct mdi_client {
5125e3986cbScth 	/* protected by MDI_VHCI_CLIENT_LOCK vh_client_mutex... */
5137c478bd9Sstevel@tonic-gate 	struct mdi_client	*ct_hnext;	/* next client		*/
5147c478bd9Sstevel@tonic-gate 	struct mdi_client	*ct_hprev;	/* prev client		*/
5157c478bd9Sstevel@tonic-gate 	dev_info_t		*ct_dip;	/* client devi handle	*/
5167c478bd9Sstevel@tonic-gate 	struct mdi_vhci		*ct_vhci;	/* vHCI back ref	*/
5177c478bd9Sstevel@tonic-gate 	char			*ct_drvname;	/* client driver name	*/
5187c478bd9Sstevel@tonic-gate 	char			*ct_guid;	/* client guid		*/
5197c478bd9Sstevel@tonic-gate 	client_lb_t		ct_lb;		/* load balancing scheme */
5207c478bd9Sstevel@tonic-gate 	client_lb_args_t	*ct_lb_args;	/* load balancing args */
5215e3986cbScth 
5225e3986cbScth 
5235e3986cbScth 	/* protected by MDI_CLIENT_LOCK ct_mutex... */
5245e3986cbScth 	kmutex_t		ct_mutex;	/* per-client mutex	*/
5257c478bd9Sstevel@tonic-gate 	int			ct_path_count;	/* multi path count	*/
5267c478bd9Sstevel@tonic-gate 	mdi_pathinfo_t		*ct_path_head;	/* multi path list head	*/
5277c478bd9Sstevel@tonic-gate 	mdi_pathinfo_t		*ct_path_tail;	/* multi path list tail	*/
5287c478bd9Sstevel@tonic-gate 	mdi_pathinfo_t		*ct_path_last;	/* last path used for i/o */
5295e3986cbScth 	int			ct_state;	/* state information	*/
5305e3986cbScth 	int			ct_flags;	/* Driver op. flags	*/
5315e3986cbScth 	int			ct_failover_flags;	/* Failover args */
5325e3986cbScth 	int			ct_failover_status;	/* last fo status */
5335e3986cbScth 	kcondvar_t		ct_failover_cv;	/* Failover status cv	*/
5347c478bd9Sstevel@tonic-gate 	int			ct_unstable;	/* Paths in transient state */
5357c478bd9Sstevel@tonic-gate 	kcondvar_t		ct_unstable_cv;	/* Paths in transient state */
5365e3986cbScth 
5377c478bd9Sstevel@tonic-gate 	int			ct_power_cnt;	/* Hold count on parent power */
5387c478bd9Sstevel@tonic-gate 	kcondvar_t		ct_powerchange_cv;
5397c478bd9Sstevel@tonic-gate 					/* Paths in power transient state */
54078dc6db2Sllai1 	short			ct_powercnt_config;
54178dc6db2Sllai1 					/* held in pre/post config */
54278dc6db2Sllai1 	short			ct_powercnt_unconfig;
54378dc6db2Sllai1 					/* held in pre/post unconfig */
5447c478bd9Sstevel@tonic-gate 	int			ct_powercnt_reset;
54555e592a2SRandall Ralphs 					/* ct_power_cnt was reset */
5465e3986cbScth 
5475e3986cbScth 	void			*ct_cprivate;	/* client driver private */
5487c478bd9Sstevel@tonic-gate 	void			*ct_vprivate;	/* vHCI driver private	*/
5497c478bd9Sstevel@tonic-gate } mdi_client_t;
5507c478bd9Sstevel@tonic-gate 
5517c478bd9Sstevel@tonic-gate /*
5527c478bd9Sstevel@tonic-gate  * per-Client device locking definitions
5537c478bd9Sstevel@tonic-gate  */
5545e3986cbScth #define	MDI_CLIENT_LOCK(ct)		mutex_enter(&(ct)->ct_mutex)
5555e3986cbScth #define	MDI_CLIENT_TRYLOCK(ct)		mutex_tryenter(&(ct)->ct_mutex)
5565e3986cbScth #define	MDI_CLIENT_UNLOCK(ct)		mutex_exit(&(ct)->ct_mutex)
5575e3986cbScth #ifdef	DEBUG
5585e3986cbScth #define	MDI_CLIENT_LOCKED(ct)		MUTEX_HELD(&(ct)->ct_mutex)
5595e3986cbScth #endif	/* DEBUG */
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate /*
5627c478bd9Sstevel@tonic-gate  * A Client device is in unstable while one or more paths are in transitional
5637c478bd9Sstevel@tonic-gate  * state.  We do not allow failover to take place while paths are in transient
5647c478bd9Sstevel@tonic-gate  * state. Similarly we do not allow state transition while client device
5657c478bd9Sstevel@tonic-gate  * failover is in progress.
5667c478bd9Sstevel@tonic-gate  */
5677c478bd9Sstevel@tonic-gate #define	MDI_CLIENT_UNSTABLE(ct)		(ct)->ct_unstable++;
5687c478bd9Sstevel@tonic-gate #define	MDI_CLIENT_STABLE(ct) { \
5697c478bd9Sstevel@tonic-gate 	(ct)->ct_unstable--; \
5707c478bd9Sstevel@tonic-gate 	if ((ct)->ct_unstable == 0) { \
5717c478bd9Sstevel@tonic-gate 		cv_broadcast(&(ct)->ct_unstable_cv); \
5727c478bd9Sstevel@tonic-gate 	} \
5737c478bd9Sstevel@tonic-gate }
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate /*
5767c478bd9Sstevel@tonic-gate  * Client driver instance state definitions:
5777c478bd9Sstevel@tonic-gate  */
5787c478bd9Sstevel@tonic-gate #define	MDI_CLIENT_FLAGS_OFFLINE		0x00000001
5797c478bd9Sstevel@tonic-gate #define	MDI_CLIENT_FLAGS_SUSPEND		0x00000002
5807c478bd9Sstevel@tonic-gate #define	MDI_CLIENT_FLAGS_POWER_DOWN		0x00000004
5817c478bd9Sstevel@tonic-gate #define	MDI_CLIENT_FLAGS_DETACH			0x00000008
5827c478bd9Sstevel@tonic-gate #define	MDI_CLIENT_FLAGS_FAILOVER		0x00000010
5837c478bd9Sstevel@tonic-gate #define	MDI_CLIENT_FLAGS_REPORT_DEV		0x00000020
5847c478bd9Sstevel@tonic-gate #define	MDI_CLIENT_FLAGS_PATH_FREE_IN_PROGRESS	0x00000040
5857c478bd9Sstevel@tonic-gate #define	MDI_CLIENT_FLAGS_ASYNC_FREE		0x00000080
5867c478bd9Sstevel@tonic-gate #define	MDI_CLIENT_FLAGS_DEV_NOT_SUPPORTED	0x00000100
5877c478bd9Sstevel@tonic-gate #define	MDI_CLIENT_FLAGS_POWER_TRANSITION	0x00000200
5887c478bd9Sstevel@tonic-gate 
5895e3986cbScth #define	MDI_CLIENT_SET_OFFLINE(ct)					{\
5905e3986cbScth 	    ASSERT(MDI_CLIENT_LOCKED(ct));				\
5915e3986cbScth 	    (ct)->ct_flags |= MDI_CLIENT_FLAGS_OFFLINE;			}
5925e3986cbScth #define	MDI_CLIENT_SET_ONLINE(ct)					{\
5935e3986cbScth 	    ASSERT(MDI_CLIENT_LOCKED(ct));				\
5945e3986cbScth 	    (ct)->ct_flags &= ~MDI_CLIENT_FLAGS_OFFLINE;		}
5957c478bd9Sstevel@tonic-gate #define	MDI_CLIENT_IS_OFFLINE(ct) \
5967c478bd9Sstevel@tonic-gate 	    ((ct)->ct_flags & MDI_CLIENT_FLAGS_OFFLINE)
5977c478bd9Sstevel@tonic-gate 
5985e3986cbScth #define	MDI_CLIENT_SET_SUSPEND(ct)					{\
5995e3986cbScth 	    ASSERT(MDI_CLIENT_LOCKED(ct));				\
6005e3986cbScth 	    (ct)->ct_flags |= MDI_CLIENT_FLAGS_SUSPEND;			}
6015e3986cbScth #define	MDI_CLIENT_SET_RESUME(ct)					{\
6025e3986cbScth 	    ASSERT(MDI_CLIENT_LOCKED(ct));				\
6035e3986cbScth 	    (ct)->ct_flags &= ~MDI_CLIENT_FLAGS_SUSPEND;		}
6047c478bd9Sstevel@tonic-gate #define	MDI_CLIENT_IS_SUSPENDED(ct) \
6057c478bd9Sstevel@tonic-gate 	    ((ct)->ct_flags & MDI_CLIENT_FLAGS_SUSPEND)
6067c478bd9Sstevel@tonic-gate 
6075e3986cbScth #define	MDI_CLIENT_SET_POWER_DOWN(ct)					{\
6085e3986cbScth 	    ASSERT(MDI_CLIENT_LOCKED(ct));				\
6095e3986cbScth 	    (ct)->ct_flags |= MDI_CLIENT_FLAGS_POWER_DOWN;		}
6105e3986cbScth #define	MDI_CLIENT_SET_POWER_UP(ct)					{\
6115e3986cbScth 	    ASSERT(MDI_CLIENT_LOCKED(ct));				\
6125e3986cbScth 	    (ct)->ct_flags &= ~MDI_CLIENT_FLAGS_POWER_DOWN;		}
6137c478bd9Sstevel@tonic-gate #define	MDI_CLIENT_IS_POWERED_DOWN(ct) \
6147c478bd9Sstevel@tonic-gate 	    ((ct)->ct_flags & MDI_CLIENT_FLAGS_POWER_DOWN)
6157c478bd9Sstevel@tonic-gate 
6165e3986cbScth #define	MDI_CLIENT_SET_POWER_TRANSITION(ct)				{\
6175e3986cbScth 	    ASSERT(MDI_CLIENT_LOCKED(ct));				\
6185e3986cbScth 	    (ct)->ct_flags |= MDI_CLIENT_FLAGS_POWER_TRANSITION;	}
6195e3986cbScth #define	MDI_CLIENT_CLEAR_POWER_TRANSITION(ct)				{\
6205e3986cbScth 	    ASSERT(MDI_CLIENT_LOCKED(ct));				\
6215e3986cbScth 	    (ct)->ct_flags &= ~MDI_CLIENT_FLAGS_POWER_TRANSITION;	}
6227c478bd9Sstevel@tonic-gate #define	MDI_CLIENT_IS_POWER_TRANSITION(ct) \
6237c478bd9Sstevel@tonic-gate 	    ((ct)->ct_flags & MDI_CLIENT_FLAGS_POWER_TRANSITION)
6247c478bd9Sstevel@tonic-gate 
6255e3986cbScth #define	MDI_CLIENT_SET_DETACH(ct)					{\
6265e3986cbScth 	    ASSERT(MDI_CLIENT_LOCKED(ct));				\
6275e3986cbScth 	    (ct)->ct_flags |= MDI_CLIENT_FLAGS_DETACH;			}
6285e3986cbScth #define	MDI_CLIENT_SET_ATTACH(ct)					{\
6295e3986cbScth 	    ASSERT(MDI_CLIENT_LOCKED(ct));				\
6305e3986cbScth 	    (ct)->ct_flags &= ~MDI_CLIENT_FLAGS_DETACH;			}
6317c478bd9Sstevel@tonic-gate #define	MDI_CLIENT_IS_DETACHED(ct) \
6327c478bd9Sstevel@tonic-gate 	    ((ct)->ct_flags & MDI_CLIENT_FLAGS_DETACH)
6337c478bd9Sstevel@tonic-gate 
6345e3986cbScth #define	MDI_CLIENT_SET_FAILOVER_IN_PROGRESS(ct)				{\
6355e3986cbScth 	    ASSERT(MDI_CLIENT_LOCKED(ct));				\
6365e3986cbScth 	    (ct)->ct_flags |= MDI_CLIENT_FLAGS_FAILOVER;		}
6375e3986cbScth #define	MDI_CLIENT_CLEAR_FAILOVER_IN_PROGRESS(ct)			{\
6385e3986cbScth 	    ASSERT(MDI_CLIENT_LOCKED(ct));				\
6395e3986cbScth 	    (ct)->ct_flags &= ~MDI_CLIENT_FLAGS_FAILOVER;		}
6407c478bd9Sstevel@tonic-gate #define	MDI_CLIENT_IS_FAILOVER_IN_PROGRESS(ct) \
6417c478bd9Sstevel@tonic-gate 	    ((ct)->ct_flags & MDI_CLIENT_FLAGS_FAILOVER)
6427c478bd9Sstevel@tonic-gate 
6435e3986cbScth #define	MDI_CLIENT_SET_REPORT_DEV_NEEDED(ct)				{\
6445e3986cbScth 	    ASSERT(MDI_CLIENT_LOCKED(ct));				\
6455e3986cbScth 	    (ct)->ct_flags |= MDI_CLIENT_FLAGS_REPORT_DEV;		}
6465e3986cbScth #define	MDI_CLIENT_CLEAR_REPORT_DEV_NEEDED(ct)				{\
6475e3986cbScth 	    ASSERT(MDI_CLIENT_LOCKED(ct));				\
6485e3986cbScth 	    (ct)->ct_flags &= ~MDI_CLIENT_FLAGS_REPORT_DEV;		}
6497c478bd9Sstevel@tonic-gate #define	MDI_CLIENT_IS_REPORT_DEV_NEEDED(ct) \
6507c478bd9Sstevel@tonic-gate 	    ((ct)->ct_flags & MDI_CLIENT_FLAGS_REPORT_DEV)
6517c478bd9Sstevel@tonic-gate 
6525e3986cbScth #define	MDI_CLIENT_SET_PATH_FREE_IN_PROGRESS(ct)			{\
6535e3986cbScth 	    ASSERT(MDI_CLIENT_LOCKED(ct));				\
6545e3986cbScth 	    (ct)->ct_flags |= MDI_CLIENT_FLAGS_PATH_FREE_IN_PROGRESS;	}
6555e3986cbScth #define	MDI_CLIENT_CLEAR_PATH_FREE_IN_PROGRESS(ct)			{\
6565e3986cbScth 	    ASSERT(MDI_CLIENT_LOCKED(ct));				\
6575e3986cbScth 	    (ct)->ct_flags &= ~MDI_CLIENT_FLAGS_PATH_FREE_IN_PROGRESS;	}
6587c478bd9Sstevel@tonic-gate #define	MDI_CLIENT_IS_PATH_FREE_IN_PROGRESS(ct) \
6597c478bd9Sstevel@tonic-gate 	    ((ct)->ct_flags & MDI_CLIENT_FLAGS_PATH_FREE_IN_PROGRESS)
6607c478bd9Sstevel@tonic-gate 
6615e3986cbScth #define	MDI_CLIENT_SET_DEV_NOT_SUPPORTED(ct)				{\
6625e3986cbScth 	    ASSERT(MDI_CLIENT_LOCKED(ct));				\
6635e3986cbScth 	    (ct)->ct_flags |= MDI_CLIENT_FLAGS_DEV_NOT_SUPPORTED;	}
6647c478bd9Sstevel@tonic-gate #define	MDI_CLIENT_IS_DEV_NOT_SUPPORTED(ct) \
6657c478bd9Sstevel@tonic-gate 	    ((ct)->ct_flags & MDI_CLIENT_FLAGS_DEV_NOT_SUPPORTED)
6667c478bd9Sstevel@tonic-gate 
6677c478bd9Sstevel@tonic-gate /*
6687c478bd9Sstevel@tonic-gate  * Client operating states.
6697c478bd9Sstevel@tonic-gate  */
6707c478bd9Sstevel@tonic-gate #define	MDI_CLIENT_STATE_OPTIMAL	1
6717c478bd9Sstevel@tonic-gate #define	MDI_CLIENT_STATE_DEGRADED	2
6727c478bd9Sstevel@tonic-gate #define	MDI_CLIENT_STATE_FAILED		3
6737c478bd9Sstevel@tonic-gate 
6747c478bd9Sstevel@tonic-gate #define	MDI_CLIENT_STATE(ct) ((ct)->ct_state)
6757c478bd9Sstevel@tonic-gate #define	MDI_CLIENT_SET_STATE(ct, state) ((ct)->ct_state = state)
6767c478bd9Sstevel@tonic-gate 
6777c478bd9Sstevel@tonic-gate #define	MDI_CLIENT_IS_FAILED(ct) \
6787c478bd9Sstevel@tonic-gate 	    ((ct)->ct_state == MDI_CLIENT_STATE_FAILED)
6797c478bd9Sstevel@tonic-gate 
6807c478bd9Sstevel@tonic-gate /*
6817c478bd9Sstevel@tonic-gate  * mdi_pathinfo nodes:
6827c478bd9Sstevel@tonic-gate  *
6837c478bd9Sstevel@tonic-gate  * From this framework's perspective, a 'path' is a tuple consisting of a
6847c478bd9Sstevel@tonic-gate  * client or end device, a host controller which provides device
6857c478bd9Sstevel@tonic-gate  * identification and transport services (pHCI), and bus specific unit
6867c478bd9Sstevel@tonic-gate  * addressing information.  A path may be decorated with properties which
6877c478bd9Sstevel@tonic-gate  * describe the capabilities of the path; such properties are analogous to
6887c478bd9Sstevel@tonic-gate  * device node and minor node properties.
6897c478bd9Sstevel@tonic-gate  *
6907c478bd9Sstevel@tonic-gate  * The framework maintains link list of mdi_pathinfo nodes created by every
6917c478bd9Sstevel@tonic-gate  * pHCI driver instance via the pi_phci_link linkage; this is used (for example)
6927c478bd9Sstevel@tonic-gate  * to make sure that all relevant pathinfo nodes are freed before the pHCI
6937c478bd9Sstevel@tonic-gate  * is unregistered.
6947c478bd9Sstevel@tonic-gate  *
6957c478bd9Sstevel@tonic-gate  * Locking order:
6967c478bd9Sstevel@tonic-gate  *
6975e3986cbScth  * _NOTE(LOCK_ORDER(mdi_phci::ph_mutex mdi_pathinfo::pi_mutex))		XXX
6985e3986cbScth  * _NOTE(LOCK_ORDER(mdi_client::ct_mutex mdi_pathinfo::pi_mutex))	XXX
6995e3986cbScth  * _NOTE(LOCK_ORDER(mdi_phci::ph_mutex mdi_client::ct_mutex))		XXX
7005e3986cbScth  * _NOTE(LOCK_ORDER(devinfo_tree_lock mdi_pathinfo::pi_mutex))		XXX
7017c478bd9Sstevel@tonic-gate  *
7027c478bd9Sstevel@tonic-gate  * mdi_pathinfo node structure definition
7037c478bd9Sstevel@tonic-gate  */
7047c478bd9Sstevel@tonic-gate struct mdi_pathinfo {
7055e3986cbScth 	/* protected by MDI_PHCI_LOCK ph_mutex... */
7065e3986cbScth 	struct mdi_pathinfo	*pi_phci_link;	 /* next path in phci list */
7075e3986cbScth 	mdi_phci_t		*pi_phci;	/* pHCI dev_info node	*/
7085e3986cbScth 
7095e3986cbScth 	/* protected by MDI_CLIENT_LOCK ct_mutex... */
7105e3986cbScth 	struct mdi_pathinfo	*pi_client_link; /* next path in client list */
7115e3986cbScth 	mdi_client_t		*pi_client;	/* client		*/
7125e3986cbScth 
7135e3986cbScth 	/* protected by MDI_VHCI_CLIENT_LOCK vh_client_mutex... */
7145e3986cbScth 	char			*pi_addr;	/* path unit address	*/
715602ca9eaScth 	int			pi_path_instance; /* path instance */
7165e3986cbScth 
7175e3986cbScth 	/* protected by MDI_PI_LOCK pi_mutex... */
7187c478bd9Sstevel@tonic-gate 	kmutex_t		pi_mutex;	/* per path mutex	*/
7197c478bd9Sstevel@tonic-gate 	mdi_pathinfo_state_t	pi_state;	/* path state		*/
7207c478bd9Sstevel@tonic-gate 	mdi_pathinfo_state_t	pi_old_state;	/* path state		*/
7217c478bd9Sstevel@tonic-gate 	kcondvar_t		pi_state_cv;	/* path state condvar	*/
7227c478bd9Sstevel@tonic-gate 	nvlist_t		*pi_prop;	/* Properties		*/
7237c478bd9Sstevel@tonic-gate 	void			*pi_cprivate;	/* client private info	*/
7247c478bd9Sstevel@tonic-gate 	void			*pi_pprivate;	/* phci private info	*/
7257c478bd9Sstevel@tonic-gate 	int			pi_ref_cnt;	/* pi reference count	*/
7267c478bd9Sstevel@tonic-gate 	kcondvar_t		pi_ref_cv;	/* condition variable	*/
7277c478bd9Sstevel@tonic-gate 	struct mdi_pi_kstats	*pi_kstats;	/* aggregate kstats */
7287c478bd9Sstevel@tonic-gate 	int			pi_pm_held;	/* phci's kidsup incremented */
7297c478bd9Sstevel@tonic-gate 	int			pi_preferred;	/* Preferred path	*/
7307c478bd9Sstevel@tonic-gate 	void			*pi_vprivate;	/* vhci private info	*/
731*4c06356bSdh142964 	uint_t			pi_flags;	/* path flags */
7327c478bd9Sstevel@tonic-gate };
7337c478bd9Sstevel@tonic-gate 
7347c478bd9Sstevel@tonic-gate /*
7357c478bd9Sstevel@tonic-gate  * pathinfo statistics:
7367c478bd9Sstevel@tonic-gate  *
7377c478bd9Sstevel@tonic-gate  * The mpxio architecture allows for multiple pathinfo nodes for each
7387c478bd9Sstevel@tonic-gate  * client-pHCI combination.  For statistics purposes, these statistics are
7397c478bd9Sstevel@tonic-gate  * aggregated into a single client-pHCI set of kstats.
7407c478bd9Sstevel@tonic-gate  */
7417c478bd9Sstevel@tonic-gate struct mdi_pi_kstats {
7427c478bd9Sstevel@tonic-gate 	int	pi_kstat_ref;		/* # paths aggregated, also a ref cnt */
7437c478bd9Sstevel@tonic-gate 	kstat_t	*pi_kstat_iostats;	/* mdi:iopath statistic set */
7447c478bd9Sstevel@tonic-gate 	kstat_t *pi_kstat_errstats;	/* error statistics */
7457c478bd9Sstevel@tonic-gate };
7467c478bd9Sstevel@tonic-gate 
7477c478bd9Sstevel@tonic-gate /*
7487c478bd9Sstevel@tonic-gate  * pathinfo error kstat
7497c478bd9Sstevel@tonic-gate  */
7507c478bd9Sstevel@tonic-gate struct pi_errs {
7517c478bd9Sstevel@tonic-gate 	struct kstat_named pi_softerrs;		/* "Soft" Error */
7527c478bd9Sstevel@tonic-gate 	struct kstat_named pi_harderrs;		/* "Hard" Error */
7537c478bd9Sstevel@tonic-gate 	struct kstat_named pi_transerrs;	/* Transport Errors */
7547c478bd9Sstevel@tonic-gate 	struct kstat_named pi_icnt_busy;	/* Interconnect Busy */
7557c478bd9Sstevel@tonic-gate 	struct kstat_named pi_icnt_errors;	/* Interconnect Errors */
7567c478bd9Sstevel@tonic-gate 	struct kstat_named pi_phci_rsrc;	/* pHCI No Resources */
7577c478bd9Sstevel@tonic-gate 	struct kstat_named pi_phci_localerr;	/* pHCI Local Errors */
7587c478bd9Sstevel@tonic-gate 	struct kstat_named pi_phci_invstate;	/* pHCI Invalid State */
7597c478bd9Sstevel@tonic-gate 	struct kstat_named pi_failedfrom;	/* Failover: Failed From */
7607c478bd9Sstevel@tonic-gate 	struct kstat_named pi_failedto;		/* Failover: Failed To */
7617c478bd9Sstevel@tonic-gate };
7627c478bd9Sstevel@tonic-gate 
7637c478bd9Sstevel@tonic-gate /*
7647c478bd9Sstevel@tonic-gate  * increment an error counter
7657c478bd9Sstevel@tonic-gate  */
7667c478bd9Sstevel@tonic-gate #define	MDI_PI_ERRSTAT(pip, x) { \
7677c478bd9Sstevel@tonic-gate 	if (MDI_PI((pip))->pi_kstats != NULL) { \
7687c478bd9Sstevel@tonic-gate 		struct pi_errs *pep; \
7697c478bd9Sstevel@tonic-gate 		pep = MDI_PI(pip)->pi_kstats->pi_kstat_errstats->ks_data; \
7707c478bd9Sstevel@tonic-gate 		pep->x.value.ui32++; \
7717c478bd9Sstevel@tonic-gate 	} \
7727c478bd9Sstevel@tonic-gate }
7737c478bd9Sstevel@tonic-gate 
7747c478bd9Sstevel@tonic-gate /*
7757c478bd9Sstevel@tonic-gate  * error codes which can be passed to MDI_PI_ERRSTAT
7767c478bd9Sstevel@tonic-gate  */
7777c478bd9Sstevel@tonic-gate #define	MDI_PI_SOFTERR	pi_softerrs
7787c478bd9Sstevel@tonic-gate #define	MDI_PI_HARDERR	pi_harderrs
7797c478bd9Sstevel@tonic-gate #define	MDI_PI_TRANSERR	pi_transerrs
7807c478bd9Sstevel@tonic-gate #define	MDI_PI_ICNTBUSY	pi_icnt_busy
7817c478bd9Sstevel@tonic-gate #define	MDI_PI_ICNTERR	pi_icnt_errors
7827c478bd9Sstevel@tonic-gate #define	MDI_PI_PHCIRSRC	pi_phci_rsrc
7837c478bd9Sstevel@tonic-gate #define	MDI_PI_PHCILOCL	pi_phci_localerr
7847c478bd9Sstevel@tonic-gate #define	MDI_PI_PHCIINVS	pi_phci_invstate
7857c478bd9Sstevel@tonic-gate #define	MDI_PI_FAILFROM	pi_failedfrom
7867c478bd9Sstevel@tonic-gate #define	MDI_PI_FAILTO	pi_failedto
7877c478bd9Sstevel@tonic-gate 
7887c478bd9Sstevel@tonic-gate #define	MDI_PI(type)			((struct mdi_pathinfo *)(type))
7897c478bd9Sstevel@tonic-gate 
7905e3986cbScth #define	MDI_PI_LOCK(pip)		mutex_enter(&MDI_PI(pip)->pi_mutex)
7915e3986cbScth #define	MDI_PI_TRYLOCK(pip)		mutex_tryenter(&MDI_PI(pip)->pi_mutex)
7925e3986cbScth #define	MDI_PI_UNLOCK(pip)		mutex_exit(&MDI_PI(pip)->pi_mutex)
7935e3986cbScth #ifdef	DEBUG
7945e3986cbScth #define	MDI_PI_LOCKED(pip)		MUTEX_HELD(&MDI_PI(pip)->pi_mutex)
7955e3986cbScth #endif	/* DEBUG */
7965e3986cbScth 
7975e3986cbScth #define	MDI_PI_HOLD(pip)		(++MDI_PI(pip)->pi_ref_cnt)
7985e3986cbScth #define	MDI_PI_RELE(pip)		(--MDI_PI(pip)->pi_ref_cnt)
7997c478bd9Sstevel@tonic-gate 
8007c478bd9Sstevel@tonic-gate #define	MDI_EXT_STATE_CHANGE		0x10000000
8017c478bd9Sstevel@tonic-gate 
8027c478bd9Sstevel@tonic-gate 
8037c478bd9Sstevel@tonic-gate #define	MDI_DISABLE_OP			0x1
8047c478bd9Sstevel@tonic-gate #define	MDI_ENABLE_OP			0x2
8057c478bd9Sstevel@tonic-gate #define	MDI_BEFORE_STATE_CHANGE		0x4
8067c478bd9Sstevel@tonic-gate #define	MDI_AFTER_STATE_CHANGE		0x8
8077c478bd9Sstevel@tonic-gate #define	MDI_SYNC_FLAG			0x10
8087c478bd9Sstevel@tonic-gate 
8097c478bd9Sstevel@tonic-gate #define	MDI_PI_STATE(pip)						\
8107c478bd9Sstevel@tonic-gate 	(MDI_PI((pip))->pi_state & MDI_PATHINFO_STATE_MASK)
8117c478bd9Sstevel@tonic-gate #define	MDI_PI_OLD_STATE(pip)						\
8127c478bd9Sstevel@tonic-gate 	(MDI_PI((pip))->pi_old_state & MDI_PATHINFO_STATE_MASK)
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate #define	MDI_PI_EXT_STATE(pip)						\
8157c478bd9Sstevel@tonic-gate 	(MDI_PI((pip))->pi_state & MDI_PATHINFO_EXT_STATE_MASK)
8167c478bd9Sstevel@tonic-gate #define	MDI_PI_OLD_EXT_STATE(pip)					\
8177c478bd9Sstevel@tonic-gate 	(MDI_PI((pip))->pi_old_state & MDI_PATHINFO_EXT_STATE_MASK)
8187c478bd9Sstevel@tonic-gate 
8195e3986cbScth #define	MDI_PI_SET_TRANSIENT(pip)					{\
8205e3986cbScth 	ASSERT(MDI_PI_LOCKED(pip));					\
8215e3986cbScth 	MDI_PI(pip)->pi_state |= MDI_PATHINFO_STATE_TRANSIENT;		}
8225e3986cbScth #define	MDI_PI_CLEAR_TRANSIENT(pip)					{\
8235e3986cbScth 	ASSERT(MDI_PI_LOCKED(pip));					\
8245e3986cbScth 	MDI_PI(pip)->pi_state &= ~MDI_PATHINFO_STATE_TRANSIENT;		}
8257c478bd9Sstevel@tonic-gate #define	MDI_PI_IS_TRANSIENT(pip) \
8267c478bd9Sstevel@tonic-gate 	(MDI_PI(pip)->pi_state & MDI_PATHINFO_STATE_TRANSIENT)
8277c478bd9Sstevel@tonic-gate 
8285e3986cbScth #define	MDI_PI_SET_USER_DISABLE(pip)					{\
8295e3986cbScth 	ASSERT(MDI_PI_LOCKED(pip));					\
8305e3986cbScth 	MDI_PI(pip)->pi_state |= MDI_PATHINFO_STATE_USER_DISABLE;	}
8315e3986cbScth #define	MDI_PI_SET_DRV_DISABLE(pip)					{\
8325e3986cbScth 	ASSERT(MDI_PI_LOCKED(pip));					\
8335e3986cbScth 	MDI_PI(pip)->pi_state |= MDI_PATHINFO_STATE_DRV_DISABLE;	}
8345e3986cbScth #define	MDI_PI_SET_DRV_DISABLE_TRANS(pip)				{\
8355e3986cbScth 	ASSERT(MDI_PI_LOCKED(pip));					\
8365e3986cbScth 	MDI_PI(pip)->pi_state |= MDI_PATHINFO_STATE_DRV_DISABLE_TRANSIENT; }
8377c478bd9Sstevel@tonic-gate 
8385e3986cbScth #define	MDI_PI_SET_USER_ENABLE(pip)					{\
8395e3986cbScth 	ASSERT(MDI_PI_LOCKED(pip));					\
8405e3986cbScth 	MDI_PI(pip)->pi_state &= ~MDI_PATHINFO_STATE_USER_DISABLE;	}
8415e3986cbScth #define	MDI_PI_SET_DRV_ENABLE(pip)					{\
8425e3986cbScth 	ASSERT(MDI_PI_LOCKED(pip));					\
8435e3986cbScth 	MDI_PI(pip)->pi_state &= ~MDI_PATHINFO_STATE_DRV_DISABLE;	}
8445e3986cbScth #define	MDI_PI_SET_DRV_ENABLE_TRANS(pip)				{\
8455e3986cbScth 	ASSERT(MDI_PI_LOCKED(pip));					\
8465e3986cbScth 	MDI_PI(pip)->pi_state &= ~MDI_PATHINFO_STATE_DRV_DISABLE_TRANSIENT; }
8477c478bd9Sstevel@tonic-gate 
8487c478bd9Sstevel@tonic-gate #define	MDI_PI_IS_USER_DISABLE(pip)					\
8497c478bd9Sstevel@tonic-gate 	(MDI_PI(pip)->pi_state & MDI_PATHINFO_STATE_USER_DISABLE)
8507c478bd9Sstevel@tonic-gate #define	MDI_PI_IS_DRV_DISABLE(pip)					\
8517c478bd9Sstevel@tonic-gate 	(MDI_PI(pip)->pi_state & MDI_PATHINFO_STATE_DRV_DISABLE)
8527c478bd9Sstevel@tonic-gate #define	MDI_PI_IS_DRV_DISABLE_TRANSIENT(pip)				\
8537c478bd9Sstevel@tonic-gate 	(MDI_PI(pip)->pi_state & MDI_PATHINFO_STATE_DRV_DISABLE_TRANSIENT)
8547c478bd9Sstevel@tonic-gate 
8557c478bd9Sstevel@tonic-gate #define	MDI_PI_IS_DISABLE(pip)						\
8567c478bd9Sstevel@tonic-gate 	(MDI_PI_IS_USER_DISABLE(pip) ||					\
8577c478bd9Sstevel@tonic-gate 	MDI_PI_IS_DRV_DISABLE(pip) ||					\
8587c478bd9Sstevel@tonic-gate 	MDI_PI_IS_DRV_DISABLE_TRANSIENT(pip))
8597c478bd9Sstevel@tonic-gate 
8607c478bd9Sstevel@tonic-gate #define	MDI_PI_IS_INIT(pip)						\
8617c478bd9Sstevel@tonic-gate 	((MDI_PI(pip)->pi_state & MDI_PATHINFO_STATE_MASK) ==		\
8627c478bd9Sstevel@tonic-gate 		MDI_PATHINFO_STATE_INIT)
8637c478bd9Sstevel@tonic-gate 
8647c478bd9Sstevel@tonic-gate #define	MDI_PI_IS_INITING(pip)						\
8657c478bd9Sstevel@tonic-gate 	((MDI_PI(pip)->pi_state & ~MDI_PATHINFO_EXT_STATE_MASK) ==	\
8667c478bd9Sstevel@tonic-gate 		(MDI_PATHINFO_STATE_INIT | MDI_PATHINFO_STATE_TRANSIENT))
8677c478bd9Sstevel@tonic-gate 
8685e3986cbScth #define	MDI_PI_SET_INIT(pip)						{\
8695e3986cbScth 	ASSERT(MDI_PI_LOCKED(pip));					\
8705e3986cbScth 	MDI_PI(pip)->pi_state = MDI_PATHINFO_STATE_INIT;		}
8717c478bd9Sstevel@tonic-gate 
8727c478bd9Sstevel@tonic-gate #define	MDI_PI_SET_ONLINING(pip)					{\
8737c478bd9Sstevel@tonic-gate 	uint32_t	ext_state;					\
8745e3986cbScth 	ASSERT(MDI_PI_LOCKED(pip));					\
8757c478bd9Sstevel@tonic-gate 	ext_state = MDI_PI(pip)->pi_state & MDI_PATHINFO_EXT_STATE_MASK; \
8767c478bd9Sstevel@tonic-gate 	MDI_PI(pip)->pi_old_state = MDI_PI_STATE(pip);			\
8777c478bd9Sstevel@tonic-gate 	MDI_PI(pip)->pi_state =						\
8787c478bd9Sstevel@tonic-gate 	(MDI_PATHINFO_STATE_ONLINE | MDI_PATHINFO_STATE_TRANSIENT);	\
8795e3986cbScth 	MDI_PI(pip)->pi_state |= ext_state;				}
8807c478bd9Sstevel@tonic-gate 
8817c478bd9Sstevel@tonic-gate #define	MDI_PI_IS_ONLINING(pip)						\
8827c478bd9Sstevel@tonic-gate 	((MDI_PI(pip)->pi_state & ~MDI_PATHINFO_EXT_STATE_MASK) ==	\
8837c478bd9Sstevel@tonic-gate 	(MDI_PATHINFO_STATE_ONLINE | MDI_PATHINFO_STATE_TRANSIENT))
8847c478bd9Sstevel@tonic-gate 
8857c478bd9Sstevel@tonic-gate #define	MDI_PI_SET_ONLINE(pip)						{\
8867c478bd9Sstevel@tonic-gate 	uint32_t	ext_state;					\
8875e3986cbScth 	ASSERT(MDI_PI_LOCKED(pip));					\
8887c478bd9Sstevel@tonic-gate 	ext_state = MDI_PI(pip)->pi_state & MDI_PATHINFO_EXT_STATE_MASK; \
8897c478bd9Sstevel@tonic-gate 	MDI_PI(pip)->pi_state = MDI_PATHINFO_STATE_ONLINE;		\
8905e3986cbScth 	MDI_PI(pip)->pi_state |= ext_state;				}
8917c478bd9Sstevel@tonic-gate 
8927c478bd9Sstevel@tonic-gate #define	MDI_PI_IS_ONLINE(pip)						\
8937c478bd9Sstevel@tonic-gate 	((MDI_PI(pip)->pi_state & MDI_PATHINFO_STATE_MASK) ==		\
8947c478bd9Sstevel@tonic-gate 	MDI_PATHINFO_STATE_ONLINE)
8957c478bd9Sstevel@tonic-gate 
8967c478bd9Sstevel@tonic-gate #define	MDI_PI_SET_OFFLINING(pip)					{\
8977c478bd9Sstevel@tonic-gate 	uint32_t	ext_state;					\
8985e3986cbScth 	ASSERT(MDI_PI_LOCKED(pip));					\
8997c478bd9Sstevel@tonic-gate 	ext_state = MDI_PI(pip)->pi_state & MDI_PATHINFO_EXT_STATE_MASK; \
9007c478bd9Sstevel@tonic-gate 	MDI_PI(pip)->pi_old_state = MDI_PI_STATE(pip);			\
9017c478bd9Sstevel@tonic-gate 	MDI_PI(pip)->pi_state =						\
9027c478bd9Sstevel@tonic-gate 	(MDI_PATHINFO_STATE_OFFLINE | MDI_PATHINFO_STATE_TRANSIENT);	\
9035e3986cbScth 	MDI_PI(pip)->pi_state |= ext_state;				}
9047c478bd9Sstevel@tonic-gate 
9057c478bd9Sstevel@tonic-gate #define	MDI_PI_IS_OFFLINING(pip)					\
9067c478bd9Sstevel@tonic-gate 	((MDI_PI(pip)->pi_state & ~MDI_PATHINFO_EXT_STATE_MASK) ==	\
9077c478bd9Sstevel@tonic-gate 	(MDI_PATHINFO_STATE_OFFLINE | MDI_PATHINFO_STATE_TRANSIENT))
9087c478bd9Sstevel@tonic-gate 
9097c478bd9Sstevel@tonic-gate #define	MDI_PI_SET_OFFLINE(pip)						{\
9107c478bd9Sstevel@tonic-gate 	uint32_t	ext_state;					\
9115e3986cbScth 	ASSERT(MDI_PI_LOCKED(pip));					\
9127c478bd9Sstevel@tonic-gate 	ext_state = MDI_PI(pip)->pi_state & MDI_PATHINFO_EXT_STATE_MASK; \
9137c478bd9Sstevel@tonic-gate 	MDI_PI(pip)->pi_state = MDI_PATHINFO_STATE_OFFLINE;		\
9145e3986cbScth 	MDI_PI(pip)->pi_state |= ext_state;				}
9157c478bd9Sstevel@tonic-gate 
9167c478bd9Sstevel@tonic-gate #define	MDI_PI_IS_OFFLINE(pip)						\
9177c478bd9Sstevel@tonic-gate 	((MDI_PI(pip)->pi_state & MDI_PATHINFO_STATE_MASK) ==		\
9187c478bd9Sstevel@tonic-gate 	MDI_PATHINFO_STATE_OFFLINE)
9197c478bd9Sstevel@tonic-gate 
9207c478bd9Sstevel@tonic-gate #define	MDI_PI_SET_STANDBYING(pip)					{\
9217c478bd9Sstevel@tonic-gate 	uint32_t	ext_state;					\
9225e3986cbScth 	ASSERT(MDI_PI_LOCKED(pip));					\
9237c478bd9Sstevel@tonic-gate 	ext_state = MDI_PI(pip)->pi_state & MDI_PATHINFO_EXT_STATE_MASK; \
9247c478bd9Sstevel@tonic-gate 	MDI_PI(pip)->pi_old_state = MDI_PI_STATE(pip);			\
9257c478bd9Sstevel@tonic-gate 	MDI_PI(pip)->pi_state =						\
9267c478bd9Sstevel@tonic-gate 	(MDI_PATHINFO_STATE_STANDBY | MDI_PATHINFO_STATE_TRANSIENT);	\
9275e3986cbScth 	MDI_PI(pip)->pi_state |= ext_state;				}
9287c478bd9Sstevel@tonic-gate 
9297c478bd9Sstevel@tonic-gate #define	MDI_PI_SET_STANDBY(pip)						{\
9307c478bd9Sstevel@tonic-gate 	uint32_t	ext_state;					\
9315e3986cbScth 	ASSERT(MDI_PI_LOCKED(pip));					\
9327c478bd9Sstevel@tonic-gate 	ext_state = MDI_PI(pip)->pi_state & MDI_PATHINFO_EXT_STATE_MASK; \
9337c478bd9Sstevel@tonic-gate 	MDI_PI(pip)->pi_state = MDI_PATHINFO_STATE_STANDBY;		\
9345e3986cbScth 	MDI_PI(pip)->pi_state |= ext_state;				}
9357c478bd9Sstevel@tonic-gate 
9367c478bd9Sstevel@tonic-gate #define	MDI_PI_IS_STANDBY(pip)						\
9377c478bd9Sstevel@tonic-gate 	((MDI_PI(pip)->pi_state & MDI_PATHINFO_STATE_MASK) ==		\
9387c478bd9Sstevel@tonic-gate 	MDI_PATHINFO_STATE_STANDBY)
9397c478bd9Sstevel@tonic-gate 
9407c478bd9Sstevel@tonic-gate #define	MDI_PI_SET_FAULTING(pip)					{\
9417c478bd9Sstevel@tonic-gate 	uint32_t	ext_state;					\
9425e3986cbScth 	ASSERT(MDI_PI_LOCKED(pip));					\
9437c478bd9Sstevel@tonic-gate 	ext_state = MDI_PI(pip)->pi_state & MDI_PATHINFO_EXT_STATE_MASK; \
9447c478bd9Sstevel@tonic-gate 	MDI_PI(pip)->pi_old_state = MDI_PI_STATE(pip);			\
9457c478bd9Sstevel@tonic-gate 	MDI_PI(pip)->pi_state =						\
9467c478bd9Sstevel@tonic-gate 	    (MDI_PATHINFO_STATE_FAULT | MDI_PATHINFO_STATE_TRANSIENT);	\
9475e3986cbScth 	MDI_PI(pip)->pi_state |= ext_state;				}
9487c478bd9Sstevel@tonic-gate 
9497c478bd9Sstevel@tonic-gate #define	MDI_PI_SET_FAULT(pip)						{\
9507c478bd9Sstevel@tonic-gate 	uint32_t	ext_state;					\
9515e3986cbScth 	ASSERT(MDI_PI_LOCKED(pip));					\
9527c478bd9Sstevel@tonic-gate 	ext_state = MDI_PI(pip)->pi_state & MDI_PATHINFO_EXT_STATE_MASK; \
9537c478bd9Sstevel@tonic-gate 	MDI_PI(pip)->pi_state = MDI_PATHINFO_STATE_FAULT;		\
9545e3986cbScth 	MDI_PI(pip)->pi_state |= ext_state;				}
9557c478bd9Sstevel@tonic-gate 
9567c478bd9Sstevel@tonic-gate #define	MDI_PI_IS_FAULT(pip)						\
9577c478bd9Sstevel@tonic-gate 	((MDI_PI(pip)->pi_state & MDI_PATHINFO_STATE_MASK) ==		\
9587c478bd9Sstevel@tonic-gate 	MDI_PATHINFO_STATE_FAULT)
9597c478bd9Sstevel@tonic-gate 
9607c478bd9Sstevel@tonic-gate #define	MDI_PI_IS_SUSPENDED(pip)					\
9617c478bd9Sstevel@tonic-gate 	((MDI_PI(pip))->pi_phci->ph_flags & MDI_PHCI_FLAGS_SUSPEND)
9627c478bd9Sstevel@tonic-gate 
963*4c06356bSdh142964 #define	MDI_PI_FLAGS_SET_HIDDEN(pip)					{\
964*4c06356bSdh142964 	ASSERT(MDI_PI_LOCKED(pip));					\
965*4c06356bSdh142964 	MDI_PI(pip)->pi_flags |= MDI_PATHINFO_FLAGS_HIDDEN;		}
966*4c06356bSdh142964 #define	MDI_PI_FLAGS_CLR_HIDDEN(pip)					{\
967*4c06356bSdh142964 	ASSERT(MDI_PI_LOCKED(pip));					\
968*4c06356bSdh142964 	MDI_PI(pip)->pi_flags &= ~MDI_PATHINFO_FLAGS_HIDDEN;		}
969*4c06356bSdh142964 #define	MDI_PI_FLAGS_IS_HIDDEN(pip)					\
970*4c06356bSdh142964 	((MDI_PI(pip)->pi_flags & MDI_PATHINFO_FLAGS_HIDDEN) ==		\
971*4c06356bSdh142964 	MDI_PATHINFO_FLAGS_HIDDEN)
972*4c06356bSdh142964 
973*4c06356bSdh142964 #define	MDI_PI_FLAGS_SET_DEVICE_REMOVED(pip)				{\
974*4c06356bSdh142964 	ASSERT(MDI_PI_LOCKED(pip));					\
975*4c06356bSdh142964 	MDI_PI(pip)->pi_flags |= MDI_PATHINFO_FLAGS_DEVICE_REMOVED;	}
976*4c06356bSdh142964 #define	MDI_PI_FLAGS_CLR_DEVICE_REMOVED(pip)				{\
977*4c06356bSdh142964 	ASSERT(MDI_PI_LOCKED(pip));					\
978*4c06356bSdh142964 	MDI_PI(pip)->pi_flags &= ~MDI_PATHINFO_FLAGS_DEVICE_REMOVED;	}
979*4c06356bSdh142964 #define	MDI_PI_FLAGS_IS_DEVICE_REMOVED(pip)				\
980*4c06356bSdh142964 	((MDI_PI(pip)->pi_flags & MDI_PATHINFO_FLAGS_DEVICE_REMOVED) ==	\
981*4c06356bSdh142964 	MDI_PATHINFO_FLAGS_DEVICE_REMOVED)
982*4c06356bSdh142964 
9837c478bd9Sstevel@tonic-gate /*
9843c34adc5Sramat  * mdi_vhcache_client, mdi_vhcache_pathinfo, and mdi_vhcache_phci structures
9853c34adc5Sramat  * hold the vhci to phci client mappings of the on-disk vhci busconfig cache.
9863c34adc5Sramat  */
9873c34adc5Sramat 
9883c34adc5Sramat /* phci structure of vhci cache */
9893c34adc5Sramat typedef struct mdi_vhcache_phci {
9903c34adc5Sramat 	char			*cphci_path;	/* phci path name */
9913c34adc5Sramat 	uint32_t		cphci_id;	/* used when building nvlist */
9923c34adc5Sramat 	mdi_phci_t		*cphci_phci;	/* pointer to actual phci */
9933c34adc5Sramat 	struct mdi_vhcache_phci	*cphci_next;	/* next in vhci phci list */
9943c34adc5Sramat } mdi_vhcache_phci_t;
9953c34adc5Sramat 
9963c34adc5Sramat /* pathinfo structure of vhci cache */
9973c34adc5Sramat typedef struct mdi_vhcache_pathinfo {
9983c34adc5Sramat 	char			*cpi_addr;	/* path address */
9993c34adc5Sramat 	mdi_vhcache_phci_t	*cpi_cphci;	/* phci the path belongs to */
10003c34adc5Sramat 	struct mdi_pathinfo	*cpi_pip;	/* ptr to actual pathinfo */
10013c34adc5Sramat 	uint32_t		cpi_flags;	/* see below */
10023c34adc5Sramat 	struct mdi_vhcache_pathinfo *cpi_next;	/* next path for the client */
10033c34adc5Sramat } mdi_vhcache_pathinfo_t;
10043c34adc5Sramat 
10053c34adc5Sramat /*
10063c34adc5Sramat  * cpi_flags
10073c34adc5Sramat  *
10083c34adc5Sramat  * MDI_CPI_HINT_PATH_DOES_NOT_EXIST - set when configuration of the path has
10093c34adc5Sramat  * failed.
10103c34adc5Sramat  */
10113c34adc5Sramat #define	MDI_CPI_HINT_PATH_DOES_NOT_EXIST	0x0001
10123c34adc5Sramat 
10133c34adc5Sramat /* client structure of vhci cache */
10143c34adc5Sramat typedef struct mdi_vhcache_client {
10153c34adc5Sramat 	char			*cct_name_addr;	/* client address */
10163c34adc5Sramat 	mdi_vhcache_pathinfo_t	*cct_cpi_head;	/* client's path list head */
10173c34adc5Sramat 	mdi_vhcache_pathinfo_t	*cct_cpi_tail;	/* client's path list tail */
10183c34adc5Sramat 	struct mdi_vhcache_client *cct_next;	/* next in vhci client list */
10193c34adc5Sramat } mdi_vhcache_client_t;
10203c34adc5Sramat 
10213c34adc5Sramat /* vhci cache structure - one for vhci instance */
10223c34adc5Sramat typedef struct mdi_vhci_cache {
10233c34adc5Sramat 	mdi_vhcache_phci_t	*vhcache_phci_head;	/* phci list head */
10243c34adc5Sramat 	mdi_vhcache_phci_t	*vhcache_phci_tail;	/* phci list tail */
10253c34adc5Sramat 	mdi_vhcache_client_t	*vhcache_client_head;	/* client list head */
10263c34adc5Sramat 	mdi_vhcache_client_t	*vhcache_client_tail;	/* client list tail */
10273c34adc5Sramat 	mod_hash_t		*vhcache_client_hash;	/* client hash */
10283c34adc5Sramat 	int			vhcache_flags;		/* see below */
10293c34adc5Sramat 	int64_t			vhcache_clean_time;	/* last clean time */
10303c34adc5Sramat 	krwlock_t		vhcache_lock;		/* cache lock */
10313c34adc5Sramat } mdi_vhci_cache_t;
10323c34adc5Sramat 
10333c34adc5Sramat /* vhcache_flags */
10343c34adc5Sramat #define	MDI_VHCI_CACHE_SETUP_DONE	0x0001	/* cache setup completed */
10353c34adc5Sramat 
10363c34adc5Sramat /* vhci bus config structure - one for vhci instance */
10373c34adc5Sramat typedef struct mdi_vhci_config {
10383c34adc5Sramat 	char			*vhc_vhcache_filename;	/* on-disk file name */
10393c34adc5Sramat 	mdi_vhci_cache_t	vhc_vhcache;		/* vhci cache */
10403c34adc5Sramat 	kmutex_t		vhc_lock;		/* vhci config lock */
10413c34adc5Sramat 	kcondvar_t		vhc_cv;
10423c34adc5Sramat 	int			vhc_flags;		/* see below */
10433c34adc5Sramat 
10443c34adc5Sramat 	/* flush vhci cache when lbolt reaches vhc_flush_at_ticks */
10453c34adc5Sramat 	clock_t			vhc_flush_at_ticks;
10463c34adc5Sramat 
10473c34adc5Sramat 	/*
10483c34adc5Sramat 	 * Head and tail of the client list whose paths are being configured
10493c34adc5Sramat 	 * asynchronously. vhc_acc_count is the number of clients on this list.
10503c34adc5Sramat 	 * vhc_acc_thrcount is the number threads running to configure
10513c34adc5Sramat 	 * the paths for these clients.
10523c34adc5Sramat 	 */
10533c34adc5Sramat 	struct mdi_async_client_config *vhc_acc_list_head;
10543c34adc5Sramat 	struct mdi_async_client_config *vhc_acc_list_tail;
10553c34adc5Sramat 	int			vhc_acc_count;
10563c34adc5Sramat 	int			vhc_acc_thrcount;
10573c34adc5Sramat 
10583c34adc5Sramat 	/* callback id - for flushing the cache during system shutdown */
10593c34adc5Sramat 	callb_id_t		vhc_cbid;
106067e56d35Sramat 
106167e56d35Sramat 	/*
106267e56d35Sramat 	 * vhc_path_discovery_boot -	number of times path discovery will be
106367e56d35Sramat 	 *				attempted during early boot.
106467e56d35Sramat 	 * vhc_path_discovery_postboot	number of times path discovery will be
106567e56d35Sramat 	 *				attempted during late boot.
106667e56d35Sramat 	 * vhc_path_discovery_cutoff_time - time at which paths were last
106767e56d35Sramat 	 *				discovered  + some timeout
106867e56d35Sramat 	 */
106967e56d35Sramat 	int			vhc_path_discovery_boot;
107067e56d35Sramat 	int			vhc_path_discovery_postboot;
107167e56d35Sramat 	int64_t			vhc_path_discovery_cutoff_time;
10723c34adc5Sramat } mdi_vhci_config_t;
10733c34adc5Sramat 
10743c34adc5Sramat /* vhc_flags */
10753c34adc5Sramat #define	MDI_VHC_SINGLE_THREADED		0x0001	/* config single threaded */
10763c34adc5Sramat #define	MDI_VHC_EXIT			0x0002	/* exit all config activity */
10773c34adc5Sramat #define	MDI_VHC_VHCACHE_DIRTY		0x0004	/* cache dirty */
10783c34adc5Sramat #define	MDI_VHC_VHCACHE_FLUSH_THREAD	0x0008	/* cache flush thead running */
10793c34adc5Sramat #define	MDI_VHC_VHCACHE_FLUSH_ERROR	0x0010	/* failed to flush cache */
10803c34adc5Sramat #define	MDI_VHC_READONLY_FS		0x0020	/* filesys is readonly */
10813c34adc5Sramat 
10823c34adc5Sramat typedef struct mdi_phys_path {
10833c34adc5Sramat 	char			*phys_path;
10843c34adc5Sramat 	struct mdi_phys_path	*phys_path_next;
10853c34adc5Sramat } mdi_phys_path_t;
10863c34adc5Sramat 
10873c34adc5Sramat /*
10883c34adc5Sramat  * Lookup tokens are used to cache the result of the vhci cache client lookup
10893c34adc5Sramat  * operations (to reduce the number of real lookup operations).
10903c34adc5Sramat  */
10913c34adc5Sramat typedef struct mdi_vhcache_lookup_token {
10923c34adc5Sramat 	mdi_vhcache_client_t	*lt_cct;		/* vhcache client */
10933c34adc5Sramat 	int64_t			lt_cct_lookup_time;	/* last lookup time */
10943c34adc5Sramat } mdi_vhcache_lookup_token_t;
10953c34adc5Sramat 
10963c34adc5Sramat /* asynchronous configuration of client paths */
10973c34adc5Sramat typedef struct mdi_async_client_config {
10983c34adc5Sramat 	char			*acc_ct_name;	/* client name */
10993c34adc5Sramat 	char			*acc_ct_addr;	/* client address */
11003c34adc5Sramat 	mdi_phys_path_t		*acc_phclient_path_list_head;	/* path head */
11013c34adc5Sramat 	mdi_vhcache_lookup_token_t acc_token;	/* lookup token */
11023c34adc5Sramat 	struct mdi_async_client_config *acc_next; /* next in vhci acc list */
11033c34adc5Sramat } mdi_async_client_config_t;
11043c34adc5Sramat 
11053c34adc5Sramat /*
11067c478bd9Sstevel@tonic-gate  * vHCI driver instance registration/unregistration
11077c478bd9Sstevel@tonic-gate  *
11087c478bd9Sstevel@tonic-gate  * mdi_vhci_register() is called by a vHCI driver to register itself as the
11097c478bd9Sstevel@tonic-gate  * manager of devices from a particular 'class'.  This should be called from
11107c478bd9Sstevel@tonic-gate  * attach(9e).
11117c478bd9Sstevel@tonic-gate  *
11127c478bd9Sstevel@tonic-gate  * mdi_vhci_unregister() is called from detach(9E) to unregister a vHCI
11137c478bd9Sstevel@tonic-gate  * instance from the framework.
11147c478bd9Sstevel@tonic-gate  */
11157c478bd9Sstevel@tonic-gate int		mdi_vhci_register(char *, dev_info_t *, mdi_vhci_ops_t *, int);
11167c478bd9Sstevel@tonic-gate int		mdi_vhci_unregister(dev_info_t *, int);
11177c478bd9Sstevel@tonic-gate 
11187c478bd9Sstevel@tonic-gate /*
11197c478bd9Sstevel@tonic-gate  * Utility functions
11207c478bd9Sstevel@tonic-gate  */
11217c478bd9Sstevel@tonic-gate int		mdi_phci_get_path_count(dev_info_t *);
11227c478bd9Sstevel@tonic-gate dev_info_t	*mdi_phci_path2devinfo(dev_info_t *, caddr_t);
11237c478bd9Sstevel@tonic-gate 
11247c478bd9Sstevel@tonic-gate 
11257c478bd9Sstevel@tonic-gate /*
11267c478bd9Sstevel@tonic-gate  * Path Selection Functions:
11277c478bd9Sstevel@tonic-gate  *
11287c478bd9Sstevel@tonic-gate  * mdi_select_path() is called by a vHCI driver to select to which path an
11297c478bd9Sstevel@tonic-gate  * I/O request should be routed.  The caller passes the 'buf' structure as
11307c478bd9Sstevel@tonic-gate  * one of the parameters.  The mpxio framework uses the buf's contents to
11317c478bd9Sstevel@tonic-gate  * maintain per path statistics (total I/O size / count pending).  If more
11327c478bd9Sstevel@tonic-gate  * than one online path is available, the framework automatically selects
11337c478bd9Sstevel@tonic-gate  * a suitable one.  If a failover operation is active for this client device
11347c478bd9Sstevel@tonic-gate  * the call fails, returning MDI_BUSY.
11357c478bd9Sstevel@tonic-gate  *
11367c478bd9Sstevel@tonic-gate  * By default this function returns a suitable path in the 'online' state,
11377c478bd9Sstevel@tonic-gate  * based on the current load balancing policy.  Currently we support
11387c478bd9Sstevel@tonic-gate  * LOAD_BALANCE_NONE (Previously selected online path will continue to be
11397c478bd9Sstevel@tonic-gate  * used as long as the path is usable) and LOAD_BALANCE_RR (Online paths
11407c478bd9Sstevel@tonic-gate  * will be selected in a round robin fashion).  The load balancing scheme
11417c478bd9Sstevel@tonic-gate  * can be configured in the vHCI driver's configuration file (driver.conf).
11427c478bd9Sstevel@tonic-gate  *
114355e592a2SRandall Ralphs  * vHCI drivers may override this default behavior by specifying appropriate
11447c478bd9Sstevel@tonic-gate  * flags.  If start_pip is specified (non NULL), it is used as the routine's
11457c478bd9Sstevel@tonic-gate  * starting point; it starts walking from there to find the next appropriate
11467c478bd9Sstevel@tonic-gate  * path.
11477c478bd9Sstevel@tonic-gate  *
1148602ca9eaScth  * The following values for 'flags' are currently defined, the third argument
1149602ca9eaScth  * to mdi_select_path depends on the flags used.
11507c478bd9Sstevel@tonic-gate  *
1151602ca9eaScth  *   <none>:				default, arg is pip
1152b08fdaf7SSheshadri Vasudevan  *   MDI_SELECT_ONLINE_PATH:		select an ONLINE path preferred-first,
1153b08fdaf7SSheshadri Vasudevan  *					arg is pip
1154602ca9eaScth  *   MDI_SELECT_STANDBY_PATH:		select a STANDBY path, arg is pip
1155ee28b439Scm136836  *   MDI_SELECT_USER_DISABLE_PATH:	select user disable for failover and
1156ee28b439Scm136836  *					auto_failback
1157602ca9eaScth  *   MDI_SELECT_PATH_INSTANCE:		select a specific path, arg is
1158602ca9eaScth  *					path instance
1159b08fdaf7SSheshadri Vasudevan  *   MDI_SELECT_NO_PREFERRED:		select path without preferred-first
11607c478bd9Sstevel@tonic-gate  *
11615e3986cbScth  * The selected paths are returned in an mdi_hold_path() state (pi_ref_cnt),
11625e3986cbScth  * caller should release the hold by calling mdi_rele_path() at the end of
11635e3986cbScth  * operation.
11647c478bd9Sstevel@tonic-gate  */
11657c478bd9Sstevel@tonic-gate int		mdi_select_path(dev_info_t *, struct buf *, int,
1166602ca9eaScth 		    void *, mdi_pathinfo_t **);
11677c478bd9Sstevel@tonic-gate int		mdi_set_lb_policy(dev_info_t *, client_lb_t);
11687c478bd9Sstevel@tonic-gate int		mdi_set_lb_region_size(dev_info_t *, int);
11697c478bd9Sstevel@tonic-gate client_lb_t	mdi_get_lb_policy(dev_info_t *);
11707c478bd9Sstevel@tonic-gate 
11717c478bd9Sstevel@tonic-gate /*
11727c478bd9Sstevel@tonic-gate  * flags for mdi_select_path() routine
11737c478bd9Sstevel@tonic-gate  */
11747c478bd9Sstevel@tonic-gate #define	MDI_SELECT_ONLINE_PATH		0x0001
11757c478bd9Sstevel@tonic-gate #define	MDI_SELECT_STANDBY_PATH		0x0002
1176ee28b439Scm136836 #define	MDI_SELECT_USER_DISABLE_PATH	0x0004
1177602ca9eaScth #define	MDI_SELECT_PATH_INSTANCE	0x0008
1178b08fdaf7SSheshadri Vasudevan #define	MDI_SELECT_NO_PREFERRED		0x0010
11797c478bd9Sstevel@tonic-gate 
11807c478bd9Sstevel@tonic-gate /*
11817c478bd9Sstevel@tonic-gate  * MDI client device utility functions
11827c478bd9Sstevel@tonic-gate  */
11837c478bd9Sstevel@tonic-gate int		mdi_client_get_path_count(dev_info_t *);
11847c478bd9Sstevel@tonic-gate dev_info_t	*mdi_client_path2devinfo(dev_info_t *, caddr_t);
11857c478bd9Sstevel@tonic-gate 
11867c478bd9Sstevel@tonic-gate /*
11877c478bd9Sstevel@tonic-gate  * Failover:
11887c478bd9Sstevel@tonic-gate  *
11897c478bd9Sstevel@tonic-gate  * The vHCI driver calls mdi_failover() to initiate a failover operation.
11907c478bd9Sstevel@tonic-gate  * mdi_failover() calls back into the vHCI driver's vo_failover()
11917c478bd9Sstevel@tonic-gate  * entry point to perform the actual failover operation.  The reason
11927c478bd9Sstevel@tonic-gate  * for requiring the vHCI driver to initiate failover by calling
11937c478bd9Sstevel@tonic-gate  * mdi_failover(), instead of directly executing vo_failover() itself,
11947c478bd9Sstevel@tonic-gate  * is to ensure that the mdi framework can keep track of the client
11957c478bd9Sstevel@tonic-gate  * state properly.  Additionally, mdi_failover() provides as a
11967c478bd9Sstevel@tonic-gate  * convenience the option of performing the failover operation
11977c478bd9Sstevel@tonic-gate  * synchronously or asynchronously
11987c478bd9Sstevel@tonic-gate  *
11997c478bd9Sstevel@tonic-gate  * Upon successful completion of the failover operation, the paths that were
12007c478bd9Sstevel@tonic-gate  * previously ONLINE will be in the STANDBY state, and the newly activated
12017c478bd9Sstevel@tonic-gate  * paths will be in the ONLINE state.
12027c478bd9Sstevel@tonic-gate  *
12037c478bd9Sstevel@tonic-gate  * The flags modifier determines whether the activation is done synchronously
12047c478bd9Sstevel@tonic-gate  */
12057c478bd9Sstevel@tonic-gate int mdi_failover(dev_info_t *, dev_info_t *, int);
12067c478bd9Sstevel@tonic-gate 
12077c478bd9Sstevel@tonic-gate /*
12087c478bd9Sstevel@tonic-gate  * Client device failover mode of operation
12097c478bd9Sstevel@tonic-gate  */
121055e592a2SRandall Ralphs #define	MDI_FAILOVER_SYNC	1	/* Synchronous Failover		*/
121155e592a2SRandall Ralphs #define	MDI_FAILOVER_ASYNC	2	/* Asynchronous Failover	*/
121255e592a2SRandall Ralphs 
121355e592a2SRandall Ralphs /*
121455e592a2SRandall Ralphs  * mdi_is_dev_supported: The pHCI driver bus_config implementation calls
121555e592a2SRandall Ralphs  * mdi_is_dev_supported to determine if a child device should is supported as
121655e592a2SRandall Ralphs  * a vHCI child (i.e. as a client). The method used to specify the child
121755e592a2SRandall Ralphs  * device, via the cinfo argument, is by agreement between the pHCI and the
121855e592a2SRandall Ralphs  * vHCI.  In the case of SCSA and scsi_vhci cinfo is a pointer to the pHCI
121955e592a2SRandall Ralphs  * probe dev_info node, which is decorated with the device idenity information
122055e592a2SRandall Ralphs  * necessary to determine scsi_vhci support.
122155e592a2SRandall Ralphs  */
122255e592a2SRandall Ralphs int mdi_is_dev_supported(char *class, dev_info_t *pdip, void *cinfo);
12237c478bd9Sstevel@tonic-gate 
12247c478bd9Sstevel@tonic-gate /*
122537fbbce5Scth  * mdi_pathinfo node kstat functions.
12267c478bd9Sstevel@tonic-gate  */
122737fbbce5Scth int mdi_pi_kstat_exists(mdi_pathinfo_t *);
122837fbbce5Scth int mdi_pi_kstat_create(mdi_pathinfo_t *pip, char *ks_name);
12297c478bd9Sstevel@tonic-gate void mdi_pi_kstat_iosupdate(mdi_pathinfo_t *, struct buf *);
12307c478bd9Sstevel@tonic-gate 
12317c478bd9Sstevel@tonic-gate /*
12327c478bd9Sstevel@tonic-gate  * mdi_pathinfo node extended state change functions.
12337c478bd9Sstevel@tonic-gate  */
12347c478bd9Sstevel@tonic-gate int mdi_pi_get_state2(mdi_pathinfo_t *, mdi_pathinfo_state_t *, uint32_t *);
12357c478bd9Sstevel@tonic-gate int mdi_pi_get_preferred(mdi_pathinfo_t *);
12367c478bd9Sstevel@tonic-gate 
12377c478bd9Sstevel@tonic-gate /*
12387c478bd9Sstevel@tonic-gate  * mdi_pathinfo node member functions
12397c478bd9Sstevel@tonic-gate  */
12407c478bd9Sstevel@tonic-gate void *mdi_pi_get_client_private(mdi_pathinfo_t *);
12417c478bd9Sstevel@tonic-gate void mdi_pi_set_client_private(mdi_pathinfo_t *, void *);
12427c478bd9Sstevel@tonic-gate void mdi_pi_set_state(mdi_pathinfo_t *, mdi_pathinfo_state_t);
12437c478bd9Sstevel@tonic-gate void mdi_pi_set_preferred(mdi_pathinfo_t *, int);
12447c478bd9Sstevel@tonic-gate 
12457c478bd9Sstevel@tonic-gate /* get/set vhci private data */
12467c478bd9Sstevel@tonic-gate void *mdi_client_get_vhci_private(dev_info_t *);
12477c478bd9Sstevel@tonic-gate void mdi_client_set_vhci_private(dev_info_t *, void *);
12487c478bd9Sstevel@tonic-gate void *mdi_phci_get_vhci_private(dev_info_t *);
12497c478bd9Sstevel@tonic-gate void mdi_phci_set_vhci_private(dev_info_t *, void *);
12507c478bd9Sstevel@tonic-gate void *mdi_pi_get_vhci_private(mdi_pathinfo_t *);
12517c478bd9Sstevel@tonic-gate void mdi_pi_set_vhci_private(mdi_pathinfo_t *, void *);
125255e592a2SRandall Ralphs int mdi_dc_return_dev_state(mdi_pathinfo_t *pip, struct devctl_iocdata *dcp);
12537c478bd9Sstevel@tonic-gate 
12547c478bd9Sstevel@tonic-gate /*
12557c478bd9Sstevel@tonic-gate  * mdi_pathinfo Property utilities
12567c478bd9Sstevel@tonic-gate  */
12577c478bd9Sstevel@tonic-gate int mdi_prop_size(mdi_pathinfo_t *, size_t *);
12587c478bd9Sstevel@tonic-gate int mdi_prop_pack(mdi_pathinfo_t *, char **, uint_t);
12597c478bd9Sstevel@tonic-gate 
12607c478bd9Sstevel@tonic-gate /* obsolete interface, to be removed */
12617c478bd9Sstevel@tonic-gate void mdi_get_next_path(dev_info_t *, mdi_pathinfo_t *, mdi_pathinfo_t **);
12627c478bd9Sstevel@tonic-gate int mdi_get_component_type(dev_info_t *);
12637c478bd9Sstevel@tonic-gate 
12647c478bd9Sstevel@tonic-gate #endif	/* _KERNEL */
12657c478bd9Sstevel@tonic-gate 
12667c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
12677c478bd9Sstevel@tonic-gate }
12687c478bd9Sstevel@tonic-gate #endif
12697c478bd9Sstevel@tonic-gate 
12707c478bd9Sstevel@tonic-gate #endif	/* _SYS_MDI_IMPLDEFS_H */
1271