summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcth <none@none>2008-07-30 10:30:05 -0700
committercth <none@none>2008-07-30 10:30:05 -0700
commitb9ccdc5a0f0a722ae408b257a831b90011369316 (patch)
tree270c4af8f4db077f69e1a5160f17bdd1d0884756
parent945a353f89a55e9591f2aefc0cf7a23800b354be (diff)
downloadillumos-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
-rw-r--r--usr/src/cmd/mdb/common/modules/genunix/devinfo.c1
-rw-r--r--usr/src/cmd/prtconf/pdevinfo.c133
-rw-r--r--usr/src/uts/common/fs/devfs/devfs_subr.c168
-rw-r--r--usr/src/uts/common/io/cmlb.c141
-rw-r--r--usr/src/uts/common/io/devinfo.c1068
-rw-r--r--usr/src/uts/common/io/scsi/impl/scsi_hba.c12
-rw-r--r--usr/src/uts/common/io/scsi/targets/sd.c87
-rw-r--r--usr/src/uts/common/os/devcfg.c52
-rw-r--r--usr/src/uts/common/os/devid_cache.c7
-rw-r--r--usr/src/uts/common/os/modctl.c24
-rw-r--r--usr/src/uts/common/os/sunddi.c231
-rw-r--r--usr/src/uts/common/os/sunndi.c96
-rw-r--r--usr/src/uts/common/pcmcia/nexus/pcmcia.c22
-rw-r--r--usr/src/uts/common/sys/cmlb.h24
-rw-r--r--usr/src/uts/common/sys/ddi_impldefs.h61
-rw-r--r--usr/src/uts/common/sys/devinfo_impl.h16
-rw-r--r--usr/src/uts/common/sys/sunddi.h9
-rw-r--r--usr/src/uts/common/xen/io/xdf.c28
-rw-r--r--usr/src/uts/intel/io/dktp/disk/cmdk.c32
-rw-r--r--usr/src/uts/sun/io/dada/targets/dad.c82
-rw-r--r--usr/src/uts/sun4u/montecarlo/io/ttymux_dacf/ttymux_dacf.c17
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