usr/src/uts/common/os/devcfg.c
author cth
Fri, 22 Feb 2008 09:02:16 -0800
changeset 6065 b05c5c670963
parent 5895 f251acdd9bdc
child 6640 c92ca9b95b9c
permissions -rw-r--r--
6453345 devfs_getattr violates devfs locking rules 6527396 devfsadm -C taking hours after reconfiguration reboot 6661843 i_ddi_di_cache_invalidate() should only use taskq_dispatch on valid->invalid 6662461 reserved_links_exist() should be optimized
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     1
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     2
 * CDDL HEADER START
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     3
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
1961
cceb6bfa61a5 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 1826
diff changeset
     5
 * Common Development and Distribution License (the "License").
cceb6bfa61a5 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 1826
diff changeset
     6
 * You may not use this file except in compliance with the License.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     7
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     8
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     9
 * or http://www.opensolaris.org/os/licensing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    10
 * See the License for the specific language governing permissions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    11
 * and limitations under the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    12
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    13
 * When distributing Covered Code, include this CDDL HEADER in each
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    14
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    15
 * If applicable, add the following below this CDDL HEADER, with the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    16
 * fields enclosed by brackets "[]" replaced with your own identifying
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    17
 * information: Portions Copyright [yyyy] [name of copyright owner]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    18
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    19
 * CDDL HEADER END
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    20
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    21
/*
5895
f251acdd9bdc PSARC/2006/499 Clearview Nemo unification and vanity naming
yz147064
parents: 5742
diff changeset
    22
 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    23
 * Use is subject to license terms.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    24
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    25
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    26
#pragma ident	"%Z%%M%	%I%	%E% SMI"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    27
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    28
#include <sys/note.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    29
#include <sys/t_lock.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    30
#include <sys/cmn_err.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    31
#include <sys/instance.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    32
#include <sys/conf.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    33
#include <sys/stat.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    34
#include <sys/ddi.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    35
#include <sys/hwconf.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    36
#include <sys/sunddi.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    37
#include <sys/sunndi.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    38
#include <sys/ddi_impldefs.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    39
#include <sys/ndi_impldefs.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    40
#include <sys/modctl.h>
4845
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
    41
#include <sys/contract/device_impl.h>
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    42
#include <sys/dacf.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    43
#include <sys/promif.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    44
#include <sys/cpuvar.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    45
#include <sys/pathname.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    46
#include <sys/taskq.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    47
#include <sys/sysevent.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    48
#include <sys/sunmdi.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    49
#include <sys/stream.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    50
#include <sys/strsubr.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    51
#include <sys/fs/snode.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    52
#include <sys/fs/dv_node.h>
2621
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
    53
#include <sys/reboot.h>
4845
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
    54
#include <sys/sysmacros.h>
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
    55
#include <sys/sunldi.h>
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
    56
#include <sys/sunldi_impl.h>
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    57
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    58
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    59
int ddidebug = DDI_AUDIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    60
#else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    61
int ddidebug = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    62
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    63
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    64
#define	MT_CONFIG_OP	0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    65
#define	MT_UNCONFIG_OP	1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    66
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    67
/* Multi-threaded configuration */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    68
struct mt_config_handle {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    69
	kmutex_t mtc_lock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    70
	kcondvar_t mtc_cv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    71
	int mtc_thr_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    72
	dev_info_t *mtc_pdip;	/* parent dip for mt_config_children */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    73
	dev_info_t **mtc_fdip;	/* "a" dip where unconfigure failed */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    74
	major_t mtc_parmajor;	/* parent major for mt_config_driver */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    75
	major_t mtc_major;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    76
	int mtc_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    77
	int mtc_op;		/* config or unconfig */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    78
	int mtc_error;		/* operation error */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    79
	struct brevq_node **mtc_brevqp;	/* outstanding branch events queue */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    80
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    81
	int total_time;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    82
	timestruc_t start_time;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    83
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    84
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    85
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    86
struct devi_nodeid {
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 693
diff changeset
    87
	pnode_t nodeid;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    88
	dev_info_t *dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    89
	struct devi_nodeid *next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    90
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    91
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    92
struct devi_nodeid_list {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    93
	kmutex_t dno_lock;		/* Protects other fields */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    94
	struct devi_nodeid *dno_head;	/* list of devi nodeid elements */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    95
	struct devi_nodeid *dno_free;	/* Free list */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    96
	uint_t dno_list_length;		/* number of dips in list */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    97
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    98
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    99
/* used to keep track of branch remove events to be generated */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   100
struct brevq_node {
1317
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
   101
	char *brn_deviname;
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
   102
	struct brevq_node *brn_sibling;
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
   103
	struct brevq_node *brn_child;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   104
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   105
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   106
static struct devi_nodeid_list devi_nodeid_list;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   107
static struct devi_nodeid_list *devimap = &devi_nodeid_list;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   108
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   109
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   110
 * Well known nodes which are attached first at boot time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   111
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   112
dev_info_t *top_devinfo;		/* root of device tree */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   113
dev_info_t *options_dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   114
dev_info_t *pseudo_dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   115
dev_info_t *clone_dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   116
dev_info_t *scsi_vhci_dip;		/* MPXIO dip */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   117
major_t clone_major;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   118
2621
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
   119
/*
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
   120
 * A non-global zone's /dev is derived from the device tree.
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
   121
 * This generation number serves to indicate when a zone's
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
   122
 * /dev may need to be updated.
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
   123
 */
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
   124
volatile ulong_t devtree_gen;		/* generation number */
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
   125
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   126
/* block all future dev_info state changes */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   127
static hrtime_t volatile devinfo_freeze = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   128
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   129
/* number of dev_info attaches/detaches currently in progress */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   130
static ulong_t devinfo_attach_detach = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   131
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   132
extern kmutex_t global_vhci_lock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   133
2621
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
   134
/* bitset of DS_SYSAVAIL & DS_RECONFIG - no races, no lock */
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
   135
static int devname_state = 0;
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
   136
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   137
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   138
 * The devinfo snapshot cache and related variables.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   139
 * The only field in the di_cache structure that needs initialization
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   140
 * is the mutex (cache_lock). However, since this is an adaptive mutex
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   141
 * (MUTEX_DEFAULT) - it is automatically initialized by being allocated
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   142
 * in zeroed memory (static storage class). Therefore no explicit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   143
 * initialization of the di_cache structure is needed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   144
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   145
struct di_cache	di_cache = {1};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   146
int		di_cache_debug = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   147
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   148
/* For ddvis, which needs pseudo children under PCI */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   149
int pci_allow_pseudo_children = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   150
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   151
/* Allow path-oriented alias driver binding on driver.conf enumerated nodes */
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   152
int driver_conf_allow_path_alias = 1;
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   153
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   154
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   155
 * The following switch is for service people, in case a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   156
 * 3rd party driver depends on identify(9e) being called.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   157
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   158
int identify_9e = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   159
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   160
int mtc_off;					/* turn off mt config */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   161
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   162
static kmem_cache_t *ddi_node_cache;		/* devinfo node cache */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   163
static devinfo_log_header_t *devinfo_audit_log;	/* devinfo log */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   164
static int devinfo_log_size;			/* size in pages */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   165
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   166
static int lookup_compatible(dev_info_t *, uint_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   167
static char *encode_composite_string(char **, uint_t, size_t *, uint_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   168
static void link_to_driver_list(dev_info_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   169
static void unlink_from_driver_list(dev_info_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   170
static void add_to_dn_list(struct devnames *, dev_info_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   171
static void remove_from_dn_list(struct devnames *, dev_info_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   172
static dev_info_t *find_child_by_callback(dev_info_t *, char *, char *,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   173
    int (*)(dev_info_t *, char *, int));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   174
static dev_info_t *find_duplicate_child();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   175
static void add_global_props(dev_info_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   176
static void remove_global_props(dev_info_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   177
static int uninit_node(dev_info_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   178
static void da_log_init(void);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   179
static void da_log_enter(dev_info_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   180
static int walk_devs(dev_info_t *, int (*f)(dev_info_t *, void *), void *, int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   181
static int reset_nexus_flags(dev_info_t *, void *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   182
static void ddi_optimize_dtree(dev_info_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   183
static int is_leaf_node(dev_info_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   184
static struct mt_config_handle *mt_config_init(dev_info_t *, dev_info_t **,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   185
    int, major_t, int, struct brevq_node **);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   186
static void mt_config_children(struct mt_config_handle *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   187
static void mt_config_driver(struct mt_config_handle *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   188
static int mt_config_fini(struct mt_config_handle *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   189
static int devi_unconfig_common(dev_info_t *, dev_info_t **, int, major_t,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   190
    struct brevq_node **);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   191
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   192
ndi_devi_config_obp_args(dev_info_t *parent, char *devnm,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   193
    dev_info_t **childp, int flags);
1093
4dc7aec69dc9 6299476 DM Does not interoperate with TS90 switch, cannot discover SRP targets
hiremath
parents: 789
diff changeset
   194
static void i_link_vhci_node(dev_info_t *);
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
   195
static void ndi_devi_exit_and_wait(dev_info_t *dip,
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
   196
    int circular, clock_t end_time);
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   197
static int ndi_devi_unbind_driver(dev_info_t *dip);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   198
4845
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
   199
static void i_ddi_check_retire(dev_info_t *dip);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
   200
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
   201
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
   202
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   203
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   204
 * dev_info cache and node management
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   205
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   206
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   207
/* initialize dev_info node cache */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   208
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   209
i_ddi_node_cache_init()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   210
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   211
	ASSERT(ddi_node_cache == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   212
	ddi_node_cache = kmem_cache_create("dev_info_node_cache",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   213
	    sizeof (struct dev_info), 0, NULL, NULL, NULL, NULL, NULL, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   214
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   215
	if (ddidebug & DDI_AUDIT)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   216
		da_log_init();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   217
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   218
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   219
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   220
 * Allocating a dev_info node, callable from interrupt context with KM_NOSLEEP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   221
 * The allocated node has a reference count of 0.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   222
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   223
dev_info_t *
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 693
diff changeset
   224
i_ddi_alloc_node(dev_info_t *pdip, char *node_name, pnode_t nodeid,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   225
    int instance, ddi_prop_t *sys_prop, int flag)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   226
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   227
	struct dev_info *devi;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   228
	struct devi_nodeid *elem;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   229
	static char failed[] = "i_ddi_alloc_node: out of memory";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   230
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   231
	ASSERT(node_name != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   232
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   233
	if ((devi = kmem_cache_alloc(ddi_node_cache, flag)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   234
		cmn_err(CE_NOTE, failed);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   235
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   236
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   237
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   238
	bzero(devi, sizeof (struct dev_info));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   239
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   240
	if (devinfo_audit_log) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   241
		devi->devi_audit = kmem_zalloc(sizeof (devinfo_audit_t), flag);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   242
		if (devi->devi_audit == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   243
			goto fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   244
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   245
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   246
	if ((devi->devi_node_name = i_ddi_strdup(node_name, flag)) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   247
		goto fail;
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   248
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   249
	/* default binding name is node name */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   250
	devi->devi_binding_name = devi->devi_node_name;
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   251
	devi->devi_major = (major_t)-1;		/* unbound by default */
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   252
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   253
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   254
	 * Make a copy of system property
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   255
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   256
	if (sys_prop &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   257
	    (devi->devi_sys_prop_ptr = i_ddi_prop_list_dup(sys_prop, flag))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   258
	    == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   259
		goto fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   260
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   261
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   262
	 * Assign devi_nodeid, devi_node_class, devi_node_attributes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   263
	 * according to the following algorithm:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   264
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   265
	 * nodeid arg			node class		node attributes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   266
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   267
	 * DEVI_PSEUDO_NODEID		DDI_NC_PSEUDO		A
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   268
	 * DEVI_SID_NODEID		DDI_NC_PSEUDO		A,P
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   269
	 * other			DDI_NC_PROM		P
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   270
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   271
	 * Where A = DDI_AUTO_ASSIGNED_NODEID (auto-assign a nodeid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   272
	 * and	 P = DDI_PERSISTENT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   273
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   274
	 * auto-assigned nodeids are also auto-freed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   275
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   276
	switch (nodeid) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   277
	case DEVI_SID_NODEID:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   278
		devi->devi_node_attributes = DDI_PERSISTENT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   279
		if ((elem = kmem_zalloc(sizeof (*elem), flag)) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   280
			goto fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   281
		/*FALLTHROUGH*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   282
	case DEVI_PSEUDO_NODEID:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   283
		devi->devi_node_attributes |= DDI_AUTO_ASSIGNED_NODEID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   284
		devi->devi_node_class = DDI_NC_PSEUDO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   285
		if (impl_ddi_alloc_nodeid(&devi->devi_nodeid)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   286
			panic("i_ddi_alloc_node: out of nodeids");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   287
			/*NOTREACHED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   288
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   289
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   290
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   291
		if ((elem = kmem_zalloc(sizeof (*elem), flag)) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   292
			goto fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   293
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   294
		 * the nodetype is 'prom', try to 'take' the nodeid now.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   295
		 * This requires memory allocation, so check for failure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   296
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   297
		if (impl_ddi_take_nodeid(nodeid, flag) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   298
			kmem_free(elem, sizeof (*elem));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   299
			goto fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   300
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   301
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   302
		devi->devi_nodeid = nodeid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   303
		devi->devi_node_class = DDI_NC_PROM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   304
		devi->devi_node_attributes = DDI_PERSISTENT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   305
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   306
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   307
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   308
	if (ndi_dev_is_persistent_node((dev_info_t *)devi)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   309
		mutex_enter(&devimap->dno_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   310
		elem->next = devimap->dno_free;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   311
		devimap->dno_free = elem;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   312
		mutex_exit(&devimap->dno_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   313
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   314
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   315
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   316
	 * Instance is normally initialized to -1. In a few special
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   317
	 * cases, the caller may specify an instance (e.g. CPU nodes).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   318
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   319
	devi->devi_instance = instance;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   320
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   321
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   322
	 * set parent and bus_ctl parent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   323
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   324
	devi->devi_parent = DEVI(pdip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   325
	devi->devi_bus_ctl = DEVI(pdip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   326
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   327
	NDI_CONFIG_DEBUG((CE_CONT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   328
	    "i_ddi_alloc_node: name=%s id=%d\n", node_name, devi->devi_nodeid));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   329
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   330
	cv_init(&(devi->devi_cv), NULL, CV_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   331
	mutex_init(&(devi->devi_lock), NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   332
	mutex_init(&(devi->devi_pm_lock), NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   333
	mutex_init(&(devi->devi_pm_busy_lock), NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   334
4845
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
   335
	RIO_TRACE((CE_NOTE, "i_ddi_alloc_node: Initing contract fields: "
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
   336
	    "dip=%p, name=%s", (void *)devi, node_name));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
   337
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
   338
	mutex_init(&(devi->devi_ct_lock), NULL, MUTEX_DEFAULT, NULL);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
   339
	cv_init(&(devi->devi_ct_cv), NULL, CV_DEFAULT, NULL);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
   340
	devi->devi_ct_count = -1;	/* counter not in use if -1 */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
   341
	list_create(&(devi->devi_ct), sizeof (cont_device_t),
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
   342
	    offsetof(cont_device_t, cond_next));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
   343
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   344
	i_ddi_set_node_state((dev_info_t *)devi, DS_PROTO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   345
	da_log_enter((dev_info_t *)devi);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   346
	return ((dev_info_t *)devi);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   347
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   348
fail:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   349
	if (devi->devi_sys_prop_ptr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   350
		i_ddi_prop_list_delete(devi->devi_sys_prop_ptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   351
	if (devi->devi_node_name)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   352
		kmem_free(devi->devi_node_name, strlen(node_name) + 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   353
	if (devi->devi_audit)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   354
		kmem_free(devi->devi_audit, sizeof (devinfo_audit_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   355
	kmem_cache_free(ddi_node_cache, devi);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   356
	cmn_err(CE_NOTE, failed);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   357
	return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   358
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   359
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   360
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   361
 * free a dev_info structure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   362
 * NB. Not callable from interrupt since impl_ddi_free_nodeid may block.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   363
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   364
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   365
i_ddi_free_node(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   366
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   367
	struct dev_info *devi = DEVI(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   368
	struct devi_nodeid *elem;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   369
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   370
	ASSERT(devi->devi_ref == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   371
	ASSERT(devi->devi_addr == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   372
	ASSERT(devi->devi_node_state == DS_PROTO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   373
	ASSERT(devi->devi_child == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   374
439
8048629e2754 6299820 ddi_deviname() can dereference NULL pointer
cth
parents: 438
diff changeset
   375
	/* free devi_addr_buf allocated by ddi_set_name_addr() */
8048629e2754 6299820 ddi_deviname() can dereference NULL pointer
cth
parents: 438
diff changeset
   376
	if (devi->devi_addr_buf)
8048629e2754 6299820 ddi_deviname() can dereference NULL pointer
cth
parents: 438
diff changeset
   377
		kmem_free(devi->devi_addr_buf, 2 * MAXNAMELEN);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   378
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   379
	if (i_ndi_dev_is_auto_assigned_node(dip))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   380
		impl_ddi_free_nodeid(DEVI(dip)->devi_nodeid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   381
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   382
	if (ndi_dev_is_persistent_node(dip)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   383
		mutex_enter(&devimap->dno_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   384
		ASSERT(devimap->dno_free);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   385
		elem = devimap->dno_free;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   386
		devimap->dno_free = elem->next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   387
		mutex_exit(&devimap->dno_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   388
		kmem_free(elem, sizeof (*elem));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   389
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   390
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   391
	if (DEVI(dip)->devi_compat_names)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   392
		kmem_free(DEVI(dip)->devi_compat_names,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   393
		    DEVI(dip)->devi_compat_length);
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   394
	if (DEVI(dip)->devi_rebinding_name)
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   395
		kmem_free(DEVI(dip)->devi_rebinding_name,
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   396
		    strlen(DEVI(dip)->devi_rebinding_name) + 1);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   397
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   398
	ddi_prop_remove_all(dip);	/* remove driver properties */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   399
	if (devi->devi_sys_prop_ptr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   400
		i_ddi_prop_list_delete(devi->devi_sys_prop_ptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   401
	if (devi->devi_hw_prop_ptr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   402
		i_ddi_prop_list_delete(devi->devi_hw_prop_ptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   403
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   404
	i_ddi_set_node_state(dip, DS_INVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   405
	da_log_enter(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   406
	if (devi->devi_audit) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   407
		kmem_free(devi->devi_audit, sizeof (devinfo_audit_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   408
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   409
	if (devi->devi_device_class)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   410
		kmem_free(devi->devi_device_class,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   411
		    strlen(devi->devi_device_class) + 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   412
	cv_destroy(&(devi->devi_cv));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   413
	mutex_destroy(&(devi->devi_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   414
	mutex_destroy(&(devi->devi_pm_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   415
	mutex_destroy(&(devi->devi_pm_busy_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   416
4845
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
   417
	RIO_TRACE((CE_NOTE, "i_ddi_free_node: destroying contract fields: "
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
   418
	    "dip=%p", (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
   419
	contract_device_remove_dip(dip);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
   420
	ASSERT(devi->devi_ct_count == -1);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
   421
	ASSERT(list_is_empty(&(devi->devi_ct)));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
   422
	cv_destroy(&(devi->devi_ct_cv));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
   423
	list_destroy(&(devi->devi_ct));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
   424
	/* free this last since contract_device_remove_dip() uses it */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
   425
	mutex_destroy(&(devi->devi_ct_lock));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
   426
	RIO_TRACE((CE_NOTE, "i_ddi_free_node: destroyed all contract fields: "
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
   427
	    "dip=%p, name=%s", (void *)dip, devi->devi_node_name));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
   428
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
   429
	kmem_free(devi->devi_node_name, strlen(devi->devi_node_name) + 1);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
   430
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   431
	kmem_cache_free(ddi_node_cache, devi);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   432
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   433
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   434
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   435
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   436
 * Node state transitions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   437
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   438
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   439
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   440
 * Change the node name
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   441
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   442
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   443
ndi_devi_set_nodename(dev_info_t *dip, char *name, int flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   444
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   445
	_NOTE(ARGUNUSED(flags))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   446
	char *nname, *oname;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   447
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   448
	ASSERT(dip && name);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   449
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   450
	oname = DEVI(dip)->devi_node_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   451
	if (strcmp(oname, name) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   452
		return (DDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   453
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   454
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   455
	 * pcicfg_fix_ethernet requires a name change after node
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   456
	 * is linked into the tree. When pcicfg is fixed, we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   457
	 * should only allow name change in DS_PROTO state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   458
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   459
	if (i_ddi_node_state(dip) >= DS_BOUND) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   460
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   461
		 * Don't allow name change once node is bound
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   462
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   463
		cmn_err(CE_NOTE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   464
		    "ndi_devi_set_nodename: node already bound dip = %p,"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   465
		    " %s -> %s", (void *)dip, ddi_node_name(dip), name);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   466
		return (NDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   467
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   468
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   469
	nname = i_ddi_strdup(name, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   470
	DEVI(dip)->devi_node_name = nname;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   471
	i_ddi_set_binding_name(dip, nname);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   472
	kmem_free(oname, strlen(oname) + 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   473
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   474
	da_log_enter(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   475
	return (NDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   476
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   477
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   478
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   479
i_ddi_add_devimap(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   480
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   481
	struct devi_nodeid *elem;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   482
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   483
	ASSERT(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   484
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   485
	if (!ndi_dev_is_persistent_node(dip))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   486
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   487
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   488
	ASSERT(ddi_get_parent(dip) == NULL || (DEVI_VHCI_NODE(dip)) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   489
	    DEVI_BUSY_OWNED(ddi_get_parent(dip)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   490
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   491
	mutex_enter(&devimap->dno_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   492
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   493
	ASSERT(devimap->dno_free);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   494
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   495
	elem = devimap->dno_free;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   496
	devimap->dno_free = elem->next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   497
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   498
	elem->nodeid = ddi_get_nodeid(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   499
	elem->dip = dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   500
	elem->next = devimap->dno_head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   501
	devimap->dno_head = elem;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   502
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   503
	devimap->dno_list_length++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   504
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   505
	mutex_exit(&devimap->dno_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   506
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   507
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   508
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   509
i_ddi_remove_devimap(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   510
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   511
	struct devi_nodeid *prev, *elem;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   512
	static const char *fcn = "i_ddi_remove_devimap";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   513
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   514
	ASSERT(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   515
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   516
	if (!ndi_dev_is_persistent_node(dip))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   517
		return (DDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   518
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   519
	mutex_enter(&devimap->dno_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   520
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   521
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   522
	 * The following check is done with dno_lock held
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   523
	 * to prevent race between dip removal and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   524
	 * e_ddi_prom_node_to_dip()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   525
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   526
	if (e_ddi_devi_holdcnt(dip)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   527
		mutex_exit(&devimap->dno_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   528
		return (DDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   529
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   530
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   531
	ASSERT(devimap->dno_head);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   532
	ASSERT(devimap->dno_list_length > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   533
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   534
	prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   535
	for (elem = devimap->dno_head; elem; elem = elem->next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   536
		if (elem->dip == dip) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   537
			ASSERT(elem->nodeid == ddi_get_nodeid(dip));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   538
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   539
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   540
		prev = elem;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   541
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   542
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   543
	if (elem && prev)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   544
		prev->next = elem->next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   545
	else if (elem)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   546
		devimap->dno_head = elem->next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   547
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   548
		panic("%s: devinfo node(%p) not found",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   549
		    fcn, (void *)dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   550
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   551
	devimap->dno_list_length--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   552
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   553
	elem->nodeid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   554
	elem->dip = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   555
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   556
	elem->next = devimap->dno_free;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   557
	devimap->dno_free = elem;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   558
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   559
	mutex_exit(&devimap->dno_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   560
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   561
	return (DDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   562
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   563
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   564
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   565
 * Link this node into the devinfo tree and add to orphan list
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   566
 * Not callable from interrupt context
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   567
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   568
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   569
link_node(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   570
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   571
	struct dev_info *devi = DEVI(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   572
	struct dev_info *parent = devi->devi_parent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   573
	dev_info_t **dipp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   574
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   575
	ASSERT(parent);	/* never called for root node */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   576
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   577
	NDI_CONFIG_DEBUG((CE_CONT, "link_node: parent = %s child = %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   578
	    parent->devi_node_name, devi->devi_node_name));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   579
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   580
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   581
	 * Hold the global_vhci_lock before linking any direct
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   582
	 * children of rootnex driver. This special lock protects
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   583
	 * linking and unlinking for rootnext direct children.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   584
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   585
	if ((dev_info_t *)parent == ddi_root_node())
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   586
		mutex_enter(&global_vhci_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   587
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   588
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   589
	 * attach the node to end of the list unless the node is already there
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   590
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   591
	dipp = (dev_info_t **)(&DEVI(parent)->devi_child);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   592
	while (*dipp && (*dipp != dip)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   593
		dipp = (dev_info_t **)(&DEVI(*dipp)->devi_sibling);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   594
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   595
	ASSERT(*dipp == NULL);	/* node is not linked */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   596
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   597
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   598
	 * Now that we are in the tree, update the devi-nodeid map.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   599
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   600
	i_ddi_add_devimap(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   601
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   602
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   603
	 * This is a temporary workaround for Bug 4618861.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   604
	 * We keep the scsi_vhci nexus node on the left side of the devinfo
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   605
	 * tree (under the root nexus driver), so that virtual nodes under
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   606
	 * scsi_vhci will be SUSPENDed first and RESUMEd last.  This ensures
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   607
	 * that the pHCI nodes are active during times when their clients
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   608
	 * may be depending on them.  This workaround embodies the knowledge
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   609
	 * that system PM and CPR both traverse the tree left-to-right during
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   610
	 * SUSPEND and right-to-left during RESUME.
1093
4dc7aec69dc9 6299476 DM Does not interoperate with TS90 switch, cannot discover SRP targets
hiremath
parents: 789
diff changeset
   611
	 * Extending the workaround to IB Nexus/VHCI
4dc7aec69dc9 6299476 DM Does not interoperate with TS90 switch, cannot discover SRP targets
hiremath
parents: 789
diff changeset
   612
	 * driver also.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   613
	 */
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   614
	if (strcmp(devi->devi_binding_name, "scsi_vhci") == 0) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   615
		/* Add scsi_vhci to beginning of list */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   616
		ASSERT((dev_info_t *)parent == top_devinfo);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   617
		/* scsi_vhci under rootnex */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   618
		devi->devi_sibling = parent->devi_child;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   619
		parent->devi_child = devi;
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   620
	} else if (strcmp(devi->devi_binding_name, "ib") == 0) {
1093
4dc7aec69dc9 6299476 DM Does not interoperate with TS90 switch, cannot discover SRP targets
hiremath
parents: 789
diff changeset
   621
		i_link_vhci_node(dip);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   622
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   623
		/* Add to end of list */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   624
		*dipp = dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   625
		DEVI(dip)->devi_sibling = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   626
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   627
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   628
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   629
	 * Release the global_vhci_lock before linking any direct
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   630
	 * children of rootnex driver.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   631
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   632
	if ((dev_info_t *)parent == ddi_root_node())
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   633
		mutex_exit(&global_vhci_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   634
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   635
	/* persistent nodes go on orphan list */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   636
	if (ndi_dev_is_persistent_node(dip))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   637
		add_to_dn_list(&orphanlist, dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   638
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   639
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   640
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   641
 * Unlink this node from the devinfo tree
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   642
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   643
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   644
unlink_node(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   645
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   646
	struct dev_info *devi = DEVI(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   647
	struct dev_info *parent = devi->devi_parent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   648
	dev_info_t **dipp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   649
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   650
	ASSERT(parent != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   651
	ASSERT(devi->devi_node_state == DS_LINKED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   652
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   653
	NDI_CONFIG_DEBUG((CE_CONT, "unlink_node: name = %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   654
	    ddi_node_name(dip)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   655
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   656
	/* check references */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   657
	if (devi->devi_ref || i_ddi_remove_devimap(dip) != DDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   658
		return (DDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   659
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   660
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   661
	 * Hold the global_vhci_lock before linking any direct
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   662
	 * children of rootnex driver.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   663
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   664
	if ((dev_info_t *)parent == ddi_root_node())
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   665
		mutex_enter(&global_vhci_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   666
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   667
	dipp = (dev_info_t **)(&DEVI(parent)->devi_child);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   668
	while (*dipp && (*dipp != dip)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   669
		dipp = (dev_info_t **)(&DEVI(*dipp)->devi_sibling);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   670
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   671
	if (*dipp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   672
		*dipp = (dev_info_t *)(devi->devi_sibling);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   673
		devi->devi_sibling = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   674
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   675
		NDI_CONFIG_DEBUG((CE_NOTE, "unlink_node: %s not linked",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   676
		    devi->devi_node_name));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   677
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   678
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   679
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   680
	 * Release the global_vhci_lock before linking any direct
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   681
	 * children of rootnex driver.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   682
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   683
	if ((dev_info_t *)parent == ddi_root_node())
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   684
		mutex_exit(&global_vhci_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   685
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   686
	/* Remove node from orphan list */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   687
	if (ndi_dev_is_persistent_node(dip)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   688
		remove_from_dn_list(&orphanlist, dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   689
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   690
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   691
	return (DDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   692
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   693
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   694
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   695
 * Bind this devinfo node to a driver. If compat is NON-NULL, try that first.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   696
 * Else, use the node-name.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   697
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   698
 * NOTE: IEEE1275 specifies that nodename should be tried before compatible.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   699
 *	Solaris implementation binds nodename after compatible.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   700
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   701
 * If we find a binding,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   702
 * - set the binding name to the the string,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   703
 * - set major number to driver major
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   704
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   705
 * If we don't find a binding,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   706
 * - return failure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   707
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   708
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   709
bind_node(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   710
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   711
	char *p = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   712
	major_t major = (major_t)(major_t)-1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   713
	struct dev_info *devi = DEVI(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   714
	dev_info_t *parent = ddi_get_parent(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   715
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   716
	ASSERT(devi->devi_node_state == DS_LINKED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   717
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   718
	NDI_CONFIG_DEBUG((CE_CONT, "bind_node: 0x%p(name = %s)\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   719
	    (void *)dip, ddi_node_name(dip)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   720
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   721
	mutex_enter(&DEVI(dip)->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   722
	if (DEVI(dip)->devi_flags & DEVI_NO_BIND) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   723
		mutex_exit(&DEVI(dip)->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   724
		return (DDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   725
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   726
	mutex_exit(&DEVI(dip)->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   727
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   728
	/* find the driver with most specific binding using compatible */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   729
	major = ddi_compatible_driver_major(dip, &p);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   730
	if (major == (major_t)-1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   731
		return (DDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   732
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   733
	devi->devi_major = major;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   734
	if (p != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   735
		i_ddi_set_binding_name(dip, p);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   736
		NDI_CONFIG_DEBUG((CE_CONT, "bind_node: %s bound to %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   737
		    devi->devi_node_name, p));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   738
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   739
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   740
	/* Link node to per-driver list */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   741
	link_to_driver_list(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   742
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   743
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   744
	 * reset parent flag so that nexus will merge .conf props
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   745
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   746
	if (ndi_dev_is_persistent_node(dip)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   747
		mutex_enter(&DEVI(parent)->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   748
		DEVI(parent)->devi_flags &=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   749
		    ~(DEVI_ATTACHED_CHILDREN|DEVI_MADE_CHILDREN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   750
		mutex_exit(&DEVI(parent)->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   751
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   752
	return (DDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   753
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   754
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   755
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   756
 * Unbind this devinfo node
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   757
 * Called before the node is destroyed or driver is removed from system
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   758
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   759
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   760
unbind_node(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   761
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   762
	ASSERT(DEVI(dip)->devi_node_state == DS_BOUND);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   763
	ASSERT(DEVI(dip)->devi_major != (major_t)-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   764
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   765
	/* check references */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   766
	if (DEVI(dip)->devi_ref)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   767
		return (DDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   768
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   769
	NDI_CONFIG_DEBUG((CE_CONT, "unbind_node: 0x%p(name = %s)\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   770
	    (void *)dip, ddi_node_name(dip)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   771
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   772
	unlink_from_driver_list(dip);
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   773
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   774
	DEVI(dip)->devi_major = (major_t)-1;
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   775
	DEVI(dip)->devi_binding_name = DEVI(dip)->devi_node_name;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   776
	return (DDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   777
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   778
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   779
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   780
 * Initialize a node: calls the parent nexus' bus_ctl ops to do the operation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   781
 * Must hold parent and per-driver list while calling this function.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   782
 * A successful init_node() returns with an active ndi_hold_devi() hold on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   783
 * the parent.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   784
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   785
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   786
init_node(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   787
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   788
	int error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   789
	dev_info_t *pdip = ddi_get_parent(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   790
	int (*f)(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, void *, void *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   791
	char *path;
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   792
	major_t	major;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   793
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   794
	ASSERT(i_ddi_node_state(dip) == DS_BOUND);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   795
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   796
	/* should be DS_READY except for pcmcia ... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   797
	ASSERT(i_ddi_node_state(pdip) >= DS_PROBED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   798
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   799
	path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   800
	(void) ddi_pathname(dip, path);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   801
	NDI_CONFIG_DEBUG((CE_CONT, "init_node: entry: path %s 0x%p\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   802
	    path, (void *)dip));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   803
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   804
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   805
	 * The parent must have a bus_ctl operation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   806
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   807
	if ((DEVI(pdip)->devi_ops->devo_bus_ops == NULL) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   808
	    (f = DEVI(pdip)->devi_ops->devo_bus_ops->bus_ctl) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   809
		error = DDI_FAILURE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   810
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   811
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   812
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   813
	add_global_props(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   814
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   815
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   816
	 * Invoke the parent's bus_ctl operation with the DDI_CTLOPS_INITCHILD
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   817
	 * command to transform the child to canonical form 1. If there
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   818
	 * is an error, ddi_remove_child should be called, to clean up.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   819
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   820
	error = (*f)(pdip, pdip, DDI_CTLOPS_INITCHILD, dip, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   821
	if (error != DDI_SUCCESS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   822
		NDI_CONFIG_DEBUG((CE_CONT, "init_node: %s 0x%p failed\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   823
		    path, (void *)dip));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   824
		remove_global_props(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   825
		/* in case nexus driver didn't clear this field */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   826
		ddi_set_name_addr(dip, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   827
		error = DDI_FAILURE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   828
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   829
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   830
4950
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
   831
	ndi_hold_devi(pdip);			/* initial hold of parent */
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   832
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   833
	/* recompute path after initchild for @addr information */
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   834
	(void) ddi_pathname(dip, path);
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   835
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   836
	/* Check for duplicate nodes */
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   837
	if (find_duplicate_child(pdip, dip) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   838
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   839
		 * uninit_node() the duplicate - a successful uninit_node()
4950
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
   840
		 * will release inital hold of parent using ndi_rele_devi().
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   841
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   842
		if ((error = uninit_node(dip)) != DDI_SUCCESS) {
4950
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
   843
			ndi_rele_devi(pdip);	/* release initial hold */
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   844
			cmn_err(CE_WARN, "init_node: uninit of duplicate "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   845
			    "node %s failed", path);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   846
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   847
		NDI_CONFIG_DEBUG((CE_CONT, "init_node: duplicate uninit "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   848
		    "%s 0x%p%s\n", path, (void *)dip,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   849
		    (error == DDI_SUCCESS) ? "" : " failed"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   850
		error = DDI_FAILURE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   851
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   852
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   853
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   854
	/*
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   855
	 * Check to see if we have a path-oriented driver alias that overrides
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   856
	 * the current driver binding. If so, we need to rebind. This check
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   857
	 * needs to be delayed until after a successful DDI_CTLOPS_INITCHILD,
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   858
	 * so the unit-address is established on the last component of the path.
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   859
	 *
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   860
	 * NOTE: Allowing a path-oriented alias to change the driver binding
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   861
	 * of a driver.conf node results in non-intuitive property behavior.
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   862
	 * We provide a tunable (driver_conf_allow_path_alias) to control
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   863
	 * this behavior. See uninit_node() for more details.
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   864
	 *
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   865
	 * NOTE: If you are adding a path-oriented alias for the boot device,
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   866
	 * and there is mismatch between OBP and the kernel in regard to
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   867
	 * generic name use, like "disk" .vs. "ssd", then you will need
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   868
	 * to add a path-oriented alias for both paths.
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   869
	 */
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   870
	major = ddi_name_to_major(path);
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   871
	if ((major != (major_t)-1) &&
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   872
	    !(devnamesp[major].dn_flags & DN_DRIVER_REMOVED) &&
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   873
	    (major != DEVI(dip)->devi_major) &&
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   874
	    (ndi_dev_is_persistent_node(dip) || driver_conf_allow_path_alias)) {
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   875
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   876
		/* Mark node for rebind processing. */
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   877
		mutex_enter(&DEVI(dip)->devi_lock);
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   878
		DEVI(dip)->devi_flags |= DEVI_REBIND;
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   879
		mutex_exit(&DEVI(dip)->devi_lock);
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   880
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   881
		/*
4950
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
   882
		 * Add an extra hold on the parent to prevent it from ever
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
   883
		 * having a zero devi_ref during the child rebind process.
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
   884
		 * This is necessary to ensure that the parent will never
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
   885
		 * detach(9E) during the rebind.
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
   886
		 */
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
   887
		ndi_hold_devi(pdip);		/* extra hold of parent */
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
   888
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
   889
		/*
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   890
		 * uninit_node() current binding - a successful uninit_node()
4950
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
   891
		 * will release extra hold of parent using ndi_rele_devi().
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   892
		 */
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   893
		if ((error = uninit_node(dip)) != DDI_SUCCESS) {
4950
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
   894
			ndi_rele_devi(pdip);	/* release extra hold */
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
   895
			ndi_rele_devi(pdip);	/* release initial hold */
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   896
			cmn_err(CE_WARN, "init_node: uninit for rebind "
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   897
			    "of node %s failed", path);
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   898
			goto out;
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   899
		}
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   900
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   901
		/* Unbind: demote the node back to DS_LINKED.  */
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   902
		if ((error = ndi_devi_unbind_driver(dip)) != DDI_SUCCESS) {
4950
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
   903
			ndi_rele_devi(pdip);	/* relrease initial hold */
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   904
			cmn_err(CE_WARN, "init_node: unbind for rebind "
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   905
			    "of node %s failed", path);
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   906
			goto out;
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   907
		}
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   908
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   909
		/* establish rebinding name */
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   910
		if (DEVI(dip)->devi_rebinding_name == NULL)
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   911
			DEVI(dip)->devi_rebinding_name =
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   912
			    i_ddi_strdup(path, KM_SLEEP);
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   913
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   914
		/*
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   915
		 * Now that we are demoted and marked for rebind, repromote.
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   916
		 * We need to do this in steps, instead of just calling
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   917
		 * ddi_initchild, so that we can redo the merge operation
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   918
		 * after we are rebound to the path-bound driver.
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   919
		 *
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   920
		 * Start by rebinding node to the path-bound driver.
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   921
		 */
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   922
		if ((error = ndi_devi_bind_driver(dip, 0)) != DDI_SUCCESS) {
4950
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
   923
			ndi_rele_devi(pdip);	/* relrease initial hold */
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   924
			cmn_err(CE_WARN, "init_node: rebind "
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   925
			    "of node %s failed", path);
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   926
			goto out;
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   927
		}
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   928
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   929
		/*
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   930
		 * If the node is not a driver.conf node then merge
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   931
		 * driver.conf properties from new path-bound driver.conf.
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   932
		 */
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   933
		if (ndi_dev_is_persistent_node(dip))
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   934
			(void) i_ndi_make_spec_children(pdip, 0);
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   935
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   936
		/*
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   937
		 * Now that we have taken care of merge, repromote back
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   938
		 * to DS_INITIALIZED.
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   939
		 */
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   940
		error = ddi_initchild(pdip, dip);
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   941
		NDI_CONFIG_DEBUG((CE_CONT, "init_node: rebind "
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   942
		    "%s 0x%p\n", path, (void *)dip));
4950
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
   943
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
   944
		/*
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
   945
		 * Release our initial hold. If ddi_initchild() was
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
   946
		 * successfull then it will return with the active hold.
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
   947
		 */
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
   948
		ndi_rele_devi(pdip);
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   949
		goto out;
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   950
	}
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   951
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   952
	/*
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   953
	 * Apply multi-parent/deep-nexus optimization to the new node
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   954
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   955
	DEVI(dip)->devi_instance = e_ddi_assign_instance(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   956
	ddi_optimize_dtree(dip);
4950
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
   957
	error = DDI_SUCCESS;		/* return with active hold */
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   958
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   959
out:	if (error != DDI_SUCCESS) {
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   960
		/* On failure ensure that DEVI_REBIND is cleared */
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   961
		mutex_enter(&DEVI(dip)->devi_lock);
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   962
		DEVI(dip)->devi_flags &= ~DEVI_REBIND;
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   963
		mutex_exit(&DEVI(dip)->devi_lock);
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   964
	}
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
   965
	kmem_free(path, MAXPATHLEN);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   966
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   967
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   968
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   969
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   970
 * Uninitialize node
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   971
 * The per-driver list must be held busy during the call.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   972
 * A successful uninit_node() releases the init_node() hold on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   973
 * the parent by calling ndi_rele_devi().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   974
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   975
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   976
uninit_node(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   977
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   978
	int node_state_entry;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   979
	dev_info_t *pdip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   980
	struct dev_ops *ops;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   981
	int (*f)();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   982
	int error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   983
	char *addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   984
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   985
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   986
	 * Don't check for references here or else a ref-counted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   987
	 * dip cannot be downgraded by the framework.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   988
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   989
	node_state_entry = i_ddi_node_state(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   990
	ASSERT((node_state_entry == DS_BOUND) ||
4950
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
   991
	    (node_state_entry == DS_INITIALIZED));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   992
	pdip = ddi_get_parent(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   993
	ASSERT(pdip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   994
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   995
	NDI_CONFIG_DEBUG((CE_CONT, "uninit_node: 0x%p(%s%d)\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   996
	    (void *)dip, ddi_driver_name(dip), ddi_get_instance(dip)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   997
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   998
	if (((ops = ddi_get_driver(pdip)) == NULL) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   999
	    (ops->devo_bus_ops == NULL) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1000
	    ((f = ops->devo_bus_ops->bus_ctl) == NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1001
		return (DDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1002
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1003
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1004
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1005
	 * save the @addr prior to DDI_CTLOPS_UNINITCHILD for use in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1006
	 * freeing the instance if it succeeds.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1007
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1008
	if (node_state_entry == DS_INITIALIZED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1009
		addr = ddi_get_name_addr(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1010
		if (addr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1011
			addr = i_ddi_strdup(addr, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1012
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1013
		addr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1014
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1015
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1016
	error = (*f)(pdip, pdip, DDI_CTLOPS_UNINITCHILD, dip, (void *)NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1017
	if (error == DDI_SUCCESS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1018
		/* if uninitchild forgot to set devi_addr to NULL do it now */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1019
		ddi_set_name_addr(dip, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1020
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1021
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1022
		 * Free instance number. This is a no-op if instance has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1023
		 * been kept by probe_node().  Avoid free when we are called
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1024
		 * from init_node (DS_BOUND) because the instance has not yet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1025
		 * been assigned.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1026
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1027
		if (node_state_entry == DS_INITIALIZED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1028
			e_ddi_free_instance(dip, addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1029
			DEVI(dip)->devi_instance = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1030
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1031
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1032
		/* release the init_node hold */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1033
		ndi_rele_devi(pdip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1034
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1035
		remove_global_props(dip);
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  1036
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  1037
		/*
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  1038
		 * NOTE: The decision on whether to allow a path-oriented
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  1039
		 * rebind of a driver.conf enumerated node is made by
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  1040
		 * init_node() based on driver_conf_allow_path_alias. The
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  1041
		 * rebind code below prevents deletion of system properties
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  1042
		 * on driver.conf nodes.
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  1043
		 *
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  1044
		 * When driver_conf_allow_path_alias is set, property behavior
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  1045
		 * on rebound driver.conf file is non-intuitive. For a
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  1046
		 * driver.conf node, the unit-address properties come from
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  1047
		 * the driver.conf file as system properties. Removing system
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  1048
		 * properties from a driver.conf node makes the node
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  1049
		 * useless (we get node without unit-address properties) - so
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  1050
		 * we leave system properties in place. The result is a node
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  1051
		 * where system properties come from the node being rebound,
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  1052
		 * and global properties come from the driver.conf file
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  1053
		 * of the driver we are rebinding to.  If we could determine
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  1054
		 * that the path-oriented alias driver.conf file defined a
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  1055
		 * node at the same unit address, it would be best to use
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  1056
		 * that node and avoid the non-intuitive property behavior.
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  1057
		 * Unfortunately, the current "merge" code does not support
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  1058
		 * this, so we live with the non-intuitive property behavior.
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  1059
		 */
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  1060
		if (!((ndi_dev_is_persistent_node(dip) == 0) &&
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  1061
		    (DEVI(dip)->devi_flags & DEVI_REBIND)))
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  1062
			e_ddi_prop_remove_all(dip);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1063
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1064
		NDI_CONFIG_DEBUG((CE_CONT, "uninit_node failed: 0x%p(%s%d)\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1065
		    (void *)dip, ddi_driver_name(dip), ddi_get_instance(dip)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1066
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1067
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1068
	if (addr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1069
		kmem_free(addr, strlen(addr) + 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1070
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1071
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1072
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1073
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1074
 * Invoke driver's probe entry point to probe for existence of hardware.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1075
 * Keep instance permanent for successful probe and leaf nodes.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1076
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1077
 * Per-driver list must be held busy while calling this function.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1078
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1079
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1080
probe_node(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1081
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1082
	int rv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1083
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1084
	ASSERT(i_ddi_node_state(dip) == DS_INITIALIZED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1085
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1086
	NDI_CONFIG_DEBUG((CE_CONT, "probe_node: 0x%p(%s%d)\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1087
	    (void *)dip, ddi_driver_name(dip), ddi_get_instance(dip)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1088
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1089
	/* temporarily hold the driver while we probe */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1090
	DEVI(dip)->devi_ops = ndi_hold_driver(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1091
	if (DEVI(dip)->devi_ops == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1092
		NDI_CONFIG_DEBUG((CE_CONT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1093
		    "probe_node: 0x%p(%s%d) cannot load driver\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1094
		    (void *)dip, ddi_driver_name(dip), ddi_get_instance(dip)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1095
		return (DDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1096
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1097
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1098
	if (identify_9e != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1099
		(void) devi_identify(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1100
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1101
	rv = devi_probe(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1102
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1103
	/* release the driver now that probe is complete */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1104
	ndi_rele_driver(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1105
	DEVI(dip)->devi_ops = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1106
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1107
	switch (rv) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1108
	case DDI_PROBE_SUCCESS:			/* found */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1109
	case DDI_PROBE_DONTCARE:		/* ddi_dev_is_sid */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1110
		e_ddi_keep_instance(dip);	/* persist instance */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1111
		rv = DDI_SUCCESS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1112
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1113
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1114
	case DDI_PROBE_PARTIAL:			/* maybe later */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1115
	case DDI_PROBE_FAILURE:			/* not found */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1116
		NDI_CONFIG_DEBUG((CE_CONT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1117
		    "probe_node: 0x%p(%s%d) no hardware found%s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1118
		    (void *)dip, ddi_driver_name(dip), ddi_get_instance(dip),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1119
		    (rv == DDI_PROBE_PARTIAL) ? " yet" : ""));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1120
		rv = DDI_FAILURE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1121
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1122
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1123
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1124
#ifdef	DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1125
		cmn_err(CE_WARN, "probe_node: %s%d: illegal probe(9E) value",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1126
		    ddi_driver_name(dip), ddi_get_instance(dip));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1127
#endif	/* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1128
		rv = DDI_FAILURE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1129
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1130
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1131
	return (rv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1132
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1133
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1134
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1135
 * Unprobe a node. Simply reset the node state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1136
 * Per-driver list must be held busy while calling this function.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1137
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1138
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1139
unprobe_node(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1140
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1141
	ASSERT(i_ddi_node_state(dip) == DS_PROBED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1142
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1143
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1144
	 * Don't check for references here or else a ref-counted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1145
	 * dip cannot be downgraded by the framework.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1146
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1147
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1148
	NDI_CONFIG_DEBUG((CE_CONT, "unprobe_node: 0x%p(name = %s)\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1149
	    (void *)dip, ddi_node_name(dip)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1150
	return (DDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1151
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1152
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1153
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1154
 * Attach devinfo node.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1155
 * Per-driver list must be held busy.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1156
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1157
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1158
attach_node(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1159
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1160
	int rv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1161
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1162
	ASSERT(DEVI_BUSY_OWNED(ddi_get_parent(dip)));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1163
	ASSERT(i_ddi_node_state(dip) == DS_PROBED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1164
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1165
	NDI_CONFIG_DEBUG((CE_CONT, "attach_node: 0x%p(%s%d)\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1166
	    (void *)dip, ddi_driver_name(dip), ddi_get_instance(dip)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1167
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1168
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1169
	 * Tell mpxio framework that a node is about to online.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1170
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1171
	if ((rv = mdi_devi_online(dip, 0)) != NDI_SUCCESS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1172
		return (DDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1173
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1174
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1175
	/* no recursive attachment */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1176
	ASSERT(DEVI(dip)->devi_ops == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1177
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1178
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1179
	 * Hold driver the node is bound to.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1180
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1181
	DEVI(dip)->devi_ops = ndi_hold_driver(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1182
	if (DEVI(dip)->devi_ops == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1183
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1184
		 * We were able to load driver for probing, so we should
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1185
		 * not get here unless something really bad happened.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1186
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1187
		cmn_err(CE_WARN, "attach_node: no driver for major %d",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1188
		    DEVI(dip)->devi_major);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1189
		return (DDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1190
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1191
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1192
	if (NEXUS_DRV(DEVI(dip)->devi_ops))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1193
		DEVI(dip)->devi_taskq = ddi_taskq_create(dip,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1194
		    "nexus_enum_tq", 1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1195
		    TASKQ_DEFAULTPRI, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1196
495
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  1197
	mutex_enter(&(DEVI(dip)->devi_lock));
2009
b1f98dc679ae Backout 6423041, 6426345; exposes deadlock
dm120769
parents: 1961
diff changeset
  1198
	DEVI_SET_ATTACHING(dip);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1199
	DEVI_SET_NEED_RESET(dip);
495
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  1200
	mutex_exit(&(DEVI(dip)->devi_lock));
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  1201
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1202
	rv = devi_attach(dip, DDI_ATTACH);
495
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  1203
2009
b1f98dc679ae Backout 6423041, 6426345; exposes deadlock
dm120769
parents: 1961
diff changeset
  1204
	mutex_enter(&(DEVI(dip)->devi_lock));
b1f98dc679ae Backout 6423041, 6426345; exposes deadlock
dm120769
parents: 1961
diff changeset
  1205
	DEVI_CLR_ATTACHING(dip);
b1f98dc679ae Backout 6423041, 6426345; exposes deadlock
dm120769
parents: 1961
diff changeset
  1206
1961
cceb6bfa61a5 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 1826
diff changeset
  1207
	if (rv != DDI_SUCCESS) {
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1208
		DEVI_CLR_NEED_RESET(dip);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1209
438
221f0e038fcc 6305386 detach_node() should not hold devi_lock across call to e_devid_cache_unregister()
cth
parents: 298
diff changeset
  1210
		/* ensure that devids are unregistered */
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1211
		if (DEVI(dip)->devi_flags & DEVI_REGISTERED_DEVID) {
438
221f0e038fcc 6305386 detach_node() should not hold devi_lock across call to e_devid_cache_unregister()
cth
parents: 298
diff changeset
  1212
			DEVI(dip)->devi_flags &= ~DEVI_REGISTERED_DEVID;
221f0e038fcc 6305386 detach_node() should not hold devi_lock across call to e_devid_cache_unregister()
cth
parents: 298
diff changeset
  1213
			mutex_exit(&DEVI(dip)->devi_lock);
221f0e038fcc 6305386 detach_node() should not hold devi_lock across call to e_devid_cache_unregister()
cth
parents: 298
diff changeset
  1214
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1215
			e_devid_cache_unregister(dip);
438
221f0e038fcc 6305386 detach_node() should not hold devi_lock across call to e_devid_cache_unregister()
cth
parents: 298
diff changeset
  1216
		} else
221f0e038fcc 6305386 detach_node() should not hold devi_lock across call to e_devid_cache_unregister()
cth
parents: 298
diff changeset
  1217
			mutex_exit(&DEVI(dip)->devi_lock);
221f0e038fcc 6305386 detach_node() should not hold devi_lock across call to e_devid_cache_unregister()
cth
parents: 298
diff changeset
  1218
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1219
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1220
		 * Cleanup dacf reservations
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1221
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1222
		mutex_enter(&dacf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1223
		dacf_clr_rsrvs(dip, DACF_OPID_POSTATTACH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1224
		dacf_clr_rsrvs(dip, DACF_OPID_PREDETACH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1225
		mutex_exit(&dacf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1226
		if (DEVI(dip)->devi_taskq)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1227
			ddi_taskq_destroy(DEVI(dip)->devi_taskq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1228
		ddi_remove_minor_node(dip, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1229
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1230
		/* release the driver if attach failed */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1231
		ndi_rele_driver(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1232
		DEVI(dip)->devi_ops = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1233
		NDI_CONFIG_DEBUG((CE_CONT, "attach_node: 0x%p(%s%d) failed\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1234
		    (void *)dip, ddi_driver_name(dip), ddi_get_instance(dip)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1235
		return (DDI_FAILURE);
2009
b1f98dc679ae Backout 6423041, 6426345; exposes deadlock
dm120769
parents: 1961
diff changeset
  1236
	} else
b1f98dc679ae Backout 6423041, 6426345; exposes deadlock
dm120769
parents: 1961
diff changeset
  1237
		mutex_exit(&DEVI(dip)->devi_lock);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1238
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1239
	/* successful attach, return with driver held */
495
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  1240
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1241
	return (DDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1242
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1243
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1244
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1245
 * Detach devinfo node.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1246
 * Per-driver list must be held busy.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1247
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1248
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1249
detach_node(dev_info_t *dip, uint_t flag)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1250
{
53
0b88e5a15258 6259385 qassociate() should drive attach
cth
parents: 0
diff changeset
  1251
	struct devnames	*dnp;
0b88e5a15258 6259385 qassociate() should drive attach
cth
parents: 0
diff changeset
  1252
	int		rv;
0b88e5a15258 6259385 qassociate() should drive attach
cth
parents: 0
diff changeset
  1253
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1254
	ASSERT(DEVI_BUSY_OWNED(ddi_get_parent(dip)));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1255
	ASSERT(i_ddi_node_state(dip) == DS_ATTACHED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1256
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1257
	/* check references */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1258
	if (DEVI(dip)->devi_ref)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1259
		return (DDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1260
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1261
	NDI_CONFIG_DEBUG((CE_CONT, "detach_node: 0x%p(%s%d)\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1262
	    (void *)dip, ddi_driver_name(dip), ddi_get_instance(dip)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1263
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1264
	/*
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1265
	 * NOTE: If we are processing a pHCI node then the calling code
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1266
	 * must detect this and ndi_devi_enter() in (vHCI, parent(pHCI))
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1267
	 * order unless pHCI and vHCI are siblings.  Code paths leading
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1268
	 * here that must ensure this ordering include:
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1269
	 * unconfig_immediate_children(), devi_unconfig_one(),
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1270
	 * ndi_devi_unconfig_one(), ndi_devi_offline().
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1271
	 */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1272
	ASSERT(!MDI_PHCI(dip) ||
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1273
	    (ddi_get_parent(mdi_devi_get_vdip(dip)) == ddi_get_parent(dip)) ||
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1274
	    DEVI_BUSY_OWNED(mdi_devi_get_vdip(dip)));
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1275
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1276
	/* Offline the device node with the mpxio framework. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1277
	if (mdi_devi_offline(dip, flag) != NDI_SUCCESS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1278
		return (DDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1279
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1280
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1281
	/* drain the taskq */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1282
	if (DEVI(dip)->devi_taskq)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1283
		ddi_taskq_wait(DEVI(dip)->devi_taskq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1284
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1285
	rv = devi_detach(dip, DDI_DETACH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1286
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1287
	if (rv != DDI_SUCCESS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1288
		NDI_CONFIG_DEBUG((CE_CONT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1289
		    "detach_node: 0x%p(%s%d) failed\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1290
		    (void *)dip, ddi_driver_name(dip), ddi_get_instance(dip)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1291
		return (DDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1292
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1293
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1294
	mutex_enter(&(DEVI(dip)->devi_lock));
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1295
	DEVI_CLR_NEED_RESET(dip);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1296
	mutex_exit(&(DEVI(dip)->devi_lock));
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1297
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1298
	/* destroy the taskq */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1299
	if (DEVI(dip)->devi_taskq) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1300
		ddi_taskq_destroy(DEVI(dip)->devi_taskq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1301
		DEVI(dip)->devi_taskq = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1302
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1303
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1304
	/* Cleanup dacf reservations */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1305
	mutex_enter(&dacf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1306
	dacf_clr_rsrvs(dip, DACF_OPID_POSTATTACH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1307
	dacf_clr_rsrvs(dip, DACF_OPID_PREDETACH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1308
	mutex_exit(&dacf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1309
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1310
	/* Remove properties and minor nodes in case driver forgots */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1311
	ddi_remove_minor_node(dip, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1312
	ddi_prop_remove_all(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1313
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1314
	/* a detached node can't have attached or .conf children */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1315
	mutex_enter(&DEVI(dip)->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1316
	DEVI(dip)->devi_flags &= ~(DEVI_MADE_CHILDREN|DEVI_ATTACHED_CHILDREN);
438
221f0e038fcc 6305386 detach_node() should not hold devi_lock across call to e_devid_cache_unregister()
cth
parents: 298
diff changeset
  1317
221f0e038fcc 6305386 detach_node() should not hold devi_lock across call to e_devid_cache_unregister()
cth
parents: 298
diff changeset
  1318
	/* ensure that devids registered during attach are unregistered */
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1319
	if (DEVI(dip)->devi_flags & DEVI_REGISTERED_DEVID) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1320
		DEVI(dip)->devi_flags &= ~DEVI_REGISTERED_DEVID;
438
221f0e038fcc 6305386 detach_node() should not hold devi_lock across call to e_devid_cache_unregister()
cth
parents: 298
diff changeset
  1321
		mutex_exit(&DEVI(dip)->devi_lock);
221f0e038fcc 6305386 detach_node() should not hold devi_lock across call to e_devid_cache_unregister()
cth
parents: 298
diff changeset
  1322
221f0e038fcc 6305386 detach_node() should not hold devi_lock across call to e_devid_cache_unregister()
cth
parents: 298
diff changeset
  1323
		e_devid_cache_unregister(dip);
221f0e038fcc 6305386 detach_node() should not hold devi_lock across call to e_devid_cache_unregister()
cth
parents: 298
diff changeset
  1324
	} else
221f0e038fcc 6305386 detach_node() should not hold devi_lock across call to e_devid_cache_unregister()
cth
parents: 298
diff changeset
  1325
		mutex_exit(&DEVI(dip)->devi_lock);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1326
53
0b88e5a15258 6259385 qassociate() should drive attach
cth
parents: 0
diff changeset
  1327
	/*
0b88e5a15258 6259385 qassociate() should drive attach
cth
parents: 0
diff changeset
  1328
	 * If the instance has successfully detached in detach_driver() context,
0b88e5a15258 6259385 qassociate() should drive attach
cth
parents: 0
diff changeset
  1329
	 * clear DN_DRIVER_HELD for correct ddi_hold_installed_driver()
0b88e5a15258 6259385 qassociate() should drive attach
cth
parents: 0
diff changeset
  1330
	 * behavior. Consumers like qassociate() depend on this (via clnopen()).
0b88e5a15258 6259385 qassociate() should drive attach
cth
parents: 0
diff changeset
  1331
	 */
0b88e5a15258 6259385 qassociate() should drive attach
cth
parents: 0
diff changeset
  1332
	if (flag & NDI_DETACH_DRIVER) {
0b88e5a15258 6259385 qassociate() should drive attach
cth
parents: 0
diff changeset
  1333
		dnp = &(devnamesp[DEVI(dip)->devi_major]);
0b88e5a15258 6259385 qassociate() should drive attach
cth
parents: 0
diff changeset
  1334
		LOCK_DEV_OPS(&dnp->dn_lock);
0b88e5a15258 6259385 qassociate() should drive attach
cth
parents: 0
diff changeset
  1335
		dnp->dn_flags &= ~DN_DRIVER_HELD;
0b88e5a15258 6259385 qassociate() should drive attach
cth
parents: 0
diff changeset
  1336
		UNLOCK_DEV_OPS(&dnp->dn_lock);
0b88e5a15258 6259385 qassociate() should drive attach
cth
parents: 0
diff changeset
  1337
	}
0b88e5a15258 6259385 qassociate() should drive attach
cth
parents: 0
diff changeset
  1338
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1339
	/* successful detach, release the driver */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1340
	ndi_rele_driver(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1341
	DEVI(dip)->devi_ops = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1342
	return (DDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1343
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1344
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1345
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1346
 * Run dacf post_attach routines
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1347
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1348
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1349
postattach_node(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1350
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1351
	int rval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1352
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1353
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1354
	 * For hotplug busses like USB, it's possible that devices
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1355
	 * are removed but dip is still around. We don't want to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1356
	 * run dacf routines as part of detach failure recovery.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1357
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1358
	 * Pretend success until we figure out how to prevent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1359
	 * access to such devinfo nodes.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1360
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1361
	if (DEVI_IS_DEVICE_REMOVED(dip))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1362
		return (DDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1363
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1364
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1365
	 * if dacf_postattach failed, report it to the framework
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1366
	 * so that it can be retried later at the open time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1367
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1368
	mutex_enter(&dacf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1369
	rval = dacfc_postattach(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1370
	mutex_exit(&dacf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1371
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1372
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1373
	 * Plumbing during postattach may fail because of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1374
	 * underlying device is not ready. This will fail ndi_devi_config()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1375
	 * in dv_filldir() and a warning message is issued. The message
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1376
	 * from here will explain what happened
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1377
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1378
	if (rval != DACF_SUCCESS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1379
		cmn_err(CE_WARN, "Postattach failed for %s%d\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1380
		    ddi_driver_name(dip), ddi_get_instance(dip));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1381
		return (DDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1382
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1383
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1384
	return (DDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1385
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1386
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1387
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1388
 * Run dacf pre-detach routines
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1389
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1390
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1391
predetach_node(dev_info_t *dip, uint_t flag)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1392
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1393
	int ret;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1394
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1395
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1396
	 * Don't auto-detach if DDI_FORCEATTACH or DDI_NO_AUTODETACH
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1397
	 * properties are set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1398
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1399
	if (flag & NDI_AUTODETACH) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1400
		struct devnames *dnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1401
		int pflag = DDI_PROP_NOTPROM | DDI_PROP_DONTPASS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1402
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1403
		if ((ddi_prop_get_int(DDI_DEV_T_ANY, dip,
4950
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
  1404
		    pflag, DDI_FORCEATTACH, 0) == 1) ||
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1405
		    (ddi_prop_get_int(DDI_DEV_T_ANY, dip,
4950
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
  1406
		    pflag, DDI_NO_AUTODETACH, 0) == 1))
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1407
			return (DDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1408
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1409
		/* check for driver global version of DDI_NO_AUTODETACH */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1410
		dnp = &devnamesp[DEVI(dip)->devi_major];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1411
		LOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1412
		if (dnp->dn_flags & DN_NO_AUTODETACH) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1413
			UNLOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1414
			return (DDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1415
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1416
		UNLOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1417
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1418
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1419
	mutex_enter(&dacf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1420
	ret = dacfc_predetach(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1421
	mutex_exit(&dacf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1422
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1423
	return (ret);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1424
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1425
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1426
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1427
 * Wrapper for making multiple state transitions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1428
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1429
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1430
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1431
 * i_ndi_config_node: upgrade dev_info node into a specified state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1432
 * It is a bit tricky because the locking protocol changes before and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1433
 * after a node is bound to a driver. All locks are held external to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1434
 * this function.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1435
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1436
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1437
i_ndi_config_node(dev_info_t *dip, ddi_node_state_t state, uint_t flag)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1438
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1439
	_NOTE(ARGUNUSED(flag))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1440
	int rv = DDI_SUCCESS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1441
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1442
	ASSERT(DEVI_BUSY_OWNED(ddi_get_parent(dip)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1443
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1444
	while ((i_ddi_node_state(dip) < state) && (rv == DDI_SUCCESS)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1445
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1446
		/* don't allow any more changes to the device tree */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1447
		if (devinfo_freeze) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1448
			rv = DDI_FAILURE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1449
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1450
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1451
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1452
		switch (i_ddi_node_state(dip)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1453
		case DS_PROTO:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1454
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1455
			 * only caller can reference this node, no external
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1456
			 * locking needed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1457
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1458
			link_node(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1459
			i_ddi_set_node_state(dip, DS_LINKED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1460
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1461
		case DS_LINKED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1462
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1463
			 * Three code path may attempt to bind a node:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1464
			 * - boot code
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1465
			 * - add_drv
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1466
			 * - hotplug thread
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1467
			 * Boot code is single threaded, add_drv synchronize
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1468
			 * on a userland lock, and hotplug synchronize on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1469
			 * hotplug_lk. There could be a race between add_drv
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1470
			 * and hotplug thread. We'll live with this until the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1471
			 * conversion to top-down loading.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1472
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1473
			if ((rv = bind_node(dip)) == DDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1474
				i_ddi_set_node_state(dip, DS_BOUND);
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  1475
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1476
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1477
		case DS_BOUND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1478
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1479
			 * The following transitions synchronizes on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1480
			 * per-driver busy changing flag, since we already
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1481
			 * have a driver.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1482
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1483
			if ((rv = init_node(dip)) == DDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1484
				i_ddi_set_node_state(dip, DS_INITIALIZED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1485
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1486
		case DS_INITIALIZED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1487
			if ((rv = probe_node(dip)) == DDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1488
				i_ddi_set_node_state(dip, DS_PROBED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1489
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1490
		case DS_PROBED:
4845
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  1491
			i_ddi_check_retire(dip);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1492
			atomic_add_long(&devinfo_attach_detach, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1493
			if ((rv = attach_node(dip)) == DDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1494
				i_ddi_set_node_state(dip, DS_ATTACHED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1495
			atomic_add_long(&devinfo_attach_detach, -1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1496
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1497
		case DS_ATTACHED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1498
			if ((rv = postattach_node(dip)) == DDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1499
				i_ddi_set_node_state(dip, DS_READY);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1500
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1501
		case DS_READY:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1502
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1503
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1504
			/* should never reach here */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1505
			ASSERT("unknown devinfo state");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1506
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1507
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1508
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1509
	if (ddidebug & DDI_AUDIT)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1510
		da_log_enter(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1511
	return (rv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1512
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1513
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1514
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1515
 * i_ndi_unconfig_node: downgrade dev_info node into a specified state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1516
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1517
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1518
i_ndi_unconfig_node(dev_info_t *dip, ddi_node_state_t state, uint_t flag)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1519
{
4950
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
  1520
	int	rv = DDI_SUCCESS;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1521
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1522
	ASSERT(DEVI_BUSY_OWNED(ddi_get_parent(dip)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1523
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1524
	while ((i_ddi_node_state(dip) > state) && (rv == DDI_SUCCESS)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1525
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1526
		/* don't allow any more changes to the device tree */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1527
		if (devinfo_freeze) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1528
			rv = DDI_FAILURE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1529
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1530
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1531
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1532
		switch (i_ddi_node_state(dip)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1533
		case DS_PROTO:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1534
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1535
		case DS_LINKED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1536
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1537
			 * Persistent nodes are only removed by hotplug code
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1538
			 * .conf nodes synchronizes on per-driver list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1539
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1540
			if ((rv = unlink_node(dip)) == DDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1541
				i_ddi_set_node_state(dip, DS_PROTO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1542
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1543
		case DS_BOUND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1544
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1545
			 * The following transitions synchronizes on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1546
			 * per-driver busy changing flag, since we already
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1547
			 * have a driver.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1548
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1549
			if ((rv = unbind_node(dip)) == DDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1550
				i_ddi_set_node_state(dip, DS_LINKED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1551
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1552
		case DS_INITIALIZED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1553
			if ((rv = uninit_node(dip)) == DDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1554
				i_ddi_set_node_state(dip, DS_BOUND);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1555
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1556
		case DS_PROBED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1557
			if ((rv = unprobe_node(dip)) == DDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1558
				i_ddi_set_node_state(dip, DS_INITIALIZED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1559
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1560
		case DS_ATTACHED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1561
			atomic_add_long(&devinfo_attach_detach, 1);
495
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  1562
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  1563
			mutex_enter(&(DEVI(dip)->devi_lock));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1564
			DEVI_SET_DETACHING(dip);
495
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  1565
			mutex_exit(&(DEVI(dip)->devi_lock));
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  1566
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1567
			membar_enter();	/* ensure visibility for hold_devi */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1568
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1569
			if ((rv = detach_node(dip, flag)) == DDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1570
				i_ddi_set_node_state(dip, DS_PROBED);
495
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  1571
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  1572
			mutex_enter(&(DEVI(dip)->devi_lock));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1573
			DEVI_CLR_DETACHING(dip);
495
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  1574
			mutex_exit(&(DEVI(dip)->devi_lock));
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  1575
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1576
			atomic_add_long(&devinfo_attach_detach, -1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1577
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1578
		case DS_READY:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1579
			if ((rv = predetach_node(dip, flag)) == DDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1580
				i_ddi_set_node_state(dip, DS_ATTACHED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1581
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1582
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1583
			ASSERT("unknown devinfo state");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1584
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1585
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1586
	da_log_enter(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1587
	return (rv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1588
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1589
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1590
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1591
 * ddi_initchild: transform node to DS_INITIALIZED state
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1592
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1593
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1594
ddi_initchild(dev_info_t *parent, dev_info_t *proto)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1595
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1596
	int ret, circ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1597
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1598
	ndi_devi_enter(parent, &circ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1599
	ret = i_ndi_config_node(proto, DS_INITIALIZED, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1600
	ndi_devi_exit(parent, circ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1601
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1602
	return (ret);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1603
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1604
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1605
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1606
 * ddi_uninitchild: transform node down to DS_BOUND state
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1607
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1608
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1609
ddi_uninitchild(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1610
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1611
	int ret, circ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1612
	dev_info_t *parent = ddi_get_parent(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1613
	ASSERT(parent);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1614
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1615
	ndi_devi_enter(parent, &circ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1616
	ret = i_ndi_unconfig_node(dip, DS_BOUND, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1617
	ndi_devi_exit(parent, circ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1618
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1619
	return (ret);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1620
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1621
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1622
/*
1333
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  1623
 * i_ddi_attachchild: transform node to DS_READY/i_ddi_devi_attached() state
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1624
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1625
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1626
i_ddi_attachchild(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1627
{
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1628
	dev_info_t	*parent = ddi_get_parent(dip);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1629
	int		ret;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1630
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1631
	ASSERT(parent && DEVI_BUSY_OWNED(parent));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1632
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1633
	if ((i_ddi_node_state(dip) < DS_BOUND) || DEVI_IS_DEVICE_OFFLINE(dip))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1634
		return (DDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1635
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1636
	ret = i_ndi_config_node(dip, DS_READY, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1637
	if (ret == NDI_SUCCESS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1638
		ret = DDI_SUCCESS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1639
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1640
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1641
		 * Take it down to DS_INITIALIZED so pm_pre_probe is run
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1642
		 * on the next attach
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1643
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1644
		(void) i_ndi_unconfig_node(dip, DS_INITIALIZED, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1645
		ret = DDI_FAILURE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1646
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1647
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1648
	return (ret);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1649
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1650
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1651
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1652
 * i_ddi_detachchild: transform node down to DS_PROBED state
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1653
 *	If it fails, put it back to DS_READY state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1654
 * NOTE: A node that fails detach may be at DS_ATTACHED instead
1333
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  1655
 * of DS_READY for a small amount of time - this is the source of
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  1656
 * transient DS_READY->DS_ATTACHED->DS_READY state changes.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1657
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1658
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1659
i_ddi_detachchild(dev_info_t *dip, uint_t flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1660
{
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1661
	dev_info_t	*parent = ddi_get_parent(dip);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1662
	int		ret;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1663
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1664
	ASSERT(parent && DEVI_BUSY_OWNED(parent));
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1665
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1666
	ret = i_ndi_unconfig_node(dip, DS_PROBED, flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1667
	if (ret != DDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1668
		(void) i_ndi_config_node(dip, DS_READY, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1669
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1670
		/* allow pm_pre_probe to reestablish pm state */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1671
		(void) i_ndi_unconfig_node(dip, DS_INITIALIZED, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1672
	return (ret);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1673
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1674
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1675
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1676
 * Add a child and bind to driver
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1677
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1678
dev_info_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1679
ddi_add_child(dev_info_t *pdip, char *name, uint_t nodeid, uint_t unit)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1680
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1681
	int circ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1682
	dev_info_t *dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1683
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1684
	/* allocate a new node */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1685
	dip = i_ddi_alloc_node(pdip, name, nodeid, (int)unit, NULL, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1686
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1687
	ndi_devi_enter(pdip, &circ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1688
	(void) i_ndi_config_node(dip, DS_BOUND, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1689
	ndi_devi_exit(pdip, circ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1690
	return (dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1691
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1692
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1693
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1694
 * ddi_remove_child: remove the dip. The parent must be attached and held
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1695
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1696
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1697
ddi_remove_child(dev_info_t *dip, int dummy)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1698
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1699
	_NOTE(ARGUNUSED(dummy))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1700
	int circ, ret;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1701
	dev_info_t *parent = ddi_get_parent(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1702
	ASSERT(parent);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1703
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1704
	ndi_devi_enter(parent, &circ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1705
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1706
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1707
	 * If we still have children, for example SID nodes marked
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1708
	 * as persistent but not attached, attempt to remove them.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1709
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1710
	if (DEVI(dip)->devi_child) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1711
		ret = ndi_devi_unconfig(dip, NDI_DEVI_REMOVE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1712
		if (ret != NDI_SUCCESS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1713
			ndi_devi_exit(parent, circ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1714
			return (DDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1715
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1716
		ASSERT(DEVI(dip)->devi_child == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1717
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1718
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1719
	ret = i_ndi_unconfig_node(dip, DS_PROTO, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1720
	ndi_devi_exit(parent, circ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1721
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1722
	if (ret != DDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1723
		return (ret);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1724
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1725
	ASSERT(i_ddi_node_state(dip) == DS_PROTO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1726
	i_ddi_free_node(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1727
	return (DDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1728
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1729
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1730
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1731
 * NDI wrappers for ref counting, node allocation, and transitions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1732
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1733
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1734
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1735
 * Hold/release the devinfo node itself.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1736
 * Caller is assumed to prevent the devi from detaching during this call
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1737
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1738
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1739
ndi_hold_devi(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1740
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1741
	mutex_enter(&DEVI(dip)->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1742
	ASSERT(DEVI(dip)->devi_ref >= 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1743
	DEVI(dip)->devi_ref++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1744
	membar_enter();			/* make sure stores are flushed */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1745
	mutex_exit(&DEVI(dip)->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1746
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1747
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1748
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1749
ndi_rele_devi(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1750
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1751
	ASSERT(DEVI(dip)->devi_ref > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1752
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1753
	mutex_enter(&DEVI(dip)->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1754
	DEVI(dip)->devi_ref--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1755
	membar_enter();			/* make sure stores are flushed */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1756
	mutex_exit(&DEVI(dip)->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1757
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1758
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1759
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1760
e_ddi_devi_holdcnt(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1761
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1762
	return (DEVI(dip)->devi_ref);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1763
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1764
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1765
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1766
 * Hold/release the driver the devinfo node is bound to.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1767
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1768
struct dev_ops *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1769
ndi_hold_driver(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1770
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1771
	if (i_ddi_node_state(dip) < DS_BOUND)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1772
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1773
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1774
	ASSERT(DEVI(dip)->devi_major != -1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1775
	return (mod_hold_dev_by_major(DEVI(dip)->devi_major));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1776
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1777
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1778
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1779
ndi_rele_driver(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1780
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1781
	ASSERT(i_ddi_node_state(dip) >= DS_BOUND);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1782
	mod_rele_dev_by_major(DEVI(dip)->devi_major);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1783
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1784
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1785
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1786
 * Single thread entry into devinfo node for modifying its children.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1787
 * To verify in ASSERTS use DEVI_BUSY_OWNED macro.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1788
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1789
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1790
ndi_devi_enter(dev_info_t *dip, int *circular)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1791
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1792
	struct dev_info *devi = DEVI(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1793
	ASSERT(dip != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1794
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1795
	/* for vHCI, enforce (vHCI, pHCI) ndi_deve_enter() order */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1796
	ASSERT(!MDI_VHCI(dip) || (mdi_devi_pdip_entered(dip) == 0) ||
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1797
	    DEVI_BUSY_OWNED(dip));
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1798
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1799
	mutex_enter(&devi->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1800
	if (devi->devi_busy_thread == curthread) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1801
		devi->devi_circular++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1802
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1803
		while (DEVI_BUSY_CHANGING(devi) && !panicstr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1804
			cv_wait(&(devi->devi_cv), &(devi->devi_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1805
		if (panicstr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1806
			mutex_exit(&devi->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1807
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1808
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1809
		devi->devi_flags |= DEVI_BUSY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1810
		devi->devi_busy_thread = curthread;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1811
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1812
	*circular = devi->devi_circular;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1813
	mutex_exit(&devi->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1814
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1815
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1816
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1817
 * Release ndi_devi_enter or successful ndi_devi_tryenter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1818
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1819
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1820
ndi_devi_exit(dev_info_t *dip, int circular)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1821
{
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1822
	struct dev_info	*devi = DEVI(dip);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1823
	struct dev_info	*vdevi;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1824
	ASSERT(dip != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1825
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1826
	if (panicstr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1827
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1828
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1829
	mutex_enter(&(devi->devi_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1830
	if (circular != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1831
		devi->devi_circular--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1832
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1833
		devi->devi_flags &= ~DEVI_BUSY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1834
		ASSERT(devi->devi_busy_thread == curthread);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1835
		devi->devi_busy_thread = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1836
		cv_broadcast(&(devi->devi_cv));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1837
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1838
	mutex_exit(&(devi->devi_lock));
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1839
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1840
	/*
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1841
	 * For pHCI exit we issue a broadcast to vHCI for ndi_devi_config_one()
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1842
	 * doing cv_wait on vHCI.
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1843
	 */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1844
	if (MDI_PHCI(dip)) {
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1845
		vdevi = DEVI(mdi_devi_get_vdip(dip));
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1846
		if (vdevi) {
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1847
			mutex_enter(&(vdevi->devi_lock));
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1848
			if (vdevi->devi_flags & DEVI_PHCI_SIGNALS_VHCI) {
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1849
				vdevi->devi_flags &= ~DEVI_PHCI_SIGNALS_VHCI;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1850
				cv_broadcast(&(vdevi->devi_cv));
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1851
			}
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1852
			mutex_exit(&(vdevi->devi_lock));
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1853
		}
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1854
	}
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1855
}
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1856
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1857
/*
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1858
 * Release ndi_devi_enter and wait for possibility of new children, avoiding
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1859
 * possibility of missing broadcast before getting to cv_timedwait().
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1860
 */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1861
static void
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1862
ndi_devi_exit_and_wait(dev_info_t *dip, int circular, clock_t end_time)
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1863
{
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1864
	struct dev_info	*devi = DEVI(dip);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1865
	ASSERT(dip != NULL);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1866
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1867
	if (panicstr)
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1868
		return;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1869
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1870
	/*
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1871
	 * We are called to wait for of a new child, and new child can
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1872
	 * only be added if circular is zero.
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1873
	 */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1874
	ASSERT(circular == 0);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1875
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1876
	/* like ndi_devi_exit with circular of zero */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1877
	mutex_enter(&(devi->devi_lock));
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1878
	devi->devi_flags &= ~DEVI_BUSY;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1879
	ASSERT(devi->devi_busy_thread == curthread);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1880
	devi->devi_busy_thread = NULL;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1881
	cv_broadcast(&(devi->devi_cv));
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1882
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1883
	/* now wait for new children while still holding devi_lock */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1884
	(void) cv_timedwait(&devi->devi_cv, &(devi->devi_lock), end_time);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  1885
	mutex_exit(&(devi->devi_lock));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1886
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1887
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1888
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1889
 * Attempt to single thread entry into devinfo node for modifying its children.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1890
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1891
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1892
ndi_devi_tryenter(dev_info_t *dip, int *circular)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1893
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1894
	int rval = 1;		   /* assume we enter */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1895
	struct dev_info *devi = DEVI(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1896
	ASSERT(dip != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1897
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1898
	mutex_enter(&devi->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1899
	if (devi->devi_busy_thread == (void *)curthread) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1900
		devi->devi_circular++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1901
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1902
		if (!DEVI_BUSY_CHANGING(devi)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1903
			devi->devi_flags |= DEVI_BUSY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1904
			devi->devi_busy_thread = (void *)curthread;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1905
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1906
			rval = 0;	/* devi is busy */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1907
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1908
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1909
	*circular = devi->devi_circular;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1910
	mutex_exit(&devi->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1911
	return (rval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1912
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1913
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1914
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1915
 * Allocate and initialize a new dev_info structure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1916
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1917
 * This routine may be called at interrupt time by a nexus in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1918
 * response to a hotplug event, therefore memory allocations are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1919
 * not allowed to sleep.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1920
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1921
int
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 693
diff changeset
  1922
ndi_devi_alloc(dev_info_t *parent, char *node_name, pnode_t nodeid,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1923
    dev_info_t **ret_dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1924
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1925
	ASSERT(node_name != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1926
	ASSERT(ret_dip != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1927
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1928
	*ret_dip = i_ddi_alloc_node(parent, node_name, nodeid, -1, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1929
	    KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1930
	if (*ret_dip == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1931
		return (NDI_NOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1932
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1933
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1934
	return (NDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1935
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1936
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1937
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1938
 * Allocate and initialize a new dev_info structure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1939
 * This routine may sleep and should not be called at interrupt time
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1940
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1941
void
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 693
diff changeset
  1942
ndi_devi_alloc_sleep(dev_info_t *parent, char *node_name, pnode_t nodeid,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1943
    dev_info_t **ret_dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1944
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1945
	ASSERT(node_name != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1946
	ASSERT(ret_dip != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1947
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1948
	*ret_dip = i_ddi_alloc_node(parent, node_name, nodeid, -1, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1949
	    KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1950
	ASSERT(*ret_dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1951
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1952
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1953
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1954
 * Remove an initialized (but not yet attached) dev_info
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1955
 * node from it's parent.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1956
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1957
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1958
ndi_devi_free(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1959
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1960
	ASSERT(dip != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1961
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1962
	if (i_ddi_node_state(dip) >= DS_INITIALIZED)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1963
		return (DDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1964
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1965
	NDI_CONFIG_DEBUG((CE_CONT, "ndi_devi_free: %s%d (%p)\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1966
	    ddi_driver_name(dip), ddi_get_instance(dip), (void *)dip));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1967
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1968
	(void) ddi_remove_child(dip, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1969
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1970
	return (NDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1971
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1972
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1973
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1974
 * ndi_devi_bind_driver() binds a driver to a given device. If it fails
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1975
 * to bind the driver, it returns an appropriate error back. Some drivers
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1976
 * may want to know if the actually failed to bind.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1977
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1978
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1979
ndi_devi_bind_driver(dev_info_t *dip, uint_t flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1980
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1981
	int ret = NDI_FAILURE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1982
	int circ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1983
	dev_info_t *pdip = ddi_get_parent(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1984
	ASSERT(pdip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1985
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1986
	NDI_CONFIG_DEBUG((CE_CONT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1987
	    "ndi_devi_bind_driver: %s%d (%p) flags: %x\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1988
	    ddi_driver_name(dip), ddi_get_instance(dip), (void *)dip, flags));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1989
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1990
	ndi_devi_enter(pdip, &circ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1991
	if (i_ndi_config_node(dip, DS_BOUND, flags) == DDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1992
		ret = NDI_SUCCESS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1993
	ndi_devi_exit(pdip, circ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1994
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1995
	return (ret);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1996
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1997
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1998
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1999
 * ndi_devi_unbind_driver: unbind the dip
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2000
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2001
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2002
ndi_devi_unbind_driver(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2003
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2004
	ASSERT(DEVI_BUSY_OWNED(ddi_get_parent(dip)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2005
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2006
	return (i_ndi_unconfig_node(dip, DS_LINKED, 0));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2007
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2008
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2009
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2010
 * Misc. help routines called by framework only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2011
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2012
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2013
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2014
 * Get the state of node
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2015
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2016
ddi_node_state_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2017
i_ddi_node_state(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2018
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2019
	return (DEVI(dip)->devi_node_state);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2020
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2021
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2022
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2023
 * Set the state of node
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2024
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2025
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2026
i_ddi_set_node_state(dev_info_t *dip, ddi_node_state_t state)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2027
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2028
	DEVI(dip)->devi_node_state = state;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2029
	membar_enter();			/* make sure stores are flushed */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2030
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2031
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2032
/*
1333
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  2033
 * Determine if node is attached. The implementation accommodates transient
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  2034
 * DS_READY->DS_ATTACHED->DS_READY state changes.  Outside this file, this
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  2035
 * function should be instead of i_ddi_node_state() DS_ATTACHED/DS_READY
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  2036
 * state checks.
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  2037
 */
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  2038
int
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  2039
i_ddi_devi_attached(dev_info_t *dip)
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  2040
{
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  2041
	return (DEVI(dip)->devi_node_state >= DS_ATTACHED);
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  2042
}
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  2043
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  2044
/*
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2045
 * Common function for finding a node in a sibling list given name and addr.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2046
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2047
 * By default, name is matched with devi_node_name. The following
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2048
 * alternative match strategies are supported:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2049
 *
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2050
 *	FIND_NODE_BY_NODENAME: Match on node name - typical use.
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2051
 *	FIND_NODE_BY_DRIVER: A match on driver name bound to node is conducted.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2052
 *		This support is used for support of OBP generic names and
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2053
 *		for the conversion from driver names to generic names. When
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2054
 *		more consistency in the generic name environment is achieved
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2055
 *		(and not needed for upgrade) this support can be removed.
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2056
 *	FIND_NODE_BY_ADDR: Match on just the addr.
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2057
 *		This support is only used/needed during boot to match
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2058
 *		a node bound via a path-based driver alias.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2059
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2060
 * If a child is not named (dev_addr == NULL), there are three
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2061
 * possible actions:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2062
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2063
 *	(1) skip it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2064
 *	(2) FIND_ADDR_BY_INIT: bring child to DS_INITIALIZED state
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2065
 *	(3) FIND_ADDR_BY_CALLBACK: use a caller-supplied callback function
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2066
 */
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2067
#define	FIND_NODE_BY_NODENAME	0x01
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2068
#define	FIND_NODE_BY_DRIVER	0x02
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2069
#define	FIND_NODE_BY_ADDR	0x04
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2070
#define	FIND_ADDR_BY_INIT	0x10
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2071
#define	FIND_ADDR_BY_CALLBACK	0x20
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2072
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2073
static dev_info_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2074
find_sibling(dev_info_t *head, char *cname, char *caddr, uint_t flag,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2075
    int (*callback)(dev_info_t *, char *, int))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2076
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2077
	dev_info_t	*dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2078
	char		*addr, *buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2079
	major_t		major;
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2080
	uint_t		by;
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2081
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2082
	/* only one way to find a node */
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2083
	by = flag &
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2084
	    (FIND_NODE_BY_DRIVER | FIND_NODE_BY_NODENAME | FIND_NODE_BY_ADDR);
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2085
	ASSERT(by && BIT_ONLYONESET(by));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2086
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2087
	/* only one way to name a node */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2088
	ASSERT(((flag & FIND_ADDR_BY_INIT) == 0) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2089
	    ((flag & FIND_ADDR_BY_CALLBACK) == 0));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2090
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2091
	if (by == FIND_NODE_BY_DRIVER) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2092
		major = ddi_name_to_major(cname);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2093
		if (major == (major_t)-1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2094
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2095
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2096
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2097
	/* preallocate buffer of naming node by callback */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2098
	if (flag & FIND_ADDR_BY_CALLBACK)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2099
		buf = kmem_alloc(MAXNAMELEN, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2100
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2101
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2102
	 * Walk the child list to find a match
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2103
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2104
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2105
	for (dip = head; dip; dip = ddi_get_next_sibling(dip)) {
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2106
		if (by == FIND_NODE_BY_NODENAME) {
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2107
			/* match node name */
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2108
			if (strcmp(cname, DEVI(dip)->devi_node_name) != 0)
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2109
				continue;
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2110
		} else if (by == FIND_NODE_BY_DRIVER) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2111
			/* match driver major */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2112
			if (DEVI(dip)->devi_major != major)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2113
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2114
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2115
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2116
		if ((addr = DEVI(dip)->devi_addr) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2117
			/* name the child based on the flag */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2118
			if (flag & FIND_ADDR_BY_INIT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2119
				if (ddi_initchild(ddi_get_parent(dip), dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2120
				    != DDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2121
					continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2122
				addr = DEVI(dip)->devi_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2123
			} else if (flag & FIND_ADDR_BY_CALLBACK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2124
				if ((callback == NULL) || (callback(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2125
				    dip, buf, MAXNAMELEN) != DDI_SUCCESS))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2126
					continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2127
				addr = buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2128
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2129
				continue;	/* skip */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2130
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2131
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2132
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2133
		/* match addr */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2134
		ASSERT(addr != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2135
		if (strcmp(caddr, addr) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2136
			break;	/* node found */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2137
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2138
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2139
	if (flag & FIND_ADDR_BY_CALLBACK)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2140
		kmem_free(buf, MAXNAMELEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2141
	return (dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2142
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2143
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2144
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2145
 * Find child of pdip with name: cname@caddr
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2146
 * Called by init_node() to look for duplicate nodes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2147
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2148
static dev_info_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2149
find_duplicate_child(dev_info_t *pdip, dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2150
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2151
	dev_info_t *dup;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2152
	char *cname = DEVI(dip)->devi_node_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2153
	char *caddr = DEVI(dip)->devi_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2154
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2155
	/* search nodes before dip */
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2156
	dup = find_sibling(ddi_get_child(pdip), cname, caddr,
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2157
	    FIND_NODE_BY_NODENAME, NULL);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2158
	if (dup != dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2159
		return (dup);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2160
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2161
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2162
	 * search nodes after dip; normally this is not needed,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2163
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2164
	return (find_sibling(ddi_get_next_sibling(dip), cname, caddr,
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2165
	    FIND_NODE_BY_NODENAME, NULL));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2166
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2167
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2168
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2169
 * Find a child of a given name and address, using a callback to name
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2170
 * unnamed children. cname is the binding name.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2171
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2172
static dev_info_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2173
find_child_by_callback(dev_info_t *pdip, char *cname, char *caddr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2174
    int (*name_node)(dev_info_t *, char *, int))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2175
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2176
	return (find_sibling(ddi_get_child(pdip), cname, caddr,
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2177
	    FIND_NODE_BY_DRIVER|FIND_ADDR_BY_CALLBACK, name_node));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2178
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2179
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2180
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2181
 * Find a child of a given name and address, invoking initchild to name
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2182
 * unnamed children. cname is the node name.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2183
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2184
static dev_info_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2185
find_child_by_name(dev_info_t *pdip, char *cname, char *caddr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2186
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2187
	dev_info_t	*dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2188
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2189
	/* attempt search without changing state of preceding siblings */
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2190
	dip = find_sibling(ddi_get_child(pdip), cname, caddr,
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2191
	    FIND_NODE_BY_NODENAME, NULL);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2192
	if (dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2193
		return (dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2194
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2195
	return (find_sibling(ddi_get_child(pdip), cname, caddr,
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2196
	    FIND_NODE_BY_NODENAME|FIND_ADDR_BY_INIT, NULL));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2197
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2198
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2199
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2200
 * Find a child of a given name and address, invoking initchild to name
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2201
 * unnamed children. cname is the node name.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2202
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2203
static dev_info_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2204
find_child_by_driver(dev_info_t *pdip, char *cname, char *caddr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2205
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2206
	dev_info_t	*dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2207
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2208
	/* attempt search without changing state of preceding siblings */
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2209
	dip = find_sibling(ddi_get_child(pdip), cname, caddr,
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2210
	    FIND_NODE_BY_DRIVER, NULL);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2211
	if (dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2212
		return (dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2213
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2214
	return (find_sibling(ddi_get_child(pdip), cname, caddr,
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2215
	    FIND_NODE_BY_DRIVER|FIND_ADDR_BY_INIT, NULL));
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2216
}
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2217
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2218
/*
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2219
 * Find a child of a given address, invoking initchild to name
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2220
 * unnamed children. cname is the node name.
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2221
 *
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2222
 * NOTE: This function is only used during boot. One would hope that
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2223
 * unique sibling unit-addresses on hardware branches of the tree would
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2224
 * be a requirement to avoid two drivers trying to control the same
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2225
 * piece of hardware. Unfortunately there are some cases where this
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2226
 * situation exists (/ssm@0,0/pci@1c,700000 /ssm@0,0/sghsc@1c,700000).
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2227
 * Until unit-address uniqueness of siblings is guaranteed, use of this
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2228
 * interface for purposes other than boot should be avoided.
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2229
 */
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2230
static dev_info_t *
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2231
find_child_by_addr(dev_info_t *pdip, char *caddr)
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2232
{
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2233
	dev_info_t	*dip;
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2234
4540
f18ef423e3a7 6571223 find_child_by_addr() returns unwanted dip if input caddr is an empty string
cth
parents: 4411
diff changeset
  2235
	/* return NULL if called without a unit-address */
f18ef423e3a7 6571223 find_child_by_addr() returns unwanted dip if input caddr is an empty string
cth
parents: 4411
diff changeset
  2236
	if ((caddr == NULL) || (*caddr == '\0'))
f18ef423e3a7 6571223 find_child_by_addr() returns unwanted dip if input caddr is an empty string
cth
parents: 4411
diff changeset
  2237
		return (NULL);
f18ef423e3a7 6571223 find_child_by_addr() returns unwanted dip if input caddr is an empty string
cth
parents: 4411
diff changeset
  2238
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2239
	/* attempt search without changing state of preceding siblings */
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2240
	dip = find_sibling(ddi_get_child(pdip), NULL, caddr,
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2241
	    FIND_NODE_BY_ADDR, NULL);
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2242
	if (dip)
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2243
		return (dip);
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2244
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2245
	return (find_sibling(ddi_get_child(pdip), NULL, caddr,
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2246
	    FIND_NODE_BY_ADDR|FIND_ADDR_BY_INIT, NULL));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2247
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2248
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2249
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2250
 * Deleting a property list. Take care, since some property structures
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2251
 * may not be fully built.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2252
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2253
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2254
i_ddi_prop_list_delete(ddi_prop_t *prop)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2255
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2256
	while (prop) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2257
		ddi_prop_t *next = prop->prop_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2258
		if (prop->prop_name)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2259
			kmem_free(prop->prop_name, strlen(prop->prop_name) + 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2260
		if ((prop->prop_len != 0) && prop->prop_val)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2261
			kmem_free(prop->prop_val, prop->prop_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2262
		kmem_free(prop, sizeof (struct ddi_prop));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2263
		prop = next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2264
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2265
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2266
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2267
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2268
 * Duplicate property list
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2269
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2270
ddi_prop_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2271
i_ddi_prop_list_dup(ddi_prop_t *prop, uint_t flag)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2272
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2273
	ddi_prop_t *result, *prev, *copy;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2274
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2275
	if (prop == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2276
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2277
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2278
	result = prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2279
	for (; prop != NULL; prop = prop->prop_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2280
		ASSERT(prop->prop_name != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2281
		copy = kmem_zalloc(sizeof (struct ddi_prop), flag);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2282
		if (copy == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2283
			goto fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2284
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2285
		copy->prop_dev = prop->prop_dev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2286
		copy->prop_flags = prop->prop_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2287
		copy->prop_name = i_ddi_strdup(prop->prop_name, flag);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2288
		if (copy->prop_name == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2289
			goto fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2290
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2291
		if ((copy->prop_len = prop->prop_len) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2292
			copy->prop_val = kmem_zalloc(prop->prop_len, flag);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2293
			if (copy->prop_val == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2294
				goto fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2295
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2296
			bcopy(prop->prop_val, copy->prop_val, prop->prop_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2297
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2298
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2299
		if (prev == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2300
			result = prev = copy;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2301
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2302
			prev->prop_next = copy;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2303
		prev = copy;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2304
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2305
	return (result);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2306
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2307
fail:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2308
	i_ddi_prop_list_delete(result);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2309
	return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2310
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2311
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2312
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2313
 * Create a reference property list, currently used only for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2314
 * driver global properties. Created with ref count of 1.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2315
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2316
ddi_prop_list_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2317
i_ddi_prop_list_create(ddi_prop_t *props)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2318
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2319
	ddi_prop_list_t *list = kmem_alloc(sizeof (*list), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2320
	list->prop_list = props;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2321
	list->prop_ref = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2322
	return (list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2323
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2324
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2325
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2326
 * Increment/decrement reference count. The reference is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2327
 * protected by dn_lock. The only interfaces modifying
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2328
 * dn_global_prop_ptr is in impl_make[free]_parlist().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2329
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2330
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2331
i_ddi_prop_list_hold(ddi_prop_list_t *prop_list, struct devnames *dnp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2332
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2333
	ASSERT(prop_list->prop_ref >= 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2334
	ASSERT(mutex_owned(&dnp->dn_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2335
	prop_list->prop_ref++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2336
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2337
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2338
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2339
i_ddi_prop_list_rele(ddi_prop_list_t *prop_list, struct devnames *dnp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2340
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2341
	ASSERT(prop_list->prop_ref > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2342
	ASSERT(mutex_owned(&dnp->dn_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2343
	prop_list->prop_ref--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2344
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2345
	if (prop_list->prop_ref == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2346
		i_ddi_prop_list_delete(prop_list->prop_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2347
		kmem_free(prop_list, sizeof (*prop_list));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2348
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2349
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2350
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2351
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2352
 * Free table of classes by drivers
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2353
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2354
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2355
i_ddi_free_exported_classes(char **classes, int n)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2356
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2357
	if ((n == 0) || (classes == NULL))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2358
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2359
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2360
	kmem_free(classes, n * sizeof (char *));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2361
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2362
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2363
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2364
 * Get all classes exported by dip
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2365
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2366
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2367
i_ddi_get_exported_classes(dev_info_t *dip, char ***classes)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2368
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2369
	extern void lock_hw_class_list();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2370
	extern void unlock_hw_class_list();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2371
	extern int get_class(const char *, char **);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2372
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2373
	static char *rootclass = "root";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2374
	int n = 0, nclass = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2375
	char **buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2376
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2377
	ASSERT(i_ddi_node_state(dip) >= DS_BOUND);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2378
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2379
	if (dip == ddi_root_node())	/* rootnode exports class "root" */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2380
		nclass = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2381
	lock_hw_class_list();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2382
	nclass += get_class(ddi_driver_name(dip), NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2383
	if (nclass == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2384
		unlock_hw_class_list();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2385
		return (0);		/* no class exported */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2386
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2387
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2388
	*classes = buf = kmem_alloc(nclass * sizeof (char *), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2389
	if (dip == ddi_root_node()) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2390
		*buf++ = rootclass;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2391
		n = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2392
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2393
	n += get_class(ddi_driver_name(dip), buf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2394
	unlock_hw_class_list();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2395
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2396
	ASSERT(n == nclass);    /* make sure buf wasn't overrun */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2397
	return (nclass);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2398
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2399
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2400
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2401
 * Helper functions, returns NULL if no memory.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2402
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2403
char *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2404
i_ddi_strdup(char *str, uint_t flag)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2405
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2406
	char *copy;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2407
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2408
	if (str == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2409
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2410
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2411
	copy = kmem_alloc(strlen(str) + 1, flag);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2412
	if (copy == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2413
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2414
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2415
	(void) strcpy(copy, str);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2416
	return (copy);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2417
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2418
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2419
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2420
 * Load driver.conf file for major. Load all if major == -1.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2421
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2422
 * This is called
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2423
 * - early in boot after devnames array is initialized
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2424
 * - from vfs code when certain file systems are mounted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2425
 * - from add_drv when a new driver is added
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2426
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2427
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2428
i_ddi_load_drvconf(major_t major)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2429
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2430
	extern int modrootloaded;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2431
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2432
	major_t low, high, m;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2433
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2434
	if (major == (major_t)-1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2435
		low = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2436
		high = devcnt - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2437
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2438
		if (major >= devcnt)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2439
			return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2440
		low = high = major;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2441
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2442
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2443
	for (m = low; m <= high; m++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2444
		struct devnames *dnp = &devnamesp[m];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2445
		LOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2446
		dnp->dn_flags &= ~DN_DRIVER_HELD;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2447
		(void) impl_make_parlist(m);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2448
		UNLOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2449
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2450
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2451
	if (modrootloaded) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2452
		ddi_walk_devs(ddi_root_node(), reset_nexus_flags,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2453
		    (void *)(uintptr_t)major);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2454
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2455
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2456
	/* build dn_list from old entries in path_to_inst */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2457
	e_ddi_unorphan_instance_nos();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2458
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2459
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2460
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2461
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2462
 * Unload a specific driver.conf.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2463
 * Don't support unload all because it doesn't make any sense
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2464
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2465
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2466
i_ddi_unload_drvconf(major_t major)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2467
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2468
	int error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2469
	struct devnames *dnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2470
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2471
	if (major >= devcnt)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2472
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2473
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2474
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2475
	 * Take the per-driver lock while unloading driver.conf
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2476
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2477
	dnp = &devnamesp[major];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2478
	LOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2479
	error = impl_free_parlist(major);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2480
	UNLOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2481
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2482
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2483
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2484
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2485
 * Merge a .conf node. This is called by nexus drivers to augment
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2486
 * hw node with properties specified in driver.conf file. This function
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2487
 * takes a callback routine to name nexus children.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2488
 * The parent node must be held busy.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2489
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2490
 * It returns DDI_SUCCESS if the node is merged and DDI_FAILURE otherwise.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2491
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2492
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2493
ndi_merge_node(dev_info_t *dip, int (*name_node)(dev_info_t *, char *, int))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2494
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2495
	dev_info_t *hwdip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2496
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2497
	ASSERT(ndi_dev_is_persistent_node(dip) == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2498
	ASSERT(ddi_get_name_addr(dip) != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2499
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2500
	hwdip = find_child_by_callback(ddi_get_parent(dip),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2501
	    ddi_binding_name(dip), ddi_get_name_addr(dip), name_node);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2502
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2503
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2504
	 * Look for the hardware node that is the target of the merge;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2505
	 * return failure if not found.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2506
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2507
	if ((hwdip == NULL) || (hwdip == dip)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2508
		char *buf = kmem_alloc(MAXNAMELEN, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2509
		NDI_CONFIG_DEBUG((CE_WARN, "No HW node to merge conf node %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2510
		    ddi_deviname(dip, buf)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2511
		kmem_free(buf, MAXNAMELEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2512
		return (DDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2513
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2514
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2515
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2516
	 * Make sure the hardware node is uninitialized and has no property.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2517
	 * This may not be the case if new .conf files are load after some
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2518
	 * hardware nodes have already been initialized and attached.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2519
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2520
	 * N.B. We return success here because the node was *intended*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2521
	 * 	to be a merge node because there is a hw node with the name.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2522
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2523
	mutex_enter(&DEVI(hwdip)->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2524
	if (ndi_dev_is_persistent_node(hwdip) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2525
		char *buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2526
		mutex_exit(&DEVI(hwdip)->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2527
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2528
		buf = kmem_alloc(MAXNAMELEN, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2529
		NDI_CONFIG_DEBUG((CE_NOTE, "Duplicate .conf node %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2530
		    ddi_deviname(dip, buf)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2531
		kmem_free(buf, MAXNAMELEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2532
		return (DDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2533
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2534
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2535
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2536
	 * If it is possible that the hardware has already been touched
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2537
	 * then don't merge.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2538
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2539
	if (i_ddi_node_state(hwdip) >= DS_INITIALIZED ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2540
	    (DEVI(hwdip)->devi_sys_prop_ptr != NULL) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2541
	    (DEVI(hwdip)->devi_drv_prop_ptr != NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2542
		char *buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2543
		mutex_exit(&DEVI(hwdip)->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2544
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2545
		buf = kmem_alloc(MAXNAMELEN, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2546
		NDI_CONFIG_DEBUG((CE_NOTE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2547
		    "!Cannot merge .conf node %s with hw node %p "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2548
		    "-- not in proper state",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2549
		    ddi_deviname(dip, buf), (void *)hwdip));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2550
		kmem_free(buf, MAXNAMELEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2551
		return (DDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2552
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2553
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2554
	mutex_enter(&DEVI(dip)->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2555
	DEVI(hwdip)->devi_sys_prop_ptr = DEVI(dip)->devi_sys_prop_ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2556
	DEVI(hwdip)->devi_drv_prop_ptr = DEVI(dip)->devi_drv_prop_ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2557
	DEVI(dip)->devi_sys_prop_ptr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2558
	DEVI(dip)->devi_drv_prop_ptr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2559
	mutex_exit(&DEVI(dip)->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2560
	mutex_exit(&DEVI(hwdip)->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2561
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2562
	return (DDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2563
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2564
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2565
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2566
 * Merge a "wildcard" .conf node. This is called by nexus drivers to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2567
 * augment a set of hw node with properties specified in driver.conf file.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2568
 * The parent node must be held busy.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2569
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2570
 * There is no failure mode, since the nexus may or may not have child
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2571
 * node bound the driver specified by the wildcard node.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2572
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2573
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2574
ndi_merge_wildcard_node(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2575
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2576
	dev_info_t *hwdip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2577
	dev_info_t *pdip = ddi_get_parent(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2578
	major_t major = ddi_driver_major(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2579
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2580
	/* never attempt to merge a hw node */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2581
	ASSERT(ndi_dev_is_persistent_node(dip) == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2582
	/* must be bound to a driver major number */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2583
	ASSERT(major != (major_t)-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2584
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2585
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2586
	 * Walk the child list to find all nodes bound to major
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2587
	 * and copy properties.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2588
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2589
	mutex_enter(&DEVI(dip)->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2590
	for (hwdip = ddi_get_child(pdip); hwdip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2591
	    hwdip = ddi_get_next_sibling(hwdip)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2592
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2593
		 * Skip nodes not bound to same driver
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2594
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2595
		if (ddi_driver_major(hwdip) != major)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2596
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2597
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2598
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2599
		 * Skip .conf nodes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2600
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2601
		if (ndi_dev_is_persistent_node(hwdip) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2602
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2603
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2604
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2605
		 * Make sure the node is uninitialized and has no property.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2606
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2607
		mutex_enter(&DEVI(hwdip)->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2608
		if (i_ddi_node_state(hwdip) >= DS_INITIALIZED ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2609
		    (DEVI(hwdip)->devi_sys_prop_ptr != NULL) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2610
		    (DEVI(hwdip)->devi_drv_prop_ptr != NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2611
			mutex_exit(&DEVI(hwdip)->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2612
			NDI_CONFIG_DEBUG((CE_NOTE, "HW node %p state not "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2613
			    "suitable for merging wildcard conf node %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2614
			    (void *)hwdip, ddi_node_name(dip)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2615
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2616
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2617
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2618
		DEVI(hwdip)->devi_sys_prop_ptr =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2619
		    i_ddi_prop_list_dup(DEVI(dip)->devi_sys_prop_ptr, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2620
		DEVI(hwdip)->devi_drv_prop_ptr =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2621
		    i_ddi_prop_list_dup(DEVI(dip)->devi_drv_prop_ptr, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2622
		mutex_exit(&DEVI(hwdip)->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2623
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2624
	mutex_exit(&DEVI(dip)->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2625
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2626
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2627
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2628
 * Return the major number based on the compatible property. This interface
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2629
 * may be used in situations where we are trying to detect if a better driver
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2630
 * now exists for a device, so it must use the 'compatible' property.  If
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2631
 * a non-NULL formp is specified and the binding was based on compatible then
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2632
 * return the pointer to the form used in *formp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2633
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2634
major_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2635
ddi_compatible_driver_major(dev_info_t *dip, char **formp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2636
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2637
	struct dev_info *devi = DEVI(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2638
	void		*compat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2639
	size_t		len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2640
	char		*p = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2641
	major_t		major = (major_t)-1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2642
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2643
	if (formp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2644
		*formp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2645
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2646
	/*
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2647
	 * Highest precedence binding is a path-oriented alias. Since this
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2648
	 * requires a 'path', this type of binding occurs via more obtuse
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2649
	 * 'rebind'. The need for a path-oriented alias 'rebind' is detected
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2650
	 * after a successful DDI_CTLOPS_INITCHILD to another driver: this is
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2651
	 * is the first point at which the unit-address (or instance) of the
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2652
	 * last component of the path is available (even though the path is
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2653
	 * bound to the wrong driver at this point).
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2654
	 */
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2655
	if (devi->devi_flags & DEVI_REBIND) {
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2656
		p = devi->devi_rebinding_name;
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2657
		major = ddi_name_to_major(p);
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2658
		if ((major != (major_t)-1) &&
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2659
		    !(devnamesp[major].dn_flags & DN_DRIVER_REMOVED)) {
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2660
			if (formp)
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2661
				*formp = p;
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2662
			return (major);
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2663
		}
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2664
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2665
		/*
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2666
		 * If for some reason devi_rebinding_name no longer resolves
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2667
		 * to a proper driver then clear DEVI_REBIND.
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2668
		 */
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2669
		mutex_enter(&devi->devi_lock);
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2670
		devi->devi_flags &= ~DEVI_REBIND;
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2671
		mutex_exit(&devi->devi_lock);
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2672
	}
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  2673
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2674
	/* look up compatible property */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2675
	(void) lookup_compatible(dip, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2676
	compat = (void *)(devi->devi_compat_names);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2677
	len = devi->devi_compat_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2678
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2679
	/* find the highest precedence compatible form with a driver binding */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2680
	while ((p = prom_decode_composite_string(compat, len, p)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2681
		major = ddi_name_to_major(p);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2682
		if ((major != (major_t)-1) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2683
		    !(devnamesp[major].dn_flags & DN_DRIVER_REMOVED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2684
			if (formp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2685
				*formp = p;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2686
			return (major);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2687
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2688
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2689
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2690
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2691
	 * none of the compatible forms have a driver binding, see if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2692
	 * the node name has a driver binding.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2693
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2694
	major = ddi_name_to_major(ddi_node_name(dip));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2695
	if ((major != (major_t)-1) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2696
	    !(devnamesp[major].dn_flags & DN_DRIVER_REMOVED))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2697
		return (major);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2698
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2699
	/* no driver */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2700
	return ((major_t)-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2701
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2702
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2703
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2704
 * Static help functions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2705
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2706
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2707
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2708
 * lookup the "compatible" property and cache it's contents in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2709
 * device node.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2710
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2711
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2712
lookup_compatible(dev_info_t *dip, uint_t flag)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2713
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2714
	int rv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2715
	int prop_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2716
	uint_t ncompatstrs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2717
	char **compatstrpp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2718
	char *di_compat_strp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2719
	size_t di_compat_strlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2720
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2721
	if (DEVI(dip)->devi_compat_names) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2722
		return (DDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2723
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2724
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2725
	prop_flags = DDI_PROP_TYPE_STRING | DDI_PROP_DONTPASS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2726
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2727
	if (flag & KM_NOSLEEP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2728
		prop_flags |= DDI_PROP_DONTSLEEP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2729
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2730
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2731
	if (ndi_dev_is_prom_node(dip) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2732
		prop_flags |= DDI_PROP_NOTPROM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2733
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2734
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2735
	rv = ddi_prop_lookup_common(DDI_DEV_T_ANY, dip, prop_flags,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2736
	    "compatible", &compatstrpp, &ncompatstrs,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2737
	    ddi_prop_fm_decode_strings);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2738
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2739
	if (rv == DDI_PROP_NOT_FOUND) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2740
		return (DDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2741
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2742
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2743
	if (rv != DDI_PROP_SUCCESS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2744
		return (DDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2745
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2746
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2747
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2748
	 * encode the compatible property data in the dev_info node
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2749
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2750
	rv = DDI_SUCCESS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2751
	if (ncompatstrs != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2752
		di_compat_strp = encode_composite_string(compatstrpp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2753
		    ncompatstrs, &di_compat_strlen, flag);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2754
		if (di_compat_strp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2755
			DEVI(dip)->devi_compat_names = di_compat_strp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2756
			DEVI(dip)->devi_compat_length = di_compat_strlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2757
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2758
			rv = DDI_FAILURE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2759
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2760
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2761
	ddi_prop_free(compatstrpp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2762
	return (rv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2763
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2764
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2765
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2766
 * Create a composite string from a list of strings.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2767
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2768
 * A composite string consists of a single buffer containing one
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2769
 * or more NULL terminated strings.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2770
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2771
static char *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2772
encode_composite_string(char **strings, uint_t nstrings, size_t *retsz,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2773
    uint_t flag)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2774
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2775
	uint_t index;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2776
	char  **strpp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2777
	uint_t slen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2778
	size_t cbuf_sz = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2779
	char *cbuf_p;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2780
	char *cbuf_ip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2781
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2782
	if (strings == NULL || nstrings == 0 || retsz == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2783
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2784
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2785
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2786
	for (index = 0, strpp = strings; index < nstrings; index++)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2787
		cbuf_sz += strlen(*(strpp++)) + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2788
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2789
	if ((cbuf_p = kmem_alloc(cbuf_sz, flag)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2790
		cmn_err(CE_NOTE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2791
		    "?failed to allocate device node compatstr");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2792
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2793
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2794
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2795
	cbuf_ip = cbuf_p;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2796
	for (index = 0, strpp = strings; index < nstrings; index++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2797
		slen = strlen(*strpp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2798
		bcopy(*(strpp++), cbuf_ip, slen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2799
		cbuf_ip += slen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2800
		*(cbuf_ip++) = '\0';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2801
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2802
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2803
	*retsz = cbuf_sz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2804
	return (cbuf_p);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2805
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2806
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2807
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2808
link_to_driver_list(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2809
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2810
	major_t major = DEVI(dip)->devi_major;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2811
	struct devnames *dnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2812
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2813
	ASSERT(major != (major_t)-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2814
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2815
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2816
	 * Remove from orphan list
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2817
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2818
	if (ndi_dev_is_persistent_node(dip)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2819
		dnp = &orphanlist;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2820
		remove_from_dn_list(dnp, dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2821
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2822
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2823
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2824
	 * Add to per driver list
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2825
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2826
	dnp = &devnamesp[major];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2827
	add_to_dn_list(dnp, dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2828
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2829
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2830
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2831
unlink_from_driver_list(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2832
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2833
	major_t major = DEVI(dip)->devi_major;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2834
	struct devnames *dnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2835
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2836
	ASSERT(major != (major_t)-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2837
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2838
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2839
	 * Remove from per-driver list
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2840
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2841
	dnp = &devnamesp[major];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2842
	remove_from_dn_list(dnp, dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2843
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2844
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2845
	 * Add to orphan list
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2846
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2847
	if (ndi_dev_is_persistent_node(dip)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2848
		dnp = &orphanlist;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2849
		add_to_dn_list(dnp, dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2850
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2851
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2852
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2853
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2854
 * scan the per-driver list looking for dev_info "dip"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2855
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2856
static dev_info_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2857
in_dn_list(struct devnames *dnp, dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2858
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2859
	struct dev_info *idevi;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2860
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2861
	if ((idevi = DEVI(dnp->dn_head)) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2862
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2863
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2864
	while (idevi) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2865
		if (idevi == DEVI(dip))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2866
			return (dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2867
		idevi = idevi->devi_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2868
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2869
	return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2870
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2871
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2872
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2873
 * insert devinfo node 'dip' into the per-driver instance list
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2874
 * headed by 'dnp'
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2875
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2876
 * Nodes on the per-driver list are ordered: HW - SID - PSEUDO.  The order is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2877
 * required for merging of .conf file data to work properly.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2878
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2879
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2880
add_to_ordered_dn_list(struct devnames *dnp, dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2881
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2882
	dev_info_t **dipp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2883
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2884
	ASSERT(mutex_owned(&(dnp->dn_lock)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2885
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2886
	dipp = &dnp->dn_head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2887
	if (ndi_dev_is_prom_node(dip)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2888
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2889
		 * Find the first non-prom node or end of list
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2890
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2891
		while (*dipp && (ndi_dev_is_prom_node(*dipp) != 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2892
			dipp = (dev_info_t **)&DEVI(*dipp)->devi_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2893
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2894
	} else if (ndi_dev_is_persistent_node(dip)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2895
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2896
		 * Find the first non-persistent node
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2897
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2898
		while (*dipp && (ndi_dev_is_persistent_node(*dipp) != 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2899
			dipp = (dev_info_t **)&DEVI(*dipp)->devi_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2900
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2901
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2902
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2903
		 * Find the end of the list
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2904
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2905
		while (*dipp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2906
			dipp = (dev_info_t **)&DEVI(*dipp)->devi_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2907
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2908
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2909
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2910
	DEVI(dip)->devi_next = DEVI(*dipp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2911
	*dipp = dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2912
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2913
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2914
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2915
 * add a list of device nodes to the device node list in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2916
 * devnames structure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2917
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2918
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2919
add_to_dn_list(struct devnames *dnp, dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2920
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2921
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2922
	 * Look to see if node already exists
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2923
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2924
	LOCK_DEV_OPS(&(dnp->dn_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2925
	if (in_dn_list(dnp, dip)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2926
		cmn_err(CE_NOTE, "add_to_dn_list: node %s already in list",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2927
		    DEVI(dip)->devi_node_name);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2928
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2929
		add_to_ordered_dn_list(dnp, dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2930
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2931
	UNLOCK_DEV_OPS(&(dnp->dn_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2932
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2933
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2934
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2935
remove_from_dn_list(struct devnames *dnp, dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2936
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2937
	dev_info_t **plist;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2938
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2939
	LOCK_DEV_OPS(&(dnp->dn_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2940
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2941
	plist = (dev_info_t **)&dnp->dn_head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2942
	while (*plist && (*plist != dip)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2943
		plist = (dev_info_t **)&DEVI(*plist)->devi_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2944
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2945
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2946
	if (*plist != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2947
		ASSERT(*plist == dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2948
		*plist = (dev_info_t *)(DEVI(dip)->devi_next);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2949
		DEVI(dip)->devi_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2950
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2951
		NDI_CONFIG_DEBUG((CE_NOTE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2952
		    "remove_from_dn_list: node %s not found in list",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2953
		    DEVI(dip)->devi_node_name));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2954
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2955
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2956
	UNLOCK_DEV_OPS(&(dnp->dn_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2957
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2958
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2959
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2960
 * Add and remove reference driver global property list
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2961
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2962
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2963
add_global_props(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2964
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2965
	struct devnames *dnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2966
	ddi_prop_list_t *plist;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2967
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2968
	ASSERT(DEVI(dip)->devi_global_prop_list == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2969
	ASSERT(DEVI(dip)->devi_major != (major_t)-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2970
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2971
	dnp = &devnamesp[DEVI(dip)->devi_major];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2972
	LOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2973
	plist = dnp->dn_global_prop_ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2974
	if (plist == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2975
		UNLOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2976
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2977
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2978
	i_ddi_prop_list_hold(plist, dnp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2979
	UNLOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2980
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2981
	mutex_enter(&DEVI(dip)->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2982
	DEVI(dip)->devi_global_prop_list = plist;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2983
	mutex_exit(&DEVI(dip)->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2984
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2985
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2986
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2987
remove_global_props(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2988
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2989
	ddi_prop_list_t *proplist;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2990
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2991
	mutex_enter(&DEVI(dip)->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2992
	proplist = DEVI(dip)->devi_global_prop_list;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2993
	DEVI(dip)->devi_global_prop_list = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2994
	mutex_exit(&DEVI(dip)->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2995
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2996
	if (proplist) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2997
		major_t major;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2998
		struct devnames *dnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2999
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3000
		major = ddi_driver_major(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3001
		ASSERT(major != (major_t)-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3002
		dnp = &devnamesp[major];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3003
		LOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3004
		i_ddi_prop_list_rele(proplist, dnp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3005
		UNLOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3006
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3007
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3008
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3009
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3010
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3011
 * Set this variable to '0' to disable the optimization,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3012
 * and to 2 to print debug message.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3013
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3014
static int optimize_dtree = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3015
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3016
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3017
debug_dtree(dev_info_t *devi, struct dev_info *adevi, char *service)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3018
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3019
	char *adeviname, *buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3020
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3021
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3022
	 * Don't print unless optimize dtree is set to 2+
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3023
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3024
	if (optimize_dtree <= 1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3025
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3026
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3027
	buf = kmem_alloc(MAXNAMELEN, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3028
	adeviname = ddi_deviname((dev_info_t *)adevi, buf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3029
	if (*adeviname == '\0')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3030
		adeviname = "root";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3031
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3032
	cmn_err(CE_CONT, "%s %s -> %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3033
	    ddi_deviname(devi, buf), service, adeviname);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3034
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3035
	kmem_free(buf, MAXNAMELEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3036
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3037
#else /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3038
#define	debug_dtree(a1, a2, a3)	 /* nothing */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3039
#endif  /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3040
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3041
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3042
ddi_optimize_dtree(dev_info_t *devi)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3043
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3044
	struct dev_info *pdevi;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3045
	struct bus_ops *b;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3046
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3047
	pdevi = DEVI(devi)->devi_parent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3048
	ASSERT(pdevi);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3049
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3050
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3051
	 * Set the unoptimized values
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3052
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3053
	DEVI(devi)->devi_bus_map_fault = pdevi;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3054
	DEVI(devi)->devi_bus_dma_map = pdevi;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3055
	DEVI(devi)->devi_bus_dma_allochdl = pdevi;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3056
	DEVI(devi)->devi_bus_dma_freehdl = pdevi;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3057
	DEVI(devi)->devi_bus_dma_bindhdl = pdevi;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3058
	DEVI(devi)->devi_bus_dma_bindfunc =
4950
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
  3059
	    pdevi->devi_ops->devo_bus_ops->bus_dma_bindhdl;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3060
	DEVI(devi)->devi_bus_dma_unbindhdl = pdevi;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3061
	DEVI(devi)->devi_bus_dma_unbindfunc =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3062
	    pdevi->devi_ops->devo_bus_ops->bus_dma_unbindhdl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3063
	DEVI(devi)->devi_bus_dma_flush = pdevi;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3064
	DEVI(devi)->devi_bus_dma_win = pdevi;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3065
	DEVI(devi)->devi_bus_dma_ctl = pdevi;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3066
	DEVI(devi)->devi_bus_ctl = pdevi;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3067
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3068
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3069
	if (optimize_dtree == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3070
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3071
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3072
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3073
	b = pdevi->devi_ops->devo_bus_ops;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3074
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3075
	if (i_ddi_map_fault == b->bus_map_fault) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3076
		DEVI(devi)->devi_bus_map_fault = pdevi->devi_bus_map_fault;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3077
		debug_dtree(devi, DEVI(devi)->devi_bus_map_fault,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3078
		    "bus_map_fault");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3079
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3080
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3081
	if (ddi_dma_map == b->bus_dma_map) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3082
		DEVI(devi)->devi_bus_dma_map = pdevi->devi_bus_dma_map;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3083
		debug_dtree(devi, DEVI(devi)->devi_bus_dma_map, "bus_dma_map");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3084
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3085
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3086
	if (ddi_dma_allochdl == b->bus_dma_allochdl) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3087
		DEVI(devi)->devi_bus_dma_allochdl =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3088
		    pdevi->devi_bus_dma_allochdl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3089
		debug_dtree(devi, DEVI(devi)->devi_bus_dma_allochdl,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3090
		    "bus_dma_allochdl");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3091
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3092
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3093
	if (ddi_dma_freehdl == b->bus_dma_freehdl) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3094
		DEVI(devi)->devi_bus_dma_freehdl = pdevi->devi_bus_dma_freehdl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3095
		debug_dtree(devi, DEVI(devi)->devi_bus_dma_freehdl,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3096
		    "bus_dma_freehdl");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3097
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3098
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3099
	if (ddi_dma_bindhdl == b->bus_dma_bindhdl) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3100
		DEVI(devi)->devi_bus_dma_bindhdl = pdevi->devi_bus_dma_bindhdl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3101
		DEVI(devi)->devi_bus_dma_bindfunc =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3102
		    pdevi->devi_bus_dma_bindhdl->devi_ops->
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3103
		    devo_bus_ops->bus_dma_bindhdl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3104
		debug_dtree(devi, DEVI(devi)->devi_bus_dma_bindhdl,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3105
		    "bus_dma_bindhdl");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3106
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3107
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3108
	if (ddi_dma_unbindhdl == b->bus_dma_unbindhdl) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3109
		DEVI(devi)->devi_bus_dma_unbindhdl =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3110
		    pdevi->devi_bus_dma_unbindhdl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3111
		DEVI(devi)->devi_bus_dma_unbindfunc =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3112
		    pdevi->devi_bus_dma_unbindhdl->devi_ops->
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3113
		    devo_bus_ops->bus_dma_unbindhdl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3114
		debug_dtree(devi, DEVI(devi)->devi_bus_dma_unbindhdl,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3115
		    "bus_dma_unbindhdl");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3116
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3117
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3118
	if (ddi_dma_flush == b->bus_dma_flush) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3119
		DEVI(devi)->devi_bus_dma_flush = pdevi->devi_bus_dma_flush;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3120
		debug_dtree(devi, DEVI(devi)->devi_bus_dma_flush,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3121
		    "bus_dma_flush");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3122
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3123
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3124
	if (ddi_dma_win == b->bus_dma_win) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3125
		DEVI(devi)->devi_bus_dma_win = pdevi->devi_bus_dma_win;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3126
		debug_dtree(devi, DEVI(devi)->devi_bus_dma_win,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3127
		    "bus_dma_win");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3128
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3129
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3130
	if (ddi_dma_mctl == b->bus_dma_ctl) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3131
		DEVI(devi)->devi_bus_dma_ctl = pdevi->devi_bus_dma_ctl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3132
		debug_dtree(devi, DEVI(devi)->devi_bus_dma_ctl, "bus_dma_ctl");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3133
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3134
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3135
	if (ddi_ctlops == b->bus_ctl) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3136
		DEVI(devi)->devi_bus_ctl = pdevi->devi_bus_ctl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3137
		debug_dtree(devi, DEVI(devi)->devi_bus_ctl, "bus_ctl");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3138
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3139
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3140
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3141
#define	MIN_DEVINFO_LOG_SIZE	max_ncpus
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3142
#define	MAX_DEVINFO_LOG_SIZE	max_ncpus * 10
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3143
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3144
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3145
da_log_init()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3146
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3147
	devinfo_log_header_t *dh;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3148
	int logsize = devinfo_log_size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3149
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3150
	if (logsize == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3151
		logsize = MIN_DEVINFO_LOG_SIZE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3152
	else if (logsize > MAX_DEVINFO_LOG_SIZE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3153
		logsize = MAX_DEVINFO_LOG_SIZE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3154
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3155
	dh = kmem_alloc(logsize * PAGESIZE, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3156
	mutex_init(&dh->dh_lock, NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3157
	dh->dh_max = ((logsize * PAGESIZE) - sizeof (*dh)) /
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3158
	    sizeof (devinfo_audit_t) + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3159
	dh->dh_curr = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3160
	dh->dh_hits = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3161
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3162
	devinfo_audit_log = dh;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3163
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3164
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3165
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3166
 * Log the stack trace in per-devinfo audit structure and also enter
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3167
 * it into a system wide log for recording the time history.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3168
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3169
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3170
da_log_enter(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3171
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3172
	devinfo_audit_t *da_log, *da = DEVI(dip)->devi_audit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3173
	devinfo_log_header_t *dh = devinfo_audit_log;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3174
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3175
	if (devinfo_audit_log == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3176
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3177
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3178
	ASSERT(da != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3179
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3180
	da->da_devinfo = dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3181
	da->da_timestamp = gethrtime();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3182
	da->da_thread = curthread;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3183
	da->da_node_state = DEVI(dip)->devi_node_state;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3184
	da->da_device_state = DEVI(dip)->devi_state;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3185
	da->da_depth = getpcstack(da->da_stack, DDI_STACK_DEPTH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3186
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3187
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3188
	 * Copy into common log and note the location for tracing history
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3189
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3190
	mutex_enter(&dh->dh_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3191
	dh->dh_hits++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3192
	dh->dh_curr++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3193
	if (dh->dh_curr >= dh->dh_max)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3194
		dh->dh_curr -= dh->dh_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3195
	da_log = &dh->dh_entry[dh->dh_curr];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3196
	mutex_exit(&dh->dh_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3197
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3198
	bcopy(da, da_log, sizeof (devinfo_audit_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3199
	da->da_lastlog = da_log;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3200
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3201
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3202
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3203
attach_drivers()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3204
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3205
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3206
	for (i = 0; i < devcnt; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3207
		struct devnames *dnp = &devnamesp[i];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3208
		if ((dnp->dn_flags & DN_FORCE_ATTACH) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3209
		    (ddi_hold_installed_driver((major_t)i) != NULL))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3210
			ddi_rele_driver((major_t)i);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3211
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3212
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3213
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3214
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3215
 * Launch a thread to force attach drivers. This avoids penalty on boot time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3216
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3217
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3218
i_ddi_forceattach_drivers()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3219
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3220
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3221
	 * On i386, the USB drivers need to load and take over from the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3222
	 * SMM BIOS drivers ASAP after consconfig(), so make sure they
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3223
	 * get loaded right here rather than letting the thread do it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3224
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3225
	 * The order here is important.  EHCI must be loaded first, as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3226
	 * we have observed many systems on which hangs occur if the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3227
	 * {U,O}HCI companion controllers take over control from the BIOS
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3228
	 * before EHCI does.  These hangs are also caused by BIOSes leaving
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3229
	 * interrupt-on-port-change enabled in the ehci controller, so that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3230
	 * when uhci/ohci reset themselves, it induces a port change on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3231
	 * the ehci companion controller.  Since there's no interrupt handler
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3232
	 * installed at the time, the moment that interrupt is unmasked, an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3233
	 * interrupt storm will occur.  All this is averted when ehci is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3234
	 * loaded first.  And now you know..... the REST of the story.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3235
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3236
	 * Regardless of platform, ehci needs to initialize first to avoid
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3237
	 * unnecessary connects and disconnects on the companion controller
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3238
	 * when ehci sets up the routing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3239
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3240
	(void) ddi_hold_installed_driver(ddi_name_to_major("ehci"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3241
	(void) ddi_hold_installed_driver(ddi_name_to_major("uhci"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3242
	(void) ddi_hold_installed_driver(ddi_name_to_major("ohci"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3243
1093
4dc7aec69dc9 6299476 DM Does not interoperate with TS90 switch, cannot discover SRP targets
hiremath
parents: 789
diff changeset
  3244
	/*
4dc7aec69dc9 6299476 DM Does not interoperate with TS90 switch, cannot discover SRP targets
hiremath
parents: 789
diff changeset
  3245
	 * Attach IB VHCI driver before the force-attach thread attaches the
4dc7aec69dc9 6299476 DM Does not interoperate with TS90 switch, cannot discover SRP targets
hiremath
parents: 789
diff changeset
  3246
	 * IB HCA driver. IB HCA driver will fail if IB Nexus has not yet
4dc7aec69dc9 6299476 DM Does not interoperate with TS90 switch, cannot discover SRP targets
hiremath
parents: 789
diff changeset
  3247
	 * been attached.
4dc7aec69dc9 6299476 DM Does not interoperate with TS90 switch, cannot discover SRP targets
hiremath
parents: 789
diff changeset
  3248
	 */
4dc7aec69dc9 6299476 DM Does not interoperate with TS90 switch, cannot discover SRP targets
hiremath
parents: 789
diff changeset
  3249
	(void) ddi_hold_installed_driver(ddi_name_to_major("ib"));
4dc7aec69dc9 6299476 DM Does not interoperate with TS90 switch, cannot discover SRP targets
hiremath
parents: 789
diff changeset
  3250
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3251
	(void) thread_create(NULL, 0, (void (*)())attach_drivers, NULL, 0, &p0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3252
	    TS_RUN, minclsyspri);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3253
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3254
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3255
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3256
 * This is a private DDI interface for optimizing boot performance.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3257
 * I/O subsystem initialization is considered complete when devfsadm
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3258
 * is executed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3259
 *
2621
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3260
 * NOTE: The start of syseventd happens to be a convenient indicator
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3261
 *	of the completion of I/O initialization during boot.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3262
 *	The implementation should be replaced by something more robust.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3263
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3264
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3265
i_ddi_io_initialized()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3266
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3267
	extern int sysevent_daemon_init;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3268
	return (sysevent_daemon_init);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3269
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3270
2621
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3271
/*
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3272
 * May be used to determine system boot state
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3273
 * "Available" means the system is for the most part up
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3274
 * and initialized, with all system services either up or
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3275
 * capable of being started.  This state is set by devfsadm
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3276
 * during the boot process.  The /dev filesystem infers
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3277
 * from this when implicit reconfig can be performed,
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3278
 * ie, devfsadm can be invoked.  Please avoid making
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3279
 * further use of this unless it's really necessary.
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3280
 */
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3281
int
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3282
i_ddi_sysavail()
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3283
{
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3284
	return (devname_state & DS_SYSAVAIL);
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3285
}
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3286
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3287
/*
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3288
 * May be used to determine if boot is a reconfigure boot.
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3289
 */
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3290
int
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3291
i_ddi_reconfig()
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3292
{
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3293
	return (devname_state & DS_RECONFIG);
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3294
}
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3295
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3296
/*
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3297
 * Note system services are up, inform /dev.
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3298
 */
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3299
void
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3300
i_ddi_set_sysavail()
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3301
{
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3302
	if ((devname_state & DS_SYSAVAIL) == 0) {
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3303
		devname_state |= DS_SYSAVAIL;
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3304
		sdev_devstate_change();
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3305
	}
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3306
}
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3307
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3308
/*
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3309
 * Note reconfiguration boot, inform /dev.
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3310
 */
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3311
void
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3312
i_ddi_set_reconfig()
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3313
{
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3314
	if ((devname_state & DS_RECONFIG) == 0) {
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3315
		devname_state |= DS_RECONFIG;
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3316
		sdev_devstate_change();
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3317
	}
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3318
}
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  3319
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3320
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3321
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3322
 * device tree walking
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3323
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3324
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3325
struct walk_elem {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3326
	struct walk_elem *next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3327
	dev_info_t *dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3328
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3329
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3330
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3331
free_list(struct walk_elem *list)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3332
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3333
	while (list) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3334
		struct walk_elem *next = list->next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3335
		kmem_free(list, sizeof (*list));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3336
		list = next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3337
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3338
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3339
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3340
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3341
append_node(struct walk_elem **list, dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3342
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3343
	struct walk_elem *tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3344
	struct walk_elem *elem = kmem_alloc(sizeof (*elem), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3345
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3346
	elem->next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3347
	elem->dip = dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3348
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3349
	if (*list == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3350
		*list = elem;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3351
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3352
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3353
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3354
	tail = *list;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3355
	while (tail->next)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3356
		tail = tail->next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3357
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3358
	tail->next = elem;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3359
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3360
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3361
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3362
 * The implementation of ddi_walk_devs().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3363
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3364
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3365
walk_devs(dev_info_t *dip, int (*f)(dev_info_t *, void *), void *arg,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3366
    int do_locking)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3367
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3368
	struct walk_elem *head = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3369
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3370
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3371
	 * Do it in two passes. First pass invoke callback on each
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3372
	 * dip on the sibling list. Second pass invoke callback on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3373
	 * children of each dip.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3374
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3375
	while (dip) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3376
		switch ((*f)(dip, arg)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3377
		case DDI_WALK_TERMINATE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3378
			free_list(head);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3379
			return (DDI_WALK_TERMINATE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3380
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3381
		case DDI_WALK_PRUNESIB:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3382
			/* ignore sibling by setting dip to NULL */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3383
			append_node(&head, dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3384
			dip = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3385
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3386
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3387
		case DDI_WALK_PRUNECHILD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3388
			/* don't worry about children */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3389
			dip = ddi_get_next_sibling(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3390
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3391
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3392
		case DDI_WALK_CONTINUE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3393
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3394
			append_node(&head, dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3395
			dip = ddi_get_next_sibling(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3396
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3397
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3398
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3399
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3400
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3401
	/* second pass */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3402
	while (head) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3403
		int circ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3404
		struct walk_elem *next = head->next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3405
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3406
		if (do_locking)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3407
			ndi_devi_enter(head->dip, &circ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3408
		if (walk_devs(ddi_get_child(head->dip), f, arg, do_locking) ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3409
		    DDI_WALK_TERMINATE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3410
			if (do_locking)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3411
				ndi_devi_exit(head->dip, circ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3412
			free_list(head);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3413
			return (DDI_WALK_TERMINATE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3414
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3415
		if (do_locking)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3416
			ndi_devi_exit(head->dip, circ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3417
		kmem_free(head, sizeof (*head));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3418
		head = next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3419
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3420
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3421
	return (DDI_WALK_CONTINUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3422
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3423
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3424
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3425
 * This general-purpose routine traverses the tree of dev_info nodes,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3426
 * starting from the given node, and calls the given function for each
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3427
 * node that it finds with the current node and the pointer arg (which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3428
 * can point to a structure of information that the function
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3429
 * needs) as arguments.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3430
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3431
 * It does the walk a layer at a time, not depth-first. The given function
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3432
 * must return one of the following values:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3433
 *	DDI_WALK_CONTINUE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3434
 *	DDI_WALK_PRUNESIB
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3435
 *	DDI_WALK_PRUNECHILD
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3436
 *	DDI_WALK_TERMINATE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3437
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3438
 * N.B. Since we walk the sibling list, the caller must ensure that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3439
 *	the parent of dip is held against changes, unless the parent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3440
 *	is rootnode.  ndi_devi_enter() on the parent is sufficient.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3441
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3442
 *	To avoid deadlock situations, caller must not attempt to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3443
 *	configure/unconfigure/remove device node in (*f)(), nor should
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  3444
 *	it attempt to recurse on other nodes in the system. Any
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  3445
 *	ndi_devi_enter() done by (*f)() must occur 'at-or-below' the
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  3446
 *	node entered prior to ddi_walk_devs(). Furthermore, if (*f)()
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  3447
 *	does any multi-threading (in framework *or* in driver) then the
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  3448
 *	ndi_devi_enter() calls done by dependent threads must be
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  3449
 *	'strictly-below'.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3450
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3451
 *	This is not callable from device autoconfiguration routines.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3452
 *	They include, but not limited to, _init(9e), _fini(9e), probe(9e),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3453
 *	attach(9e), and detach(9e).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3454
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3455
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3456
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3457
ddi_walk_devs(dev_info_t *dip, int (*f)(dev_info_t *, void *), void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3458
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3459
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3460
	ASSERT(dip == NULL || ddi_get_parent(dip) == NULL ||
4950
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
  3461
	    DEVI_BUSY_OWNED(ddi_get_parent(dip)));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3462
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3463
	(void) walk_devs(dip, f, arg, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3464
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3465
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3466
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3467
 * This is a general-purpose routine traverses the per-driver list
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3468
 * and calls the given function for each node. must return one of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3469
 * the following values:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3470
 *	DDI_WALK_CONTINUE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3471
 *	DDI_WALK_TERMINATE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3472
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3473
 * N.B. The same restrictions from ddi_walk_devs() apply.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3474
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3475
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3476
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3477
e_ddi_walk_driver(char *drv, int (*f)(dev_info_t *, void *), void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3478
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3479
	major_t major;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3480
	struct devnames *dnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3481
	dev_info_t *dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3482
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3483
	major = ddi_name_to_major(drv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3484
	if (major == (major_t)-1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3485
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3486
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3487
	dnp = &devnamesp[major];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3488
	LOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3489
	dip = dnp->dn_head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3490
	while (dip) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3491
		ndi_hold_devi(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3492
		UNLOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3493
		if ((*f)(dip, arg) == DDI_WALK_TERMINATE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3494
			ndi_rele_devi(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3495
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3496
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3497
		LOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3498
		ndi_rele_devi(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3499
		dip = ddi_get_next(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3500
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3501
	UNLOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3502
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3503
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3504
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3505
 * argument to i_find_devi, a devinfo node search callback function.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3506
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3507
struct match_info {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3508
	dev_info_t	*dip;		/* result */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3509
	char		*nodename;	/* if non-null, nodename must match */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3510
	int		instance;	/* if != -1, instance must match */
1333
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  3511
	int		attached;	/* if != 0, i_ddi_devi_attached() */
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3512
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3513
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3514
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3515
i_find_devi(dev_info_t *dip, void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3516
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3517
	struct match_info *info = (struct match_info *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3518
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3519
	if (((info->nodename == NULL) ||
4950
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
  3520
	    (strcmp(ddi_node_name(dip), info->nodename) == 0)) &&
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3521
	    ((info->instance == -1) ||
4950
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
  3522
	    (ddi_get_instance(dip) == info->instance)) &&
1333
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  3523
	    ((info->attached == 0) || i_ddi_devi_attached(dip))) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3524
		info->dip = dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3525
		ndi_hold_devi(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3526
		return (DDI_WALK_TERMINATE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3527
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3528
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3529
	return (DDI_WALK_CONTINUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3530
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3531
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3532
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3533
 * Find dip with a known node name and instance and return with it held
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3534
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3535
dev_info_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3536
ddi_find_devinfo(char *nodename, int instance, int attached)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3537
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3538
	struct match_info	info;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3539
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3540
	info.nodename = nodename;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3541
	info.instance = instance;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3542
	info.attached = attached;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3543
	info.dip = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3544
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3545
	ddi_walk_devs(ddi_root_node(), i_find_devi, &info);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3546
	return (info.dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3547
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3548
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3549
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3550
 * Parse for name, addr, and minor names. Some args may be NULL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3551
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3552
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3553
i_ddi_parse_name(char *name, char **nodename, char **addrname, char **minorname)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3554
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3555
	char *cp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3556
	static char nulladdrname[] = "";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3557
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3558
	/* default values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3559
	if (nodename)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3560
		*nodename = name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3561
	if (addrname)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3562
		*addrname = nulladdrname;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3563
	if (minorname)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3564
		*minorname = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3565
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3566
	cp = name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3567
	while (*cp != '\0') {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3568
		if (addrname && *cp == '@') {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3569
			*addrname = cp + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3570
			*cp = '\0';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3571
		} else if (minorname && *cp == ':') {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3572
			*minorname = cp + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3573
			*cp = '\0';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3574
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3575
		++cp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3576
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3577
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3578
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3579
static char *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3580
child_path_to_driver(dev_info_t *parent, char *child_name, char *unit_address)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3581
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3582
	char *p, *drvname = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3583
	major_t maj;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3584
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3585
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3586
	 * Construct the pathname and ask the implementation
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3587
	 * if it can do a driver = f(pathname) for us, if not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3588
	 * we'll just default to using the node-name that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3589
	 * was given to us.  We want to do this first to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3590
	 * allow the platform to use 'generic' names for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3591
	 * legacy device drivers.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3592
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3593
	p = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3594
	(void) ddi_pathname(parent, p);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3595
	(void) strcat(p, "/");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3596
	(void) strcat(p, child_name);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3597
	if (unit_address && *unit_address) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3598
		(void) strcat(p, "@");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3599
		(void) strcat(p, unit_address);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3600
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3601
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3602
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3603
	 * Get the binding. If there is none, return the child_name
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3604
	 * and let the caller deal with it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3605
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3606
	maj = path_to_major(p);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3607
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3608
	kmem_free(p, MAXPATHLEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3609
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3610
	if (maj != (major_t)-1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3611
		drvname = ddi_major_to_name(maj);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3612
	if (drvname == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3613
		drvname = child_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3614
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3615
	return (drvname);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3616
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3617
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3618
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3619
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3620
 * Given the pathname of a device, fill in the dev_info_t value and/or the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3621
 * dev_t value and/or the spectype, depending on which parameters are non-NULL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3622
 * If there is an error, this function returns -1.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3623
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3624
 * NOTE: If this function returns the dev_info_t structure, then it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3625
 * does so with a hold on the devi. Caller should ensure that they get
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3626
 * decremented via ddi_release_devi() or ndi_rele_devi();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3627
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3628
 * This function can be invoked in the boot case for a pathname without
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3629
 * device argument (:xxxx), traditionally treated as a minor name.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3630
 * In this case, we do the following
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3631
 * (1) search the minor node of type DDM_DEFAULT.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3632
 * (2) if no DDM_DEFAULT minor exists, then the first non-alias minor is chosen.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3633
 * (3) if neither exists, a dev_t is faked with minor number = instance.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3634
 * As of S9 FCS, no instance of #1 exists. #2 is used by several platforms
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3635
 * to default the boot partition to :a possibly by other OBP definitions.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3636
 * #3 is used for booting off network interfaces, most SPARC network
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3637
 * drivers support Style-2 only, so only DDM_ALIAS minor exists.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3638
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3639
 * It is possible for OBP to present device args at the end of the path as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3640
 * well as in the middle. For example, with IB the following strings are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3641
 * valid boot paths.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3642
 *	a /pci@8,700000/ib@1,2:port=1,pkey=ff,dhcp,...
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3643
 *	b /pci@8,700000/ib@1,1:port=1/ioc@xxxxxx,yyyyyyy:dhcp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3644
 * Case (a), we first look for minor node "port=1,pkey...".
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3645
 * Failing that, we will pass "port=1,pkey..." to the bus_config
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3646
 * entry point of ib (HCA) driver.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3647
 * Case (b), configure ib@1,1 as usual. Then invoke ib's bus_config
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3648
 * with argument "ioc@xxxxxxx,yyyyyyy:port=1". After configuring
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3649
 * the ioc, look for minor node dhcp. If not found, pass ":dhcp"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3650
 * to ioc's bus_config entry point.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3651
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3652
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3653
resolve_pathname(char *pathname,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3654
	dev_info_t **dipp, dev_t *devtp, int *spectypep)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3655
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3656
	int error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3657
	dev_info_t *parent, *child;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3658
	struct pathname pn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3659
	char *component, *config_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3660
	char *minorname = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3661
	char *prev_minor = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3662
	dev_t devt = NODEV;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3663
	int spectype;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3664
	struct ddi_minor_data *dmn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3665
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3666
	if (*pathname != '/')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3667
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3668
	parent = ddi_root_node();	/* Begin at the top of the tree */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3669
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3670
	if (error = pn_get(pathname, UIO_SYSSPACE, &pn))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3671
		return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3672
	pn_skipslash(&pn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3673
1333
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  3674
	ASSERT(i_ddi_devi_attached(parent));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3675
	ndi_hold_devi(parent);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3676
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3677
	component = kmem_alloc(MAXNAMELEN, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3678
	config_name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3679
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3680
	while (pn_pathleft(&pn)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3681
		/* remember prev minor (:xxx) in the middle of path */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3682
		if (minorname)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3683
			prev_minor = i_ddi_strdup(minorname, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3684
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3685
		/* Get component and chop off minorname */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3686
		(void) pn_getcomponent(&pn, component);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3687
		i_ddi_parse_name(component, NULL, NULL, &minorname);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3688
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3689
		if (prev_minor == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3690
			(void) snprintf(config_name, MAXNAMELEN, "%s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3691
			    component);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3692
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3693
			(void) snprintf(config_name, MAXNAMELEN, "%s:%s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3694
			    component, prev_minor);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3695
			kmem_free(prev_minor, strlen(prev_minor) + 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3696
			prev_minor = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3697
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3698
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3699
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3700
		 * Find and configure the child
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3701
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3702
		if (ndi_devi_config_one(parent, config_name, &child,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3703
		    NDI_PROMNAME | NDI_NO_EVENT) != NDI_SUCCESS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3704
			ndi_rele_devi(parent);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3705
			pn_free(&pn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3706
			kmem_free(component, MAXNAMELEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3707
			kmem_free(config_name, MAXNAMELEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3708
			return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3709
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3710
1333
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  3711
		ASSERT(i_ddi_devi_attached(child));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3712
		ndi_rele_devi(parent);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3713
		parent = child;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3714
		pn_skipslash(&pn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3715
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3716
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3717
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3718
	 * First look for a minor node matching minorname.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3719
	 * Failing that, try to pass minorname to bus_config().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3720
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3721
	if (minorname && i_ddi_minorname_to_devtspectype(parent,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3722
	    minorname, &devt, &spectype) == DDI_FAILURE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3723
		(void) snprintf(config_name, MAXNAMELEN, "%s", minorname);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3724
		if (ndi_devi_config_obp_args(parent,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3725
		    config_name, &child, 0) != NDI_SUCCESS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3726
			ndi_rele_devi(parent);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3727
			pn_free(&pn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3728
			kmem_free(component, MAXNAMELEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3729
			kmem_free(config_name, MAXNAMELEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3730
			NDI_CONFIG_DEBUG((CE_NOTE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3731
			    "%s: minor node not found\n", pathname));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3732
			return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3733
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3734
		minorname = NULL;	/* look for default minor */
1333
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  3735
		ASSERT(i_ddi_devi_attached(child));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3736
		ndi_rele_devi(parent);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3737
		parent = child;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3738
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3739
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3740
	if (devtp || spectypep) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3741
		if (minorname == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3742
			/* search for a default entry */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3743
			mutex_enter(&(DEVI(parent)->devi_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3744
			for (dmn = DEVI(parent)->devi_minor; dmn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3745
			    dmn = dmn->next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3746
				if (dmn->type == DDM_DEFAULT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3747
					devt = dmn->ddm_dev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3748
					spectype = dmn->ddm_spec_type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3749
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3750
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3751
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3752
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3753
			if (devt == NODEV) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3754
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3755
				 * No default minor node, try the first one;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3756
				 * else, assume 1-1 instance-minor mapping
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3757
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3758
				dmn = DEVI(parent)->devi_minor;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3759
				if (dmn && ((dmn->type == DDM_MINOR) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3760
				    (dmn->type == DDM_INTERNAL_PATH))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3761
					devt = dmn->ddm_dev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3762
					spectype = dmn->ddm_spec_type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3763
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3764
					devt = makedevice(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3765
					    DEVI(parent)->devi_major,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3766
					    ddi_get_instance(parent));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3767
					spectype = S_IFCHR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3768
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3769
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3770
			mutex_exit(&(DEVI(parent)->devi_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3771
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3772
		if (devtp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3773
			*devtp = devt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3774
		if (spectypep)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3775
			*spectypep = spectype;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3776
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3777
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3778
	pn_free(&pn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3779
	kmem_free(component, MAXNAMELEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3780
	kmem_free(config_name, MAXNAMELEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3781
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3782
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3783
	 * If there is no error, return the appropriate parameters
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3784
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3785
	if (dipp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3786
		*dipp = parent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3787
	else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3788
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3789
		 * We should really keep the ref count to keep the node from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3790
		 * detaching but ddi_pathname_to_dev_t() specifies a NULL dipp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3791
		 * so we have no way of passing back the held dip.  Not holding
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3792
		 * the dip allows detaches to occur - which can cause problems
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3793
		 * for subsystems which call ddi_pathname_to_dev_t (console).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3794
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3795
		 * Instead of holding the dip, we place a ddi-no-autodetach
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3796
		 * property on the node to prevent auto detaching.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3797
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3798
		 * The right fix is to remove ddi_pathname_to_dev_t and replace
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3799
		 * it, and all references, with a call that specifies a dipp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3800
		 * In addition, the callers of this new interfaces would then
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3801
		 * need to call ndi_rele_devi when the reference is complete.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3802
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3803
		(void) ddi_prop_update_int(DDI_DEV_T_NONE, parent,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3804
		    DDI_NO_AUTODETACH, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3805
		ndi_rele_devi(parent);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3806
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3807
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3808
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3809
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3810
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3811
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3812
 * Given the pathname of a device, return the dev_t of the corresponding
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3813
 * device.  Returns NODEV on failure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3814
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3815
 * Note that this call sets the DDI_NO_AUTODETACH property on the devinfo node.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3816
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3817
dev_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3818
ddi_pathname_to_dev_t(char *pathname)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3819
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3820
	dev_t devt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3821
	int error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3822
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3823
	error = resolve_pathname(pathname, NULL, &devt, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3824
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3825
	return (error ? NODEV : devt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3826
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3827
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3828
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3829
 * Translate a prom pathname to kernel devfs pathname.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3830
 * Caller is assumed to allocate devfspath memory of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3831
 * size at least MAXPATHLEN
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3832
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3833
 * The prom pathname may not include minor name, but
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3834
 * devfs pathname has a minor name portion.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3835
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3836
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3837
i_ddi_prompath_to_devfspath(char *prompath, char *devfspath)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3838
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3839
	dev_t		devt = (dev_t)NODEV;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3840
	dev_info_t	*dip = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3841
	char		*minor_name = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3842
	int		spectype;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3843
	int		error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3844
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3845
	error = resolve_pathname(prompath, &dip, &devt, &spectype);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3846
	if (error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3847
		return (DDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3848
	ASSERT(dip && devt != NODEV);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3849
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3850
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3851
	 * Get in-kernel devfs pathname
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3852
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3853
	(void) ddi_pathname(dip, devfspath);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3854
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3855
	mutex_enter(&(DEVI(dip)->devi_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3856
	minor_name = i_ddi_devtspectype_to_minorname(dip, devt, spectype);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3857
	if (minor_name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3858
		(void) strcat(devfspath, ":");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3859
		(void) strcat(devfspath, minor_name);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3860
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3861
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3862
		 * If minor_name is NULL, we have an alias minor node.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3863
		 * So manufacture a path to the corresponding clone minor.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3864
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3865
		(void) snprintf(devfspath, MAXPATHLEN, "%s:%s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3866
		    CLONE_PATH, ddi_driver_name(dip));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3867
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3868
	mutex_exit(&(DEVI(dip)->devi_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3869
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3870
	/* release hold from resolve_pathname() */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3871
	ndi_rele_devi(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3872
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3873
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3874
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3875
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3876
 * Reset all the pure leaf drivers on the system at halt time
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3877
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3878
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3879
reset_leaf_device(dev_info_t *dip, void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3880
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3881
	_NOTE(ARGUNUSED(arg))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3882
	struct dev_ops *ops;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3883
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3884
	/* if the device doesn't need to be reset then there's nothing to do */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3885
	if (!DEVI_NEED_RESET(dip))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3886
		return (DDI_WALK_CONTINUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3887
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3888
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3889
	 * if the device isn't a char/block device or doesn't have a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3890
	 * reset entry point then there's nothing to do.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3891
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3892
	ops = ddi_get_driver(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3893
	if ((ops == NULL) || (ops->devo_cb_ops == NULL) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3894
	    (ops->devo_reset == nodev) || (ops->devo_reset == nulldev) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3895
	    (ops->devo_reset == NULL))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3896
		return (DDI_WALK_CONTINUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3897
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3898
	if (DEVI_IS_ATTACHING(dip) || DEVI_IS_DETACHING(dip)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3899
		static char path[MAXPATHLEN];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3900
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3901
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3902
		 * bad news, this device has blocked in it's attach or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3903
		 * detach routine, which means it not safe to call it's
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3904
		 * devo_reset() entry point.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3905
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3906
		cmn_err(CE_WARN, "unable to reset device: %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3907
		    ddi_pathname(dip, path));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3908
		return (DDI_WALK_CONTINUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3909
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3910
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3911
	NDI_CONFIG_DEBUG((CE_NOTE, "resetting %s%d\n",
4950
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
  3912
	    ddi_driver_name(dip), ddi_get_instance(dip)));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3913
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3914
	(void) devi_reset(dip, DDI_RESET_FORCE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3915
	return (DDI_WALK_CONTINUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3916
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3917
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3918
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3919
reset_leaves(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3920
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3921
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3922
	 * if we're reached here, the device tree better not be changing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3923
	 * so either devinfo_freeze better be set or we better be panicing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3924
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3925
	ASSERT(devinfo_freeze || panicstr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3926
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3927
	(void) walk_devs(top_devinfo, reset_leaf_device, NULL, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3928
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3929
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3930
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3931
 * devtree_freeze() must be called before reset_leaves() during a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3932
 * normal system shutdown.  It attempts to ensure that there are no
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3933
 * outstanding attach or detach operations in progress when reset_leaves()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3934
 * is invoked.  It must be called before the system becomes single-threaded
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3935
 * because device attach and detach are multi-threaded operations.  (note
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3936
 * that during system shutdown the system doesn't actually become
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3937
 * single-thread since other threads still exist, but the shutdown thread
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3938
 * will disable preemption for itself, raise it's pil, and stop all the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3939
 * other cpus in the system there by effectively making the system
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3940
 * single-threaded.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3941
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3942
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3943
devtree_freeze(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3944
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3945
	int delayed = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3946
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3947
	/* if we're panicing then the device tree isn't going to be changing */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3948
	if (panicstr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3949
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3950
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3951
	/* stop all dev_info state changes in the device tree */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3952
	devinfo_freeze = gethrtime();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3953
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3954
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3955
	 * if we're not panicing and there are on-going attach or detach
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3956
	 * operations, wait for up to 3 seconds for them to finish.  This
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3957
	 * is a randomly chosen interval but this should be ok because:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3958
	 * - 3 seconds is very small relative to the deadman timer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3959
	 * - normal attach and detach operations should be very quick.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3960
	 * - attach and detach operations are fairly rare.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3961
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3962
	while (!panicstr && atomic_add_long_nv(&devinfo_attach_detach, 0) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3963
	    (delayed < 3)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3964
		delayed += 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3965
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3966
		/* do a sleeping wait for one second */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3967
		ASSERT(!servicing_interrupt());
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3968
		delay(drv_usectohz(MICROSEC));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3969
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3970
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3971
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3972
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3973
bind_dip(dev_info_t *dip, void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3974
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3975
	_NOTE(ARGUNUSED(arg))
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  3976
	char	*path;
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  3977
	major_t	major, pmajor;
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  3978
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  3979
	/*
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  3980
	 * If the node is currently bound to the wrong driver, try to unbind
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  3981
	 * so that we can rebind to the correct driver.
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  3982
	 */
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  3983
	if (i_ddi_node_state(dip) >= DS_BOUND) {
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  3984
		major = ddi_compatible_driver_major(dip, NULL);
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  3985
		if ((DEVI(dip)->devi_major == major) &&
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  3986
		    (i_ddi_node_state(dip) >= DS_INITIALIZED)) {
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  3987
			/*
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  3988
			 * Check for a path-oriented driver alias that
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  3989
			 * takes precedence over current driver binding.
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  3990
			 */
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  3991
			path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  3992
			(void) ddi_pathname(dip, path);
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  3993
			pmajor = ddi_name_to_major(path);
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  3994
			if ((pmajor != (major_t)-1) &&
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  3995
			    !(devnamesp[pmajor].dn_flags & DN_DRIVER_REMOVED))
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  3996
				major = pmajor;
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  3997
			kmem_free(path, MAXPATHLEN);
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  3998
		}
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  3999
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  4000
		/* attempt unbind if current driver is incorrect */
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  4001
		if ((major != (major_t)-1) &&
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  4002
		    !(devnamesp[major].dn_flags & DN_DRIVER_REMOVED) &&
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  4003
		    (major != DEVI(dip)->devi_major))
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  4004
			(void) ndi_devi_unbind_driver(dip);
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  4005
	}
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  4006
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  4007
	/* If unbound, try to bind to a driver */
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4008
	if (i_ddi_node_state(dip) < DS_BOUND)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4009
		(void) ndi_devi_bind_driver(dip, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4010
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4011
	return (DDI_WALK_CONTINUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4012
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4013
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4014
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4015
i_ddi_bind_devs(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4016
{
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  4017
	/* flush devfs so that ndi_devi_unbind_driver will work when possible */
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  4018
	(void) devfs_clean(top_devinfo, NULL, 0);
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  4019
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4020
	ddi_walk_devs(top_devinfo, bind_dip, (void *)NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4021
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4022
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4023
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4024
unbind_children(dev_info_t *dip, void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4025
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4026
	int circ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4027
	dev_info_t *cdip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4028
	major_t major = (major_t)(uintptr_t)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4029
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4030
	ndi_devi_enter(dip, &circ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4031
	cdip = ddi_get_child(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4032
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4033
	 * We are called either from rem_drv or update_drv.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4034
	 * In both cases, we unbind persistent nodes and destroy
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4035
	 * .conf nodes. In the case of rem_drv, this will be the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4036
	 * final state. In the case of update_drv, i_ddi_bind_devs()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4037
	 * will be invoked later to reenumerate (new) driver.conf
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4038
	 * rebind persistent nodes.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4039
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4040
	while (cdip) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4041
		dev_info_t *next = ddi_get_next_sibling(cdip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4042
		if ((i_ddi_node_state(cdip) > DS_INITIALIZED) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4043
		    (ddi_driver_major(cdip) != major)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4044
			cdip = next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4045
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4046
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4047
		(void) ndi_devi_unbind_driver(cdip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4048
		if (ndi_dev_is_persistent_node(cdip) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4049
			(void) ddi_remove_child(cdip, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4050
		cdip = next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4051
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4052
	ndi_devi_exit(dip, circ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4053
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4054
	return (DDI_WALK_CONTINUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4055
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4056
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4057
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4058
i_ddi_unbind_devs(major_t major)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4059
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4060
	ddi_walk_devs(top_devinfo, unbind_children, (void *)(uintptr_t)major);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4061
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4062
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4063
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4064
 * I/O Hotplug control
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4065
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4066
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4067
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4068
 * create and attach a dev_info node from a .conf file spec
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4069
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4070
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4071
init_spec_child(dev_info_t *pdip, struct hwc_spec *specp, uint_t flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4072
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4073
	_NOTE(ARGUNUSED(flags))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4074
	dev_info_t *dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4075
	char *node_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4076
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4077
	if (((node_name = specp->hwc_devi_name) == NULL) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4078
	    (ddi_name_to_major(node_name) == (major_t)-1)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4079
		char *tmp = node_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4080
		if (tmp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4081
			tmp = "<none>";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4082
		cmn_err(CE_CONT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4083
		    "init_spec_child: parent=%s, bad spec (%s)\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4084
		    ddi_node_name(pdip), tmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4085
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4086
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4087
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 693
diff changeset
  4088
	dip = i_ddi_alloc_node(pdip, node_name, (pnode_t)DEVI_PSEUDO_NODEID,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4089
	    -1, specp->hwc_devi_sys_prop_ptr, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4090
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4091
	if (dip == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4092
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4093
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4094
	if (ddi_initchild(pdip, dip) != DDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4095
		(void) ddi_remove_child(dip, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4096
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4097
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4098
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4099
 * Lookup hwc specs from hash tables and make children from the spec
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4100
 * Because some .conf children are "merge" nodes, we also initialize
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4101
 * .conf children to merge properties onto hardware nodes.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4102
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4103
 * The pdip must be held busy.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4104
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4105
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4106
i_ndi_make_spec_children(dev_info_t *pdip, uint_t flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4107
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4108
	extern struct hwc_spec *hwc_get_child_spec(dev_info_t *, major_t);
298
dde238e879a8 6303210 Assertion failure: DEVI(pdip)->devi_flags & DEVI_MADE_CHILDREN
cth
parents: 53
diff changeset
  4109
	int			circ;
dde238e879a8 6303210 Assertion failure: DEVI(pdip)->devi_flags & DEVI_MADE_CHILDREN
cth
parents: 53
diff changeset
  4110
	struct hwc_spec		*list, *spec;
dde238e879a8 6303210 Assertion failure: DEVI(pdip)->devi_flags & DEVI_MADE_CHILDREN
cth
parents: 53
diff changeset
  4111
dde238e879a8 6303210 Assertion failure: DEVI(pdip)->devi_flags & DEVI_MADE_CHILDREN
cth
parents: 53
diff changeset
  4112
	ndi_devi_enter(pdip, &circ);
dde238e879a8 6303210 Assertion failure: DEVI(pdip)->devi_flags & DEVI_MADE_CHILDREN
cth
parents: 53
diff changeset
  4113
	if (DEVI(pdip)->devi_flags & DEVI_MADE_CHILDREN) {
dde238e879a8 6303210 Assertion failure: DEVI(pdip)->devi_flags & DEVI_MADE_CHILDREN
cth
parents: 53
diff changeset
  4114
		ndi_devi_exit(pdip, circ);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4115
		return (DDI_SUCCESS);
298
dde238e879a8 6303210 Assertion failure: DEVI(pdip)->devi_flags & DEVI_MADE_CHILDREN
cth
parents: 53
diff changeset
  4116
	}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4117
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4118
	list = hwc_get_child_spec(pdip, (major_t)-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4119
	for (spec = list; spec != NULL; spec = spec->hwc_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4120
		init_spec_child(pdip, spec, flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4121
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4122
	hwc_free_spec_list(list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4123
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4124
	mutex_enter(&DEVI(pdip)->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4125
	DEVI(pdip)->devi_flags |= DEVI_MADE_CHILDREN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4126
	mutex_exit(&DEVI(pdip)->devi_lock);
298
dde238e879a8 6303210 Assertion failure: DEVI(pdip)->devi_flags & DEVI_MADE_CHILDREN
cth
parents: 53
diff changeset
  4127
	ndi_devi_exit(pdip, circ);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4128
	return (DDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4129
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4130
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4131
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4132
 * Run initchild on all child nodes such that instance assignment
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4133
 * for multiport network cards are contiguous.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4134
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4135
 * The pdip must be held busy.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4136
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4137
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4138
i_ndi_init_hw_children(dev_info_t *pdip, uint_t flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4139
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4140
	dev_info_t *dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4141
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4142
	ASSERT(DEVI(pdip)->devi_flags & DEVI_MADE_CHILDREN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4143
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4144
	/* contiguous instance assignment */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4145
	e_ddi_enter_instance();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4146
	dip = ddi_get_child(pdip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4147
	while (dip) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4148
		if (ndi_dev_is_persistent_node(dip))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4149
			(void) i_ndi_config_node(dip, DS_INITIALIZED, flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4150
		dip = ddi_get_next_sibling(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4151
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4152
	e_ddi_exit_instance();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4153
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4154
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4155
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4156
 * report device status
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4157
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4158
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4159
i_ndi_devi_report_status_change(dev_info_t *dip, char *path)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4160
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4161
	char *status;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4162
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4163
	if (!DEVI_NEED_REPORT(dip) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4164
	    (i_ddi_node_state(dip) < DS_INITIALIZED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4165
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4166
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4167
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4168
	if (DEVI_IS_DEVICE_OFFLINE(dip)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4169
		status = "offline";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4170
	} else if (DEVI_IS_DEVICE_DOWN(dip)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4171
		status = "down";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4172
	} else if (DEVI_IS_BUS_QUIESCED(dip)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4173
		status = "quiesced";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4174
	} else if (DEVI_IS_BUS_DOWN(dip)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4175
		status = "down";
1333
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  4176
	} else if (i_ddi_devi_attached(dip)) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4177
		status = "online";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4178
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4179
		status = "unknown";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4180
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4181
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4182
	if (path == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4183
		path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4184
		cmn_err(CE_CONT, "?%s (%s%d) %s\n",
4950
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
  4185
		    ddi_pathname(dip, path), ddi_driver_name(dip),
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
  4186
		    ddi_get_instance(dip), status);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4187
		kmem_free(path, MAXPATHLEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4188
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4189
		cmn_err(CE_CONT, "?%s (%s%d) %s\n",
4950
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
  4190
		    path, ddi_driver_name(dip),
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
  4191
		    ddi_get_instance(dip), status);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4192
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4193
495
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  4194
	mutex_enter(&(DEVI(dip)->devi_lock));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4195
	DEVI_REPORT_DONE(dip);
495
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  4196
	mutex_exit(&(DEVI(dip)->devi_lock));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4197
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4198
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4199
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4200
 * log a notification that a dev_info node has been configured.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4201
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4202
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4203
i_log_devfs_add_devinfo(dev_info_t *dip, uint_t flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4204
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4205
	int se_err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4206
	char *pathname;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4207
	sysevent_t *ev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4208
	sysevent_id_t eid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4209
	sysevent_value_t se_val;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4210
	sysevent_attr_list_t *ev_attr_list = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4211
	char *class_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4212
	int no_transport = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4213
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4214
	ASSERT(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4215
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4216
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4217
	 * Invalidate the devinfo snapshot cache
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4218
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4219
	i_ddi_di_cache_invalidate(KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4220
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4221
	/* do not generate ESC_DEVFS_DEVI_ADD event during boot */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4222
	if (!i_ddi_io_initialized())
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4223
		return (DDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4224
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4225
	ev = sysevent_alloc(EC_DEVFS, ESC_DEVFS_DEVI_ADD, EP_DDI, SE_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4226
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4227
	pathname = kmem_alloc(MAXPATHLEN, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4228
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4229
	(void) ddi_pathname(dip, pathname);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4230
	ASSERT(strlen(pathname));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4231
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4232
	se_val.value_type = SE_DATA_TYPE_STRING;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4233
	se_val.value.sv_string = pathname;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4234
	if (sysevent_add_attr(&ev_attr_list, DEVFS_PATHNAME,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4235
	    &se_val, SE_SLEEP) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4236
		goto fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4237
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4238
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4239
	/* add the device class attribute */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4240
	if ((class_name = i_ddi_devi_class(dip)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4241
		se_val.value_type = SE_DATA_TYPE_STRING;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4242
		se_val.value.sv_string = class_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4243
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4244
		if (sysevent_add_attr(&ev_attr_list,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4245
		    DEVFS_DEVI_CLASS, &se_val, SE_SLEEP) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4246
			sysevent_free_attr(ev_attr_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4247
			goto fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4248
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4249
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4250
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4251
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4252
	 * must log a branch event too unless NDI_BRANCH_EVENT_OP is set,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4253
	 * in which case the branch event will be logged by the caller
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4254
	 * after the entire branch has been configured.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4255
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4256
	if ((flags & NDI_BRANCH_EVENT_OP) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4257
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4258
		 * Instead of logging a separate branch event just add
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4259
		 * DEVFS_BRANCH_EVENT attribute. It indicates devfsadmd to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4260
		 * generate a EC_DEV_BRANCH event.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4261
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4262
		se_val.value_type = SE_DATA_TYPE_INT32;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4263
		se_val.value.sv_int32 = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4264
		if (sysevent_add_attr(&ev_attr_list,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4265
		    DEVFS_BRANCH_EVENT, &se_val, SE_SLEEP) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4266
			sysevent_free_attr(ev_attr_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4267
			goto fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4268
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4269
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4270
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4271
	if (sysevent_attach_attributes(ev, ev_attr_list) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4272
		sysevent_free_attr(ev_attr_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4273
		goto fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4274
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4275
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4276
	if ((se_err = log_sysevent(ev, SE_SLEEP, &eid)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4277
		if (se_err == SE_NO_TRANSPORT)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4278
			no_transport = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4279
		goto fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4280
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4281
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4282
	sysevent_free(ev);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4283
	kmem_free(pathname, MAXPATHLEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4284
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4285
	return (DDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4286
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4287
fail:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4288
	cmn_err(CE_WARN, "failed to log ESC_DEVFS_DEVI_ADD event for %s%s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4289
	    pathname, (no_transport) ? " (syseventd not responding)" : "");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4290
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4291
	cmn_err(CE_WARN, "/dev may not be current for driver %s. "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4292
	    "Run devfsadm -i %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4293
	    ddi_driver_name(dip), ddi_driver_name(dip));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4294
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4295
	sysevent_free(ev);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4296
	kmem_free(pathname, MAXPATHLEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4297
	return (DDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4298
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4299
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4300
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4301
 * log a notification that a dev_info node has been unconfigured.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4302
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4303
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4304
i_log_devfs_remove_devinfo(char *pathname, char *class_name, char *driver_name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4305
    int instance, uint_t flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4306
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4307
	sysevent_t *ev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4308
	sysevent_id_t eid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4309
	sysevent_value_t se_val;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4310
	sysevent_attr_list_t *ev_attr_list = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4311
	int se_err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4312
	int no_transport = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4313
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4314
	i_ddi_di_cache_invalidate(KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4315
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4316
	if (!i_ddi_io_initialized())
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4317
		return (DDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4318
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4319
	ev = sysevent_alloc(EC_DEVFS, ESC_DEVFS_DEVI_REMOVE, EP_DDI, SE_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4320
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4321
	se_val.value_type = SE_DATA_TYPE_STRING;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4322
	se_val.value.sv_string = pathname;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4323
	if (sysevent_add_attr(&ev_attr_list, DEVFS_PATHNAME,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4324
	    &se_val, SE_SLEEP) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4325
		goto fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4326
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4327
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4328
	if (class_name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4329
		/* add the device class, driver name and instance attributes */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4330
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4331
		se_val.value_type = SE_DATA_TYPE_STRING;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4332
		se_val.value.sv_string = class_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4333
		if (sysevent_add_attr(&ev_attr_list,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4334
		    DEVFS_DEVI_CLASS, &se_val, SE_SLEEP) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4335
			sysevent_free_attr(ev_attr_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4336
			goto fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4337
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4338
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4339
		se_val.value_type = SE_DATA_TYPE_STRING;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4340
		se_val.value.sv_string = driver_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4341
		if (sysevent_add_attr(&ev_attr_list,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4342
		    DEVFS_DRIVER_NAME, &se_val, SE_SLEEP) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4343
			sysevent_free_attr(ev_attr_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4344
			goto fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4345
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4346
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4347
		se_val.value_type = SE_DATA_TYPE_INT32;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4348
		se_val.value.sv_int32 = instance;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4349
		if (sysevent_add_attr(&ev_attr_list,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4350
		    DEVFS_INSTANCE, &se_val, SE_SLEEP) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4351
			sysevent_free_attr(ev_attr_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4352
			goto fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4353
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4354
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4355
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4356
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4357
	 * must log a branch event too unless NDI_BRANCH_EVENT_OP is set,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4358
	 * in which case the branch event will be logged by the caller
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4359
	 * after the entire branch has been unconfigured.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4360
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4361
	if ((flags & NDI_BRANCH_EVENT_OP) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4362
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4363
		 * Instead of logging a separate branch event just add
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4364
		 * DEVFS_BRANCH_EVENT attribute. It indicates devfsadmd to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4365
		 * generate a EC_DEV_BRANCH event.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4366
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4367
		se_val.value_type = SE_DATA_TYPE_INT32;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4368
		se_val.value.sv_int32 = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4369
		if (sysevent_add_attr(&ev_attr_list,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4370
		    DEVFS_BRANCH_EVENT, &se_val, SE_SLEEP) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4371
			sysevent_free_attr(ev_attr_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4372
			goto fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4373
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4374
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4375
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4376
	if (sysevent_attach_attributes(ev, ev_attr_list) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4377
		sysevent_free_attr(ev_attr_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4378
		goto fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4379
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4380
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4381
	if ((se_err = log_sysevent(ev, SE_SLEEP, &eid)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4382
		if (se_err == SE_NO_TRANSPORT)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4383
			no_transport = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4384
		goto fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4385
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4386
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4387
	sysevent_free(ev);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4388
	return (DDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4389
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4390
fail:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4391
	sysevent_free(ev);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4392
	cmn_err(CE_WARN, "failed to log ESC_DEVFS_DEVI_REMOVE event for %s%s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4393
	    pathname, (no_transport) ? " (syseventd not responding)" : "");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4394
	return (DDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4395
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4396
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4397
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4398
 * log an event that a dev_info branch has been configured or unconfigured.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4399
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4400
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4401
i_log_devfs_branch(char *node_path, char *subclass)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4402
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4403
	int se_err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4404
	sysevent_t *ev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4405
	sysevent_id_t eid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4406
	sysevent_value_t se_val;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4407
	sysevent_attr_list_t *ev_attr_list = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4408
	int no_transport = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4409
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4410
	/* do not generate the event during boot */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4411
	if (!i_ddi_io_initialized())
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4412
		return (DDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4413
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4414
	ev = sysevent_alloc(EC_DEVFS, subclass, EP_DDI, SE_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4415
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4416
	se_val.value_type = SE_DATA_TYPE_STRING;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4417
	se_val.value.sv_string = node_path;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4418
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4419
	if (sysevent_add_attr(&ev_attr_list, DEVFS_PATHNAME,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4420
	    &se_val, SE_SLEEP) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4421
		goto fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4422
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4423
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4424
	if (sysevent_attach_attributes(ev, ev_attr_list) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4425
		sysevent_free_attr(ev_attr_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4426
		goto fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4427
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4428
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4429
	if ((se_err = log_sysevent(ev, SE_SLEEP, &eid)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4430
		if (se_err == SE_NO_TRANSPORT)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4431
			no_transport = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4432
		goto fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4433
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4434
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4435
	sysevent_free(ev);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4436
	return (DDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4437
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4438
fail:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4439
	cmn_err(CE_WARN, "failed to log %s branch event for %s%s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4440
	    subclass, node_path,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4441
	    (no_transport) ? " (syseventd not responding)" : "");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4442
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4443
	sysevent_free(ev);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4444
	return (DDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4445
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4446
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4447
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4448
 * log an event that a dev_info tree branch has been configured.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4449
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4450
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4451
i_log_devfs_branch_add(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4452
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4453
	char *node_path;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4454
	int rv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4455
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4456
	node_path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4457
	(void) ddi_pathname(dip, node_path);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4458
	rv = i_log_devfs_branch(node_path, ESC_DEVFS_BRANCH_ADD);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4459
	kmem_free(node_path, MAXPATHLEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4460
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4461
	return (rv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4462
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4463
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4464
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4465
 * log an event that a dev_info tree branch has been unconfigured.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4466
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4467
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4468
i_log_devfs_branch_remove(char *node_path)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4469
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4470
	return (i_log_devfs_branch(node_path, ESC_DEVFS_BRANCH_REMOVE));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4471
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4472
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4473
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4474
 * enqueue the dip's deviname on the branch event queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4475
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4476
static struct brevq_node *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4477
brevq_enqueue(struct brevq_node **brevqp, dev_info_t *dip,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4478
    struct brevq_node *child)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4479
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4480
	struct brevq_node *brn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4481
	char *deviname;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4482
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4483
	deviname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4484
	(void) ddi_deviname(dip, deviname);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4485
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4486
	brn = kmem_zalloc(sizeof (*brn), KM_SLEEP);
1317
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  4487
	brn->brn_deviname = i_ddi_strdup(deviname, KM_SLEEP);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4488
	kmem_free(deviname, MAXNAMELEN);
1317
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  4489
	brn->brn_child = child;
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  4490
	brn->brn_sibling = *brevqp;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4491
	*brevqp = brn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4492
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4493
	return (brn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4494
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4495
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4496
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4497
 * free the memory allocated for the elements on the branch event queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4498
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4499
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4500
free_brevq(struct brevq_node *brevq)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4501
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4502
	struct brevq_node *brn, *next_brn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4503
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4504
	for (brn = brevq; brn != NULL; brn = next_brn) {
1317
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  4505
		next_brn = brn->brn_sibling;
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  4506
		ASSERT(brn->brn_child == NULL);
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  4507
		kmem_free(brn->brn_deviname, strlen(brn->brn_deviname) + 1);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4508
		kmem_free(brn, sizeof (*brn));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4509
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4510
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4511
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4512
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4513
 * log the events queued up on the branch event queue and free the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4514
 * associated memory.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4515
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4516
 * node_path must have been allocated with at least MAXPATHLEN bytes.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4517
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4518
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4519
log_and_free_brevq(char *node_path, struct brevq_node *brevq)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4520
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4521
	struct brevq_node *brn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4522
	char *p;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4523
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4524
	p = node_path + strlen(node_path);
1317
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  4525
	for (brn = brevq; brn != NULL; brn = brn->brn_sibling) {
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  4526
		(void) strcpy(p, brn->brn_deviname);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4527
		(void) i_log_devfs_branch_remove(node_path);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4528
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4529
	*p = '\0';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4530
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4531
	free_brevq(brevq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4532
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4533
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4534
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4535
 * log the events queued up on the branch event queue and free the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4536
 * associated memory. Same as the previous function but operates on dip.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4537
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4538
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4539
log_and_free_brevq_dip(dev_info_t *dip, struct brevq_node *brevq)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4540
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4541
	char *path;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4542
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4543
	path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4544
	(void) ddi_pathname(dip, path);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4545
	log_and_free_brevq(path, brevq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4546
	kmem_free(path, MAXPATHLEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4547
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4548
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4549
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4550
 * log the outstanding branch remove events for the grand children of the dip
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4551
 * and free the associated memory.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4552
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4553
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4554
log_and_free_br_events_on_grand_children(dev_info_t *dip,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4555
    struct brevq_node *brevq)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4556
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4557
	struct brevq_node *brn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4558
	char *path;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4559
	char *p;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4560
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4561
	path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4562
	(void) ddi_pathname(dip, path);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4563
	p = path + strlen(path);
1317
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  4564
	for (brn = brevq; brn != NULL; brn = brn->brn_sibling) {
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  4565
		if (brn->brn_child) {
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  4566
			(void) strcpy(p, brn->brn_deviname);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4567
			/* now path contains the node path to the dip's child */
1317
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  4568
			log_and_free_brevq(path, brn->brn_child);
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  4569
			brn->brn_child = NULL;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4570
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4571
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4572
	kmem_free(path, MAXPATHLEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4573
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4574
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4575
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4576
 * log and cleanup branch remove events for the grand children of the dip.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4577
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4578
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4579
cleanup_br_events_on_grand_children(dev_info_t *dip, struct brevq_node **brevqp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4580
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4581
	dev_info_t *child;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4582
	struct brevq_node *brevq, *brn, *prev_brn, *next_brn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4583
	char *path;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4584
	int circ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4585
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4586
	path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4587
	prev_brn = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4588
	brevq = *brevqp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4589
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4590
	ndi_devi_enter(dip, &circ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4591
	for (brn = brevq; brn != NULL; brn = next_brn) {
1317
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  4592
		next_brn = brn->brn_sibling;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4593
		for (child = ddi_get_child(dip); child != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4594
		    child = ddi_get_next_sibling(child)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4595
			if (i_ddi_node_state(child) >= DS_INITIALIZED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4596
				(void) ddi_deviname(child, path);
1317
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  4597
				if (strcmp(path, brn->brn_deviname) == 0)
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4598
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4599
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4600
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4601
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4602
		if (child != NULL && !(DEVI_EVREMOVE(child))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4603
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4604
			 * Event state is not REMOVE. So branch remove event
1317
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  4605
			 * is not going be generated on brn->brn_child.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4606
			 * If any branch remove events were queued up on
1317
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  4607
			 * brn->brn_child log them and remove the brn
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4608
			 * from the queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4609
			 */
1317
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  4610
			if (brn->brn_child) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4611
				(void) ddi_pathname(dip, path);
1317
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  4612
				(void) strcat(path, brn->brn_deviname);
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  4613
				log_and_free_brevq(path, brn->brn_child);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4614
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4615
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4616
			if (prev_brn)
1317
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  4617
				prev_brn->brn_sibling = next_brn;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4618
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4619
				*brevqp = next_brn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4620
1317
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  4621
			kmem_free(brn->brn_deviname,
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  4622
			    strlen(brn->brn_deviname) + 1);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4623
			kmem_free(brn, sizeof (*brn));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4624
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4625
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4626
			 * Free up the outstanding branch remove events
1317
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  4627
			 * queued on brn->brn_child since brn->brn_child
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4628
			 * itself is eligible for branch remove event.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4629
			 */
1317
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  4630
			if (brn->brn_child) {
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  4631
				free_brevq(brn->brn_child);
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  4632
				brn->brn_child = NULL;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4633
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4634
			prev_brn = brn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4635
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4636
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4637
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4638
	ndi_devi_exit(dip, circ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4639
	kmem_free(path, MAXPATHLEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4640
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4641
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4642
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4643
need_remove_event(dev_info_t *dip, int flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4644
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4645
	if ((flags & (NDI_NO_EVENT | NDI_AUTODETACH)) == 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4646
	    (flags & (NDI_DEVI_OFFLINE | NDI_UNCONFIG | NDI_DEVI_REMOVE)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4647
	    !(DEVI_EVREMOVE(dip)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4648
		return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4649
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4650
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4651
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4652
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4653
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4654
 * Unconfigure children/descendants of the dip.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4655
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4656
 * If the operation involves a branch event NDI_BRANCH_EVENT_OP is set
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4657
 * through out the unconfiguration. On successful return *brevqp is set to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4658
 * a queue of dip's child devinames for which branch remove events need
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4659
 * to be generated.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4660
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4661
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4662
devi_unconfig_branch(dev_info_t *dip, dev_info_t **dipp, int flags,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4663
    struct brevq_node **brevqp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4664
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4665
	int rval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4666
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4667
	*brevqp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4668
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4669
	if ((!(flags & NDI_BRANCH_EVENT_OP)) && need_remove_event(dip, flags))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4670
		flags |= NDI_BRANCH_EVENT_OP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4671
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4672
	if (flags & NDI_BRANCH_EVENT_OP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4673
		rval = devi_unconfig_common(dip, dipp, flags, (major_t)-1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4674
		    brevqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4675
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4676
		if (rval != NDI_SUCCESS && (*brevqp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4677
			log_and_free_brevq_dip(dip, *brevqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4678
			*brevqp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4679
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4680
	} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4681
		rval = devi_unconfig_common(dip, dipp, flags, (major_t)-1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4682
		    NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4683
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4684
	return (rval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4685
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4686
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4687
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4688
 * If the dip is already bound to a driver transition to DS_INITIALIZED
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4689
 * in order to generate an event in the case where the node was left in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4690
 * DS_BOUND state since boot (never got attached) and the node is now
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4691
 * being offlined.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4692
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4693
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4694
init_bound_node_ev(dev_info_t *pdip, dev_info_t *dip, int flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4695
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4696
	if (need_remove_event(dip, flags) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4697
	    i_ddi_node_state(dip) == DS_BOUND &&
1333
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  4698
	    i_ddi_devi_attached(pdip) && !DEVI_IS_DEVICE_OFFLINE(dip))
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4699
		(void) ddi_initchild(pdip, dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4700
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4701
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4702
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4703
 * attach a node/branch with parent already held busy
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4704
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4705
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4706
devi_attach_node(dev_info_t *dip, uint_t flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4707
{
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4708
	dev_info_t *pdip = ddi_get_parent(dip);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4709
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4710
	ASSERT(pdip && DEVI_BUSY_OWNED(pdip));
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4711
495
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  4712
	mutex_enter(&(DEVI(dip)->devi_lock));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4713
	if (flags & NDI_DEVI_ONLINE) {
1333
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  4714
		if (!i_ddi_devi_attached(dip))
495
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  4715
			DEVI_SET_REPORT(dip);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4716
		DEVI_SET_DEVICE_ONLINE(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4717
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4718
	if (DEVI_IS_DEVICE_OFFLINE(dip)) {
495
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  4719
		mutex_exit(&(DEVI(dip)->devi_lock));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4720
		return (NDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4721
	}
495
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  4722
	mutex_exit(&(DEVI(dip)->devi_lock));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4723
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4724
	if (i_ddi_attachchild(dip) != DDI_SUCCESS) {
495
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  4725
		mutex_enter(&(DEVI(dip)->devi_lock));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4726
		DEVI_SET_EVUNINIT(dip);
495
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  4727
		mutex_exit(&(DEVI(dip)->devi_lock));
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  4728
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4729
		if (ndi_dev_is_persistent_node(dip))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4730
			(void) ddi_uninitchild(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4731
		else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4732
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4733
			 * Delete .conf nodes and nodes that are not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4734
			 * well formed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4735
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4736
			(void) ddi_remove_child(dip, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4737
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4738
		return (NDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4739
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4740
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4741
	i_ndi_devi_report_status_change(dip, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4742
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4743
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4744
	 * log an event, but not during devfs lookups in which case
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4745
	 * NDI_NO_EVENT is set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4746
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4747
	if ((flags & NDI_NO_EVENT) == 0 && !(DEVI_EVADD(dip))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4748
		(void) i_log_devfs_add_devinfo(dip, flags);
495
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  4749
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  4750
		mutex_enter(&(DEVI(dip)->devi_lock));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4751
		DEVI_SET_EVADD(dip);
495
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  4752
		mutex_exit(&(DEVI(dip)->devi_lock));
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  4753
	} else if (!(flags & NDI_NO_EVENT_STATE_CHNG)) {
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  4754
		mutex_enter(&(DEVI(dip)->devi_lock));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4755
		DEVI_SET_EVADD(dip);
495
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  4756
		mutex_exit(&(DEVI(dip)->devi_lock));
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  4757
	}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4758
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4759
	return (NDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4760
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4761
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4762
/* internal function to config immediate children */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4763
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4764
config_immediate_children(dev_info_t *pdip, uint_t flags, major_t major)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4765
{
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4766
	dev_info_t	*child, *next;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4767
	int		circ;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4768
1333
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  4769
	ASSERT(i_ddi_devi_attached(pdip));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4770
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4771
	if (!NEXUS_DRV(ddi_get_driver(pdip)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4772
		return (NDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4773
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4774
	NDI_CONFIG_DEBUG((CE_CONT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4775
	    "config_immediate_children: %s%d (%p), flags=%x\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4776
	    ddi_driver_name(pdip), ddi_get_instance(pdip),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4777
	    (void *)pdip, flags));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4778
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4779
	ndi_devi_enter(pdip, &circ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4780
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4781
	if (flags & NDI_CONFIG_REPROBE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4782
		mutex_enter(&DEVI(pdip)->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4783
		DEVI(pdip)->devi_flags &= ~DEVI_MADE_CHILDREN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4784
		mutex_exit(&DEVI(pdip)->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4785
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4786
	(void) i_ndi_make_spec_children(pdip, flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4787
	i_ndi_init_hw_children(pdip, flags);
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4788
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4789
	child = ddi_get_child(pdip);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4790
	while (child) {
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4791
		/* NOTE: devi_attach_node() may remove the dip */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4792
		next = ddi_get_next_sibling(child);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4793
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4794
		/*
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4795
		 * Configure all nexus nodes or leaf nodes with
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4796
		 * matching driver major
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4797
		 */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4798
		if ((major == (major_t)-1) ||
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4799
		    (major == ddi_driver_major(child)) ||
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4800
		    ((flags & NDI_CONFIG) && (is_leaf_node(child) == 0)))
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4801
			(void) devi_attach_node(child, flags);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4802
		child = next;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4803
	}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4804
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4805
	ndi_devi_exit(pdip, circ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4806
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4807
	return (NDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4808
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4809
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4810
/* internal function to config grand children */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4811
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4812
config_grand_children(dev_info_t *pdip, uint_t flags, major_t major)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4813
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4814
	struct mt_config_handle *hdl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4815
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4816
	/* multi-threaded configuration of child nexus */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4817
	hdl = mt_config_init(pdip, NULL, flags, major, MT_CONFIG_OP, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4818
	mt_config_children(hdl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4819
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4820
	return (mt_config_fini(hdl));	/* wait for threads to exit */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4821
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4822
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4823
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4824
 * Common function for device tree configuration,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4825
 * either BUS_CONFIG_ALL or BUS_CONFIG_DRIVER.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4826
 * The NDI_CONFIG flag causes recursive configuration of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4827
 * grandchildren, devfs usage should not recurse.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4828
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4829
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4830
devi_config_common(dev_info_t *dip, int flags, major_t major)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4831
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4832
	int error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4833
	int (*f)();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4834
1333
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  4835
	if (!i_ddi_devi_attached(dip))
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4836
		return (NDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4837
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4838
	if (pm_pre_config(dip, NULL) != DDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4839
		return (NDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4840
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4841
	if ((DEVI(dip)->devi_ops->devo_bus_ops == NULL) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4842
	    (DEVI(dip)->devi_ops->devo_bus_ops->busops_rev < BUSO_REV_5) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4843
	    (f = DEVI(dip)->devi_ops->devo_bus_ops->bus_config) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4844
		error = config_immediate_children(dip, flags, major);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4845
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4846
		/* call bus_config entry point */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4847
		ddi_bus_config_op_t bus_op = (major == (major_t)-1) ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4848
		    BUS_CONFIG_ALL : BUS_CONFIG_DRIVER;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4849
		error = (*f)(dip,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4850
		    flags, bus_op, (void *)(uintptr_t)major, NULL, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4851
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4852
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4853
	if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4854
		pm_post_config(dip, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4855
		return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4856
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4857
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4858
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4859
	 * Some callers, notably SCSI, need to mark the devfs cache
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4860
	 * to be rebuilt together with the config operation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4861
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4862
	if (flags & NDI_DEVFS_CLEAN)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4863
		(void) devfs_clean(dip, NULL, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4864
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4865
	if (flags & NDI_CONFIG)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4866
		(void) config_grand_children(dip, flags, major);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4867
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4868
	pm_post_config(dip, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4869
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4870
	return (NDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4871
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4872
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4873
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4874
 * Framework entry point for BUS_CONFIG_ALL
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4875
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4876
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4877
ndi_devi_config(dev_info_t *dip, int flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4878
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4879
	NDI_CONFIG_DEBUG((CE_CONT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4880
	    "ndi_devi_config: par = %s%d (%p), flags = 0x%x\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4881
	    ddi_driver_name(dip), ddi_get_instance(dip), (void *)dip, flags));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4882
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4883
	return (devi_config_common(dip, flags, (major_t)-1));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4884
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4885
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4886
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4887
 * Framework entry point for BUS_CONFIG_DRIVER, bound to major
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4888
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4889
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4890
ndi_devi_config_driver(dev_info_t *dip, int flags, major_t major)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4891
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4892
	/* don't abuse this function */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4893
	ASSERT(major != (major_t)-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4894
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4895
	NDI_CONFIG_DEBUG((CE_CONT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4896
	    "ndi_devi_config_driver: par = %s%d (%p), flags = 0x%x\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4897
	    ddi_driver_name(dip), ddi_get_instance(dip), (void *)dip, flags));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4898
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4899
	return (devi_config_common(dip, flags, major));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4900
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4901
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4902
/*
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4903
 * Called by nexus drivers to configure its children.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4904
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4905
static int
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4906
devi_config_one(dev_info_t *pdip, char *devnm, dev_info_t **cdipp,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4907
    uint_t flags, clock_t timeout)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4908
{
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4909
	dev_info_t	*vdip = NULL;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4910
	char		*drivername = NULL;
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  4911
	int		find_by_addr = 0;
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4912
	char		*name, *addr;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4913
	int		v_circ, p_circ;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4914
	clock_t		end_time;	/* 60 sec */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4915
	int		probed;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4916
	dev_info_t	*cdip;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4917
	mdi_pathinfo_t	*cpip;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4918
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4919
	*cdipp = NULL;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4920
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4921
	if (!NEXUS_DRV(ddi_get_driver(pdip)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4922
		return (NDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4923
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4924
	/* split name into "name@addr" parts */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4925
	i_ddi_parse_name(devnm, &name, &addr, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4926
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4927
	/*
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4928
	 * If the nexus is a pHCI and we are not processing a pHCI from
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4929
	 * mdi bus_config code then we need to know the vHCI.
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4930
	 */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4931
	if (MDI_PHCI(pdip))
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4932
		vdip = mdi_devi_get_vdip(pdip);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4933
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4934
	/*
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4935
	 * We may have a genericname on a system that creates drivername
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4936
	 * nodes (from .conf files).  Find the drivername by nodeid. If we
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4937
	 * can't find a node with devnm as the node name then we search by
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4938
	 * drivername.  This allows an implementation to supply a genericly
5742
b0948deb63bc 6642582 Testcase initfini failing on all machines (sparc & x86) in s10u5_05
cth
parents: 4950
diff changeset
  4939
	 * named boot path (disk) and locate drivename nodes (sd).  The
b0948deb63bc 6642582 Testcase initfini failing on all machines (sparc & x86) in s10u5_05
cth
parents: 4950
diff changeset
  4940
	 * NDI_PROMNAME flag does not apply to /devices/pseudo paths.
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4941
	 */
5742
b0948deb63bc 6642582 Testcase initfini failing on all machines (sparc & x86) in s10u5_05
cth
parents: 4950
diff changeset
  4942
	if ((flags & NDI_PROMNAME) && (pdip != pseudo_dip)) {
2009
b1f98dc679ae Backout 6423041, 6426345; exposes deadlock
dm120769
parents: 1961
diff changeset
  4943
		drivername = child_path_to_driver(pdip, name, addr);
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  4944
		find_by_addr = 1;
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  4945
	}
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4946
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4947
	/*
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4948
	 * Determine end_time: This routine should *not* be called with a
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4949
	 * constant non-zero timeout argument, the caller should be adjusting
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4950
	 * the timeout argument relative to when it *started* its asynchronous
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4951
	 * enumeration.
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4952
	 */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4953
	if (timeout > 0)
2009
b1f98dc679ae Backout 6423041, 6426345; exposes deadlock
dm120769
parents: 1961
diff changeset
  4954
		end_time = ddi_get_lbolt() + timeout;
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4955
2009
b1f98dc679ae Backout 6423041, 6426345; exposes deadlock
dm120769
parents: 1961
diff changeset
  4956
	for (;;) {
1961
cceb6bfa61a5 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 1826
diff changeset
  4957
		/*
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4958
		 * For pHCI, enter (vHCI, pHCI) and search for pathinfo/client
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4959
		 * child - break out of for(;;) loop if child found.
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4960
		 * NOTE: Lock order for ndi_devi_enter is (vHCI, pHCI).
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4961
		 */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4962
		if (vdip) {
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4963
			/* use mdi_devi_enter ordering */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4964
			ndi_devi_enter(vdip, &v_circ);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4965
			ndi_devi_enter(pdip, &p_circ);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4966
			cpip = mdi_pi_find(pdip, NULL, addr);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4967
			cdip = mdi_pi_get_client(cpip);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4968
			if (cdip)
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4969
				break;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4970
		} else
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4971
			ndi_devi_enter(pdip, &p_circ);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4972
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4973
		/*
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4974
		 * When not a  vHCI or not all pHCI devices are required to
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4975
		 * enumerated under the vHCI (NDI_MDI_FALLBACK) search for
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4976
		 * devinfo child.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4977
		 */
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4978
		if ((vdip == NULL) || (flags & NDI_MDI_FALLBACK)) {
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4979
			/* determine if .conf nodes already built */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4980
			probed = (DEVI(pdip)->devi_flags & DEVI_MADE_CHILDREN);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4981
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4982
			/*
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4983
			 * Search for child by name, if not found then search
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4984
			 * for a node bound to the drivername driver with the
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4985
			 * specified "@addr". Break out of for(;;) loop if
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  4986
			 * child found.  To support path-oriented aliases
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  4987
			 * binding on boot-device, we do a search_by_addr too.
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4988
			 */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4989
again:			(void) i_ndi_make_spec_children(pdip, flags);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4990
			cdip = find_child_by_name(pdip, name, addr);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4991
			if ((cdip == NULL) && drivername)
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4992
				cdip = find_child_by_driver(pdip,
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4993
				    drivername, addr);
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  4994
			if ((cdip == NULL) && find_by_addr)
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  4995
				cdip = find_child_by_addr(pdip, addr);
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4996
			if (cdip)
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4997
				break;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4998
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  4999
			/*
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5000
			 * determine if we should reenumerate .conf nodes
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5001
			 * and look for child again.
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5002
			 */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5003
			if (probed &&
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5004
			    i_ddi_io_initialized() &&
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5005
			    (flags & NDI_CONFIG_REPROBE) &&
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5006
			    ((timeout <= 0) || (ddi_get_lbolt() >= end_time))) {
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5007
				probed = 0;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5008
				mutex_enter(&DEVI(pdip)->devi_lock);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5009
				DEVI(pdip)->devi_flags &= ~DEVI_MADE_CHILDREN;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5010
				mutex_exit(&DEVI(pdip)->devi_lock);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5011
				goto again;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5012
			}
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5013
		}
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5014
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5015
		/* break out of for(;;) if time expired */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5016
		if ((timeout <= 0) || (ddi_get_lbolt() >= end_time))
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5017
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5018
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5019
		/*
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5020
		 * Child not found, exit and wait for asynchronous enumeration
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5021
		 * to add child (or timeout). The addition of a new child (vhci
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5022
		 * or phci) requires the asynchronous enumeration thread to
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5023
		 * ndi_devi_enter/ndi_devi_exit. This exit will signal devi_cv
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5024
		 * and cause us to return from ndi_devi_exit_and_wait, after
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5025
		 * which we loop and search for the requested child again.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5026
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5027
		NDI_DEBUG(flags, (CE_CONT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5028
		    "%s%d: waiting for child %s@%s, timeout %ld",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5029
		    ddi_driver_name(pdip), ddi_get_instance(pdip),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5030
		    name, addr, timeout));
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5031
		if (vdip) {
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5032
			/*
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5033
			 * Mark vHCI for pHCI ndi_devi_exit broadcast.
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5034
			 */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5035
			mutex_enter(&DEVI(vdip)->devi_lock);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5036
			DEVI(vdip)->devi_flags |=
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5037
			    DEVI_PHCI_SIGNALS_VHCI;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5038
			mutex_exit(&DEVI(vdip)->devi_lock);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5039
			ndi_devi_exit(pdip, p_circ);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5040
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5041
			/*
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5042
			 * NB: There is a small race window from above
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5043
			 * ndi_devi_exit() of pdip to cv_wait() in
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5044
			 * ndi_devi_exit_and_wait() which can result in
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5045
			 * not immediately finding a new pHCI child
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5046
			 * of a pHCI that uses NDI_MDI_FAILBACK.
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5047
			 */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5048
			ndi_devi_exit_and_wait(vdip, v_circ, end_time);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5049
		} else {
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5050
			ndi_devi_exit_and_wait(pdip, p_circ, end_time);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5051
		}
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5052
	}
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5053
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5054
	/* done with paddr, fixup i_ddi_parse_name '@'->'\0' change */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5055
	if (addr && *addr != '\0')
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5056
		*(addr - 1) = '@';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5057
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5058
	/* attach and hold the child, returning pointer to child */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5059
	if (cdip && (devi_attach_node(cdip, flags) == NDI_SUCCESS)) {
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5060
		ndi_hold_devi(cdip);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5061
		*cdipp = cdip;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5062
	}
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5063
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5064
	ndi_devi_exit(pdip, p_circ);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5065
	if (vdip)
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5066
		ndi_devi_exit(vdip, v_circ);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5067
	return (*cdipp ? NDI_SUCCESS : NDI_FAILURE);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5068
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5069
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5070
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5071
 * Enumerate and attach a child specified by name 'devnm'.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5072
 * Called by devfs lookup and DR to perform a BUS_CONFIG_ONE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5073
 * Note: devfs does not make use of NDI_CONFIG to configure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5074
 * an entire branch.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5075
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5076
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5077
ndi_devi_config_one(dev_info_t *dip, char *devnm, dev_info_t **dipp, int flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5078
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5079
	int error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5080
	int (*f)();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5081
	int branch_event = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5082
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5083
	ASSERT(dipp);
1333
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  5084
	ASSERT(i_ddi_devi_attached(dip));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5085
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5086
	NDI_CONFIG_DEBUG((CE_CONT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5087
	    "ndi_devi_config_one: par = %s%d (%p), child = %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5088
	    ddi_driver_name(dip), ddi_get_instance(dip), (void *)dip, devnm));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5089
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5090
	if (pm_pre_config(dip, devnm) != DDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5091
		return (NDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5092
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5093
	if ((flags & (NDI_NO_EVENT | NDI_BRANCH_EVENT_OP)) == 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5094
	    (flags & NDI_CONFIG)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5095
		flags |= NDI_BRANCH_EVENT_OP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5096
		branch_event = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5097
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5098
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5099
	if ((DEVI(dip)->devi_ops->devo_bus_ops == NULL) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5100
	    (DEVI(dip)->devi_ops->devo_bus_ops->busops_rev < BUSO_REV_5) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5101
	    (f = DEVI(dip)->devi_ops->devo_bus_ops->bus_config) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5102
		error = devi_config_one(dip, devnm, dipp, flags, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5103
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5104
		/* call bus_config entry point */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5105
		error = (*f)(dip, flags, BUS_CONFIG_ONE, (void *)devnm, dipp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5106
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5107
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5108
	if (error || (flags & NDI_CONFIG) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5109
		pm_post_config(dip, devnm);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5110
		return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5111
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5112
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5113
	/*
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  5114
	 * DR usage (i.e. call with NDI_CONFIG) recursively configures
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5115
	 * grandchildren, performing a BUS_CONFIG_ALL from the node attached
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5116
	 * by the BUS_CONFIG_ONE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5117
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5118
	ASSERT(*dipp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5119
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5120
	error = devi_config_common(*dipp, flags, (major_t)-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5121
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5122
	pm_post_config(dip, devnm);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5123
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5124
	if (branch_event)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5125
		(void) i_log_devfs_branch_add(*dipp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5126
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5127
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5128
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5129
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5130
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5131
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5132
 * Enumerate and attach a child specified by name 'devnm'.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5133
 * Called during configure the OBP options. This configures
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5134
 * only one node.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5135
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5136
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5137
ndi_devi_config_obp_args(dev_info_t *parent, char *devnm,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5138
    dev_info_t **childp, int flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5139
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5140
	int error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5141
	int (*f)();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5142
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5143
	ASSERT(childp);
1333
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  5144
	ASSERT(i_ddi_devi_attached(parent));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5145
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5146
	NDI_CONFIG_DEBUG((CE_CONT, "ndi_devi_config_obp_args: "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5147
	    "par = %s%d (%p), child = %s\n", ddi_driver_name(parent),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5148
	    ddi_get_instance(parent), (void *)parent, devnm));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5149
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5150
	if ((DEVI(parent)->devi_ops->devo_bus_ops == NULL) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5151
	    (DEVI(parent)->devi_ops->devo_bus_ops->busops_rev < BUSO_REV_5) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5152
	    (f = DEVI(parent)->devi_ops->devo_bus_ops->bus_config) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5153
		error = NDI_FAILURE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5154
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5155
		/* call bus_config entry point */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5156
		error = (*f)(parent, flags,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5157
		    BUS_CONFIG_OBP_ARGS, (void *)devnm, childp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5158
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5159
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5160
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5161
4845
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5162
/*
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5163
 * Pay attention, the following is a bit tricky:
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5164
 * There are three possible cases when constraints are applied
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5165
 *
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5166
 *	- A constraint is applied and the offline is disallowed.
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5167
 *	  Simply return failure and block the offline
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5168
 *
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5169
 *	- A constraint is applied and the offline is allowed.
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5170
 *	  Mark the dip as having passed the constraint and allow
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5171
 *	  offline to proceed.
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5172
 *
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5173
 *	- A constraint is not applied. Allow the offline to proceed for now.
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5174
 *
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5175
 * In the latter two cases we allow the offline to proceed. If the
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5176
 * offline succeeds (no users) everything is fine. It is ok for an unused
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5177
 * device to be offlined even if no constraints were imposed on the offline.
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5178
 * If the offline fails because there are users, we look at the constraint
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5179
 * flag on the dip. If the constraint flag is set (implying that it passed
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5180
 * a constraint) we allow the dip to be retired. If not, we don't allow
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5181
 * the retire. This ensures that we don't allow unconstrained retire.
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5182
 */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5183
int
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5184
e_ddi_offline_notify(dev_info_t *dip)
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5185
{
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5186
	int retval;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5187
	int constraint;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5188
	int failure;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5189
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5190
	RIO_VERBOSE((CE_NOTE, "e_ddi_offline_notify(): entered: dip=%p",
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5191
	    (void *) dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5192
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5193
	constraint = 0;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5194
	failure = 0;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5195
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5196
	/*
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5197
	 * Start with userland constraints first - applied via device contracts
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5198
	 */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5199
	retval = contract_device_offline(dip, DDI_DEV_T_ANY, 0);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5200
	switch (retval) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5201
	case CT_NACK:
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5202
		RIO_DEBUG((CE_NOTE, "Received NACK for dip=%p", (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5203
		failure = 1;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5204
		goto out;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5205
	case CT_ACK:
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5206
		constraint = 1;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5207
		RIO_DEBUG((CE_NOTE, "Received ACK for dip=%p", (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5208
		break;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5209
	case CT_NONE:
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5210
		/* no contracts */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5211
		RIO_DEBUG((CE_NOTE, "No contracts on dip=%p", (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5212
		break;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5213
	default:
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5214
		ASSERT(retval == CT_NONE);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5215
	}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5216
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5217
	/*
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5218
	 * Next, use LDI to impose kernel constraints
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5219
	 */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5220
	retval = ldi_invoke_notify(dip, DDI_DEV_T_ANY, 0, LDI_EV_OFFLINE, NULL);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5221
	switch (retval) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5222
	case LDI_EV_FAILURE:
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5223
		contract_device_negend(dip, DDI_DEV_T_ANY, 0, CT_EV_FAILURE);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5224
		RIO_DEBUG((CE_NOTE, "LDI callback failed on dip=%p",
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5225
		    (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5226
		failure = 1;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5227
		goto out;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5228
	case LDI_EV_SUCCESS:
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5229
		constraint = 1;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5230
		RIO_DEBUG((CE_NOTE, "LDI callback success on dip=%p",
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5231
		    (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5232
		break;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5233
	case LDI_EV_NONE:
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5234
		/* no matching LDI callbacks */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5235
		RIO_DEBUG((CE_NOTE, "No LDI callbacks for dip=%p",
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5236
		    (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5237
		break;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5238
	default:
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5239
		ASSERT(retval == LDI_EV_NONE);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5240
	}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5241
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5242
out:
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5243
	mutex_enter(&(DEVI(dip)->devi_lock));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5244
	if ((DEVI(dip)->devi_flags & DEVI_RETIRING) && failure) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5245
		RIO_VERBOSE((CE_NOTE, "e_ddi_offline_notify(): setting "
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5246
		    "BLOCKED flag. dip=%p", (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5247
		DEVI(dip)->devi_flags |= DEVI_R_BLOCKED;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5248
		if (DEVI(dip)->devi_flags & DEVI_R_CONSTRAINT) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5249
			RIO_VERBOSE((CE_NOTE, "e_ddi_offline_notify(): "
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5250
			    "blocked. clearing RCM CONSTRAINT flag. dip=%p",
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5251
			    (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5252
			DEVI(dip)->devi_flags &= ~DEVI_R_CONSTRAINT;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5253
		}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5254
	} else if ((DEVI(dip)->devi_flags & DEVI_RETIRING) && constraint) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5255
		RIO_VERBOSE((CE_NOTE, "e_ddi_offline_notify(): setting "
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5256
		    "CONSTRAINT flag. dip=%p", (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5257
		DEVI(dip)->devi_flags |= DEVI_R_CONSTRAINT;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5258
	} else if ((DEVI(dip)->devi_flags & DEVI_RETIRING) &&
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5259
	    DEVI(dip)->devi_ref == 0) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5260
		/* also allow retire if device is not in use */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5261
		RIO_VERBOSE((CE_NOTE, "e_ddi_offline_notify(): device not in "
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5262
		    "use. Setting CONSTRAINT flag. dip=%p", (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5263
		DEVI(dip)->devi_flags |= DEVI_R_CONSTRAINT;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5264
	} else {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5265
		/*
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5266
		 * Note: We cannot ASSERT here that DEVI_R_CONSTRAINT is
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5267
		 * not set, since other sources (such as RCM) may have
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5268
		 * set the flag.
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5269
		 */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5270
		RIO_VERBOSE((CE_NOTE, "e_ddi_offline_notify(): not setting "
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5271
		    "constraint flag. dip=%p", (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5272
	}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5273
	mutex_exit(&(DEVI(dip)->devi_lock));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5274
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5275
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5276
	RIO_VERBOSE((CE_NOTE, "e_ddi_offline_notify(): exit: dip=%p",
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5277
	    (void *) dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5278
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5279
	return (failure ? DDI_FAILURE : DDI_SUCCESS);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5280
}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5281
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5282
void
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5283
e_ddi_offline_finalize(dev_info_t *dip, int result)
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5284
{
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5285
	RIO_DEBUG((CE_NOTE, "e_ddi_offline_finalize(): entry: result=%s, "
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5286
	    "dip=%p", result == DDI_SUCCESS ? "SUCCESS" : "FAILURE",
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5287
	    (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5288
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5289
	contract_device_negend(dip, DDI_DEV_T_ANY, 0,  result == DDI_SUCCESS ?
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5290
	    CT_EV_SUCCESS : CT_EV_FAILURE);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5291
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5292
	ldi_invoke_finalize(dip, DDI_DEV_T_ANY, 0,
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5293
	    LDI_EV_OFFLINE, result == DDI_SUCCESS ?
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5294
	    LDI_EV_SUCCESS : LDI_EV_FAILURE, NULL);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5295
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5296
	RIO_VERBOSE((CE_NOTE, "e_ddi_offline_finalize(): exit: dip=%p",
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5297
	    (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5298
}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5299
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5300
void
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5301
e_ddi_degrade_finalize(dev_info_t *dip)
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5302
{
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5303
	RIO_DEBUG((CE_NOTE, "e_ddi_degrade_finalize(): entry: "
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5304
	    "result always = DDI_SUCCESS, dip=%p", (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5305
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5306
	contract_device_degrade(dip, DDI_DEV_T_ANY, 0);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5307
	contract_device_negend(dip, DDI_DEV_T_ANY, 0, CT_EV_SUCCESS);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5308
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5309
	ldi_invoke_finalize(dip, DDI_DEV_T_ANY, 0, LDI_EV_DEGRADE,
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5310
	    LDI_EV_SUCCESS, NULL);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5311
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5312
	RIO_VERBOSE((CE_NOTE, "e_ddi_degrade_finalize(): exit: dip=%p",
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5313
	    (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5314
}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5315
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5316
void
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5317
e_ddi_undegrade_finalize(dev_info_t *dip)
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5318
{
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5319
	RIO_DEBUG((CE_NOTE, "e_ddi_undegrade_finalize(): entry: "
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5320
	    "result always = DDI_SUCCESS, dip=%p", (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5321
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5322
	contract_device_undegrade(dip, DDI_DEV_T_ANY, 0);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5323
	contract_device_negend(dip, DDI_DEV_T_ANY, 0, CT_EV_SUCCESS);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5324
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5325
	RIO_VERBOSE((CE_NOTE, "e_ddi_undegrade_finalize(): exit: dip=%p",
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5326
	    (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5327
}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5328
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5329
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5330
 * detach a node with parent already held busy
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5331
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5332
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5333
devi_detach_node(dev_info_t *dip, uint_t flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5334
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5335
	dev_info_t *pdip = ddi_get_parent(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5336
	int ret = NDI_SUCCESS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5337
	ddi_eventcookie_t cookie;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5338
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5339
	ASSERT(pdip && DEVI_BUSY_OWNED(pdip));
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5340
4845
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5341
	/*
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5342
	 * Invoke notify if offlining
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5343
	 */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5344
	if (flags & NDI_DEVI_OFFLINE) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5345
		RIO_DEBUG((CE_NOTE, "devi_detach_node: offlining dip=%p",
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5346
		    (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5347
		if (e_ddi_offline_notify(dip) != DDI_SUCCESS) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5348
			RIO_DEBUG((CE_NOTE, "devi_detach_node: offline NACKed"
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5349
			    "dip=%p", (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5350
			return (NDI_FAILURE);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5351
		}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5352
	}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5353
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5354
	if (flags & NDI_POST_EVENT) {
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5355
		if (i_ddi_devi_attached(pdip)) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5356
			if (ddi_get_eventcookie(dip, DDI_DEVI_REMOVE_EVENT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5357
			    &cookie) == NDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5358
				(void) ndi_post_event(dip, dip, cookie, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5359
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5360
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5361
4845
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5362
	if (i_ddi_detachchild(dip, flags) != DDI_SUCCESS) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5363
		if (flags & NDI_DEVI_OFFLINE) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5364
			RIO_DEBUG((CE_NOTE, "devi_detach_node: offline failed."
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5365
			    " Calling e_ddi_offline_finalize with result=%d. "
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5366
			    "dip=%p", DDI_FAILURE, (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5367
			e_ddi_offline_finalize(dip, DDI_FAILURE);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5368
		}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5369
		return (NDI_FAILURE);
4845
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5370
	}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5371
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5372
	if (flags & NDI_DEVI_OFFLINE) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5373
		RIO_DEBUG((CE_NOTE, "devi_detach_node: offline succeeded."
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5374
		    " Calling e_ddi_offline_finalize with result=%d, "
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5375
		    "dip=%p", DDI_SUCCESS, (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5376
		e_ddi_offline_finalize(dip, DDI_SUCCESS);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  5377
	}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5378
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5379
	if (flags & NDI_AUTODETACH)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5380
		return (NDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5381
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5382
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5383
	 * For DR, even bound nodes may need to have offline
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5384
	 * flag set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5385
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5386
	if (flags & NDI_DEVI_OFFLINE) {
495
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  5387
		mutex_enter(&(DEVI(dip)->devi_lock));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5388
		DEVI_SET_DEVICE_OFFLINE(dip);
495
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  5389
		mutex_exit(&(DEVI(dip)->devi_lock));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5390
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5391
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5392
	if (i_ddi_node_state(dip) == DS_INITIALIZED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5393
		char *path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5394
		(void) ddi_pathname(dip, path);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5395
		if (flags & NDI_DEVI_OFFLINE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5396
			i_ndi_devi_report_status_change(dip, path);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5397
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5398
		if (need_remove_event(dip, flags)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5399
			(void) i_log_devfs_remove_devinfo(path,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5400
			    i_ddi_devi_class(dip),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5401
			    (char *)ddi_driver_name(dip),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5402
			    ddi_get_instance(dip),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5403
			    flags);
495
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  5404
			mutex_enter(&(DEVI(dip)->devi_lock));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5405
			DEVI_SET_EVREMOVE(dip);
495
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  5406
			mutex_exit(&(DEVI(dip)->devi_lock));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5407
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5408
		kmem_free(path, MAXPATHLEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5409
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5410
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5411
	if (flags & (NDI_UNCONFIG | NDI_DEVI_REMOVE)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5412
		ret = ddi_uninitchild(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5413
		if (ret == NDI_SUCCESS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5414
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5415
			 * Remove uninitialized pseudo nodes because
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5416
			 * system props are lost and the node cannot be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5417
			 * reattached.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5418
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5419
			if (!ndi_dev_is_persistent_node(dip))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5420
				flags |= NDI_DEVI_REMOVE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5421
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5422
			if (flags & NDI_DEVI_REMOVE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5423
				ret = ddi_remove_child(dip, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5424
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5425
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5426
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5427
	return (ret);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5428
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5429
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5430
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5431
 * unconfigure immediate children of bus nexus device
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5432
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5433
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5434
unconfig_immediate_children(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5435
	dev_info_t *dip,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5436
	dev_info_t **dipp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5437
	int flags,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5438
	major_t major)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5439
{
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5440
	int rv = NDI_SUCCESS;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5441
	int circ, vcirc;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5442
	dev_info_t *child;
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5443
	dev_info_t *vdip = NULL;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5444
	dev_info_t *next;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5445
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5446
	ASSERT(dipp == NULL || *dipp == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5447
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5448
	/*
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5449
	 * Scan forward to see if we will be processing a pHCI child. If we
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5450
	 * have a child that is a pHCI and vHCI and pHCI are not siblings then
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5451
	 * enter vHCI before parent(pHCI) to prevent deadlock with mpxio
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5452
	 * Client power management operations.
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5453
	 */
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5454
	ndi_devi_enter(dip, &circ);
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5455
	for (child = ddi_get_child(dip); child;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5456
	    child = ddi_get_next_sibling(child)) {
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5457
		/* skip same nodes we skip below */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5458
		if (((major != (major_t)-1) &&
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5459
		    (major != ddi_driver_major(child))) ||
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5460
		    ((flags & NDI_AUTODETACH) && !is_leaf_node(child)))
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5461
			continue;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5462
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5463
		if (MDI_PHCI(child)) {
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5464
			vdip = mdi_devi_get_vdip(child);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5465
			/*
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5466
			 * If vHCI and vHCI is not a sibling of pHCI
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5467
			 * then enter in (vHCI, parent(pHCI)) order.
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5468
			 */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5469
			if (vdip && (ddi_get_parent(vdip) != dip)) {
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5470
				ndi_devi_exit(dip, circ);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5471
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5472
				/* use mdi_devi_enter ordering */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5473
				ndi_devi_enter(vdip, &vcirc);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5474
				ndi_devi_enter(dip, &circ);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5475
				break;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5476
			} else
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5477
				vdip = NULL;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5478
		}
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5479
	}
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5480
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5481
	child = ddi_get_child(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5482
	while (child) {
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5483
		next = ddi_get_next_sibling(child);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5484
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5485
		if ((major != (major_t)-1) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5486
		    (major != ddi_driver_major(child))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5487
			child = next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5488
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5489
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5490
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5491
		/* skip nexus nodes during autodetach */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5492
		if ((flags & NDI_AUTODETACH) && !is_leaf_node(child)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5493
			child = next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5494
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5495
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5496
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5497
		if (devi_detach_node(child, flags) != NDI_SUCCESS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5498
			if (dipp && *dipp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5499
				ndi_hold_devi(child);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5500
				*dipp = child;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5501
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5502
			rv = NDI_FAILURE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5503
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5504
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5505
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5506
		 * Continue upon failure--best effort algorithm
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5507
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5508
		child = next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5509
	}
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5510
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5511
	ndi_devi_exit(dip, circ);
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5512
	if (vdip)
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5513
		ndi_devi_exit(vdip, vcirc);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5514
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5515
	return (rv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5516
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5517
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5518
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5519
 * unconfigure grand children of bus nexus device
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5520
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5521
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5522
unconfig_grand_children(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5523
	dev_info_t *dip,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5524
	dev_info_t **dipp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5525
	int flags,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5526
	major_t major,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5527
	struct brevq_node **brevqp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5528
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5529
	struct mt_config_handle *hdl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5530
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5531
	if (brevqp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5532
		*brevqp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5533
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5534
	/* multi-threaded configuration of child nexus */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5535
	hdl = mt_config_init(dip, dipp, flags, major, MT_UNCONFIG_OP, brevqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5536
	mt_config_children(hdl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5537
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5538
	return (mt_config_fini(hdl));	/* wait for threads to exit */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5539
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5540
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5541
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5542
 * Unconfigure children/descendants of the dip.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5543
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5544
 * If brevqp is not NULL, on return *brevqp is set to a queue of dip's
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5545
 * child devinames for which branch remove events need to be generated.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5546
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5547
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5548
devi_unconfig_common(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5549
	dev_info_t *dip,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5550
	dev_info_t **dipp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5551
	int flags,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5552
	major_t major,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5553
	struct brevq_node **brevqp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5554
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5555
	int rv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5556
	int pm_cookie;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5557
	int (*f)();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5558
	ddi_bus_config_op_t bus_op;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5559
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5560
	if (dipp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5561
		*dipp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5562
	if (brevqp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5563
		*brevqp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5564
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5565
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5566
	 * Power up the dip if it is powered off.  If the flag bit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5567
	 * NDI_AUTODETACH is set and the dip is not at its full power,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5568
	 * skip the rest of the branch.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5569
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5570
	if (pm_pre_unconfig(dip, flags, &pm_cookie, NULL) != DDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5571
		return ((flags & NDI_AUTODETACH) ? NDI_SUCCESS :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5572
		    NDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5573
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5574
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5575
	 * Some callers, notably SCSI, need to clear out the devfs
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5576
	 * cache together with the unconfig to prevent stale entries.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5577
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5578
	if (flags & NDI_DEVFS_CLEAN)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5579
		(void) devfs_clean(dip, NULL, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5580
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5581
	rv = unconfig_grand_children(dip, dipp, flags, major, brevqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5582
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5583
	if ((rv != NDI_SUCCESS) && ((flags & NDI_AUTODETACH) == 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5584
		if (brevqp && *brevqp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5585
			log_and_free_br_events_on_grand_children(dip, *brevqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5586
			free_brevq(*brevqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5587
			*brevqp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5588
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5589
		pm_post_unconfig(dip, pm_cookie, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5590
		return (rv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5591
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5592
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5593
	if (dipp && *dipp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5594
		ndi_rele_devi(*dipp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5595
		*dipp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5596
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5597
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5598
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5599
	 * It is possible to have a detached nexus with children
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5600
	 * and grandchildren (for example: a branch consisting
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5601
	 * entirely of bound nodes.) Since the nexus is detached
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5602
	 * the bus_unconfig entry point cannot be used to remove
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5603
	 * or unconfigure the descendants.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5604
	 */
1333
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  5605
	if (!i_ddi_devi_attached(dip) ||
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5606
	    (DEVI(dip)->devi_ops->devo_bus_ops == NULL) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5607
	    (DEVI(dip)->devi_ops->devo_bus_ops->busops_rev < BUSO_REV_5) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5608
	    (f = DEVI(dip)->devi_ops->devo_bus_ops->bus_unconfig) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5609
		rv = unconfig_immediate_children(dip, dipp, flags, major);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5610
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5611
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5612
		 * call bus_unconfig entry point
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5613
		 * It should reset nexus flags if unconfigure succeeds.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5614
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5615
		bus_op = (major == (major_t)-1) ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5616
		    BUS_UNCONFIG_ALL : BUS_UNCONFIG_DRIVER;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5617
		rv = (*f)(dip, flags, bus_op, (void *)(uintptr_t)major);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5618
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5619
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5620
	pm_post_unconfig(dip, pm_cookie, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5621
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5622
	if (brevqp && *brevqp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5623
		cleanup_br_events_on_grand_children(dip, brevqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5624
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5625
	return (rv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5626
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5627
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5628
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5629
 * called by devfs/framework to unconfigure children bound to major
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5630
 * If NDI_AUTODETACH is specified, this is invoked by either the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5631
 * moduninstall daemon or the modunload -i 0 command.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5632
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5633
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5634
ndi_devi_unconfig_driver(dev_info_t *dip, int flags, major_t major)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5635
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5636
	NDI_CONFIG_DEBUG((CE_CONT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5637
	    "ndi_devi_unconfig_driver: par = %s%d (%p), flags = 0x%x\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5638
	    ddi_driver_name(dip), ddi_get_instance(dip), (void *)dip, flags));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5639
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5640
	return (devi_unconfig_common(dip, NULL, flags, major, NULL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5641
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5642
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5643
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5644
ndi_devi_unconfig(dev_info_t *dip, int flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5645
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5646
	NDI_CONFIG_DEBUG((CE_CONT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5647
	    "ndi_devi_unconfig: par = %s%d (%p), flags = 0x%x\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5648
	    ddi_driver_name(dip), ddi_get_instance(dip), (void *)dip, flags));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5649
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5650
	return (devi_unconfig_common(dip, NULL, flags, (major_t)-1, NULL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5651
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5652
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5653
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5654
e_ddi_devi_unconfig(dev_info_t *dip, dev_info_t **dipp, int flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5655
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5656
	NDI_CONFIG_DEBUG((CE_CONT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5657
	    "e_ddi_devi_unconfig: par = %s%d (%p), flags = 0x%x\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5658
	    ddi_driver_name(dip), ddi_get_instance(dip), (void *)dip, flags));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5659
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5660
	return (devi_unconfig_common(dip, dipp, flags, (major_t)-1, NULL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5661
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5662
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5663
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5664
 * Unconfigure child by name
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5665
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5666
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5667
devi_unconfig_one(dev_info_t *pdip, char *devnm, int flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5668
{
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5669
	int		rv, circ;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5670
	dev_info_t	*child;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5671
	dev_info_t	*vdip = NULL;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5672
	int		v_circ;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5673
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5674
	ndi_devi_enter(pdip, &circ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5675
	child = ndi_devi_findchild(pdip, devnm);
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5676
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5677
	/*
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5678
	 * If child is pHCI and vHCI and pHCI are not siblings then enter vHCI
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5679
	 * before parent(pHCI) to avoid deadlock with mpxio Client power
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5680
	 * management operations.
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5681
	 */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5682
	if (child && MDI_PHCI(child)) {
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5683
		vdip = mdi_devi_get_vdip(child);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5684
		if (vdip && (ddi_get_parent(vdip) != pdip)) {
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5685
			ndi_devi_exit(pdip, circ);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5686
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5687
			/* use mdi_devi_enter ordering */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5688
			ndi_devi_enter(vdip, &v_circ);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5689
			ndi_devi_enter(pdip, &circ);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5690
			child = ndi_devi_findchild(pdip, devnm);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5691
		} else
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5692
			vdip = NULL;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5693
	}
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5694
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5695
	if (child) {
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5696
		rv = devi_detach_node(child, flags);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5697
	} else {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5698
		NDI_CONFIG_DEBUG((CE_CONT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5699
		    "devi_unconfig_one: %s not found\n", devnm));
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5700
		rv = NDI_SUCCESS;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5701
	}
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5702
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5703
	ndi_devi_exit(pdip, circ);
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5704
	if (vdip)
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5705
		ndi_devi_exit(pdip, v_circ);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5706
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5707
	return (rv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5708
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5709
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5710
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5711
ndi_devi_unconfig_one(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5712
	dev_info_t *pdip,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5713
	char *devnm,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5714
	dev_info_t **dipp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5715
	int flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5716
{
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5717
	int		(*f)();
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5718
	int		circ, rv;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5719
	int		pm_cookie;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5720
	dev_info_t	*child;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5721
	dev_info_t	*vdip = NULL;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5722
	int		v_circ;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5723
	struct brevq_node *brevq = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5724
1333
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  5725
	ASSERT(i_ddi_devi_attached(pdip));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5726
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5727
	NDI_CONFIG_DEBUG((CE_CONT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5728
	    "ndi_devi_unconfig_one: par = %s%d (%p), child = %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5729
	    ddi_driver_name(pdip), ddi_get_instance(pdip),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5730
	    (void *)pdip, devnm));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5731
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5732
	if (pm_pre_unconfig(pdip, flags, &pm_cookie, devnm) != DDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5733
		return (NDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5734
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5735
	if (dipp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5736
		*dipp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5737
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5738
	ndi_devi_enter(pdip, &circ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5739
	child = ndi_devi_findchild(pdip, devnm);
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5740
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5741
	/*
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5742
	 * If child is pHCI and vHCI and pHCI are not siblings then enter vHCI
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5743
	 * before parent(pHCI) to avoid deadlock with mpxio Client power
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5744
	 * management operations.
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5745
	 */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5746
	if (child && MDI_PHCI(child)) {
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5747
		vdip = mdi_devi_get_vdip(child);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5748
		if (vdip && (ddi_get_parent(vdip) != pdip)) {
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5749
			ndi_devi_exit(pdip, circ);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5750
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5751
			/* use mdi_devi_enter ordering */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5752
			ndi_devi_enter(vdip, &v_circ);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5753
			ndi_devi_enter(pdip, &circ);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5754
			child = ndi_devi_findchild(pdip, devnm);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5755
		} else
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5756
			vdip = NULL;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5757
	}
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5758
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5759
	if (child == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5760
		NDI_CONFIG_DEBUG((CE_CONT, "ndi_devi_unconfig_one: %s"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5761
		    " not found\n", devnm));
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5762
		rv = NDI_SUCCESS;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5763
		goto out;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5764
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5765
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5766
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5767
	 * Unconfigure children/descendants of named child
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5768
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5769
	rv = devi_unconfig_branch(child, dipp, flags | NDI_UNCONFIG, &brevq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5770
	if (rv != NDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5771
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5772
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5773
	init_bound_node_ev(pdip, child, flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5774
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5775
	if ((DEVI(pdip)->devi_ops->devo_bus_ops == NULL) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5776
	    (DEVI(pdip)->devi_ops->devo_bus_ops->busops_rev < BUSO_REV_5) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5777
	    (f = DEVI(pdip)->devi_ops->devo_bus_ops->bus_unconfig) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5778
		rv = devi_detach_node(child, flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5779
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5780
		/* call bus_config entry point */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5781
		rv = (*f)(pdip, flags, BUS_UNCONFIG_ONE, (void *)devnm);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5782
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5783
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5784
	if (brevq) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5785
		if (rv != NDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5786
			log_and_free_brevq_dip(child, brevq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5787
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5788
			free_brevq(brevq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5789
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5790
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5791
	if (dipp && rv != NDI_SUCCESS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5792
		ndi_hold_devi(child);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5793
		ASSERT(*dipp == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5794
		*dipp = child;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5795
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5796
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5797
out:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5798
	ndi_devi_exit(pdip, circ);
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5799
	if (vdip)
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5800
		ndi_devi_exit(pdip, v_circ);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5801
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5802
	pm_post_unconfig(pdip, pm_cookie, devnm);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5803
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5804
	return (rv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5805
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5806
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5807
struct async_arg {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5808
	dev_info_t *dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5809
	uint_t flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5810
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5811
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5812
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5813
 * Common async handler for:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5814
 *	ndi_devi_bind_driver_async
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5815
 *	ndi_devi_online_async
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5816
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5817
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5818
i_ndi_devi_async_common(dev_info_t *dip, uint_t flags, void (*func)())
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5819
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5820
	int tqflag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5821
	int kmflag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5822
	struct async_arg *arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5823
	dev_info_t *pdip = ddi_get_parent(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5824
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5825
	ASSERT(pdip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5826
	ASSERT(DEVI(pdip)->devi_taskq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5827
	ASSERT(ndi_dev_is_persistent_node(dip));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5828
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5829
	if (flags & NDI_NOSLEEP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5830
		kmflag = KM_NOSLEEP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5831
		tqflag = TQ_NOSLEEP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5832
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5833
		kmflag = KM_SLEEP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5834
		tqflag = TQ_SLEEP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5835
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5836
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5837
	arg = kmem_alloc(sizeof (*arg), kmflag);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5838
	if (arg == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5839
		goto fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5840
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5841
	arg->flags = flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5842
	arg->dip = dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5843
	if (ddi_taskq_dispatch(DEVI(pdip)->devi_taskq, func, arg, tqflag) ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5844
	    DDI_SUCCESS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5845
		return (NDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5846
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5847
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5848
fail:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5849
	NDI_CONFIG_DEBUG((CE_CONT, "%s%d: ddi_taskq_dispatch failed",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5850
	    ddi_driver_name(pdip), ddi_get_instance(pdip)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5851
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5852
	if (arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5853
		kmem_free(arg, sizeof (*arg));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5854
	return (NDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5855
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5856
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5857
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5858
i_ndi_devi_bind_driver_cb(struct async_arg *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5859
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5860
	(void) ndi_devi_bind_driver(arg->dip, arg->flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5861
	kmem_free(arg, sizeof (*arg));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5862
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5863
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5864
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5865
ndi_devi_bind_driver_async(dev_info_t *dip, uint_t flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5866
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5867
	return (i_ndi_devi_async_common(dip, flags,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5868
	    (void (*)())i_ndi_devi_bind_driver_cb));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5869
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5870
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5871
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5872
 * place the devinfo in the ONLINE state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5873
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5874
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5875
ndi_devi_online(dev_info_t *dip, uint_t flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5876
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5877
	int circ, rv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5878
	dev_info_t *pdip = ddi_get_parent(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5879
	int branch_event = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5880
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5881
	ASSERT(pdip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5882
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5883
	NDI_CONFIG_DEBUG((CE_CONT, "ndi_devi_online: %s%d (%p)\n",
4950
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
  5884
	    ddi_driver_name(dip), ddi_get_instance(dip), (void *)dip));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5885
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5886
	ndi_devi_enter(pdip, &circ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5887
	/* bind child before merging .conf nodes */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5888
	rv = i_ndi_config_node(dip, DS_BOUND, flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5889
	if (rv != NDI_SUCCESS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5890
		ndi_devi_exit(pdip, circ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5891
		return (rv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5892
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5893
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5894
	/* merge .conf properties */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5895
	(void) i_ndi_make_spec_children(pdip, flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5896
2009
b1f98dc679ae Backout 6423041, 6426345; exposes deadlock
dm120769
parents: 1961
diff changeset
  5897
	flags |= (NDI_DEVI_ONLINE | NDI_CONFIG);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5898
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5899
	if (flags & NDI_NO_EVENT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5900
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5901
		 * Caller is specifically asking for not to generate an event.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5902
		 * Set the following flag so that devi_attach_node() don't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5903
		 * change the event state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5904
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5905
		flags |= NDI_NO_EVENT_STATE_CHNG;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5906
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5907
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5908
	if ((flags & (NDI_NO_EVENT | NDI_BRANCH_EVENT_OP)) == 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5909
	    ((flags & NDI_CONFIG) || DEVI_NEED_NDI_CONFIG(dip))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5910
		flags |= NDI_BRANCH_EVENT_OP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5911
		branch_event = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5912
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5913
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5914
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5915
	 * devi_attach_node() may remove dip on failure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5916
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5917
	if ((rv = devi_attach_node(dip, flags)) == NDI_SUCCESS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5918
		if ((flags & NDI_CONFIG) || DEVI_NEED_NDI_CONFIG(dip)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5919
			(void) ndi_devi_config(dip, flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5920
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5921
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5922
		if (branch_event)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5923
			(void) i_log_devfs_branch_add(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5924
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5925
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5926
	ndi_devi_exit(pdip, circ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5927
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5928
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5929
	 * Notify devfs that we have a new node. Devfs needs to invalidate
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5930
	 * cached directory contents.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5931
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5932
	 * For PCMCIA devices, it is possible the pdip is not fully
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5933
	 * attached. In this case, calling back into devfs will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5934
	 * result in a loop or assertion error. Hence, the check
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5935
	 * on node state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5936
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5937
	 * If we own parent lock, this is part of a branch operation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5938
	 * We skip the devfs_clean() step because the cache invalidation
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5939
	 * is done higher up in the device tree.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5940
	 */
1333
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  5941
	if (rv == NDI_SUCCESS && i_ddi_devi_attached(pdip) &&
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5942
	    !DEVI_BUSY_OWNED(pdip))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5943
		(void) devfs_clean(pdip, NULL, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5944
	return (rv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5945
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5946
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5947
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5948
i_ndi_devi_online_cb(struct async_arg *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5949
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5950
	(void) ndi_devi_online(arg->dip, arg->flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5951
	kmem_free(arg, sizeof (*arg));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5952
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5953
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5954
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5955
ndi_devi_online_async(dev_info_t *dip, uint_t flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5956
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5957
	/* mark child as need config if requested. */
495
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  5958
	if (flags & NDI_CONFIG) {
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  5959
		mutex_enter(&(DEVI(dip)->devi_lock));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5960
		DEVI_SET_NDI_CONFIG(dip);
495
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  5961
		mutex_exit(&(DEVI(dip)->devi_lock));
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  5962
	}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5963
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5964
	return (i_ndi_devi_async_common(dip, flags,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5965
	    (void (*)())i_ndi_devi_online_cb));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5966
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5967
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5968
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5969
 * Take a device node Offline
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5970
 * To take a device Offline means to detach the device instance from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5971
 * the driver and prevent devfs requests from re-attaching the device
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5972
 * instance.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5973
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5974
 * The flag NDI_DEVI_REMOVE causes removes the device node from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5975
 * the driver list and the device tree. In this case, the device
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5976
 * is assumed to be removed from the system.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5977
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5978
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5979
ndi_devi_offline(dev_info_t *dip, uint_t flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5980
{
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5981
	int		circ, rval = 0;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5982
	dev_info_t	*pdip = ddi_get_parent(dip);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5983
	dev_info_t	*vdip = NULL;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5984
	int		v_circ;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5985
	struct brevq_node *brevq = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5986
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5987
	ASSERT(pdip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5988
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5989
	flags |= NDI_DEVI_OFFLINE;
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5990
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5991
	/*
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5992
	 * If child is pHCI and vHCI and pHCI are not siblings then enter vHCI
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5993
	 * before parent(pHCI) to avoid deadlock with mpxio Client power
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5994
	 * management operations.
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5995
	 */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5996
	if (MDI_PHCI(dip)) {
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5997
		vdip = mdi_devi_get_vdip(dip);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5998
		if (vdip && (ddi_get_parent(vdip) != pdip))
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  5999
			ndi_devi_enter(vdip, &v_circ);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  6000
		else
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  6001
			vdip = NULL;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  6002
	}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6003
	ndi_devi_enter(pdip, &circ);
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  6004
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6005
	if (i_ddi_node_state(dip) == DS_READY) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6006
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6007
		 * If dip is in DS_READY state, there may be cached dv_nodes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6008
		 * referencing this dip, so we invoke devfs code path.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6009
		 * Note that we must release busy changing on pdip to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6010
		 * avoid deadlock against devfs.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6011
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6012
		char *devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6013
		(void) ddi_deviname(dip, devname);
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  6014
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6015
		ndi_devi_exit(pdip, circ);
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  6016
		if (vdip)
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  6017
			ndi_devi_exit(vdip, v_circ);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6018
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6019
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6020
		 * If we own parent lock, this is part of a branch
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6021
		 * operation. We skip the devfs_clean() step.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6022
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6023
		if (!DEVI_BUSY_OWNED(pdip))
4411
d3fb57af2eda 6565553 devfs_clean() should not be used to test for offlinability
vikram
parents: 4145
diff changeset
  6024
			(void) devfs_clean(pdip, devname + 1, DV_CLEAN_FORCE);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6025
		kmem_free(devname, MAXNAMELEN + 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6026
4411
d3fb57af2eda 6565553 devfs_clean() should not be used to test for offlinability
vikram
parents: 4145
diff changeset
  6027
		rval = devi_unconfig_branch(dip, NULL, flags|NDI_UNCONFIG,
d3fb57af2eda 6565553 devfs_clean() should not be used to test for offlinability
vikram
parents: 4145
diff changeset
  6028
		    &brevq);
d3fb57af2eda 6565553 devfs_clean() should not be used to test for offlinability
vikram
parents: 4145
diff changeset
  6029
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6030
		if (rval)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6031
			return (NDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6032
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  6033
		if (vdip)
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  6034
			ndi_devi_enter(vdip, &v_circ);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6035
		ndi_devi_enter(pdip, &circ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6036
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6037
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6038
	init_bound_node_ev(pdip, dip, flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6039
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6040
	rval = devi_detach_node(dip, flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6041
	if (brevq) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6042
		if (rval != NDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6043
			log_and_free_brevq_dip(dip, brevq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6044
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6045
			free_brevq(brevq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6046
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6047
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6048
	ndi_devi_exit(pdip, circ);
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  6049
	if (vdip)
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  6050
		ndi_devi_exit(vdip, v_circ);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6051
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6052
	return (rval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6053
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6054
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6055
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6056
 * Find the child dev_info node of parent nexus 'p' whose name
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6057
 * matches "cname@caddr".  Recommend use of ndi_devi_findchild() instead.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6058
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6059
dev_info_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6060
ndi_devi_find(dev_info_t *pdip, char *cname, char *caddr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6061
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6062
	dev_info_t *child;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6063
	int circ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6064
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6065
	if (pdip == NULL || cname == NULL || caddr == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6066
		return ((dev_info_t *)NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6067
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6068
	ndi_devi_enter(pdip, &circ);
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  6069
	child = find_sibling(ddi_get_child(pdip), cname, caddr,
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  6070
	    FIND_NODE_BY_NODENAME, NULL);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6071
	ndi_devi_exit(pdip, circ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6072
	return (child);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6073
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6074
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6075
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6076
 * Find the child dev_info node of parent nexus 'p' whose name
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6077
 * matches devname "name@addr".  Permits caller to hold the parent.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6078
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6079
dev_info_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6080
ndi_devi_findchild(dev_info_t *pdip, char *devname)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6081
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6082
	dev_info_t *child;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6083
	char	*cname, *caddr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6084
	char	*devstr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6085
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6086
	ASSERT(DEVI_BUSY_OWNED(pdip));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6087
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6088
	devstr = i_ddi_strdup(devname, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6089
	i_ddi_parse_name(devstr, &cname, &caddr, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6090
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6091
	if (cname == NULL || caddr == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6092
		kmem_free(devstr, strlen(devname)+1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6093
		return ((dev_info_t *)NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6094
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6095
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  6096
	child = find_sibling(ddi_get_child(pdip), cname, caddr,
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  6097
	    FIND_NODE_BY_NODENAME, NULL);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6098
	kmem_free(devstr, strlen(devname)+1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6099
	return (child);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6100
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6101
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6102
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6103
 * Misc. routines called by framework only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6104
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6105
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6106
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6107
 * Clear the DEVI_MADE_CHILDREN/DEVI_ATTACHED_CHILDREN flags
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6108
 * if new child spec has been added.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6109
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6110
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6111
reset_nexus_flags(dev_info_t *dip, void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6112
{
298
dde238e879a8 6303210 Assertion failure: DEVI(pdip)->devi_flags & DEVI_MADE_CHILDREN
cth
parents: 53
diff changeset
  6113
	struct hwc_spec	*list;
dde238e879a8 6303210 Assertion failure: DEVI(pdip)->devi_flags & DEVI_MADE_CHILDREN
cth
parents: 53
diff changeset
  6114
	int		circ;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6115
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6116
	if (((DEVI(dip)->devi_flags & DEVI_MADE_CHILDREN) == 0) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6117
	    ((list = hwc_get_child_spec(dip, (major_t)(uintptr_t)arg)) == NULL))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6118
		return (DDI_WALK_CONTINUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6119
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6120
	hwc_free_spec_list(list);
298
dde238e879a8 6303210 Assertion failure: DEVI(pdip)->devi_flags & DEVI_MADE_CHILDREN
cth
parents: 53
diff changeset
  6121
dde238e879a8 6303210 Assertion failure: DEVI(pdip)->devi_flags & DEVI_MADE_CHILDREN
cth
parents: 53
diff changeset
  6122
	/* coordinate child state update */
dde238e879a8 6303210 Assertion failure: DEVI(pdip)->devi_flags & DEVI_MADE_CHILDREN
cth
parents: 53
diff changeset
  6123
	ndi_devi_enter(dip, &circ);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6124
	mutex_enter(&DEVI(dip)->devi_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6125
	DEVI(dip)->devi_flags &= ~(DEVI_MADE_CHILDREN | DEVI_ATTACHED_CHILDREN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6126
	mutex_exit(&DEVI(dip)->devi_lock);
298
dde238e879a8 6303210 Assertion failure: DEVI(pdip)->devi_flags & DEVI_MADE_CHILDREN
cth
parents: 53
diff changeset
  6127
	ndi_devi_exit(dip, circ);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6128
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6129
	return (DDI_WALK_CONTINUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6130
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6131
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6132
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6133
 * Helper functions, returns NULL if no memory.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6134
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6135
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6136
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6137
 * path_to_major:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6138
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6139
 * Return an alternate driver name binding for the leaf device
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6140
 * of the given pathname, if there is one. The purpose of this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6141
 * function is to deal with generic pathnames. The default action
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6142
 * for platforms that can't do this (ie: x86 or any platform that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6143
 * does not have prom_finddevice functionality, which matches
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6144
 * nodenames and unit-addresses without the drivers participation)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6145
 * is to return (major_t)-1.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6146
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6147
 * Used in loadrootmodules() in the swapgeneric module to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6148
 * associate a given pathname with a given leaf driver.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6149
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6150
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6151
major_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6152
path_to_major(char *path)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6153
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6154
	dev_info_t *dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6155
	char *p, *q;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 693
diff changeset
  6156
	pnode_t nodeid;
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  6157
	major_t major;
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  6158
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  6159
	/* check for path-oriented alias */
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  6160
	major = ddi_name_to_major(path);
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  6161
	if ((major != (major_t)-1) &&
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  6162
	    !(devnamesp[major].dn_flags & DN_DRIVER_REMOVED)) {
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  6163
		NDI_CONFIG_DEBUG((CE_NOTE, "path_to_major: %s path bound %s\n",
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  6164
		    path, ddi_major_to_name(major)));
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  6165
		return (major);
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  6166
	}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6167
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6168
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6169
	 * Get the nodeid of the given pathname, if such a mapping exists.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6170
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6171
	dip = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6172
	nodeid = prom_finddevice(path);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6173
	if (nodeid != OBP_BADNODE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6174
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6175
		 * Find the nodeid in our copy of the device tree and return
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6176
		 * whatever name we used to bind this node to a driver.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6177
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6178
		dip = e_ddi_nodeid_to_dip(nodeid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6179
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6180
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6181
	if (dip == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6182
		NDI_CONFIG_DEBUG((CE_WARN,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6183
		    "path_to_major: can't bind <%s>\n", path));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6184
		return ((major_t)-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6185
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6186
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6187
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6188
	 * If we're bound to something other than the nodename,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6189
	 * note that in the message buffer and system log.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6190
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6191
	p = ddi_binding_name(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6192
	q = ddi_node_name(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6193
	if (p && q && (strcmp(p, q) != 0))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6194
		NDI_CONFIG_DEBUG((CE_NOTE, "path_to_major: %s bound to %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6195
		    path, p));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6196
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  6197
	major = ddi_name_to_major(p);
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  6198
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  6199
	ndi_rele_devi(dip);		/* release e_ddi_nodeid_to_dip hold */
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  6200
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  6201
	return (major);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6202
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6203
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6204
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6205
 * Return the held dip for the specified major and instance, attempting to do
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6206
 * an attach if specified. Return NULL if the devi can't be found or put in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6207
 * the proper state. The caller must release the hold via ddi_release_devi if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6208
 * a non-NULL value is returned.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6209
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6210
 * Some callers expect to be able to perform a hold_devi() while in a context
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6211
 * where using ndi_devi_enter() to ensure the hold might cause deadlock (see
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6212
 * open-from-attach code in consconfig_dacf.c). Such special-case callers
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6213
 * must ensure that an ndi_devi_enter(parent)/ndi_devi_hold() from a safe
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6214
 * context is already active. The hold_devi() implementation must accommodate
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6215
 * these callers.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6216
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6217
static dev_info_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6218
hold_devi(major_t major, int instance, int flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6219
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6220
	struct devnames	*dnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6221
	dev_info_t	*dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6222
	char		*path;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6223
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6224
	if ((major >= devcnt) || (instance == -1))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6225
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6226
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6227
	/* try to find the instance in the per driver list */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6228
	dnp = &(devnamesp[major]);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6229
	LOCK_DEV_OPS(&(dnp->dn_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6230
	for (dip = dnp->dn_head; dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6231
	    dip = (dev_info_t *)DEVI(dip)->devi_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6232
		/* skip node if instance field is not valid */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6233
		if (i_ddi_node_state(dip) < DS_INITIALIZED)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6234
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6235
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6236
		/* look for instance match */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6237
		if (DEVI(dip)->devi_instance == instance) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6238
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6239
			 * To accommodate callers that can't block in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6240
			 * ndi_devi_enter() we do an ndi_devi_hold(), and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6241
			 * afterwards check that the node is in a state where
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6242
			 * the hold prevents detach(). If we did not manage to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6243
			 * prevent detach then we ndi_rele_devi() and perform
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6244
			 * the slow path below (which can result in a blocking
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6245
			 * ndi_devi_enter() while driving attach top-down).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6246
			 * This code depends on the ordering of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6247
			 * DEVI_SET_DETACHING and the devi_ref check in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6248
			 * detach_node() code path.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6249
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6250
			ndi_hold_devi(dip);
1333
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  6251
			if (i_ddi_devi_attached(dip) &&
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6252
			    !DEVI_IS_DETACHING(dip)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6253
				UNLOCK_DEV_OPS(&(dnp->dn_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6254
				return (dip);	/* fast-path with devi held */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6255
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6256
			ndi_rele_devi(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6257
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6258
			/* try slow-path */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6259
			dip = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6260
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6261
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6262
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6263
	ASSERT(dip == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6264
	UNLOCK_DEV_OPS(&(dnp->dn_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6265
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6266
	if (flags & E_DDI_HOLD_DEVI_NOATTACH)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6267
		return (NULL);		/* told not to drive attach */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6268
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6269
	/* slow-path may block, so it should not occur from interrupt */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6270
	ASSERT(!servicing_interrupt());
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6271
	if (servicing_interrupt())
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6272
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6273
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6274
	/* reconstruct the path and drive attach by path through devfs. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6275
	path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6276
	if (e_ddi_majorinstance_to_path(major, instance, path) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6277
		dip = e_ddi_hold_devi_by_path(path, flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6278
	kmem_free(path, MAXPATHLEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6279
	return (dip);			/* with devi held */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6280
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6281
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6282
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6283
 * The {e_}ddi_hold_devi{_by_{instance|dev|path}} hold the devinfo node
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6284
 * associated with the specified arguments.  This hold should be released
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6285
 * by calling ddi_release_devi.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6286
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6287
 * The E_DDI_HOLD_DEVI_NOATTACH flag argument allows the caller to to specify
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6288
 * a failure return if the node is not already attached.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6289
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6290
 * NOTE: by the time we make e_ddi_hold_devi public, we should be able to reuse
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6291
 * ddi_hold_devi again.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6292
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6293
dev_info_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6294
ddi_hold_devi_by_instance(major_t major, int instance, int flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6295
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6296
	return (hold_devi(major, instance, flags));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6297
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6298
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6299
dev_info_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6300
e_ddi_hold_devi_by_dev(dev_t dev, int flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6301
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6302
	major_t	major = getmajor(dev);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6303
	dev_info_t	*dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6304
	struct dev_ops	*ops;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6305
	dev_info_t	*ddip = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6306
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6307
	dip = hold_devi(major, dev_to_instance(dev), flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6308
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6309
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6310
	 * The rest of this routine is legacy support for drivers that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6311
	 * have broken DDI_INFO_DEVT2INSTANCE implementations but may have
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6312
	 * functional DDI_INFO_DEVT2DEVINFO implementations.  This code will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6313
	 * diagnose inconsistency and, for maximum compatibility with legacy
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6314
	 * drivers, give preference to the drivers DDI_INFO_DEVT2DEVINFO
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6315
	 * implementation over the above derived dip based the driver's
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6316
	 * DDI_INFO_DEVT2INSTANCE implementation. This legacy support should
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6317
	 * be removed when DDI_INFO_DEVT2DEVINFO is deprecated.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6318
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6319
	 * NOTE: The following code has a race condition. DEVT2DEVINFO
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6320
	 *	returns a dip which is not held. By the time we ref ddip,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6321
	 *	it could have been freed. The saving grace is that for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6322
	 *	most drivers, the dip returned from hold_devi() is the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6323
	 *	same one as the one returned by DEVT2DEVINFO, so we are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6324
	 *	safe for drivers with the correct getinfo(9e) impl.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6325
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6326
	if (((ops = ddi_hold_driver(major)) != NULL) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6327
	    CB_DRV_INSTALLED(ops) && ops->devo_getinfo)  {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6328
		if ((*ops->devo_getinfo)(NULL, DDI_INFO_DEVT2DEVINFO,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6329
		    (void *)dev, (void **)&ddip) != DDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6330
			ddip = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6331
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6332
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6333
	/* give preference to the driver returned DEVT2DEVINFO dip */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6334
	if (ddip && (dip != ddip)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6335
#ifdef	DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6336
		cmn_err(CE_WARN, "%s: inconsistent getinfo(9E) implementation",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6337
		    ddi_driver_name(ddip));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6338
#endif	/* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6339
		ndi_hold_devi(ddip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6340
		if (dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6341
			ndi_rele_devi(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6342
		dip = ddip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6343
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6344
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6345
	if (ops)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6346
		ddi_rele_driver(major);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6347
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6348
	return (dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6349
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6350
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6351
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6352
 * For compatibility only. Do not call this function!
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6353
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6354
dev_info_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6355
e_ddi_get_dev_info(dev_t dev, vtype_t type)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6356
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6357
	dev_info_t *dip = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6358
	if (getmajor(dev) >= devcnt)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6359
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6360
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6361
	switch (type) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6362
	case VCHR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6363
	case VBLK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6364
		dip = e_ddi_hold_devi_by_dev(dev, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6365
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6366
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6367
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6368
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6369
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6370
	 * For compatibility reasons, we can only return the dip with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6371
	 * the driver ref count held. This is not a safe thing to do.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6372
	 * For certain broken third-party software, we are willing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6373
	 * to venture into unknown territory.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6374
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6375
	if (dip) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6376
		(void) ndi_hold_driver(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6377
		ndi_rele_devi(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6378
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6379
	return (dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6380
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6381
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6382
dev_info_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6383
e_ddi_hold_devi_by_path(char *path, int flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6384
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6385
	dev_info_t	*dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6386
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6387
	/* can't specify NOATTACH by path */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6388
	ASSERT(!(flags & E_DDI_HOLD_DEVI_NOATTACH));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6389
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6390
	return (resolve_pathname(path, &dip, NULL, NULL) ? NULL : dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6391
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6392
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6393
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6394
e_ddi_hold_devi(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6395
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6396
	ndi_hold_devi(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6397
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6398
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6399
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6400
ddi_release_devi(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6401
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6402
	ndi_rele_devi(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6403
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6404
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6405
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6406
 * Associate a streams queue with a devinfo node
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6407
 * NOTE: This function is called by STREAM driver's put procedure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6408
 *	It cannot block.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6409
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6410
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6411
ddi_assoc_queue_with_devi(queue_t *q, dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6412
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6413
	queue_t *rq = _RD(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6414
	struct stdata *stp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6415
	vnode_t *vp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6416
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6417
	/* set flag indicating that ddi_assoc_queue_with_devi was called */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6418
	mutex_enter(QLOCK(rq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6419
	rq->q_flag |= _QASSOCIATED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6420
	mutex_exit(QLOCK(rq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6421
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6422
	/* get the vnode associated with the queue */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6423
	stp = STREAM(rq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6424
	vp = stp->sd_vnode;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6425
	ASSERT(vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6426
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6427
	/* change the hardware association of the vnode */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6428
	spec_assoc_vp_with_devi(vp, dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6429
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6430
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6431
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6432
 * ddi_install_driver(name)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6433
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6434
 * Driver installation is currently a byproduct of driver loading.  This
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6435
 * may change.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6436
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6437
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6438
ddi_install_driver(char *name)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6439
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6440
	major_t major = ddi_name_to_major(name);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6441
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6442
	if ((major == (major_t)-1) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6443
	    (ddi_hold_installed_driver(major) == NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6444
		return (DDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6445
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6446
	ddi_rele_driver(major);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6447
	return (DDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6448
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6449
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6450
struct dev_ops *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6451
ddi_hold_driver(major_t major)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6452
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6453
	return (mod_hold_dev_by_major(major));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6454
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6455
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6456
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6457
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6458
ddi_rele_driver(major_t major)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6459
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6460
	mod_rele_dev_by_major(major);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6461
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6462
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6463
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6464
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6465
 * This is called during boot to force attachment order of special dips
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6466
 * dip must be referenced via ndi_hold_devi()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6467
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6468
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6469
i_ddi_attach_node_hierarchy(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6470
{
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  6471
	dev_info_t	*parent;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  6472
	int		ret, circ;
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  6473
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  6474
	/*
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  6475
	 * Recurse up until attached parent is found.
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  6476
	 */
2009
b1f98dc679ae Backout 6423041, 6426345; exposes deadlock
dm120769
parents: 1961
diff changeset
  6477
	if (i_ddi_devi_attached(dip))
b1f98dc679ae Backout 6423041, 6426345; exposes deadlock
dm120769
parents: 1961
diff changeset
  6478
		return (DDI_SUCCESS);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6479
	parent = ddi_get_parent(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6480
	if (i_ddi_attach_node_hierarchy(parent) != DDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6481
		return (DDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6482
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6483
	/*
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  6484
	 * Come top-down, expanding .conf nodes under this parent
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  6485
	 * and driving attach.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6486
	 */
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  6487
	ndi_devi_enter(parent, &circ);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6488
	(void) i_ndi_make_spec_children(parent, 0);
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  6489
	ret = i_ddi_attachchild(dip);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  6490
	ndi_devi_exit(parent, circ);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  6491
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  6492
	return (ret);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6493
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6494
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6495
/* keep this function static */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6496
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6497
attach_driver_nodes(major_t major)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6498
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6499
	struct devnames *dnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6500
	dev_info_t *dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6501
	int error = DDI_FAILURE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6502
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6503
	dnp = &devnamesp[major];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6504
	LOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6505
	dip = dnp->dn_head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6506
	while (dip) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6507
		ndi_hold_devi(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6508
		UNLOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6509
		if (i_ddi_attach_node_hierarchy(dip) == DDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6510
			error = DDI_SUCCESS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6511
		LOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6512
		ndi_rele_devi(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6513
		dip = ddi_get_next(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6514
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6515
	if (error == DDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6516
		dnp->dn_flags |= DN_NO_AUTODETACH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6517
	UNLOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6518
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6519
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6520
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6521
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6522
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6523
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6524
 * i_ddi_attach_hw_nodes configures and attaches all hw nodes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6525
 * bound to a specific driver. This function replaces calls to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6526
 * ddi_hold_installed_driver() for drivers with no .conf
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6527
 * enumerated nodes.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6528
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6529
 * This facility is typically called at boot time to attach
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6530
 * platform-specific hardware nodes, such as ppm nodes on xcal
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6531
 * and grover and keyswitch nodes on cherrystone. It does not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6532
 * deal with .conf enumerated node. Calling it beyond the boot
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6533
 * process is strongly discouraged.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6534
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6535
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6536
i_ddi_attach_hw_nodes(char *driver)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6537
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6538
	major_t major;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6539
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6540
	major = ddi_name_to_major(driver);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6541
	if (major == (major_t)-1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6542
		return (DDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6543
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6544
	return (attach_driver_nodes(major));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6545
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6546
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6547
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6548
 * i_ddi_attach_pseudo_node configures pseudo drivers which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6549
 * has a single node. The .conf nodes must be enumerated
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6550
 * before calling this interface. The dip is held attached
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6551
 * upon returning.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6552
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6553
 * This facility should only be called only at boot time
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6554
 * by the I/O framework.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6555
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6556
dev_info_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6557
i_ddi_attach_pseudo_node(char *driver)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6558
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6559
	major_t major;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6560
	dev_info_t *dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6561
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6562
	major = ddi_name_to_major(driver);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6563
	if (major == (major_t)-1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6564
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6565
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6566
	if (attach_driver_nodes(major) != DDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6567
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6568
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6569
	dip = devnamesp[major].dn_head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6570
	ASSERT(dip && ddi_get_next(dip) == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6571
	ndi_hold_devi(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6572
	return (dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6573
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6574
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6575
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6576
diplist_to_parent_major(dev_info_t *head, char parents[])
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6577
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6578
	major_t major;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6579
	dev_info_t *dip, *pdip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6580
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6581
	for (dip = head; dip != NULL; dip = ddi_get_next(dip)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6582
		pdip = ddi_get_parent(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6583
		ASSERT(pdip);	/* disallow rootnex.conf nodes */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6584
		major = ddi_driver_major(pdip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6585
		if ((major != (major_t)-1) && parents[major] == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6586
			parents[major] = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6587
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6588
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6589
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6590
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6591
 * Call ddi_hold_installed_driver() on each parent major
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6592
 * and invoke mt_config_driver() to attach child major.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6593
 * This is part of the implementation of ddi_hold_installed_driver.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6594
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6595
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6596
attach_driver_by_parent(major_t child_major, char parents[])
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6597
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6598
	major_t par_major;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6599
	struct mt_config_handle *hdl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6600
	int flags = NDI_DEVI_PERSIST | NDI_NO_EVENT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6601
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6602
	hdl = mt_config_init(NULL, NULL, flags, child_major, MT_CONFIG_OP,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6603
	    NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6604
	for (par_major = 0; par_major < devcnt; par_major++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6605
		/* disallow recursion on the same driver */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6606
		if (parents[par_major] == 0 || par_major == child_major)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6607
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6608
		if (ddi_hold_installed_driver(par_major) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6609
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6610
		hdl->mtc_parmajor = par_major;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6611
		mt_config_driver(hdl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6612
		ddi_rele_driver(par_major);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6613
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6614
	(void) mt_config_fini(hdl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6615
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6616
	return (i_ddi_devs_attached(child_major));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6617
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6618
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6619
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6620
i_ddi_devs_attached(major_t major)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6621
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6622
	dev_info_t *dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6623
	struct devnames *dnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6624
	int error = DDI_FAILURE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6625
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6626
	/* check for attached instances */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6627
	dnp = &devnamesp[major];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6628
	LOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6629
	for (dip = dnp->dn_head; dip != NULL; dip = ddi_get_next(dip)) {
1333
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  6630
		if (i_ddi_devi_attached(dip)) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6631
			error = DDI_SUCCESS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6632
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6633
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6634
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6635
	UNLOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6636
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6637
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6638
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6639
5895
f251acdd9bdc PSARC/2006/499 Clearview Nemo unification and vanity naming
yz147064
parents: 5742
diff changeset
  6640
int
f251acdd9bdc PSARC/2006/499 Clearview Nemo unification and vanity naming
yz147064
parents: 5742
diff changeset
  6641
i_ddi_minor_node_count(dev_info_t *ddip, const char *node_type)
f251acdd9bdc PSARC/2006/499 Clearview Nemo unification and vanity naming
yz147064
parents: 5742
diff changeset
  6642
{
f251acdd9bdc PSARC/2006/499 Clearview Nemo unification and vanity naming
yz147064
parents: 5742
diff changeset
  6643
	struct ddi_minor_data *dp;
f251acdd9bdc PSARC/2006/499 Clearview Nemo unification and vanity naming
yz147064
parents: 5742
diff changeset
  6644
	int count = 0;
f251acdd9bdc PSARC/2006/499 Clearview Nemo unification and vanity naming
yz147064
parents: 5742
diff changeset
  6645
f251acdd9bdc PSARC/2006/499 Clearview Nemo unification and vanity naming
yz147064
parents: 5742
diff changeset
  6646
	mutex_enter(&(DEVI(ddip)->devi_lock));
f251acdd9bdc PSARC/2006/499 Clearview Nemo unification and vanity naming
yz147064
parents: 5742
diff changeset
  6647
	for (dp = DEVI(ddip)->devi_minor; dp != NULL; dp = dp->next)
f251acdd9bdc PSARC/2006/499 Clearview Nemo unification and vanity naming
yz147064
parents: 5742
diff changeset
  6648
		if (strcmp(dp->ddm_node_type, node_type) == 0)
f251acdd9bdc PSARC/2006/499 Clearview Nemo unification and vanity naming
yz147064
parents: 5742
diff changeset
  6649
			count++;
f251acdd9bdc PSARC/2006/499 Clearview Nemo unification and vanity naming
yz147064
parents: 5742
diff changeset
  6650
	mutex_exit(&(DEVI(ddip)->devi_lock));
f251acdd9bdc PSARC/2006/499 Clearview Nemo unification and vanity naming
yz147064
parents: 5742
diff changeset
  6651
	return (count);
f251acdd9bdc PSARC/2006/499 Clearview Nemo unification and vanity naming
yz147064
parents: 5742
diff changeset
  6652
}
f251acdd9bdc PSARC/2006/499 Clearview Nemo unification and vanity naming
yz147064
parents: 5742
diff changeset
  6653
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6654
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6655
 * ddi_hold_installed_driver configures and attaches all
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6656
 * instances of the specified driver. To accomplish this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6657
 * it configures and attaches all possible parents of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6658
 * the driver, enumerated both in h/w nodes and in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6659
 * driver's .conf file.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6660
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6661
 * NOTE: This facility is for compatibility purposes only and will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6662
 *	eventually go away. Its usage is strongly discouraged.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6663
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6664
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6665
enter_driver(struct devnames *dnp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6666
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6667
	mutex_enter(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6668
	ASSERT(dnp->dn_busy_thread != curthread);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6669
	while (dnp->dn_flags & DN_DRIVER_BUSY)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6670
		cv_wait(&dnp->dn_wait, &dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6671
	dnp->dn_flags |= DN_DRIVER_BUSY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6672
	dnp->dn_busy_thread = curthread;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6673
	mutex_exit(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6674
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6675
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6676
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6677
exit_driver(struct devnames *dnp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6678
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6679
	mutex_enter(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6680
	ASSERT(dnp->dn_busy_thread == curthread);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6681
	dnp->dn_flags &= ~DN_DRIVER_BUSY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6682
	dnp->dn_busy_thread = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6683
	cv_broadcast(&dnp->dn_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6684
	mutex_exit(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6685
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6686
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6687
struct dev_ops *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6688
ddi_hold_installed_driver(major_t major)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6689
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6690
	struct dev_ops *ops;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6691
	struct devnames *dnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6692
	char *parents;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6693
	int error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6694
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6695
	ops = ddi_hold_driver(major);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6696
	if (ops == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6697
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6698
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6699
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6700
	 * Return immediately if all the attach operations associated
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6701
	 * with a ddi_hold_installed_driver() call have already been done.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6702
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6703
	dnp = &devnamesp[major];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6704
	enter_driver(dnp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6705
	if (dnp->dn_flags & DN_DRIVER_HELD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6706
		exit_driver(dnp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6707
		if (i_ddi_devs_attached(major) == DDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6708
			return (ops);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6709
		ddi_rele_driver(major);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6710
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6711
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6712
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6713
	LOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6714
	dnp->dn_flags |= (DN_DRIVER_HELD | DN_NO_AUTODETACH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6715
	UNLOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6716
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6717
	DCOMPATPRINTF((CE_CONT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6718
	    "ddi_hold_installed_driver: %s\n", dnp->dn_name));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6719
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6720
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6721
	 * When the driver has no .conf children, it is sufficient
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6722
	 * to attach existing nodes in the device tree. Nodes not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6723
	 * enumerated by the OBP are not attached.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6724
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6725
	if (dnp->dn_pl == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6726
		if (attach_driver_nodes(major) == DDI_SUCCESS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6727
			exit_driver(dnp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6728
			return (ops);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6729
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6730
		exit_driver(dnp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6731
		ddi_rele_driver(major);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6732
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6733
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6734
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6735
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6736
	 * Driver has .conf nodes. We find all possible parents
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6737
	 * and recursively all ddi_hold_installed_driver on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6738
	 * parent driver; then we invoke ndi_config_driver()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6739
	 * on all possible parent node in parallel to speed up
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6740
	 * performance.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6741
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6742
	parents = kmem_zalloc(devcnt * sizeof (char), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6743
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6744
	LOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6745
	/* find .conf parents */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6746
	(void) impl_parlist_to_major(dnp->dn_pl, parents);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6747
	/* find hw node parents */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6748
	diplist_to_parent_major(dnp->dn_head, parents);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6749
	UNLOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6750
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6751
	error = attach_driver_by_parent(major, parents);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6752
	kmem_free(parents, devcnt * sizeof (char));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6753
	if (error == DDI_SUCCESS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6754
		exit_driver(dnp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6755
		return (ops);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6756
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6757
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6758
	exit_driver(dnp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6759
	ddi_rele_driver(major);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6760
	return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6761
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6762
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6763
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6764
 * Default bus_config entry point for nexus drivers
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6765
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6766
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6767
ndi_busop_bus_config(dev_info_t *pdip, uint_t flags, ddi_bus_config_op_t op,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6768
    void *arg, dev_info_t **child, clock_t timeout)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6769
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6770
	major_t major;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6771
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6772
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6773
	 * A timeout of 30 minutes or more is probably a mistake
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6774
	 * This is intended to catch uses where timeout is in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6775
	 * the wrong units.  timeout must be in units of ticks.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6776
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6777
	ASSERT(timeout < SEC_TO_TICK(1800));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6778
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6779
	major = (major_t)-1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6780
	switch (op) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6781
	case BUS_CONFIG_ONE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6782
		NDI_DEBUG(flags, (CE_CONT, "%s%d: bus config %s timeout=%ld\n",
4950
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
  6783
		    ddi_driver_name(pdip), ddi_get_instance(pdip),
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
  6784
		    (char *)arg, timeout));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6785
		return (devi_config_one(pdip, (char *)arg, child, flags,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6786
		    timeout));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6787
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6788
	case BUS_CONFIG_DRIVER:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6789
		major = (major_t)(uintptr_t)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6790
		/*FALLTHROUGH*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6791
	case BUS_CONFIG_ALL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6792
		NDI_DEBUG(flags, (CE_CONT, "%s%d: bus config timeout=%ld\n",
4950
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
  6793
		    ddi_driver_name(pdip), ddi_get_instance(pdip),
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
  6794
		    timeout));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6795
		if (timeout > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6796
			NDI_DEBUG(flags, (CE_CONT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6797
			    "%s%d: bus config all timeout=%ld\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6798
			    ddi_driver_name(pdip), ddi_get_instance(pdip),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6799
			    timeout));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6800
			delay(timeout);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6801
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6802
		return (config_immediate_children(pdip, flags, major));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6803
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6804
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6805
		return (NDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6806
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6807
	/*NOTREACHED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6808
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6809
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6810
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6811
 * Default busop bus_unconfig handler for nexus drivers
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6812
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6813
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6814
ndi_busop_bus_unconfig(dev_info_t *pdip, uint_t flags, ddi_bus_config_op_t op,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6815
    void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6816
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6817
	major_t major;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6818
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6819
	major = (major_t)-1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6820
	switch (op) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6821
	case BUS_UNCONFIG_ONE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6822
		NDI_DEBUG(flags, (CE_CONT, "%s%d: bus unconfig %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6823
		    ddi_driver_name(pdip), ddi_get_instance(pdip),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6824
		    (char *)arg));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6825
		return (devi_unconfig_one(pdip, (char *)arg, flags));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6826
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6827
	case BUS_UNCONFIG_DRIVER:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6828
		major = (major_t)(uintptr_t)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6829
		/*FALLTHROUGH*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6830
	case BUS_UNCONFIG_ALL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6831
		NDI_DEBUG(flags, (CE_CONT, "%s%d: bus unconfig all\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6832
		    ddi_driver_name(pdip), ddi_get_instance(pdip)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6833
		return (unconfig_immediate_children(pdip, NULL, flags, major));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6834
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6835
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6836
		return (NDI_FAILURE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6837
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6838
	/*NOTREACHED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6839
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6840
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6841
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6842
 * dummy functions to be removed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6843
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6844
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6845
impl_rem_dev_props(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6846
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6847
	_NOTE(ARGUNUSED(dip))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6848
	/* do nothing */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6849
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6850
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6851
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6852
 * Determine if a node is a leaf node. If not sure, return false (0).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6853
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6854
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6855
is_leaf_node(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6856
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6857
	major_t major = ddi_driver_major(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6858
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6859
	if (major == (major_t)-1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6860
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6861
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6862
	return (devnamesp[major].dn_flags & DN_LEAF_DRIVER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6863
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6864
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6865
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6866
 * Multithreaded [un]configuration
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6867
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6868
static struct mt_config_handle *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6869
mt_config_init(dev_info_t *pdip, dev_info_t **dipp, int flags,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6870
    major_t major, int op, struct brevq_node **brevqp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6871
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6872
	struct mt_config_handle	*hdl = kmem_alloc(sizeof (*hdl), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6873
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6874
	mutex_init(&hdl->mtc_lock, NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6875
	cv_init(&hdl->mtc_cv, NULL, CV_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6876
	hdl->mtc_pdip = pdip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6877
	hdl->mtc_fdip = dipp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6878
	hdl->mtc_parmajor = (major_t)-1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6879
	hdl->mtc_flags = flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6880
	hdl->mtc_major = major;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6881
	hdl->mtc_thr_count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6882
	hdl->mtc_op = op;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6883
	hdl->mtc_error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6884
	hdl->mtc_brevqp = brevqp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6885
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6886
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6887
	gethrestime(&hdl->start_time);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6888
	hdl->total_time = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6889
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6890
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6891
	return (hdl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6892
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6893
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6894
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6895
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6896
time_diff_in_msec(timestruc_t start, timestruc_t end)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6897
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6898
	int	nsec, sec;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6899
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6900
	sec = end.tv_sec - start.tv_sec;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6901
	nsec = end.tv_nsec - start.tv_nsec;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6902
	if (nsec < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6903
		nsec += NANOSEC;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6904
		sec -= 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6905
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6906
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6907
	return (sec * (NANOSEC >> 20) + (nsec >> 20));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6908
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6909
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6910
#endif	/* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6911
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6912
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6913
mt_config_fini(struct mt_config_handle *hdl)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6914
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6915
	int		rv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6916
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6917
	int		real_time;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6918
	timestruc_t	end_time;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6919
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6920
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6921
	mutex_enter(&hdl->mtc_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6922
	while (hdl->mtc_thr_count > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6923
		cv_wait(&hdl->mtc_cv, &hdl->mtc_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6924
	rv = hdl->mtc_error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6925
	mutex_exit(&hdl->mtc_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6926
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6927
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6928
	gethrestime(&end_time);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6929
	real_time = time_diff_in_msec(hdl->start_time, end_time);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6930
	if ((ddidebug & DDI_MTCONFIG) && hdl->mtc_pdip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6931
		cmn_err(CE_NOTE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6932
		    "config %s%d: total time %d msec, real time %d msec",
4950
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
  6933
		    ddi_driver_name(hdl->mtc_pdip),
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
  6934
		    ddi_get_instance(hdl->mtc_pdip),
a7a707716fea 6594969 path oriented rebind code needs to protect nexus parent from detach
cth
parents: 4845
diff changeset
  6935
		    hdl->total_time, real_time);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6936
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6937
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6938
	cv_destroy(&hdl->mtc_cv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6939
	mutex_destroy(&hdl->mtc_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6940
	kmem_free(hdl, sizeof (*hdl));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6941
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6942
	return (rv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6943
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6944
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6945
struct mt_config_data {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6946
	struct mt_config_handle	*mtc_hdl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6947
	dev_info_t		*mtc_dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6948
	major_t			mtc_major;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6949
	int			mtc_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6950
	struct brevq_node	*mtc_brn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6951
	struct mt_config_data	*mtc_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6952
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6953
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6954
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6955
mt_config_thread(void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6956
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6957
	struct mt_config_data	*mcd = (struct mt_config_data *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6958
	struct mt_config_handle	*hdl = mcd->mtc_hdl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6959
	dev_info_t		*dip = mcd->mtc_dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6960
	dev_info_t		*rdip, **dipp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6961
	major_t			major = mcd->mtc_major;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6962
	int			flags = mcd->mtc_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6963
	int			rv = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6964
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6965
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6966
	timestruc_t start_time, end_time;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6967
	gethrestime(&start_time);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6968
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6969
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6970
	rdip = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6971
	dipp = hdl->mtc_fdip ? &rdip : NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6972
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6973
	switch (hdl->mtc_op) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6974
	case MT_CONFIG_OP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6975
		rv = devi_config_common(dip, flags, major);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6976
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6977
	case MT_UNCONFIG_OP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6978
		if (mcd->mtc_brn) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6979
			struct brevq_node *brevq = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6980
			rv = devi_unconfig_common(dip, dipp, flags, major,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6981
			    &brevq);
1317
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  6982
			mcd->mtc_brn->brn_child = brevq;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6983
		} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6984
			rv = devi_unconfig_common(dip, dipp, flags, major,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6985
			    NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6986
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6987
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6988
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6989
	mutex_enter(&hdl->mtc_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6990
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6991
	gethrestime(&end_time);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6992
	hdl->total_time += time_diff_in_msec(start_time, end_time);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6993
#endif /* DEBUG */
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  6994
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  6995
	if ((rv != NDI_SUCCESS) && (hdl->mtc_error == 0)) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6996
		hdl->mtc_error = rv;
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  6997
#ifdef	DEBUG
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  6998
		if ((ddidebug & DDI_DEBUG) && (major != (major_t)-1)) {
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  6999
			char	*path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  7000
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  7001
			(void) ddi_pathname(dip, path);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  7002
			cmn_err(CE_NOTE, "mt_config_thread: "
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  7003
			    "op %d.%d.%x at %s failed %d",
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  7004
			    hdl->mtc_op, major, flags, path, rv);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  7005
			kmem_free(path, MAXPATHLEN);
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  7006
		}
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  7007
#endif	/* DEBUG */
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  7008
	}
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  7009
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7010
	if (hdl->mtc_fdip && *hdl->mtc_fdip == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7011
		*hdl->mtc_fdip = rdip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7012
		rdip = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7013
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7014
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7015
	if (rdip) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7016
		ASSERT(rv != NDI_SUCCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7017
		ndi_rele_devi(rdip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7018
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7019
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7020
	ndi_rele_devi(dip);
1826
8b76ba84edbf 6405619 mt_config_thread() says it is done before it really is
bm42561
parents: 1333
diff changeset
  7021
8b76ba84edbf 6405619 mt_config_thread() says it is done before it really is
bm42561
parents: 1333
diff changeset
  7022
	if (--hdl->mtc_thr_count == 0)
8b76ba84edbf 6405619 mt_config_thread() says it is done before it really is
bm42561
parents: 1333
diff changeset
  7023
		cv_broadcast(&hdl->mtc_cv);
8b76ba84edbf 6405619 mt_config_thread() says it is done before it really is
bm42561
parents: 1333
diff changeset
  7024
	mutex_exit(&hdl->mtc_lock);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7025
	kmem_free(mcd, sizeof (*mcd));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7026
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7027
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7028
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7029
 * Multi-threaded config/unconfig of child nexus
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7030
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7031
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7032
mt_config_children(struct mt_config_handle *hdl)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7033
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7034
	dev_info_t		*pdip = hdl->mtc_pdip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7035
	major_t			major = hdl->mtc_major;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7036
	dev_info_t		*dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7037
	int			circ;
1317
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  7038
	struct brevq_node	*brn;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7039
	struct mt_config_data	*mcd_head = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7040
	struct mt_config_data	*mcd_tail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7041
	struct mt_config_data	*mcd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7042
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7043
	timestruc_t		end_time;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7044
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7045
	/* Update total_time in handle */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7046
	gethrestime(&end_time);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7047
	hdl->total_time += time_diff_in_msec(hdl->start_time, end_time);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7048
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7049
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7050
	ndi_devi_enter(pdip, &circ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7051
	dip = ddi_get_child(pdip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7052
	while (dip) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7053
		if (hdl->mtc_op == MT_UNCONFIG_OP && hdl->mtc_brevqp &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7054
		    !(DEVI_EVREMOVE(dip)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7055
		    i_ddi_node_state(dip) >= DS_INITIALIZED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7056
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7057
			 * Enqueue this dip's deviname.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7058
			 * No need to hold a lock while enqueuing since this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7059
			 * is the only thread doing the enqueue and no one
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7060
			 * walks the queue while we are in multithreaded
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7061
			 * unconfiguration.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7062
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7063
			brn = brevq_enqueue(hdl->mtc_brevqp, dip, NULL);
1317
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  7064
		} else
632121dc3a0f 6364339 Memory leaks are found in "brevq_enqueue()"
cth
parents: 1093
diff changeset
  7065
			brn = NULL;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7066
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7067
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7068
		 * Hold the child that we are processing so he does not get
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7069
		 * removed. The corrisponding ndi_rele_devi() for children
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7070
		 * that are not being skipped is done at the end of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7071
		 * mt_config_thread().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7072
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7073
		ndi_hold_devi(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7074
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7075
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7076
		 * skip leaf nodes and (for configure) nodes not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7077
		 * fully attached.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7078
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7079
		if (is_leaf_node(dip) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7080
		    (hdl->mtc_op == MT_CONFIG_OP &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7081
		    i_ddi_node_state(dip) < DS_READY)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7082
			ndi_rele_devi(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7083
			dip = ddi_get_next_sibling(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7084
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7085
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7086
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7087
		mcd = kmem_alloc(sizeof (*mcd), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7088
		mcd->mtc_dip = dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7089
		mcd->mtc_hdl = hdl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7090
		mcd->mtc_brn = brn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7091
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7092
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7093
		 * Switch a 'driver' operation to an 'all' operation below a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7094
		 * node bound to the driver.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7095
		 */
662
524269c34bb5 6295108 When installing to second disk, grub defaults to hd0 instead of hd1
szhou
parents: 495
diff changeset
  7096
		if ((major == (major_t)-1) || (major == ddi_driver_major(dip)))
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7097
			mcd->mtc_major = (major_t)-1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7098
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7099
			mcd->mtc_major = major;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7100
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7101
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7102
		 * The unconfig-driver to unconfig-all conversion above
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7103
		 * constitutes an autodetach for NDI_DETACH_DRIVER calls,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7104
		 * set NDI_AUTODETACH.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7105
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7106
		mcd->mtc_flags = hdl->mtc_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7107
		if ((mcd->mtc_flags & NDI_DETACH_DRIVER) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7108
		    (hdl->mtc_op == MT_UNCONFIG_OP) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7109
		    (major == ddi_driver_major(pdip)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7110
			mcd->mtc_flags |= NDI_AUTODETACH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7111
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7112
		mutex_enter(&hdl->mtc_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7113
		hdl->mtc_thr_count++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7114
		mutex_exit(&hdl->mtc_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7115
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7116
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7117
		 * Add to end of list to process after ndi_devi_exit to avoid
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7118
		 * locking differences depending on value of mtc_off.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7119
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7120
		mcd->mtc_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7121
		if (mcd_head == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7122
			mcd_head = mcd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7123
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7124
			mcd_tail->mtc_next = mcd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7125
		mcd_tail = mcd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7126
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7127
		dip = ddi_get_next_sibling(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7128
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7129
	ndi_devi_exit(pdip, circ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7130
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7131
	/* go through the list of held children */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7132
	for (mcd = mcd_head; mcd; mcd = mcd_head) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7133
		mcd_head = mcd->mtc_next;
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  7134
		if (mtc_off || (mcd->mtc_flags & NDI_MTC_OFF))
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7135
			mt_config_thread(mcd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7136
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7137
			(void) thread_create(NULL, 0, mt_config_thread, mcd,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7138
			    0, &p0, TS_RUN, minclsyspri);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7139
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7140
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7141
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7142
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7143
mt_config_driver(struct mt_config_handle *hdl)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7144
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7145
	major_t			par_major = hdl->mtc_parmajor;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7146
	major_t			major = hdl->mtc_major;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7147
	struct devnames		*dnp = &devnamesp[par_major];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7148
	dev_info_t		*dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7149
	struct mt_config_data	*mcd_head = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7150
	struct mt_config_data	*mcd_tail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7151
	struct mt_config_data	*mcd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7152
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7153
	timestruc_t		end_time;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7154
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7155
	/* Update total_time in handle */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7156
	gethrestime(&end_time);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7157
	hdl->total_time += time_diff_in_msec(hdl->start_time, end_time);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7158
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7159
	ASSERT(par_major != (major_t)-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7160
	ASSERT(major != (major_t)-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7161
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7162
	LOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7163
	dip = devnamesp[par_major].dn_head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7164
	while (dip) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7165
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7166
		 * Hold the child that we are processing so he does not get
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7167
		 * removed. The corrisponding ndi_rele_devi() for children
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7168
		 * that are not being skipped is done at the end of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7169
		 * mt_config_thread().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7170
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7171
		ndi_hold_devi(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7172
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7173
		/* skip leaf nodes and nodes not fully attached */
1333
9eb72fd56702 6369724 DS_READY references should be checked for correctness
cth
parents: 1317
diff changeset
  7174
		if (!i_ddi_devi_attached(dip) || is_leaf_node(dip)) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7175
			ndi_rele_devi(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7176
			dip = ddi_get_next(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7177
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7178
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7179
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7180
		mcd = kmem_alloc(sizeof (*mcd), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7181
		mcd->mtc_dip = dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7182
		mcd->mtc_hdl = hdl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7183
		mcd->mtc_major = major;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7184
		mcd->mtc_flags = hdl->mtc_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7185
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7186
		mutex_enter(&hdl->mtc_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7187
		hdl->mtc_thr_count++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7188
		mutex_exit(&hdl->mtc_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7189
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7190
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7191
		 * Add to end of list to process after UNLOCK_DEV_OPS to avoid
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7192
		 * locking differences depending on value of mtc_off.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7193
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7194
		mcd->mtc_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7195
		if (mcd_head == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7196
			mcd_head = mcd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7197
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7198
			mcd_tail->mtc_next = mcd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7199
		mcd_tail = mcd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7200
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7201
		dip = ddi_get_next(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7202
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7203
	UNLOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7204
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7205
	/* go through the list of held children */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7206
	for (mcd = mcd_head; mcd; mcd = mcd_head) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7207
		mcd_head = mcd->mtc_next;
2155
9ba71f09c173 6423041 PSARC 2006/242 'mdi interfaces to support pHCI driver locking' and related fixes
cth
parents: 2009
diff changeset
  7208
		if (mtc_off || (mcd->mtc_flags & NDI_MTC_OFF))
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7209
			mt_config_thread(mcd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7210
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7211
			(void) thread_create(NULL, 0, mt_config_thread, mcd,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7212
			    0, &p0, TS_RUN, minclsyspri);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7213
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7214
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7215
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7216
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7217
 * Given the nodeid for a persistent (PROM or SID) node, return
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7218
 * the corresponding devinfo node
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7219
 * NOTE: This function will return NULL for .conf nodeids.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7220
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7221
dev_info_t *
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents: 693
diff changeset
  7222
e_ddi_nodeid_to_dip(pnode_t nodeid)
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7223
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7224
	dev_info_t		*dip = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7225
	struct devi_nodeid	*prev, *elem;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7226
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7227
	mutex_enter(&devimap->dno_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7228
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7229
	prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7230
	for (elem = devimap->dno_head; elem; elem = elem->next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7231
		if (elem->nodeid == nodeid) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7232
			ndi_hold_devi(elem->dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7233
			dip = elem->dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7234
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7235
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7236
		prev = elem;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7237
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7238
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7239
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7240
	 * Move to head for faster lookup next time
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7241
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7242
	if (elem && prev) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7243
		prev->next = elem->next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7244
		elem->next = devimap->dno_head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7245
		devimap->dno_head = elem;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7246
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7247
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7248
	mutex_exit(&devimap->dno_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7249
	return (dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7250
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7251
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7252
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7253
free_cache_task(void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7254
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7255
	ASSERT(arg == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7256
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7257
	mutex_enter(&di_cache.cache_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7258
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7259
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7260
	 * The cache can be invalidated without holding the lock
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7261
	 * but it can be made valid again only while the lock is held.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7262
	 * So if the cache is invalid when the lock is held, it will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7263
	 * stay invalid until lock is released.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7264
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7265
	if (!di_cache.cache_valid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7266
		i_ddi_di_cache_free(&di_cache);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7267
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7268
	mutex_exit(&di_cache.cache_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7269
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7270
	if (di_cache_debug)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7271
		cmn_err(CE_NOTE, "system_taskq: di_cache freed");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7272
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7273
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7274
extern int modrootloaded;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7275
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7276
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7277
i_ddi_di_cache_free(struct di_cache *cache)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7278
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7279
	int	error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7280
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7281
	ASSERT(mutex_owned(&cache->cache_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7282
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7283
	if (cache->cache_size) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7284
		ASSERT(cache->cache_size > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7285
		ASSERT(cache->cache_data);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7286
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7287
		kmem_free(cache->cache_data, cache->cache_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7288
		cache->cache_data = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7289
		cache->cache_size = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7290
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7291
		if (di_cache_debug)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7292
			cmn_err(CE_NOTE, "i_ddi_di_cache_free: freed cachemem");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7293
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7294
		ASSERT(cache->cache_data == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7295
		if (di_cache_debug)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7296
			cmn_err(CE_NOTE, "i_ddi_di_cache_free: NULL cache");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7297
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7298
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7299
	if (!modrootloaded || rootvp == NULL || vn_is_readonly(rootvp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7300
		if (di_cache_debug) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7301
			cmn_err(CE_WARN, "/ not mounted/RDONLY. Skip unlink");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7302
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7303
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7304
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7305
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7306
	error = vn_remove(DI_CACHE_FILE, UIO_SYSSPACE, RMFILE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7307
	if (di_cache_debug && error && error != ENOENT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7308
		cmn_err(CE_WARN, "%s: unlink failed: %d", DI_CACHE_FILE, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7309
	} else if (di_cache_debug && !error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7310
		cmn_err(CE_NOTE, "i_ddi_di_cache_free: unlinked cache file");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7311
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7312
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7313
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7314
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7315
i_ddi_di_cache_invalidate(int kmflag)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7316
{
6065
b05c5c670963 6453345 devfs_getattr violates devfs locking rules
cth
parents: 5895
diff changeset
  7317
	int	cache_valid;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7318
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7319
	if (!modrootloaded || !i_ddi_io_initialized()) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7320
		if (di_cache_debug)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7321
			cmn_err(CE_NOTE, "I/O not inited. Skipping invalidate");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7322
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7323
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7324
6065
b05c5c670963 6453345 devfs_getattr violates devfs locking rules
cth
parents: 5895
diff changeset
  7325
	/* Increment devtree generation number. */
2621
4ea88858d952 PSARC/2003/246 Filesystem Driven Device Naming
llai1
parents: 2155
diff changeset
  7326
	atomic_inc_ulong(&devtree_gen);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7327
6065
b05c5c670963 6453345 devfs_getattr violates devfs locking rules
cth
parents: 5895
diff changeset
  7328
	/* Invalidate the in-core cache and dispatch free on valid->invalid */
b05c5c670963 6453345 devfs_getattr violates devfs locking rules
cth
parents: 5895
diff changeset
  7329
	cache_valid = atomic_swap_uint(&di_cache.cache_valid, 0);
b05c5c670963 6453345 devfs_getattr violates devfs locking rules
cth
parents: 5895
diff changeset
  7330
	if (cache_valid) {
b05c5c670963 6453345 devfs_getattr violates devfs locking rules
cth
parents: 5895
diff changeset
  7331
		(void) taskq_dispatch(system_taskq, free_cache_task, NULL,
b05c5c670963 6453345 devfs_getattr violates devfs locking rules
cth
parents: 5895
diff changeset
  7332
		    (kmflag == KM_SLEEP) ? TQ_SLEEP : TQ_NOSLEEP);
b05c5c670963 6453345 devfs_getattr violates devfs locking rules
cth
parents: 5895
diff changeset
  7333
	}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7334
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7335
	if (di_cache_debug) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7336
		cmn_err(CE_NOTE, "invalidation with km_flag: %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7337
		    kmflag == KM_SLEEP ? "KM_SLEEP" : "KM_NOSLEEP");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7338
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7339
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7340
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7341
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7342
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7343
i_bind_vhci_node(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7344
{
4145
90dc07a3821d PSARC 2007/176 path-oriented driver alias
cth
parents: 2621
diff changeset
  7345
	DEVI(dip)->devi_major = ddi_name_to_major(ddi_node_name(dip));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7346
	i_ddi_set_node_state(dip, DS_BOUND);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7347
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7348
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7349
static char vhci_node_addr[2];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7350
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7351
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7352
i_init_vhci_node(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7353
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7354
	add_global_props(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7355
	DEVI(dip)->devi_ops = ndi_hold_driver(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7356
	if (DEVI(dip)->devi_ops == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7357
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7358
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7359
	DEVI(dip)->devi_instance = e_ddi_assign_instance(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7360
	e_ddi_keep_instance(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7361
	vhci_node_addr[0]	= '\0';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7362
	ddi_set_name_addr(dip, vhci_node_addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7363
	i_ddi_set_node_state(dip, DS_INITIALIZED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7364
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7365
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7366
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7367
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7368
i_link_vhci_node(dev_info_t *dip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7369
{
1093
4dc7aec69dc9 6299476 DM Does not interoperate with TS90 switch, cannot discover SRP targets
hiremath
parents: 789
diff changeset
  7370
	ASSERT(MUTEX_HELD(&global_vhci_lock));
4dc7aec69dc9 6299476 DM Does not interoperate with TS90 switch, cannot discover SRP targets
hiremath
parents: 789
diff changeset
  7371
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7372
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7373
	 * scsi_vhci should be kept left most of the device tree.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7374
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7375
	if (scsi_vhci_dip) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7376
		DEVI(dip)->devi_sibling = DEVI(scsi_vhci_dip)->devi_sibling;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7377
		DEVI(scsi_vhci_dip)->devi_sibling = DEVI(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7378
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7379
		DEVI(dip)->devi_sibling = DEVI(top_devinfo)->devi_child;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7380
		DEVI(top_devinfo)->devi_child = DEVI(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7381
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7382
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7383
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7384
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7385
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7386
 * This a special routine to enumerate vhci node (child of rootnex
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7387
 * node) without holding the ndi_devi_enter() lock. The device node
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7388
 * is allocated, initialized and brought into DS_READY state before
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7389
 * inserting into the device tree. The VHCI node is handcrafted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7390
 * here to bring the node to DS_READY, similar to rootnex node.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7391
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7392
 * The global_vhci_lock protects linking the node into the device
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7393
 * as same lock is held before linking/unlinking any direct child
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7394
 * of rootnex children.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7395
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7396
 * This routine is a workaround to handle a possible deadlock
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7397
 * that occurs while trying to enumerate node in a different sub-tree
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7398
 * during _init/_attach entry points.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7399
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7400
/*ARGSUSED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7401
dev_info_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7402
ndi_devi_config_vhci(char *drvname, int flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7403
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7404
	struct devnames		*dnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7405
	dev_info_t		*dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7406
	major_t			major = ddi_name_to_major(drvname);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7407
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7408
	if (major == -1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7409
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7410
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7411
	/* Make sure we create the VHCI node only once */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7412
	dnp = &devnamesp[major];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7413
	LOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7414
	if (dnp->dn_head) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7415
		dip = dnp->dn_head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7416
		UNLOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7417
		return (dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7418
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7419
	UNLOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7420
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7421
	/* Allocate the VHCI node */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7422
	ndi_devi_alloc_sleep(top_devinfo, drvname, DEVI_SID_NODEID, &dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7423
	ndi_hold_devi(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7424
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7425
	/* Mark the node as VHCI */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7426
	DEVI(dip)->devi_node_attributes |= DDI_VHCI_NODE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7427
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7428
	i_ddi_add_devimap(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7429
	i_bind_vhci_node(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7430
	if (i_init_vhci_node(dip) == -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7431
		ndi_rele_devi(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7432
		(void) ndi_devi_free(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7433
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7434
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7435
495
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  7436
	mutex_enter(&(DEVI(dip)->devi_lock));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7437
	DEVI_SET_ATTACHING(dip);
495
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  7438
	mutex_exit(&(DEVI(dip)->devi_lock));
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  7439
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7440
	if (devi_attach(dip, DDI_ATTACH) != DDI_SUCCESS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7441
		cmn_err(CE_CONT, "Could not attach %s driver", drvname);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7442
		e_ddi_free_instance(dip, vhci_node_addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7443
		ndi_rele_devi(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7444
		(void) ndi_devi_free(dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7445
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7446
	}
495
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  7447
	mutex_enter(&(DEVI(dip)->devi_lock));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7448
	DEVI_CLR_ATTACHING(dip);
495
310ccf2a1604 6213273 Hang in i_devi_enter from fcip detach ddi_remove_minor_node call
cth
parents: 439
diff changeset
  7449
	mutex_exit(&(DEVI(dip)->devi_lock));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7450
1093
4dc7aec69dc9 6299476 DM Does not interoperate with TS90 switch, cannot discover SRP targets
hiremath
parents: 789
diff changeset
  7451
	mutex_enter(&global_vhci_lock);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7452
	i_link_vhci_node(dip);
1093
4dc7aec69dc9 6299476 DM Does not interoperate with TS90 switch, cannot discover SRP targets
hiremath
parents: 789
diff changeset
  7453
	mutex_exit(&global_vhci_lock);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7454
	i_ddi_set_node_state(dip, DS_READY);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7455
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7456
	LOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7457
	dnp->dn_flags |= DN_DRIVER_HELD;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7458
	dnp->dn_head = dip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7459
	UNLOCK_DEV_OPS(&dnp->dn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7460
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7461
	i_ndi_devi_report_status_change(dip, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7462
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7463
	return (dip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7464
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7465
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7466
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7467
 * ibt_hw_is_present() returns 0 when there is no IB hardware actively
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7468
 * running.  This is primarily useful for modules like rpcmod which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7469
 * needs a quick check to decide whether or not it should try to use
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7470
 * InfiniBand
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7471
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7472
int ib_hw_status = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7473
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7474
ibt_hw_is_present()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7475
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7476
	return (ib_hw_status);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7477
}
4845
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7478
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7479
/*
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7480
 * ASSERT that constraint flag is not set and then set the "retire attempt"
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7481
 * flag.
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7482
 */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7483
int
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7484
e_ddi_mark_retiring(dev_info_t *dip, void *arg)
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7485
{
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7486
	char	**cons_array = (char **)arg;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7487
	char	*path;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7488
	int	constraint;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7489
	int	i;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7490
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7491
	constraint = 0;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7492
	if (cons_array) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7493
		path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7494
		(void) ddi_pathname(dip, path);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7495
		for (i = 0; cons_array[i] != NULL; i++) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7496
			if (strcmp(path, cons_array[i]) == 0) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7497
				constraint = 1;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7498
				break;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7499
			}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7500
		}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7501
		kmem_free(path, MAXPATHLEN);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7502
	}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7503
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7504
	mutex_enter(&DEVI(dip)->devi_lock);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7505
	ASSERT(!(DEVI(dip)->devi_flags & DEVI_R_CONSTRAINT));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7506
	DEVI(dip)->devi_flags |= DEVI_RETIRING;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7507
	if (constraint)
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7508
		DEVI(dip)->devi_flags |= DEVI_R_CONSTRAINT;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7509
	mutex_exit(&DEVI(dip)->devi_lock);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7510
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7511
	RIO_VERBOSE((CE_NOTE, "marked dip as undergoing retire process dip=%p",
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7512
	    (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7513
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7514
	if (constraint)
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7515
		RIO_DEBUG((CE_NOTE, "marked dip as constrained, dip=%p",
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7516
		    (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7517
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7518
	if (MDI_PHCI(dip))
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7519
		mdi_phci_mark_retiring(dip, cons_array);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7520
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7521
	return (DDI_WALK_CONTINUE);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7522
}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7523
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7524
static void
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7525
free_array(char **cons_array)
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7526
{
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7527
	int	i;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7528
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7529
	if (cons_array == NULL)
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7530
		return;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7531
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7532
	for (i = 0; cons_array[i] != NULL; i++) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7533
		kmem_free(cons_array[i], strlen(cons_array[i]) + 1);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7534
	}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7535
	kmem_free(cons_array, (i+1) * sizeof (char *));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7536
}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7537
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7538
/*
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7539
 * Walk *every* node in subtree and check if it blocks, allows or has no
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7540
 * comment on a proposed retire.
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7541
 */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7542
int
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7543
e_ddi_retire_notify(dev_info_t *dip, void *arg)
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7544
{
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7545
	int	*constraint = (int *)arg;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7546
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7547
	RIO_DEBUG((CE_NOTE, "retire notify: dip = %p", (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7548
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7549
	(void) e_ddi_offline_notify(dip);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7550
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7551
	mutex_enter(&(DEVI(dip)->devi_lock));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7552
	if (!(DEVI(dip)->devi_flags & DEVI_RETIRING)) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7553
		RIO_DEBUG((CE_WARN, "retire notify: dip in retire "
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7554
		    "subtree is not marked: dip = %p", (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7555
		*constraint = 0;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7556
	} else if (DEVI(dip)->devi_flags & DEVI_R_BLOCKED) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7557
		ASSERT(!(DEVI(dip)->devi_flags & DEVI_R_CONSTRAINT));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7558
		RIO_DEBUG((CE_NOTE, "retire notify: BLOCKED: dip = %p",
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7559
		    (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7560
		*constraint = 0;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7561
	} else if (!(DEVI(dip)->devi_flags & DEVI_R_CONSTRAINT)) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7562
		RIO_DEBUG((CE_NOTE, "retire notify: NO CONSTRAINT: "
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7563
		    "dip = %p", (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7564
		*constraint = 0;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7565
	} else {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7566
		RIO_DEBUG((CE_NOTE, "retire notify: CONSTRAINT set: "
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7567
		    "dip = %p", (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7568
	}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7569
	mutex_exit(&DEVI(dip)->devi_lock);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7570
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7571
	if (MDI_PHCI(dip))
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7572
		mdi_phci_retire_notify(dip, constraint);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7573
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7574
	return (DDI_WALK_CONTINUE);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7575
}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7576
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7577
int
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7578
e_ddi_retire_finalize(dev_info_t *dip, void *arg)
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7579
{
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7580
	int constraint = *(int *)arg;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7581
	int finalize;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7582
	int phci_only;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7583
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7584
	ASSERT(DEVI_BUSY_OWNED(ddi_get_parent(dip)));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7585
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7586
	mutex_enter(&DEVI(dip)->devi_lock);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7587
	if (!(DEVI(dip)->devi_flags & DEVI_RETIRING)) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7588
		RIO_DEBUG((CE_WARN,
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7589
		    "retire: unmarked dip(%p) in retire subtree",
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7590
		    (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7591
		ASSERT(!(DEVI(dip)->devi_flags & DEVI_RETIRED));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7592
		ASSERT(!(DEVI(dip)->devi_flags & DEVI_R_CONSTRAINT));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7593
		ASSERT(!(DEVI(dip)->devi_flags & DEVI_R_BLOCKED));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7594
		mutex_exit(&DEVI(dip)->devi_lock);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7595
		return (DDI_WALK_CONTINUE);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7596
	}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7597
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7598
	/*
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7599
	 * retire the device if constraints have been applied
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7600
	 * or if the device is not in use
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7601
	 */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7602
	finalize = 0;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7603
	if (constraint) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7604
		ASSERT(DEVI(dip)->devi_flags & DEVI_R_CONSTRAINT);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7605
		ASSERT(!(DEVI(dip)->devi_flags & DEVI_R_BLOCKED));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7606
		DEVI(dip)->devi_flags &= ~DEVI_R_CONSTRAINT;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7607
		DEVI(dip)->devi_flags &= ~DEVI_RETIRING;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7608
		DEVI(dip)->devi_flags |= DEVI_RETIRED;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7609
		mutex_exit(&DEVI(dip)->devi_lock);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7610
		(void) spec_fence_snode(dip, NULL);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7611
		RIO_DEBUG((CE_NOTE, "Fenced off: dip = %p", (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7612
		e_ddi_offline_finalize(dip, DDI_SUCCESS);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7613
	} else {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7614
		if (DEVI(dip)->devi_flags & DEVI_R_BLOCKED) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7615
			ASSERT(!(DEVI(dip)->devi_flags & DEVI_R_CONSTRAINT));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7616
			DEVI(dip)->devi_flags &= ~DEVI_R_BLOCKED;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7617
			DEVI(dip)->devi_flags &= ~DEVI_RETIRING;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7618
			/* we have already finalized during notify */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7619
		} else if (DEVI(dip)->devi_flags & DEVI_R_CONSTRAINT) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7620
			DEVI(dip)->devi_flags &= ~DEVI_R_CONSTRAINT;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7621
			DEVI(dip)->devi_flags &= ~DEVI_RETIRING;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7622
			finalize = 1;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7623
		} else {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7624
			DEVI(dip)->devi_flags &= ~DEVI_RETIRING;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7625
			/*
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7626
			 * even if no contracts, need to call finalize
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7627
			 * to clear the contract barrier on the dip
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7628
			 */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7629
			finalize = 1;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7630
		}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7631
		mutex_exit(&DEVI(dip)->devi_lock);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7632
		RIO_DEBUG((CE_NOTE, "finalize: NOT retired: dip = %p",
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7633
		    (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7634
		if (finalize)
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7635
			e_ddi_offline_finalize(dip, DDI_FAILURE);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7636
		mutex_enter(&DEVI(dip)->devi_lock);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7637
		DEVI_SET_DEVICE_DEGRADED(dip);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7638
		mutex_exit(&DEVI(dip)->devi_lock);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7639
	}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7640
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7641
	/*
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7642
	 * phci_only variable indicates no client checking, just
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7643
	 * offline the PHCI. We set that to 0 to enable client
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7644
	 * checking
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7645
	 */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7646
	phci_only = 0;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7647
	if (MDI_PHCI(dip))
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7648
		mdi_phci_retire_finalize(dip, phci_only);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7649
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7650
	return (DDI_WALK_CONTINUE);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7651
}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7652
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7653
/*
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7654
 * Returns
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7655
 * 	DDI_SUCCESS if constraints allow retire
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7656
 *	DDI_FAILURE if constraints don't allow retire.
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7657
 * cons_array is a NULL terminated array of node paths for
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7658
 * which constraints have already been applied.
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7659
 */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7660
int
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7661
e_ddi_retire_device(char *path, char **cons_array)
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7662
{
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7663
	dev_info_t	*dip;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7664
	dev_info_t	*pdip;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7665
	int		circ;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7666
	int		circ2;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7667
	int		constraint;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7668
	char		*devnm;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7669
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7670
	/*
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7671
	 * First, lookup the device
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7672
	 */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7673
	dip = e_ddi_hold_devi_by_path(path, 0);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7674
	if (dip == NULL) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7675
		/*
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7676
		 * device does not exist. This device cannot be
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7677
		 * a critical device since it is not in use. Thus
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7678
		 * this device is always retireable. Return DDI_SUCCESS
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7679
		 * to indicate this. If this device is ever
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7680
		 * instantiated, I/O framework will consult the
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7681
		 * the persistent retire store, mark it as
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7682
		 * retired and fence it off.
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7683
		 */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7684
		RIO_DEBUG((CE_NOTE, "Retire device: device doesn't exist."
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7685
		    " NOP. Just returning SUCCESS. path=%s", path));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7686
		free_array(cons_array);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7687
		return (DDI_SUCCESS);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7688
	}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7689
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7690
	RIO_DEBUG((CE_NOTE, "Retire device: found dip = %p.", (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7691
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7692
	pdip = ddi_get_parent(dip);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7693
	ndi_hold_devi(pdip);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7694
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7695
	/*
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7696
	 * Run devfs_clean() in case dip has no constraints and is
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7697
	 * not in use, so is retireable but there are dv_nodes holding
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7698
	 * ref-count on the dip. Note that devfs_clean() always returns
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7699
	 * success.
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7700
	 */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7701
	devnm = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7702
	(void) ddi_deviname(dip, devnm);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7703
	(void) devfs_clean(pdip, devnm + 1, DV_CLEAN_FORCE);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7704
	kmem_free(devnm, MAXNAMELEN + 1);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7705
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7706
	ndi_devi_enter(pdip, &circ);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7707
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7708
	/* release hold from e_ddi_hold_devi_by_path */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7709
	ndi_rele_devi(dip);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7710
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7711
	/*
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7712
	 * If it cannot make a determination, is_leaf_node() assumes
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7713
	 * dip is a nexus.
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7714
	 */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7715
	(void) e_ddi_mark_retiring(dip, cons_array);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7716
	if (!is_leaf_node(dip)) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7717
		ndi_devi_enter(dip, &circ2);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7718
		ddi_walk_devs(ddi_get_child(dip), e_ddi_mark_retiring,
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7719
		    cons_array);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7720
		ndi_devi_exit(dip, circ2);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7721
	}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7722
	free_array(cons_array);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7723
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7724
	/*
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7725
	 * apply constraints
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7726
	 */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7727
	RIO_DEBUG((CE_NOTE, "retire: subtree retire notify: path = %s", path));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7728
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7729
	constraint = 1;	/* assume constraints allow retire */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7730
	(void) e_ddi_retire_notify(dip, &constraint);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7731
	if (!is_leaf_node(dip)) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7732
		ndi_devi_enter(dip, &circ2);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7733
		ddi_walk_devs(ddi_get_child(dip), e_ddi_retire_notify,
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7734
		    &constraint);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7735
		ndi_devi_exit(dip, circ2);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7736
	}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7737
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7738
	/*
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7739
	 * Now finalize the retire
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7740
	 */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7741
	(void) e_ddi_retire_finalize(dip, &constraint);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7742
	if (!is_leaf_node(dip)) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7743
		ndi_devi_enter(dip, &circ2);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7744
		ddi_walk_devs(ddi_get_child(dip), e_ddi_retire_finalize,
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7745
		    &constraint);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7746
		ndi_devi_exit(dip, circ2);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7747
	}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7748
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7749
	if (!constraint) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7750
		RIO_DEBUG((CE_WARN, "retire failed: path = %s", path));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7751
	} else {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7752
		RIO_DEBUG((CE_NOTE, "retire succeeded: path = %s", path));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7753
	}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7754
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7755
	ndi_devi_exit(pdip, circ);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7756
	ndi_rele_devi(pdip);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7757
	return (constraint ? DDI_SUCCESS : DDI_FAILURE);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7758
}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7759
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7760
static int
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7761
unmark_and_unfence(dev_info_t *dip, void *arg)
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7762
{
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7763
	char	*path = (char *)arg;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7764
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7765
	ASSERT(path);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7766
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7767
	(void) ddi_pathname(dip, path);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7768
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7769
	mutex_enter(&DEVI(dip)->devi_lock);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7770
	DEVI(dip)->devi_flags &= ~DEVI_RETIRED;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7771
	DEVI_SET_DEVICE_ONLINE(dip);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7772
	mutex_exit(&DEVI(dip)->devi_lock);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7773
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7774
	RIO_VERBOSE((CE_NOTE, "Cleared RETIRED flag: dip=%p, path=%s",
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7775
	    (void *)dip, path));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7776
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7777
	(void) spec_unfence_snode(dip);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7778
	RIO_DEBUG((CE_NOTE, "Unfenced device: %s", path));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7779
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7780
	if (MDI_PHCI(dip))
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7781
		mdi_phci_unretire(dip);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7782
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7783
	return (DDI_WALK_CONTINUE);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7784
}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7785
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7786
struct find_dip {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7787
	char	*fd_buf;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7788
	char	*fd_path;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7789
	dev_info_t *fd_dip;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7790
};
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7791
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7792
static int
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7793
find_dip_fcn(dev_info_t *dip, void *arg)
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7794
{
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7795
	struct find_dip *findp = (struct find_dip *)arg;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7796
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7797
	(void) ddi_pathname(dip, findp->fd_buf);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7798
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7799
	if (strcmp(findp->fd_path, findp->fd_buf) != 0)
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7800
		return (DDI_WALK_CONTINUE);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7801
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7802
	ndi_hold_devi(dip);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7803
	findp->fd_dip = dip;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7804
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7805
	return (DDI_WALK_TERMINATE);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7806
}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7807
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7808
int
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7809
e_ddi_unretire_device(char *path)
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7810
{
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7811
	int		circ;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7812
	char		*path2;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7813
	dev_info_t	*pdip;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7814
	dev_info_t	*dip;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7815
	struct find_dip	 find_dip;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7816
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7817
	ASSERT(path);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7818
	ASSERT(*path == '/');
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7819
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7820
	if (strcmp(path, "/") == 0) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7821
		cmn_err(CE_WARN, "Root node cannot be retired. Skipping "
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7822
		    "device unretire: %s", path);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7823
		return (0);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7824
	}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7825
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7826
	/*
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7827
	 * We can't lookup the dip (corresponding to path) via
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7828
	 * e_ddi_hold_devi_by_path() because the dip may be offline
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7829
	 * and may not attach. Use ddi_walk_devs() instead;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7830
	 */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7831
	find_dip.fd_buf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7832
	find_dip.fd_path = path;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7833
	find_dip.fd_dip = NULL;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7834
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7835
	pdip = ddi_root_node();
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7836
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7837
	ndi_devi_enter(pdip, &circ);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7838
	ddi_walk_devs(ddi_get_child(pdip), find_dip_fcn, &find_dip);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7839
	ndi_devi_exit(pdip, circ);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7840
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7841
	kmem_free(find_dip.fd_buf, MAXPATHLEN);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7842
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7843
	if (find_dip.fd_dip == NULL) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7844
		cmn_err(CE_WARN, "Device not found in device tree. Skipping "
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7845
		    "device unretire: %s", path);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7846
		return (0);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7847
	}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7848
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7849
	dip = find_dip.fd_dip;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7850
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7851
	pdip = ddi_get_parent(dip);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7852
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7853
	ndi_hold_devi(pdip);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7854
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7855
	ndi_devi_enter(pdip, &circ);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7856
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7857
	path2 = kmem_alloc(MAXPATHLEN, KM_SLEEP);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7858
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7859
	(void) unmark_and_unfence(dip, path2);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7860
	if (!is_leaf_node(dip)) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7861
		ndi_devi_enter(dip, &circ);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7862
		ddi_walk_devs(ddi_get_child(dip), unmark_and_unfence, path2);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7863
		ndi_devi_exit(dip, circ);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7864
	}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7865
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7866
	kmem_free(path2, MAXPATHLEN);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7867
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7868
	/* release hold from find_dip_fcn() */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7869
	ndi_rele_devi(dip);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7870
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7871
	ndi_devi_exit(pdip, circ);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7872
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7873
	ndi_rele_devi(pdip);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7874
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7875
	return (0);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7876
}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7877
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7878
/*
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7879
 * Called before attach on a dip that has been retired.
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7880
 */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7881
static int
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7882
mark_and_fence(dev_info_t *dip, void *arg)
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7883
{
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7884
	char    *fencepath = (char *)arg;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7885
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7886
	/*
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7887
	 * We have already decided to retire this device. The various
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7888
	 * constraint checking should not be set.
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7889
	 * NOTE that the retire flag may already be set due to
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7890
	 * fenced -> detach -> fenced transitions.
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7891
	 */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7892
	mutex_enter(&DEVI(dip)->devi_lock);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7893
	ASSERT(!(DEVI(dip)->devi_flags & DEVI_R_CONSTRAINT));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7894
	ASSERT(!(DEVI(dip)->devi_flags & DEVI_R_BLOCKED));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7895
	ASSERT(!(DEVI(dip)->devi_flags & DEVI_RETIRING));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7896
	DEVI(dip)->devi_flags |= DEVI_RETIRED;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7897
	mutex_exit(&DEVI(dip)->devi_lock);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7898
	RIO_VERBOSE((CE_NOTE, "marked as RETIRED dip=%p", (void *)dip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7899
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7900
	if (fencepath) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7901
		(void) spec_fence_snode(dip, NULL);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7902
		RIO_DEBUG((CE_NOTE, "Fenced: %s",
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7903
		    ddi_pathname(dip, fencepath)));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7904
	}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7905
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7906
	return (DDI_WALK_CONTINUE);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7907
}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7908
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7909
/*
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7910
 * Checks the retire database and:
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7911
 *
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7912
 * - if device is present in the retire database, marks the device retired
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7913
 *   and fences it off.
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7914
 * - if device is not in retire database, allows the device to attach normally
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7915
 *
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7916
 * To be called only by framework attach code on first attach attempt.
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7917
 *
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7918
 */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7919
static void
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7920
i_ddi_check_retire(dev_info_t *dip)
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7921
{
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7922
	char		*path;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7923
	dev_info_t	*pdip;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7924
	int		circ;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7925
	int		phci_only;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7926
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7927
	pdip = ddi_get_parent(dip);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7928
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7929
	/*
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7930
	 * Root dip is treated special and doesn't take this code path.
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7931
	 * Also root can never be retired.
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7932
	 */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7933
	ASSERT(pdip);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7934
	ASSERT(DEVI_BUSY_OWNED(pdip));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7935
	ASSERT(i_ddi_node_state(dip) < DS_ATTACHED);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7936
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7937
	path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7938
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7939
	(void) ddi_pathname(dip, path);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7940
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7941
	RIO_VERBOSE((CE_NOTE, "Checking if dip should attach: dip=%p, path=%s",
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7942
	    (void *)dip, path));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7943
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7944
	/*
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7945
	 * Check if this device is in the "retired" store i.e.  should
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7946
	 * be retired. If not, we have nothing to do.
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7947
	 */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7948
	if (e_ddi_device_retired(path) == 0) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7949
		RIO_VERBOSE((CE_NOTE, "device is NOT retired: path=%s", path));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7950
		kmem_free(path, MAXPATHLEN);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7951
		return;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7952
	}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7953
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7954
	RIO_DEBUG((CE_NOTE, "attach: device is retired: path=%s", path));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7955
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7956
	/*
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7957
	 * Mark dips and fence off snodes (if any)
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7958
	 */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7959
	RIO_DEBUG((CE_NOTE, "attach: Mark and fence subtree: path=%s", path));
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7960
	(void) mark_and_fence(dip, path);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7961
	if (!is_leaf_node(dip)) {
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7962
		ndi_devi_enter(dip, &circ);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7963
		ddi_walk_devs(ddi_get_child(dip), mark_and_fence, path);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7964
		ndi_devi_exit(dip, circ);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7965
	}
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7966
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7967
	kmem_free(path, MAXPATHLEN);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7968
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7969
	/*
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7970
	 * We don't want to check the client. We just want to
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7971
	 * offline the PHCI
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7972
	 */
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7973
	phci_only = 1;
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7974
	if (MDI_PHCI(dip))
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7975
		mdi_phci_retire_finalize(dip, phci_only);
357e8e7542af PSARC 2007/290 Retire Agent for I/O Devices
vikram
parents: 4540
diff changeset
  7976
}