diff options
author | cth <none@none> | 2008-07-30 10:30:05 -0700 |
---|---|---|
committer | cth <none@none> | 2008-07-30 10:30:05 -0700 |
commit | b9ccdc5a0f0a722ae408b257a831b90011369316 (patch) | |
tree | 270c4af8f4db077f69e1a5160f17bdd1d0884756 | |
parent | 945a353f89a55e9591f2aefc0cf7a23800b354be (diff) | |
download | illumos-joyent-b9ccdc5a0f0a722ae408b257a831b90011369316.tar.gz |
PSARC/2008/412 Properties and Devinfo Snapshots
5034258 device size should be available in devinfo snapshots that request properties
5100405 Deadlock can occur due to the devinfo driver holding devi_lock
6276452 ddi_append_minor_node() and ddi_remove_minor_node() use the extra code to protect the critical code.
6588656 ddi_prop_op_size() should not check callers *lengthp on PROP_LEN_AND_VAL_ALLOC call
6720361 missing locks on devi_minor list traversal
6729639 scsi_hba code should not use DDI_MAJOR_T_UNKNOWN for properties
21 files changed, 1250 insertions, 1061 deletions
diff --git a/usr/src/cmd/mdb/common/modules/genunix/devinfo.c b/usr/src/cmd/mdb/common/modules/genunix/devinfo.c index a564225c8c..63fad43892 100644 --- a/usr/src/cmd/mdb/common/modules/genunix/devinfo.c +++ b/usr/src/cmd/mdb/common/modules/genunix/devinfo.c @@ -1110,7 +1110,6 @@ devinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { "S_OFFLINING", DEVI_S_OFFLINING, DEVI_S_OFFLINING }, { "S_INVOKING_DACF", DEVI_S_INVOKING_DACF, DEVI_S_INVOKING_DACF }, { "S_UNBOUND", DEVI_S_UNBOUND, DEVI_S_UNBOUND }, - { "S_MD_UPDATE", DEVI_S_MD_UPDATE, DEVI_S_MD_UPDATE }, { "S_REPORT", DEVI_S_REPORT, DEVI_S_REPORT }, { "S_EVADD", DEVI_S_EVADD, DEVI_S_EVADD }, { "S_EVREMOVE", DEVI_S_EVREMOVE, DEVI_S_EVREMOVE }, diff --git a/usr/src/cmd/prtconf/pdevinfo.c b/usr/src/cmd/prtconf/pdevinfo.c index 29b26fd5ef..8fb6d537cb 100644 --- a/usr/src/cmd/prtconf/pdevinfo.c +++ b/usr/src/cmd/prtconf/pdevinfo.c @@ -128,10 +128,10 @@ static const dumpops_t sysprop_dumpops = { #define NUM_ELEMENTS(A) (sizeof (A) / sizeof (A[0])) static int prop_type_guess(const dumpops_t *, void *, void **, int *); -static void dump_prop_list_common(const dumpops_t *, int, void *); static void walk_driver(di_node_t, di_devlink_handle_t); static int dump_devs(di_node_t, void *); -static int dump_prop_list(const dumpops_t *, const char *, int, di_node_t); +static int dump_prop_list(const dumpops_t *, const char *, + int, void *, dev_t); static int _error(const char *, ...); static int is_openprom(); static void walk(uchar_t *, uint_t, int); @@ -415,7 +415,6 @@ minor_ptr_set(di_minor_t minor, void *ptr) di_minor_private_set(minor, (void *)data); } - /* * In this comment typed properties are those of type DI_PROP_TYPE_UNDEF_IT, * DI_PROP_TYPE_BOOLEAN, DI_PROP_TYPE_INT, DI_PROP_TYPE_INT64, @@ -502,18 +501,80 @@ prop_type_guess(const dumpops_t *propops, void *prop, void **prop_data, return (len); } -static void -dump_prop_list_common(const dumpops_t *dumpops, int ilev, void *node) +/* + * Returns 0 if nothing is printed, 1 otherwise + */ +static int +dump_prop_list(const dumpops_t *dumpops, const char *name, int ilev, + void *node, dev_t dev) { - void *prop = DI_PROP_NIL, *prop_data; - char *p; - int i, prop_type, nitems; + void *prop = DI_PROP_NIL, *prop_data; + di_minor_t minor; + char *p; + int i, prop_type, nitems; + dev_t pdev; + int nprop = 0; while ((prop = NEXTPROP(dumpops)(node, prop)) != DI_PROP_NIL) { - nitems = prop_type_guess(dumpops, prop, &prop_data, &prop_type); + + /* Skip properties a dev_t oriented caller is not requesting */ + if (PROPDEVT(dumpops)) { + pdev = PROPDEVT(dumpops)(prop); + + if (dev == DDI_DEV_T_ANY) { + /* + * Caller requesting print all properties + */ + goto print; + } else if (dev == DDI_DEV_T_NONE) { + /* + * Caller requesting print of properties + * associated with devinfo (not minor). + */ + if ((pdev == DDI_DEV_T_ANY) || + (pdev == DDI_DEV_T_NONE)) + goto print; + + /* + * Property has a minor association, see if + * we have a minor with this dev_t. If there + * is no such minor we print the property now + * so it gets displayed. + */ + minor = DI_MINOR_NIL; + while ((minor = di_minor_next((di_node_t)node, + minor)) != DI_MINOR_NIL) { + if (di_minor_devt(minor) == pdev) + break; + } + if (minor == DI_MINOR_NIL) + goto print; + } else if (dev == pdev) { + /* + * Caller requesting print of properties + * associated with a specific matching minor + * node. + */ + goto print; + } + + /* otherwise skip print */ + continue; + } + +print: nitems = prop_type_guess(dumpops, prop, &prop_data, &prop_type); if (nitems < 0) continue; + if (nprop == 0) { + if (name) { + indent_to_level(ilev); + (void) printf("%s properties:\n", name); + } + ilev++; + } + nprop++; + indent_to_level(ilev); (void) printf("name='%s' type=", PROPNAME(dumpops)(prop)); @@ -548,15 +609,13 @@ dump_prop_list_common(const dumpops_t *dumpops, int ilev, void *node) (void) printf(" items=%i", nitems); /* print the major and minor numbers for a device property */ - if (PROPDEVT(dumpops) != NULL) { - dev_t dev; - - dev = PROPDEVT(dumpops)(prop); - if (dev != DDI_DEV_T_NONE) { - (void) printf(" dev=(%u,%u)", - (uint_t)major(dev), (uint_t)minor(dev)); - } else { + if (PROPDEVT(dumpops)) { + if ((pdev == DDI_DEV_T_NONE) || + (pdev == DDI_DEV_T_ANY)) { (void) printf(" dev=none"); + } else { + (void) printf(" dev=(%u,%u)", + (uint_t)major(pdev), (uint_t)minor(pdev)); } } @@ -598,6 +657,8 @@ dump_prop_list_common(const dumpops_t *dumpops, int ilev, void *node) (void) putchar('\n'); } + + return (nprop ? 1 : 0); } /* @@ -682,17 +743,17 @@ dump_devs(di_node_t node, void *arg) if (opts.o_verbose) { if (dump_prop_list(&sysprop_dumpops, "System", ilev + 1, - node)) { + node, DDI_DEV_T_ANY)) { (void) dump_prop_list(&globprop_dumpops, NULL, ilev + 1, - node); + node, DDI_DEV_T_ANY); } else { (void) dump_prop_list(&globprop_dumpops, - "System software", ilev + 1, node); + "System software", ilev + 1, node, DDI_DEV_T_ANY); } (void) dump_prop_list(&drvprop_dumpops, "Driver", ilev + 1, - node); + node, DDI_DEV_T_NONE); (void) dump_prop_list(&hwprop_dumpops, "Hardware", ilev + 1, - node); + node, DDI_DEV_T_ANY); dump_priv_data(ilev + 1, node); dump_pathing_data(ilev + 1, node); dump_link_data(ilev + 1, node, devlink_hdl); @@ -708,26 +769,6 @@ dump_devs(di_node_t node, void *arg) return (DI_WALK_CONTINUE); } -/* - * Returns 0 if nothing is printed, 1 otherwise - */ -static int -dump_prop_list(const dumpops_t *dumpops, const char *name, int ilev, - di_node_t node) -{ - if (NEXTPROP(dumpops)(node, DI_PROP_NIL) == DI_PROP_NIL) - return (0); - - if (name != NULL) { - indent_to_level(ilev); - (void) printf("%s properties:\n", name); - } - - dump_prop_list_common(dumpops, ilev + 1, node); - return (1); -} - - /* _error([no_perror, ] fmt [, arg ...]) */ static int _error(const char *opt_noperror, ...) @@ -979,8 +1020,8 @@ dump_pathing_data(int ilev, di_node_t node) indent_to_level(ilev); (void) printf("%s#%d (%s)\n", di_driver_name(phci_node), di_instance(phci_node), path_state_name(di_path_state(pi))); - - dump_prop_list_common(&pathprop_dumpops, ilev + 1, pi); + (void) dump_prop_list(&pathprop_dumpops, NULL, ilev + 1, + pi, DDI_DEV_T_ANY); } } @@ -1325,6 +1366,10 @@ dump_minor_data(int ilev, di_node_t node, di_devlink_handle_t devlink_hdl) /* display who has this device minor node open */ dump_minor_link_data(ilev + 1, node, devt, devlink_hdl); + + /* display properties associated with this devt */ + (void) dump_prop_list(&drvprop_dumpops, "Minor", + ilev + 1, node, devt); } /* diff --git a/usr/src/uts/common/fs/devfs/devfs_subr.c b/usr/src/uts/common/fs/devfs/devfs_subr.c index 897ba4455f..0d2791d326 100644 --- a/usr/src/uts/common/fs/devfs/devfs_subr.c +++ b/usr/src/uts/common/fs/devfs/devfs_subr.c @@ -268,7 +268,8 @@ dv_mkino(dev_info_t *devi, vtype_t typ, dev_t dev) static int dv_compare_nodes(const struct dv_node *dv1, const struct dv_node *dv2) { - int rv; + int rv; + if ((rv = strcmp(dv1->dv_name, dv2->dv_name)) == 0) return (0); return ((rv < 0) ? -1 : 1); @@ -282,8 +283,8 @@ dv_compare_nodes(const struct dv_node *dv1, const struct dv_node *dv2) struct dv_node * dv_mkroot(struct vfs *vfsp, dev_t devfsdev) { - struct dv_node *dv; - struct vnode *vp; + struct dv_node *dv; + struct vnode *vp; ASSERT(ddi_root_node() != NULL); ASSERT(dv_node_cache != NULL); @@ -332,9 +333,9 @@ dv_mkroot(struct vfs *vfsp, dev_t devfsdev) struct dv_node * dv_mkdir(struct dv_node *ddv, dev_info_t *devi, char *nm) { - struct dv_node *dv; - struct vnode *vp; - size_t nmlen; + struct dv_node *dv; + struct vnode *vp; + size_t nmlen; ASSERT((devi)); dcmn_err4(("dv_mkdir: %s\n", nm)); @@ -384,9 +385,9 @@ static struct dv_node * dv_mknod(struct dv_node *ddv, dev_info_t *devi, char *nm, struct ddi_minor_data *dmd) { - struct dv_node *dv; - struct vnode *vp; - size_t nmlen; + struct dv_node *dv; + struct vnode *vp; + size_t nmlen; dcmn_err4(("dv_mknod: %s\n", nm)); @@ -405,9 +406,12 @@ dv_mknod(struct dv_node *ddv, dev_info_t *devi, char *nm, vn_setops(vp, vn_getops(DVTOV(ddv))); vn_exists(vp); - ASSERT(MUTEX_HELD(&DEVI(devi)->devi_lock)); + /* increment dev_ref with devi_lock held */ + ASSERT(DEVI_BUSY_OWNED(devi)); + mutex_enter(&DEVI(devi)->devi_lock); dv->dv_devi = devi; DEVI(devi)->devi_ref++; + mutex_exit(&DEVI(devi)->devi_lock); dv->dv_ino = dv_mkino(devi, vp->v_type, vp->v_rdev); dv->dv_nlink = 0; /* updated on insert */ @@ -518,7 +522,7 @@ dv_findbyname(struct dv_node *ddv, char *nm) void dv_insert(struct dv_node *ddv, struct dv_node *dv) { - avl_index_t where; + avl_index_t where; ASSERT(RW_WRITE_HELD(&ddv->dv_contents)); ASSERT(DVTOV(ddv)->v_type == VDIR); @@ -577,7 +581,7 @@ dv_unlink(struct dv_node *ddv, struct dv_node *dv) void dv_vattr_merge(struct dv_node *dv, struct vattr *vap) { - struct vnode *vp = DVTOV(dv); + struct vnode *vp = DVTOV(dv); vap->va_nodeid = dv->dv_ino; vap->va_nlink = dv->dv_nlink; @@ -608,8 +612,8 @@ dv_vattr_merge(struct dv_node *dv, struct vattr *vap) void devfs_get_defattr(struct vnode *vp, struct vattr *vap, int *no_fs_perm) { - mperm_t mp; - struct dv_node *dv; + mperm_t mp; + struct dv_node *dv; /* If vp isn't a dv_node, return something sensible */ if (!vn_matchops(vp, dv_vnodeops)) { @@ -837,12 +841,12 @@ lookup: static int dv_find_leafnode(dev_info_t *devi, char *minor_nm, struct ddi_minor_data *r_mi) { - struct ddi_minor_data *dmd; + struct ddi_minor_data *dmd; ASSERT(i_ddi_devi_attached(devi)); - ASSERT(MUTEX_HELD(&DEVI(devi)->devi_lock)); dcmn_err3(("dv_find_leafnode: %s\n", minor_nm)); + ASSERT(DEVI_BUSY_OWNED(devi)); for (dmd = DEVI(devi)->devi_minor; dmd; dmd = dmd->next) { /* @@ -880,10 +884,10 @@ dv_find_leafnode(dev_info_t *devi, char *minor_nm, struct ddi_minor_data *r_mi) static struct dv_node * dv_clone_mknod(struct dv_node *ddv, char *drvname) { - major_t major; - struct dv_node *dvp; - char *devnm; - struct ddi_minor_data *dmd; + major_t major; + struct dv_node *dvp; + char *devnm; + struct ddi_minor_data *dmd; /* * Make sure drvname is a STREAMS driver. We load the driver, @@ -926,12 +930,13 @@ dv_find(struct dv_node *ddv, char *nm, struct vnode **vpp, struct pathname *pnp, { extern int isminiroot; /* see modctl.c */ - int rv = 0, was_busy = 0, nmlen, write_held = 0; - struct vnode *vp; - struct dv_node *dv, *dup; - dev_info_t *pdevi, *devi = NULL; - char *mnm; - struct ddi_minor_data *dmd; + int circ; + int rv = 0, was_busy = 0, nmlen, write_held = 0; + struct vnode *vp; + struct dv_node *dv, *dup; + dev_info_t *pdevi, *devi = NULL; + char *mnm; + struct ddi_minor_data *dmd; dcmn_err3(("dv_find %s\n", nm)); @@ -1119,24 +1124,29 @@ founddv: dv = dv_mkdir(ddv, devi, nm); } else { /* - * For clone minors, load the driver indicated by minor name. + * Allocate dmd first to avoid KM_SLEEP with active + * ndi_devi_enter. */ - mutex_enter(&DEVI(devi)->devi_lock); + dmd = kmem_zalloc(sizeof (*dmd), KM_SLEEP); + ndi_devi_enter(devi, &circ); if (devi == clone_dip) { + /* + * For clone minors, load the driver indicated by + * minor name. + */ dv = dv_clone_mknod(ddv, mnm + 1); } else { /* * Find minor node and make a dv_node */ - dmd = kmem_zalloc(sizeof (*dmd), KM_SLEEP); if (dv_find_leafnode(devi, mnm + 1, dmd) == 0) { dv = dv_mknod(ddv, devi, nm, dmd); if (dmd->ddm_node_priv) dpfree(dmd->ddm_node_priv); } - kmem_free(dmd, sizeof (*dmd)); } - mutex_exit(&DEVI(devi)->devi_lock); + ndi_devi_exit(devi, circ); + kmem_free(dmd, sizeof (*dmd)); } /* * Release hold from ndi_devi_config_one() @@ -1213,11 +1223,11 @@ notfound: void dv_filldir(struct dv_node *ddv) { - struct dv_node *dv; - dev_info_t *devi, *pdevi; - struct ddi_minor_data *dmd; - char devnm[MAXNAMELEN]; - int circ; + struct dv_node *dv; + dev_info_t *devi, *pdevi; + struct ddi_minor_data *dmd; + char devnm[MAXNAMELEN]; + int circ, ccirc; ASSERT(DVTOV(ddv)->v_type == VDIR); ASSERT(RW_WRITE_HELD(&ddv->dv_contents)); @@ -1240,7 +1250,7 @@ dv_filldir(struct dv_node *ddv) dcmn_err3(("dv_filldir: node %s\n", ddi_node_name(devi))); - mutex_enter(&DEVI(devi)->devi_lock); + ndi_devi_enter(devi, &ccirc); for (dmd = DEVI(devi)->devi_minor; dmd; dmd = dmd->next) { char *addr; @@ -1272,7 +1282,7 @@ dv_filldir(struct dv_node *ddv) dv_insert(ddv, dv); VN_RELE(DVTOV(dv)); } - mutex_exit(&DEVI(devi)->devi_lock); + ndi_devi_exit(devi, ccirc); (void) ddi_deviname(devi, devnm); if ((dv = dv_findbyname(ddv, devnm + 1)) == NULL) { @@ -1300,10 +1310,10 @@ dv_filldir(struct dv_node *ddv) int dv_cleandir(struct dv_node *ddv, char *devnm, uint_t flags) { - struct dv_node *dv; - struct dv_node *next; - struct vnode *vp; - int busy = 0; + struct dv_node *dv; + struct dv_node *next; + struct vnode *vp; + int busy = 0; /* * We should always be holding the tsd_clean_key here: dv_cleandir() @@ -1428,15 +1438,15 @@ set_busy: busy++; static int dv_reset_perm_dir(struct dv_node *ddv, uint_t flags) { - struct dv_node *dv; - struct vnode *vp; - int retval = 0; - struct vattr *attrp; - mperm_t mp; - char *nm; - uid_t old_uid; - gid_t old_gid; - mode_t old_mode; + struct dv_node *dv; + struct vnode *vp; + int retval = 0; + struct vattr *attrp; + mperm_t mp; + char *nm; + uid_t old_uid; + gid_t old_gid; + mode_t old_mode; rw_enter(&ddv->dv_contents, RW_WRITER); for (dv = DV_FIRST_ENTRY(ddv); dv; dv = DV_NEXT_ENTRY(ddv, dv)) { @@ -1524,8 +1534,8 @@ dv_reset_perm_dir(struct dv_node *ddv, uint_t flags) int devfs_reset_perm(uint_t flags) { - struct dv_node *dvp; - int rval; + struct dv_node *dvp; + int rval; if ((dvp = devfs_dip_to_dvnode(ddi_root_node())) == NULL) return (0); @@ -1555,17 +1565,17 @@ devfs_reset_perm(uint_t flags) static int devfs_remdrv_rmdir(vnode_t *dirvp, const char *dir, vnode_t *rvp) { - int error; - vnode_t *vp; - int eof; - struct iovec iov; - struct uio uio; - struct dirent64 *dp; - dirent64_t *dbuf; - size_t dlen; - size_t dbuflen; - int ndirents = 64; - char *nm; + int error; + vnode_t *vp; + int eof; + struct iovec iov; + struct uio uio; + struct dirent64 *dp; + dirent64_t *dbuf; + size_t dlen; + size_t dbuflen; + int ndirents = 64; + char *nm; VN_HOLD(dirvp); @@ -1651,21 +1661,21 @@ exit: int devfs_remdrv_cleanup(const char *dir, const char *nodename) { - int error; - vnode_t *vp; - vnode_t *dirvp; - int eof; - struct iovec iov; - struct uio uio; - struct dirent64 *dp; - dirent64_t *dbuf; - size_t dlen; - size_t dbuflen; - int ndirents = 64; - int nodenamelen = strlen(nodename); - char *nm; - struct pathname pn; - vnode_t *rvp; /* root node of the underlying attribute fs */ + int error; + vnode_t *vp; + vnode_t *dirvp; + int eof; + struct iovec iov; + struct uio uio; + struct dirent64 *dp; + dirent64_t *dbuf; + size_t dlen; + size_t dbuflen; + int ndirents = 64; + int nodenamelen = strlen(nodename); + char *nm; + struct pathname pn; + vnode_t *rvp; /* root node of the underlying attribute fs */ dcmn_err5(("devfs_remdrv_cleanup: %s %s\n", dir, nodename)); diff --git a/usr/src/uts/common/io/cmlb.c b/usr/src/uts/common/io/cmlb.c index 6b204ba86a..c3994cbb7f 100644 --- a/usr/src/uts/common/io/cmlb.c +++ b/usr/src/uts/common/io/cmlb.c @@ -41,6 +41,7 @@ #include <sys/efi_partition.h> #include <sys/cmlb.h> #include <sys/cmlb_impl.h> +#include <sys/ddi_impldefs.h> /* * Driver minor node structure and data table @@ -139,6 +140,18 @@ static struct driver_minor_data dk_minor_data_efi[] = { {0} }; +/* + * Declare the dynamic properties implemented in prop_op(9E) implementation + * that we want to have show up in a di_init(3DEVINFO) device tree snapshot + * of drivers that call cmlb_attach(). + */ +static i_ddi_prop_dyn_t cmlb_prop_dyn[] = { + {"Nblocks", DDI_PROP_TYPE_INT64, S_IFBLK}, + {"Size", DDI_PROP_TYPE_INT64, S_IFCHR}, + {"device-nblocks", DDI_PROP_TYPE_INT64}, + {"device-blksize", DDI_PROP_TYPE_INT}, + {NULL} +}; /* * External kernel interfaces @@ -595,6 +608,9 @@ cmlb_attach(dev_info_t *devi, cmlb_tg_ops_t *tgopsp, int device_type, return (ENXIO); } + /* Define the dynamic properties for devinfo spapshots. */ + i_ddi_prop_dyn_driver_set(CMLB_DEVINFO(cl), cmlb_prop_dyn); + cl->cl_state = CMLB_ATTACHED; mutex_exit(CMLB_MUTEX(cl)); @@ -624,6 +640,7 @@ cmlb_detach(cmlb_handle_t cmlbhandle, void *tg_cookie) cl->cl_def_labeltype = CMLB_LABEL_UNDEF; cl->cl_f_geometry_is_valid = FALSE; ddi_remove_minor_node(CMLB_DEVINFO(cl), NULL); + i_ddi_prop_dyn_driver_set(CMLB_DEVINFO(cl), NULL); cl->cl_state = CMLB_INITED; mutex_exit(CMLB_MUTEX(cl)); } @@ -1162,6 +1179,25 @@ cmlb_ioctl(cmlb_handle_t cmlbhandle, dev_t dev, int cmd, intptr_t arg, err = ENOTTY; } + + /* + * An ioctl that succeeds and changed ('set') size(9P) information + * needs to invalidate the cached devinfo snapshot to avoid having + * old information being returned in a snapshots. + * + * NB: When available, call ddi_change_minor_node() to clear + * SSIZEVALID in specfs vnodes via spec_size_invalidate(). + */ + if (err == 0) { + switch (cmd) { + case DKIOCSGEOM: + case DKIOCSAPART: + case DKIOCSVTOC: + case DKIOCSETEFI: + i_ddi_prop_dyn_cache_invalidate(CMLB_DEVINFO(cl), + i_ddi_prop_dyn_driver_get(CMLB_DEVINFO(cl))); + } + } return (err); } @@ -2737,7 +2773,7 @@ cmlb_build_default_label(struct cmlb_lun *cl, void *tg_cookie) /* * Refer to comments related to off-by-1 at the * header of this file. - * Before caculating geometry, capacity should be + * Before calculating geometry, capacity should be * decreased by 1. */ @@ -4735,3 +4771,106 @@ cmlb_dkio_partinfo(struct cmlb_lun *cl, dev_t dev, caddr_t arg, int flag) return (err); } #endif + +int +cmlb_prop_op(cmlb_handle_t cmlbhandle, + dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags, + char *name, caddr_t valuep, int *lengthp, int part, void *tg_cookie) +{ + struct cmlb_lun *cl; + diskaddr_t capacity; + uint32_t lbasize; + enum dp { DP_NBLOCKS, DP_BLKSIZE } dp; + int callers_length; + caddr_t buffer; + uint64_t nblocks64; + uint_t dblk; + + /* Always fallback to ddi_prop_op... */ + cl = (struct cmlb_lun *)cmlbhandle; + if (cl == NULL) { +fallback: return (ddi_prop_op(dev, dip, prop_op, mod_flags, + name, valuep, lengthp)); + } + + /* Pick up capacity and blocksize information. */ + capacity = cl->cl_blockcount; + if (capacity == 0) + goto fallback; + lbasize = cl->cl_tgt_blocksize; + if (lbasize == 0) + lbasize = DEV_BSIZE; /* 0 -> DEV_BSIZE units */ + + /* Check for dynamic property of whole device. */ + if (dev == DDI_DEV_T_ANY) { + /* Fallback to ddi_prop_op if we don't understand. */ + if (strcmp(name, "device-nblocks") == 0) + dp = DP_NBLOCKS; + else if (strcmp(name, "device-blksize") == 0) + dp = DP_BLKSIZE; + else + goto fallback; + + /* get callers length, establish length of our dynamic prop */ + callers_length = *lengthp; + if (dp == DP_NBLOCKS) + *lengthp = sizeof (uint64_t); + else if (dp == DP_BLKSIZE) + *lengthp = sizeof (uint32_t); + + /* service request for the length of the property */ + if (prop_op == PROP_LEN) + return (DDI_PROP_SUCCESS); + + switch (prop_op) { + case PROP_LEN_AND_VAL_ALLOC: + if ((buffer = kmem_alloc(*lengthp, + (mod_flags & DDI_PROP_CANSLEEP) ? + KM_SLEEP : KM_NOSLEEP)) == NULL) + return (DDI_PROP_NO_MEMORY); + *(caddr_t *)valuep = buffer; /* set callers buf */ + break; + + case PROP_LEN_AND_VAL_BUF: + /* the length of the prop and the request must match */ + if (callers_length != *lengthp) + return (DDI_PROP_INVAL_ARG); + buffer = valuep; /* get callers buf */ + break; + + default: + return (DDI_PROP_INVAL_ARG); + } + + /* transfer the value into the buffer */ + if (dp == DP_NBLOCKS) + *((uint64_t *)buffer) = capacity; + else if (dp == DP_BLKSIZE) + *((uint32_t *)buffer) = lbasize; + + return (DDI_PROP_SUCCESS); + } + + /* + * Support dynamic size oriented properties of partition. Requests + * issued under conditions where size is valid are passed to + * ddi_prop_op_nblocks with the size information, otherwise the + * request is passed to ddi_prop_op. Size depends on valid geometry. + */ + if (!cmlb_is_valid(cmlbhandle)) + goto fallback; + + /* Get partition nblocks value. */ + (void) cmlb_partinfo(cmlbhandle, part, + (diskaddr_t *)&nblocks64, NULL, NULL, NULL, tg_cookie); + + /* + * Assume partition information is in DEV_BSIZE units, compute + * divisor for size(9P) property representation. + */ + dblk = lbasize / DEV_BSIZE; + + /* Now let ddi_prop_op_nblocks_blksize() handle the request. */ + return (ddi_prop_op_nblocks_blksize(dev, dip, prop_op, mod_flags, + name, valuep, lengthp, nblocks64 / dblk, lbasize)); +} diff --git a/usr/src/uts/common/io/devinfo.c b/usr/src/uts/common/io/devinfo.c index 97556719bd..a61d0b1bfa 100644 --- a/usr/src/uts/common/io/devinfo.c +++ b/usr/src/uts/common/io/devinfo.c @@ -32,6 +32,7 @@ #include <sys/pathname.h> #include <sys/debug.h> #include <sys/autoconf.h> +#include <sys/vmsystm.h> #include <sys/conf.h> #include <sys/file.h> #include <sys/kmem.h> @@ -74,6 +75,8 @@ static int di_debug; */ static int di_max_opens = 32; +static int di_prop_dyn = 1; /* enable dynamic property support */ + #define DI_FULL_PARENT 0 #define DI_READONLY_PARENT 1 #define DI_NODE_SPECIES 2 @@ -85,7 +88,12 @@ static int di_max_opens = 32; #define IOC_COPY 3 /* copyout in progress */ /* - * Keep max alignment so we can move snapshot to different platforms + * Keep max alignment so we can move snapshot to different platforms. + * + * NOTE: Most callers should rely on the di_checkmem return value + * being aligned, and reestablish *off_p with aligned value, instead + * of trying to align size of their allocations: this approach will + * minimize memory use. */ #define DI_ALIGN(addr) ((addr + 7l) & ~7l) @@ -94,10 +102,10 @@ static int di_max_opens = 32; * Size of each chunk is buf_size. */ struct di_mem { - struct di_mem *next; /* link to next chunk */ - char *buf; /* contiguous kernel memory */ - size_t buf_size; /* size of buf in bytes */ - devmap_cookie_t cook; /* cookie from ddi_umem_alloc */ + struct di_mem *next; /* link to next chunk */ + char *buf; /* contiguous kernel memory */ + size_t buf_size; /* size of buf in bytes */ + devmap_cookie_t cook; /* cookie from ddi_umem_alloc */ }; /* @@ -124,15 +132,15 @@ struct di_stack { (stack)->circ[(stack)->depth - 1]); \ ((stack)->depth--); \ } -#define PUSH_STACK(stack, node, offp) { \ +#define PUSH_STACK(stack, node, off_p) { \ ASSERT(node != NULL); \ ndi_devi_enter((dev_info_t *)node, &(stack)->circ[(stack)->depth]); \ (stack)->dip[(stack)->depth] = (node); \ - (stack)->offset[(stack)->depth] = (void *)(offp); \ + (stack)->offset[(stack)->depth] = (void *)(off_p); \ ((stack)->depth)++; \ } -#define DI_ALL_PTR(s) ((struct di_all *)(intptr_t)di_mem_addr((s), 0)) +#define DI_ALL_PTR(s) DI_ALL(di_mem_addr((s), 0)) /* * With devfs, the device tree has no global locks. The device tree is @@ -228,17 +236,17 @@ typedef struct i_lnode { * Soft state associated with each instance of driver open. */ static struct di_state { - di_off_t mem_size; /* total # bytes in memlist */ - struct di_mem *memlist; /* head of memlist */ - uint_t command; /* command from ioctl */ - int di_iocstate; /* snapshot ioctl state */ - mod_hash_t *reg_dip_hash; - mod_hash_t *reg_pip_hash; - int lnode_count; - int link_count; - - mod_hash_t *lnode_hash; - mod_hash_t *link_hash; + di_off_t mem_size; /* total # bytes in memlist */ + struct di_mem *memlist; /* head of memlist */ + uint_t command; /* command from ioctl */ + int di_iocstate; /* snapshot ioctl state */ + mod_hash_t *reg_dip_hash; + mod_hash_t *reg_pip_hash; + int lnode_count; + int link_count; + + mod_hash_t *lnode_hash; + mod_hash_t *link_hash; } **di_states; static kmutex_t di_lock; /* serialize instance assignment */ @@ -285,18 +293,19 @@ static di_off_t di_copyformat(di_off_t, struct di_state *, intptr_t, int); static di_off_t di_snapshot_and_clean(struct di_state *); static di_off_t di_copydevnm(di_off_t *, struct di_state *); static di_off_t di_copytree(struct dev_info *, di_off_t *, struct di_state *); -static di_off_t di_copynode(struct di_stack *, struct di_state *); +static di_off_t di_copynode(struct dev_info *, struct di_stack *, + struct di_state *); static di_off_t di_getmdata(struct ddi_minor_data *, di_off_t *, di_off_t, struct di_state *); static di_off_t di_getppdata(struct dev_info *, di_off_t *, struct di_state *); static di_off_t di_getdpdata(struct dev_info *, di_off_t *, struct di_state *); -static di_off_t di_getprop(struct ddi_prop *, di_off_t *, - struct di_state *, struct dev_info *, int); +static di_off_t di_getprop(int, struct ddi_prop **, di_off_t *, + struct di_state *, struct dev_info *); static void di_allocmem(struct di_state *, size_t); static void di_freemem(struct di_state *); static void di_copymem(struct di_state *st, caddr_t buf, size_t bufsiz); static di_off_t di_checkmem(struct di_state *, di_off_t, size_t); -static caddr_t di_mem_addr(struct di_state *, di_off_t); +static void *di_mem_addr(struct di_state *, di_off_t); static int di_setstate(struct di_state *, int); static void di_register_dip(struct di_state *, dev_info_t *, di_off_t); static void di_register_pip(struct di_state *, mdi_pathinfo_t *, di_off_t); @@ -310,8 +319,14 @@ 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 int build_vhci_list(dev_info_t *vh_devinfo, void *arg); +static int build_phci_list(dev_info_t *ph_devinfo, void *arg); + +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 struct cb_ops di_cb_ops = { di_open, /* open */ @@ -401,7 +416,7 @@ static dev_info_t *di_dip; static int di_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) { - int error = DDI_FAILURE; + int error = DDI_FAILURE; switch (infocmd) { case DDI_INFO_DEVT2DEVINFO: @@ -425,7 +440,7 @@ di_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) static int di_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) { - int error = DDI_FAILURE; + int error = DDI_FAILURE; switch (cmd) { case DDI_ATTACH: @@ -458,7 +473,7 @@ di_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) static int di_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) { - int error = DDI_FAILURE; + int error = DDI_FAILURE; switch (cmd) { case DDI_DETACH: @@ -487,8 +502,8 @@ di_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) static int di_open(dev_t *devp, int flag, int otyp, cred_t *credp) { - int m; - minor_t minor_parent = getminor(*devp); + int m; + minor_t minor_parent = getminor(*devp); if (minor_parent != DI_FULL_PARENT && minor_parent != DI_READONLY_PARENT) @@ -527,8 +542,8 @@ di_open(dev_t *devp, int flag, int otyp, cred_t *credp) static int di_close(dev_t dev, int flag, int otype, cred_t *cred_p) { - struct di_state *st; - int m = (int)getminor(dev) - DI_NODE_SPECIES; + struct di_state *st; + int m = (int)getminor(dev) - DI_NODE_SPECIES; if (m < 0) { cmn_err(CE_WARN, "closing non-existent devinfo minor %d", @@ -559,17 +574,16 @@ di_close(dev_t dev, int flag, int otype, cred_t *cred_p) static int di_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp) { - int rv, error; - di_off_t off; - struct di_all *all; - struct di_state *st; - int m = (int)getminor(dev) - DI_NODE_SPECIES; - - major_t i; - char *drv_name; - size_t map_size, size; - struct di_mem *dcp; - int ndi_flags; + int rv, error; + di_off_t off; + struct di_all *all; + struct di_state *st; + int m = (int)getminor(dev) - DI_NODE_SPECIES; + major_t i; + char *drv_name; + size_t map_size, size; + struct di_mem *dcp; + int ndi_flags; if (m < 0 || m >= di_max_opens) { return (ENXIO); @@ -645,8 +659,7 @@ di_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp) if (di_setstate(st, IOC_COPY) == -1) return (EBUSY); - map_size = ((struct di_all *) - (intptr_t)di_mem_addr(st, 0))->map_size; + map_size = DI_ALL_PTR(st)->map_size; if (map_size == 0) { (void) di_setstate(st, IOC_DONE); return (EFAULT); @@ -712,17 +725,22 @@ di_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp) if (di_setstate(st, IOC_SNAP) == -1) return (EBUSY); + /* + * Initial memlist always holds di_all and the root_path - and + * is at least a page and size. + */ size = sizeof (struct di_all) + sizeof (((struct dinfo_io *)(NULL))->root_path); if (size < PAGESIZE) size = PAGESIZE; - di_allocmem(st, size); + off = di_checkmem(st, 0, size); + all = DI_ALL_PTR(st); + off += sizeof (struct di_all); /* real length of di_all */ - all = (struct di_all *)(intptr_t)di_mem_addr(st, 0); all->devcnt = devcnt; all->command = st->command; all->version = DI_SNAPSHOT_VERSION; - all->top_vhci_devinfo = 0; /* filled up by build_vhci_list. */ + all->top_vhci_devinfo = 0; /* filled by build_vhci_list. */ /* * Note the endianness in case we need to transport snapshot @@ -741,6 +759,7 @@ di_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp) (void) di_setstate(st, IOC_IDLE); return (EFAULT); } + off += size; /* real length of root_path */ if ((st->command & DINFOCLEANUP) && !DEVICES_FILES_CLEANABLE(st)) { di_freemem(st); @@ -755,8 +774,6 @@ di_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp) return (error); } - off = DI_ALIGN(sizeof (struct di_all) + size); - /* * Only the fully enabled version may force load drivers or read * the parent private data from a driver. @@ -834,8 +851,8 @@ di_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp) static void di_allocmem(struct di_state *st, size_t size) { - struct di_mem *mem = kmem_zalloc(sizeof (struct di_mem), - KM_SLEEP); + struct di_mem *mem = kmem_zalloc(sizeof (struct di_mem), KM_SLEEP); + /* * Round up size to nearest power of 2. If it is less * than st->mem_size, set it to st->mem_size (i.e., @@ -876,8 +893,8 @@ di_allocmem(struct di_state *st, size_t size) static void di_copymem(struct di_state *st, caddr_t buf, size_t bufsiz) { - struct di_mem *dcp; - size_t copysz; + struct di_mem *dcp; + size_t copysz; if (st->mem_size == 0) { ASSERT(st->memlist == NULL); @@ -910,7 +927,7 @@ di_copymem(struct di_state *st, caddr_t buf, size_t bufsiz) static void di_freemem(struct di_state *st) { - struct di_mem *dcp, *tmp; + struct di_mem *dcp, *tmp; dcmn_err2((CE_CONT, "di_freemem\n")); @@ -980,7 +997,7 @@ di_cache2mem(struct di_cache *cache, struct di_state *st) static size_t di_mem2cache(struct di_state *st, struct di_cache *cache) { - size_t map_size; + size_t map_size; ASSERT(cache->cache_size == 0); ASSERT(cache->cache_data == NULL); @@ -1040,6 +1057,8 @@ di_checkmem(struct di_state *st, di_off_t off, size_t size) di_allocmem(st, size); } + /* verify that return value is aligned */ + ASSERT(off == DI_ALIGN(off)); return (off); } @@ -1050,9 +1069,9 @@ di_checkmem(struct di_state *st, di_off_t off, size_t size) static di_off_t di_copyformat(di_off_t off, struct di_state *st, intptr_t arg, int mode) { - di_off_t size; - struct di_priv_data *priv; - struct di_all *all = (struct di_all *)(intptr_t)di_mem_addr(st, 0); + di_off_t size; + struct di_priv_data *priv; + struct di_all *all = DI_ALL_PTR(st); dcmn_err2((CE_CONT, "di_copyformat: off=%x, arg=%p mode=%x\n", off, (void *)arg, mode)); @@ -1083,8 +1102,7 @@ di_copyformat(di_off_t off, struct di_state *st, intptr_t arg, int mode) * check memory */ size = all->n_ppdata * sizeof (struct di_priv_format); - off = di_checkmem(st, off, size); - all->ppdata_format = off; + all->ppdata_format = off = di_checkmem(st, off, size); if (ddi_copyin(priv->parent, di_mem_addr(st, off), size, mode) != 0) { kmem_free(priv, sizeof (struct di_priv_data)); @@ -1099,8 +1117,7 @@ di_copyformat(di_off_t off, struct di_state *st, intptr_t arg, int mode) * check memory */ size = all->n_dpdata * sizeof (struct di_priv_format); - off = di_checkmem(st, off, size); - all->dpdata_format = off; + all->dpdata_format = off = di_checkmem(st, off, size); if (ddi_copyin(priv->driver, di_mem_addr(st, off), size, mode) != 0) { kmem_free(priv, sizeof (struct di_priv_data)); @@ -1117,10 +1134,10 @@ di_copyformat(di_off_t off, struct di_state *st, intptr_t arg, int mode) /* * Return the real address based on the offset (off) within snapshot */ -static caddr_t +static void * di_mem_addr(struct di_state *st, di_off_t off) { - struct di_mem *dcp = st->memlist; + struct di_mem *dcp = st->memlist; dcmn_err3((CE_CONT, "di_mem_addr: dcp=%p off=%x\n", (void *)dcp, off)); @@ -1147,9 +1164,9 @@ di_mem_addr(struct di_state *st, di_off_t off) static uint_t di_hash_byptr(void *arg, mod_hash_key_t key) { - struct di_key *dik = key; - size_t rshift; - void *ptr; + struct di_key *dik = key; + size_t rshift; + void *ptr; ASSERT(arg == NULL); @@ -1215,8 +1232,8 @@ di_dkey_cmp(struct di_dkey *dk1, struct di_dkey *dk2) static int di_pkey_cmp(struct di_pkey *pk1, struct di_pkey *pk2) { - char *p1, *p2; - int rv; + char *p1, *p2; + int rv; if (pk1->pk_pip != pk2->pk_pip) return (pk1->pk_pip > pk2->pk_pip ? 1 : -1); @@ -1243,7 +1260,7 @@ di_pkey_cmp(struct di_pkey *pk1, struct di_pkey *pk2) static int di_key_cmp(mod_hash_key_t key1, mod_hash_key_t key2) { - struct di_key *dik1, *dik2; + struct di_key *dik1, *dik2; dik1 = key1; dik2 = key2; @@ -1270,15 +1287,15 @@ di_key_cmp(mod_hash_key_t key1, mod_hash_key_t key2) static di_off_t di_snapshot(struct di_state *st) { - di_off_t off; - struct di_all *all; - dev_info_t *rootnode; - char buf[80]; - int plen; - char *path; - vnode_t *vp; + di_off_t off; + struct di_all *all; + dev_info_t *rootnode; + char buf[80]; + int plen; + char *path; + vnode_t *vp; - all = (struct di_all *)(intptr_t)di_mem_addr(st, 0); + all = DI_ALL_PTR(st); dcmn_err((CE_CONT, "Taking a snapshot of devinfo tree...\n")); /* @@ -1411,20 +1428,19 @@ di_snapshot_and_clean(struct di_state *st) /* * construct vhci linkage in the snapshot. */ -int +static 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; - phci_walk_arg_t pwa; + struct di_all *all; + struct di_node *me; + struct di_state *st; + di_off_t off; + phci_walk_arg_t 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)); + dcmn_err3((CE_CONT, "vhci node %s%d\n", + ddi_driver_name(vh_devinfo), ddi_get_instance(vh_devinfo))); st = (struct di_state *)arg; if (di_dip_find(st, vh_devinfo, &off) != 0) { @@ -1435,16 +1451,14 @@ build_vhci_list(dev_info_t *vh_devinfo, void *arg) dcmn_err3((CE_CONT, "st->mem_size: %d vh_devinfo off: 0x%x\n", st->mem_size, off)); - all = (struct di_all *)(intptr_t)di_mem_addr(st, 0); + all = DI_ALL_PTR(st); if (all->top_vhci_devinfo == 0) { all->top_vhci_devinfo = off; } else { - me = (struct di_node *) - (intptr_t)di_mem_addr(st, all->top_vhci_devinfo); + me = DI_NODE(di_mem_addr(st, all->top_vhci_devinfo)); while (me->next_vhci != 0) { - me = (struct di_node *) - (intptr_t)di_mem_addr(st, me->next_vhci); + me = DI_NODE(di_mem_addr(st, me->next_vhci)); } me->next_vhci = off; @@ -1460,41 +1474,37 @@ build_vhci_list(dev_info_t *vh_devinfo, void *arg) /* * construct phci linkage for the given vhci in the snapshot. */ -int +static int build_phci_list(dev_info_t *ph_devinfo, void *arg) { - struct di_node *vh_di_node; - struct di_node *me; - phci_walk_arg_t *pwa; - di_off_t off; + struct di_node *vh_di_node; + struct di_node *me; + phci_walk_arg_t *pwa; + di_off_t off; pwa = (phci_walk_arg_t *)arg; dcmn_err3((CE_CONT, "build_phci list for vhci at offset: 0x%x\n", pwa->off)); - vh_di_node = (struct di_node *)(intptr_t)di_mem_addr(pwa->st, pwa->off); - + vh_di_node = 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)); + dcmn_err3((CE_CONT, "phci node %s%d, at offset 0x%x\n", + ddi_driver_name(ph_devinfo), ddi_get_instance(ph_devinfo), off)); if (vh_di_node->top_phci == 0) { vh_di_node->top_phci = off; return (DDI_WALK_CONTINUE); } - me = (struct di_node *) - (intptr_t)di_mem_addr(pwa->st, vh_di_node->top_phci); + me = DI_NODE(di_mem_addr(pwa->st, vh_di_node->top_phci)); while (me->next_phci != 0) { - me = (struct di_node *) - (intptr_t)di_mem_addr(pwa->st, me->next_phci); + me = DI_NODE(di_mem_addr(pwa->st, me->next_phci)); } me->next_phci = off; @@ -1505,11 +1515,11 @@ build_phci_list(dev_info_t *ph_devinfo, void *arg) * Assumes all devinfo nodes in device tree have been snapshotted */ static void -snap_driver_list(struct di_state *st, struct devnames *dnp, di_off_t *poff_p) +snap_driver_list(struct di_state *st, struct devnames *dnp, di_off_t *off_p) { - struct dev_info *node; - struct di_node *me; - di_off_t off; + struct dev_info *node; + struct di_node *me; + di_off_t off; ASSERT(mutex_owned(&dnp->dn_lock)); @@ -1519,7 +1529,7 @@ snap_driver_list(struct di_state *st, struct devnames *dnp, di_off_t *poff_p) continue; ASSERT(off > 0); - me = (struct di_node *)(intptr_t)di_mem_addr(st, off); + me = DI_NODE(di_mem_addr(st, off)); ASSERT(me->next == 0 || me->next == -1); /* * Only nodes which were BOUND when they were @@ -1528,11 +1538,11 @@ snap_driver_list(struct di_state *st, struct devnames *dnp, di_off_t *poff_p) if (me->next != -1) continue; - *poff_p = off; - poff_p = &me->next; + *off_p = off; + off_p = &me->next; } - *poff_p = 0; + *off_p = 0; } /* @@ -1542,10 +1552,10 @@ snap_driver_list(struct di_state *st, struct devnames *dnp, di_off_t *poff_p) static di_off_t di_copydevnm(di_off_t *off_p, struct di_state *st) { - int i; - di_off_t off; - size_t size; - struct di_devnm *dnp; + int i; + di_off_t off; + size_t size; + struct di_devnm *dnp; dcmn_err2((CE_CONT, "di_copydevnm: *off_p = %p\n", (void *)off_p)); @@ -1553,15 +1563,13 @@ di_copydevnm(di_off_t *off_p, struct di_state *st) * make sure there is some allocated memory */ size = devcnt * sizeof (struct di_devnm); - off = di_checkmem(st, *off_p, size); - *off_p = off; + *off_p = off = di_checkmem(st, *off_p, size); + dnp = DI_DEVNM(di_mem_addr(st, off)); + off += size; dcmn_err((CE_CONT, "Start copying devnamesp[%d] at offset 0x%x\n", devcnt, off)); - dnp = (struct di_devnm *)(intptr_t)di_mem_addr(st, off); - off += size; - for (i = 0; i < devcnt; i++) { if (devnamesp[i].dn_name == NULL) { continue; @@ -1577,14 +1585,13 @@ di_copydevnm(di_off_t *off_p, struct di_state *st) * the same problem. */ dcmn_err2((CE_CONT, "di_copydevnm: %s%d, off=%x\n", - devnamesp[i].dn_name, devnamesp[i].dn_instance, - off)); + devnamesp[i].dn_name, devnamesp[i].dn_instance, off)); - off = di_checkmem(st, off, strlen(devnamesp[i].dn_name) + 1); - dnp[i].name = off; + size = strlen(devnamesp[i].dn_name) + 1; + dnp[i].name = off = di_checkmem(st, off, size); (void) strcpy((char *)di_mem_addr(st, off), devnamesp[i].dn_name); - off += DI_ALIGN(strlen(devnamesp[i].dn_name) + 1); + off += size; mutex_enter(&devnamesp[i].dn_lock); @@ -1605,9 +1612,9 @@ di_copydevnm(di_off_t *off_p, struct di_state *st) if ((DINFOPROP & st->command) && devnamesp[i].dn_global_prop_ptr) { dnp[i].global_prop = off; - off = di_getprop( - devnamesp[i].dn_global_prop_ptr->prop_list, - &dnp[i].global_prop, st, NULL, DI_PROP_GLB_LIST); + off = di_getprop(DI_PROP_GLB_LIST, + &devnamesp[i].dn_global_prop_ptr->prop_list, + &dnp[i].global_prop, st, NULL); } /* @@ -1639,8 +1646,9 @@ di_copydevnm(di_off_t *off_p, struct di_state *st) static di_off_t di_copytree(struct dev_info *root, di_off_t *off_p, struct di_state *st) { - di_off_t off; - struct di_stack *dsp = kmem_zalloc(sizeof (struct di_stack), KM_SLEEP); + di_off_t off; + struct dev_info *node; + struct di_stack *dsp = kmem_zalloc(sizeof (struct di_stack), KM_SLEEP); dcmn_err((CE_CONT, "di_copytree: root = %p, *off_p = %x\n", (void *)root, *off_p)); @@ -1667,7 +1675,8 @@ di_copytree(struct dev_info *root, di_off_t *off_p, struct di_state *st) * child and sibling nodes on the stack. */ while (!EMPTY_STACK(dsp)) { - off = di_copynode(dsp, st); + node = TOP_NODE(dsp); + off = di_copynode(node, dsp, st); } /* @@ -1684,24 +1693,23 @@ di_copytree(struct dev_info *root, di_off_t *off_p, struct di_state *st) * ioctl command. */ static di_off_t -di_copynode(struct di_stack *dsp, struct di_state *st) +di_copynode(struct dev_info *node, struct di_stack *dsp, struct di_state *st) { di_off_t off; struct di_node *me; - struct dev_info *node; + size_t size; dcmn_err2((CE_CONT, "di_copynode: depth = %x\n", dsp->depth)); - - node = TOP_NODE(dsp); - - ASSERT(node != NULL); + ASSERT((node != NULL) && (node == TOP_NODE(dsp))); /* * check memory usage, and fix offsets accordingly. */ - off = di_checkmem(st, *(TOP_OFFSET(dsp)), sizeof (struct di_node)); - *(TOP_OFFSET(dsp)) = off; + size = sizeof (struct di_node); + *(TOP_OFFSET(dsp)) = off = di_checkmem(st, *(TOP_OFFSET(dsp)), size); me = DI_NODE(di_mem_addr(st, off)); + me->self = off; + off += size; dcmn_err((CE_CONT, "copy node %s, instance #%d, at offset 0x%x\n", node->devi_node_name, node->devi_instance, off)); @@ -1711,9 +1719,8 @@ di_copynode(struct di_stack *dsp, struct di_state *st) * self -- offset of current node within snapshot * nodeid -- pointer to PROM node (tri-valued) * state -- hot plugging device state - * node_state -- devinfo node state (CF1, CF2, etc.) + * node_state -- devinfo node state */ - me->self = off; me->instance = node->devi_instance; me->nodeid = node->devi_nodeid; me->node_class = node->devi_node_class; @@ -1745,16 +1752,10 @@ di_copynode(struct di_stack *dsp, struct di_state *st) */ di_register_dip(st, (dev_info_t *)node, me->self); - /* - * increment offset - */ - off += sizeof (struct di_node); - #ifdef DEVID_COMPATIBILITY /* check for devid as property marker */ if (node->devi_devid_str) { ddi_devid_t devid; - int devid_size; /* * The devid is now represented as a property. For @@ -1765,44 +1766,43 @@ di_copynode(struct di_stack *dsp, struct di_state *st) */ if (ddi_devid_str_decode(node->devi_devid_str, &devid, NULL) == DDI_SUCCESS) { - devid_size = ddi_devid_sizeof(devid); - off = di_checkmem(st, off, devid_size); + size = ddi_devid_sizeof(devid); + off = di_checkmem(st, off, size); me->devid = off; - bcopy(devid, di_mem_addr(st, off), devid_size); - off += devid_size; + bcopy(devid, di_mem_addr(st, off), size); + off += size; ddi_devid_free(devid); } } #endif /* DEVID_COMPATIBILITY */ if (node->devi_node_name) { - off = di_checkmem(st, off, strlen(node->devi_node_name) + 1); - me->node_name = off; + size = strlen(node->devi_node_name) + 1; + me->node_name = off = di_checkmem(st, off, size); (void) strcpy(di_mem_addr(st, off), node->devi_node_name); - off += strlen(node->devi_node_name) + 1; + off += size; } if (node->devi_compat_names && (node->devi_compat_length > 1)) { - off = di_checkmem(st, off, node->devi_compat_length); - me->compat_names = off; - me->compat_length = node->devi_compat_length; - bcopy(node->devi_compat_names, di_mem_addr(st, off), - node->devi_compat_length); - off += node->devi_compat_length; + size = node->devi_compat_length; + me->compat_names = off = di_checkmem(st, off, size); + me->compat_length = (int)size; + bcopy(node->devi_compat_names, di_mem_addr(st, off), size); + off += size; } if (node->devi_addr) { - off = di_checkmem(st, off, strlen(node->devi_addr) + 1); - me->address = off; + size = strlen(node->devi_addr) + 1; + me->address = off = di_checkmem(st, off, size); (void) strcpy(di_mem_addr(st, off), node->devi_addr); - off += strlen(node->devi_addr) + 1; + off += size; } if (node->devi_binding_name) { - off = di_checkmem(st, off, strlen(node->devi_binding_name) + 1); - me->bind_name = off; + size = strlen(node->devi_binding_name) + 1; + me->bind_name = off = di_checkmem(st, off, size); (void) strcpy(di_mem_addr(st, off), node->devi_binding_name); - off += strlen(node->devi_binding_name) + 1; + off += size; } me->drv_major = node->devi_major; @@ -1826,17 +1826,17 @@ di_copynode(struct di_stack *dsp, struct di_state *st) } /* - * Grab current per dev_info node lock to - * get minor data and properties. + * LOCKING: We already have an active ndi_devi_enter to gather the + * minor data, and we will take devi_lock to gather properties as + * needed off di_getprop. */ - mutex_enter(&(node->devi_lock)); - if (!(DINFOMINOR & st->command)) { goto path; } + ASSERT(DEVI_BUSY_OWNED(node)); if (node->devi_minor) { /* minor data */ - me->minor_data = DI_ALIGN(off); + me->minor_data = off; off = di_getmdata(node->devi_minor, &me->minor_data, me->self, st); } @@ -1852,7 +1852,7 @@ path: if (MDI_CLIENT(node)) { me->multipath_component = MULTIPATH_COMPONENT_CLIENT; - me->multipath_client = DI_ALIGN(off); + me->multipath_client = off; off = di_getpath_data((dev_info_t *)node, &me->multipath_client, me->self, st, 1); dcmn_err((CE_WARN, "me->multipath_client = %x for node %p " @@ -1863,7 +1863,7 @@ path: if (MDI_PHCI(node)) { me->multipath_component = MULTIPATH_COMPONENT_PHCI; - me->multipath_phci = DI_ALIGN(off); + me->multipath_phci = off; off = di_getpath_data((dev_info_t *)node, &me->multipath_phci, me->self, st, 0); dcmn_err((CE_WARN, "me->multipath_phci = %x for node %p " @@ -1874,25 +1874,25 @@ path: property: if (!(DINFOPROP & st->command)) { - goto unlock; + goto priv_data; } if (node->devi_drv_prop_ptr) { /* driver property list */ - me->drv_prop = DI_ALIGN(off); - off = di_getprop(node->devi_drv_prop_ptr, &me->drv_prop, st, - node, DI_PROP_DRV_LIST); + me->drv_prop = off; + off = di_getprop(DI_PROP_DRV_LIST, &node->devi_drv_prop_ptr, + &me->drv_prop, st, node); } if (node->devi_sys_prop_ptr) { /* system property list */ - me->sys_prop = DI_ALIGN(off); - off = di_getprop(node->devi_sys_prop_ptr, &me->sys_prop, st, - node, DI_PROP_SYS_LIST); + me->sys_prop = off; + off = di_getprop(DI_PROP_SYS_LIST, &node->devi_sys_prop_ptr, + &me->sys_prop, st, node); } if (node->devi_hw_prop_ptr) { /* hardware property list */ - me->hw_prop = DI_ALIGN(off); - off = di_getprop(node->devi_hw_prop_ptr, &me->hw_prop, st, - node, DI_PROP_HW_LIST); + me->hw_prop = off; + off = di_getprop(DI_PROP_HW_LIST, &node->devi_hw_prop_ptr, + &me->hw_prop, st, node); } if (node->devi_global_prop_list == NULL) { @@ -1907,39 +1907,37 @@ property: ASSERT(me->drv_major != -1); if (node->devi_global_prop_list != devnamesp[me->drv_major].dn_global_prop_ptr) { - me->glob_prop = DI_ALIGN(off); - off = di_getprop(node->devi_global_prop_list->prop_list, - &me->glob_prop, st, node, DI_PROP_GLB_LIST); + me->glob_prop = off; + off = di_getprop(DI_PROP_GLB_LIST, + &node->devi_global_prop_list->prop_list, + &me->glob_prop, st, node); } } -unlock: - /* - * release current per dev_info node lock - */ - mutex_exit(&(node->devi_lock)); - priv_data: if (!(DINFOPRIVDATA & st->command)) { goto pm_info; } if (ddi_get_parent_data((dev_info_t *)node) != NULL) { - me->parent_data = DI_ALIGN(off); + me->parent_data = off; off = di_getppdata(node, &me->parent_data, st); } if (ddi_get_driver_private((dev_info_t *)node) != NULL) { - me->driver_data = DI_ALIGN(off); + me->driver_data = off; off = di_getdpdata(node, &me->driver_data, st); } pm_info: /* NOT implemented */ subtree: + /* keep the stack aligned */ + off = DI_ALIGN(off); + if (!(DINFOSUBTREE & st->command)) { POP_STACK(dsp); - return (DI_ALIGN(off)); + return (off); } child: @@ -1948,7 +1946,7 @@ child: * Hold the parent busy while doing so. */ if (node->devi_child) { - me->child = DI_ALIGN(off); + me->child = off; PUSH_STACK(dsp, node->devi_child, &me->child); return (me->child); } @@ -1969,7 +1967,7 @@ sibling: /* * a sibling is found, replace top of stack by its sibling */ - me->sibling = DI_ALIGN(off); + me->sibling = off; PUSH_STACK(dsp, node->devi_sibling, &me->sibling); return (me->sibling); } @@ -1977,7 +1975,7 @@ sibling: /* * DONE with all nodes */ - return (DI_ALIGN(off)); + return (off); } static i_lnode_t * @@ -2015,7 +2013,7 @@ i_lnode_check_free(i_lnode_t *i_lnode) static i_link_t * i_link_alloc(int spec_type) { - i_link_t *i_link; + i_link_t *i_link; i_link = kmem_zalloc(sizeof (i_link_t), KM_SLEEP); i_link->spec_type = spec_type; @@ -2096,7 +2094,7 @@ di_ldi_callback(const ldi_usage_t *ldi_usage, void *arg) /* * if the source or target of this device usage information doesn't - * corrospond to a device node then we don't report it via + * correspond to a device node then we don't report it via * libdevinfo so return. */ if ((ldi_usage->src_dip == NULL) || (ldi_usage->tgt_dip == NULL)) @@ -2125,7 +2123,7 @@ di_ldi_callback(const ldi_usage_t *ldi_usage, void *arg) * operations - so it may already be in the hash. */ i_lnode = i_lnode_alloc(ldi_usage->src_modid); - i_lnode->di_node = (struct di_node *)(intptr_t)di_mem_addr(st, soff); + i_lnode->di_node = DI_NODE(di_mem_addr(st, soff)); i_lnode->devt = ldi_usage->src_devt; res = mod_hash_find(st->lnode_hash, i_lnode, &nodep); @@ -2148,7 +2146,7 @@ di_ldi_callback(const ldi_usage_t *ldi_usage, void *arg) * allocate a tgt i_lnode and add it to the lnode hash */ i_lnode = i_lnode_alloc(ldi_usage->tgt_modid); - i_lnode->di_node = (struct di_node *)(intptr_t)di_mem_addr(st, toff); + i_lnode->di_node = DI_NODE(di_mem_addr(st, toff)); i_lnode->devt = ldi_usage->tgt_devt; res = mod_hash_find(st->lnode_hash, i_lnode, &nodep); @@ -2238,7 +2236,7 @@ i_link_walker(mod_hash_key_t key, mod_hash_val_t *val, void *arg) ASSERT(data->link_count <= data->st->link_count); /* fill in fields for the di_link snapshot */ - me = (struct di_link *)(intptr_t)di_mem_addr(data->st, i_link->self); + me = DI_LINK(di_mem_addr(data->st, i_link->self)); me->self = i_link->self; me->spec_type = i_link->spec_type; @@ -2256,16 +2254,14 @@ i_link_walker(mod_hash_key_t key, mod_hash_val_t *val, void *arg) * Save this link's offset in the src_lnode snapshot's link_out * field */ - melnode = (struct di_lnode *) - (intptr_t)di_mem_addr(data->st, me->src_lnode); + melnode = DI_LNODE(di_mem_addr(data->st, me->src_lnode)); me->src_link_next = melnode->link_out; melnode->link_out = me->self; /* * Put this link on the tgt_lnode's link_in field */ - melnode = (struct di_lnode *) - (intptr_t)di_mem_addr(data->st, me->tgt_lnode); + melnode = DI_LNODE(di_mem_addr(data->st, me->tgt_lnode)); me->tgt_link_next = melnode->link_in; melnode->link_in = me->self; @@ -2311,7 +2307,7 @@ i_lnode_walker(mod_hash_key_t key, mod_hash_val_t *val, void *arg) ASSERT(data->lnode_count <= data->st->lnode_count); /* fill in fields for the di_lnode snapshot */ - me = (struct di_lnode *)(intptr_t)di_mem_addr(data->st, i_lnode->self); + me = DI_LNODE(di_mem_addr(data->st, i_lnode->self)); me->self = i_lnode->self; if (i_lnode->devt == DDI_DEV_T_NONE) { @@ -2354,8 +2350,8 @@ i_lnode_walker(mod_hash_key_t key, mod_hash_val_t *val, void *arg) static di_off_t di_getlink_data(di_off_t off, struct di_state *st) { - struct i_layer_data data = {0}; - size_t size; + struct i_layer_data data = {0}; + size_t size; dcmn_err2((CE_CONT, "di_copylyr: off = %x\n", off)); @@ -2380,12 +2376,12 @@ di_getlink_data(di_off_t off, struct di_state *st) /* get a pointer to snapshot memory for all the di_lnodes */ size = sizeof (struct di_lnode) * st->lnode_count; data.lnode_off = off = di_checkmem(st, off, size); - off += DI_ALIGN(size); + off += size; /* get a pointer to snapshot memory for all the di_links */ size = sizeof (struct di_link) * st->link_count; data.link_off = off = di_checkmem(st, off, size); - off += DI_ALIGN(size); + off += size; data.lnode_count = data.link_count = 0; data.st = st; @@ -2415,14 +2411,16 @@ out: /* * Copy all minor data nodes attached to a devinfo node into the snapshot. - * It is called from di_copynode with devi_lock held. + * It is called from di_copynode with active ndi_devi_enter to protect + * the list of minor nodes. */ static di_off_t di_getmdata(struct ddi_minor_data *mnode, di_off_t *off_p, di_off_t node, struct di_state *st) { - di_off_t off; - struct di_minor *me; + di_off_t off; + struct di_minor *me; + size_t size; dcmn_err2((CE_CONT, "di_getmdata:\n")); @@ -2433,13 +2431,13 @@ di_getmdata(struct ddi_minor_data *mnode, di_off_t *off_p, di_off_t node, *off_p = off; do { - me = (struct di_minor *)(intptr_t)di_mem_addr(st, off); + me = DI_MINOR(di_mem_addr(st, off)); me->self = off; me->type = mnode->type; me->node = node; me->user_private_data = NULL; - off += DI_ALIGN(sizeof (struct di_minor)); + off += sizeof (struct di_minor); /* * Split dev_t to major/minor, so it works for @@ -2450,20 +2448,18 @@ di_getmdata(struct ddi_minor_data *mnode, di_off_t *off_p, di_off_t node, me->spec_type = mnode->ddm_spec_type; if (mnode->ddm_name) { - off = di_checkmem(st, off, - strlen(mnode->ddm_name) + 1); - me->name = off; + size = strlen(mnode->ddm_name) + 1; + me->name = off = di_checkmem(st, off, size); (void) strcpy(di_mem_addr(st, off), mnode->ddm_name); - off += DI_ALIGN(strlen(mnode->ddm_name) + 1); + off += size; } if (mnode->ddm_node_type) { - off = di_checkmem(st, off, - strlen(mnode->ddm_node_type) + 1); - me->node_type = off; + size = strlen(mnode->ddm_node_type) + 1; + me->node_type = off = di_checkmem(st, off, size); (void) strcpy(di_mem_addr(st, off), mnode->ddm_node_type); - off += DI_ALIGN(strlen(mnode->ddm_node_type) + 1); + off += size; } off = di_checkmem(st, off, sizeof (struct di_minor)); @@ -2485,9 +2481,9 @@ di_getmdata(struct ddi_minor_data *mnode, di_off_t *off_p, di_off_t node, static void di_register_dip(struct di_state *st, dev_info_t *dip, di_off_t off) { - struct dev_info *node = DEVI(dip); - struct di_key *key = kmem_zalloc(sizeof (*key), KM_SLEEP); - struct di_dkey *dk; + struct dev_info *node = DEVI(dip); + struct di_key *key = kmem_zalloc(sizeof (*key), KM_SLEEP); + struct di_dkey *dk; ASSERT(dip); ASSERT(off > 0); @@ -2639,12 +2635,18 @@ path_state_convert(mdi_pathinfo_state_t st) static di_off_t -di_path_getprop(mdi_pathinfo_t *pip, di_off_t off, di_off_t *off_p, +di_path_getprop(mdi_pathinfo_t *pip, di_off_t *off_p, struct di_state *st) { - nvpair_t *prop = NULL; - struct di_path_prop *me; + nvpair_t *prop = NULL; + struct di_path_prop *me; + int off; + size_t size; + char *str; + uchar_t *buf; + uint_t nelems; + off = *off_p; if (mdi_pi_get_next_prop(pip, NULL) == NULL) { *off_p = 0; return (off); @@ -2654,19 +2656,17 @@ di_path_getprop(mdi_pathinfo_t *pip, di_off_t off, di_off_t *off_p, *off_p = off; while (prop = mdi_pi_get_next_prop(pip, prop)) { - int delta = 0; - - me = (struct di_path_prop *)(intptr_t)di_mem_addr(st, off); + me = DI_PATHPROP(di_mem_addr(st, off)); me->self = off; off += sizeof (struct di_path_prop); /* * property name */ - off = di_checkmem(st, off, strlen(nvpair_name(prop)) + 1); - me->prop_name = off; + size = strlen(nvpair_name(prop)) + 1; + me->prop_name = off = di_checkmem(st, off, size); (void) strcpy(di_mem_addr(st, off), nvpair_name(prop)); - off += strlen(nvpair_name(prop)) + 1; + off += size; switch (nvpair_type(prop)) { case DATA_TYPE_BYTE: @@ -2674,32 +2674,30 @@ di_path_getprop(mdi_pathinfo_t *pip, di_off_t off, di_off_t *off_p, case DATA_TYPE_UINT16: case DATA_TYPE_INT32: case DATA_TYPE_UINT32: - delta = sizeof (int32_t); me->prop_type = DDI_PROP_TYPE_INT; - off = di_checkmem(st, off, delta); + size = sizeof (int32_t); + off = di_checkmem(st, off, size); (void) nvpair_value_int32(prop, - (int32_t *)(intptr_t)di_mem_addr(st, off)); + (int32_t *)di_mem_addr(st, off)); break; case DATA_TYPE_INT64: case DATA_TYPE_UINT64: - delta = sizeof (int64_t); me->prop_type = DDI_PROP_TYPE_INT64; - off = di_checkmem(st, off, delta); + size = sizeof (int64_t); + off = di_checkmem(st, off, size); (void) nvpair_value_int64(prop, - (int64_t *)(intptr_t)di_mem_addr(st, off)); + (int64_t *)di_mem_addr(st, off)); break; case DATA_TYPE_STRING: - { - char *str; - (void) nvpair_value_string(prop, &str); - delta = strlen(str) + 1; me->prop_type = DDI_PROP_TYPE_STRING; - off = di_checkmem(st, off, delta); + (void) nvpair_value_string(prop, &str); + size = strlen(str) + 1; + off = di_checkmem(st, off, size); (void) strcpy(di_mem_addr(st, off), str); break; - } + case DATA_TYPE_BYTE_ARRAY: case DATA_TYPE_INT16_ARRAY: case DATA_TYPE_UINT16_ARRAY: @@ -2707,30 +2705,26 @@ di_path_getprop(mdi_pathinfo_t *pip, di_off_t off, di_off_t *off_p, case DATA_TYPE_UINT32_ARRAY: case DATA_TYPE_INT64_ARRAY: case DATA_TYPE_UINT64_ARRAY: - { - uchar_t *buf; - uint_t nelems; - (void) nvpair_value_byte_array(prop, &buf, &nelems); - delta = nelems; me->prop_type = DDI_PROP_TYPE_BYTE; + (void) nvpair_value_byte_array(prop, &buf, &nelems); + size = nelems; if (nelems != 0) { - off = di_checkmem(st, off, delta); - bcopy(buf, di_mem_addr(st, off), nelems); + off = di_checkmem(st, off, size); + bcopy(buf, di_mem_addr(st, off), size); } break; - } default: /* Unknown or unhandled type; skip it */ - delta = 0; + size = 0; break; } - if (delta > 0) { + if (size > 0) { me->prop_data = off; } - me->prop_len = delta; - off += delta; + me->prop_len = (int)size; + off += size; off = di_checkmem(st, off, sizeof (struct di_path_prop)); me->prop_next = off; @@ -2763,18 +2757,19 @@ di_path_one_endpoint(struct di_path *me, di_off_t noff, di_off_t **off_pp, } /* - * poff_p: pointer to the linkage field. This links pips along the client|phci + * off_p: pointer to the linkage field. This links pips along the client|phci * linkage list. * noff : Offset for the endpoint dip snapshot. */ static di_off_t -di_getpath_data(dev_info_t *dip, di_off_t *poff_p, di_off_t noff, +di_getpath_data(dev_info_t *dip, di_off_t *off_p, di_off_t noff, struct di_state *st, int get_client) { - di_off_t off; - mdi_pathinfo_t *pip; - struct di_path *me; - mdi_pathinfo_t *(*next_pip)(dev_info_t *, mdi_pathinfo_t *); + di_off_t off; + mdi_pathinfo_t *pip; + struct di_path *me; + mdi_pathinfo_t *(*next_pip)(dev_info_t *, mdi_pathinfo_t *); + size_t size; dcmn_err2((CE_WARN, "di_getpath_data: client = %d", get_client)); @@ -2789,7 +2784,7 @@ di_getpath_data(dev_info_t *dip, di_off_t *poff_p, di_off_t noff, else next_pip = &mdi_get_next_client_path; - off = *poff_p; + off = *off_p; pip = NULL; while (pip = (*next_pip)(dip, pip)) { @@ -2809,12 +2804,10 @@ di_getpath_data(dev_info_t *dip, di_off_t *poff_p, di_off_t noff, * first snapshotted i.e. when the other endpoint dip * was snapshotted. */ - me = (struct di_path *)(intptr_t) - di_mem_addr(st, stored_offset); - - *poff_p = stored_offset; + me = DI_PATH(di_mem_addr(st, stored_offset)); + *off_p = stored_offset; - di_path_one_endpoint(me, noff, &poff_p, get_client); + di_path_one_endpoint(me, noff, &off_p, get_client); /* * The other endpoint and linkage were set when this @@ -2833,11 +2826,11 @@ di_getpath_data(dev_info_t *dip, di_off_t *poff_p, di_off_t noff, /* * Now that we need to snapshot this pip, check memory */ - off = di_checkmem(st, off, sizeof (struct di_path)); - me = (struct di_path *)(intptr_t)di_mem_addr(st, off); + size = sizeof (struct di_path); + *off_p = off = di_checkmem(st, off, size); + me = DI_PATH(di_mem_addr(st, off)); me->self = off; - *poff_p = off; - off += sizeof (struct di_path); + off += size; me->path_snap_state = DI_PATH_SNAP_NOCLINK | DI_PATH_SNAP_NOPLINK; @@ -2851,7 +2844,7 @@ di_getpath_data(dev_info_t *dip, di_off_t *poff_p, di_off_t noff, me->path_client = me->path_phci = 0; me->path_c_link = me->path_p_link = 0; - di_path_one_endpoint(me, noff, &poff_p, get_client); + di_path_one_endpoint(me, noff, &off_p, get_client); /* * Note the existence of this pathinfo @@ -2866,17 +2859,18 @@ di_getpath_data(dev_info_t *dip, di_off_t *poff_p, di_off_t noff, /* * Get intermediate addressing info. */ - off = di_checkmem(st, off, strlen(mdi_pi_get_addr(pip)) + 1); - me->path_addr = off; + size = strlen(mdi_pi_get_addr(pip)) + 1; + me->path_addr = off = di_checkmem(st, off, size); (void) strcpy(di_mem_addr(st, off), mdi_pi_get_addr(pip)); - off += strlen(mdi_pi_get_addr(pip)) + 1; + off += size; /* * Get path properties if props are to be included in the * snapshot */ if (DINFOPROP & st->command) { - off = di_path_getprop(pip, off, &me->path_prop, st); + me->path_prop = off; + off = di_path_getprop(pip, &me->path_prop, st); } else { me->path_prop = 0; } @@ -2884,234 +2878,285 @@ di_getpath_data(dev_info_t *dip, di_off_t *poff_p, di_off_t noff, mdi_pi_unlock(pip); } - *poff_p = 0; - + *off_p = 0; return (off); } /* - * Copy a list of properties attached to a devinfo node. Called from - * di_copynode with devi_lock held. The major number is passed in case - * we need to call driver's prop_op entry. The value of list indicates - * which list we are copying. Possible values are: - * DI_PROP_DRV_LIST, DI_PROP_SYS_LIST, DI_PROP_GLB_LIST, DI_PROP_HW_LIST + * Return driver prop_op entry point for the specified devinfo node. + * + * To return a non-NULL value: + * - driver must be attached and held: + * If driver is not attached we ignore the driver property list. + * No one should rely on such properties. + * - driver "cb_prop_op != ddi_prop_op": + * If "cb_prop_op == ddi_prop_op", framework does not need to call driver. + * XXX or parent's bus_prop_op != ddi_bus_prop_op */ -static di_off_t -di_getprop(struct ddi_prop *prop, di_off_t *off_p, struct di_state *st, - struct dev_info *dip, int list) +static int +(*di_getprop_prop_op(struct dev_info *dip)) + (dev_t, dev_info_t *, ddi_prop_op_t, int, char *, caddr_t, int *) { - dev_t dev; - int (*prop_op)(); - int off, need_prop_op = 0; - int prop_op_fail = 0; - ddi_prop_t *propp = NULL; - struct di_prop *pp; - struct dev_ops *ops = NULL; - int prop_len; - caddr_t prop_val; - + struct dev_ops *ops; - dcmn_err2((CE_CONT, "di_getprop:\n")); - - ASSERT(st != NULL); - - dcmn_err((CE_CONT, "copy property list at addr %p\n", (void *)prop)); - - /* - * Figure out if we need to call driver's prop_op entry point. - * The conditions are: - * -- driver property list - * -- driver must be attached and held - * -- driver's cb_prop_op != ddi_prop_op - * or parent's bus_prop_op != ddi_bus_prop_op - */ - - if (list != DI_PROP_DRV_LIST) { - goto getprop; - } - - /* - * If driver is not attached or if major is -1, we ignore - * the driver property list. No one should rely on such - * properties. - */ - if (!i_ddi_devi_attached((dev_info_t *)dip)) { - off = *off_p; - *off_p = 0; - return (off); - } + /* If driver is not attached we ignore the driver property list. */ + if ((dip == NULL) || !i_ddi_devi_attached((dev_info_t *)dip)) + return (NULL); /* - * Now we have a driver which is held. We can examine entry points - * and check the condition listed above. + * Some nexus drivers incorrectly set cb_prop_op to nodev, nulldev, + * or even NULL. */ ops = dip->devi_ops; - - /* - * Some nexus drivers incorrectly set cb_prop_op to nodev, - * nulldev or even NULL. - */ if (ops && ops->devo_cb_ops && (ops->devo_cb_ops->cb_prop_op != ddi_prop_op) && (ops->devo_cb_ops->cb_prop_op != nodev) && (ops->devo_cb_ops->cb_prop_op != nulldev) && - (ops->devo_cb_ops->cb_prop_op != NULL)) { - need_prop_op = 1; - } + (ops->devo_cb_ops->cb_prop_op != NULL)) + return (ops->devo_cb_ops->cb_prop_op); + return (NULL); +} -getprop: - /* - * check memory availability - */ - off = di_checkmem(st, *off_p, sizeof (struct di_prop)); - *off_p = off; - /* - * Now copy properties - */ - do { - pp = (struct di_prop *)(intptr_t)di_mem_addr(st, off); - pp->self = off; - /* - * Split dev_t to major/minor, so it works for - * both ILP32 and LP64 model - */ - pp->dev_major = getmajor(prop->prop_dev); - pp->dev_minor = getminor(prop->prop_dev); - pp->prop_flags = prop->prop_flags; - pp->prop_list = list; +static di_off_t +di_getprop_add(int list, int dyn, struct di_state *st, struct dev_info *dip, + int (*prop_op)(), + char *name, dev_t devt, int aflags, int alen, caddr_t aval, + di_off_t off, di_off_t **off_pp) +{ + int need_free = 0; + dev_t pdevt; + int pflags; + int rv; + caddr_t val; + int len; + size_t size; + struct di_prop *pp; + + /* If we have prop_op function, ask driver for latest value */ + if (prop_op) { + ASSERT(dip); + + /* Must search DDI_DEV_T_NONE with DDI_DEV_T_ANY */ + pdevt = (devt == DDI_DEV_T_NONE) ? DDI_DEV_T_ANY : devt; /* - * property name + * We have type information in flags, but are invoking an + * old non-typed prop_op(9E) interface. Since not all types are + * part of DDI_PROP_TYPE_ANY (example is DDI_PROP_TYPE_INT64), + * we set DDI_PROP_CONSUMER_TYPED - causing the framework to + * expand type bits beyond DDI_PROP_TYPE_ANY. This allows us + * to use the legacy prop_op(9E) interface to obtain updates + * non-DDI_PROP_TYPE_ANY dynamic properties. */ - off += sizeof (struct di_prop); - if (prop->prop_name) { - off = di_checkmem(st, off, strlen(prop->prop_name) - + 1); - pp->prop_name = off; - (void) strcpy(di_mem_addr(st, off), prop->prop_name); - off += strlen(prop->prop_name) + 1; - } + pflags = aflags & ~DDI_PROP_TYPE_MASK; + pflags |= DDI_PROP_DONTPASS | DDI_PROP_NOTPROM | + DDI_PROP_CONSUMER_TYPED; + rv = (*prop_op)(pdevt, (dev_info_t)dip, PROP_LEN_AND_VAL_ALLOC, + pflags, name, &val, &len); + + if (rv == DDI_PROP_SUCCESS) { + need_free = 1; /* dynamic prop obtained */ + } else if (dyn) { + /* + * A dynamic property must succeed prop_op(9E) to show + * up in the snapshot - that is the only source of its + * value. + */ + return (off); /* dynamic prop not supported */ + } else { + /* + * In case calling the driver caused an update off + * prop_op(9E) of a non-dynamic property (code leading + * to ddi_prop_change), we defer picking up val and + * len informatiojn until after prop_op(9E) to ensure + * that we snapshot the latest value. + */ + val = aval; + len = alen; - /* - * Set prop_len here. This may change later - * if cb_prop_op returns a different length. - */ - pp->prop_len = prop->prop_len; - if (!need_prop_op) { - if (prop->prop_val == NULL) { - dcmn_err((CE_WARN, - "devinfo: property fault at %p", - (void *)prop)); - pp->prop_data = -1; - } else if (prop->prop_len != 0) { - off = di_checkmem(st, off, prop->prop_len); - pp->prop_data = off; - bcopy(prop->prop_val, di_mem_addr(st, off), - prop->prop_len); - off += DI_ALIGN(pp->prop_len); - } } + } else { + val = aval; + len = alen; + } - off = di_checkmem(st, off, sizeof (struct di_prop)); - pp->next = off; - prop = prop->prop_next; - } while (prop); + dcmn_err((CE_CONT, "di_getprop_add: list %d %s len %d val %p\n", + list, name ? name : "NULL", len, (void *)val)); - pp->next = 0; + size = sizeof (struct di_prop); + **off_pp = off = di_checkmem(st, off, size); + pp = DI_PROP(di_mem_addr(st, off)); + pp->self = off; + off += size; - if (!need_prop_op) { - dcmn_err((CE_CONT, "finished property " - "list at offset 0x%x\n", off)); - return (off); + pp->dev_major = getmajor(devt); + pp->dev_minor = getminor(devt); + pp->prop_flags = aflags; + pp->prop_list = list; + + /* property name */ + if (name) { + size = strlen(name) + 1; + pp->prop_name = off = di_checkmem(st, off, size); + (void) strcpy(di_mem_addr(st, off), name); + off += size; + } else { + pp->prop_name = -1; } - /* - * If there is a need to call driver's prop_op entry, - * we must release driver's devi_lock, because the - * cb_prop_op entry point will grab it. - * - * The snapshot memory has already been allocated above, - * which means the length of an active property should - * remain fixed for this implementation to work. - */ + pp->prop_len = len; + if (val == NULL) { + pp->prop_data = -1; + } else if (len != 0) { + size = len; + pp->prop_data = off = di_checkmem(st, off, size); + bcopy(val, di_mem_addr(st, off), size); + off += size; + } + pp->next = 0; /* assume tail for now */ + *off_pp = &pp->next; /* return pointer to our next */ - prop_op = ops->devo_cb_ops->cb_prop_op; - pp = (struct di_prop *)(intptr_t)di_mem_addr(st, *off_p); + if (need_free) /* free PROP_LEN_AND_VAL_ALLOC alloc */ + kmem_free(val, len); + return (off); +} - mutex_exit(&dip->devi_lock); - do { - int err; - struct di_prop *tmp; +/* + * Copy a list of properties attached to a devinfo node. Called from + * di_copynode with active ndi_devi_enter. The major number is passed in case + * we need to call driver's prop_op entry. The value of list indicates + * which list we are copying. Possible values are: + * DI_PROP_DRV_LIST, DI_PROP_SYS_LIST, DI_PROP_GLB_LIST, DI_PROP_HW_LIST + */ +static di_off_t +di_getprop(int list, struct ddi_prop **pprop, di_off_t *off_p, + struct di_state *st, struct dev_info *dip) +{ + struct ddi_prop *prop; + int (*prop_op)(); + int off; + struct ddi_minor_data *mn; + i_ddi_prop_dyn_t *dp; + struct plist { + struct plist *pl_next; + char *pl_name; + int pl_flags; + dev_t pl_dev; + int pl_len; + caddr_t pl_val; + } *pl, *pl0, **plp; - if (pp->next) { - tmp = (struct di_prop *) - (intptr_t)di_mem_addr(st, pp->next); + ASSERT(st != NULL); + + off = *off_p; + *off_p = 0; + dcmn_err((CE_CONT, "di_getprop: copy property list %d at addr %p\n", + list, (void *)*pprop)); + + /* get pointer to driver's prop_op(9E) implementation if DRV_LIST */ + prop_op = (list == DI_PROP_DRV_LIST) ? di_getprop_prop_op(dip) : NULL; + + /* + * Form private list of properties, holding devi_lock for properties + * than hang off the dip. + */ + if (dip) + mutex_enter(&(dip->devi_lock)); + for (plp = &pl0, prop = *pprop; + prop; plp = &pl->pl_next, prop = prop->prop_next) { + pl = kmem_alloc(sizeof (*pl), KM_SLEEP); + *plp = pl; + pl->pl_next = NULL; + if (prop->prop_name) + pl->pl_name = i_ddi_strdup(prop->prop_name, KM_SLEEP); + else + pl->pl_name = NULL; + pl->pl_flags = prop->prop_flags; + pl->pl_dev = prop->prop_dev; + if (prop->prop_len) { + pl->pl_len = prop->prop_len; + pl->pl_val = kmem_alloc(pl->pl_len, KM_SLEEP); + bcopy(prop->prop_val, pl->pl_val, pl->pl_len); } else { - tmp = NULL; + pl->pl_len = 0; + pl->pl_val = NULL; } + } + if (dip) + mutex_exit(&(dip->devi_lock)); - /* - * call into driver's prop_op entry point - * - * Must search DDI_DEV_T_NONE with DDI_DEV_T_ANY - */ - dev = makedevice(pp->dev_major, pp->dev_minor); - if (dev == DDI_DEV_T_NONE) - dev = DDI_DEV_T_ANY; - - dcmn_err((CE_CONT, "call prop_op" - "(%lx, %p, PROP_LEN_AND_VAL_BUF, " - "DDI_PROP_DONTPASS, \"%s\", %p, &%d)\n", - dev, - (void *)dip, - (char *)di_mem_addr(st, pp->prop_name), - (void *)di_mem_addr(st, pp->prop_data), - pp->prop_len)); - - if ((err = (*prop_op)(dev, (dev_info_t)dip, - PROP_LEN_AND_VAL_ALLOC, DDI_PROP_DONTPASS, - (char *)di_mem_addr(st, pp->prop_name), - &prop_val, &prop_len)) != DDI_PROP_SUCCESS) { - if ((propp = i_ddi_prop_search(dev, - (char *)di_mem_addr(st, pp->prop_name), - (uint_t)pp->prop_flags, - &(DEVI(dip)->devi_drv_prop_ptr))) != NULL) { - pp->prop_len = propp->prop_len; - if (pp->prop_len != 0) { - off = di_checkmem(st, off, - pp->prop_len); - pp->prop_data = off; - bcopy(propp->prop_val, di_mem_addr(st, - pp->prop_data), propp->prop_len); - off += DI_ALIGN(pp->prop_len); - } - } else { - prop_op_fail = 1; + /* + * Now that we have dropped devi_lock, perform a second-pass to + * add properties to the snapshot. We do this as a second pass + * because we may need to call prop_op(9E) and we can't hold + * devi_lock across that call. + */ + for (pl = pl0; pl; pl = pl0) { + pl0 = pl->pl_next; + off = di_getprop_add(list, 0, st, dip, prop_op, pl->pl_name, + pl->pl_dev, pl->pl_flags, pl->pl_len, pl->pl_val, + off, &off_p); + if (pl->pl_val) + kmem_free(pl->pl_val, pl->pl_len); + if (pl->pl_name) + kmem_free(pl->pl_name, strlen(pl->pl_name) + 1); + kmem_free(pl, sizeof (*pl)); + } + + /* + * If there is no prop_op or dynamic property support has been + * disabled, we are done. + */ + if ((prop_op == NULL) || (di_prop_dyn == 0)) { + *off_p = 0; + return (off); + } + + /* Add dynamic driver properties to snapshot */ + for (dp = i_ddi_prop_dyn_driver_get((dev_info_t *)dip); + dp && dp->dp_name; dp++) { + if (dp->dp_spec_type) { + /* if spec_type, property of matching minor */ + ASSERT(DEVI_BUSY_OWNED(dip)); + for (mn = dip->devi_minor; mn; mn = mn->next) { + if (mn->ddm_spec_type != dp->dp_spec_type) + continue; + off = di_getprop_add(list, 1, st, dip, prop_op, + dp->dp_name, mn->ddm_dev, dp->dp_type, + 0, NULL, off, &off_p); } - } else if (prop_len != 0) { - pp->prop_len = prop_len; - off = di_checkmem(st, off, prop_len); - pp->prop_data = off; - bcopy(prop_val, di_mem_addr(st, off), prop_len); - off += DI_ALIGN(prop_len); - kmem_free(prop_val, prop_len); + } else { + /* property of devinfo node */ + off = di_getprop_add(list, 1, st, dip, prop_op, + dp->dp_name, DDI_DEV_T_NONE, dp->dp_type, + 0, NULL, off, &off_p); } + } - if (prop_op_fail) { - pp->prop_data = -1; - dcmn_err((CE_WARN, "devinfo: prop_op failure " - "for \"%s\" err %d", - di_mem_addr(st, pp->prop_name), err)); + /* Add dynamic parent properties to snapshot */ + for (dp = i_ddi_prop_dyn_parent_get((dev_info_t *)dip); + dp && dp->dp_name; dp++) { + if (dp->dp_spec_type) { + /* if spec_type, property of matching minor */ + ASSERT(DEVI_BUSY_OWNED(dip)); + for (mn = dip->devi_minor; mn; mn = mn->next) { + if (mn->ddm_spec_type != dp->dp_spec_type) + continue; + off = di_getprop_add(list, 1, st, dip, prop_op, + dp->dp_name, mn->ddm_dev, dp->dp_type, + 0, NULL, off, &off_p); + } + } else { + /* property of devinfo node */ + off = di_getprop_add(list, 1, st, dip, prop_op, + dp->dp_name, DDI_DEV_T_NONE, dp->dp_type, + 0, NULL, off, &off_p); } + } - pp = tmp; - - } while (pp); - - mutex_enter(&dip->devi_lock); - dcmn_err((CE_CONT, "finished property list at offset 0x%x\n", off)); + *off_p = 0; return (off); } @@ -3126,11 +3171,11 @@ getprop: struct di_priv_format * di_match_drv_name(struct dev_info *node, struct di_state *st, int match) { - int i, count, len; - char *drv_name; - major_t major; - struct di_all *all; - struct di_priv_format *form; + int i, count, len; + char *drv_name; + major_t major; + struct di_all *all; + struct di_priv_format *form; dcmn_err2((CE_CONT, "di_match_drv_name: node = %s, match = %x\n", node->devi_node_name, match)); @@ -3157,16 +3202,13 @@ di_match_drv_name(struct dev_info *node, struct di_state *st, int match) } /* Now get the di_priv_format array */ - all = (struct di_all *)(intptr_t)di_mem_addr(st, 0); - + all = DI_ALL_PTR(st); if (match == DI_MATCH_PARENT) { count = all->n_ppdata; - form = (struct di_priv_format *) - (intptr_t)(di_mem_addr(st, 0) + all->ppdata_format); + form = DI_PRIV_FORMAT(di_mem_addr(st, all->ppdata_format)); } else { count = all->n_dpdata; - form = (struct di_priv_format *) - (intptr_t)((caddr_t)all + all->dpdata_format); + form = DI_PRIV_FORMAT(di_mem_addr(st, all->dpdata_format)); } len = strlen(drv_name); @@ -3202,13 +3244,12 @@ static di_off_t di_getprvdata(struct di_priv_format *pdp, struct dev_info *node, void *data, di_off_t *off_p, struct di_state *st) { - caddr_t pa; - void *ptr; - int i, size, repeat; - di_off_t off, off0, *tmp; - char *path; - - label_t ljb; + caddr_t pa; + void *ptr; + int i, size, repeat; + di_off_t off, off0, *tmp; + char *path; + label_t ljb; dcmn_err2((CE_CONT, "di_getprvdata:\n")); @@ -3217,6 +3258,7 @@ di_getprvdata(struct di_priv_format *pdp, struct dev_info *node, * limited to DI_MAX_PRIVDATA. */ off = di_checkmem(st, *off_p, DI_MAX_PRIVDATA); + *off_p = off; if ((pdp->bytes == 0) || pdp->bytes > DI_MAX_PRIVDATA) { goto failure; @@ -3225,7 +3267,7 @@ di_getprvdata(struct di_priv_format *pdp, struct dev_info *node, if (!on_fault(&ljb)) { /* copy the struct */ bcopy(data, di_mem_addr(st, off), pdp->bytes); - off0 = DI_ALIGN(pdp->bytes); + off0 = DI_ALIGN(pdp->bytes); /* XXX remove DI_ALIGN */ /* dereferencing pointers */ for (i = 0; i < MAX_PTR_IN_PRV; i++) { @@ -3238,8 +3280,7 @@ di_getprvdata(struct di_priv_format *pdp, struct dev_info *node, * first, get the pointer content */ if ((pdp->ptr[i].offset < 0) || - (pdp->ptr[i].offset > - pdp->bytes - sizeof (char *))) + (pdp->ptr[i].offset > pdp->bytes - sizeof (char *))) goto failure; /* wrong offset */ pa = di_mem_addr(st, off + pdp->ptr[i].offset); @@ -3295,7 +3336,7 @@ di_getprvdata(struct di_priv_format *pdp, struct dev_info *node, */ *tmp = off0; bcopy(ptr, di_mem_addr(st, off + off0), size); - off0 += DI_ALIGN(size); + off0 += DI_ALIGN(size); /* XXX remove DI_ALIGN */ } } else { goto failure; @@ -3306,8 +3347,6 @@ success: * success if reached here */ no_fault(); - *off_p = off; - return (off + off0); /*NOTREACHED*/ @@ -3331,8 +3370,8 @@ failure: static di_off_t di_getppdata(struct dev_info *node, di_off_t *off_p, struct di_state *st) { - int off; - struct di_priv_format *ppdp; + int off; + struct di_priv_format *ppdp; dcmn_err2((CE_CONT, "di_getppdata:\n")); @@ -3353,8 +3392,8 @@ di_getppdata(struct dev_info *node, di_off_t *off_p, struct di_state *st) static di_off_t di_getdpdata(struct dev_info *node, di_off_t *off_p, struct di_state *st) { - int off; - struct di_priv_format *dpdp; + int off; + struct di_priv_format *dpdp; dcmn_err2((CE_CONT, "di_getdpdata:")); @@ -3382,7 +3421,7 @@ di_getdpdata(struct dev_info *node, di_off_t *off_p, struct di_state *st) static int di_setstate(struct di_state *st, int new_state) { - int ret = 0; + int ret = 0; mutex_enter(&di_lock); switch (new_state) { @@ -3495,11 +3534,6 @@ chunk_write(struct vnode *vp, offset_t off, caddr_t buf, size_t len) return (error); } -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) { @@ -3616,8 +3650,9 @@ di_cache_write(struct di_cache *cache) buf += chunk; map_size -= chunk; - /* Give pageout a chance to run */ - delay(1); + /* If low on memory, give pageout a chance to run */ + if (freemem < desfree) + delay(1); } /* @@ -3877,14 +3912,12 @@ di_cache_lookup(struct di_state *st) rval = 0; if (di_cache2mem(&di_cache, st) > 0) { - - ASSERT(DI_ALL_PTR(st)); - /* * map_size is size of valid data in the * cached snapshot and may be less than * size of the cache. */ + ASSERT(DI_ALL_PTR(st)); rval = DI_ALL_PTR(st)->map_size; ASSERT(rval >= sizeof (struct di_all)); @@ -3922,9 +3955,9 @@ di_cache_lookup(struct di_state *st) static int di_cache_update(struct di_state *st) { - int rval; - uint32_t crc; - struct di_all *all; + int rval; + uint32_t crc; + struct di_all *all; ASSERT(DI_CACHE_LOCKED(di_cache)); ASSERT(snapshot_is_cacheable(st)); @@ -3950,7 +3983,6 @@ di_cache_update(struct di_state *st) } DI_ALL_PTR(st)->map_size = rval; - if (di_mem2cache(st, &di_cache) == 0) { CACHE_DEBUG((DI_ERR, "can't update cache: copy failed")); return (0); 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 6f04d89f91..94a59cd5c1 100644 --- a/usr/src/uts/common/io/scsi/impl/scsi_hba.c +++ b/usr/src/uts/common/io/scsi/impl/scsi_hba.c @@ -474,7 +474,7 @@ scsi_hba_attach_setup( if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN, 0, prop_name, NULL, &len) == DDI_PROP_NOT_FOUND) { value = scsi_reset_delay; - if (ddi_prop_update_int(DDI_MAJOR_T_UNKNOWN, dip, + if (ddi_prop_update_int(DDI_DEV_T_NONE, dip, prop_name, value) != DDI_PROP_SUCCESS) { cmn_err(CE_CONT, errmsg, prop_name, ddi_driver_name(dip), ddi_get_instance(dip)); @@ -486,7 +486,7 @@ scsi_hba_attach_setup( if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN, 0, prop_name, NULL, &len) == DDI_PROP_NOT_FOUND) { value = scsi_tag_age_limit; - if (ddi_prop_update_int(DDI_MAJOR_T_UNKNOWN, dip, + if (ddi_prop_update_int(DDI_DEV_T_NONE, dip, prop_name, value) != DDI_PROP_SUCCESS) { cmn_err(CE_CONT, errmsg, prop_name, ddi_driver_name(dip), ddi_get_instance(dip)); @@ -498,7 +498,7 @@ scsi_hba_attach_setup( if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN, 0, prop_name, NULL, &len) == DDI_PROP_NOT_FOUND) { value = scsi_watchdog_tick; - if (ddi_prop_update_int(DDI_MAJOR_T_UNKNOWN, dip, + if (ddi_prop_update_int(DDI_DEV_T_NONE, dip, prop_name, value) != DDI_PROP_SUCCESS) { cmn_err(CE_CONT, errmsg, prop_name, ddi_driver_name(dip), ddi_get_instance(dip)); @@ -510,7 +510,7 @@ scsi_hba_attach_setup( if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN, 0, prop_name, NULL, &len) == DDI_PROP_NOT_FOUND) { value = scsi_options; - if (ddi_prop_update_int(DDI_MAJOR_T_UNKNOWN, dip, + if (ddi_prop_update_int(DDI_DEV_T_NONE, dip, prop_name, value) != DDI_PROP_SUCCESS) { cmn_err(CE_CONT, errmsg, prop_name, ddi_driver_name(dip), ddi_get_instance(dip)); @@ -522,7 +522,7 @@ scsi_hba_attach_setup( if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN, 0, prop_name, NULL, &len) == DDI_PROP_NOT_FOUND) { value = scsi_selection_timeout; - if (ddi_prop_update_int(DDI_MAJOR_T_UNKNOWN, dip, + if (ddi_prop_update_int(DDI_DEV_T_NONE, dip, prop_name, value) != DDI_PROP_SUCCESS) { cmn_err(CE_CONT, errmsg, prop_name, ddi_driver_name(dip), ddi_get_instance(dip)); @@ -537,7 +537,7 @@ scsi_hba_attach_setup( 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, + if (ddi_prop_update_string(DDI_DEV_T_NONE, dip, prop_name, (char *)prop_value) != DDI_PROP_SUCCESS) { cmn_err(CE_CONT, errmsg, prop_name, diff --git a/usr/src/uts/common/io/scsi/targets/sd.c b/usr/src/uts/common/io/scsi/targets/sd.c index 9c59ed08a0..f989acf673 100644 --- a/usr/src/uts/common/io/scsi/targets/sd.c +++ b/usr/src/uts/common/io/scsi/targets/sd.c @@ -2174,7 +2174,7 @@ _init(void) /* * Creating taskq before mod_install ensures that all callers (threads) - * that enter the module after a successfull mod_install encounter + * that enter the module after a successful mod_install encounter * a valid taskq. */ sd_taskq_create(); @@ -2601,36 +2601,15 @@ static int sd_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags, char *name, caddr_t valuep, int *lengthp) { - int instance = ddi_get_instance(dip); struct sd_lun *un; - uint64_t nblocks64; - uint_t dblk; - /* - * Our dynamic properties are all device specific and size oriented. - * Requests issued under conditions where size is valid are passed - * to ddi_prop_op_nblocks with the size information, otherwise the - * request is passed to ddi_prop_op. Size depends on valid geometry. - */ - un = ddi_get_soft_state(sd_state, instance); - if ((dev == DDI_DEV_T_ANY) || (un == NULL)) { + if ((un = ddi_get_soft_state(sd_state, ddi_get_instance(dip))) == NULL) return (ddi_prop_op(dev, dip, prop_op, mod_flags, name, valuep, lengthp)); - } else if (!SD_IS_VALID_LABEL(un)) { - return (ddi_prop_op(dev, dip, prop_op, mod_flags, name, - valuep, lengthp)); - } - /* get nblocks value */ - ASSERT(!mutex_owned(SD_MUTEX(un))); - - (void) cmlb_partinfo(un->un_cmlbhandle, SDPART(dev), - (diskaddr_t *)&nblocks64, NULL, NULL, NULL, (void *)SD_PATH_DIRECT); - - /* report size in target size blocks */ - dblk = un->un_tgt_blocksize / un->un_sys_blocksize; - return (ddi_prop_op_nblocks_blksize(dev, dip, prop_op, mod_flags, - name, valuep, lengthp, nblocks64 / dblk, un->un_tgt_blocksize)); + return (cmlb_prop_op(un->un_cmlbhandle, + dev, dip, prop_op, mod_flags, name, valuep, lengthp, + SDPART(dev), (void *)SD_PATH_DIRECT)); } /* @@ -4592,8 +4571,6 @@ sd_get_virtual_geometry(struct sd_lun *un, cmlb_geom_t *lgeom_p, static void sd_update_block_info(struct sd_lun *un, uint32_t lbasize, uint64_t capacity) { - uint_t dblk; - if (lbasize != 0) { un->un_tgt_blocksize = lbasize; un->un_f_tgt_blocksize_is_valid = TRUE; @@ -4603,32 +4580,6 @@ sd_update_block_info(struct sd_lun *un, uint32_t lbasize, uint64_t capacity) un->un_blockcount = capacity; un->un_f_blockcount_is_valid = TRUE; } - - /* - * Update device capacity properties. - * - * 'device-nblocks' number of blocks in target's units - * 'device-blksize' data bearing size of target's block - * - * NOTE: math is complicated by the fact that un_tgt_blocksize may - * not be a power of two for checksumming disks with 520/528 byte - * sectors. - */ - if (un->un_f_tgt_blocksize_is_valid && - un->un_f_blockcount_is_valid && - un->un_sys_blocksize) { - dblk = un->un_tgt_blocksize / un->un_sys_blocksize; - (void) ddi_prop_update_int64(DDI_DEV_T_NONE, SD_DEVINFO(un), - "device-nblocks", un->un_blockcount / dblk); - /* - * To save memory, only define "device-blksize" when its - * value is differnet than the default DEV_BSIZE value. - */ - if ((un->un_sys_blocksize * dblk) != DEV_BSIZE) - (void) ddi_prop_update_int(DDI_DEV_T_NONE, - SD_DEVINFO(un), "device-blksize", - un->un_sys_blocksize * dblk); - } } @@ -4706,11 +4657,11 @@ sd_register_devid(struct sd_lun *un, dev_info_t *devi, int reservation_flag) } /* - * We check the availibility of the World Wide Name (0x83) and Unit + * We check the availability of the World Wide Name (0x83) and Unit * Serial Number (0x80) pages in sd_check_vpd_page_support(), and using * un_vpd_page_mask from them, we decide which way to get the WWN. If - * 0x83 is availible, that is the best choice. Our next choice is - * 0x80. If neither are availible, we munge the devid from the device + * 0x83 is available, that is the best choice. Our next choice is + * 0x80. If neither are available, we munge the devid from the device * vid/pid/serial # for Sun qualified disks, or use the ddi framework * to fabricate a devid for non-Sun qualified disks. */ @@ -5044,7 +4995,7 @@ sd_write_deviceid(struct sd_lun *un) * * Description: This routine sends an inquiry command with the EVPD bit set and * a page code of 0x00 to the device. It is used to determine which - * vital product pages are availible to find the devid. We are + * vital product pages are available to find the devid. We are * looking for pages 0x83 or 0x80. If we return a negative 1, the * device does not support that command. * @@ -5276,7 +5227,7 @@ sd_setup_pm(struct sd_lun *un, dev_info_t *devi) /* * If the Log sense for Page( Start/stop cycle counter page) - * succeeds, then power managment is supported and we can + * succeeds, then power management is supported and we can * enable auto-pm. */ if (rval == 0) { @@ -6041,7 +5992,7 @@ sdpower(dev_info_t *devi, int component, int level) * To effect this behavior, call pm_busy_component to * indicate to the framework this device is busy. * By not adjusting un_pm_count the rest of PM in - * the driver will function normally, and independant + * the driver will function normally, and independent * of this but because the framework is told the device * is busy it won't attempt powering down until it gets * a matching idle. The timeout handler sends this. @@ -6546,7 +6497,7 @@ sd_unit_attach(dev_info_t *devi) * Note: This driver is currently compiled as two binaries, a parallel * scsi version (sd) and a fibre channel version (ssd). All functional * differences are determined at compile time. In the future a single - * binary will be provided and the inteconnect type will be used to + * binary will be provided and the interconnect type will be used to * differentiate between fibre and parallel scsi behaviors. At that time * it will be necessary for all fibre channel HBAs to support this * property. @@ -6808,7 +6759,7 @@ sd_unit_attach(dev_info_t *devi) * configuration file (.conf) for this unit and update the soft state * for the device as needed for the indicated properties. * Note: the property configuration needs to occur here as some of the - * following routines may have dependancies on soft state flags set + * following routines may have dependencies on soft state flags set * as part of the driver property configuration. */ sd_read_unit_properties(un); @@ -7263,7 +7214,7 @@ sd_unit_attach(dev_info_t *devi) * "retry-on-reservation-conflict") (1189689) * * Note: The use of a global here can have unintended consequences. A - * per instance variable is preferrable to match the capabilities of + * per instance variable is preferable to match the capabilities of * different underlying hba's (4402600) */ sd_retry_on_reservation_conflict = ddi_getprop(DDI_DEV_T_ANY, devi, @@ -7337,7 +7288,7 @@ sd_unit_attach(dev_info_t *devi) #if (defined(__fibre)) /* - * Register callbacks for fibre only. You can't do this soley + * Register callbacks for fibre only. You can't do this solely * on the basis of the devid_type because this is hba specific. * We need to query our hba capabilities to find out whether to * register or not. @@ -26058,12 +26009,6 @@ sr_ejected(struct sd_lun *un) stp = (struct sd_errstats *)un->un_errstats->ks_data; stp->sd_capacity.value.ui64 = 0; } - - /* remove "capacity-of-device" properties */ - (void) ddi_prop_remove(DDI_DEV_T_NONE, SD_DEVINFO(un), - "device-nblocks"); - (void) ddi_prop_remove(DDI_DEV_T_NONE, SD_DEVINFO(un), - "device-blksize"); } @@ -28227,7 +28172,7 @@ sd_tg_getinfo(dev_info_t *devi, int cmd, void *arg, void *tg_cookie) case TG_GETPHYGEOM: case TG_GETVIRTGEOM: case TG_GETCAPACITY: - case TG_GETBLOCKSIZE: + case TG_GETBLOCKSIZE: mutex_enter(SD_MUTEX(un)); if ((un->un_f_blockcount_is_valid == TRUE) && diff --git a/usr/src/uts/common/os/devcfg.c b/usr/src/uts/common/os/devcfg.c index 3157b26411..91f5426e5d 100644 --- a/usr/src/uts/common/os/devcfg.c +++ b/usr/src/uts/common/os/devcfg.c @@ -946,7 +946,7 @@ init_node(dev_info_t *dip) /* * Release our initial hold. If ddi_initchild() was - * successfull then it will return with the active hold. + * successful then it will return with the active hold. */ ndi_rele_devi(pdip); goto out; @@ -1784,8 +1784,8 @@ ndi_rele_driver(dev_info_t *dip) } /* - * Single thread entry into devinfo node for modifying its children. - * To verify in ASSERTS use DEVI_BUSY_OWNED macro. + * Single thread entry into devinfo node for modifying its children (devinfo, + * pathinfo, and minor). To verify in ASSERTS use DEVI_BUSY_OWNED macro. */ void ndi_devi_enter(dev_info_t *dip, int *circular) @@ -2588,6 +2588,7 @@ ndi_merge_wildcard_node(dev_info_t *dip) * and copy properties. */ mutex_enter(&DEVI(dip)->devi_lock); + ASSERT(DEVI_BUSY_OWNED(pdip)); for (hwdip = ddi_get_child(pdip); hwdip; hwdip = ddi_get_next_sibling(hwdip)) { /* @@ -3654,15 +3655,16 @@ int resolve_pathname(char *pathname, dev_info_t **dipp, dev_t *devtp, int *spectypep) { - int error; - dev_info_t *parent, *child; - struct pathname pn; - char *component, *config_name; - char *minorname = NULL; - char *prev_minor = NULL; - dev_t devt = NODEV; - int spectype; - struct ddi_minor_data *dmn; + int error; + dev_info_t *parent, *child; + struct pathname pn; + char *component, *config_name; + char *minorname = NULL; + char *prev_minor = NULL; + dev_t devt = NODEV; + int spectype; + struct ddi_minor_data *dmn; + int circ; if (*pathname != '/') return (EINVAL); @@ -3740,8 +3742,11 @@ resolve_pathname(char *pathname, if (devtp || spectypep) { if (minorname == NULL) { - /* search for a default entry */ - mutex_enter(&(DEVI(parent)->devi_lock)); + /* + * Search for a default entry with an active + * ndi_devi_enter to protect the devi_minor list. + */ + ndi_devi_enter(parent, &circ); for (dmn = DEVI(parent)->devi_minor; dmn; dmn = dmn->next) { if (dmn->type == DDM_DEFAULT) { @@ -3768,7 +3773,7 @@ resolve_pathname(char *pathname, spectype = S_IFCHR; } } - mutex_exit(&(DEVI(parent)->devi_lock)); + ndi_devi_exit(parent, circ); } if (devtp) *devtp = devt; @@ -3842,6 +3847,7 @@ i_ddi_prompath_to_devfspath(char *prompath, char *devfspath) char *minor_name = NULL; int spectype; int error; + int circ; error = resolve_pathname(prompath, &dip, &devt, &spectype); if (error) @@ -3853,7 +3859,7 @@ i_ddi_prompath_to_devfspath(char *prompath, char *devfspath) */ (void) ddi_pathname(dip, devfspath); - mutex_enter(&(DEVI(dip)->devi_lock)); + ndi_devi_enter(dip, &circ); minor_name = i_ddi_devtspectype_to_minorname(dip, devt, spectype); if (minor_name) { (void) strcat(devfspath, ":"); @@ -3866,7 +3872,7 @@ i_ddi_prompath_to_devfspath(char *prompath, char *devfspath) (void) snprintf(devfspath, MAXPATHLEN, "%s:%s", CLONE_PATH, ddi_driver_name(dip)); } - mutex_exit(&(DEVI(dip)->devi_lock)); + ndi_devi_exit(dip, circ); /* release hold from resolve_pathname() */ ndi_rele_devi(dip); @@ -6641,14 +6647,16 @@ i_ddi_devs_attached(major_t major) int i_ddi_minor_node_count(dev_info_t *ddip, const char *node_type) { - struct ddi_minor_data *dp; - int count = 0; + int circ; + struct ddi_minor_data *dp; + int count = 0; - mutex_enter(&(DEVI(ddip)->devi_lock)); - for (dp = DEVI(ddip)->devi_minor; dp != NULL; dp = dp->next) + ndi_devi_enter(ddip, &circ); + for (dp = DEVI(ddip)->devi_minor; dp != NULL; dp = dp->next) { if (strcmp(dp->ddm_node_type, node_type) == 0) count++; - mutex_exit(&(DEVI(ddip)->devi_lock)); + } + ndi_devi_exit(ddip, circ); return (count); } diff --git a/usr/src/uts/common/os/devid_cache.c b/usr/src/uts/common/os/devid_cache.c index c451caeb8a..ed6b3a8dad 100644 --- a/usr/src/uts/common/os/devid_cache.c +++ b/usr/src/uts/common/os/devid_cache.c @@ -680,6 +680,7 @@ e_devid_minor_to_devlist( int *devtcntp, dev_t *devtsp) { + int circ; struct ddi_minor_data *dmdp; int minor_all = 0; int ndevts = *devtcntp; @@ -692,9 +693,8 @@ e_devid_minor_to_devlist( (minor_name == DEVID_MINOR_NAME_ALL_BLK)) minor_all = 1; - mutex_enter(&(DEVI(dip)->devi_lock)); - /* Find matching minor names */ + ndi_devi_enter(dip, &circ); for (dmdp = DEVI(dip)->devi_minor; dmdp; dmdp = dmdp->next) { /* Skip non-minors, and non matching minor names */ @@ -714,8 +714,7 @@ e_devid_minor_to_devlist( devtsp[ndevts] = dmdp->ddm_dev; ndevts++; } - - mutex_exit(&(DEVI(dip)->devi_lock)); + ndi_devi_exit(dip, circ); *devtcntp = ndevts; } diff --git a/usr/src/uts/common/os/modctl.c b/usr/src/uts/common/os/modctl.c index 3fd2700460..9303b3fdc1 100644 --- a/usr/src/uts/common/os/modctl.c +++ b/usr/src/uts/common/os/modctl.c @@ -1099,6 +1099,7 @@ modctl_devid2paths(ddi_devid_t udevid, char *uminor_name, uint_t flag, int devid_len; char *minor_name = NULL; dev_info_t *dip = NULL; + int circ; struct ddi_minor_data *dmdp; char *path = NULL; int ulens; @@ -1185,6 +1186,7 @@ modctl_devid2paths(ddi_devid_t udevid, char *uminor_name, uint_t flag, continue; /* loop over all the minor nodes, skipping ones we don't want */ + ndi_devi_enter(dip, &circ); for (dmdp = DEVI(dip)->devi_minor; dmdp; dmdp = dmdp->next) { if ((dmdp->ddm_dev != devlist[i]) || (dmdp->type != DDM_MINOR)) @@ -1227,6 +1229,7 @@ modctl_devid2paths(ddi_devid_t udevid, char *uminor_name, uint_t flag, upaths += len; } } + ndi_devi_exit(dip, circ); ddi_release_devi(dip); dip = NULL; } @@ -1239,8 +1242,10 @@ modctl_devid2paths(ddi_devid_t udevid, char *uminor_name, uint_t flag, } ret = 0; -out: if (dip) +out: if (dip) { + ndi_devi_exit(dip, circ); ddi_release_devi(dip); + } if (path) kmem_free(path, MAXPATHLEN); if (devlist) @@ -4323,12 +4328,13 @@ gmatch(const char *s, const char *p) static int dev_alias_minorperm(dev_info_t *dip, char *minor_name, mperm_t *rmp) { - major_t major; - struct devnames *dnp; - mperm_t *mp; - char *alias = NULL; - dev_info_t *cdevi; - struct ddi_minor_data *dmd; + major_t major; + struct devnames *dnp; + mperm_t *mp; + char *alias = NULL; + dev_info_t *cdevi; + int circ; + struct ddi_minor_data *dmd; major = ddi_name_to_major(minor_name); @@ -4347,14 +4353,14 @@ dev_alias_minorperm(dev_info_t *dip, char *minor_name, mperm_t *rmp) LOCK_DEV_OPS(&dnp->dn_lock); if ((cdevi = dnp->dn_head) != NULL) { - mutex_enter(&DEVI(cdevi)->devi_lock); + ndi_devi_enter(cdevi, &circ); for (dmd = DEVI(cdevi)->devi_minor; dmd; dmd = dmd->next) { if (dmd->type == DDM_ALIAS) { alias = i_ddi_strdup(dmd->ddm_name, KM_SLEEP); break; } } - mutex_exit(&DEVI(cdevi)->devi_lock); + ndi_devi_exit(cdevi, circ); } UNLOCK_DEV_OPS(&dnp->dn_lock); diff --git a/usr/src/uts/common/os/sunddi.c b/usr/src/uts/common/os/sunddi.c index 6996e2c92f..b4397bff62 100644 --- a/usr/src/uts/common/os/sunddi.c +++ b/usr/src/uts/common/os/sunddi.c @@ -1894,6 +1894,21 @@ ddi_prop_op_size_blksize(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, caddr_t buffer; int blkshift; + /* + * This is a kludge to support capture of size(9P) pure dynamic + * properties in snapshots for non-cmlb code (without exposing + * i_ddi_prop_dyn changes). When everyone uses cmlb, this code + * should be removed. + */ + if (i_ddi_prop_dyn_driver_get(dip) == NULL) { + static i_ddi_prop_dyn_t prop_dyn_size[] = { + {"Size", DDI_PROP_TYPE_INT64, S_IFCHR}, + {"Nblocks", DDI_PROP_TYPE_INT64, S_IFBLK}, + {NULL} + }; + i_ddi_prop_dyn_driver_set(dip, prop_dyn_size); + } + /* convert block size to shift value */ ASSERT(BIT_ONLYONESET(blksize)); blkshift = highbit(blksize) - 1; @@ -1924,10 +1939,6 @@ ddi_prop_op_size_blksize(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, if (prop_op == PROP_LEN) return (DDI_PROP_SUCCESS); - /* the length of the property and the request must match */ - if (callers_length != *lengthp) - return (DDI_PROP_INVAL_ARG); - switch (prop_op) { case PROP_LEN_AND_VAL_ALLOC: if ((buffer = kmem_alloc(*lengthp, @@ -1939,6 +1950,10 @@ ddi_prop_op_size_blksize(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, break; case PROP_LEN_AND_VAL_BUF: + /* the length of the property and the request must match */ + if (callers_length != *lengthp) + return (DDI_PROP_INVAL_ARG); + buffer = valuep; /* get callers buf ptr */ break; @@ -3842,8 +3857,8 @@ ddi_prop_create(dev_t dev, dev_info_t *dip, int flag, #endif /* DDI_PROP_DEBUG */ } flag &= ~DDI_PROP_SYSTEM_DEF; - return (ddi_prop_update_common(dev, dip, - (flag | DDI_PROP_STACK_CREATE | DDI_PROP_TYPE_ANY), name, + flag |= DDI_PROP_STACK_CREATE | DDI_PROP_TYPE_ANY; + return (ddi_prop_update_common(dev, dip, flag, name, value, length, ddi_prop_fm_encode_bytes)); } @@ -3853,9 +3868,8 @@ e_ddi_prop_create(dev_t dev, dev_info_t *dip, int flag, { if (!(flag & DDI_PROP_CANSLEEP)) flag |= DDI_PROP_DONTSLEEP; - return (ddi_prop_update_common(dev, dip, - (flag | DDI_PROP_SYSTEM_DEF | DDI_PROP_STACK_CREATE | - DDI_PROP_TYPE_ANY), + flag |= DDI_PROP_SYSTEM_DEF | DDI_PROP_STACK_CREATE | DDI_PROP_TYPE_ANY; + return (ddi_prop_update_common(dev, dip, flag, name, value, length, ddi_prop_fm_encode_bytes)); } @@ -4501,6 +4515,7 @@ ddi_prop_remove_all_common(dev_info_t *dip, int flag) void ddi_prop_remove_all(dev_info_t *dip) { + i_ddi_prop_dyn_driver_set(dip, NULL); ddi_prop_remove_all_common(dip, 0); } @@ -4531,9 +4546,9 @@ ddi_prop_undefine(dev_t dev, dev_info_t *dip, int flag, char *name) { if (!(flag & DDI_PROP_CANSLEEP)) flag |= DDI_PROP_DONTSLEEP; - return (ddi_prop_update_common(dev, dip, - (flag | DDI_PROP_STACK_CREATE | DDI_PROP_UNDEF_IT | - DDI_PROP_TYPE_ANY), name, NULL, 0, ddi_prop_fm_encode_bytes)); + flag |= DDI_PROP_STACK_CREATE | DDI_PROP_UNDEF_IT | DDI_PROP_TYPE_ANY; + return (ddi_prop_update_common(dev, dip, flag, + name, NULL, 0, ddi_prop_fm_encode_bytes)); } int @@ -4541,13 +4556,57 @@ e_ddi_prop_undefine(dev_t dev, dev_info_t *dip, int flag, char *name) { if (!(flag & DDI_PROP_CANSLEEP)) flag |= DDI_PROP_DONTSLEEP; - return (ddi_prop_update_common(dev, dip, - (flag | DDI_PROP_SYSTEM_DEF | DDI_PROP_STACK_CREATE | - DDI_PROP_UNDEF_IT | DDI_PROP_TYPE_ANY), + flag |= DDI_PROP_SYSTEM_DEF | DDI_PROP_STACK_CREATE | + DDI_PROP_UNDEF_IT | DDI_PROP_TYPE_ANY; + return (ddi_prop_update_common(dev, dip, flag, name, NULL, 0, ddi_prop_fm_encode_bytes)); } /* + * Support for gathering dynamic properties in devinfo snapshot. + */ +void +i_ddi_prop_dyn_driver_set(dev_info_t *dip, i_ddi_prop_dyn_t *dp) +{ + DEVI(dip)->devi_prop_dyn_driver = dp; +} + +i_ddi_prop_dyn_t * +i_ddi_prop_dyn_driver_get(dev_info_t *dip) +{ + return (DEVI(dip)->devi_prop_dyn_driver); +} + +void +i_ddi_prop_dyn_parent_set(dev_info_t *dip, i_ddi_prop_dyn_t *dp) +{ + DEVI(dip)->devi_prop_dyn_parent = dp; +} + +i_ddi_prop_dyn_t * +i_ddi_prop_dyn_parent_get(dev_info_t *dip) +{ + return (DEVI(dip)->devi_prop_dyn_parent); +} + +void +i_ddi_prop_dyn_cache_invalidate(dev_info_t *dip, i_ddi_prop_dyn_t *dp) +{ + /* for now we invalidate the entire cached snapshot */ + if (dip && dp) + i_ddi_di_cache_invalidate(KM_SLEEP); +} + +/* ARGSUSED */ +void +ddi_prop_cache_invalidate(dev_t dev, dev_info_t *dip, char *name, int flags) +{ + /* for now we invalidate the entire cached snapshot */ + i_ddi_di_cache_invalidate(KM_SLEEP); +} + + +/* * Code to search hardware layer (PROM), if it exists, on behalf of child. * * if input dip != child_dip, then call is on behalf of child @@ -5639,11 +5698,10 @@ swab(void *src, void *dst, size_t nbytes) static void ddi_append_minor_node(dev_info_t *ddip, struct ddi_minor_data *dmdp) { - struct ddi_minor_data *dp; - - mutex_enter(&(DEVI(ddip)->devi_lock)); - i_devi_enter(ddip, DEVI_S_MD_UPDATE, DEVI_S_MD_UPDATE, 1); + int circ; + struct ddi_minor_data *dp; + ndi_devi_enter(ddip, &circ); if ((dp = DEVI(ddip)->devi_minor) == (struct ddi_minor_data *)NULL) { DEVI(ddip)->devi_minor = dmdp; } else { @@ -5651,9 +5709,7 @@ ddi_append_minor_node(dev_info_t *ddip, struct ddi_minor_data *dmdp) dp = dp->next; dp->next = dmdp; } - - i_devi_exit(ddip, DEVI_S_MD_UPDATE, 1); - mutex_exit(&(DEVI(ddip)->devi_lock)); + ndi_devi_exit(ddip, circ); } /* @@ -6094,12 +6150,11 @@ ddi_create_internal_pathname(dev_info_t *dip, char *name, int spec_type, void ddi_remove_minor_node(dev_info_t *dip, char *name) { - struct ddi_minor_data *dmdp, *dmdp1; - struct ddi_minor_data **dmdp_prev; - - mutex_enter(&(DEVI(dip)->devi_lock)); - i_devi_enter(dip, DEVI_S_MD_UPDATE, DEVI_S_MD_UPDATE, 1); + int circ; + struct ddi_minor_data *dmdp, *dmdp1; + struct ddi_minor_data **dmdp_prev; + ndi_devi_enter(dip, &circ); dmdp_prev = &DEVI(dip)->devi_minor; dmdp = DEVI(dip)->devi_minor; while (dmdp != NULL) { @@ -6134,9 +6189,7 @@ ddi_remove_minor_node(dev_info_t *dip, char *name) } dmdp = dmdp1; } - - i_devi_exit(dip, DEVI_S_MD_UPDATE, 1); - mutex_exit(&(DEVI(dip)->devi_lock)); + ndi_devi_exit(dip, circ); } @@ -6650,6 +6703,7 @@ ddi_pathname(dev_info_t *dip, char *path) int ddi_dev_pathname(dev_t devt, int spec_type, char *path) { + int circ; major_t major = getmajor(devt); int instance; dev_info_t *dip; @@ -6682,14 +6736,14 @@ ddi_dev_pathname(dev_t devt, int spec_type, char *path) goto fail; /* Add minorname to path. */ - mutex_enter(&(DEVI(dip)->devi_lock)); + ndi_devi_enter(dip, &circ); minorname = i_ddi_devtspectype_to_minorname(dip, devt, spec_type); if (minorname) { (void) strcat(path, ":"); (void) strcat(path, minorname); } - mutex_exit(&(DEVI(dip)->devi_lock)); + ndi_devi_exit(dip, circ); ddi_release_devi(dip); if (minorname == NULL) goto fail; @@ -7359,8 +7413,8 @@ i_ddi_devtspectype_to_minorname(dev_info_t *dip, dev_t dev, int spec_type) */ ASSERT((ddi_driver_major(dip) == getmajor(dev)) || (strcmp(ddi_major_to_name(getmajor(dev)), "did") == 0)); - ASSERT(MUTEX_HELD(&(DEVI(dip)->devi_lock))); + ASSERT(DEVI_BUSY_OWNED(dip)); for (dmdp = DEVI(dip)->devi_minor; dmdp; dmdp = dmdp->next) { if (((dmdp->type == DDM_MINOR) || (dmdp->type == DDM_INTERNAL_PATH) || @@ -7383,6 +7437,7 @@ int i_ddi_minorname_to_devtspectype(dev_info_t *dip, char *minor_name, dev_t *devtp, int *spectypep) { + int circ; struct ddi_minor_data *dmdp; /* deal with clone minor nodes */ @@ -7415,9 +7470,7 @@ i_ddi_minorname_to_devtspectype(dev_info_t *dip, char *minor_name, return (DDI_SUCCESS); } - ASSERT(!MUTEX_HELD(&(DEVI(dip)->devi_lock))); - mutex_enter(&(DEVI(dip)->devi_lock)); - + ndi_devi_enter(dip, &circ); for (dmdp = DEVI(dip)->devi_minor; dmdp; dmdp = dmdp->next) { if (((dmdp->type != DDM_MINOR) && (dmdp->type != DDM_INTERNAL_PATH) && @@ -7431,11 +7484,11 @@ i_ddi_minorname_to_devtspectype(dev_info_t *dip, char *minor_name, if (spectypep) *spectypep = dmdp->ddm_spec_type; - mutex_exit(&(DEVI(dip)->devi_lock)); + ndi_devi_exit(dip, circ); return (DDI_SUCCESS); } + ndi_devi_exit(dip, circ); - mutex_exit(&(DEVI(dip)->devi_lock)); return (DDI_FAILURE); } @@ -7792,54 +7845,38 @@ ddi_lyr_get_devid(dev_t dev, ddi_devid_t *ret_devid) int ddi_lyr_get_minor_name(dev_t dev, int spec_type, char **minor_name) { + char *buf; + int circ; dev_info_t *dip; char *nm; - size_t alloc_sz, sz; - - if ((dip = e_ddi_hold_devi_by_dev(dev, 0)) == NULL) - return (DDI_FAILURE); - - mutex_enter(&(DEVI(dip)->devi_lock)); + int rval; - if ((nm = i_ddi_devtspectype_to_minorname(dip, - dev, spec_type)) == NULL) { - mutex_exit(&(DEVI(dip)->devi_lock)); - ddi_release_devi(dip); /* e_ddi_hold_devi_by_dev() */ + if ((dip = e_ddi_hold_devi_by_dev(dev, 0)) == NULL) { + *minor_name = NULL; return (DDI_FAILURE); } - /* make a copy */ - alloc_sz = strlen(nm) + 1; -retry: - /* drop lock to allocate memory */ - mutex_exit(&(DEVI(dip)->devi_lock)); - *minor_name = kmem_alloc(alloc_sz, KM_SLEEP); - mutex_enter(&(DEVI(dip)->devi_lock)); + /* Find the minor name and copy into max size buf */ + buf = kmem_alloc(MAXNAMELEN, KM_SLEEP); + ndi_devi_enter(dip, &circ); + nm = i_ddi_devtspectype_to_minorname(dip, dev, spec_type); + if (nm) + (void) strcpy(buf, nm); + ndi_devi_exit(dip, circ); + ddi_release_devi(dip); /* e_ddi_hold_devi_by_dev() */ - /* re-check things, since we dropped the lock */ - if ((nm = i_ddi_devtspectype_to_minorname(dip, - dev, spec_type)) == NULL) { - mutex_exit(&(DEVI(dip)->devi_lock)); - kmem_free(*minor_name, alloc_sz); + if (nm) { + /* duplicate into min size buf for return result */ + *minor_name = i_ddi_strdup(buf, KM_SLEEP); + rval = DDI_SUCCESS; + } else { *minor_name = NULL; - ddi_release_devi(dip); /* e_ddi_hold_devi_by_dev() */ - return (DDI_FAILURE); - } - - /* verify size is the same */ - sz = strlen(nm) + 1; - if (alloc_sz != sz) { - kmem_free(*minor_name, alloc_sz); - alloc_sz = sz; - goto retry; + rval = DDI_FAILURE; } - /* sz == alloc_sz - make a copy */ - (void) strcpy(*minor_name, nm); - - mutex_exit(&(DEVI(dip)->devi_lock)); - ddi_release_devi(dip); /* e_ddi_hold_devi_by_dev() */ - return (DDI_SUCCESS); + /* free max size buf and return */ + kmem_free(buf, MAXNAMELEN); + return (rval); } int @@ -7948,48 +7985,6 @@ ddi_get_eventcookie(dev_info_t *dip, char *name, } /* - * single thread access to dev_info node and set state - */ -void -i_devi_enter(dev_info_t *dip, uint_t s_mask, uint_t w_mask, int has_lock) -{ - if (!has_lock) - mutex_enter(&(DEVI(dip)->devi_lock)); - - ASSERT(mutex_owned(&(DEVI(dip)->devi_lock))); - - /* - * wait until state(s) have been changed - */ - while ((DEVI(dip)->devi_state & w_mask) != 0) { - cv_wait(&(DEVI(dip)->devi_cv), &(DEVI(dip)->devi_lock)); - } - DEVI(dip)->devi_state |= s_mask; - - if (!has_lock) - mutex_exit(&(DEVI(dip)->devi_lock)); -} - -void -i_devi_exit(dev_info_t *dip, uint_t c_mask, int has_lock) -{ - if (!has_lock) - mutex_enter(&(DEVI(dip)->devi_lock)); - - ASSERT(mutex_owned(&(DEVI(dip)->devi_lock))); - - /* - * clear the state(s) and wakeup any threads waiting - * for state change - */ - DEVI(dip)->devi_state &= ~c_mask; - cv_broadcast(&(DEVI(dip)->devi_cv)); - - if (!has_lock) - mutex_exit(&(DEVI(dip)->devi_lock)); -} - -/* * This procedure is provided as the general callback function when * umem_lockmemory calls as_add_callback for long term memory locking. * When as_unmap, as_setprot, or as_free encounter segments which have diff --git a/usr/src/uts/common/os/sunndi.c b/usr/src/uts/common/os/sunndi.c index cab88ecfe3..acbccac770 100644 --- a/usr/src/uts/common/os/sunndi.c +++ b/usr/src/uts/common/os/sunndi.c @@ -163,6 +163,7 @@ ndi_prop_remove(dev_t dev, dev_info_t *dip, char *name) void ndi_prop_remove_all(dev_info_t *dip) { + i_ddi_prop_dyn_parent_set(dip, NULL); ddi_prop_remove_all_common(dip, (int)DDI_PROP_HW_DEF); } @@ -202,7 +203,7 @@ ndi_post_event(dev_info_t *dip, dev_info_t *rdip, * post the event to the responsible ancestor */ return ((*(DEVI(ddip)->devi_ops->devo_bus_ops->bus_post_event)) - (ddip, rdip, cookie, impl_data)); + (ddip, rdip, cookie, impl_data)); } /* @@ -225,7 +226,7 @@ ndi_busop_remove_eventcall(dev_info_t *ddip, ddi_callback_id_t id) * request responsible nexus to remove the eventcall */ return ((*(DEVI(ddip)->devi_ops->devo_bus_ops->bus_remove_eventcall)) - (ddip, id)); + (ddip, id)); } /* @@ -256,7 +257,7 @@ ndi_busop_add_eventcall(dev_info_t *dip, dev_info_t *rdip, * request responsible ancestor to add the eventcall */ return ((*(DEVI(ddip)->devi_ops->devo_bus_ops->bus_add_eventcall)) - (ddip, rdip, cookie, callback, arg, cb_id)); + (ddip, rdip, cookie, callback, arg, cb_id)); } /* @@ -294,11 +295,11 @@ ndi_busop_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, char *name, #endif /* DEBUG */ return (ndi_busop_get_eventcookie(pdip, rdip, name, - event_cookiep)); + event_cookiep)); } return ((*(DEVI(pdip)->devi_ops->devo_bus_ops->bus_get_eventcookie)) - (pdip, rdip, name, event_cookiep)); + (pdip, rdip, name, event_cookiep)); } /* @@ -466,7 +467,7 @@ ndi_devctl_device_online(dev_info_t *dip, struct devctl_iocdata *dcp, name = kmem_alloc(MAXNAMELEN, KM_SLEEP); (void) snprintf(name, MAXNAMELEN, "%s@%s", - ndi_dc_getname(dcp), ndi_dc_getaddr(dcp)); + ndi_dc_getname(dcp), ndi_dc_getaddr(dcp)); if ((rval = ndi_devi_config_one(dip, name, &rdip, flags | NDI_DEVI_ONLINE | NDI_CONFIG)) == NDI_SUCCESS) { @@ -486,8 +487,8 @@ ndi_devctl_device_online(dev_info_t *dip, struct devctl_iocdata *dcp, } NDI_DEBUG(flags, (CE_CONT, "%s%d: online: %s: %s\n", - ddi_driver_name(dip), ddi_get_instance(dip), name, - ((rval == NDI_SUCCESS) ? "ok" : "failed"))); + ddi_driver_name(dip), ddi_get_instance(dip), name, + ((rval == NDI_SUCCESS) ? "ok" : "failed"))); kmem_free(name, MAXNAMELEN); @@ -510,7 +511,7 @@ ndi_devctl_device_offline(dev_info_t *dip, struct devctl_iocdata *dcp, name = kmem_alloc(MAXNAMELEN, KM_SLEEP); (void) snprintf(name, MAXNAMELEN, "%s@%s", - ndi_dc_getname(dcp), ndi_dc_getaddr(dcp)); + ndi_dc_getname(dcp), ndi_dc_getaddr(dcp)); (void) devfs_clean(dip, name, DV_CLEAN_FORCE); rval = ndi_devi_unconfig_one(dip, name, NULL, @@ -523,8 +524,8 @@ ndi_devctl_device_offline(dev_info_t *dip, struct devctl_iocdata *dcp, } NDI_DEBUG(flags, (CE_CONT, "%s%d: offline: %s: %s\n", - ddi_driver_name(dip), ddi_get_instance(dip), name, - (rval == NDI_SUCCESS) ? "ok" : "failed")); + ddi_driver_name(dip), ddi_get_instance(dip), name, + (rval == NDI_SUCCESS) ? "ok" : "failed")); kmem_free(name, MAXNAMELEN); @@ -547,7 +548,7 @@ ndi_devctl_device_remove(dev_info_t *dip, struct devctl_iocdata *dcp, name = kmem_alloc(MAXNAMELEN, KM_SLEEP); (void) snprintf(name, MAXNAMELEN, "%s@%s", - ndi_dc_getname(dcp), ndi_dc_getaddr(dcp)); + ndi_dc_getname(dcp), ndi_dc_getaddr(dcp)); (void) devfs_clean(dip, name, DV_CLEAN_FORCE); @@ -560,8 +561,8 @@ ndi_devctl_device_remove(dev_info_t *dip, struct devctl_iocdata *dcp, } NDI_DEBUG(flags, (CE_CONT, "%s%d: remove: %s: %s\n", - ddi_driver_name(dip), ddi_get_instance(dip), name, - (rval == NDI_SUCCESS) ? "ok" : "failed")); + ddi_driver_name(dip), ddi_get_instance(dip), name, + (rval == NDI_SUCCESS) ? "ok" : "failed")); kmem_free(name, MAXNAMELEN); @@ -765,8 +766,8 @@ ndi_dc_return_ap_state(devctl_ap_state_t *ap, struct devctl_iocdata *dcp) if (get_udatamodel() == DATAMODEL_NATIVE) { if (copyout(ap, dcp->cpyout_buf, - sizeof (devctl_ap_state_t)) != 0) - return (NDI_FAULT); + sizeof (devctl_ap_state_t)) != 0) + return (NDI_FAULT); } #ifdef _SYSCALL32_IMPL else { @@ -779,8 +780,8 @@ ndi_dc_return_ap_state(devctl_ap_state_t *ap, struct devctl_iocdata *dcp) ap_state32.ap_in_transition = ap->ap_in_transition; ap_state32.ap_last_change = (time32_t)ap->ap_last_change; if (copyout(&ap_state32, dcp->cpyout_buf, - sizeof (devctl_ap_state32_t)) != 0) - return (NDI_FAULT); + sizeof (devctl_ap_state32_t)) != 0) + return (NDI_FAULT); } #endif @@ -1209,7 +1210,7 @@ ndi_event_alloc_hdl(dev_info_t *dip, ddi_iblock_cookie_t cookie, struct ndi_event_hdl *ndi_event_hdl; ndi_event_hdl = kmem_zalloc(sizeof (struct ndi_event_hdl), - ((flag & NDI_NOSLEEP) ? KM_NOSLEEP : KM_SLEEP)); + ((flag & NDI_NOSLEEP) ? KM_NOSLEEP : KM_SLEEP)); if (!ndi_event_hdl) { return (NDI_FAILURE); @@ -1487,12 +1488,12 @@ ndi_event_unbind_set(ndi_event_hdl_t handle, ndi_event_set_t *ndi_events, if (strncmp(NDI_EVENT_NAME(cookie_list), ndi_event_defs[i].ndi_event_name, len) == 0) { - ASSERT(cookie_list->callback_list == NULL); - if (cookie_list->callback_list) { - rval = NDI_FAILURE; - goto done; - } - break; + ASSERT(cookie_list->callback_list == NULL); + if (cookie_list->callback_list) { + rval = NDI_FAILURE; + goto done; + } + break; } else { cookie_list = cookie_list->next_cookie; } @@ -1633,8 +1634,7 @@ ndi_event_retrieve_cookie(ndi_event_hdl_t handle, */ if ((flag & NDI_EVENT_NOPASS) == 0) { return (ndi_busop_get_eventcookie( - ndi_event_hdl->ndi_evthdl_dip, rdip, - eventname, cookiep)); + ndi_event_hdl->ndi_evthdl_dip, rdip, eventname, cookiep)); } else { return (NDI_FAILURE); } @@ -2113,25 +2113,19 @@ ndi_event_dump_hdl(struct ndi_event_hdl *hdl, char *location) list = hdl->ndi_evthdl_cookie_list; cmn_err(CE_CONT, "%s: event handle (%p): dip = %p (%s%d)\n", - location, (void *)hdl, - (void *)hdl->ndi_evthdl_dip, - ddi_node_name(hdl->ndi_evthdl_dip), - ddi_get_instance(hdl->ndi_evthdl_dip)); + location, (void *)hdl, (void *)hdl->ndi_evthdl_dip, + ddi_node_name(hdl->ndi_evthdl_dip), + ddi_get_instance(hdl->ndi_evthdl_dip)); cmn_err(CE_CONT, "\thigh=%d other=%d n=%d\n", - hdl->ndi_evthdl_high_plevels, - hdl->ndi_evthdl_other_plevels, - hdl->ndi_evthdl_n_events); - + hdl->ndi_evthdl_high_plevels, hdl->ndi_evthdl_other_plevels, + hdl->ndi_evthdl_n_events); cmn_err(CE_CONT, "\tevent cookies:\n"); while (list) { - cmn_err(CE_CONT, - "\t\ttag=%d name=%s p=%d a=%x dd=%p\n", - NDI_EVENT_TAG(list), - NDI_EVENT_NAME(list), - NDI_EVENT_PLEVEL(list), - NDI_EVENT_ATTRIBUTES(list), - (void *)NDI_EVENT_DDIP(list)); + cmn_err(CE_CONT, "\t\ttag=%d name=%s p=%d a=%x dd=%p\n", + NDI_EVENT_TAG(list), NDI_EVENT_NAME(list), + NDI_EVENT_PLEVEL(list), NDI_EVENT_ATTRIBUTES(list), + (void *)NDI_EVENT_DDIP(list)); cmn_err(CE_CONT, "\t\tcallbacks:\n"); for (next = list->callback_list; next != NULL; next = next->ndi_evtcb_next) { @@ -2355,15 +2349,13 @@ i_ddi_fault_logger(dev_info_t *rdip, struct ddi_fault_event_data *fedp) } cmn_err(level, "!%s%d: %s %s device; service %s%s"+(bad|changed), - ddi_driver_name(fedp->f_dip), - ddi_get_instance(fedp->f_dip), - bad ? "invalid report of fault" : action, - location, still ? "still " : "", servstate); + ddi_driver_name(fedp->f_dip), ddi_get_instance(fedp->f_dip), + bad ? "invalid report of fault" : action, + location, still ? "still " : "", servstate); cmn_err(level, "!%s%d: %s"+(bad|changed), - ddi_driver_name(fedp->f_dip), - ddi_get_instance(fedp->f_dip), - fedp->f_message); + ddi_driver_name(fedp->f_dip), ddi_get_instance(fedp->f_dip), + fedp->f_message); } /* @@ -2425,7 +2417,7 @@ i_ddi_rootnex_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, if (rootnex_event_hdl == NULL) return (NDI_FAILURE); return (ndi_event_retrieve_cookie(rootnex_event_hdl, rdip, eventname, - cookiep, NDI_EVENT_NOPASS)); + cookiep, NDI_EVENT_NOPASS)); } /*ARGSUSED*/ @@ -2438,7 +2430,7 @@ i_ddi_rootnex_add_eventcall(dev_info_t *dip, dev_info_t *rdip, if (rootnex_event_hdl == NULL) return (NDI_FAILURE); return (ndi_event_add_callback(rootnex_event_hdl, rdip, - eventid, handler, arg, NDI_SLEEP, cb_id)); + eventid, handler, arg, NDI_SLEEP, cb_id)); } /*ARGSUSED*/ @@ -2467,7 +2459,7 @@ i_ddi_rootnex_post_event(dev_info_t *dip, dev_info_t *rdip, (*plat_fault_logger)(rdip, impl_data); } return (ndi_event_run_callbacks(rootnex_event_hdl, rdip, - eventid, impl_data)); + eventid, impl_data)); } /* diff --git a/usr/src/uts/common/pcmcia/nexus/pcmcia.c b/usr/src/uts/common/pcmcia/nexus/pcmcia.c index 511e7f1c27..577b23c23a 100644 --- a/usr/src/uts/common/pcmcia/nexus/pcmcia.c +++ b/usr/src/uts/common/pcmcia/nexus/pcmcia.c @@ -1565,7 +1565,7 @@ pcm_search_devinfo(dev_info_t *self, struct pcm_device_info *info, int socket) char bf[256]; struct pcmcia_parent_private *ppd; dev_info_t *dip; - int circular; + int circ; #if defined(PCMCIA_DEBUG) if (pcmcia_debug) @@ -1575,7 +1575,7 @@ pcm_search_devinfo(dev_info_t *self, struct pcm_device_info *info, int socket) info->pd_vers1_name, info->pd_flags); #endif - ndi_devi_enter(self, &circular); + ndi_devi_enter(self, &circ); /* do searches in compatible property order */ for (dip = (dev_info_t *)DEVI(self)->devi_child; dip != NULL; @@ -1644,7 +1644,7 @@ pcm_search_devinfo(dev_info_t *self, struct pcm_device_info *info, int socket) break; } } - ndi_devi_exit(self, circular); + ndi_devi_exit(self, circ); return (dip); } @@ -3996,6 +3996,7 @@ pcmcia_create_device(ss_make_device_node_t *init) int pcmcia_get_minors(dev_info_t *dip, struct pcm_make_dev **minors) { + int circ; int count = 0; struct ddi_minor_data *dp; struct pcm_make_dev *md; @@ -4005,7 +4006,7 @@ pcmcia_get_minors(dev_info_t *dip, struct pcm_make_dev **minors) socket = ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, PCM_DEV_SOCKET, -1); - mutex_enter(&(DEVI(dip)->devi_lock)); + ndi_devi_enter(dip, &circ); if (DEVI(dip)->devi_minor != (struct ddi_minor_data *)NULL) { for (dp = DEVI(dip)->devi_minor; dp != (struct ddi_minor_data *)NULL; @@ -4060,7 +4061,7 @@ pcmcia_get_minors(dev_info_t *dip, struct pcm_make_dev **minors) count = 0; } } - mutex_exit(&(DEVI(dip)->devi_lock)); + ndi_devi_exit(dip, circ); return (count); } @@ -4070,6 +4071,7 @@ static char *ddmtypes[] = { "minor", "alias", "default", "internal" }; static void pcmcia_dump_minors(dev_info_t *dip) { + int circ; int count = 0; struct ddi_minor_data *dp; int unit, major; @@ -4093,7 +4095,7 @@ pcmcia_dump_minors(dev_info_t *dip) cmn_err(CE_CONT, "\tsibs: %s %s %s\n", ddi_binding_name(np), cf2, cur); - mutex_enter(&(DEVI(np)->devi_lock)); + ndi_devi_enter(np, &circ); if (DEVI(np)->devi_minor != (struct ddi_minor_data *)NULL) { for (dp = DEVI(np)->devi_minor; @@ -4117,7 +4119,7 @@ pcmcia_dump_minors(dev_info_t *dip) ddi_binding_name(np)); } } - mutex_exit(&(DEVI(np)->devi_lock)); + ndi_devi_exit(np, circ); } } } @@ -4639,9 +4641,9 @@ pcmcia_free_resources(dev_info_t *self) struct regspec *assigned; int len; dev_info_t *dip; - int circular; + int circ; - ndi_devi_enter(self, &circular); + ndi_devi_enter(self, &circ); /* do searches in compatible property order */ for (dip = (dev_info_t *)DEVI(self)->devi_child; dip != NULL; @@ -4660,7 +4662,7 @@ pcmcia_free_resources(dev_info_t *self) kmem_free(assigned, len); } } - ndi_devi_exit(self, circular); + ndi_devi_exit(self, circ); } /* diff --git a/usr/src/uts/common/sys/cmlb.h b/usr/src/uts/common/sys/cmlb.h index 6f65daee8b..e95cce9ade 100644 --- a/usr/src/uts/common/sys/cmlb.h +++ b/usr/src/uts/common/sys/cmlb.h @@ -184,7 +184,7 @@ typedef struct cmlb_tg_ops { * In case of TG_GETCAP, this return code * indicates no media in the drive. * - * EIO An error occured during obtaining info + * EIO An error occurred during obtaining info * from device/media. * * ENOTSUP In case of TG_GETCAP, target does not @@ -483,6 +483,28 @@ cmlb_ioctl(cmlb_handle_t cmlbhandle, dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cred_p, int *rval_p, void *tg_cookie); /* + * cmlb_prop_op: + * provide common label prop_op(9E) implementation that understands the + * size(9p) properties. + * + * Arguments: + * cmlbhandle cmlb handle associated with device. + * dev See prop_op(9E) + * dip " + * prop_op " + * mod_flags " + * name " + * valuep " + * lengthp " + * part partition number + * tg_cookie cookie from target driver to be passed back to target + */ +int +cmlb_prop_op(cmlb_handle_t cmlbhandle, + dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags, + char *name, caddr_t valuep, int *lengthp, int part, void *tg_cookie); + +/* * cmlb_get_devid_block: * get the block number where device id is stored. * diff --git a/usr/src/uts/common/sys/ddi_impldefs.h b/usr/src/uts/common/sys/ddi_impldefs.h index d1c31b318f..8269886431 100644 --- a/usr/src/uts/common/sys/ddi_impldefs.h +++ b/usr/src/uts/common/sys/ddi_impldefs.h @@ -219,6 +219,10 @@ struct dev_info { /* owned by bus framework */ devi_bus_priv_t devi_bus; /* bus private data */ + + /* Declarations of the pure dynamic properties to snapshot */ + struct i_ddi_prop_dyn *devi_prop_dyn_driver; /* prop_op */ + struct i_ddi_prop_dyn *devi_prop_dyn_parent; /* bus_prop_op */ }; #define DEVI(dev_info_type) ((struct dev_info *)(dev_info_type)) @@ -258,7 +262,7 @@ struct dev_info { * Device state information is stored in bits [0-7], bus state in bits * [8-15]. * - * NOTE: all devi_state updates shoule be protected by devi_lock. + * NOTE: all devi_state updates should be protected by devi_lock. */ #define DEVI_DEVICE_OFFLINE 0x00000001 #define DEVI_DEVICE_DOWN 0x00000002 @@ -277,7 +281,6 @@ struct dev_info { #define DEVI_S_INVOKING_DACF 0x00100000 /* busy invoking a dacf task */ #define DEVI_S_UNBOUND 0x00200000 -#define DEVI_S_MD_UPDATE 0x00400000 #define DEVI_S_REPORT 0x08000000 /* report status change */ #define DEVI_S_EVADD 0x10000000 /* state of devfs event */ @@ -525,13 +528,10 @@ struct dev_info { DEVI(dip)->devi_state &= ~DEVI_S_NEED_RESET; \ } -void i_devi_enter(dev_info_t *, uint_t s_mask, uint_t w_mask, int has_lock); -void i_devi_exit(dev_info_t *, uint_t c_mask, int has_lock); - /* * devi_flags bits * - * NOTE: all devi_state updates shoule be protected by devi_lock. + * NOTE: all devi_state updates should be protected by devi_lock. */ #define DEVI_BUSY 0x00000001 /* busy configuring children */ #define DEVI_MADE_CHILDREN 0x00000002 /* children made from specs */ @@ -878,6 +878,55 @@ struct ddi_callback { size_t c_size; }; +/* + * Pure dynamic property declaration. A pure dynamic property is a property + * for which a driver's prop_op(9E) implementation will return a value on + * demand, but the property name does not exist on a property list (global, + * driver, system, or hardware) - the person asking for the value must know + * the name and type information. + * + * For a pure dynamic property to show up in a di_init() devinfo shapshot, the + * devinfo driver must know name and type. The i_ddi_prop_dyn_t mechanism + * allows a driver to define an array of the name/type information of its + * dynamic properties. When a driver declares its dynamic properties in a + * i_ddi_prop_dyn_t array, and registers that array using + * i_ddi_prop_dyn_driver_set() the devinfo driver has sufficient information + * to represent the properties in a snapshot - calling the driver's + * prop_op(9E) to obtain values. + * + * The last element of a i_ddi_prop_dyn_t is detected via a NULL dp_name value. + * + * A pure dynamic property name associated with a minor_node/dev_t should be + * defined with a dp_spec_type of S_IFCHR or S_IFBLK, as appropriate. The + * driver's prop_op(9E) entry point will be called for all + * ddi_create_minor_node(9F) nodes of the specified spec_type. For a driver + * where not all minor_node/dev_t combinations support the same named + * properties, it is the responsibility of the prop_op(9E) implementation to + * sort out what combinations are appropriate. + * + * A pure dynamic property of a devinfo node should be defined with a + * dp_spec_type of 0. + * + * NB: Public DDI property interfaces no longer support pure dynamic + * properties, but they are still still used. A prime example is the cmlb + * implementation of size(9P) properties. Using pure dynamic properties + * reduces the space required to maintain per-partition information. Since + * there are no public interfaces to create pure dynamic properties, + * the i_ddi_prop_dyn_t mechanism should remain private. + */ +typedef struct i_ddi_prop_dyn { + char *dp_name; /* name of dynamic property */ + int dp_type; /* DDI_PROP_TYPE_ of property */ + int dp_spec_type; /* 0, S_IFCHR, S_IFBLK */ +} i_ddi_prop_dyn_t; +void i_ddi_prop_dyn_driver_set(dev_info_t *, + i_ddi_prop_dyn_t *); +i_ddi_prop_dyn_t *i_ddi_prop_dyn_driver_get(dev_info_t *); +void i_ddi_prop_dyn_parent_set(dev_info_t *, + i_ddi_prop_dyn_t *); +i_ddi_prop_dyn_t *i_ddi_prop_dyn_parent_get(dev_info_t *); +void i_ddi_prop_dyn_cache_invalidate(dev_info_t *, + i_ddi_prop_dyn_t *); /* * Device id - Internal definition. diff --git a/usr/src/uts/common/sys/devinfo_impl.h b/usr/src/uts/common/sys/devinfo_impl.h index 5cc9705bad..bcc4787d48 100644 --- a/usr/src/uts/common/sys/devinfo_impl.h +++ b/usr/src/uts/common/sys/devinfo_impl.h @@ -118,15 +118,7 @@ extern "C" { #define DI_DEVNM(addr) ((struct di_devnm *)((void *)(addr))) #define DI_LINK(addr) ((struct di_link *)((void *)(addr))) #define DI_LNODE(addr) ((struct di_lnode *)((void *)(addr))) - -/* - * For compatibility only - */ -#define DINO(addr) DI_NODE(addr) -#define DIMI(addr) DI_MINOR(addr) -#define DIPROP(addr) DI_PROP(addr) -#define DIPATH(addr) DI_PATH(addr) -#define DIPATHPROP(addr) DI_PATHPROP(addr) +#define DI_PRIV_FORMAT(addr) ((struct di_priv_format *)((void *)(addr))) /* * multipath component definitions: Follows the registered component of @@ -360,9 +352,9 @@ struct di_prop { di_off_t prop_data; /* property data */ major_t dev_major; /* dev_t can be 64 bit */ minor_t dev_minor; - int prop_flags; /* mark prop value types & more */ - int prop_len; /* prop length in bytes (boolean if 0) */ - int prop_list; /* which list (DI_PROP_SYS_LIST), etc */ + int prop_flags; /* mark prop value types & more */ + int prop_len; /* prop len in bytes (boolean if 0) */ + int prop_list; /* which list (DI_PROP_SYS_LIST), etc */ }; /* diff --git a/usr/src/uts/common/sys/sunddi.h b/usr/src/uts/common/sys/sunddi.h index 8f2b59bca9..af6acd290a 100644 --- a/usr/src/uts/common/sys/sunddi.h +++ b/usr/src/uts/common/sys/sunddi.h @@ -924,6 +924,15 @@ ddi_prop_undefine(dev_t dev, dev_info_t *dip, int flag, char *name); /* + * ddi_prop_cache_invalidate + * Invalidate a property in the current cached + * devinfo snapshot - next cached snapshot will + * return the latest property value available. + */ +void +ddi_prop_cache_invalidate(dev_t dev, dev_info_t *dip, char *name, int flags); + +/* * The default ddi_bus_prop_op wrapper... */ diff --git a/usr/src/uts/common/xen/io/xdf.c b/usr/src/uts/common/xen/io/xdf.c index f00ed03706..9683196362 100644 --- a/usr/src/uts/common/xen/io/xdf.c +++ b/usr/src/uts/common/xen/io/xdf.c @@ -301,19 +301,9 @@ static int xdf_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags, char *name, caddr_t valuep, int *lengthp) { - int instance = ddi_get_instance(dip); - xdf_t *vdp; - diskaddr_t p_blkcnt; - - /* - * xdf dynamic properties are device specific and size oriented. - * Requests issued under conditions where size is valid are passed - * to ddi_prop_op_nblocks with the size information, otherwise the - * request is passed to ddi_prop_op. - */ - vdp = ddi_get_soft_state(vbd_ss, instance); + xdf_t *vdp; - if ((dev == DDI_DEV_T_ANY) || (vdp == NULL)) + if ((vdp = ddi_get_soft_state(vbd_ss, ddi_get_instance(dip))) == NULL) return (ddi_prop_op(dev, dip, prop_op, mod_flags, name, valuep, lengthp)); @@ -321,18 +311,14 @@ xdf_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags, mutex_enter(&vdp->xdf_dev_lk); if (xdf_connect(vdp, B_TRUE) != XD_READY) { mutex_exit(&vdp->xdf_dev_lk); - goto out; + return (ddi_prop_op(dev, dip, prop_op, mod_flags, + name, valuep, lengthp)); } mutex_exit(&vdp->xdf_dev_lk); - if (cmlb_partinfo(vdp->xdf_vd_lbl, XDF_PART(getminor(dev)), &p_blkcnt, - NULL, NULL, NULL, NULL) == 0) - return (ddi_prop_op_nblocks(dev, dip, prop_op, mod_flags, - name, valuep, lengthp, (uint64_t)p_blkcnt)); - -out: - return (ddi_prop_op(dev, dip, prop_op, mod_flags, name, valuep, - lengthp)); + return (cmlb_prop_op(vdp->xdf_vd_lbl, + dev, dip, prop_op, mod_flags, name, valuep, lengthp, + XDF_PART(getminor(dev)), NULL)); } static int diff --git a/usr/src/uts/intel/io/dktp/disk/cmdk.c b/usr/src/uts/intel/io/dktp/disk/cmdk.c index 798e7108a5..f67d3eeaaa 100644 --- a/usr/src/uts/intel/io/dktp/disk/cmdk.c +++ b/usr/src/uts/intel/io/dktp/disk/cmdk.c @@ -684,8 +684,6 @@ cmdk_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags, char *name, caddr_t valuep, int *lengthp) { struct cmdk *dkp; - diskaddr_t p_lblksrt; - diskaddr_t p_lblkcnt; #ifdef CMDK_DEBUG if (cmdk_debug & DENT) @@ -693,31 +691,13 @@ cmdk_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags, #endif dkp = ddi_get_soft_state(cmdk_state, ddi_get_instance(dip)); + if (dkp == NULL) + return (ddi_prop_op(dev, dip, prop_op, mod_flags, + name, valuep, lengthp)); - /* - * Our dynamic properties are all device specific and size oriented. - * Requests issued under conditions where size is valid are passed - * to ddi_prop_op_nblocks with the size information, otherwise the - * request is passed to ddi_prop_op. Size depends on valid label. - */ - if ((dev != DDI_DEV_T_ANY) && (dkp != NULL)) { - if (!cmlb_partinfo( - dkp->dk_cmlbhandle, - CMDKPART(dev), - &p_lblkcnt, - &p_lblksrt, - NULL, - NULL, - 0)) - return (ddi_prop_op_nblocks(dev, dip, - prop_op, mod_flags, - name, valuep, lengthp, - (uint64_t)p_lblkcnt)); - } - - return (ddi_prop_op(dev, dip, - prop_op, mod_flags, - name, valuep, lengthp)); + return (cmlb_prop_op(dkp->dk_cmlbhandle, + dev, dip, prop_op, mod_flags, name, valuep, lengthp, + CMDKPART(dev), NULL)); } /* diff --git a/usr/src/uts/sun/io/dada/targets/dad.c b/usr/src/uts/sun/io/dada/targets/dad.c index eba181b9f3..5b0e39683d 100644 --- a/usr/src/uts/sun/io/dada/targets/dad.c +++ b/usr/src/uts/sun/io/dada/targets/dad.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -419,8 +419,7 @@ dcdprobe(dev_info_t *devi) dcd_max_instance = instance; mutex_exit(&dcd_attach_mutex); - DAD_DEBUG2(devp->dcd_dev, dcd_label, DCD_DEBUG, - "dcdprobe:\n"); + DAD_DEBUG2(devp->dcd_dev, dcd_label, DCD_DEBUG, "dcdprobe:\n"); if (ddi_get_soft_state(dcd_state, instance) != NULL) return (DDI_PROBE_PARTIAL); @@ -586,14 +585,14 @@ dcdattach(dev_info_t *devi, ddi_attach_cmd_t cmd) cmlb_alloc_handle(&un->un_dklbhandle); if (cmlb_attach(devi, - &dcd_lb_ops, - 0, - 0, - 0, - DDI_NT_BLOCK_CHAN, - CMLB_FAKE_GEOM_LABEL_IOCTLS_VTOC8, - un->un_dklbhandle, - 0) != 0) { + &dcd_lb_ops, + 0, + 0, + 0, + DDI_NT_BLOCK_CHAN, + CMLB_FAKE_GEOM_LABEL_IOCTLS_VTOC8, + un->un_dklbhandle, + 0) != 0) { cmlb_free_handle(&un->un_dklbhandle); dcd_free_softstate(un, devi); return (DDI_FAILURE); @@ -705,7 +704,7 @@ dcddetach(dev_info_t *devi, ddi_detach_cmd_t cmd) */ wait_cmds_complete = ddi_get_lbolt(); wait_cmds_complete += - DCD_WAIT_CMDS_COMPLETE * drv_usectohz(1000000); + DCD_WAIT_CMDS_COMPLETE * drv_usectohz(1000000); while (un->un_ncmds) { if (cv_timedwait(&un->un_disk_busy_cv, @@ -820,8 +819,8 @@ dcdpower(dev_info_t *devi, int component, int level) instance = ddi_get_instance(devi); if (!(un = ddi_get_soft_state(dcd_state, instance)) || - (DCD_DEVICE_STANDBY > level) || (level > DCD_DEVICE_ACTIVE) || - component != 0) { + (DCD_DEVICE_STANDBY > level) || (level > DCD_DEVICE_ACTIVE) || + component != 0) { return (DDI_FAILURE); } @@ -1189,8 +1188,8 @@ dcd_validate_geometry(struct dcd_disk *un) if (un->un_state == DCD_STATE_PM_SUSPENDED) { mutex_exit(DCD_MUTEX); - if (pm_raise_power(DCD_DEVINFO, 0, DCD_DEVICE_ACTIVE) - != DDI_SUCCESS) { + if (pm_raise_power(DCD_DEVINFO, 0, DCD_DEVICE_ACTIVE) != + DDI_SUCCESS) { mutex_enter(DCD_MUTEX); return (DCD_BAD_LABEL); } @@ -1638,40 +1637,15 @@ static int dcd_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags, char *name, caddr_t valuep, int *lengthp) { - int instance = ddi_get_instance(dip); struct dcd_disk *un; - uint64_t nblocks64; - diskaddr_t lblocks; - /* - * Our dynamic properties are all device specific and size oriented. - * Requests issued under conditions where size is valid are passed - * to ddi_prop_op_nblocks with the size information, otherwise the - * request is passed to ddi_prop_op. Size depends on valid geometry. - */ - un = ddi_get_soft_state(dcd_state, instance); - if ((dev == DDI_DEV_T_ANY) || (un == NULL)) { + if ((un = ddi_get_soft_state(dcd_state, ddi_get_instance(dip))) == NULL) return (ddi_prop_op(dev, dip, prop_op, mod_flags, name, valuep, lengthp)); - } else { - if (cmlb_partinfo( - un->un_dklbhandle, - DCDPART(dev), - &lblocks, - NULL, - NULL, - NULL, - 0)) { - return (ddi_prop_op(dev, dip, prop_op, mod_flags, - name, valuep, lengthp)); - } - - /* get nblocks value */ - nblocks64 = (ulong_t)lblocks; - return (ddi_prop_op_nblocks(dev, dip, prop_op, mod_flags, - name, valuep, lengthp, nblocks64)); - } + return (cmlb_prop_op(un->un_dklbhandle, + dev, dip, prop_op, mod_flags, name, valuep, lengthp, + DCDPART(dev), NULL)); } /* @@ -1858,7 +1832,7 @@ error: mutex_exit(DCD_MUTEX); (void) pm_idle_component(DCD_DEVINFO, 0); if (pm_raise_power(DCD_DEVINFO, 0, - DCD_DEVICE_ACTIVE) != DDI_SUCCESS) { + DCD_DEVICE_ACTIVE) != DDI_SUCCESS) { SET_BP_ERROR(bp, EIO); goto error; } @@ -2744,7 +2718,7 @@ dcd_handle_incomplete(struct dcd_disk *un, struct buf *bp) */ DCD_DO_ERRSTATS(un, dcd_transerrs); if ((pkt->pkt_reason != CMD_RESET) && - (pkt->pkt_reason != CMD_ABORTED)) { + (pkt->pkt_reason != CMD_ABORTED)) { (void) dcd_reset_disk(un, pkt); } break; @@ -2779,7 +2753,7 @@ dcd_handle_incomplete(struct dcd_disk *un, struct buf *bp) */ if (un->un_state != DCD_STATE_OFFLINE) { dcd_log(DCD_DEVINFO, dcd_label, CE_WARN, - (const char *) notresp); + (const char *) notresp); New_state(un, DCD_STATE_OFFLINE); } } else if (pkt->pkt_reason == CMD_FATAL) { @@ -2876,11 +2850,13 @@ dcd_check_error(struct dcd_disk *un, struct buf *bp) } else if ((error & ERR_UNC) == ERR_UNC) { dcd_log(DCD_DEVINFO, dcd_label, CE_WARN, "Uncorrectable data Error: Block %x\n", - ((struct dcd_cmd *)pkt->pkt_cdbp)->sector_num.lba_num); + ((struct dcd_cmd *)pkt->pkt_cdbp)-> + sector_num.lba_num); } else if ((error & ERR_BBK) == ERR_BBK) { dcd_log(DCD_DEVINFO, dcd_label, CE_WARN, "Bad block detected: Block %x\n", - ((struct dcd_cmd *)pkt->pkt_cdbp)->sector_num.lba_num); + ((struct dcd_cmd *)pkt->pkt_cdbp)-> + sector_num.lba_num); } else if ((error & ERR_ABORT) == ERR_ABORT) { /* Aborted Command */ dcd_log(DCD_DEVINFO, dcd_label, CE_WARN, @@ -3824,7 +3800,7 @@ dcdrestart(void *arg) * } */ un->un_reissued_timeid = - timeout(dcdrestart, (caddr_t)un, + timeout(dcdrestart, (caddr_t)un, DCD_BSY_TIMEOUT/500); mutex_exit(DCD_MUTEX); return; @@ -3898,7 +3874,7 @@ dcd_handle_tran_busy(struct buf *bp, struct diskhd *dp, struct dcd_disk *un) } if (!un->un_reissued_timeid) { un->un_reissued_timeid = - timeout(dcdrestart, (caddr_t)un, DCD_BSY_TIMEOUT/500); + timeout(dcdrestart, (caddr_t)un, DCD_BSY_TIMEOUT/500); } } @@ -4710,7 +4686,7 @@ dcd_lb_getinfo(dev_info_t *devi, int cmd, void *arg, void *tg_cookie) if (un->un_diskcapacity <= 0) { mutex_exit(DCD_MUTEX); dcd_log(DCD_DEVINFO, dcd_label, CE_WARN, - "invalid disk capacity\n"); + "invalid disk capacity\n"); return (EIO); } if (cmd == TG_GETCAPACITY) diff --git a/usr/src/uts/sun4u/montecarlo/io/ttymux_dacf/ttymux_dacf.c b/usr/src/uts/sun4u/montecarlo/io/ttymux_dacf/ttymux_dacf.c index 4e08be6d8d..8abf3540df 100644 --- a/usr/src/uts/sun4u/montecarlo/io/ttymux_dacf/ttymux_dacf.c +++ b/usr/src/uts/sun4u/montecarlo/io/ttymux_dacf/ttymux_dacf.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -240,6 +240,7 @@ usable_consoles(sm_mux_state_t *sp, uint_t *iconsoles, uint_t *oconsoles) static boolean_t compatible_console(dev_t dev) { + int circ; boolean_t compatible; char *const *nodetype; struct ddi_minor_data *dmdp; @@ -261,6 +262,7 @@ compatible_console(dev_t dev) compatible = B_FALSE; len = sizeof (devtype); + ndi_devi_enter(dip, &circ); for (dmdp = DEVI(dip)->devi_minor; dmdp != NULL; dmdp = dmdp->next) { struct ddi_minor_data *mdp = dmdp; @@ -279,9 +281,9 @@ compatible_console(dev_t dev) compatible = B_TRUE; } else { for (nodetype = - (char *const *)&supported_types[0]; - *nodetype != (char *const)NULL; - nodetype++) { + (char *const *)&supported_types[0]; + *nodetype != (char *const)NULL; + nodetype++) { if (strcmp(*nodetype, mdp->ddm_node_type) == 0) { compatible = B_TRUE; @@ -292,6 +294,7 @@ compatible_console(dev_t dev) break; } } + ndi_devi_exit(dip, circ); ddi_release_devi(dip); /* @@ -300,7 +303,7 @@ compatible_console(dev_t dev) */ ttymux_dprintf(DPRINT_L0, "%d:%d is %s\n", getmajor(dev), - getminor(dev), (compatible) ? "compatible" : "incompatible"); + getminor(dev), (compatible) ? "compatible" : "incompatible"); return (compatible); } @@ -636,7 +639,7 @@ link_aconsole(vnode_t *mux_avp, sm_console_t *cn) } if ((rv = strioctl(mux_avp, I_PLINK, (intptr_t)lfd, - FREAD+FWRITE+FNOCTTY, K_TO_K, CRED(), &(cn->sm_muxid))) != 0) { + FREAD+FWRITE+FNOCTTY, K_TO_K, CRED(), &(cn->sm_muxid))) != 0) { ttymux_dprintf(DPRINT_L3, "Failed to link device: error %d", rv); @@ -718,7 +721,7 @@ enable_all_consoles(sm_mux_state_t *ms, vnode_t *muxvp) continue; } ttymux_dprintf(DPRINT_L0, "Enabling %d:%d\n", - getmajor(cn->sm_dev), getminor(cn->sm_dev)); + getmajor(cn->sm_dev), getminor(cn->sm_dev)); /* * Refuse requests to use devices as consoles which have an |