#ifndef _SYS_MDI_IMPLDEFS_H
#define _SYS_MDI_IMPLDEFS_H
#include <sys/note.h>
#include <sys/types.h>
#include <sys/sunmdi.h>
#include <sys/modhash.h>
#include <sys/callb.h>
#include <sys/devctl.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _KERNEL
extern const char *mdi_client_guid_prop;
#define MDI_CLIENT_GUID_PROP (char *)mdi_client_guid_prop
typedef enum {
LOAD_BALANCE_NONE,
LOAD_BALANCE_RR,
LOAD_BALANCE_LBA
} client_lb_t;
typedef struct {
int region_size;
}client_lb_args_t;
extern const char *mdi_load_balance;
extern const char *mdi_load_balance_none;
extern const char *mdi_load_balance_ap;
extern const char *mdi_load_balance_rr;
extern const char *mdi_load_balance_lba;
#define LOAD_BALANCE_PROP (char *)mdi_load_balance
#define LOAD_BALANCE_PROP_NONE (char *)mdi_load_balance_none
#define LOAD_BALANCE_PROP_AP (char *)mdi_load_balance_ap
#define LOAD_BALANCE_PROP_RR (char *)mdi_load_balance_rr
#define LOAD_BALANCE_PROP_LBA (char *)mdi_load_balance_lba
#define LOAD_BALANCE_DEFAULT_REGION_SIZE 18
#define MDI_VHCI_OPS_REV_1 1
#define MDI_VHCI_OPS_REV MDI_VHCI_OPS_REV_1
typedef struct mdi_vhci_ops {
int vo_revision;
int (*vo_pi_init)(dev_info_t *vdip, mdi_pathinfo_t *pip, int flags);
int (*vo_pi_uninit)(dev_info_t *vdip, mdi_pathinfo_t *pip,
int flags);
int (*vo_pi_state_change)(dev_info_t *vdip, mdi_pathinfo_t *pip,
mdi_pathinfo_state_t state, uint32_t, int flags);
int (*vo_failover)(dev_info_t *vdip, dev_info_t *cdip, int flags);
void (*vo_client_attached)(dev_info_t *cdip);
int (*vo_is_dev_supported)(dev_info_t *vdip, dev_info_t *pdip,
void *cinfo);
} mdi_vhci_ops_t;
typedef struct mdi_vhci {
struct mdi_vhci *vh_next;
struct mdi_vhci *vh_prev;
char *vh_class;
dev_info_t *vh_dip;
int vh_refcnt;
struct mdi_vhci_config *vh_config;
client_lb_t vh_lb;
struct mdi_vhci_ops *vh_ops;
kmutex_t vh_phci_mutex;
int vh_phci_count;
struct mdi_phci *vh_phci_head;
struct mdi_phci *vh_phci_tail;
kmutex_t vh_client_mutex;
int vh_client_count;
struct client_hash *vh_client_table;
} mdi_vhci_t;
#define MDI_VHCI_PHCI_LOCK(vh) mutex_enter(&(vh)->vh_phci_mutex)
#define MDI_VHCI_PHCI_TRYLOCK(vh) mutex_tryenter(&(vh)->vh_phci_mutex)
#define MDI_VHCI_PHCI_UNLOCK(vh) mutex_exit(&(vh)->vh_phci_mutex)
#ifdef DEBUG
#define MDI_VHCI_PCHI_LOCKED(vh) MUTEX_HELD(&(vh)->vh_phci_mutex)
#endif
#define MDI_VHCI_CLIENT_LOCK(vh) mutex_enter(&(vh)->vh_client_mutex)
#define MDI_VHCI_CLIENT_TRYLOCK(vh) mutex_tryenter(&(vh)->vh_client_mutex)
#define MDI_VHCI_CLIENT_UNLOCK(vh) mutex_exit(&(vh)->vh_client_mutex)
#ifdef DEBUG
#define MDI_VHCI_CLIENT_LOCKED(vh) MUTEX_HELD(&(vh)->vh_client_mutex)
#endif
#define CLIENT_HASH_TABLE_SIZE (32)
struct client_hash {
struct mdi_client *ct_hash_head;
int ct_hash_count;
};
typedef struct mdi_phci {
struct mdi_phci *ph_next;
struct mdi_phci *ph_prev;
dev_info_t *ph_dip;
struct mdi_vhci *ph_vhci;
kmutex_t ph_mutex;
int ph_path_count;
mdi_pathinfo_t *ph_path_head;
mdi_pathinfo_t *ph_path_tail;
int ph_flags;
int ph_unstable;
kcondvar_t ph_unstable_cv;
void *ph_vprivate;
} mdi_phci_t;
#define MDI_PHCI_UNSTABLE(ph) (ph)->ph_unstable++;
#define MDI_PHCI_STABLE(ph) { \
(ph)->ph_unstable--; \
if ((ph)->ph_unstable == 0) { \
cv_broadcast(&(ph)->ph_unstable_cv); \
} \
}
#define MDI_PHCI_LOCK(ph) mutex_enter(&(ph)->ph_mutex)
#define MDI_PHCI_TRYLOCK(ph) mutex_tryenter(&(ph)->ph_mutex)
#define MDI_PHCI_UNLOCK(ph) mutex_exit(&(ph)->ph_mutex)
#ifdef DEBUG
#define MDI_PHCI_LOCKED(vh) MUTEX_HELD(&(ph)->ph_mutex)
#endif
#define MDI_PHCI_FLAGS_OFFLINE 0x1
#define MDI_PHCI_FLAGS_SUSPEND 0x2
#define MDI_PHCI_FLAGS_POWER_DOWN 0x4
#define MDI_PHCI_FLAGS_DETACH 0x8
#define MDI_PHCI_FLAGS_USER_DISABLE 0x10
#define MDI_PHCI_FLAGS_D_DISABLE 0x20
#define MDI_PHCI_FLAGS_D_DISABLE_TRANS 0x40
#define MDI_PHCI_FLAGS_POWER_TRANSITION 0x80
#define MDI_PHCI_DISABLE_MASK \
(MDI_PHCI_FLAGS_USER_DISABLE | MDI_PHCI_FLAGS_D_DISABLE | \
MDI_PHCI_FLAGS_D_DISABLE_TRANS)
#define MDI_PHCI_IS_READY(ph) \
(((ph)->ph_flags & MDI_PHCI_DISABLE_MASK) == 0)
#define MDI_PHCI_SET_OFFLINE(ph) {\
ASSERT(MDI_PHCI_LOCKED(ph)); \
(ph)->ph_flags |= MDI_PHCI_FLAGS_OFFLINE; }
#define MDI_PHCI_SET_ONLINE(ph) {\
ASSERT(MDI_PHCI_LOCKED(ph)); \
(ph)->ph_flags &= ~MDI_PHCI_FLAGS_OFFLINE; }
#define MDI_PHCI_IS_OFFLINE(ph) \
((ph)->ph_flags & MDI_PHCI_FLAGS_OFFLINE)
#define MDI_PHCI_SET_SUSPEND(ph) {\
ASSERT(MDI_PHCI_LOCKED(ph)); \
(ph)->ph_flags |= MDI_PHCI_FLAGS_SUSPEND; }
#define MDI_PHCI_SET_RESUME(ph) {\
ASSERT(MDI_PHCI_LOCKED(ph)); \
(ph)->ph_flags &= ~MDI_PHCI_FLAGS_SUSPEND; }
#define MDI_PHCI_IS_SUSPENDED(ph) \
((ph)->ph_flags & MDI_PHCI_FLAGS_SUSPEND)
#define MDI_PHCI_SET_DETACH(ph) {\
ASSERT(MDI_PHCI_LOCKED(ph)); \
(ph)->ph_flags |= MDI_PHCI_FLAGS_DETACH; }
#define MDI_PHCI_SET_ATTACH(ph) {\
ASSERT(MDI_PHCI_LOCKED(ph)); \
(ph)->ph_flags &= ~MDI_PHCI_FLAGS_DETACH; }
#define MDI_PHCI_SET_POWER_DOWN(ph) {\
ASSERT(MDI_PHCI_LOCKED(ph)); \
(ph)->ph_flags |= MDI_PHCI_FLAGS_POWER_DOWN; }
#define MDI_PHCI_SET_POWER_UP(ph) {\
ASSERT(MDI_PHCI_LOCKED(ph)); \
(ph)->ph_flags &= ~MDI_PHCI_FLAGS_POWER_DOWN; }
#define MDI_PHCI_IS_POWERED_DOWN(ph) \
((ph)->ph_flags & MDI_PHCI_FLAGS_POWER_DOWN)
#define MDI_PHCI_SET_USER_ENABLE(ph) {\
ASSERT(MDI_PHCI_LOCKED(ph)); \
(ph)->ph_flags &= ~MDI_PHCI_FLAGS_USER_DISABLE; }
#define MDI_PHCI_SET_USER_DISABLE(ph) {\
ASSERT(MDI_PHCI_LOCKED(ph)); \
(ph)->ph_flags |= MDI_PHCI_FLAGS_USER_DISABLE; }
#define MDI_PHCI_IS_USER_DISABLED(ph) \
((ph)->ph_flags & MDI_PHCI_FLAGS_USER_DISABLE)
#define MDI_PHCI_SET_DRV_ENABLE(ph) {\
ASSERT(MDI_PHCI_LOCKED(ph)); \
(ph)->ph_flags &= ~MDI_PHCI_FLAGS_D_DISABLE; }
#define MDI_PHCI_SET_DRV_DISABLE(ph) {\
ASSERT(MDI_PHCI_LOCKED(ph)); \
(ph)->ph_flags |= MDI_PHCI_FLAGS_D_DISABLE; }
#define MDI_PHCI_IS_DRV_DISABLED(ph) \
((ph)->ph_flags & MDI_PHCI_FLAGS_D_DISABLE)
#define MDI_PHCI_SET_DRV_ENABLE_TRANSIENT(ph) {\
ASSERT(MDI_PHCI_LOCKED(ph)); \
(ph)->ph_flags &= ~MDI_PHCI_FLAGS_D_DISABLE_TRANS; }
#define MDI_PHCI_SET_DRV_DISABLE_TRANSIENT(ph) {\
ASSERT(MDI_PHCI_LOCKED(ph)); \
(ph)->ph_flags |= MDI_PHCI_FLAGS_D_DISABLE_TRANS; }
#define MDI_PHCI_IS_DRV_DISABLED_TRANSIENT(ph) \
((ph)->ph_flags & MDI_PHCI_FLAGS_D_DISABLE_TRANS)
#define MDI_PHCI_SET_POWER_TRANSITION(ph) {\
ASSERT(MDI_PHCI_LOCKED(ph)); \
(ph)->ph_flags |= MDI_PHCI_FLAGS_POWER_TRANSITION; }
#define MDI_PHCI_CLEAR_POWER_TRANSITION(ph) {\
ASSERT(MDI_PHCI_LOCKED(ph)); \
(ph)->ph_flags &= ~MDI_PHCI_FLAGS_POWER_TRANSITION; }
#define MDI_PHCI_IS_POWER_TRANSITION(ph) \
((ph)->ph_flags & MDI_PHCI_FLAGS_POWER_TRANSITION)
typedef struct mdi_client {
struct mdi_client *ct_hnext;
struct mdi_client *ct_hprev;
dev_info_t *ct_dip;
struct mdi_vhci *ct_vhci;
char *ct_drvname;
char *ct_guid;
client_lb_t ct_lb;
client_lb_args_t *ct_lb_args;
kmutex_t ct_mutex;
int ct_path_count;
mdi_pathinfo_t *ct_path_head;
mdi_pathinfo_t *ct_path_tail;
mdi_pathinfo_t *ct_path_last;
int ct_state;
int ct_flags;
int ct_failover_flags;
int ct_failover_status;
kcondvar_t ct_failover_cv;
int ct_unstable;
kcondvar_t ct_unstable_cv;
int ct_power_cnt;
kcondvar_t ct_powerchange_cv;
short ct_powercnt_config;
short ct_powercnt_unconfig;
int ct_powercnt_reset;
void *ct_cprivate;
void *ct_vprivate;
} mdi_client_t;
#define MDI_CLIENT_LOCK(ct) mutex_enter(&(ct)->ct_mutex)
#define MDI_CLIENT_TRYLOCK(ct) mutex_tryenter(&(ct)->ct_mutex)
#define MDI_CLIENT_UNLOCK(ct) mutex_exit(&(ct)->ct_mutex)
#ifdef DEBUG
#define MDI_CLIENT_LOCKED(ct) MUTEX_HELD(&(ct)->ct_mutex)
#endif
#define MDI_CLIENT_UNSTABLE(ct) (ct)->ct_unstable++;
#define MDI_CLIENT_STABLE(ct) { \
(ct)->ct_unstable--; \
if ((ct)->ct_unstable == 0) { \
cv_broadcast(&(ct)->ct_unstable_cv); \
} \
}
#define MDI_CLIENT_FLAGS_OFFLINE 0x00000001
#define MDI_CLIENT_FLAGS_SUSPEND 0x00000002
#define MDI_CLIENT_FLAGS_POWER_DOWN 0x00000004
#define MDI_CLIENT_FLAGS_DETACH 0x00000008
#define MDI_CLIENT_FLAGS_FAILOVER 0x00000010
#define MDI_CLIENT_FLAGS_REPORT_DEV 0x00000020
#define MDI_CLIENT_FLAGS_PATH_FREE_IN_PROGRESS 0x00000040
#define MDI_CLIENT_FLAGS_ASYNC_FREE 0x00000080
#define MDI_CLIENT_FLAGS_DEV_NOT_SUPPORTED 0x00000100
#define MDI_CLIENT_FLAGS_POWER_TRANSITION 0x00000200
#define MDI_CLIENT_SET_OFFLINE(ct) {\
ASSERT(MDI_CLIENT_LOCKED(ct)); \
(ct)->ct_flags |= MDI_CLIENT_FLAGS_OFFLINE; }
#define MDI_CLIENT_SET_ONLINE(ct) {\
ASSERT(MDI_CLIENT_LOCKED(ct)); \
(ct)->ct_flags &= ~MDI_CLIENT_FLAGS_OFFLINE; }
#define MDI_CLIENT_IS_OFFLINE(ct) \
((ct)->ct_flags & MDI_CLIENT_FLAGS_OFFLINE)
#define MDI_CLIENT_SET_SUSPEND(ct) {\
ASSERT(MDI_CLIENT_LOCKED(ct)); \
(ct)->ct_flags |= MDI_CLIENT_FLAGS_SUSPEND; }
#define MDI_CLIENT_SET_RESUME(ct) {\
ASSERT(MDI_CLIENT_LOCKED(ct)); \
(ct)->ct_flags &= ~MDI_CLIENT_FLAGS_SUSPEND; }
#define MDI_CLIENT_IS_SUSPENDED(ct) \
((ct)->ct_flags & MDI_CLIENT_FLAGS_SUSPEND)
#define MDI_CLIENT_SET_POWER_DOWN(ct) {\
ASSERT(MDI_CLIENT_LOCKED(ct)); \
(ct)->ct_flags |= MDI_CLIENT_FLAGS_POWER_DOWN; }
#define MDI_CLIENT_SET_POWER_UP(ct) {\
ASSERT(MDI_CLIENT_LOCKED(ct)); \
(ct)->ct_flags &= ~MDI_CLIENT_FLAGS_POWER_DOWN; }
#define MDI_CLIENT_IS_POWERED_DOWN(ct) \
((ct)->ct_flags & MDI_CLIENT_FLAGS_POWER_DOWN)
#define MDI_CLIENT_SET_POWER_TRANSITION(ct) {\
ASSERT(MDI_CLIENT_LOCKED(ct)); \
(ct)->ct_flags |= MDI_CLIENT_FLAGS_POWER_TRANSITION; }
#define MDI_CLIENT_CLEAR_POWER_TRANSITION(ct) {\
ASSERT(MDI_CLIENT_LOCKED(ct)); \
(ct)->ct_flags &= ~MDI_CLIENT_FLAGS_POWER_TRANSITION; }
#define MDI_CLIENT_IS_POWER_TRANSITION(ct) \
((ct)->ct_flags & MDI_CLIENT_FLAGS_POWER_TRANSITION)
#define MDI_CLIENT_SET_DETACH(ct) {\
ASSERT(MDI_CLIENT_LOCKED(ct)); \
(ct)->ct_flags |= MDI_CLIENT_FLAGS_DETACH; }
#define MDI_CLIENT_SET_ATTACH(ct) {\
ASSERT(MDI_CLIENT_LOCKED(ct)); \
(ct)->ct_flags &= ~MDI_CLIENT_FLAGS_DETACH; }
#define MDI_CLIENT_IS_DETACHED(ct) \
((ct)->ct_flags & MDI_CLIENT_FLAGS_DETACH)
#define MDI_CLIENT_SET_FAILOVER_IN_PROGRESS(ct) {\
ASSERT(MDI_CLIENT_LOCKED(ct)); \
(ct)->ct_flags |= MDI_CLIENT_FLAGS_FAILOVER; }
#define MDI_CLIENT_CLEAR_FAILOVER_IN_PROGRESS(ct) {\
ASSERT(MDI_CLIENT_LOCKED(ct)); \
(ct)->ct_flags &= ~MDI_CLIENT_FLAGS_FAILOVER; }
#define MDI_CLIENT_IS_FAILOVER_IN_PROGRESS(ct) \
((ct)->ct_flags & MDI_CLIENT_FLAGS_FAILOVER)
#define MDI_CLIENT_SET_REPORT_DEV_NEEDED(ct) {\
ASSERT(MDI_CLIENT_LOCKED(ct)); \
(ct)->ct_flags |= MDI_CLIENT_FLAGS_REPORT_DEV; }
#define MDI_CLIENT_CLEAR_REPORT_DEV_NEEDED(ct) {\
ASSERT(MDI_CLIENT_LOCKED(ct)); \
(ct)->ct_flags &= ~MDI_CLIENT_FLAGS_REPORT_DEV; }
#define MDI_CLIENT_IS_REPORT_DEV_NEEDED(ct) \
((ct)->ct_flags & MDI_CLIENT_FLAGS_REPORT_DEV)
#define MDI_CLIENT_SET_PATH_FREE_IN_PROGRESS(ct) {\
ASSERT(MDI_CLIENT_LOCKED(ct)); \
(ct)->ct_flags |= MDI_CLIENT_FLAGS_PATH_FREE_IN_PROGRESS; }
#define MDI_CLIENT_CLEAR_PATH_FREE_IN_PROGRESS(ct) {\
ASSERT(MDI_CLIENT_LOCKED(ct)); \
(ct)->ct_flags &= ~MDI_CLIENT_FLAGS_PATH_FREE_IN_PROGRESS; }
#define MDI_CLIENT_IS_PATH_FREE_IN_PROGRESS(ct) \
((ct)->ct_flags & MDI_CLIENT_FLAGS_PATH_FREE_IN_PROGRESS)
#define MDI_CLIENT_SET_DEV_NOT_SUPPORTED(ct) {\
ASSERT(MDI_CLIENT_LOCKED(ct)); \
(ct)->ct_flags |= MDI_CLIENT_FLAGS_DEV_NOT_SUPPORTED; }
#define MDI_CLIENT_IS_DEV_NOT_SUPPORTED(ct) \
((ct)->ct_flags & MDI_CLIENT_FLAGS_DEV_NOT_SUPPORTED)
#define MDI_CLIENT_STATE_OPTIMAL 1
#define MDI_CLIENT_STATE_DEGRADED 2
#define MDI_CLIENT_STATE_FAILED 3
#define MDI_CLIENT_STATE(ct) ((ct)->ct_state)
#define MDI_CLIENT_SET_STATE(ct, state) ((ct)->ct_state = state)
#define MDI_CLIENT_IS_FAILED(ct) \
((ct)->ct_state == MDI_CLIENT_STATE_FAILED)
struct mdi_pathinfo {
struct mdi_pathinfo *pi_phci_link;
mdi_phci_t *pi_phci;
struct mdi_pathinfo *pi_client_link;
mdi_client_t *pi_client;
char *pi_addr;
int pi_path_instance;
kmutex_t pi_mutex;
mdi_pathinfo_state_t pi_state;
mdi_pathinfo_state_t pi_old_state;
kcondvar_t pi_state_cv;
nvlist_t *pi_prop;
void *pi_cprivate;
void *pi_pprivate;
int pi_ref_cnt;
kcondvar_t pi_ref_cv;
struct mdi_pi_kstats *pi_kstats;
int pi_pm_held;
int pi_preferred;
void *pi_vprivate;
uint_t pi_flags;
};
struct mdi_pi_kstats {
int pi_kstat_ref;
kstat_t *pi_kstat_iostats;
kstat_t *pi_kstat_errstats;
};
struct pi_errs {
struct kstat_named pi_softerrs;
struct kstat_named pi_harderrs;
struct kstat_named pi_transerrs;
struct kstat_named pi_icnt_busy;
struct kstat_named pi_icnt_errors;
struct kstat_named pi_phci_rsrc;
struct kstat_named pi_phci_localerr;
struct kstat_named pi_phci_invstate;
struct kstat_named pi_failedfrom;
struct kstat_named pi_failedto;
};
#define MDI_PI_ERRSTAT(pip, x) { \
if (MDI_PI((pip))->pi_kstats != NULL) { \
struct pi_errs *pep; \
pep = MDI_PI(pip)->pi_kstats->pi_kstat_errstats->ks_data; \
pep->x.value.ui32++; \
} \
}
#define MDI_PI_SOFTERR pi_softerrs
#define MDI_PI_HARDERR pi_harderrs
#define MDI_PI_TRANSERR pi_transerrs
#define MDI_PI_ICNTBUSY pi_icnt_busy
#define MDI_PI_ICNTERR pi_icnt_errors
#define MDI_PI_PHCIRSRC pi_phci_rsrc
#define MDI_PI_PHCILOCL pi_phci_localerr
#define MDI_PI_PHCIINVS pi_phci_invstate
#define MDI_PI_FAILFROM pi_failedfrom
#define MDI_PI_FAILTO pi_failedto
#define MDI_PI(type) ((struct mdi_pathinfo *)(type))
#define MDI_PI_LOCK(pip) mutex_enter(&MDI_PI(pip)->pi_mutex)
#define MDI_PI_TRYLOCK(pip) mutex_tryenter(&MDI_PI(pip)->pi_mutex)
#define MDI_PI_UNLOCK(pip) mutex_exit(&MDI_PI(pip)->pi_mutex)
#ifdef DEBUG
#define MDI_PI_LOCKED(pip) MUTEX_HELD(&MDI_PI(pip)->pi_mutex)
#endif
#define MDI_PI_HOLD(pip) (++MDI_PI(pip)->pi_ref_cnt)
#define MDI_PI_RELE(pip) (--MDI_PI(pip)->pi_ref_cnt)
#define MDI_EXT_STATE_CHANGE 0x10000000
#define MDI_DISABLE_OP 0x1
#define MDI_ENABLE_OP 0x2
#define MDI_BEFORE_STATE_CHANGE 0x4
#define MDI_AFTER_STATE_CHANGE 0x8
#define MDI_SYNC_FLAG 0x10
#define MDI_PI_STATE(pip) \
(MDI_PI((pip))->pi_state & MDI_PATHINFO_STATE_MASK)
#define MDI_PI_OLD_STATE(pip) \
(MDI_PI((pip))->pi_old_state & MDI_PATHINFO_STATE_MASK)
#define MDI_PI_EXT_STATE(pip) \
(MDI_PI((pip))->pi_state & MDI_PATHINFO_EXT_STATE_MASK)
#define MDI_PI_OLD_EXT_STATE(pip) \
(MDI_PI((pip))->pi_old_state & MDI_PATHINFO_EXT_STATE_MASK)
#define MDI_PI_SET_TRANSIENT(pip) {\
ASSERT(MDI_PI_LOCKED(pip)); \
MDI_PI(pip)->pi_state |= MDI_PATHINFO_STATE_TRANSIENT; }
#define MDI_PI_CLEAR_TRANSIENT(pip) {\
ASSERT(MDI_PI_LOCKED(pip)); \
MDI_PI(pip)->pi_state &= ~MDI_PATHINFO_STATE_TRANSIENT; }
#define MDI_PI_IS_TRANSIENT(pip) \
(MDI_PI(pip)->pi_state & MDI_PATHINFO_STATE_TRANSIENT)
#define MDI_PI_SET_USER_DISABLE(pip) {\
ASSERT(MDI_PI_LOCKED(pip)); \
MDI_PI(pip)->pi_state |= MDI_PATHINFO_STATE_USER_DISABLE; }
#define MDI_PI_SET_DRV_DISABLE(pip) {\
ASSERT(MDI_PI_LOCKED(pip)); \
MDI_PI(pip)->pi_state |= MDI_PATHINFO_STATE_DRV_DISABLE; }
#define MDI_PI_SET_DRV_DISABLE_TRANS(pip) {\
ASSERT(MDI_PI_LOCKED(pip)); \
MDI_PI(pip)->pi_state |= MDI_PATHINFO_STATE_DRV_DISABLE_TRANSIENT; }
#define MDI_PI_SET_USER_ENABLE(pip) {\
ASSERT(MDI_PI_LOCKED(pip)); \
MDI_PI(pip)->pi_state &= ~MDI_PATHINFO_STATE_USER_DISABLE; }
#define MDI_PI_SET_DRV_ENABLE(pip) {\
ASSERT(MDI_PI_LOCKED(pip)); \
MDI_PI(pip)->pi_state &= ~MDI_PATHINFO_STATE_DRV_DISABLE; }
#define MDI_PI_SET_DRV_ENABLE_TRANS(pip) {\
ASSERT(MDI_PI_LOCKED(pip)); \
MDI_PI(pip)->pi_state &= ~MDI_PATHINFO_STATE_DRV_DISABLE_TRANSIENT; }
#define MDI_PI_IS_USER_DISABLE(pip) \
(MDI_PI(pip)->pi_state & MDI_PATHINFO_STATE_USER_DISABLE)
#define MDI_PI_IS_DRV_DISABLE(pip) \
(MDI_PI(pip)->pi_state & MDI_PATHINFO_STATE_DRV_DISABLE)
#define MDI_PI_IS_DRV_DISABLE_TRANSIENT(pip) \
(MDI_PI(pip)->pi_state & MDI_PATHINFO_STATE_DRV_DISABLE_TRANSIENT)
#define MDI_PI_IS_DISABLE(pip) \
(MDI_PI_IS_USER_DISABLE(pip) || \
MDI_PI_IS_DRV_DISABLE(pip) || \
MDI_PI_IS_DRV_DISABLE_TRANSIENT(pip))
#define MDI_PI_IS_INIT(pip) \
((MDI_PI(pip)->pi_state & MDI_PATHINFO_STATE_MASK) == \
MDI_PATHINFO_STATE_INIT)
#define MDI_PI_IS_INITING(pip) \
((MDI_PI(pip)->pi_state & ~MDI_PATHINFO_EXT_STATE_MASK) == \
(MDI_PATHINFO_STATE_INIT | MDI_PATHINFO_STATE_TRANSIENT))
#define MDI_PI_SET_INIT(pip) {\
ASSERT(MDI_PI_LOCKED(pip)); \
MDI_PI(pip)->pi_state = MDI_PATHINFO_STATE_INIT; }
#define MDI_PI_SET_ONLINING(pip) {\
uint32_t ext_state; \
ASSERT(MDI_PI_LOCKED(pip)); \
ext_state = MDI_PI(pip)->pi_state & MDI_PATHINFO_EXT_STATE_MASK; \
MDI_PI(pip)->pi_old_state = MDI_PI_STATE(pip); \
MDI_PI(pip)->pi_state = \
(MDI_PATHINFO_STATE_ONLINE | MDI_PATHINFO_STATE_TRANSIENT); \
MDI_PI(pip)->pi_state |= ext_state; }
#define MDI_PI_IS_ONLINING(pip) \
((MDI_PI(pip)->pi_state & ~MDI_PATHINFO_EXT_STATE_MASK) == \
(MDI_PATHINFO_STATE_ONLINE | MDI_PATHINFO_STATE_TRANSIENT))
#define MDI_PI_SET_ONLINE(pip) {\
uint32_t ext_state; \
ASSERT(MDI_PI_LOCKED(pip)); \
ext_state = MDI_PI(pip)->pi_state & MDI_PATHINFO_EXT_STATE_MASK; \
MDI_PI(pip)->pi_state = MDI_PATHINFO_STATE_ONLINE; \
MDI_PI(pip)->pi_state |= ext_state; }
#define MDI_PI_IS_ONLINE(pip) \
((MDI_PI(pip)->pi_state & MDI_PATHINFO_STATE_MASK) == \
MDI_PATHINFO_STATE_ONLINE)
#define MDI_PI_SET_OFFLINING(pip) {\
uint32_t ext_state; \
ASSERT(MDI_PI_LOCKED(pip)); \
ext_state = MDI_PI(pip)->pi_state & MDI_PATHINFO_EXT_STATE_MASK; \
MDI_PI(pip)->pi_old_state = MDI_PI_STATE(pip); \
MDI_PI(pip)->pi_state = \
(MDI_PATHINFO_STATE_OFFLINE | MDI_PATHINFO_STATE_TRANSIENT); \
MDI_PI(pip)->pi_state |= ext_state; }
#define MDI_PI_IS_OFFLINING(pip) \
((MDI_PI(pip)->pi_state & ~MDI_PATHINFO_EXT_STATE_MASK) == \
(MDI_PATHINFO_STATE_OFFLINE | MDI_PATHINFO_STATE_TRANSIENT))
#define MDI_PI_SET_OFFLINE(pip) {\
uint32_t ext_state; \
ASSERT(MDI_PI_LOCKED(pip)); \
ext_state = MDI_PI(pip)->pi_state & MDI_PATHINFO_EXT_STATE_MASK; \
MDI_PI(pip)->pi_state = MDI_PATHINFO_STATE_OFFLINE; \
MDI_PI(pip)->pi_state |= ext_state; }
#define MDI_PI_IS_OFFLINE(pip) \
((MDI_PI(pip)->pi_state & MDI_PATHINFO_STATE_MASK) == \
MDI_PATHINFO_STATE_OFFLINE)
#define MDI_PI_SET_STANDBYING(pip) {\
uint32_t ext_state; \
ASSERT(MDI_PI_LOCKED(pip)); \
ext_state = MDI_PI(pip)->pi_state & MDI_PATHINFO_EXT_STATE_MASK; \
MDI_PI(pip)->pi_old_state = MDI_PI_STATE(pip); \
MDI_PI(pip)->pi_state = \
(MDI_PATHINFO_STATE_STANDBY | MDI_PATHINFO_STATE_TRANSIENT); \
MDI_PI(pip)->pi_state |= ext_state; }
#define MDI_PI_SET_STANDBY(pip) {\
uint32_t ext_state; \
ASSERT(MDI_PI_LOCKED(pip)); \
ext_state = MDI_PI(pip)->pi_state & MDI_PATHINFO_EXT_STATE_MASK; \
MDI_PI(pip)->pi_state = MDI_PATHINFO_STATE_STANDBY; \
MDI_PI(pip)->pi_state |= ext_state; }
#define MDI_PI_IS_STANDBY(pip) \
((MDI_PI(pip)->pi_state & MDI_PATHINFO_STATE_MASK) == \
MDI_PATHINFO_STATE_STANDBY)
#define MDI_PI_SET_FAULTING(pip) {\
uint32_t ext_state; \
ASSERT(MDI_PI_LOCKED(pip)); \
ext_state = MDI_PI(pip)->pi_state & MDI_PATHINFO_EXT_STATE_MASK; \
MDI_PI(pip)->pi_old_state = MDI_PI_STATE(pip); \
MDI_PI(pip)->pi_state = \
(MDI_PATHINFO_STATE_FAULT | MDI_PATHINFO_STATE_TRANSIENT); \
MDI_PI(pip)->pi_state |= ext_state; }
#define MDI_PI_SET_FAULT(pip) {\
uint32_t ext_state; \
ASSERT(MDI_PI_LOCKED(pip)); \
ext_state = MDI_PI(pip)->pi_state & MDI_PATHINFO_EXT_STATE_MASK; \
MDI_PI(pip)->pi_state = MDI_PATHINFO_STATE_FAULT; \
MDI_PI(pip)->pi_state |= ext_state; }
#define MDI_PI_IS_FAULT(pip) \
((MDI_PI(pip)->pi_state & MDI_PATHINFO_STATE_MASK) == \
MDI_PATHINFO_STATE_FAULT)
#define MDI_PI_IS_SUSPENDED(pip) \
((MDI_PI(pip))->pi_phci->ph_flags & MDI_PHCI_FLAGS_SUSPEND)
#define MDI_PI_FLAGS_SET_HIDDEN(pip) {\
ASSERT(MDI_PI_LOCKED(pip)); \
MDI_PI(pip)->pi_flags |= MDI_PATHINFO_FLAGS_HIDDEN; }
#define MDI_PI_FLAGS_CLR_HIDDEN(pip) {\
ASSERT(MDI_PI_LOCKED(pip)); \
MDI_PI(pip)->pi_flags &= ~MDI_PATHINFO_FLAGS_HIDDEN; }
#define MDI_PI_FLAGS_IS_HIDDEN(pip) \
((MDI_PI(pip)->pi_flags & MDI_PATHINFO_FLAGS_HIDDEN) == \
MDI_PATHINFO_FLAGS_HIDDEN)
#define MDI_PI_FLAGS_SET_DEVICE_REMOVED(pip) {\
ASSERT(MDI_PI_LOCKED(pip)); \
MDI_PI(pip)->pi_flags |= MDI_PATHINFO_FLAGS_DEVICE_REMOVED; }
#define MDI_PI_FLAGS_CLR_DEVICE_REMOVED(pip) {\
ASSERT(MDI_PI_LOCKED(pip)); \
MDI_PI(pip)->pi_flags &= ~MDI_PATHINFO_FLAGS_DEVICE_REMOVED; }
#define MDI_PI_FLAGS_IS_DEVICE_REMOVED(pip) \
((MDI_PI(pip)->pi_flags & MDI_PATHINFO_FLAGS_DEVICE_REMOVED) == \
MDI_PATHINFO_FLAGS_DEVICE_REMOVED)
typedef struct mdi_vhcache_phci {
char *cphci_path;
uint32_t cphci_id;
mdi_phci_t *cphci_phci;
struct mdi_vhcache_phci *cphci_next;
} mdi_vhcache_phci_t;
typedef struct mdi_vhcache_pathinfo {
char *cpi_addr;
mdi_vhcache_phci_t *cpi_cphci;
struct mdi_pathinfo *cpi_pip;
uint32_t cpi_flags;
struct mdi_vhcache_pathinfo *cpi_next;
} mdi_vhcache_pathinfo_t;
#define MDI_CPI_HINT_PATH_DOES_NOT_EXIST 0x0001
typedef struct mdi_vhcache_client {
char *cct_name_addr;
mdi_vhcache_pathinfo_t *cct_cpi_head;
mdi_vhcache_pathinfo_t *cct_cpi_tail;
struct mdi_vhcache_client *cct_next;
} mdi_vhcache_client_t;
typedef struct mdi_vhci_cache {
mdi_vhcache_phci_t *vhcache_phci_head;
mdi_vhcache_phci_t *vhcache_phci_tail;
mdi_vhcache_client_t *vhcache_client_head;
mdi_vhcache_client_t *vhcache_client_tail;
mod_hash_t *vhcache_client_hash;
int vhcache_flags;
int64_t vhcache_clean_time;
krwlock_t vhcache_lock;
} mdi_vhci_cache_t;
#define MDI_VHCI_CACHE_SETUP_DONE 0x0001
typedef struct mdi_vhci_config {
char *vhc_vhcache_filename;
mdi_vhci_cache_t vhc_vhcache;
kmutex_t vhc_lock;
kcondvar_t vhc_cv;
int vhc_flags;
clock_t vhc_flush_at_ticks;
struct mdi_async_client_config *vhc_acc_list_head;
struct mdi_async_client_config *vhc_acc_list_tail;
int vhc_acc_count;
int vhc_acc_thrcount;
callb_id_t vhc_cbid;
int vhc_path_discovery_boot;
int vhc_path_discovery_postboot;
int64_t vhc_path_discovery_cutoff_time;
} mdi_vhci_config_t;
#define MDI_VHC_SINGLE_THREADED 0x0001
#define MDI_VHC_EXIT 0x0002
#define MDI_VHC_VHCACHE_DIRTY 0x0004
#define MDI_VHC_VHCACHE_FLUSH_THREAD 0x0008
#define MDI_VHC_VHCACHE_FLUSH_ERROR 0x0010
#define MDI_VHC_READONLY_FS 0x0020
typedef struct mdi_phys_path {
char *phys_path;
struct mdi_phys_path *phys_path_next;
} mdi_phys_path_t;
typedef struct mdi_vhcache_lookup_token {
mdi_vhcache_client_t *lt_cct;
int64_t lt_cct_lookup_time;
} mdi_vhcache_lookup_token_t;
typedef struct mdi_async_client_config {
char *acc_ct_name;
char *acc_ct_addr;
mdi_phys_path_t *acc_phclient_path_list_head;
mdi_vhcache_lookup_token_t acc_token;
struct mdi_async_client_config *acc_next;
} mdi_async_client_config_t;
int mdi_vhci_register(char *, dev_info_t *, mdi_vhci_ops_t *, int);
int mdi_vhci_unregister(dev_info_t *, int);
int mdi_phci_get_path_count(dev_info_t *);
dev_info_t *mdi_phci_path2devinfo(dev_info_t *, caddr_t);
int mdi_select_path(dev_info_t *, struct buf *, int,
void *, mdi_pathinfo_t **);
int mdi_set_lb_policy(dev_info_t *, client_lb_t);
int mdi_set_lb_region_size(dev_info_t *, int);
client_lb_t mdi_get_lb_policy(dev_info_t *);
#define MDI_SELECT_ONLINE_PATH 0x0001
#define MDI_SELECT_STANDBY_PATH 0x0002
#define MDI_SELECT_USER_DISABLE_PATH 0x0004
#define MDI_SELECT_PATH_INSTANCE 0x0008
#define MDI_SELECT_NO_PREFERRED 0x0010
int mdi_client_get_path_count(dev_info_t *);
dev_info_t *mdi_client_path2devinfo(dev_info_t *, caddr_t);
int mdi_failover(dev_info_t *, dev_info_t *, int);
#define MDI_FAILOVER_SYNC 1
#define MDI_FAILOVER_ASYNC 2
int mdi_is_dev_supported(char *class, dev_info_t *pdip, void *cinfo);
int mdi_pi_kstat_exists(mdi_pathinfo_t *);
int mdi_pi_kstat_create(mdi_pathinfo_t *pip, char *ks_name);
void mdi_pi_kstat_iosupdate(mdi_pathinfo_t *, struct buf *);
int mdi_pi_get_state2(mdi_pathinfo_t *, mdi_pathinfo_state_t *, uint32_t *);
int mdi_pi_get_preferred(mdi_pathinfo_t *);
void *mdi_pi_get_client_private(mdi_pathinfo_t *);
void mdi_pi_set_client_private(mdi_pathinfo_t *, void *);
void mdi_pi_set_state(mdi_pathinfo_t *, mdi_pathinfo_state_t);
void mdi_pi_set_preferred(mdi_pathinfo_t *, int);
void *mdi_client_get_vhci_private(dev_info_t *);
void mdi_client_set_vhci_private(dev_info_t *, void *);
void *mdi_phci_get_vhci_private(dev_info_t *);
void mdi_phci_set_vhci_private(dev_info_t *, void *);
void *mdi_pi_get_vhci_private(mdi_pathinfo_t *);
void mdi_pi_set_vhci_private(mdi_pathinfo_t *, void *);
int mdi_dc_return_dev_state(mdi_pathinfo_t *pip, struct devctl_iocdata *dcp);
int mdi_prop_size(mdi_pathinfo_t *, size_t *);
int mdi_prop_pack(mdi_pathinfo_t *, char **, uint_t);
void mdi_get_next_path(dev_info_t *, mdi_pathinfo_t *, mdi_pathinfo_t **);
int mdi_get_component_type(dev_info_t *);
#endif
#ifdef __cplusplus
}
#endif
#endif