diff options
author | cth <none@none> | 2005-06-21 21:33:29 -0700 |
---|---|---|
committer | cth <none@none> | 2005-06-21 21:33:29 -0700 |
commit | cfbaf6c3da91a67c2512534fac0bed34936c5471 (patch) | |
tree | 325b9773eb8ee3bc280f92b57451040a213eaf6f /usr/src | |
parent | d3cf9c7d3cb6a89c5ee679d866610bc6baaf2c9a (diff) | |
download | illumos-joyent-cfbaf6c3da91a67c2512534fac0bed34936c5471.tar.gz |
6259385 qassociate() should drive attach
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/uts/common/os/ddi.c | 44 | ||||
-rw-r--r-- | usr/src/uts/common/os/devcfg.c | 16 |
2 files changed, 55 insertions, 5 deletions
diff --git a/usr/src/uts/common/os/ddi.c b/usr/src/uts/common/os/ddi.c index b6356a3d86..ec12f51f37 100644 --- a/usr/src/uts/common/os/ddi.c +++ b/usr/src/uts/common/os/ddi.c @@ -24,7 +24,7 @@ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1131,9 +1131,45 @@ qunbufcall(queue_t *q, bufcall_id_t id) } /* - * Associate stream with an instance of the bottom driver. - * This interface may be called from STREAM driver's put - * procedure, so it cannot block. + * Associate the stream with an instance of the bottom driver. This + * function is called by APIs that establish or modify the hardware + * association (ppa) of an open stream. Two examples of such + * post-open(9E) APIs are the dlpi(7p) DL_ATTACH_REQ message, and the + * ndd(1M) "instance=" ioctl(2). This interface may be called from a + * stream driver's wput procedure and from within syncq perimeters, + * so it can't block. + * + * The qassociate() "model" is that it should drive attach(9E), yet it + * can't really do that because driving attach(9E) is a blocking + * operation. Instead, the qassociate() implementation has complex + * dependencies on the implementation behavior of other parts of the + * kernel to ensure all appropriate instances (ones that have not been + * made inaccessible by DR) are attached at stream open() time, and + * that they will not autodetach. The code relies on the fact that an + * open() of a stream that ends up using qassociate() always occurs on + * a minor node created with CLONE_DEV. The open() comes through + * clnopen() and since clnopen() calls ddi_hold_installed_driver() we + * attach all instances and mark them DN_NO_AUTODETACH (given + * DN_DRIVER_HELD is maintained correctly). + * + * Since qassociate() can't really drive attach(9E), there are corner + * cases where the compromise described above leads to qassociate() + * returning failure. This can happen when administrative functions + * that cause detach(9E), such as "update_drv" or "modunload -i", are + * performed on the driver between the time the stream was opened and + * the time its hardware association was established. Although this can + * theoretically be an arbitrary amount of time, in practice the window + * is usually quite small, since applications almost always issue their + * hardware association request immediately after opening the stream, + * and do not typically switch association while open. When these + * corner cases occur, and qassociate() finds the requested instance + * detached, it will return failure. This failure should be propagated + * to the requesting administrative application using the appropriate + * post-open(9E) API error mechanism. + * + * All qassociate() callers are expected to check for and gracefully handle + * failure return, propagating errors back to the requesting administrative + * application. */ int qassociate(queue_t *q, int instance) diff --git a/usr/src/uts/common/os/devcfg.c b/usr/src/uts/common/os/devcfg.c index a8ae54e4c7..d8470c7701 100644 --- a/usr/src/uts/common/os/devcfg.c +++ b/usr/src/uts/common/os/devcfg.c @@ -1049,7 +1049,9 @@ attach_node(dev_info_t *dip) static int detach_node(dev_info_t *dip, uint_t flag) { - int rv; + struct devnames *dnp; + int rv; + ASSERT(i_ddi_node_state(dip) == DS_ATTACHED); /* check references */ @@ -1104,6 +1106,18 @@ detach_node(dev_info_t *dip, uint_t flag) } mutex_exit(&DEVI(dip)->devi_lock); + /* + * If the instance has successfully detached in detach_driver() context, + * clear DN_DRIVER_HELD for correct ddi_hold_installed_driver() + * behavior. Consumers like qassociate() depend on this (via clnopen()). + */ + if (flag & NDI_DETACH_DRIVER) { + dnp = &(devnamesp[DEVI(dip)->devi_major]); + LOCK_DEV_OPS(&dnp->dn_lock); + dnp->dn_flags &= ~DN_DRIVER_HELD; + UNLOCK_DEV_OPS(&dnp->dn_lock); + } + /* successful detach, release the driver */ ndi_rele_driver(dip); DEVI(dip)->devi_ops = NULL; |