Print this page
NEX-18492 Disk can't be restored in pool if disappeared under active I/O
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-18264 devi_detach_node() should be aware that device class can be NULL
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
NEX-18214 unplug of multipathed disks doesn't produce EC_DEV_REMOVE/ESC_DISK event (fix build)
NEX-18214 unplug of multipathed disks doesn't produce EC_DEV_REMOVE/ESC_DISK event
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Revert "NEX-18214 unplug of multipathed disks doesn't produce EC_DEV_REMOVE/ESC_DISK event"
This reverts commit b0f7e47b60b115c1bb6c07dc5aa150cc519790e7.
NEX-18214 unplug of multipathed disks doesn't produce EC_DEV_REMOVE/ESC_DISK event
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Dan Fields <dan.fields@nexenta.com>
NEX-17446 cleanup of hot unplugged disks fails intermittently
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
NEX-15925 pseudonex, rootnex, and friends don't need to log useless device announcements
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-15146 Retired device is not listed after appliance reboot
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Dmitry Savitsky <dmitry.savitsky@nexenta.com>
OS-164 Add ddi property to allow device
retire to succeed when device is in use
   1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */

  21 /*
  22  * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
  24  * Copyright 2012 Garrett D'Amore <garrett@damore.org>.  All rights reserved.
  25  * Copyright (c) 2013, Joyent, Inc. All rights reserved.

  26  * Copyright (c) 2016 by Delphix. All rights reserved.
  27  */
  28 
  29 #include <sys/note.h>
  30 #include <sys/t_lock.h>
  31 #include <sys/cmn_err.h>
  32 #include <sys/instance.h>
  33 #include <sys/conf.h>
  34 #include <sys/stat.h>
  35 #include <sys/ddi.h>
  36 #include <sys/hwconf.h>
  37 #include <sys/sunddi.h>
  38 #include <sys/sunndi.h>
  39 #include <sys/ddi_impldefs.h>
  40 #include <sys/ndi_impldefs.h>
  41 #include <sys/modctl.h>
  42 #include <sys/contract/device_impl.h>
  43 #include <sys/dacf.h>
  44 #include <sys/promif.h>
  45 #include <sys/pci.h>


 154  * (MUTEX_DEFAULT) - it is automatically initialized by being allocated
 155  * in zeroed memory (static storage class). Therefore no explicit
 156  * initialization of the di_cache structure is needed.
 157  */
 158 struct di_cache di_cache = {1};
 159 int             di_cache_debug = 0;
 160 
 161 /* For ddvis, which needs pseudo children under PCI */
 162 int pci_allow_pseudo_children = 0;
 163 
 164 /* Allow path-oriented alias driver binding on driver.conf enumerated nodes */
 165 int driver_conf_allow_path_alias = 1;
 166 
 167 /*
 168  * The following switch is for service people, in case a
 169  * 3rd party driver depends on identify(9e) being called.
 170  */
 171 int identify_9e = 0;
 172 
 173 /*
 174  * Add flag so behaviour of preventing attach for retired persistant nodes
 175  * can be disabled.
 176  */
 177 int retire_prevents_attach = 1;
 178 
 179 int mtc_off;                                    /* turn off mt config */
 180 
 181 int quiesce_debug = 0;
 182 
 183 boolean_t ddi_aliases_present = B_FALSE;
 184 ddi_alias_t ddi_aliases;
 185 uint_t tsd_ddi_redirect;
 186 
 187 #define DDI_ALIAS_HASH_SIZE     (2700)
 188 
 189 static kmem_cache_t *ddi_node_cache;            /* devinfo node cache */
 190 static devinfo_log_header_t *devinfo_audit_log; /* devinfo log */
 191 static int devinfo_log_size;                    /* size in pages */
 192 
 193 boolean_t ddi_err_panic = B_FALSE;
 194 
 195 static int lookup_compatible(dev_info_t *, uint_t);
 196 static char *encode_composite_string(char **, uint_t, size_t *, uint_t);
 197 static void link_to_driver_list(dev_info_t *);


 468                 kmem_free(devi->devi_device_class,
 469                     strlen(devi->devi_device_class) + 1);
 470         cv_destroy(&(devi->devi_cv));
 471         mutex_destroy(&(devi->devi_lock));
 472         mutex_destroy(&(devi->devi_pm_lock));
 473         mutex_destroy(&(devi->devi_pm_busy_lock));
 474 
 475         RIO_TRACE((CE_NOTE, "i_ddi_free_node: destroying contract fields: "
 476             "dip=%p", (void *)dip));
 477         contract_device_remove_dip(dip);
 478         ASSERT(devi->devi_ct_count == -1);
 479         ASSERT(list_is_empty(&(devi->devi_ct)));
 480         cv_destroy(&(devi->devi_ct_cv));
 481         list_destroy(&(devi->devi_ct));
 482         /* free this last since contract_device_remove_dip() uses it */
 483         mutex_destroy(&(devi->devi_ct_lock));
 484         RIO_TRACE((CE_NOTE, "i_ddi_free_node: destroyed all contract fields: "
 485             "dip=%p, name=%s", (void *)dip, devi->devi_node_name));
 486 
 487         kmem_free(devi->devi_node_name, strlen(devi->devi_node_name) + 1);
 488 
 489         /* free event data */
 490         if (devi->devi_ev_path)
 491                 kmem_free(devi->devi_ev_path, MAXPATHLEN);
 492 
 493         kmem_cache_free(ddi_node_cache, devi);
 494 }
 495 
 496 
 497 /*
 498  * Node state transitions
 499  */
 500 
 501 /*
 502  * Change the node name
 503  */
 504 int
 505 ndi_devi_set_nodename(dev_info_t *dip, char *name, int flags)
 506 {
 507         _NOTE(ARGUNUSED(flags))
 508         char *nname, *oname;
 509 
 510         ASSERT(dip && name);
 511 
 512         oname = DEVI(dip)->devi_node_name;


1343                 mutex_exit(&DEVI(dip)->devi_lock);
1344 
1345         /* successful attach, return with driver held */
1346 
1347         return (DDI_SUCCESS);
1348 }
1349 
1350 /*
1351  * Detach devinfo node.
1352  * Per-driver list must be held busy.
1353  */
1354 static int
1355 detach_node(dev_info_t *dip, uint_t flag)
1356 {
1357         struct devnames *dnp;
1358         int             rv;
1359 
1360         ASSERT(DEVI_BUSY_OWNED(ddi_get_parent(dip)));
1361         ASSERT(i_ddi_node_state(dip) == DS_ATTACHED);
1362 
1363         /* check references */
1364         if (DEVI(dip)->devi_ref)
1365                 return (DDI_FAILURE);
1366 
1367         NDI_CONFIG_DEBUG((CE_CONT, "detach_node: 0x%p(%s%d)\n",
1368             (void *)dip, ddi_driver_name(dip), ddi_get_instance(dip)));
1369 
1370         /*
1371          * NOTE: If we are processing a pHCI node then the calling code
1372          * must detect this and ndi_devi_enter() in (vHCI, parent(pHCI))
1373          * order unless pHCI and vHCI are siblings.  Code paths leading
1374          * here that must ensure this ordering include:
1375          * unconfig_immediate_children(), devi_unconfig_one(),
1376          * ndi_devi_unconfig_one(), ndi_devi_offline().
1377          */
1378         ASSERT(!MDI_PHCI(dip) ||
1379             (ddi_get_parent(mdi_devi_get_vdip(dip)) == ddi_get_parent(dip)) ||
1380             DEVI_BUSY_OWNED(mdi_devi_get_vdip(dip)));
1381 
1382         /* Offline the device node with the mpxio framework. */
1383         if (mdi_devi_offline(dip, flag) != NDI_SUCCESS) {
1384                 return (DDI_FAILURE);


1446                 dnp = &(devnamesp[DEVI(dip)->devi_major]);
1447                 LOCK_DEV_OPS(&dnp->dn_lock);
1448                 dnp->dn_flags &= ~DN_DRIVER_HELD;
1449                 UNLOCK_DEV_OPS(&dnp->dn_lock);
1450         }
1451 
1452         /* successful detach, release the driver */
1453         ndi_rele_driver(dip);
1454         DEVI(dip)->devi_ops = NULL;
1455         return (DDI_SUCCESS);
1456 }
1457 
1458 /*
1459  * Run dacf post_attach routines
1460  */
1461 static int
1462 postattach_node(dev_info_t *dip)
1463 {
1464         int rval;
1465 


1466         /*
1467          * For hotplug busses like USB, it's possible that devices
1468          * are removed but dip is still around. We don't want to
1469          * run dacf routines as part of detach failure recovery.
1470          *
1471          * Pretend success until we figure out how to prevent
1472          * access to such devinfo nodes.
1473          */
1474         if (DEVI_IS_DEVICE_REMOVED(dip))
1475                 return (DDI_SUCCESS);
1476 
1477         /*
1478          * if dacf_postattach failed, report it to the framework
1479          * so that it can be retried later at the open time.
1480          */
1481         mutex_enter(&dacf_lock);
1482         rval = dacfc_postattach(dip);
1483         mutex_exit(&dacf_lock);
1484 
1485         /*


3804  * (3) if neither exists, a dev_t is faked with minor number = instance.
3805  * As of S9 FCS, no instance of #1 exists. #2 is used by several platforms
3806  * to default the boot partition to :a possibly by other OBP definitions.
3807  * #3 is used for booting off network interfaces, most SPARC network
3808  * drivers support Style-2 only, so only DDM_ALIAS minor exists.
3809  *
3810  * It is possible for OBP to present device args at the end of the path as
3811  * well as in the middle. For example, with IB the following strings are
3812  * valid boot paths.
3813  *      a /pci@8,700000/ib@1,2:port=1,pkey=ff,dhcp,...
3814  *      b /pci@8,700000/ib@1,1:port=1/ioc@xxxxxx,yyyyyyy:dhcp
3815  * Case (a), we first look for minor node "port=1,pkey...".
3816  * Failing that, we will pass "port=1,pkey..." to the bus_config
3817  * entry point of ib (HCA) driver.
3818  * Case (b), configure ib@1,1 as usual. Then invoke ib's bus_config
3819  * with argument "ioc@xxxxxxx,yyyyyyy:port=1". After configuring
3820  * the ioc, look for minor node dhcp. If not found, pass ":dhcp"
3821  * to ioc's bus_config entry point.
3822  */
3823 int
3824 resolve_pathname(char *pathname,
3825         dev_info_t **dipp, dev_t *devtp, int *spectypep)
3826 {
3827         int                     error;
3828         dev_info_t              *parent, *child;
3829         struct pathname         pn;
3830         char                    *component, *config_name;
3831         char                    *minorname = NULL;
3832         char                    *prev_minor = NULL;
3833         dev_t                   devt = NODEV;
3834         int                     spectype;
3835         struct ddi_minor_data   *dmn;
3836         int                     circ;
3837 
3838         if (*pathname != '/')
3839                 return (EINVAL);
3840         parent = ddi_root_node();       /* Begin at the top of the tree */
3841 
3842         if (error = pn_get(pathname, UIO_SYSSPACE, &pn))
3843                 return (error);
3844         pn_skipslash(&pn);
3845 


4583 {
4584         dev_info_t *dip;
4585 
4586         ASSERT(DEVI(pdip)->devi_flags & DEVI_MADE_CHILDREN);
4587 
4588         /* contiguous instance assignment */
4589         e_ddi_enter_instance();
4590         dip = ddi_get_child(pdip);
4591         while (dip) {
4592                 if (ndi_dev_is_persistent_node(dip))
4593                         (void) i_ndi_config_node(dip, DS_INITIALIZED, flags);
4594                 dip = ddi_get_next_sibling(dip);
4595         }
4596         e_ddi_exit_instance();
4597 }
4598 
4599 /*
4600  * report device status
4601  */
4602 static void
4603 i_ndi_devi_report_status_change(dev_info_t *dip, char *path)
4604 {
4605         char *status;
4606 
4607         if (!DEVI_NEED_REPORT(dip) ||
4608             (i_ddi_node_state(dip) < DS_INITIALIZED) ||
4609             ndi_dev_is_hidden_node(dip)) {
4610                 return;
4611         }
4612 
4613         /* Invalidate the devinfo snapshot cache */
4614         i_ddi_di_cache_invalidate();
4615 
4616         if (DEVI_IS_DEVICE_REMOVED(dip)) {
4617                 status = "removed";
4618         } else if (DEVI_IS_DEVICE_OFFLINE(dip)) {
4619                 status = "offline";
4620         } else if (DEVI_IS_DEVICE_DOWN(dip)) {
4621                 status = "down";
4622         } else if (DEVI_IS_BUS_QUIESCED(dip)) {
4623                 status = "quiesced";
4624         } else if (DEVI_IS_BUS_DOWN(dip)) {
4625                 status = "down";
4626         } else if (i_ddi_devi_attached(dip)) {
4627                 status = "online";
4628         } else {
4629                 status = "unknown";
4630         }
4631 
4632         if (path == NULL) {
4633                 path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
4634                 cmn_err(CE_CONT, "?%s (%s%d) %s\n",
4635                     ddi_pathname(dip, path), ddi_driver_name(dip),
4636                     ddi_get_instance(dip), status);
4637                 kmem_free(path, MAXPATHLEN);
4638         } else {
4639                 cmn_err(CE_CONT, "?%s (%s%d) %s\n",
4640                     path, ddi_driver_name(dip),
4641                     ddi_get_instance(dip), status);
4642         }
4643 
4644         mutex_enter(&(DEVI(dip)->devi_lock));
4645         DEVI_REPORT_DONE(dip);
4646         mutex_exit(&(DEVI(dip)->devi_lock));
4647 }
4648 
4649 /*
4650  * log a notification that a dev_info node has been configured.
4651  */
4652 static int
4653 i_log_devfs_add_devinfo(dev_info_t *dip, uint_t flags)
4654 {
4655         int                     se_err;
4656         char                    *pathname;
4657         sysevent_t              *ev;
4658         sysevent_id_t           eid;
4659         sysevent_value_t        se_val;
4660         sysevent_attr_list_t    *ev_attr_list = NULL;
4661         char                    *class_name;
4662         int                     no_transport = 0;


5210         }
5211         mutex_exit(&(DEVI(dip)->devi_lock));
5212 
5213         if (i_ddi_attachchild(dip) != DDI_SUCCESS) {
5214                 mutex_enter(&(DEVI(dip)->devi_lock));
5215                 DEVI_SET_EVUNINIT(dip);
5216                 mutex_exit(&(DEVI(dip)->devi_lock));
5217 
5218                 if (ndi_dev_is_persistent_node(dip))
5219                         (void) ddi_uninitchild(dip);
5220                 else {
5221                         /*
5222                          * Delete .conf nodes and nodes that are not
5223                          * well formed.
5224                          */
5225                         (void) ddi_remove_child(dip, 0);
5226                 }
5227                 return (NDI_FAILURE);
5228         }
5229 
5230         i_ndi_devi_report_status_change(dip, NULL);
5231 
5232         /*
5233          * log an event, but not during devfs lookups in which case
5234          * NDI_NO_EVENT is set.
5235          */
5236         if ((flags & NDI_NO_EVENT) == 0 && !(DEVI_EVADD(dip))) {
5237                 (void) i_log_devfs_add_devinfo(dip, flags);
5238 
5239                 mutex_enter(&(DEVI(dip)->devi_lock));
5240                 DEVI_SET_EVADD(dip);
5241                 mutex_exit(&(DEVI(dip)->devi_lock));
5242         } else if (!(flags & NDI_NO_EVENT_STATE_CHNG)) {
5243                 mutex_enter(&(DEVI(dip)->devi_lock));
5244                 DEVI_SET_EVADD(dip);
5245                 mutex_exit(&(DEVI(dip)->devi_lock));
5246         }
5247 
5248         return (NDI_SUCCESS);
5249 }
5250 


5748         case LDI_EV_FAILURE:
5749                 contract_device_negend(dip, DDI_DEV_T_ANY, 0, CT_EV_FAILURE);
5750                 RIO_DEBUG((CE_NOTE, "LDI callback failed on dip=%p",
5751                     (void *)dip));
5752                 failure = 1;
5753                 goto out;
5754         case LDI_EV_SUCCESS:
5755                 constraint = 1;
5756                 RIO_DEBUG((CE_NOTE, "LDI callback success on dip=%p",
5757                     (void *)dip));
5758                 break;
5759         case LDI_EV_NONE:
5760                 /* no matching LDI callbacks */
5761                 RIO_DEBUG((CE_NOTE, "No LDI callbacks for dip=%p",
5762                     (void *)dip));
5763                 break;
5764         default:
5765                 ASSERT(retval == LDI_EV_NONE);
5766         }
5767 











5768 out:
5769         mutex_enter(&(DEVI(dip)->devi_lock));
5770         if ((DEVI(dip)->devi_flags & DEVI_RETIRING) && failure) {
5771                 RIO_VERBOSE((CE_NOTE, "e_ddi_offline_notify(): setting "
5772                     "BLOCKED flag. dip=%p", (void *)dip));
5773                 DEVI(dip)->devi_flags |= DEVI_R_BLOCKED;
5774                 if (DEVI(dip)->devi_flags & DEVI_R_CONSTRAINT) {
5775                         RIO_VERBOSE((CE_NOTE, "e_ddi_offline_notify(): "
5776                             "blocked. clearing RCM CONSTRAINT flag. dip=%p",
5777                             (void *)dip));
5778                         DEVI(dip)->devi_flags &= ~DEVI_R_CONSTRAINT;
5779                 }
5780         } else if ((DEVI(dip)->devi_flags & DEVI_RETIRING) && constraint) {
5781                 RIO_VERBOSE((CE_NOTE, "e_ddi_offline_notify(): setting "
5782                     "CONSTRAINT flag. dip=%p", (void *)dip));
5783                 DEVI(dip)->devi_flags |= DEVI_R_CONSTRAINT;
5784         } else if ((DEVI(dip)->devi_flags & DEVI_RETIRING) &&
5785             ((DEVI(dip)->devi_ops != NULL &&
5786             DEVI(dip)->devi_ops->devo_bus_ops != NULL) ||
5787             DEVI(dip)->devi_ref == 0)) {


5913                 RIO_DEBUG((CE_NOTE, "devi_detach_node: offline succeeded."
5914                     " Calling e_ddi_offline_finalize with result=%d, "
5915                     "dip=%p", DDI_SUCCESS, (void *)dip));
5916                 e_ddi_offline_finalize(dip, DDI_SUCCESS);
5917         }
5918 
5919         if (flags & NDI_AUTODETACH)
5920                 return (NDI_SUCCESS);
5921 
5922         /*
5923          * For DR, even bound nodes may need to have offline
5924          * flag set.
5925          */
5926         if (flags & NDI_DEVI_OFFLINE) {
5927                 mutex_enter(&(DEVI(dip)->devi_lock));
5928                 DEVI_SET_DEVICE_OFFLINE(dip);
5929                 mutex_exit(&(DEVI(dip)->devi_lock));
5930         }
5931 
5932         if (i_ddi_node_state(dip) == DS_INITIALIZED) {
5933                 struct dev_info *devi = DEVI(dip);
5934 
5935                 if (devi->devi_ev_path == NULL) {
5936                         devi->devi_ev_path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
5937                         (void) ddi_pathname(dip, devi->devi_ev_path);
5938                 }
5939                 if (flags & NDI_DEVI_OFFLINE)
5940                         i_ndi_devi_report_status_change(dip,
5941                             devi->devi_ev_path);
5942 
5943                 if (need_remove_event(dip, flags)) {
5944                         /*
5945                          * instance and path data are lost in call to
5946                          * ddi_uninitchild
5947                          */
5948                         devi->devi_ev_instance = ddi_get_instance(dip);
5949 
5950                         mutex_enter(&(DEVI(dip)->devi_lock));
5951                         DEVI_SET_EVREMOVE(dip);
5952                         mutex_exit(&(DEVI(dip)->devi_lock));



5953                 }












5954         }

5955 
5956         if (flags & (NDI_UNCONFIG | NDI_DEVI_REMOVE)) {
5957                 ret = ddi_uninitchild(dip);
5958                 if (ret == NDI_SUCCESS) {
5959                         /*
5960                          * Remove uninitialized pseudo nodes because
5961                          * system props are lost and the node cannot be
5962                          * reattached.
5963                          */
5964                         if (!ndi_dev_is_persistent_node(dip))
5965                                 flags |= NDI_DEVI_REMOVE;
5966 
5967                         if (flags & NDI_DEVI_REMOVE) {
5968                                 /*
5969                                  * NOTE: If there is a consumer of LDI events,
5970                                  * ddi_uninitchild above would have failed
5971                                  * because of active devi_ref from ldi_open().
5972                                  */
5973 
5974                                 if (DEVI_EVREMOVE(dip)) {
5975                                         path = i_ddi_strdup(
5976                                             DEVI(dip)->devi_ev_path,
5977                                             KM_SLEEP);
5978                                         class =
5979                                             i_ddi_strdup(i_ddi_devi_class(dip),
5980                                             KM_SLEEP);
5981                                         driver =
5982                                             i_ddi_strdup(
5983                                             (char *)ddi_driver_name(dip),
5984                                             KM_SLEEP);
5985                                         instance = DEVI(dip)->devi_ev_instance;
5986                                         post_event = 1;
5987                                 }

5988 
5989                                 ret = ddi_remove_child(dip, 0);
5990                                 if (post_event && ret == NDI_SUCCESS) {
5991                                         /* Generate EC_DEVFS_DEVI_REMOVE */
5992                                         (void) i_log_devfs_remove_devinfo(path,
5993                                             class, driver, instance, flags);
5994                                 }
5995                         }
5996 
5997                 }
5998         }
5999 
6000         if (path)
6001                 strfree(path);
6002         if (class)
6003                 strfree(class);
6004         if (driver)
6005                 strfree(driver);
6006 




6007         return (ret);
6008 }
6009 
6010 /*
6011  * unconfigure immediate children of bus nexus device
6012  */
6013 static int
6014 unconfig_immediate_children(
6015         dev_info_t *dip,
6016         dev_info_t **dipp,
6017         int flags,
6018         major_t major)
6019 {
6020         int rv = NDI_SUCCESS;
6021         int circ, vcirc;
6022         dev_info_t *child;
6023         dev_info_t *vdip = NULL;
6024         dev_info_t *next;
6025 
6026         ASSERT(dipp == NULL || *dipp == NULL);


6562  * the driver and prevent devfs requests from re-attaching the device
6563  * instance.
6564  *
6565  * The flag NDI_DEVI_REMOVE causes removes the device node from
6566  * the driver list and the device tree. In this case, the device
6567  * is assumed to be removed from the system.
6568  */
6569 int
6570 ndi_devi_offline(dev_info_t *dip, uint_t flags)
6571 {
6572         int             circ, rval = 0;
6573         dev_info_t      *pdip = ddi_get_parent(dip);
6574         dev_info_t      *vdip = NULL;
6575         int             v_circ;
6576         struct brevq_node *brevq = NULL;
6577 
6578         ASSERT(pdip);
6579 
6580         flags |= NDI_DEVI_OFFLINE;
6581 



6582         /*
6583          * If child is pHCI and vHCI and pHCI are not siblings then enter vHCI
6584          * before parent(pHCI) to avoid deadlock with mpxio Client power
6585          * management operations.
6586          */
6587         if (MDI_PHCI(dip)) {
6588                 vdip = mdi_devi_get_vdip(dip);
6589                 if (vdip && (ddi_get_parent(vdip) != pdip))
6590                         ndi_devi_enter(vdip, &v_circ);
6591                 else
6592                         vdip = NULL;
6593         }
6594         ndi_devi_enter(pdip, &circ);
6595 
6596         if (i_ddi_devi_attached(dip)) {
6597                 /*
6598                  * If dip is in DS_READY state, there may be cached dv_nodes
6599                  * referencing this dip, so we invoke devfs code path.
6600                  * Note that we must release busy changing on pdip to
6601                  * avoid deadlock against devfs.


8083                 cmn_err(CE_CONT, "Could not attach %s driver", drvname);
8084                 e_ddi_free_instance(dip, vhci_node_addr);
8085                 ndi_rele_devi(dip);
8086                 (void) ndi_devi_free(dip);
8087                 return (NULL);
8088         }
8089         mutex_enter(&(DEVI(dip)->devi_lock));
8090         DEVI_CLR_ATTACHING(dip);
8091         mutex_exit(&(DEVI(dip)->devi_lock));
8092 
8093         mutex_enter(&global_vhci_lock);
8094         i_link_vhci_node(dip);
8095         mutex_exit(&global_vhci_lock);
8096         i_ddi_set_node_state(dip, DS_READY);
8097 
8098         LOCK_DEV_OPS(&dnp->dn_lock);
8099         dnp->dn_flags |= DN_DRIVER_HELD;
8100         dnp->dn_head = dip;
8101         UNLOCK_DEV_OPS(&dnp->dn_lock);
8102 
8103         i_ndi_devi_report_status_change(dip, NULL);
8104 
8105         return (dip);
8106 }
8107 
8108 /*
8109  * Maintain DEVI_DEVICE_REMOVED hotplug devi_state for remove/reinsert hotplug
8110  * of open devices. Currently, because of tight coupling between the devfs file
8111  * system and the Solaris device tree, a driver can't always make the device
8112  * tree state (esp devi_node_state) match device hardware hotplug state. Until
8113  * resolved, to overcome this deficiency we use the following interfaces that
8114  * maintain the DEVI_DEVICE_REMOVED devi_state status bit.  These interface
8115  * report current state, and drive operation (like events and cache
8116  * invalidation) when a driver changes remove/insert state of an open device.
8117  *
8118  * The ndi_devi_device_isremoved() returns 1 if the device is currently removed.
8119  *
8120  * The ndi_devi_device_remove() interface declares the device as removed, and
8121  * returns 1 if there was a state change associated with this declaration.
8122  *
8123  * The ndi_devi_device_insert() declares the device as inserted, and returns 1


8130 }
8131 
8132 int
8133 ndi_devi_device_remove(dev_info_t *dip)
8134 {
8135         ASSERT(dip && ddi_get_parent(dip) &&
8136             DEVI_BUSY_OWNED(ddi_get_parent(dip)));
8137 
8138         /* Return if already marked removed. */
8139         if (ndi_devi_device_isremoved(dip))
8140                 return (0);
8141 
8142         /* Mark the device as having been physically removed. */
8143         mutex_enter(&(DEVI(dip)->devi_lock));
8144         ndi_devi_set_hidden(dip);       /* invisible: lookup/snapshot */
8145         DEVI_SET_DEVICE_REMOVED(dip);
8146         DEVI_SET_EVREMOVE(dip);         /* this clears EVADD too */
8147         mutex_exit(&(DEVI(dip)->devi_lock));
8148 
8149         /* report remove (as 'removed') */
8150         i_ndi_devi_report_status_change(dip, NULL);
8151 
8152         /*
8153          * Invalidate the cache to ensure accurate
8154          * (di_state() & DI_DEVICE_REMOVED).
8155          */
8156         i_ddi_di_cache_invalidate();
8157 
8158         /*
8159          * Generate sysevent for those interested in removal (either
8160          * directly via private EC_DEVFS or indirectly via devfsadmd
8161          * generated EC_DEV). This will generate LDI DEVICE_REMOVE
8162          * event too.
8163          */
8164         i_ddi_log_devfs_device_remove(dip);
8165 
8166         return (1);             /* DEVICE_REMOVED state changed */
8167 }
8168 
8169 int
8170 ndi_devi_device_insert(dev_info_t *dip)
8171 {
8172         ASSERT(dip && ddi_get_parent(dip) &&
8173             DEVI_BUSY_OWNED(ddi_get_parent(dip)));
8174 
8175         /* Return if not marked removed. */
8176         if (!ndi_devi_device_isremoved(dip))
8177                 return (0);
8178 
8179         /* Mark the device as having been physically reinserted. */
8180         mutex_enter(&(DEVI(dip)->devi_lock));
8181         ndi_devi_clr_hidden(dip);       /* visible: lookup/snapshot */
8182         DEVI_SET_DEVICE_REINSERTED(dip);
8183         DEVI_SET_EVADD(dip);            /* this clears EVREMOVE too */
8184         mutex_exit(&(DEVI(dip)->devi_lock));
8185 
8186         /* report insert (as 'online') */
8187         i_ndi_devi_report_status_change(dip, NULL);
8188 
8189         /*
8190          * Invalidate the cache to ensure accurate
8191          * (di_state() & DI_DEVICE_REMOVED).
8192          */
8193         i_ddi_di_cache_invalidate();
8194 
8195         /*
8196          * Generate sysevent for those interested in removal (either directly
8197          * via EC_DEVFS or indirectly via devfsadmd generated EC_DEV).
8198          */
8199         i_ddi_log_devfs_device_insert(dip);
8200 
8201         return (1);             /* DEVICE_REMOVED state changed */
8202 }
8203 
8204 /*
8205  * ibt_hw_is_present() returns 0 when there is no IB hardware actively
8206  * running.  This is primarily useful for modules like rpcmod which
8207  * needs a quick check to decide whether or not it should try to use


   1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.

  24  * Copyright 2012 Garrett D'Amore <garrett@damore.org>.  All rights reserved.
  25  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
  26  * Copyright 2018 Nexenta Systems, Inc.
  27  * Copyright (c) 2016 by Delphix. All rights reserved.
  28  */
  29 
  30 #include <sys/note.h>
  31 #include <sys/t_lock.h>
  32 #include <sys/cmn_err.h>
  33 #include <sys/instance.h>
  34 #include <sys/conf.h>
  35 #include <sys/stat.h>
  36 #include <sys/ddi.h>
  37 #include <sys/hwconf.h>
  38 #include <sys/sunddi.h>
  39 #include <sys/sunndi.h>
  40 #include <sys/ddi_impldefs.h>
  41 #include <sys/ndi_impldefs.h>
  42 #include <sys/modctl.h>
  43 #include <sys/contract/device_impl.h>
  44 #include <sys/dacf.h>
  45 #include <sys/promif.h>
  46 #include <sys/pci.h>


 155  * (MUTEX_DEFAULT) - it is automatically initialized by being allocated
 156  * in zeroed memory (static storage class). Therefore no explicit
 157  * initialization of the di_cache structure is needed.
 158  */
 159 struct di_cache di_cache = {1};
 160 int             di_cache_debug = 0;
 161 
 162 /* For ddvis, which needs pseudo children under PCI */
 163 int pci_allow_pseudo_children = 0;
 164 
 165 /* Allow path-oriented alias driver binding on driver.conf enumerated nodes */
 166 int driver_conf_allow_path_alias = 1;
 167 
 168 /*
 169  * The following switch is for service people, in case a
 170  * 3rd party driver depends on identify(9e) being called.
 171  */
 172 int identify_9e = 0;
 173 
 174 /*
 175  * Don't prevent attaching retired devices by default.

 176  */
 177 int retire_prevents_attach = 0;
 178 
 179 int mtc_off;                                    /* turn off mt config */
 180 
 181 int quiesce_debug = 0;
 182 
 183 boolean_t ddi_aliases_present = B_FALSE;
 184 ddi_alias_t ddi_aliases;
 185 uint_t tsd_ddi_redirect;
 186 
 187 #define DDI_ALIAS_HASH_SIZE     (2700)
 188 
 189 static kmem_cache_t *ddi_node_cache;            /* devinfo node cache */
 190 static devinfo_log_header_t *devinfo_audit_log; /* devinfo log */
 191 static int devinfo_log_size;                    /* size in pages */
 192 
 193 boolean_t ddi_err_panic = B_FALSE;
 194 
 195 static int lookup_compatible(dev_info_t *, uint_t);
 196 static char *encode_composite_string(char **, uint_t, size_t *, uint_t);
 197 static void link_to_driver_list(dev_info_t *);


 468                 kmem_free(devi->devi_device_class,
 469                     strlen(devi->devi_device_class) + 1);
 470         cv_destroy(&(devi->devi_cv));
 471         mutex_destroy(&(devi->devi_lock));
 472         mutex_destroy(&(devi->devi_pm_lock));
 473         mutex_destroy(&(devi->devi_pm_busy_lock));
 474 
 475         RIO_TRACE((CE_NOTE, "i_ddi_free_node: destroying contract fields: "
 476             "dip=%p", (void *)dip));
 477         contract_device_remove_dip(dip);
 478         ASSERT(devi->devi_ct_count == -1);
 479         ASSERT(list_is_empty(&(devi->devi_ct)));
 480         cv_destroy(&(devi->devi_ct_cv));
 481         list_destroy(&(devi->devi_ct));
 482         /* free this last since contract_device_remove_dip() uses it */
 483         mutex_destroy(&(devi->devi_ct_lock));
 484         RIO_TRACE((CE_NOTE, "i_ddi_free_node: destroyed all contract fields: "
 485             "dip=%p, name=%s", (void *)dip, devi->devi_node_name));
 486 
 487         kmem_free(devi->devi_node_name, strlen(devi->devi_node_name) + 1);





 488         kmem_cache_free(ddi_node_cache, devi);
 489 }
 490 
 491 
 492 /*
 493  * Node state transitions
 494  */
 495 
 496 /*
 497  * Change the node name
 498  */
 499 int
 500 ndi_devi_set_nodename(dev_info_t *dip, char *name, int flags)
 501 {
 502         _NOTE(ARGUNUSED(flags))
 503         char *nname, *oname;
 504 
 505         ASSERT(dip && name);
 506 
 507         oname = DEVI(dip)->devi_node_name;


1338                 mutex_exit(&DEVI(dip)->devi_lock);
1339 
1340         /* successful attach, return with driver held */
1341 
1342         return (DDI_SUCCESS);
1343 }
1344 
1345 /*
1346  * Detach devinfo node.
1347  * Per-driver list must be held busy.
1348  */
1349 static int
1350 detach_node(dev_info_t *dip, uint_t flag)
1351 {
1352         struct devnames *dnp;
1353         int             rv;
1354 
1355         ASSERT(DEVI_BUSY_OWNED(ddi_get_parent(dip)));
1356         ASSERT(i_ddi_node_state(dip) == DS_ATTACHED);
1357 
1358         /* Check references */
1359         if (DEVI(dip)->devi_ref != 0 && !DEVI_IS_GONE(dip))
1360                 return (DDI_FAILURE);
1361 
1362         NDI_CONFIG_DEBUG((CE_CONT, "detach_node: 0x%p(%s%d)\n",
1363             (void *)dip, ddi_driver_name(dip), ddi_get_instance(dip)));
1364 
1365         /*
1366          * NOTE: If we are processing a pHCI node then the calling code
1367          * must detect this and ndi_devi_enter() in (vHCI, parent(pHCI))
1368          * order unless pHCI and vHCI are siblings.  Code paths leading
1369          * here that must ensure this ordering include:
1370          * unconfig_immediate_children(), devi_unconfig_one(),
1371          * ndi_devi_unconfig_one(), ndi_devi_offline().
1372          */
1373         ASSERT(!MDI_PHCI(dip) ||
1374             (ddi_get_parent(mdi_devi_get_vdip(dip)) == ddi_get_parent(dip)) ||
1375             DEVI_BUSY_OWNED(mdi_devi_get_vdip(dip)));
1376 
1377         /* Offline the device node with the mpxio framework. */
1378         if (mdi_devi_offline(dip, flag) != NDI_SUCCESS) {
1379                 return (DDI_FAILURE);


1441                 dnp = &(devnamesp[DEVI(dip)->devi_major]);
1442                 LOCK_DEV_OPS(&dnp->dn_lock);
1443                 dnp->dn_flags &= ~DN_DRIVER_HELD;
1444                 UNLOCK_DEV_OPS(&dnp->dn_lock);
1445         }
1446 
1447         /* successful detach, release the driver */
1448         ndi_rele_driver(dip);
1449         DEVI(dip)->devi_ops = NULL;
1450         return (DDI_SUCCESS);
1451 }
1452 
1453 /*
1454  * Run dacf post_attach routines
1455  */
1456 static int
1457 postattach_node(dev_info_t *dip)
1458 {
1459         int rval;
1460 
1461         DEVI_UNSET_GONE(dip);
1462 
1463         /*
1464          * For hotplug busses like USB, it's possible that devices
1465          * are removed but dip is still around. We don't want to
1466          * run dacf routines as part of detach failure recovery.
1467          *
1468          * Pretend success until we figure out how to prevent
1469          * access to such devinfo nodes.
1470          */
1471         if (DEVI_IS_DEVICE_REMOVED(dip))
1472                 return (DDI_SUCCESS);
1473 
1474         /*
1475          * if dacf_postattach failed, report it to the framework
1476          * so that it can be retried later at the open time.
1477          */
1478         mutex_enter(&dacf_lock);
1479         rval = dacfc_postattach(dip);
1480         mutex_exit(&dacf_lock);
1481 
1482         /*


3801  * (3) if neither exists, a dev_t is faked with minor number = instance.
3802  * As of S9 FCS, no instance of #1 exists. #2 is used by several platforms
3803  * to default the boot partition to :a possibly by other OBP definitions.
3804  * #3 is used for booting off network interfaces, most SPARC network
3805  * drivers support Style-2 only, so only DDM_ALIAS minor exists.
3806  *
3807  * It is possible for OBP to present device args at the end of the path as
3808  * well as in the middle. For example, with IB the following strings are
3809  * valid boot paths.
3810  *      a /pci@8,700000/ib@1,2:port=1,pkey=ff,dhcp,...
3811  *      b /pci@8,700000/ib@1,1:port=1/ioc@xxxxxx,yyyyyyy:dhcp
3812  * Case (a), we first look for minor node "port=1,pkey...".
3813  * Failing that, we will pass "port=1,pkey..." to the bus_config
3814  * entry point of ib (HCA) driver.
3815  * Case (b), configure ib@1,1 as usual. Then invoke ib's bus_config
3816  * with argument "ioc@xxxxxxx,yyyyyyy:port=1". After configuring
3817  * the ioc, look for minor node dhcp. If not found, pass ":dhcp"
3818  * to ioc's bus_config entry point.
3819  */
3820 int
3821 resolve_pathname(char *pathname, dev_info_t **dipp, dev_t *devtp,
3822     int *spectypep)
3823 {
3824         int                     error;
3825         dev_info_t              *parent, *child;
3826         struct pathname         pn;
3827         char                    *component, *config_name;
3828         char                    *minorname = NULL;
3829         char                    *prev_minor = NULL;
3830         dev_t                   devt = NODEV;
3831         int                     spectype;
3832         struct ddi_minor_data   *dmn;
3833         int                     circ;
3834 
3835         if (*pathname != '/')
3836                 return (EINVAL);
3837         parent = ddi_root_node();       /* Begin at the top of the tree */
3838 
3839         if (error = pn_get(pathname, UIO_SYSSPACE, &pn))
3840                 return (error);
3841         pn_skipslash(&pn);
3842 


4580 {
4581         dev_info_t *dip;
4582 
4583         ASSERT(DEVI(pdip)->devi_flags & DEVI_MADE_CHILDREN);
4584 
4585         /* contiguous instance assignment */
4586         e_ddi_enter_instance();
4587         dip = ddi_get_child(pdip);
4588         while (dip) {
4589                 if (ndi_dev_is_persistent_node(dip))
4590                         (void) i_ndi_config_node(dip, DS_INITIALIZED, flags);
4591                 dip = ddi_get_next_sibling(dip);
4592         }
4593         e_ddi_exit_instance();
4594 }
4595 
4596 /*
4597  * report device status
4598  */
4599 static void
4600 i_ndi_devi_report_status_change(dev_info_t *dip)
4601 {
4602         const char *status;
4603 
4604         if (!DEVI_NEED_REPORT(dip) ||
4605             (i_ddi_node_state(dip) < DS_INITIALIZED) ||
4606             ndi_dev_is_hidden_node(dip)) {
4607                 return;
4608         }
4609 
4610         /* Invalidate the devinfo snapshot cache */
4611         i_ddi_di_cache_invalidate();
4612 
4613         if (DEVI_IS_DEVICE_REMOVED(dip)) {
4614                 status = "removed";
4615         } else if (DEVI_IS_DEVICE_OFFLINE(dip)) {
4616                 status = "offline";
4617         } else if (DEVI_IS_DEVICE_DOWN(dip)) {
4618                 status = "down";
4619         } else if (DEVI_IS_BUS_QUIESCED(dip)) {
4620                 status = "quiesced";
4621         } else if (DEVI_IS_BUS_DOWN(dip)) {
4622                 status = "down";
4623         } else if (i_ddi_devi_attached(dip)) {
4624                 status = "online";
4625         } else {
4626                 status = "unknown";
4627         }
4628 
4629         cmn_err(CE_CONT, "?%s%d %s\n", ddi_driver_name(dip),



4630             ddi_get_instance(dip), status);






4631 
4632         mutex_enter(&(DEVI(dip)->devi_lock));
4633         DEVI_REPORT_DONE(dip);
4634         mutex_exit(&(DEVI(dip)->devi_lock));
4635 }
4636 
4637 /*
4638  * log a notification that a dev_info node has been configured.
4639  */
4640 static int
4641 i_log_devfs_add_devinfo(dev_info_t *dip, uint_t flags)
4642 {
4643         int                     se_err;
4644         char                    *pathname;
4645         sysevent_t              *ev;
4646         sysevent_id_t           eid;
4647         sysevent_value_t        se_val;
4648         sysevent_attr_list_t    *ev_attr_list = NULL;
4649         char                    *class_name;
4650         int                     no_transport = 0;


5198         }
5199         mutex_exit(&(DEVI(dip)->devi_lock));
5200 
5201         if (i_ddi_attachchild(dip) != DDI_SUCCESS) {
5202                 mutex_enter(&(DEVI(dip)->devi_lock));
5203                 DEVI_SET_EVUNINIT(dip);
5204                 mutex_exit(&(DEVI(dip)->devi_lock));
5205 
5206                 if (ndi_dev_is_persistent_node(dip))
5207                         (void) ddi_uninitchild(dip);
5208                 else {
5209                         /*
5210                          * Delete .conf nodes and nodes that are not
5211                          * well formed.
5212                          */
5213                         (void) ddi_remove_child(dip, 0);
5214                 }
5215                 return (NDI_FAILURE);
5216         }
5217 
5218         i_ndi_devi_report_status_change(dip);
5219 
5220         /*
5221          * log an event, but not during devfs lookups in which case
5222          * NDI_NO_EVENT is set.
5223          */
5224         if ((flags & NDI_NO_EVENT) == 0 && !(DEVI_EVADD(dip))) {
5225                 (void) i_log_devfs_add_devinfo(dip, flags);
5226 
5227                 mutex_enter(&(DEVI(dip)->devi_lock));
5228                 DEVI_SET_EVADD(dip);
5229                 mutex_exit(&(DEVI(dip)->devi_lock));
5230         } else if (!(flags & NDI_NO_EVENT_STATE_CHNG)) {
5231                 mutex_enter(&(DEVI(dip)->devi_lock));
5232                 DEVI_SET_EVADD(dip);
5233                 mutex_exit(&(DEVI(dip)->devi_lock));
5234         }
5235 
5236         return (NDI_SUCCESS);
5237 }
5238 


5736         case LDI_EV_FAILURE:
5737                 contract_device_negend(dip, DDI_DEV_T_ANY, 0, CT_EV_FAILURE);
5738                 RIO_DEBUG((CE_NOTE, "LDI callback failed on dip=%p",
5739                     (void *)dip));
5740                 failure = 1;
5741                 goto out;
5742         case LDI_EV_SUCCESS:
5743                 constraint = 1;
5744                 RIO_DEBUG((CE_NOTE, "LDI callback success on dip=%p",
5745                     (void *)dip));
5746                 break;
5747         case LDI_EV_NONE:
5748                 /* no matching LDI callbacks */
5749                 RIO_DEBUG((CE_NOTE, "No LDI callbacks for dip=%p",
5750                     (void *)dip));
5751                 break;
5752         default:
5753                 ASSERT(retval == LDI_EV_NONE);
5754         }
5755 
5756         /*
5757          * In order to allow a device retire to succeed that is in use
5758          */
5759 
5760         if (ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
5761             "allow-unconstrained-retire", 0) == 1 && failure == 0) {
5762                 RIO_VERBOSE((CE_NOTE, "e_ddi_offline_notify(): setting "
5763                     "constraint flag due to 'allow-unconstrained-retire' "
5764                     "property on dip=%p", (void *)dip));
5765                 constraint = 1;
5766         }
5767 out:
5768         mutex_enter(&(DEVI(dip)->devi_lock));
5769         if ((DEVI(dip)->devi_flags & DEVI_RETIRING) && failure) {
5770                 RIO_VERBOSE((CE_NOTE, "e_ddi_offline_notify(): setting "
5771                     "BLOCKED flag. dip=%p", (void *)dip));
5772                 DEVI(dip)->devi_flags |= DEVI_R_BLOCKED;
5773                 if (DEVI(dip)->devi_flags & DEVI_R_CONSTRAINT) {
5774                         RIO_VERBOSE((CE_NOTE, "e_ddi_offline_notify(): "
5775                             "blocked. clearing RCM CONSTRAINT flag. dip=%p",
5776                             (void *)dip));
5777                         DEVI(dip)->devi_flags &= ~DEVI_R_CONSTRAINT;
5778                 }
5779         } else if ((DEVI(dip)->devi_flags & DEVI_RETIRING) && constraint) {
5780                 RIO_VERBOSE((CE_NOTE, "e_ddi_offline_notify(): setting "
5781                     "CONSTRAINT flag. dip=%p", (void *)dip));
5782                 DEVI(dip)->devi_flags |= DEVI_R_CONSTRAINT;
5783         } else if ((DEVI(dip)->devi_flags & DEVI_RETIRING) &&
5784             ((DEVI(dip)->devi_ops != NULL &&
5785             DEVI(dip)->devi_ops->devo_bus_ops != NULL) ||
5786             DEVI(dip)->devi_ref == 0)) {


5912                 RIO_DEBUG((CE_NOTE, "devi_detach_node: offline succeeded."
5913                     " Calling e_ddi_offline_finalize with result=%d, "
5914                     "dip=%p", DDI_SUCCESS, (void *)dip));
5915                 e_ddi_offline_finalize(dip, DDI_SUCCESS);
5916         }
5917 
5918         if (flags & NDI_AUTODETACH)
5919                 return (NDI_SUCCESS);
5920 
5921         /*
5922          * For DR, even bound nodes may need to have offline
5923          * flag set.
5924          */
5925         if (flags & NDI_DEVI_OFFLINE) {
5926                 mutex_enter(&(DEVI(dip)->devi_lock));
5927                 DEVI_SET_DEVICE_OFFLINE(dip);
5928                 mutex_exit(&(DEVI(dip)->devi_lock));
5929         }
5930 
5931         if (i_ddi_node_state(dip) == DS_INITIALIZED) {






5932                 if (flags & NDI_DEVI_OFFLINE)
5933                         i_ndi_devi_report_status_change(dip);

5934 
5935                 if (need_remove_event(dip, flags)) {






5936                         mutex_enter(&(DEVI(dip)->devi_lock));
5937                         DEVI_SET_EVREMOVE(dip);
5938                         mutex_exit(&(DEVI(dip)->devi_lock));
5939 
5940                         post_event = (flags & NDI_DEVI_REMOVE) ||
5941                             DEVI_IS_GONE(dip);
5942                 }
5943 
5944                 if (post_event) {
5945                         /*
5946                          * Instance and path data are lost in call to
5947                          * ddi_uninitchild.
5948                          */
5949                         path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
5950                         (void) ddi_pathname(dip, path);
5951                         class = i_ddi_strdup(i_ddi_devi_class(dip), KM_SLEEP);
5952                         driver = i_ddi_strdup((char *)ddi_driver_name(dip),
5953                             KM_SLEEP);
5954                         instance = ddi_get_instance(dip);
5955                 }
5956         }
5957 
5958         if (flags & (NDI_UNCONFIG | NDI_DEVI_REMOVE)) {
5959                 ret = ddi_uninitchild(dip);
5960                 if (ret == NDI_SUCCESS) {
5961                         /*
5962                          * Remove uninitialized pseudo nodes because
5963                          * system props are lost and the node cannot be
5964                          * reattached.
5965                          */
5966                         if (!ndi_dev_is_persistent_node(dip))
5967                                 flags |= NDI_DEVI_REMOVE;
5968 
5969                         if (flags & NDI_DEVI_REMOVE)
5970                                 ret = ddi_remove_child(dip, 0);


















5971                 }
5972         }
5973 
5974         if (ret == NDI_SUCCESS && post_event) {
5975                 /* Generate EC_DEVFS/ESC_DEVFS_DEVI_REMOVE */

5976                 (void) i_log_devfs_remove_devinfo(path,
5977                     class, driver, instance, flags);
5978         }

5979 
5980         if (path != NULL)
5981                 kmem_free(path, MAXPATHLEN);
5982         if (class != NULL)



5983                 strfree(class);
5984         if (driver != NULL)
5985                 strfree(driver);
5986 
5987         /* Clean the flag on successful detach */
5988         if (ret == NDI_SUCCESS)
5989                 DEVI_UNSET_GONE(dip);
5990 
5991         return (ret);
5992 }
5993 
5994 /*
5995  * unconfigure immediate children of bus nexus device
5996  */
5997 static int
5998 unconfig_immediate_children(
5999         dev_info_t *dip,
6000         dev_info_t **dipp,
6001         int flags,
6002         major_t major)
6003 {
6004         int rv = NDI_SUCCESS;
6005         int circ, vcirc;
6006         dev_info_t *child;
6007         dev_info_t *vdip = NULL;
6008         dev_info_t *next;
6009 
6010         ASSERT(dipp == NULL || *dipp == NULL);


6546  * the driver and prevent devfs requests from re-attaching the device
6547  * instance.
6548  *
6549  * The flag NDI_DEVI_REMOVE causes removes the device node from
6550  * the driver list and the device tree. In this case, the device
6551  * is assumed to be removed from the system.
6552  */
6553 int
6554 ndi_devi_offline(dev_info_t *dip, uint_t flags)
6555 {
6556         int             circ, rval = 0;
6557         dev_info_t      *pdip = ddi_get_parent(dip);
6558         dev_info_t      *vdip = NULL;
6559         int             v_circ;
6560         struct brevq_node *brevq = NULL;
6561 
6562         ASSERT(pdip);
6563 
6564         flags |= NDI_DEVI_OFFLINE;
6565 
6566         if (flags & NDI_DEVI_GONE)
6567                 DEVI_SET_GONE(dip);
6568 
6569         /*
6570          * If child is pHCI and vHCI and pHCI are not siblings then enter vHCI
6571          * before parent(pHCI) to avoid deadlock with mpxio Client power
6572          * management operations.
6573          */
6574         if (MDI_PHCI(dip)) {
6575                 vdip = mdi_devi_get_vdip(dip);
6576                 if (vdip && (ddi_get_parent(vdip) != pdip))
6577                         ndi_devi_enter(vdip, &v_circ);
6578                 else
6579                         vdip = NULL;
6580         }
6581         ndi_devi_enter(pdip, &circ);
6582 
6583         if (i_ddi_devi_attached(dip)) {
6584                 /*
6585                  * If dip is in DS_READY state, there may be cached dv_nodes
6586                  * referencing this dip, so we invoke devfs code path.
6587                  * Note that we must release busy changing on pdip to
6588                  * avoid deadlock against devfs.


8070                 cmn_err(CE_CONT, "Could not attach %s driver", drvname);
8071                 e_ddi_free_instance(dip, vhci_node_addr);
8072                 ndi_rele_devi(dip);
8073                 (void) ndi_devi_free(dip);
8074                 return (NULL);
8075         }
8076         mutex_enter(&(DEVI(dip)->devi_lock));
8077         DEVI_CLR_ATTACHING(dip);
8078         mutex_exit(&(DEVI(dip)->devi_lock));
8079 
8080         mutex_enter(&global_vhci_lock);
8081         i_link_vhci_node(dip);
8082         mutex_exit(&global_vhci_lock);
8083         i_ddi_set_node_state(dip, DS_READY);
8084 
8085         LOCK_DEV_OPS(&dnp->dn_lock);
8086         dnp->dn_flags |= DN_DRIVER_HELD;
8087         dnp->dn_head = dip;
8088         UNLOCK_DEV_OPS(&dnp->dn_lock);
8089 
8090         i_ndi_devi_report_status_change(dip);
8091 
8092         return (dip);
8093 }
8094 
8095 /*
8096  * Maintain DEVI_DEVICE_REMOVED hotplug devi_state for remove/reinsert hotplug
8097  * of open devices. Currently, because of tight coupling between the devfs file
8098  * system and the Solaris device tree, a driver can't always make the device
8099  * tree state (esp devi_node_state) match device hardware hotplug state. Until
8100  * resolved, to overcome this deficiency we use the following interfaces that
8101  * maintain the DEVI_DEVICE_REMOVED devi_state status bit.  These interface
8102  * report current state, and drive operation (like events and cache
8103  * invalidation) when a driver changes remove/insert state of an open device.
8104  *
8105  * The ndi_devi_device_isremoved() returns 1 if the device is currently removed.
8106  *
8107  * The ndi_devi_device_remove() interface declares the device as removed, and
8108  * returns 1 if there was a state change associated with this declaration.
8109  *
8110  * The ndi_devi_device_insert() declares the device as inserted, and returns 1


8117 }
8118 
8119 int
8120 ndi_devi_device_remove(dev_info_t *dip)
8121 {
8122         ASSERT(dip && ddi_get_parent(dip) &&
8123             DEVI_BUSY_OWNED(ddi_get_parent(dip)));
8124 
8125         /* Return if already marked removed. */
8126         if (ndi_devi_device_isremoved(dip))
8127                 return (0);
8128 
8129         /* Mark the device as having been physically removed. */
8130         mutex_enter(&(DEVI(dip)->devi_lock));
8131         ndi_devi_set_hidden(dip);       /* invisible: lookup/snapshot */
8132         DEVI_SET_DEVICE_REMOVED(dip);
8133         DEVI_SET_EVREMOVE(dip);         /* this clears EVADD too */
8134         mutex_exit(&(DEVI(dip)->devi_lock));
8135 
8136         /* report remove (as 'removed') */
8137         i_ndi_devi_report_status_change(dip);
8138 
8139         /*
8140          * Invalidate the cache to ensure accurate
8141          * (di_state() & DI_DEVICE_REMOVED).
8142          */
8143         i_ddi_di_cache_invalidate();
8144 
8145         /*
8146          * Generate sysevent for those interested in removal (either
8147          * directly via private EC_DEVFS or indirectly via devfsadmd
8148          * generated EC_DEV). This will generate LDI DEVICE_REMOVE
8149          * event too.
8150          */
8151         i_ddi_log_devfs_device_remove(dip);
8152 
8153         return (1);             /* DEVICE_REMOVED state changed */
8154 }
8155 
8156 int
8157 ndi_devi_device_insert(dev_info_t *dip)
8158 {
8159         ASSERT(dip && ddi_get_parent(dip) &&
8160             DEVI_BUSY_OWNED(ddi_get_parent(dip)));
8161 
8162         /* Return if not marked removed. */
8163         if (!ndi_devi_device_isremoved(dip))
8164                 return (0);
8165 
8166         /* Mark the device as having been physically reinserted. */
8167         mutex_enter(&(DEVI(dip)->devi_lock));
8168         ndi_devi_clr_hidden(dip);       /* visible: lookup/snapshot */
8169         DEVI_SET_DEVICE_REINSERTED(dip);
8170         DEVI_SET_EVADD(dip);            /* this clears EVREMOVE too */
8171         mutex_exit(&(DEVI(dip)->devi_lock));
8172 
8173         /* report insert (as 'online') */
8174         i_ndi_devi_report_status_change(dip);
8175 
8176         /*
8177          * Invalidate the cache to ensure accurate
8178          * (di_state() & DI_DEVICE_REMOVED).
8179          */
8180         i_ddi_di_cache_invalidate();
8181 
8182         /*
8183          * Generate sysevent for those interested in removal (either directly
8184          * via EC_DEVFS or indirectly via devfsadmd generated EC_DEV).
8185          */
8186         i_ddi_log_devfs_device_insert(dip);
8187 
8188         return (1);             /* DEVICE_REMOVED state changed */
8189 }
8190 
8191 /*
8192  * ibt_hw_is_present() returns 0 when there is no IB hardware actively
8193  * running.  This is primarily useful for modules like rpcmod which
8194  * needs a quick check to decide whether or not it should try to use