diff options
Diffstat (limited to 'usr/src')
23 files changed, 1180 insertions, 19 deletions
diff --git a/usr/src/cmd/devfsadm/devfsadm.c b/usr/src/cmd/devfsadm/devfsadm.c index 6317c86aec..0df0f12abd 100644 --- a/usr/src/cmd/devfsadm/devfsadm.c +++ b/usr/src/cmd/devfsadm/devfsadm.c @@ -945,11 +945,15 @@ process_deferred_links(struct dca_impl *dcip, int flags) * Called in non-daemon mode to take a snap shot of the devinfo tree. * Then it calls the appropriate functions to build /devices and /dev. * It also flushes path_to_inst. + * DINFOCACHE snapshot needs to be updated when devfsadm is run. + * This will only happen if the flags that devfsadm uses matches the flags + * that DINFOCACHE uses and that is why flags is set to + * DI_CACHE_SNAPSHOT_FLAGS. */ void process_devinfo_tree() { - uint_t flags = DINFOCPYALL; + uint_t flags = DI_CACHE_SNAPSHOT_FLAGS; struct dca_impl dci; char name[MAXNAMELEN]; char *fcn = "process_devinfo_tree: "; diff --git a/usr/src/lib/libdevinfo/devinfo.c b/usr/src/lib/libdevinfo/devinfo.c index 991fa7d833..ee33c2d518 100644 --- a/usr/src/lib/libdevinfo/devinfo.c +++ b/usr/src/lib/libdevinfo/devinfo.c @@ -2088,6 +2088,104 @@ int di_path_prop_lookup_strings(di_path_t path, const char *prop_name, return (di_path_prop_strings(prop, prop_data)); } +/* + * Consolidation private interfaces for traversing vhci nodes. + */ +di_node_t +di_vhci_first_node(di_node_t root) +{ + struct di_all *dap; + caddr_t pa; /* starting address of map */ + + DPRINTF((DI_INFO, "Get first vhci node\n")); + + if (root == DI_NODE_NIL) { + errno = EINVAL; + return (DI_NODE_NIL); + } + + pa = (caddr_t)root - DI_NODE(root)->self; + dap = DI_ALL(pa); + + if (dap->top_vhci_devinfo == NULL) { + errno = ENXIO; + return (DI_NODE_NIL); + } + + return (DI_NODE(pa + dap->top_vhci_devinfo)); +} + +di_node_t +di_vhci_next_node(di_node_t node) +{ + caddr_t pa; /* starting address of map */ + + if (node == DI_NODE_NIL) { + errno = EINVAL; + return (DI_NODE_NIL); + } + + DPRINTF((DI_TRACE, "next vhci node on the snap shot:" + " current=%s\n", di_node_name(node))); + + if (DI_NODE(node)->next_vhci == NULL) { + errno = ENXIO; + return (DI_NODE_NIL); + } + + pa = (caddr_t)node - DI_NODE(node)->self; + + return (DI_NODE(pa + DI_NODE(node)->next_vhci)); +} + +/* + * Consolidation private interfaces for traversing phci nodes. + */ +di_node_t +di_phci_first_node(di_node_t vhci_node) +{ + caddr_t pa; /* starting address of map */ + + DPRINTF((DI_INFO, "Get first phci node:\n" + " current=%s", di_node_name(vhci_node))); + + if (vhci_node == DI_NODE_NIL) { + errno = EINVAL; + return (DI_NODE_NIL); + } + + pa = (caddr_t)vhci_node - DI_NODE(vhci_node)->self; + + if (DI_NODE(vhci_node)->top_phci == NULL) { + errno = ENXIO; + return (DI_NODE_NIL); + } + + return (DI_NODE(pa + DI_NODE(vhci_node)->top_phci)); +} + +di_node_t +di_phci_next_node(di_node_t node) +{ + caddr_t pa; /* starting address of map */ + + if (node == DI_NODE_NIL) { + errno = EINVAL; + return (DI_NODE_NIL); + } + + DPRINTF((DI_TRACE, "next phci node on the snap shot:" + " current=%s\n", di_node_name(node))); + + if (DI_NODE(node)->next_phci == NULL) { + errno = ENXIO; + return (DI_NODE_NIL); + } + + pa = (caddr_t)node - DI_NODE(node)->self; + + return (DI_NODE(pa + DI_NODE(node)->next_phci)); +} /* * Consolidation private interfaces for private data diff --git a/usr/src/lib/libdevinfo/libdevinfo.h b/usr/src/lib/libdevinfo/libdevinfo.h index b277ff4ae5..195eee4e55 100644 --- a/usr/src/lib/libdevinfo/libdevinfo.h +++ b/usr/src/lib/libdevinfo/libdevinfo.h @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -142,6 +142,10 @@ extern di_node_t di_sibling_node(di_node_t node); extern di_node_t di_child_node(di_node_t node); extern di_node_t di_drv_first_node(const char *drv_name, di_node_t root); extern di_node_t di_drv_next_node(di_node_t node); +extern di_node_t di_vhci_first_node(di_node_t root); +extern di_node_t di_vhci_next_node(di_node_t node); +extern di_node_t di_phci_first_node(di_node_t vhci_node); +extern di_node_t di_phci_next_node(di_node_t node); /* * tree walking assistants diff --git a/usr/src/lib/libdevinfo/spec/devinfo.spec b/usr/src/lib/libdevinfo/spec/devinfo.spec index 66a4de49d8..cbf95569e3 100644 --- a/usr/src/lib/libdevinfo/spec/devinfo.spec +++ b/usr/src/lib/libdevinfo/spec/devinfo.spec @@ -949,3 +949,27 @@ declaration int devfs_rm_minor_perm(char *drv, \ void (*cb)(minorperm_err_t, int)) version SUNWprivate_1.1 end + +function di_vhci_first_node +include <libdevinfo.h> +declaration di_node_t di_vhci_first_node(di_node_t root) +version SUNWprivate_1.1 +end + +function di_vhci_next_node +include <libdevinfo.h> +declaration di_node_t di_vhci_next_node(di_node_t vhci_node) +version SUNWprivate_1.1 +end + +function di_phci_first_node +include <libdevinfo.h> +declaration di_node_t di_phci_first_node(di_node_t vhci_node) +version SUNWprivate_1.1 +end + +function di_phci_next_node +include <libdevinfo.h> +declaration di_node_t di_phci_next_node(di_node_t phci_node) +version SUNWprivate_1.1 +end diff --git a/usr/src/pkgdefs/etc/exception_list_i386 b/usr/src/pkgdefs/etc/exception_list_i386 index 845ab53571..37252fc182 100644 --- a/usr/src/pkgdefs/etc/exception_list_i386 +++ b/usr/src/pkgdefs/etc/exception_list_i386 @@ -743,3 +743,10 @@ usr/lib/llib-lzpool.ln i386 usr/lib/amd64/llib-lzfs.ln i386 usr/lib/amd64/llib-lzfs_jni.ln i386 usr/lib/amd64/llib-lzpool.ln i386 + +# +# These files are installed in the proto area for Solaris scsi_vhci driver +# (for MPAPI support) and should not be shipped +# +usr/include/sys/scsi/adapters/mpapi_impl.h i386 +usr/include/sys/scsi/adapters/mpapi_scsi_vhci.h i386 diff --git a/usr/src/pkgdefs/etc/exception_list_sparc b/usr/src/pkgdefs/etc/exception_list_sparc index 500564a3eb..eb70a2b112 100644 --- a/usr/src/pkgdefs/etc/exception_list_sparc +++ b/usr/src/pkgdefs/etc/exception_list_sparc @@ -810,3 +810,10 @@ usr/lib/llib-lzpool sparc usr/lib/sparcv9/llib-lzfs.ln sparc usr/lib/sparcv9/llib-lzfs_jni.ln sparc usr/lib/sparcv9/llib-lzpool.ln sparc + +# +# These files are installed in the proto area for Solaris scsi_vhci driver +# (for MPAPI support) and should not be shipped +# +usr/include/sys/scsi/adapters/mpapi_impl.h sparc +usr/include/sys/scsi/adapters/mpapi_scsi_vhci.h sparc diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files index 2b952a3b5a..fdb7a58762 100644 --- a/usr/src/uts/common/Makefile.files +++ b/usr/src/uts/common/Makefile.files @@ -1176,6 +1176,7 @@ SCSI_VHCI_OBJS += scsi_vhci.o \ lsi_asymmetric_fops.o \ std_asymmetric_fops.o \ emc_asymmetric_fops.o \ + mpapi_impl.o \ proprietary_vhci_util.o STRPLUMB_OBJS += strplumb.o octet.o diff --git a/usr/src/uts/common/io/devinfo.c b/usr/src/uts/common/io/devinfo.c index 20ef0add5c..3533f193fe 100644 --- a/usr/src/uts/common/io/devinfo.c +++ b/usr/src/uts/common/io/devinfo.c @@ -270,6 +270,11 @@ static uint_t di_chunk = 32; /* I/O chunk size in pages */ #define CACHE_DEBUG(args) \ { if (di_cache_debug != DI_QUIET) di_cache_print args; } +static struct phci_walk_arg { + di_off_t off; + struct di_state *st; +} phci_walk_arg_t; + static int di_open(dev_t *, int, int, cred_t *); static int di_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); static int di_close(dev_t, int, int, cred_t *); @@ -306,6 +311,8 @@ static int snapshot_is_cacheable(struct di_state *st); static int di_cache_lookup(struct di_state *st); static int di_cache_update(struct di_state *st); static void di_cache_print(di_cache_debug_t msglevel, char *fmt, ...); +int build_vhci_list(dev_info_t *vh_devinfo, void *arg); +int build_phci_list(dev_info_t *ph_devinfo, void *arg); static struct cb_ops di_cb_ops = { di_open, /* open */ @@ -715,6 +722,7 @@ di_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp) all->devcnt = devcnt; all->command = st->command; all->version = DI_SNAPSHOT_VERSION; + all->top_vhci_devinfo = 0; /* filled up by build_vhci_list. */ /* * Note the endianness in case we need to transport snapshot @@ -1321,6 +1329,10 @@ di_snapshot(struct di_state *st) */ off = di_copytree(DEVI(rootnode), &all->top_devinfo, st); + if (DINFOPATH & st->command) { + mdi_walk_vhcis(build_vhci_list, st); + } + ddi_release_devi(rootnode); /* @@ -1367,7 +1379,7 @@ di_snapshot(struct di_state *st) static di_off_t di_snapshot_and_clean(struct di_state *st) { - di_off_t off; + di_off_t off; modunload_disable(); off = di_snapshot(st); @@ -1388,6 +1400,95 @@ di_snapshot_and_clean(struct di_state *st) } /* + * construct vhci linkage in the snapshot. + */ +int +build_vhci_list(dev_info_t *vh_devinfo, void *arg) +{ + struct di_all *all; + struct di_node *me; + struct di_state *st; + di_off_t off; + struct phci_walk_arg pwa; + + dcmn_err3((CE_CONT, "build_vhci list\n")); + + dcmn_err3((CE_CONT, "vhci node %s, instance #%d\n", + DEVI(vh_devinfo)->devi_node_name, + DEVI(vh_devinfo)->devi_instance)); + + st = (struct di_state *)arg; + if (di_dip_find(st, vh_devinfo, &off) != 0) { + dcmn_err((CE_WARN, "di_dip_find error for the given node\n")); + return (DDI_WALK_TERMINATE); + } + + dcmn_err3((CE_CONT, "st->mem_size: %d vh_devinfo off: 0x%x\n", + st->mem_size, off)); + + all = (struct di_all *)di_mem_addr(st, 0); + if (all->top_vhci_devinfo == 0) { + all->top_vhci_devinfo = off; + } else { + me = (struct di_node *)di_mem_addr(st, all->top_vhci_devinfo); + + while (me->next_vhci != 0) { + me = (struct di_node *)di_mem_addr(st, me->next_vhci); + } + + me->next_vhci = off; + } + + pwa.off = off; + pwa.st = st; + mdi_vhci_walk_phcis(vh_devinfo, build_phci_list, &pwa); + + return (DDI_WALK_CONTINUE); +} + +/* + * construct phci linkage for the given vhci in the snapshot. + */ +int +build_phci_list(dev_info_t *ph_devinfo, void *arg) +{ + struct di_node *vh_di_node; + struct di_node *me; + struct phci_walk_arg *pwa; + di_off_t off; + + pwa = (struct phci_walk_arg *)arg; + + dcmn_err3((CE_CONT, "build_phci list for vhci at offset: 0x%x\n", + pwa->off)); + + vh_di_node = (struct di_node *)di_mem_addr(pwa->st, pwa->off); + + if (di_dip_find(pwa->st, ph_devinfo, &off) != 0) { + dcmn_err((CE_WARN, "di_dip_find error for the given node\n")); + return (DDI_WALK_TERMINATE); + } + + dcmn_err3((CE_CONT, "phci node %s, instance #%d, at offset 0x%x\n", + DEVI(ph_devinfo)->devi_node_name, + DEVI(ph_devinfo)->devi_instance, off)); + + if (vh_di_node->top_phci == 0) { + vh_di_node->top_phci = off; + return (DDI_WALK_CONTINUE); + } + + me = (struct di_node *)di_mem_addr(pwa->st, vh_di_node->top_phci); + + while (me->next_phci != 0) { + me = (struct di_node *)di_mem_addr(pwa->st, me->next_phci); + } + me->next_phci = off; + + return (DDI_WALK_CONTINUE); +} + +/* * Assumes all devinfo nodes in device tree have been snapshotted */ static void @@ -1607,6 +1708,10 @@ di_copynode(struct di_stack *dsp, struct di_state *st) me->attributes = node->devi_node_attributes; me->state = node->devi_state; me->node_state = node->devi_node_state; + me->next_vhci = 0; /* Filled up by build_vhci_list. */ + me->top_phci = 0; /* Filled up by build_phci_list. */ + me->next_phci = 0; /* Filled up by build_phci_list. */ + me->multipath_component = MULTIPATH_COMPONENT_NONE; /* set default. */ me->user_private_data = NULL; /* @@ -1738,7 +1843,12 @@ path: goto property; } + if (MDI_VHCI(node)) { + me->multipath_component = MULTIPATH_COMPONENT_VHCI; + } + if (MDI_CLIENT(node)) { + me->multipath_component = MULTIPATH_COMPONENT_CLIENT; me->multipath_client = DI_ALIGN(off); off = di_getpath_data((dev_info_t *)node, &me->multipath_client, me->self, st, 1); @@ -1749,6 +1859,7 @@ path: } if (MDI_PHCI(node)) { + me->multipath_component = MULTIPATH_COMPONENT_PHCI; me->multipath_phci = DI_ALIGN(off); off = di_getpath_data((dev_info_t *)node, &me->multipath_phci, me->self, st, 0); @@ -3369,6 +3480,9 @@ chunk_write(struct vnode *vp, offset_t off, caddr_t buf, size_t len) } extern int modrootloaded; +extern void mdi_walk_vhcis(int (*)(dev_info_t *, void *), void *); +extern void mdi_vhci_walk_phcis(dev_info_t *, + int (*)(dev_info_t *, void *), void *); static void di_cache_write(struct di_cache *cache) diff --git a/usr/src/uts/common/io/scsi/impl/scsi_hba.c b/usr/src/uts/common/io/scsi/impl/scsi_hba.c index 8974f1e144..0d7c21afd6 100644 --- a/usr/src/uts/common/io/scsi/impl/scsi_hba.c +++ b/usr/src/uts/common/io/scsi/impl/scsi_hba.c @@ -278,8 +278,10 @@ scsi_hba_attach_setup( int value; int len; char *prop_name; + const char *prop_value; char *errmsg = "scsi_hba_attach: cannot create property '%s' for %s%d\n"; + static const char *interconnect[] = INTERCONNECT_TYPE_ASCII; /* * Link this instance into the scsi_hba_list @@ -307,7 +309,8 @@ scsi_hba_attach_setup( * later by scsi_hba_bus_ctl(), and scsi_hba_map(). */ hba_tran->tran_hba_dip = dip; - hba_tran->tran_hba_flags = flags; + hba_tran->tran_hba_flags &= SCSI_HBA_TRAN_ALLOC; + hba_tran->tran_hba_flags |= (flags & ~SCSI_HBA_TRAN_ALLOC); /* * Note: we only need dma_attr_minxfer and dma_attr_burstsizes @@ -385,6 +388,24 @@ scsi_hba_attach_setup( ddi_get_name(dip), ddi_get_instance(dip)); } } + if ((hba_tran->tran_hba_flags & SCSI_HBA_TRAN_ALLOC) && + (hba_tran->tran_interconnect_type > 0) && + (hba_tran->tran_interconnect_type < INTERCONNECT_MAX)) { + prop_name = "initiator-interconnect-type"; + len = 0; + if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN, 0, prop_name, + NULL, &len) == DDI_PROP_NOT_FOUND) { + value = hba_tran->tran_interconnect_type; + prop_value = interconnect[value]; + if (ddi_prop_update_string(DDI_MAJOR_T_UNKNOWN, dip, + prop_name, (char *)prop_value) + != DDI_PROP_SUCCESS) { + cmn_err(CE_CONT, errmsg, prop_name, + ddi_get_name(dip), + ddi_get_instance(dip)); + } + } + } ddi_set_driver_private(dip, hba_tran); @@ -846,8 +867,15 @@ scsi_hba_tran_alloc( dev_info_t *dip, int flags) { - return (kmem_zalloc(sizeof (scsi_hba_tran_t), - (flags & SCSI_HBA_CANSLEEP) ? KM_SLEEP : KM_NOSLEEP)); + scsi_hba_tran_t *hba_tran; + + hba_tran = kmem_zalloc(sizeof (scsi_hba_tran_t), + (flags & SCSI_HBA_CANSLEEP) ? KM_SLEEP : KM_NOSLEEP); + + hba_tran->tran_interconnect_type = INTERCONNECT_PARALLEL; + hba_tran->tran_hba_flags |= SCSI_HBA_TRAN_ALLOC; + + return (hba_tran); } diff --git a/usr/src/uts/common/os/sunmdi.c b/usr/src/uts/common/os/sunmdi.c index dc2a0024a2..bdc0ebcd43 100644 --- a/usr/src/uts/common/os/sunmdi.c +++ b/usr/src/uts/common/os/sunmdi.c @@ -65,6 +65,8 @@ #include <sys/epm.h> #include <sys/sunpm.h> #include <sys/modhash.h> +#include <sys/disp.h> +#include <sys/autoconf.h> #ifdef DEBUG #include <sys/debug.h> @@ -181,6 +183,7 @@ static void i_mdi_pm_rele_client(mdi_client_t *, int); static void i_mdi_pm_reset_client(mdi_client_t *); static void i_mdi_pm_hold_all_phci(mdi_client_t *); static int i_mdi_power_all_phci(mdi_client_t *); +static void i_mdi_log_sysevent(dev_info_t *, char *, char *); /* @@ -448,7 +451,7 @@ mdi_vhci_unregister(dev_info_t *vdip, int flags) } /* - * Check the pHCI and client count. All the pHCIs and clients + * Check the vHCI, pHCI and client count. All the pHCIs and clients * should have been unregistered, before a vHCI can be * unregistered. */ @@ -616,6 +619,7 @@ mdi_phci_register(char *class, dev_info_t *pdip, int flags) vh->vh_phci_tail = ph; vh->vh_phci_count++; mutex_exit(&mdi_mutex); + i_mdi_log_sysevent(pdip, class, ESC_DDI_INITIATOR_REGISTER); return (MDI_SUCCESS); } @@ -678,6 +682,8 @@ mdi_phci_unregister(dev_info_t *pdip, int flags) mutex_exit(&mdi_mutex); + i_mdi_log_sysevent(pdip, ph->ph_vhci->vh_class, + ESC_DDI_INITIATOR_UNREGISTER); vhcache_phci_remove(vh->vh_config, ph); cv_destroy(&ph->ph_unstable_cv); cv_destroy(&ph->ph_powerchange_cv); @@ -2567,6 +2573,8 @@ i_mdi_pi_alloc(mdi_phci_t *ph, char *paddr, mdi_client_t *ct) mdi_pathinfo_t *pip; int ct_circular; int ph_circular; + int se_flag; + int kmem_flag; pip = kmem_zalloc(sizeof (struct mdi_pathinfo), KM_SLEEP); mutex_init(&MDI_PI(pip)->pi_mutex, NULL, MUTEX_DEFAULT, NULL); @@ -2612,6 +2620,12 @@ i_mdi_pi_alloc(mdi_phci_t *ph, char *paddr, mdi_client_t *ct) ndi_devi_exit(ph->ph_dip, ph_circular); ndi_devi_exit(ct->ct_dip, ct_circular); + /* determine interrupt context */ + se_flag = (servicing_interrupt()) ? SE_NOSLEEP : SE_SLEEP; + kmem_flag = (se_flag == SE_SLEEP) ? KM_SLEEP : KM_NOSLEEP; + + i_ddi_di_cache_invalidate(kmem_flag); + return (pip); } @@ -2731,7 +2745,7 @@ mdi_pi_free(mdi_pathinfo_t *pip, int flags) /* * Give a chance for pending I/Os to complete. */ - MDI_DEBUG(1, (CE_NOTE, ct->ct_vhci->vh_dip, "!i_mdi_pi_free: " + MDI_DEBUG(1, (CE_NOTE, ct->ct_vhci->vh_dip, "!mdi_pi_free: " "%d cmds still pending on path: %p\n", MDI_PI(pip)->pi_ref_cnt, pip)); if (cv_timedwait(&MDI_PI(pip)->pi_ref_cv, @@ -2742,11 +2756,11 @@ mdi_pi_free(mdi_pathinfo_t *pip, int flags) * being signaled. */ MDI_DEBUG(1, (CE_NOTE, ct->ct_vhci->vh_dip, - "!i_mdi_pi_free: " + "!mdi_pi_free: " "Timeout reached on path %p without the cond\n", pip)); MDI_DEBUG(1, (CE_NOTE, ct->ct_vhci->vh_dip, - "!i_mdi_pi_free: " + "!mdi_pi_free: " "%d cmds still pending on path: %p\n", MDI_PI(pip)->pi_ref_cnt, pip)); MDI_PI_UNLOCK(pip); @@ -2821,6 +2835,8 @@ i_mdi_pi_free(mdi_phci_t *ph, mdi_pathinfo_t *pip, mdi_client_t *ct) { int ct_circular; int ph_circular; + int se_flag; + int kmem_flag; /* * remove any per-path kstats @@ -2836,6 +2852,12 @@ i_mdi_pi_free(mdi_phci_t *ph, mdi_pathinfo_t *pip, mdi_client_t *ct) ndi_devi_exit(ph->ph_dip, ph_circular); ndi_devi_exit(ct->ct_dip, ct_circular); + /* determine interrupt context */ + se_flag = (servicing_interrupt()) ? SE_NOSLEEP : SE_SLEEP; + kmem_flag = (se_flag == SE_SLEEP) ? KM_SLEEP : KM_NOSLEEP; + + i_ddi_di_cache_invalidate(kmem_flag); + mutex_destroy(&MDI_PI(pip)->pi_mutex); cv_destroy(&MDI_PI(pip)->pi_state_cv); cv_destroy(&MDI_PI(pip)->pi_ref_cv); @@ -8362,3 +8384,162 @@ mdi_clean_vhcache(void) } mutex_exit(&mdi_mutex); } + +/* + * mdi_vhci_walk_clients(): + * Walker routine to traverse client dev_info nodes + * ddi_walk_devs(ddi_get_child(vdip), f, arg) returns the entire tree + * below the client, including nexus devices, which we dont want. + * So we just traverse the immediate siblings, starting from 1st client. + */ +void +mdi_vhci_walk_clients(dev_info_t *vdip, + int (*f)(dev_info_t *, void *), void *arg) +{ + dev_info_t *cdip; + mdi_client_t *ct; + + mutex_enter(&mdi_mutex); + + cdip = ddi_get_child(vdip); + + while (cdip) { + ct = i_devi_get_client(cdip); + MDI_CLIENT_LOCK(ct); + + switch ((*f)(cdip, arg)) { + case DDI_WALK_CONTINUE: + cdip = ddi_get_next_sibling(cdip); + MDI_CLIENT_UNLOCK(ct); + break; + + default: + MDI_CLIENT_UNLOCK(ct); + mutex_exit(&mdi_mutex); + return; + } + } + + mutex_exit(&mdi_mutex); +} + +/* + * mdi_vhci_walk_phcis(): + * Walker routine to traverse phci dev_info nodes + */ +void +mdi_vhci_walk_phcis(dev_info_t *vdip, + int (*f)(dev_info_t *, void *), void *arg) +{ + mdi_vhci_t *vh = NULL; + mdi_phci_t *ph = NULL; + + mutex_enter(&mdi_mutex); + + vh = i_devi_get_vhci(vdip); + ph = vh->vh_phci_head; + + while (ph) { + MDI_PHCI_LOCK(ph); + + switch ((*f)(ph->ph_dip, arg)) { + case DDI_WALK_CONTINUE: + MDI_PHCI_UNLOCK(ph); + ph = ph->ph_next; + break; + + default: + MDI_PHCI_UNLOCK(ph); + mutex_exit(&mdi_mutex); + return; + } + } + + mutex_exit(&mdi_mutex); +} + + +/* + * mdi_walk_vhcis(): + * Walker routine to traverse vhci dev_info nodes + */ +void +mdi_walk_vhcis(int (*f)(dev_info_t *, void *), void *arg) +{ + mdi_vhci_t *vh = NULL; + + mutex_enter(&mdi_mutex); + /* + * Scan for already registered vhci + */ + for (vh = mdi_vhci_head; vh != NULL; vh = vh->vh_next) { + vh->vh_refcnt++; + mutex_exit(&mdi_mutex); + if (((*f)(vh->vh_dip, arg)) != DDI_WALK_CONTINUE) { + mutex_enter(&mdi_mutex); + vh->vh_refcnt--; + break; + } else { + mutex_enter(&mdi_mutex); + vh->vh_refcnt--; + } + } + + mutex_exit(&mdi_mutex); +} + +/* + * i_mdi_log_sysevent(): + * Logs events for pickup by syseventd + */ +static void +i_mdi_log_sysevent(dev_info_t *dip, char *ph_vh_class, char *subclass) +{ + char *path_name; + nvlist_t *attr_list; + + if (nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE, + KM_SLEEP) != DDI_SUCCESS) { + goto alloc_failed; + } + + path_name = kmem_zalloc(MAXPATHLEN, KM_SLEEP); + (void) ddi_pathname(dip, path_name); + + if (nvlist_add_string(attr_list, DDI_DRIVER_NAME, + ddi_driver_name(dip)) != DDI_SUCCESS) { + goto error; + } + + if (nvlist_add_int32(attr_list, DDI_DRIVER_MAJOR, + (int32_t)ddi_driver_major(dip)) != DDI_SUCCESS) { + goto error; + } + + if (nvlist_add_int32(attr_list, DDI_INSTANCE, + (int32_t)ddi_get_instance(dip)) != DDI_SUCCESS) { + goto error; + } + + if (nvlist_add_string(attr_list, DDI_PATHNAME, + path_name) != DDI_SUCCESS) { + goto error; + } + + if (nvlist_add_string(attr_list, DDI_CLASS, + ph_vh_class) != DDI_SUCCESS) { + goto error; + } + + (void) ddi_log_sysevent(dip, DDI_VENDOR_SUNW, EC_DDI, subclass, + attr_list, NULL, DDI_SLEEP); + +error: + kmem_free(path_name, MAXPATHLEN); + nvlist_free(attr_list); + return; + +alloc_failed: + MDI_DEBUG(1, (CE_WARN, dip, + "!i_mdi_log_sysevent: Unable to send sysevent")); +} diff --git a/usr/src/uts/common/sys/Makefile b/usr/src/uts/common/sys/Makefile index 39ba2202d6..24704620bd 100644 --- a/usr/src/uts/common/sys/Makefile +++ b/usr/src/uts/common/sys/Makefile @@ -788,7 +788,9 @@ SCSICADHDRS= \ mptvar.h SCSIVHCIHDRS= \ - scsi_vhci.h + scsi_vhci.h \ + mpapi_impl.h \ + mpapi_scsi_vhci.h FCHDRS= \ fc_transport.h \ diff --git a/usr/src/uts/common/sys/devinfo_impl.h b/usr/src/uts/common/sys/devinfo_impl.h index 1e0f3a7fb9..6bf4255cf6 100644 --- a/usr/src/uts/common/sys/devinfo_impl.h +++ b/usr/src/uts/common/sys/devinfo_impl.h @@ -98,14 +98,16 @@ extern "C" { #define MAX_TREE_DEPTH 64 #define MAX_PTR_IN_PRV 5 #define DI_SNAPSHOT_VERSION_0 0 /* reserved */ -#define DI_SNAPSHOT_VERSION DI_SNAPSHOT_VERSION_0 /* current version */ +#define DI_SNAPSHOT_VERSION_1 1 /* reserved */ +#define DI_SNAPSHOT_VERSION DI_SNAPSHOT_VERSION_1 /* current version */ #define DI_PRIVDATA_VERSION_0 10 /* Start from 10 so caller must set */ #define DI_BIG_ENDIAN 0 /* reserved */ #define DI_LITTLE_ENDIAN 1 /* reserved */ #define DI_CACHE_MAGIC 0xdfcac6ed /* magic # for cache */ #define DI_CACHE_PERMS (0444) -#define DI_CACHE_SNAPSHOT_FLAGS (DINFOFORCE|DINFOSUBTREE|DINFOMINOR|DINFOPROP) +#define DI_CACHE_SNAPSHOT_FLAGS \ + (DINFOFORCE|DINFOSUBTREE|DINFOMINOR|DINFOPROP|DINFOPATH) #define DI_NODE(addr) ((struct di_node *)((void *)(addr))) #define DI_MINOR(addr) ((struct di_minor *)((void *)(addr))) @@ -126,6 +128,15 @@ extern "C" { #define DIPATH(addr) DI_PATH(addr) #define DIPATHPROP(addr) DI_PATHPROP(addr) +/* + * multipath component definitions: Follows the registered component of + * the mpxio system. + */ +#define MULTIPATH_COMPONENT_NONE 0 +#define MULTIPATH_COMPONENT_VHCI 0x1 +#define MULTIPATH_COMPONENT_PHCI 0x2 +#define MULTIPATH_COMPONENT_CLIENT 0x4 + typedef int32_t di_off_t; /* @@ -140,6 +151,7 @@ struct di_all { uint32_t cache_checksum; /* snapshot checksum */ uint64_t snapshot_time; /* snapshot timestamp */ di_off_t top_devinfo; + di_off_t top_vhci_devinfo; di_off_t devnames; di_off_t ppdata_format; /* parent priv data format array */ di_off_t dpdata_format; /* driver priv data format array */ @@ -256,7 +268,15 @@ struct di_node { /* useful info to export for each tree node */ di_off_t tgt_links; di_off_t src_links; - uint64_t user_private_data; + uint32_t di_pad1; /* 4 byte padding for 32bit x86 app. */ + uint64_t user_private_data; + /* + * offset to link vhci/phci nodes. + */ + di_off_t next_vhci; + di_off_t top_phci; + di_off_t next_phci; + uint32_t multipath_component; /* stores MDI_COMPONENT_* value. */ }; /* diff --git a/usr/src/uts/common/sys/scsi/adapters/mpapi_impl.h b/usr/src/uts/common/sys/scsi/adapters/mpapi_impl.h new file mode 100644 index 0000000000..7ecdc063bf --- /dev/null +++ b/usr/src/uts/common/sys/scsi/adapters/mpapi_impl.h @@ -0,0 +1,428 @@ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_SCSI_ADAPTERS_MPAPI_IMPL_H +#define _SYS_SCSI_ADAPTERS_MPAPI_IMPL_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/sunmdi.h> +#include <sys/sunddi.h> +#include <sys/mdi_impldefs.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(_BIT_FIELDS_LTOH) && !defined(_BIT_FIELDS_HTOL) +#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined +#endif /* _BIT_FIELDS_LTOH */ + +/* + * All the structures (except mp_iocdata_t) are 64-bit aligned (padded, + * where necessary) to facilitate the use of the same structure for + * handling ioctl calls made by both 32-bit and 64-bit applications. + * There are no pointers to other structures inside these structures + * as copyout to user land may not produce desired result. + * The caddr_t structure is kept at the end due to the undeterminstic + * size it could accrue to its parent structure. + */ + +/* Structure for MP_PLUGIN_PROPERTIES */ + +typedef struct mp_driver_prop { + char driverVersion[256]; + uint32_t supportedLoadBalanceTypes; + boolean_t canSetTPGAccess; + boolean_t canOverridePaths; + boolean_t exposesPathDeviceFiles; + char deviceFileNamespace[256]; + uint32_t onlySupportsSpecifiedProducts; + uint32_t maximumWeight; + uint32_t failbackPollingRateMax; + uint32_t currentFailbackPollingRate; + uint32_t autoFailbackSupport; + uint32_t autoFailbackEnabled; + uint32_t defaultLoadBalanceType; + uint32_t probingPollingRateMax; + uint32_t currentProbingPollingRate; + uint32_t autoProbingSupport; + uint32_t autoProbingEnabled; + uint32_t proprietaryPropSize; + caddr_t proprietaryProp; +} mp_driver_prop_t; + + +/* Size of "proprietaryProp" field */ + +#define MP_MAX_PROP_BUF_SIZE 1024 + + +/* Constants for autoFailbackSupport */ + +/* + * Both MP_DRVR_AUTO_FAILBACK_SUPPORT and + * MP_DRVR_AUTO_FAILBACK_SUPPORT_LU + * can be supported at the same time. + */ + +#define MP_DRVR_AUTO_FAILBACK_SUPPORT_NONE 0 +#define MP_DRVR_AUTO_FAILBACK_SUPPORT (1<<0) +#define MP_DRVR_AUTO_FAILBACK_SUPPORT_LU (1<<1) + + +/* Constants for defaultLoadBalanceType */ + +#define MP_DRVR_LOAD_BALANCE_TYPE_UNKNOWN 0 +#define MP_DRVR_LOAD_BALANCE_TYPE_ROUNDROBIN (1<<0) +#define MP_DRVR_LOAD_BALANCE_TYPE_LEASTBLOCKS (1<<1) +#define MP_DRVR_LOAD_BALANCE_TYPE_LEASTIO (1<<2) +#define MP_DRVR_LOAD_BALANCE_TYPE_DEVICE_PRODUCT (1<<3) +#define MP_DRVR_LOAD_BALANCE_TYPE_LBA_REGION (1<<4) +#define MP_DRVR_LOAD_BALANCE_TYPE_PROPRIETARY1 (1<<16) +#define MP_DRVR_LOAD_BALANCE_TYPE_PROPRIETARY2 (1<<17) + + +/* Constants for autoProbingSupport */ + +/* + * Both MP_DRVR_AUTO_PROBING_SUPPORT and + * MP_DRVR_AUTO_PROBING_SUPPORT_LU + * can be supported at the same time. + */ + +#define MP_DRVR_AUTO_PROBING_SUPPORT_NONE 0 +#define MP_DRVR_AUTO_PROBING_SUPPORT (1<<0) +#define MP_DRVR_AUTO_PROBING_SUPPORT_LU (1<<1) + + +/* Structures for MP_DEVICE_PRODUCT_PROPERTIES */ + +typedef struct mp_vendor_prod_info { + char vendor[8]; + char product[16]; + char revision[4]; + char reserved[4]; /* padding for 64bit alignment */ +} mp_vendor_prod_info_t; + +typedef struct mp_dev_prod_prop { + struct mp_vendor_prod_info prodInfo; + uint32_t supportedLoadBalanceTypes; + uint32_t reserved; /* 64bit alignment padding */ + uint64_t id; +} mp_dev_prod_prop_t; + + +/* Structure for MP_MULTIPATH_LOGICAL_UNIT_PROPERTIES */ + +typedef struct mp_logical_unit_prop { + struct mp_vendor_prod_info prodInfo; + char name[256]; /* guid */ + uint32_t nameType; + uint32_t luGroupID; + char deviceFileName[256]; + uint64_t id; + boolean_t asymmetric; + uint32_t currentLoadBalanceType; + boolean_t autoFailbackEnabled; + uint32_t failbackPollingRateMax; + uint32_t currentFailBackPollingRate; + uint32_t autoProbingEnabled; + uint32_t probingPollingRateMax; + uint32_t currentProbingPollingRate; + uint64_t overridePathID; + boolean_t overridePathInUse; + uint32_t proprietaryPropSize; + caddr_t proprietaryProp; +} mp_logical_unit_prop_t; + + +/* Constants for nameType */ + +#define MP_DRVR_NAME_TYPE_UNKNOWN 0 +#define MP_DRVR_NAME_TYPE_VPD83_TYPE1 1 +#define MP_DRVR_NAME_TYPE_VPD83_TYPE2 2 +#define MP_DRVR_NAME_TYPE_VPD83_TYPE3 3 +#define MP_DRVR_NAME_TYPE_DEVICE_SPECIFIC 4 + + +/* Structure for MP_INITIATOR_PORT_PROPERTIES */ + +typedef struct mp_init_port_prop { + char portID[256]; + char osDeviceFile[256]; + uint32_t portType; + uint32_t reserved; /* padding for 64bit alignment */ + uint64_t id; +} mp_init_port_prop_t; + + +/* Constants for portType */ + +#define MP_DRVR_TRANSPORT_TYPE_UNKNOWN 0 +#define MP_DRVR_TRANSPORT_TYPE_FC 2 +#define MP_DRVR_TRANSPORT_TYPE_SPI 3 +#define MP_DRVR_TRANSPORT_TYPE_ISCSI 4 +#define MP_DRVR_TRANSPORT_TYPE_IFB 5 + + +/* Structure for MP_TARGET_PORT_PROPERTIES */ + +typedef struct mp_target_port_prop { + char portName[256]; + uint32_t relativePortID; + uint32_t reserved; /* padding for 64bit alignment */ + uint64_t id; +} mp_target_port_prop_t; + + +/* Structure for MP_TARGET_PORT_GROUP_PROPERTIES */ + +typedef struct mp_tpg_prop { + uint32_t accessState; + boolean_t explicitFailover; + uint32_t tpgId; /* T10 defined id in report/set TPG */ + boolean_t preferredLuPath; + boolean_t supportsLuAssignment; + uint32_t reserved; /* padding for 64bit alignment */ + uint64_t id; +} mp_tpg_prop_t; + + +/* Constants for accessState */ + +#define MP_DRVR_ACCESS_STATE_ACTIVE_OPTIMIZED 0 +#define MP_DRVR_ACCESS_STATE_ACTIVE_NONOPTIMIZED 0x1 +#define MP_DRVR_ACCESS_STATE_STANDBY 0x2 +#define MP_DRVR_ACCESS_STATE_UNAVAILABLE 0x3 +#define MP_DRVR_ACCESS_STATE_TRANSITIONING 0xf +#define MP_DRVR_ACCESS_STATE_ACTIVE 0x10 + + +/* Structure for MP_PATH_LOGICAL_UNIT_PROPERTIES */ + +typedef struct mp_path_prop { + uint32_t weight; + uint32_t pathState; + boolean_t disabled; + uint32_t reserved; /* 64bit alignment padding */ + uint64_t id; + struct mp_init_port_prop initPort; + struct mp_target_port_prop targetPort; + struct mp_logical_unit_prop logicalUnit; +} mp_path_prop_t; + + +/* Constants for pathState */ + +#define MP_DRVR_PATH_STATE_ACTIVE 0 +#define MP_DRVR_PATH_STATE_PASSIVE 1 +#define MP_DRVR_PATH_STATE_PATH_ERR 2 +#define MP_DRVR_PATH_STATE_LU_ERR 3 +#define MP_DRVR_PATH_STATE_RESERVED 4 +#define MP_DRVR_PATH_STATE_REMOVED 5 +#define MP_DRVR_PATH_STATE_TRANSITIONING 6 +#define MP_DRVR_PATH_STATE_UNKNOWN 7 + + +/* Structure for MP_PROPRIETARY_LOAD_BALANCE_PROPERTIES */ + +typedef struct mp_proprietary_loadbalance_prop { + char name[256]; + char vendorName[256]; + uint64_t id; + uint32_t typeIndex; + uint32_t proprietaryPropSize; + caddr_t proprietaryProp; +} mp_proprietary_loadbalance_prop_t; + + +/* + * Structure used as input to + * MP_ASSIGN_LU_TO_TPG subcmd. + */ + +typedef struct mp_lu_tpg_pair { + uint64_t luId; + uint64_t tpgId; +} mp_lu_tpg_pair_t; + + +/* + * Structure used as input to + * MP_SET_TPG_ACCESS_STATE subcmd. + */ + +typedef struct mp_set_tpg_state_req { + struct mp_lu_tpg_pair luTpgPair; + uint32_t desiredState; + uint32_t reserved; /* padding for 64bit boundary */ +} mp_set_tpg_state_req_t; + + +/* + * Structure for ioctl data + */ +typedef struct mp_iocdata { + uint16_t mp_xfer; /* direction */ + uint16_t mp_cmd; /* sub command */ + uint16_t mp_flags; /* flags */ + uint16_t mp_cmd_flags; /* command specific flags */ + size_t mp_ilen; /* Input buffer length */ + caddr_t mp_ibuf; /* Input buffer */ + size_t mp_olen; /* Output buffer length */ + caddr_t mp_obuf; /* Output buffer */ + size_t mp_alen; /* Auxiliary buffer length */ + caddr_t mp_abuf; /* Auxiliary buffer */ + int mp_errno; /* MPAPI driver internal error code */ +} mp_iocdata_t; + + +#ifdef _KERNEL + +#if defined(_SYSCALL32) + +#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 +#pragma pack(4) +#endif + +/* + * Structure for 32-bit ioctl data + */ + +typedef struct mp_iocdata32 { + uint16_t mp_xfer; /* direction */ + uint16_t mp_cmd; /* sub command */ + uint16_t mp_flags; /* flags */ + uint16_t mp_cmd_flags; /* command specific flags */ + uint32_t mp_ilen; /* Input buffer length */ + caddr32_t mp_ibuf; /* Input buffer */ + uint32_t mp_olen; /* Output buffer length */ + caddr32_t mp_obuf; /* Output buffer */ + uint32_t mp_alen; /* Auxiliary buffer length */ + caddr32_t mp_abuf; /* Auxiliary buffer */ + int32_t mp_errno; /* MPAPI driver internal error code */ +} mp_iocdata32_t; + +#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 +#pragma pack() +#endif + +#endif /* _SYSCALL32 */ + +#endif /* _KERNEL */ + + +/* Constants for MP_XFER */ + +#define MP_XFER_NONE 0x00 +#define MP_XFER_READ 0x01 +#define MP_XFER_WRITE 0x02 +#define MP_XFER_RW (MP_XFER_READ | MP_XFER_WRITE) + + +/* Constants for MP_OBJECT_TYPE */ + +#define MP_OBJECT_TYPE_UNKNOWN 0 +#define MP_OBJECT_TYPE_PLUGIN 1 +#define MP_OBJECT_TYPE_INITIATOR_PORT 2 +#define MP_OBJECT_TYPE_TARGET_PORT 3 +#define MP_OBJECT_TYPE_MULTIPATH_LU 4 +#define MP_OBJECT_TYPE_PATH_LU 5 +#define MP_OBJECT_TYPE_DEVICE_PRODUCT 6 +#define MP_OBJECT_TYPE_TARGET_PORT_GROUP 7 +#define MP_OBJECT_TYPE_PROPRIETARY_LOAD_BALANCE 8 +#define MP_OBJECT_TYPE_LAST_ENTRY MP_OBJECT_TYPE_PROPRIETARY_LOAD_BALANCE +#define MP_MAX_OBJECT_TYPE (MP_OBJECT_TYPE_LAST_ENTRY + 1) + + +/* Constants for MP_CMD */ + +#define MPAPI_CTL ('m'<<8) +#define MP_CMD (MPAPI_CTL | 2005) +#define MP_SUB_CMD ('M'<<8) + +#define MP_API_SUBCMD_MIN (MP_SUB_CMD + 0x01) +#define MP_GET_DRIVER_PROP (MP_SUB_CMD + 0x01) +#define MP_GET_DEV_PROD_LIST (MP_SUB_CMD + 0x02) +#define MP_GET_DEV_PROD_PROP (MP_SUB_CMD + 0x03) +#define MP_GET_LU_LIST (MP_SUB_CMD + 0x04) +#define MP_GET_LU_LIST_FROM_TPG (MP_SUB_CMD + 0x05) +#define MP_GET_LU_PROP (MP_SUB_CMD + 0x06) +#define MP_GET_PATH_LIST_FOR_MP_LU (MP_SUB_CMD + 0x07) +#define MP_GET_PATH_LIST_FOR_INIT_PORT (MP_SUB_CMD + 0x08) +#define MP_GET_PATH_LIST_FOR_TARGET_PORT (MP_SUB_CMD + 0x09) +#define MP_GET_PATH_PROP (MP_SUB_CMD + 0x0a) +#define MP_GET_INIT_PORT_LIST (MP_SUB_CMD + 0x0b) +#define MP_GET_INIT_PORT_PROP (MP_SUB_CMD + 0x0c) +#define MP_GET_TARGET_PORT_PROP (MP_SUB_CMD + 0x0d) +#define MP_GET_TPG_LIST (MP_SUB_CMD + 0x0e) +#define MP_GET_TPG_PROP (MP_SUB_CMD + 0x0f) +#define MP_GET_TPG_LIST_FOR_LU (MP_SUB_CMD + 0x10) +#define MP_GET_TARGET_PORT_LIST_FOR_TPG (MP_SUB_CMD + 0x11) +#define MP_SET_TPG_ACCESS_STATE (MP_SUB_CMD + 0x12) +#define MP_ENABLE_AUTO_FAILBACK (MP_SUB_CMD + 0x13) +#define MP_DISABLE_AUTO_FAILBACK (MP_SUB_CMD + 0x14) +#define MP_ENABLE_PATH (MP_SUB_CMD + 0x15) +#define MP_DISABLE_PATH (MP_SUB_CMD + 0x16) +#define MP_GET_PROPRIETARY_LOADBALANCE_LIST (MP_SUB_CMD + 0x17) +#define MP_GET_PROPRIETARY_LOADBALANCE_PROP (MP_SUB_CMD + 0x18) +#define MP_ASSIGN_LU_TO_TPG (MP_SUB_CMD + 0x19) +#define MP_API_SUBCMD_MAX (MP_ASSIGN_LU_TO_TPG) + + +/* + * Typical MP API ioctl interface specific Return Values + */ + +#define MP_IOCTL_ERROR_START 0x5533 +#define MP_MORE_DATA (MP_IOCTL_ERROR_START + 1) +#define MP_DRVR_INVALID_ID (MP_IOCTL_ERROR_START + 2) +#define MP_DRVR_ID_OBSOLETE (MP_IOCTL_ERROR_START + 3) +#define MP_DRVR_ACCESS_SYMMETRIC (MP_IOCTL_ERROR_START + 4) +#define MP_DRVR_PATH_UNAVAILABLE (MP_IOCTL_ERROR_START + 5) +#define MP_DRVR_IDS_NOT_ASSOCIATED (MP_IOCTL_ERROR_START + 6) +#define MP_DRVR_ILLEGAL_ACCESS_STATE_REQUEST (MP_IOCTL_ERROR_START + 7) + +/* + * Macros for OID operations + */ +#define MP_ID_SHIFT4MAJOR 32 +#define MP_GET_MAJOR_FROM_ID(id) ((id) >> MP_ID_SHIFT4MAJOR) +#define MP_GET_INST_FROM_ID(id) ((id) & 0x00000000ffffffff) +#define MP_STORE_INST_TO_ID(inst, id) (((uint64_t)(inst)) | id) +#define MP_STORE_MAJOR_TO_ID(major, id) \ + ((((uint64_t)(major)) << MP_ID_SHIFT4MAJOR) | id) + +/* + * Event Class and Sub-Class definitions + */ +#define EC_SUN_MP "EC_sun_mp" + +#define ESC_SUN_MP_LU_CHANGE "ESC_sun_mp_lu_change" + +#define ESC_SUN_MP_PATH_CHANGE "ESC_sun_mp_path_change" +#define ESC_SUN_MP_PATH_ADD "ESC_sun_mp_path_add" +#define ESC_SUN_MP_PATH_REMOVE "ESC_sun_mp_path_remove" + +#define ESC_SUN_MP_INIT_PORT_CHANGE "ESC_sun_mp_init_port_change" + +#define ESC_SUN_MP_TPG_CHANGE "ESC_sun_mp_tpg_change" +#define ESC_SUN_MP_TPG_ADD "ESC_sun_mp_tpg_add" +#define ESC_SUN_MP_TPG_REMOVE "ESC_sun_mp_tpg_remove" + +#define ESC_SUN_MP_TARGET_PORT_CHANGE "ESC_sun_mp_target_port_change" +#define ESC_SUN_MP_TARGET_PORT_ADD "ESC_sun_mp_target_port_add" +#define ESC_SUN_MP_TARGET_PORT_REMOVE "ESC_sun_mp_target_port_remove" + +#define ESC_SUN_MP_DEV_PROD_CHANGE "ESC_sun_mp_dev_prod_change" +#define ESC_SUN_MP_DEV_PROD_ADD "ESC_sun_mp_dev_prod_add" +#define ESC_SUN_MP_DEV_PROD_REMOVE "ESC_sun_mp_dev_prod_remove" + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_SCSI_ADAPTERS_MPAPI_IMPL_H */ diff --git a/usr/src/uts/common/sys/scsi/adapters/mpapi_scsi_vhci.h b/usr/src/uts/common/sys/scsi/adapters/mpapi_scsi_vhci.h new file mode 100644 index 0000000000..08af5735b4 --- /dev/null +++ b/usr/src/uts/common/sys/scsi/adapters/mpapi_scsi_vhci.h @@ -0,0 +1,161 @@ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_SCSI_ADAPTERS_MPAPI_SCSI_VHCI_H +#define _SYS_SCSI_ADAPTERS_MPAPI_SCSI_VHCI_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(_BIT_FIELDS_LTOH) && !defined(_BIT_FIELDS_HTOL) +#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined +#endif /* _BIT_FIELDS_LTOH */ + + +#include <sys/scsi/adapters/mpapi_impl.h> + +/* Structure for MP_OID (kernel level only) */ + +typedef struct mp_oid { +#if defined(_BIT_FIELDS_HTOL) + uint32_t tstamp; + uint32_t type:8, + seq_id:24; +#else + uint32_t seq_id:24, + type:8; + uint32_t tstamp; +#endif +} mp_oid_t; + +typedef union mpoid { + uint64_t raw_oid; /* raw oid */ + mp_oid_t disc_oid; /* discrete oid */ +} mpoid_t; + + +/* + * MP API item - A generic one to use in a list setup + * in a common way for all types of elements of + * Object type items required for mpapi. + */ + +typedef struct mpapi_item { + mpoid_t oid; + void *idata; /* item data */ +}mpapi_item_t; + +typedef struct mpapi_item_list { + mpapi_item_t *item; + struct mpapi_item_list *next; +}mpapi_item_list_t; + +/* + * MP API item header definition. + */ + +typedef struct mpapi_list_header { + mpapi_item_list_t *head; + mpapi_item_list_t *tail; +}mpapi_list_header_t; + +/* + * Structure to maintain mp api initiator data. + */ +typedef struct mpapi_initiator_data { + void *resp; /* phci */ + mpapi_list_header_t *path_list; + int valid; + mp_init_port_prop_t prop; +} mpapi_initiator_data_t; + +/* + * Structure to maintain mp api lu data. + */ +typedef struct mpapi_lu_data { + void *resp; /* vlun */ + mpapi_list_header_t *path_list; + mpapi_list_header_t *tpg_list; + int valid; + mp_logical_unit_prop_t prop; +} mpapi_lu_data_t; + +/* + * Structure to maintain mp api path data. + */ +typedef struct mpapi_path_data { + void *resp; /* pip */ + char *path_name; + int valid; + mp_path_prop_t prop; +} mpapi_path_data_t; + +/* + * Structure to maintain mp api tpg data. + */ +typedef struct mpapi_tpg_data { + void *resp; /* target port prop, but non-unique */ + mpapi_list_header_t *tport_list; + mpapi_list_header_t *lu_list; /* mpath lu or lun list */ + int valid; + mp_tpg_prop_t prop; +} mpapi_tpg_data_t; + +/* + * Structure to maintain mp api tport data. + */ +typedef struct mpapi_tport_data { + void *resp; /* target port prop */ + mpapi_list_header_t *path_list; + int valid; + mp_target_port_prop_t prop; +} mpapi_tport_data_t; + + +/* Structure for mpapi private data */ + +typedef struct mpapi_priv { + + /* + * Will be initialized with the lbolt value(lower + * 32 bits) at the time of initialization. This will + * enable detection of stale OIDs used by the + * upper layers. + */ + uint32_t tstamp; + /* + * The Seq number space is unique within an Object + * type - that is there can be a seq# 2 in Object type + * 'initiator Port' and also a seq#2 in object type + * 'Path LU'. Even though the seq space collides, + * the unique type field(Object type) will make them + * distinct. + * The following field will indicate what the next + * sequence number that can be used for a particular + * type of Object type - Object type will be used to + * index into the array element. + */ + uint32_t oid_seq[MP_MAX_OBJECT_TYPE]; + + /* + * One list for each type of object. + */ + mpapi_list_header_t *obj_hdr_list[MP_MAX_OBJECT_TYPE]; + + /* + * Still to do.. LBA + */ + + +} mpapi_priv_t; + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_SCSI_ADAPTERS_MPAPI_SCSI_VHCI_H */ diff --git a/usr/src/uts/common/sys/scsi/adapters/scsi_vhci.h b/usr/src/uts/common/sys/scsi/adapters/scsi_vhci.h index eb7d0ad65a..b2b5346873 100644 --- a/usr/src/uts/common/sys/scsi/adapters/scsi_vhci.h +++ b/usr/src/uts/common/sys/scsi/adapters/scsi_vhci.h @@ -36,6 +36,8 @@ #include <sys/mhd.h> #include <sys/sunmdi.h> #include <sys/mdi_impldefs.h> +#include <sys/scsi/adapters/mpapi_impl.h> +#include <sys/scsi/adapters/mpapi_scsi_vhci.h> #ifdef __cplusplus extern "C" { @@ -215,6 +217,13 @@ extern int vhci_debug; #define SCSI_OPTIONS_VHCI(n) ((n) & SCSI_OPTIONS_VHCI_MASK) +typedef struct vhci_dev_vidpid_entry { + char vid[10]; + int vid_len; + char pid[20]; + int pid_len; +} vhci_dev_vidpid_entry_t; + struct scsi_vhci_swarg; typedef struct vhci_prin_readkeys { @@ -459,6 +468,7 @@ struct scsi_vhci { taskq_t *vhci_update_pathstates_taskq; struct scsi_reset_notify_entry *vhci_reset_notify_listf; uint16_t vhci_conf_flags; + mpapi_priv_t *mp_priv; }; /* @@ -724,6 +734,7 @@ typedef struct sv_switch_to_cntlr_iocdata { #define SCSI_VHCI_PATH_DISABLE (SCSI_VHCI_CTL_SUB_CMD + 0x0C) #define SCSI_VHCI_PATH_ENABLE (SCSI_VHCI_CTL_SUB_CMD + 0x0D) +#define SCSI_VHCI_MPAPI (SCSI_VHCI_CTL_SUB_CMD + 0x0E) #ifdef __cplusplus } diff --git a/usr/src/uts/common/sys/scsi/impl/services.h b/usr/src/uts/common/sys/scsi/impl/services.h index f2324e9b8b..9f48d0aabf 100644 --- a/usr/src/uts/common/sys/scsi/impl/services.h +++ b/usr/src/uts/common/sys/scsi/impl/services.h @@ -144,9 +144,36 @@ extern char *sense_keys[NUM_SENSE_KEYS + NUM_IMPL_SENSE_KEYS]; #define INTERCONNECT_ISCSI 8 #define INTERCONNECT_IBSRP 9 #define INTERCONNECT_SATA 10 +#define INTERCONNECT_MAX 11 /* Change this appropriately, */ + /* as new one(s) are added. */ + /* Is always the last & max. */ + +/* INTERCONNECT TYPE STRINGS */ +#define INTERCONNECT_PARALLEL_STR "SPI" +#define INTERCONNECT_FIBRE_STR "FIBRE" +#define INTERCONNECT_1394_STR "1394" +#define INTERCONNECT_SSA_STR "" +#define INTERCONNECT_FABRIC_STR "FABRIC" +#define INTERCONNECT_USB_STR "USB" +#define INTERCONNECT_ATAPI_STR "ATAPI" +#define INTERCONNECT_ISCSI_STR "iSCSI" +#define INTERCONNECT_IBSRP_STR "IB" +#define INTERCONNECT_SATA_STR "SATA" + #define INTERCONNECT_TYPE_ASCII { \ - "", "SPI", "FC", "1394", "", "FC", "USB", \ - "ATAPI", "iSCSI", "IB", "SATA", NULL } + "", \ + INTERCONNECT_PARALLEL_STR, \ + INTERCONNECT_FIBRE_STR, \ + INTERCONNECT_1394_STR, \ + INTERCONNECT_SSA_STR, \ + INTERCONNECT_FABRIC_STR, \ + INTERCONNECT_USB_STR, \ + INTERCONNECT_ATAPI_STR, \ + INTERCONNECT_ISCSI_STR, \ + INTERCONNECT_IBSRP_STR, \ + INTERCONNECT_SATA_STR, \ + NULL \ + }; /* * Compatibility... diff --git a/usr/src/uts/common/sys/scsi/impl/transport.h b/usr/src/uts/common/sys/scsi/impl/transport.h index 92b6c0ef92..034b3f9453 100644 --- a/usr/src/uts/common/sys/scsi/impl/transport.h +++ b/usr/src/uts/common/sys/scsi/impl/transport.h @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -253,6 +253,12 @@ struct scsi_hba_tran { pm_bus_power_op_t op, void *arg, void *result); + + /* + * Inter-Connect type of trasnport as defined in + * usr/src/uts/common/sys/scsi/impl/services.h + */ + int tran_interconnect_type; }; #ifdef __lock_lint @@ -371,6 +377,8 @@ extern void scsi_hba_nodename_compatible_free( */ #define SCSI_HBA_TRAN_CLONE 0x01 /* clone scsi_hba_tran_t */ /* structure per target */ +#define SCSI_HBA_TRAN_ALLOC 0x02 /* set if scsi_hba_tran_alloc */ + /* is called */ /* * Flags for scsi_hba allocation functions diff --git a/usr/src/uts/common/sys/sunddi.h b/usr/src/uts/common/sys/sunddi.h index 0bc48cbd84..1f287da483 100644 --- a/usr/src/uts/common/sys/sunddi.h +++ b/usr/src/uts/common/sys/sunddi.h @@ -222,6 +222,7 @@ extern "C" { * DDI event definitions */ #define EC_DEVFS "EC_devfs" /* Event class devfs */ +#define EC_DDI "EC_ddi" /* Event class ddi */ /* Class devfs subclasses */ #define ESC_DEVFS_MINOR_CREATE "ESC_devfs_minor_create" @@ -232,14 +233,17 @@ extern "C" { #define ESC_DEVFS_BRANCH_ADD "ESC_devfs_branch_add" #define ESC_DEVFS_BRANCH_REMOVE "ESC_devfs_branch_remove" +/* Class ddi subclasses */ +#define ESC_DDI_INITIATOR_REGISTER "ESC_ddi_initiator_register" +#define ESC_DDI_INITIATOR_UNREGISTER "ESC_ddi_initiator_unregister" + /* DDI/NDI event publisher */ #define EP_DDI SUNW_KERN_PUB"ddi" /* * devfs event class attributes * - * The following attributes are private to EC_DEVFS - * event data. + * The following attributes are private to EC_DEVFS event data. */ #define DEVFS_DRIVER_NAME "di.driver" #define DEVFS_INSTANCE "di.instance" @@ -253,6 +257,17 @@ extern "C" { #define DEVFS_MINOR_MINORNUM "mi.minorno" /* + * ddi event class payload + * + * The following attributes are private to EC_DDI event data. + */ +#define DDI_DRIVER_NAME "ddi.driver" +#define DDI_DRIVER_MAJOR "ddi.major" +#define DDI_INSTANCE "ddi.instance" +#define DDI_PATHNAME "ddi.path" +#define DDI_CLASS "ddi.class" + +/* * Fault-related definitions * * The specific numeric values have been chosen to be ordered, but diff --git a/usr/src/uts/common/sys/sunmdi.h b/usr/src/uts/common/sys/sunmdi.h index 0c4efcb3e3..97fe1ea59a 100644 --- a/usr/src/uts/common/sys/sunmdi.h +++ b/usr/src/uts/common/sys/sunmdi.h @@ -241,6 +241,23 @@ void mdi_pi_set_phci_private(mdi_pathinfo_t *, caddr_t); int mdi_vhci_bus_config(dev_info_t *, uint_t, ddi_bus_config_op_t, void *, dev_info_t **, char *); +/* + * mdi_vhci node walker function + */ +void mdi_walk_vhcis(int (*f)(dev_info_t *, void *), void *arg); + +/* + * mdi_phci node walker function + */ +void mdi_vhci_walk_phcis(dev_info_t *, int (*f)(dev_info_t *, void *), + void *arg); + +/* + * mdi_client node walker function + */ +void mdi_vhci_walk_clients(dev_info_t *, int (*f)(dev_info_t *, void *), + void *arg); + #endif /* _KERNEL */ #ifdef __cplusplus diff --git a/usr/src/uts/intel/os/device_policy b/usr/src/uts/intel/os/device_policy index 3e667aa25f..c2f9733153 100644 --- a/usr/src/uts/intel/os/device_policy +++ b/usr/src/uts/intel/os/device_policy @@ -73,6 +73,7 @@ vni read_priv_set=net_rawaccess write_priv_set=net_rawaccess # md:admin write_priv_set=sys_config fssnap:ctl read_priv_set=sys_config write_priv_set=sys_config +scsi_vhci:devctl write_priv_set=sys_devices # # Other devices that require a privilege to open. # diff --git a/usr/src/uts/intel/os/minor_perm b/usr/src/uts/intel/os/minor_perm index d60196d570..4d7aa42b6c 100644 --- a/usr/src/uts/intel/os/minor_perm +++ b/usr/src/uts/intel/os/minor_perm @@ -115,3 +115,4 @@ aggr:* 0666 root sys smbios:smbios 0444 root sys zfs:* 0600 root sys zfs:zfs 0666 root sys +scsi_vhci:* 0666 root sys diff --git a/usr/src/uts/sparc/os/device_policy b/usr/src/uts/sparc/os/device_policy index 45f3294cf9..a6d7e1de52 100644 --- a/usr/src/uts/sparc/os/device_policy +++ b/usr/src/uts/sparc/os/device_policy @@ -78,6 +78,7 @@ vni read_priv_set=net_rawaccess write_priv_set=net_rawaccess # md:admin write_priv_set=sys_config fssnap:ctl read_priv_set=sys_config write_priv_set=sys_config +scsi_vhci:devctl write_priv_set=sys_devices # # Other devices that require a privilege to open. # diff --git a/usr/src/uts/sparc/os/minor_perm b/usr/src/uts/sparc/os/minor_perm index e46f3718ff..07c11962eb 100644 --- a/usr/src/uts/sparc/os/minor_perm +++ b/usr/src/uts/sparc/os/minor_perm @@ -164,3 +164,4 @@ aggr:* 0666 root sys ntwdt:* 0644 root sys zfs:* 0600 root sys zfs:zfs 0666 root sys +scsi_vhci:* 0666 root sys |