xref: /titanic_50/usr/src/uts/common/io/rsm/rsm.c (revision 1a5e258f5471356ca102c7176637cdce45bac147)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
55dd2c7e9Sjg97986  * Common Development and Distribution License (the "License").
65dd2c7e9Sjg97986  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22d3d50737SRafael Vanoni  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
24b97d6ca7SMilan Jurik  * Copyright 2012 Milan Jurik. All rights reserved.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate  * Overview of the RSM Kernel Agent:
307c478bd9Sstevel@tonic-gate  * ---------------------------------
317c478bd9Sstevel@tonic-gate  *
327c478bd9Sstevel@tonic-gate  * rsm.c constitutes the implementation of the RSM kernel agent. The RSM
337c478bd9Sstevel@tonic-gate  * kernel agent is a pseudo device driver which makes use of the RSMPI
347c478bd9Sstevel@tonic-gate  * interface on behalf of the RSMAPI user library.
357c478bd9Sstevel@tonic-gate  *
367c478bd9Sstevel@tonic-gate  * The kernel agent functionality can be categorized into the following
377c478bd9Sstevel@tonic-gate  * components:
387c478bd9Sstevel@tonic-gate  * 1. Driver Infrastructure
397c478bd9Sstevel@tonic-gate  * 2. Export/Import Segment Management
407c478bd9Sstevel@tonic-gate  * 3. Internal resource allocation/deallocation
417c478bd9Sstevel@tonic-gate  *
427c478bd9Sstevel@tonic-gate  * The driver infrastructure includes the basic module loading entry points
437c478bd9Sstevel@tonic-gate  * like _init, _info, _fini to load, unload and report information about
447c478bd9Sstevel@tonic-gate  * the driver module. The driver infrastructure also includes the
457c478bd9Sstevel@tonic-gate  * autoconfiguration entry points namely, attach, detach and getinfo for
467c478bd9Sstevel@tonic-gate  * the device autoconfiguration.
477c478bd9Sstevel@tonic-gate  *
487c478bd9Sstevel@tonic-gate  * The kernel agent is a pseudo character device driver and exports
497c478bd9Sstevel@tonic-gate  * a cb_ops structure which defines the driver entry points for character
507c478bd9Sstevel@tonic-gate  * device access. This includes the open and close entry points. The
517c478bd9Sstevel@tonic-gate  * other entry points provided include ioctl, devmap and segmap and chpoll.
527c478bd9Sstevel@tonic-gate  * read and write entry points are not used since the device is memory
537c478bd9Sstevel@tonic-gate  * mapped. Also ddi_prop_op is used for the prop_op entry point.
547c478bd9Sstevel@tonic-gate  *
557c478bd9Sstevel@tonic-gate  * The ioctl entry point supports a number of commands, which are used by
567c478bd9Sstevel@tonic-gate  * the RSMAPI library in order to export and import segments. These
577c478bd9Sstevel@tonic-gate  * commands include commands for binding and rebinding the physical pages
587c478bd9Sstevel@tonic-gate  * allocated to the virtual address range, publishing the export segment,
597c478bd9Sstevel@tonic-gate  * unpublishing and republishing an export segment, creating an
607c478bd9Sstevel@tonic-gate  * import segment and a virtual connection from this import segment to
617c478bd9Sstevel@tonic-gate  * an export segment, performing scatter-gather data transfer, barrier
627c478bd9Sstevel@tonic-gate  * operations.
637c478bd9Sstevel@tonic-gate  *
647c478bd9Sstevel@tonic-gate  *
657c478bd9Sstevel@tonic-gate  * Export and Import segments:
667c478bd9Sstevel@tonic-gate  * ---------------------------
677c478bd9Sstevel@tonic-gate  *
687c478bd9Sstevel@tonic-gate  * In order to create an RSM export segment a process allocates a range in its
697c478bd9Sstevel@tonic-gate  * virtual address space for the segment using standard Solaris interfaces.
707c478bd9Sstevel@tonic-gate  * The process then calls RSMAPI, which in turn makes an ioctl call to the
717c478bd9Sstevel@tonic-gate  * RSM kernel agent for an allocation of physical memory pages and for
727c478bd9Sstevel@tonic-gate  * creation of the export segment by binding these pages to the virtual
737c478bd9Sstevel@tonic-gate  * address range. These pages are locked in memory so that remote accesses
747c478bd9Sstevel@tonic-gate  * are always applied to the correct page. Then the RSM segment is published,
757c478bd9Sstevel@tonic-gate  * again via RSMAPI making an ioctl to the RSM kernel agent, and a segment id
767c478bd9Sstevel@tonic-gate  * is assigned to it.
777c478bd9Sstevel@tonic-gate  *
787c478bd9Sstevel@tonic-gate  * In order to import a published RSM segment, RSMAPI creates an import
797c478bd9Sstevel@tonic-gate  * segment and forms a virtual connection across the interconnect to the
807c478bd9Sstevel@tonic-gate  * export segment, via an ioctl into the kernel agent with the connect
817c478bd9Sstevel@tonic-gate  * command. The import segment setup is completed by mapping the
827c478bd9Sstevel@tonic-gate  * local device memory into the importers virtual address space. The
837c478bd9Sstevel@tonic-gate  * mapping of the import segment is handled by the segmap/devmap
847c478bd9Sstevel@tonic-gate  * infrastructure described as follows.
857c478bd9Sstevel@tonic-gate  *
867c478bd9Sstevel@tonic-gate  * Segmap and Devmap interfaces:
877c478bd9Sstevel@tonic-gate  *
887c478bd9Sstevel@tonic-gate  * The RSM kernel agent allows device memory to be directly accessed by user
897c478bd9Sstevel@tonic-gate  * threads via memory mapping. In order to do so, the RSM kernel agent
907c478bd9Sstevel@tonic-gate  * supports the devmap and segmap entry points.
917c478bd9Sstevel@tonic-gate  *
927c478bd9Sstevel@tonic-gate  * The segmap entry point(rsm_segmap) is responsible for setting up a memory
937c478bd9Sstevel@tonic-gate  * mapping as requested by mmap. The devmap entry point(rsm_devmap) is
947c478bd9Sstevel@tonic-gate  * responsible for exporting the device memory to the user applications.
957c478bd9Sstevel@tonic-gate  * rsm_segmap calls RSMPI rsm_map to allocate device memory. Then the
967c478bd9Sstevel@tonic-gate  * control is transfered to the devmap_setup call which calls rsm_devmap.
977c478bd9Sstevel@tonic-gate  *
987c478bd9Sstevel@tonic-gate  * rsm_devmap validates the user mapping to the device or kernel memory
997c478bd9Sstevel@tonic-gate  * and passes the information to the system for setting up the mapping. The
1007c478bd9Sstevel@tonic-gate  * actual setting up of the mapping is done by devmap_devmem_setup(for
1017c478bd9Sstevel@tonic-gate  * device memory) or devmap_umem_setup(for kernel memory). Callbacks are
1027c478bd9Sstevel@tonic-gate  * registered for device context management via the devmap_devmem_setup
1037c478bd9Sstevel@tonic-gate  * or devmap_umem_setup calls. The callbacks are rsmmap_map, rsmmap_unmap,
1047c478bd9Sstevel@tonic-gate  * rsmmap_access, rsmmap_dup. The callbacks are called when a new mapping
1057c478bd9Sstevel@tonic-gate  * is created, a mapping is freed, a mapping is accessed or an existing
1067c478bd9Sstevel@tonic-gate  * mapping is duplicated respectively. These callbacks allow the RSM kernel
1077c478bd9Sstevel@tonic-gate  * agent to maintain state information associated with the mappings.
1087c478bd9Sstevel@tonic-gate  * The state information is mainly in the form of a cookie list for the import
1097c478bd9Sstevel@tonic-gate  * segment for which mapping has been done.
1107c478bd9Sstevel@tonic-gate  *
1117c478bd9Sstevel@tonic-gate  * Forced disconnect of import segments:
1127c478bd9Sstevel@tonic-gate  *
1137c478bd9Sstevel@tonic-gate  * When an exported segment is unpublished, the exporter sends a forced
1147c478bd9Sstevel@tonic-gate  * disconnect message to all its importers. The importer segments are
1157c478bd9Sstevel@tonic-gate  * unloaded and disconnected. This involves unloading the original
1167c478bd9Sstevel@tonic-gate  * mappings and remapping to a preallocated kernel trash page. This is
1177c478bd9Sstevel@tonic-gate  * done by devmap_umem_remap. The trash/dummy page is a kernel page,
1187c478bd9Sstevel@tonic-gate  * preallocated by the kernel agent during attach using ddi_umem_alloc with
1197c478bd9Sstevel@tonic-gate  * the DDI_UMEM_TRASH flag set. This avoids a core dump in the application
1207c478bd9Sstevel@tonic-gate  * due to unloading of the original mappings.
1217c478bd9Sstevel@tonic-gate  *
1227c478bd9Sstevel@tonic-gate  * Additionally every segment has a mapping generation number associated
1237c478bd9Sstevel@tonic-gate  * with it. This is an entry in the barrier generation page, created
1247c478bd9Sstevel@tonic-gate  * during attach time. This mapping generation number for the import
1257c478bd9Sstevel@tonic-gate  * segments is incremented on a force disconnect to notify the application
1267c478bd9Sstevel@tonic-gate  * of the force disconnect. On this notification, the application needs
1277c478bd9Sstevel@tonic-gate  * to reconnect the segment to establish a new legitimate mapping.
1287c478bd9Sstevel@tonic-gate  *
1297c478bd9Sstevel@tonic-gate  *
1307c478bd9Sstevel@tonic-gate  * Locks used in the kernel agent:
1317c478bd9Sstevel@tonic-gate  * -------------------------------
1327c478bd9Sstevel@tonic-gate  *
1337c478bd9Sstevel@tonic-gate  * The kernel agent uses a variety of mutexes and condition variables for
1347c478bd9Sstevel@tonic-gate  * mutual exclusion of the shared data structures and for synchronization
1357c478bd9Sstevel@tonic-gate  * between the various threads. Some of the locks are described as follows.
1367c478bd9Sstevel@tonic-gate  *
1377c478bd9Sstevel@tonic-gate  * Each resource structure, which represents either an export/import segment
1387c478bd9Sstevel@tonic-gate  * has a lock associated with it. The lock is the resource mutex, rsmrc_lock.
1397c478bd9Sstevel@tonic-gate  * This is used directly by RSMRC_LOCK and RSMRC_UNLOCK macros and in the
1407c478bd9Sstevel@tonic-gate  * rsmseglock_acquire and rsmseglock_release macros. An additional
1417c478bd9Sstevel@tonic-gate  * lock called the rsmsi_lock is used for the shared import data structure
1427c478bd9Sstevel@tonic-gate  * that is relevant for resources representing import segments. There is
1437c478bd9Sstevel@tonic-gate  * also a condition variable associated with the resource called s_cv. This
1447c478bd9Sstevel@tonic-gate  * is used to wait for events like the segment state change etc.
1457c478bd9Sstevel@tonic-gate  *
1467c478bd9Sstevel@tonic-gate  * The resource structures are allocated from a pool of resource structures,
1477c478bd9Sstevel@tonic-gate  * called rsm_resource. This pool is protected via a reader-writer lock,
1487c478bd9Sstevel@tonic-gate  * called rsmrc_lock.
1497c478bd9Sstevel@tonic-gate  *
1507c478bd9Sstevel@tonic-gate  * There are two separate hash tables, one for the export segments and
1517c478bd9Sstevel@tonic-gate  * one for the import segments. The export segments are inserted into the
1527c478bd9Sstevel@tonic-gate  * export segment hash table only after they have been published and the
1537c478bd9Sstevel@tonic-gate  * import segments are inserted in the import segments list only after they
1547c478bd9Sstevel@tonic-gate  * have successfully connected to an exported segment. These tables are
1557c478bd9Sstevel@tonic-gate  * protected via reader-writer locks.
1567c478bd9Sstevel@tonic-gate  *
1577c478bd9Sstevel@tonic-gate  * Debug Support in the kernel agent:
1587c478bd9Sstevel@tonic-gate  * ----------------------------------
1597c478bd9Sstevel@tonic-gate  *
1607c478bd9Sstevel@tonic-gate  * Debugging support in the kernel agent is provided by the following
1617c478bd9Sstevel@tonic-gate  * macros.
1627c478bd9Sstevel@tonic-gate  *
1637c478bd9Sstevel@tonic-gate  * DBG_PRINTF((category, level, message)) is a macro which logs a debug
1647c478bd9Sstevel@tonic-gate  * message to the kernel agents debug buffer, rsmka_dbg. This debug buffer
1657c478bd9Sstevel@tonic-gate  * can be viewed in kmdb as *rsmka_dbg/s. The message is logged based
1667c478bd9Sstevel@tonic-gate  * on the definition of the category and level. All messages that belong to
1677c478bd9Sstevel@tonic-gate  * the specified category(rsmdbg_category) and are of an equal or greater
1687c478bd9Sstevel@tonic-gate  * severity than the specified level(rsmdbg_level) are logged. The message
1697c478bd9Sstevel@tonic-gate  * is a string which uses the same formatting rules as the strings used in
1707c478bd9Sstevel@tonic-gate  * printf.
1717c478bd9Sstevel@tonic-gate  *
1727c478bd9Sstevel@tonic-gate  * The category defines which component of the kernel agent has logged this
1737c478bd9Sstevel@tonic-gate  * message. There are a number of categories that have been defined such as
1747c478bd9Sstevel@tonic-gate  * RSM_KERNEL_AGENT, RSM_OPS, RSM_IMPORT, RSM_EXPORT etc. A macro,
1757c478bd9Sstevel@tonic-gate  * DBG_ADDCATEGORY is used to add in another category to the currently
1767c478bd9Sstevel@tonic-gate  * specified category value so that the component using this new category
1777c478bd9Sstevel@tonic-gate  * can also effectively log debug messages. Thus, the category of a specific
1787c478bd9Sstevel@tonic-gate  * message is some combination of the available categories and we can define
1797c478bd9Sstevel@tonic-gate  * sub-categories if we want a finer level of granularity.
1807c478bd9Sstevel@tonic-gate  *
1817c478bd9Sstevel@tonic-gate  * The level defines the severity of the message. Different level values are
1827c478bd9Sstevel@tonic-gate  * defined, with RSM_ERR being the most severe and RSM_DEBUG_VERBOSE being
1837c478bd9Sstevel@tonic-gate  * the least severe(debug level is 0).
1847c478bd9Sstevel@tonic-gate  *
1857c478bd9Sstevel@tonic-gate  * DBG_DEFINE and DBG_DEFINE_STR are macros provided to declare a debug
1867c478bd9Sstevel@tonic-gate  * variable or a string respectively.
1877c478bd9Sstevel@tonic-gate  *
1887c478bd9Sstevel@tonic-gate  *
1897c478bd9Sstevel@tonic-gate  * NOTES:
1907c478bd9Sstevel@tonic-gate  *
1917c478bd9Sstevel@tonic-gate  * Special Fork and Exec Handling:
1927c478bd9Sstevel@tonic-gate  * -------------------------------
1937c478bd9Sstevel@tonic-gate  *
1947c478bd9Sstevel@tonic-gate  * The backing physical pages of an exported segment are always locked down.
1957c478bd9Sstevel@tonic-gate  * Thus, there are two cases in which a process having exported segments
1967c478bd9Sstevel@tonic-gate  * will cause a cpu to hang: (1) the process invokes exec; (2) a process
1977c478bd9Sstevel@tonic-gate  * forks and invokes exit before the duped file descriptors for the export
1987c478bd9Sstevel@tonic-gate  * segments are closed in the child process. The hang is caused because the
1997c478bd9Sstevel@tonic-gate  * address space release algorithm in Solaris VM subsystem is based on a
2007c478bd9Sstevel@tonic-gate  * non-blocking loop which does not terminate while segments are locked
2017c478bd9Sstevel@tonic-gate  * down. In addition to this, Solaris VM subsystem lacks a callback
2027c478bd9Sstevel@tonic-gate  * mechanism to the rsm kernel agent to allow unlocking these export
2037c478bd9Sstevel@tonic-gate  * segment pages.
2047c478bd9Sstevel@tonic-gate  *
2057c478bd9Sstevel@tonic-gate  * In order to circumvent this problem, the kernel agent does the following.
2067c478bd9Sstevel@tonic-gate  * The Solaris VM subsystem keeps memory segments in increasing order of
2077c478bd9Sstevel@tonic-gate  * virtual addressses. Thus a special page(special_exit_offset) is allocated
2087c478bd9Sstevel@tonic-gate  * by the kernel agent and is mmapped into the heap area of the process address
2097c478bd9Sstevel@tonic-gate  * space(the mmap is done by the RSMAPI library). During the mmap processing
2107c478bd9Sstevel@tonic-gate  * of this special page by the devmap infrastructure, a callback(the same
2117c478bd9Sstevel@tonic-gate  * devmap context management callbacks discussed above) is registered for an
2127c478bd9Sstevel@tonic-gate  * unmap.
2137c478bd9Sstevel@tonic-gate  *
2147c478bd9Sstevel@tonic-gate  * As discussed above, this page is processed by the Solaris address space
2157c478bd9Sstevel@tonic-gate  * release code before any of the exported segments pages(which are allocated
2167c478bd9Sstevel@tonic-gate  * from high memory). It is during this processing that the unmap callback gets
2177c478bd9Sstevel@tonic-gate  * called and this callback is responsible for force destroying the exported
2187c478bd9Sstevel@tonic-gate  * segments and thus eliminating the problem of locked pages.
2197c478bd9Sstevel@tonic-gate  *
2207c478bd9Sstevel@tonic-gate  * Flow-control:
2217c478bd9Sstevel@tonic-gate  * ------------
2227c478bd9Sstevel@tonic-gate  *
2237c478bd9Sstevel@tonic-gate  * A credit based flow control algorithm is used for messages whose
2247c478bd9Sstevel@tonic-gate  * processing cannot be done in the interrupt context because it might
2257c478bd9Sstevel@tonic-gate  * involve invoking rsmpi calls, or might take a long time to complete
2267c478bd9Sstevel@tonic-gate  * or might need to allocate resources. The algorithm operates on a per
2277c478bd9Sstevel@tonic-gate  * path basis. To send a message the pathend needs to have a credit and
2287c478bd9Sstevel@tonic-gate  * it consumes one for every message that is flow controlled. On the
2297c478bd9Sstevel@tonic-gate  * receiving pathend the message is put on a msgbuf_queue and a task is
2307c478bd9Sstevel@tonic-gate  * dispatched on the worker thread - recv_taskq where it is processed.
2317c478bd9Sstevel@tonic-gate  * After processing the message, the receiving pathend dequeues the message,
2327c478bd9Sstevel@tonic-gate  * and if it has processed > RSMIPC_LOTSFREE_MSGBUFS messages sends
2337c478bd9Sstevel@tonic-gate  * credits to the sender pathend.
2347c478bd9Sstevel@tonic-gate  *
2357c478bd9Sstevel@tonic-gate  * RSM_DRTEST:
2367c478bd9Sstevel@tonic-gate  * -----------
2377c478bd9Sstevel@tonic-gate  *
2387c478bd9Sstevel@tonic-gate  * This is used to enable the DR testing using a test driver on test
2397c478bd9Sstevel@tonic-gate  * platforms which do not supported DR.
2407c478bd9Sstevel@tonic-gate  *
2417c478bd9Sstevel@tonic-gate  */
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate #include <sys/types.h>
2447c478bd9Sstevel@tonic-gate #include <sys/param.h>
2457c478bd9Sstevel@tonic-gate #include <sys/user.h>
2467c478bd9Sstevel@tonic-gate #include <sys/buf.h>
2477c478bd9Sstevel@tonic-gate #include <sys/systm.h>
2487c478bd9Sstevel@tonic-gate #include <sys/cred.h>
2497c478bd9Sstevel@tonic-gate #include <sys/vm.h>
2507c478bd9Sstevel@tonic-gate #include <sys/uio.h>
2517c478bd9Sstevel@tonic-gate #include <vm/seg.h>
2527c478bd9Sstevel@tonic-gate #include <vm/page.h>
2537c478bd9Sstevel@tonic-gate #include <sys/stat.h>
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate #include <sys/time.h>
2567c478bd9Sstevel@tonic-gate #include <sys/errno.h>
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate #include <sys/file.h>
2597c478bd9Sstevel@tonic-gate #include <sys/uio.h>
2607c478bd9Sstevel@tonic-gate #include <sys/proc.h>
2617c478bd9Sstevel@tonic-gate #include <sys/mman.h>
2627c478bd9Sstevel@tonic-gate #include <sys/open.h>
2637c478bd9Sstevel@tonic-gate #include <sys/atomic.h>
2647c478bd9Sstevel@tonic-gate #include <sys/mem_config.h>
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
2687c478bd9Sstevel@tonic-gate #include <sys/devops.h>
2697c478bd9Sstevel@tonic-gate #include <sys/ddidevmap.h>
2707c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
2717c478bd9Sstevel@tonic-gate #include <sys/esunddi.h>
2727c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h>
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
2757c478bd9Sstevel@tonic-gate #include <sys/conf.h>
2767c478bd9Sstevel@tonic-gate #include <sys/devops.h>
2777c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h>
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate #include <sys/policy.h>
2827c478bd9Sstevel@tonic-gate #include <sys/types.h>
2837c478bd9Sstevel@tonic-gate #include <sys/conf.h>
2847c478bd9Sstevel@tonic-gate #include <sys/param.h>
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate #include <sys/taskq.h>
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate #include <sys/rsm/rsm_common.h>
2897c478bd9Sstevel@tonic-gate #include <sys/rsm/rsmapi_common.h>
2907c478bd9Sstevel@tonic-gate #include <sys/rsm/rsm.h>
2917c478bd9Sstevel@tonic-gate #include <rsm_in.h>
2927c478bd9Sstevel@tonic-gate #include <sys/rsm/rsmka_path_int.h>
2937c478bd9Sstevel@tonic-gate #include <sys/rsm/rsmpi.h>
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
2967c478bd9Sstevel@tonic-gate #include <sys/debug.h>
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate #include <sys/tuneable.h>
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate #ifdef	RSM_DRTEST
3017c478bd9Sstevel@tonic-gate extern int rsm_kphysm_setup_func_register(kphysm_setup_vector_t *vec,
3027c478bd9Sstevel@tonic-gate 		void *arg);
3037c478bd9Sstevel@tonic-gate extern void rsm_kphysm_setup_func_unregister(kphysm_setup_vector_t *vec,
3047c478bd9Sstevel@tonic-gate 		void *arg);
3057c478bd9Sstevel@tonic-gate #endif
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate extern void dbg_printf(int category, int level, char *fmt, ...);
3087c478bd9Sstevel@tonic-gate extern void rsmka_pathmanager_init();
3097c478bd9Sstevel@tonic-gate extern void rsmka_pathmanager_cleanup();
310b97d6ca7SMilan Jurik extern void rele_sendq_token(sendq_token_t *);
3117c478bd9Sstevel@tonic-gate extern rsm_addr_t get_remote_hwaddr(adapter_t *, rsm_node_id_t);
3127c478bd9Sstevel@tonic-gate extern rsm_node_id_t get_remote_nodeid(adapter_t *, rsm_addr_t);
3137c478bd9Sstevel@tonic-gate extern int rsmka_topology_ioctl(caddr_t, int, int);
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate extern pri_t maxclsyspri;
3167c478bd9Sstevel@tonic-gate extern work_queue_t work_queue;
3177c478bd9Sstevel@tonic-gate extern kmutex_t ipc_info_lock;
3187c478bd9Sstevel@tonic-gate extern kmutex_t ipc_info_cvlock;
3197c478bd9Sstevel@tonic-gate extern kcondvar_t ipc_info_cv;
3207c478bd9Sstevel@tonic-gate extern kmutex_t path_hold_cvlock;
3217c478bd9Sstevel@tonic-gate extern kcondvar_t path_hold_cv;
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate extern kmutex_t rsmka_buf_lock;
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate extern path_t *rsm_find_path(char *, int, rsm_addr_t);
3267c478bd9Sstevel@tonic-gate extern adapter_t *rsmka_lookup_adapter(char *, int);
3277c478bd9Sstevel@tonic-gate extern sendq_token_t *rsmka_get_sendq_token(rsm_node_id_t, sendq_token_t *);
3287c478bd9Sstevel@tonic-gate extern boolean_t rsmka_do_path_active(path_t *, int);
3297c478bd9Sstevel@tonic-gate extern boolean_t rsmka_check_node_alive(rsm_node_id_t);
3307c478bd9Sstevel@tonic-gate extern void rsmka_release_adapter(adapter_t *);
3317c478bd9Sstevel@tonic-gate extern void rsmka_enqueue_msgbuf(path_t *path, void *data);
3327c478bd9Sstevel@tonic-gate extern void rsmka_dequeue_msgbuf(path_t *path);
3337c478bd9Sstevel@tonic-gate extern msgbuf_elem_t *rsmka_gethead_msgbuf(path_t *path);
3347c478bd9Sstevel@tonic-gate /* lint -w2 */
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate static int rsm_open(dev_t *, int, int, cred_t *);
3377c478bd9Sstevel@tonic-gate static int rsm_close(dev_t, int, int, cred_t *);
3387c478bd9Sstevel@tonic-gate static int rsm_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
3397c478bd9Sstevel@tonic-gate     cred_t *credp, int *rvalp);
3407c478bd9Sstevel@tonic-gate static int rsm_devmap(dev_t, devmap_cookie_t, offset_t, size_t, size_t *,
3417c478bd9Sstevel@tonic-gate     uint_t);
3427c478bd9Sstevel@tonic-gate static int rsm_segmap(dev_t, off_t, struct as *, caddr_t *, off_t, uint_t,
3437c478bd9Sstevel@tonic-gate     uint_t, uint_t, cred_t *);
3447c478bd9Sstevel@tonic-gate static int rsm_chpoll(dev_t dev, short events, int anyyet, short *reventsp,
3457c478bd9Sstevel@tonic-gate     struct pollhead **phpp);
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate static int rsm_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
3487c478bd9Sstevel@tonic-gate static int rsm_attach(dev_info_t *, ddi_attach_cmd_t);
3497c478bd9Sstevel@tonic-gate static int rsm_detach(dev_info_t *, ddi_detach_cmd_t);
3507c478bd9Sstevel@tonic-gate 
3517c478bd9Sstevel@tonic-gate static int rsmipc_send(rsm_node_id_t, rsmipc_request_t *, rsmipc_reply_t *);
3527c478bd9Sstevel@tonic-gate static void rsm_force_unload(rsm_node_id_t, rsm_memseg_id_t, boolean_t);
3537c478bd9Sstevel@tonic-gate static void rsm_send_importer_disconnects(rsm_memseg_id_t, rsm_node_id_t);
3547c478bd9Sstevel@tonic-gate static void rsm_send_republish(rsm_memseg_id_t, rsmapi_access_entry_t *, int,
3557c478bd9Sstevel@tonic-gate 				rsm_permission_t);
3567c478bd9Sstevel@tonic-gate static void rsm_export_force_destroy(ddi_umem_cookie_t *);
3577c478bd9Sstevel@tonic-gate static void rsmacl_free(rsmapi_access_entry_t *, int);
3587c478bd9Sstevel@tonic-gate static void rsmpiacl_free(rsm_access_entry_t *, int);
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate static int rsm_inc_pgcnt(pgcnt_t);
3617c478bd9Sstevel@tonic-gate static void rsm_dec_pgcnt(pgcnt_t);
3627c478bd9Sstevel@tonic-gate static void rsm_free_mapinfo(rsm_mapinfo_t *mapinfop);
3637c478bd9Sstevel@tonic-gate static rsm_mapinfo_t *rsm_get_mapinfo(rsmseg_t *, off_t, size_t, off_t *,
3647c478bd9Sstevel@tonic-gate 					size_t *);
3657c478bd9Sstevel@tonic-gate static void exporter_quiesce();
3667c478bd9Sstevel@tonic-gate static void rsmseg_suspend(rsmseg_t *, int *);
3677c478bd9Sstevel@tonic-gate static void rsmsegshare_suspend(rsmseg_t *);
3687c478bd9Sstevel@tonic-gate static int rsmseg_resume(rsmseg_t *, void **);
3697c478bd9Sstevel@tonic-gate static int rsmsegshare_resume(rsmseg_t *);
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate static struct cb_ops rsm_cb_ops = {
3727c478bd9Sstevel@tonic-gate 	rsm_open,		/* open */
3737c478bd9Sstevel@tonic-gate 	rsm_close,		/* close */
3747c478bd9Sstevel@tonic-gate 	nodev,			/* strategy */
3757c478bd9Sstevel@tonic-gate 	nodev,			/* print */
3767c478bd9Sstevel@tonic-gate 	nodev,			/* dump */
3777c478bd9Sstevel@tonic-gate 	nodev,			/* read */
3787c478bd9Sstevel@tonic-gate 	nodev,			/* write */
3797c478bd9Sstevel@tonic-gate 	rsm_ioctl,		/* ioctl */
3807c478bd9Sstevel@tonic-gate 	rsm_devmap,		/* devmap */
3817c478bd9Sstevel@tonic-gate 	NULL,			/* mmap */
3827c478bd9Sstevel@tonic-gate 	rsm_segmap,		/* segmap */
3837c478bd9Sstevel@tonic-gate 	rsm_chpoll,		/* poll */
3847c478bd9Sstevel@tonic-gate 	ddi_prop_op,		/* cb_prop_op */
3857c478bd9Sstevel@tonic-gate 	0,			/* streamtab  */
3867c478bd9Sstevel@tonic-gate 	D_NEW|D_MP|D_DEVMAP,	/* Driver compatibility flag */
3877c478bd9Sstevel@tonic-gate 	0,
3887c478bd9Sstevel@tonic-gate 	0,
3897c478bd9Sstevel@tonic-gate 	0
3907c478bd9Sstevel@tonic-gate };
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate static struct dev_ops rsm_ops = {
3937c478bd9Sstevel@tonic-gate 	DEVO_REV,		/* devo_rev, */
3947c478bd9Sstevel@tonic-gate 	0,			/* refcnt  */
3957c478bd9Sstevel@tonic-gate 	rsm_info,		/* get_dev_info */
3967c478bd9Sstevel@tonic-gate 	nulldev,		/* identify */
3977c478bd9Sstevel@tonic-gate 	nulldev,		/* probe */
3987c478bd9Sstevel@tonic-gate 	rsm_attach,		/* attach */
3997c478bd9Sstevel@tonic-gate 	rsm_detach,		/* detach */
4007c478bd9Sstevel@tonic-gate 	nodev,			/* reset */
4017c478bd9Sstevel@tonic-gate 	&rsm_cb_ops,		/* driver operations */
4027c478bd9Sstevel@tonic-gate 	(struct bus_ops *)0,	/* bus operations */
40319397407SSherry Moore 	0,
40419397407SSherry Moore 	ddi_quiesce_not_needed,		/* quiesce */
4057c478bd9Sstevel@tonic-gate };
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate /*
4087c478bd9Sstevel@tonic-gate  * Module linkage information for the kernel.
4097c478bd9Sstevel@tonic-gate  */
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate static struct modldrv modldrv = {
4127c478bd9Sstevel@tonic-gate 	&mod_driverops, /* Type of module.  This one is a pseudo driver */
41319397407SSherry Moore 	"Remote Shared Memory Driver",
4147c478bd9Sstevel@tonic-gate 	&rsm_ops,	/* driver ops */
4157c478bd9Sstevel@tonic-gate };
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
4187c478bd9Sstevel@tonic-gate 	MODREV_1,
4197c478bd9Sstevel@tonic-gate 	(void *)&modldrv,
4207c478bd9Sstevel@tonic-gate 	0,
4217c478bd9Sstevel@tonic-gate 	0,
4227c478bd9Sstevel@tonic-gate 	0
4237c478bd9Sstevel@tonic-gate };
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate static void rsm_dr_callback_post_add(void *arg, pgcnt_t delta);
4267c478bd9Sstevel@tonic-gate static int rsm_dr_callback_pre_del(void *arg, pgcnt_t delta);
4277c478bd9Sstevel@tonic-gate static void rsm_dr_callback_post_del(void *arg, pgcnt_t delta, int cancelled);
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate static kphysm_setup_vector_t rsm_dr_callback_vec = {
4307c478bd9Sstevel@tonic-gate 	KPHYSM_SETUP_VECTOR_VERSION,
4317c478bd9Sstevel@tonic-gate 	rsm_dr_callback_post_add,
4327c478bd9Sstevel@tonic-gate 	rsm_dr_callback_pre_del,
4337c478bd9Sstevel@tonic-gate 	rsm_dr_callback_post_del
4347c478bd9Sstevel@tonic-gate };
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate /* This flag can be changed to 0 to help with PIT testing */
4377c478bd9Sstevel@tonic-gate int rsmka_modunloadok = 1;
4387c478bd9Sstevel@tonic-gate int no_reply_cnt = 0;
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate uint64_t rsm_ctrlmsg_errcnt = 0;
4417c478bd9Sstevel@tonic-gate uint64_t rsm_ipcsend_errcnt = 0;
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate #define	MAX_NODES 64
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate static struct rsm_driver_data rsm_drv_data;
4467c478bd9Sstevel@tonic-gate static struct rsmresource_table rsm_resource;
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate static void rsmresource_insert(minor_t, rsmresource_t *, rsm_resource_type_t);
4497c478bd9Sstevel@tonic-gate static void rsmresource_destroy(void);
4507c478bd9Sstevel@tonic-gate static int rsmresource_alloc(minor_t *);
4517c478bd9Sstevel@tonic-gate static rsmresource_t *rsmresource_free(minor_t rnum);
4527c478bd9Sstevel@tonic-gate static int rsm_closeconnection(rsmseg_t *seg, void **cookie);
4537c478bd9Sstevel@tonic-gate static int rsm_unpublish(rsmseg_t *seg, int mode);
4547c478bd9Sstevel@tonic-gate static int rsm_unbind(rsmseg_t *seg);
4557c478bd9Sstevel@tonic-gate static uint_t rsmhash(rsm_memseg_id_t key);
4567c478bd9Sstevel@tonic-gate static void rsmhash_alloc(rsmhash_table_t *rhash, int size);
4577c478bd9Sstevel@tonic-gate static void rsmhash_free(rsmhash_table_t *rhash, int size);
4587c478bd9Sstevel@tonic-gate static void *rsmhash_getbkt(rsmhash_table_t *rhash, uint_t hashval);
4597c478bd9Sstevel@tonic-gate static void **rsmhash_bktaddr(rsmhash_table_t *rhash, uint_t hashval);
4607c478bd9Sstevel@tonic-gate static int rsm_send_notimporting(rsm_node_id_t dest, rsm_memseg_id_t segid,
4617c478bd9Sstevel@tonic-gate 					void *cookie);
4627c478bd9Sstevel@tonic-gate int rsm_disconnect(rsmseg_t *seg);
4637c478bd9Sstevel@tonic-gate void rsmseg_unload(rsmseg_t *);
4647c478bd9Sstevel@tonic-gate void rsm_suspend_complete(rsm_node_id_t src_node, int flag);
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate rsm_intr_hand_ret_t rsm_srv_func(rsm_controller_object_t *chd,
4677c478bd9Sstevel@tonic-gate     rsm_intr_q_op_t opcode, rsm_addr_t src,
4687c478bd9Sstevel@tonic-gate     void *data, size_t size, rsm_intr_hand_arg_t arg);
4697c478bd9Sstevel@tonic-gate 
4707c478bd9Sstevel@tonic-gate static void rsm_intr_callback(void *, rsm_addr_t, rsm_intr_hand_arg_t);
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate rsm_node_id_t my_nodeid;
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate /* cookie, va, offsets and length for the barrier */
4757c478bd9Sstevel@tonic-gate static rsm_gnum_t		*bar_va;
4767c478bd9Sstevel@tonic-gate static ddi_umem_cookie_t	bar_cookie;
4777c478bd9Sstevel@tonic-gate static off_t			barrier_offset;
4787c478bd9Sstevel@tonic-gate static size_t			barrier_size;
4797c478bd9Sstevel@tonic-gate static int			max_segs;
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate /* cookie for the trash memory */
4827c478bd9Sstevel@tonic-gate static ddi_umem_cookie_t	remap_cookie;
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate static rsm_memseg_id_t	rsm_nextavail_segmentid;
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate extern taskq_t *work_taskq;
4877c478bd9Sstevel@tonic-gate extern char *taskq_name;
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate static dev_info_t *rsm_dip;	/* private copy of devinfo pointer */
4907c478bd9Sstevel@tonic-gate 
4917c478bd9Sstevel@tonic-gate static rsmhash_table_t rsm_export_segs;		/* list of exported segs */
4927c478bd9Sstevel@tonic-gate rsmhash_table_t rsm_import_segs;		/* list of imported segs */
4937c478bd9Sstevel@tonic-gate static rsmhash_table_t rsm_event_queues;	/* list of event queues */
4947c478bd9Sstevel@tonic-gate 
4957c478bd9Sstevel@tonic-gate static	rsm_ipc_t	rsm_ipc;		/* ipc info */
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate /* list of nodes to which RSMIPC_MSG_SUSPEND has been sent */
4987c478bd9Sstevel@tonic-gate static list_head_t	rsm_suspend_list;
4997c478bd9Sstevel@tonic-gate 
5007c478bd9Sstevel@tonic-gate /* list of descriptors for remote importers */
5017c478bd9Sstevel@tonic-gate static importers_table_t importer_list;
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate kmutex_t rsm_suspend_cvlock;
5047c478bd9Sstevel@tonic-gate kcondvar_t rsm_suspend_cv;
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate static kmutex_t rsm_lock;
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate adapter_t loopback_adapter;
5097c478bd9Sstevel@tonic-gate rsm_controller_attr_t loopback_attr;
5107c478bd9Sstevel@tonic-gate 
5117c478bd9Sstevel@tonic-gate int rsmipc_send_controlmsg(path_t *path, int msgtype);
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate void rsmka_init_loopback();
5147c478bd9Sstevel@tonic-gate 
5157c478bd9Sstevel@tonic-gate int rsmka_null_seg_create(
5167c478bd9Sstevel@tonic-gate     rsm_controller_handle_t,
5177c478bd9Sstevel@tonic-gate     rsm_memseg_export_handle_t *,
5187c478bd9Sstevel@tonic-gate     size_t,
5197c478bd9Sstevel@tonic-gate     uint_t,
5207c478bd9Sstevel@tonic-gate     rsm_memory_local_t *,
5217c478bd9Sstevel@tonic-gate     rsm_resource_callback_t,
5227c478bd9Sstevel@tonic-gate     rsm_resource_callback_arg_t);
5237c478bd9Sstevel@tonic-gate 
5247c478bd9Sstevel@tonic-gate int rsmka_null_seg_destroy(
5257c478bd9Sstevel@tonic-gate     rsm_memseg_export_handle_t);
5267c478bd9Sstevel@tonic-gate 
5277c478bd9Sstevel@tonic-gate int rsmka_null_bind(
5287c478bd9Sstevel@tonic-gate     rsm_memseg_export_handle_t,
5297c478bd9Sstevel@tonic-gate     off_t,
5307c478bd9Sstevel@tonic-gate     rsm_memory_local_t *,
5317c478bd9Sstevel@tonic-gate     rsm_resource_callback_t,
5327c478bd9Sstevel@tonic-gate     rsm_resource_callback_arg_t);
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate int rsmka_null_unbind(
5357c478bd9Sstevel@tonic-gate     rsm_memseg_export_handle_t,
5367c478bd9Sstevel@tonic-gate     off_t,
5377c478bd9Sstevel@tonic-gate     size_t);
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate int rsmka_null_rebind(
5407c478bd9Sstevel@tonic-gate     rsm_memseg_export_handle_t,
5417c478bd9Sstevel@tonic-gate     off_t,
5427c478bd9Sstevel@tonic-gate     rsm_memory_local_t *,
5437c478bd9Sstevel@tonic-gate     rsm_resource_callback_t,
5447c478bd9Sstevel@tonic-gate     rsm_resource_callback_arg_t);
5457c478bd9Sstevel@tonic-gate 
5467c478bd9Sstevel@tonic-gate int rsmka_null_publish(
5477c478bd9Sstevel@tonic-gate     rsm_memseg_export_handle_t,
5487c478bd9Sstevel@tonic-gate     rsm_access_entry_t [],
5497c478bd9Sstevel@tonic-gate     uint_t,
5507c478bd9Sstevel@tonic-gate     rsm_memseg_id_t,
5517c478bd9Sstevel@tonic-gate     rsm_resource_callback_t,
5527c478bd9Sstevel@tonic-gate     rsm_resource_callback_arg_t);
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate int rsmka_null_republish(
5567c478bd9Sstevel@tonic-gate     rsm_memseg_export_handle_t,
5577c478bd9Sstevel@tonic-gate     rsm_access_entry_t [],
5587c478bd9Sstevel@tonic-gate     uint_t,
5597c478bd9Sstevel@tonic-gate     rsm_resource_callback_t,
5607c478bd9Sstevel@tonic-gate     rsm_resource_callback_arg_t);
5617c478bd9Sstevel@tonic-gate 
5627c478bd9Sstevel@tonic-gate int rsmka_null_unpublish(
5637c478bd9Sstevel@tonic-gate     rsm_memseg_export_handle_t);
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate rsm_ops_t null_rsmpi_ops;
5667c478bd9Sstevel@tonic-gate 
5677c478bd9Sstevel@tonic-gate /*
5687c478bd9Sstevel@tonic-gate  * data and locks to keep track of total amount of exported memory
5697c478bd9Sstevel@tonic-gate  */
5707c478bd9Sstevel@tonic-gate static	pgcnt_t		rsm_pgcnt;
5717c478bd9Sstevel@tonic-gate static	pgcnt_t		rsm_pgcnt_max;	/* max allowed */
5727c478bd9Sstevel@tonic-gate static	kmutex_t	rsm_pgcnt_lock;
5737c478bd9Sstevel@tonic-gate 
5747c478bd9Sstevel@tonic-gate static	int		rsm_enable_dr;
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate static	char		loopback_str[] = "loopback";
5777c478bd9Sstevel@tonic-gate 
5787c478bd9Sstevel@tonic-gate int		rsm_hash_size;
5797c478bd9Sstevel@tonic-gate 
5807c478bd9Sstevel@tonic-gate /*
5817c478bd9Sstevel@tonic-gate  * The locking model is as follows:
5827c478bd9Sstevel@tonic-gate  *
5837c478bd9Sstevel@tonic-gate  * Local operations:
5847c478bd9Sstevel@tonic-gate  *		find resource - grab reader lock on resouce list
5857c478bd9Sstevel@tonic-gate  *		insert rc     - grab writer lock
5867c478bd9Sstevel@tonic-gate  *		delete rc     - grab writer lock and resource mutex
5877c478bd9Sstevel@tonic-gate  *		read/write    - no lock
5887c478bd9Sstevel@tonic-gate  *
5897c478bd9Sstevel@tonic-gate  * Remote invocations:
5907c478bd9Sstevel@tonic-gate  *		find resource - grab read lock and resource mutex
5917c478bd9Sstevel@tonic-gate  *
5927c478bd9Sstevel@tonic-gate  * State:
5937c478bd9Sstevel@tonic-gate  *		resource state - grab resource mutex
5947c478bd9Sstevel@tonic-gate  */
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate int
_init(void)5977c478bd9Sstevel@tonic-gate _init(void)
5987c478bd9Sstevel@tonic-gate {
5997c478bd9Sstevel@tonic-gate 	int e;
6007c478bd9Sstevel@tonic-gate 
6017c478bd9Sstevel@tonic-gate 	e = mod_install(&modlinkage);
6027c478bd9Sstevel@tonic-gate 	if (e != 0) {
6037c478bd9Sstevel@tonic-gate 		return (e);
6047c478bd9Sstevel@tonic-gate 	}
6057c478bd9Sstevel@tonic-gate 
6067c478bd9Sstevel@tonic-gate 	mutex_init(&rsm_lock, NULL, MUTEX_DRIVER, NULL);
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate 	mutex_init(&rsmka_buf_lock, NULL, MUTEX_DEFAULT, NULL);
6097c478bd9Sstevel@tonic-gate 
6107c478bd9Sstevel@tonic-gate 
6117c478bd9Sstevel@tonic-gate 	rw_init(&rsm_resource.rsmrc_lock, NULL, RW_DRIVER, NULL);
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate 	rsm_hash_size = RSM_HASHSZ;
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate 	rw_init(&rsm_export_segs.rsmhash_rw, NULL, RW_DRIVER, NULL);
6167c478bd9Sstevel@tonic-gate 
6177c478bd9Sstevel@tonic-gate 	rw_init(&rsm_import_segs.rsmhash_rw, NULL, RW_DRIVER, NULL);
6187c478bd9Sstevel@tonic-gate 
6197c478bd9Sstevel@tonic-gate 	mutex_init(&importer_list.lock, NULL, MUTEX_DRIVER, NULL);
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate 	mutex_init(&rsm_ipc.lock, NULL, MUTEX_DRIVER, NULL);
6227c478bd9Sstevel@tonic-gate 	cv_init(&rsm_ipc.cv, NULL, CV_DRIVER, 0);
6237c478bd9Sstevel@tonic-gate 
6247c478bd9Sstevel@tonic-gate 	mutex_init(&rsm_suspend_cvlock, NULL, MUTEX_DRIVER, NULL);
6257c478bd9Sstevel@tonic-gate 	cv_init(&rsm_suspend_cv, NULL, CV_DRIVER, 0);
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 	mutex_init(&rsm_drv_data.drv_lock, NULL, MUTEX_DRIVER, NULL);
6287c478bd9Sstevel@tonic-gate 	cv_init(&rsm_drv_data.drv_cv, NULL, CV_DRIVER, 0);
6297c478bd9Sstevel@tonic-gate 
6307c478bd9Sstevel@tonic-gate 	rsm_ipc.count = RSMIPC_SZ;
6317c478bd9Sstevel@tonic-gate 	rsm_ipc.wanted = 0;
6327c478bd9Sstevel@tonic-gate 	rsm_ipc.sequence = 0;
6337c478bd9Sstevel@tonic-gate 
6347c478bd9Sstevel@tonic-gate 	(void) mutex_init(&rsm_pgcnt_lock, NULL, MUTEX_DRIVER, NULL);
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate 	for (e = 0; e < RSMIPC_SZ; e++) {
6377c478bd9Sstevel@tonic-gate 		rsmipc_slot_t *slot = &rsm_ipc.slots[e];
6387c478bd9Sstevel@tonic-gate 
6397c478bd9Sstevel@tonic-gate 		RSMIPC_SET(slot, RSMIPC_FREE);
6407c478bd9Sstevel@tonic-gate 		mutex_init(&slot->rsmipc_lock, NULL, MUTEX_DRIVER, NULL);
6417c478bd9Sstevel@tonic-gate 		cv_init(&slot->rsmipc_cv, NULL, CV_DRIVER, 0);
6427c478bd9Sstevel@tonic-gate 	}
6437c478bd9Sstevel@tonic-gate 
6447c478bd9Sstevel@tonic-gate 	/*
6457c478bd9Sstevel@tonic-gate 	 * Initialize the suspend message list
6467c478bd9Sstevel@tonic-gate 	 */
6477c478bd9Sstevel@tonic-gate 	rsm_suspend_list.list_head = NULL;
6487c478bd9Sstevel@tonic-gate 	mutex_init(&rsm_suspend_list.list_lock, NULL, MUTEX_DRIVER, NULL);
6497c478bd9Sstevel@tonic-gate 
6507c478bd9Sstevel@tonic-gate 	/*
6517c478bd9Sstevel@tonic-gate 	 * It is assumed here that configuration data is available
6527c478bd9Sstevel@tonic-gate 	 * during system boot since _init may be called at that time.
6537c478bd9Sstevel@tonic-gate 	 */
6547c478bd9Sstevel@tonic-gate 
6557c478bd9Sstevel@tonic-gate 	rsmka_pathmanager_init();
6567c478bd9Sstevel@tonic-gate 
6577c478bd9Sstevel@tonic-gate 	DBG_PRINTF((RSM_KERNEL_AGENT, RSM_DEBUG_VERBOSE,
6587c478bd9Sstevel@tonic-gate 	    "rsm: _init done\n"));
6597c478bd9Sstevel@tonic-gate 
6607c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
6617c478bd9Sstevel@tonic-gate 
6627c478bd9Sstevel@tonic-gate }
6637c478bd9Sstevel@tonic-gate 
6647c478bd9Sstevel@tonic-gate int
_info(struct modinfo * modinfop)6657c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
6667c478bd9Sstevel@tonic-gate {
6677c478bd9Sstevel@tonic-gate 
6687c478bd9Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
6697c478bd9Sstevel@tonic-gate }
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate int
_fini(void)6727c478bd9Sstevel@tonic-gate _fini(void)
6737c478bd9Sstevel@tonic-gate {
6747c478bd9Sstevel@tonic-gate 	int e;
6757c478bd9Sstevel@tonic-gate 
6767c478bd9Sstevel@tonic-gate 	DBG_PRINTF((RSM_KERNEL_AGENT, RSM_DEBUG_VERBOSE,
6777c478bd9Sstevel@tonic-gate 	    "rsm: _fini enter\n"));
6787c478bd9Sstevel@tonic-gate 
6797c478bd9Sstevel@tonic-gate 	/*
6807c478bd9Sstevel@tonic-gate 	 * The rsmka_modunloadok flag is simply used to help with
6817c478bd9Sstevel@tonic-gate 	 * the PIT testing. Make this flag 0 to disallow modunload.
6827c478bd9Sstevel@tonic-gate 	 */
6837c478bd9Sstevel@tonic-gate 	if (rsmka_modunloadok == 0)
6847c478bd9Sstevel@tonic-gate 		return (EBUSY);
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate 	/* rsm_detach will be called as a result of mod_remove */
6877c478bd9Sstevel@tonic-gate 	e = mod_remove(&modlinkage);
6887c478bd9Sstevel@tonic-gate 	if (e) {
6897c478bd9Sstevel@tonic-gate 		DBG_PRINTF((RSM_KERNEL_AGENT, RSM_ERR,
6907c478bd9Sstevel@tonic-gate 		    "Unable to fini RSM %x\n", e));
6917c478bd9Sstevel@tonic-gate 		return (e);
6927c478bd9Sstevel@tonic-gate 	}
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate 	rsmka_pathmanager_cleanup();
6957c478bd9Sstevel@tonic-gate 
6967c478bd9Sstevel@tonic-gate 	rw_destroy(&rsm_resource.rsmrc_lock);
6977c478bd9Sstevel@tonic-gate 
6987c478bd9Sstevel@tonic-gate 	rw_destroy(&rsm_export_segs.rsmhash_rw);
6997c478bd9Sstevel@tonic-gate 	rw_destroy(&rsm_import_segs.rsmhash_rw);
7007c478bd9Sstevel@tonic-gate 	rw_destroy(&rsm_event_queues.rsmhash_rw);
7017c478bd9Sstevel@tonic-gate 
7027c478bd9Sstevel@tonic-gate 	mutex_destroy(&importer_list.lock);
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate 	mutex_destroy(&rsm_ipc.lock);
7057c478bd9Sstevel@tonic-gate 	cv_destroy(&rsm_ipc.cv);
7067c478bd9Sstevel@tonic-gate 
7077c478bd9Sstevel@tonic-gate 	(void) mutex_destroy(&rsm_suspend_list.list_lock);
7087c478bd9Sstevel@tonic-gate 
7097c478bd9Sstevel@tonic-gate 	(void) mutex_destroy(&rsm_pgcnt_lock);
7107c478bd9Sstevel@tonic-gate 
7117c478bd9Sstevel@tonic-gate 	DBG_PRINTF((RSM_KERNEL_AGENT, RSM_DEBUG_VERBOSE, "_fini done\n"));
7127c478bd9Sstevel@tonic-gate 
7137c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
7147c478bd9Sstevel@tonic-gate 
7157c478bd9Sstevel@tonic-gate }
7167c478bd9Sstevel@tonic-gate 
7177c478bd9Sstevel@tonic-gate /*ARGSUSED1*/
7187c478bd9Sstevel@tonic-gate static int
rsm_attach(dev_info_t * devi,ddi_attach_cmd_t cmd)7197c478bd9Sstevel@tonic-gate rsm_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
7207c478bd9Sstevel@tonic-gate {
7217c478bd9Sstevel@tonic-gate 	minor_t	rnum;
7227c478bd9Sstevel@tonic-gate 	int	percent;
7237c478bd9Sstevel@tonic-gate 	int	ret;
7247c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_DDI);
7257c478bd9Sstevel@tonic-gate 
7267c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_attach enter\n"));
7277c478bd9Sstevel@tonic-gate 
7287c478bd9Sstevel@tonic-gate 	switch (cmd) {
7297c478bd9Sstevel@tonic-gate 	case DDI_ATTACH:
7307c478bd9Sstevel@tonic-gate 		break;
7317c478bd9Sstevel@tonic-gate 	case DDI_RESUME:
7327c478bd9Sstevel@tonic-gate 	default:
7337c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
7347c478bd9Sstevel@tonic-gate 		    "rsm:rsm_attach - cmd not supported\n"));
7357c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
7367c478bd9Sstevel@tonic-gate 	}
7377c478bd9Sstevel@tonic-gate 
7387c478bd9Sstevel@tonic-gate 	if (rsm_dip != NULL) {
7397c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
7407c478bd9Sstevel@tonic-gate 		    "rsm:rsm_attach - supports only "
7417c478bd9Sstevel@tonic-gate 		    "one instance\n"));
7427c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
7437c478bd9Sstevel@tonic-gate 	}
7447c478bd9Sstevel@tonic-gate 
7457c478bd9Sstevel@tonic-gate 	rsm_enable_dr = ddi_prop_get_int(DDI_DEV_T_ANY, devi,
7467c478bd9Sstevel@tonic-gate 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
7477c478bd9Sstevel@tonic-gate 	    "enable-dynamic-reconfiguration", 1);
7487c478bd9Sstevel@tonic-gate 
7497c478bd9Sstevel@tonic-gate 	mutex_enter(&rsm_drv_data.drv_lock);
7507c478bd9Sstevel@tonic-gate 	rsm_drv_data.drv_state = RSM_DRV_REG_PROCESSING;
7517c478bd9Sstevel@tonic-gate 	mutex_exit(&rsm_drv_data.drv_lock);
7527c478bd9Sstevel@tonic-gate 
7537c478bd9Sstevel@tonic-gate 	if (rsm_enable_dr) {
7547c478bd9Sstevel@tonic-gate #ifdef	RSM_DRTEST
7557c478bd9Sstevel@tonic-gate 		ret = rsm_kphysm_setup_func_register(&rsm_dr_callback_vec,
7567c478bd9Sstevel@tonic-gate 		    (void *)NULL);
7577c478bd9Sstevel@tonic-gate #else
7587c478bd9Sstevel@tonic-gate 		ret = kphysm_setup_func_register(&rsm_dr_callback_vec,
7597c478bd9Sstevel@tonic-gate 		    (void *)NULL);
7607c478bd9Sstevel@tonic-gate #endif
7617c478bd9Sstevel@tonic-gate 		if (ret != 0) {
7627c478bd9Sstevel@tonic-gate 			mutex_exit(&rsm_drv_data.drv_lock);
7637c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT, "rsm:rsm_attach - Dynamic "
7647c478bd9Sstevel@tonic-gate 			    "reconfiguration setup failed\n");
7657c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
7667c478bd9Sstevel@tonic-gate 		}
7677c478bd9Sstevel@tonic-gate 	}
7687c478bd9Sstevel@tonic-gate 
7697c478bd9Sstevel@tonic-gate 	mutex_enter(&rsm_drv_data.drv_lock);
7707c478bd9Sstevel@tonic-gate 	ASSERT(rsm_drv_data.drv_state == RSM_DRV_REG_PROCESSING);
7717c478bd9Sstevel@tonic-gate 	rsm_drv_data.drv_state = RSM_DRV_OK;
7727c478bd9Sstevel@tonic-gate 	cv_broadcast(&rsm_drv_data.drv_cv);
7737c478bd9Sstevel@tonic-gate 	mutex_exit(&rsm_drv_data.drv_lock);
7747c478bd9Sstevel@tonic-gate 
7757c478bd9Sstevel@tonic-gate 	/*
7767c478bd9Sstevel@tonic-gate 	 * page_list_read_lock();
7777c478bd9Sstevel@tonic-gate 	 * xx_setup();
7787c478bd9Sstevel@tonic-gate 	 * page_list_read_unlock();
7797c478bd9Sstevel@tonic-gate 	 */
7807c478bd9Sstevel@tonic-gate 
7817c478bd9Sstevel@tonic-gate 	rsm_hash_size = ddi_prop_get_int(DDI_DEV_T_ANY, devi,
7827c478bd9Sstevel@tonic-gate 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
7837c478bd9Sstevel@tonic-gate 	    "segment-hashtable-size", RSM_HASHSZ);
7847c478bd9Sstevel@tonic-gate 	if (rsm_hash_size == 0) {
7857c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
7867c478bd9Sstevel@tonic-gate 		    "rsm: segment-hashtable-size in rsm.conf "
7877c478bd9Sstevel@tonic-gate 		    "must be greater than 0, defaulting to 128\n"));
7887c478bd9Sstevel@tonic-gate 		rsm_hash_size = RSM_HASHSZ;
7897c478bd9Sstevel@tonic-gate 	}
7907c478bd9Sstevel@tonic-gate 
7917c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG, "rsm_attach rsm_hash_size: %d\n",
7927c478bd9Sstevel@tonic-gate 	    rsm_hash_size));
7937c478bd9Sstevel@tonic-gate 
7947c478bd9Sstevel@tonic-gate 	rsm_pgcnt = 0;
7957c478bd9Sstevel@tonic-gate 
7967c478bd9Sstevel@tonic-gate 	percent = ddi_prop_get_int(DDI_DEV_T_ANY, devi,
7977c478bd9Sstevel@tonic-gate 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
7987c478bd9Sstevel@tonic-gate 	    "max-exported-memory", 0);
7997c478bd9Sstevel@tonic-gate 	if (percent < 0) {
8007c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
8017c478bd9Sstevel@tonic-gate 		    "rsm:rsm_attach not enough memory available to "
8027c478bd9Sstevel@tonic-gate 		    "export, or max-exported-memory set incorrectly.\n"));
8037c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
8047c478bd9Sstevel@tonic-gate 	}
8057c478bd9Sstevel@tonic-gate 	/* 0 indicates no fixed upper limit. maxmem is the max	*/
8067c478bd9Sstevel@tonic-gate 	/* available pageable physical mem			*/
8077c478bd9Sstevel@tonic-gate 	rsm_pgcnt_max = (percent*maxmem)/100;
8087c478bd9Sstevel@tonic-gate 
8097c478bd9Sstevel@tonic-gate 	if (rsm_pgcnt_max > 0) {
8107c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
8117c478bd9Sstevel@tonic-gate 		    "rsm: Available physical memory = %lu pages, "
8127c478bd9Sstevel@tonic-gate 		    "Max exportable memory = %lu pages",
8137c478bd9Sstevel@tonic-gate 		    maxmem, rsm_pgcnt_max));
8147c478bd9Sstevel@tonic-gate 	}
8157c478bd9Sstevel@tonic-gate 
8167c478bd9Sstevel@tonic-gate 	/*
8177c478bd9Sstevel@tonic-gate 	 * Create minor number
8187c478bd9Sstevel@tonic-gate 	 */
8197c478bd9Sstevel@tonic-gate 	if (rsmresource_alloc(&rnum) != RSM_SUCCESS) {
8207c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
8217c478bd9Sstevel@tonic-gate 		    "rsm: rsm_attach - Unable to get "
8227c478bd9Sstevel@tonic-gate 		    "minor number\n"));
8237c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
8247c478bd9Sstevel@tonic-gate 	}
8257c478bd9Sstevel@tonic-gate 
8267c478bd9Sstevel@tonic-gate 	ASSERT(rnum == RSM_DRIVER_MINOR);
8277c478bd9Sstevel@tonic-gate 
8287c478bd9Sstevel@tonic-gate 	if (ddi_create_minor_node(devi, DRIVER_NAME, S_IFCHR,
8297c478bd9Sstevel@tonic-gate 	    rnum, DDI_PSEUDO, NULL) == DDI_FAILURE) {
8307c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
8317c478bd9Sstevel@tonic-gate 		    "rsm: rsm_attach - unable to allocate "
8327c478bd9Sstevel@tonic-gate 		    "minor #\n"));
8337c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
8347c478bd9Sstevel@tonic-gate 	}
8357c478bd9Sstevel@tonic-gate 
8367c478bd9Sstevel@tonic-gate 	rsm_dip = devi;
8377c478bd9Sstevel@tonic-gate 	/*
8387c478bd9Sstevel@tonic-gate 	 * Allocate the hashtables
8397c478bd9Sstevel@tonic-gate 	 */
8407c478bd9Sstevel@tonic-gate 	rsmhash_alloc(&rsm_export_segs, rsm_hash_size);
8417c478bd9Sstevel@tonic-gate 	rsmhash_alloc(&rsm_import_segs, rsm_hash_size);
8427c478bd9Sstevel@tonic-gate 
8437c478bd9Sstevel@tonic-gate 	importer_list.bucket = (importing_token_t **)
84419397407SSherry Moore 	    kmem_zalloc(rsm_hash_size * sizeof (importing_token_t *), KM_SLEEP);
8457c478bd9Sstevel@tonic-gate 
8467c478bd9Sstevel@tonic-gate 	/*
8477c478bd9Sstevel@tonic-gate 	 * Allocate a resource struct
8487c478bd9Sstevel@tonic-gate 	 */
8497c478bd9Sstevel@tonic-gate 	{
8507c478bd9Sstevel@tonic-gate 		rsmresource_t *p;
8517c478bd9Sstevel@tonic-gate 
8527c478bd9Sstevel@tonic-gate 		p = (rsmresource_t *)kmem_zalloc(sizeof (*p), KM_SLEEP);
8537c478bd9Sstevel@tonic-gate 
8547c478bd9Sstevel@tonic-gate 		mutex_init(&p->rsmrc_lock, NULL, MUTEX_DRIVER, (void *) NULL);
8557c478bd9Sstevel@tonic-gate 
8567c478bd9Sstevel@tonic-gate 		rsmresource_insert(rnum, p, RSM_RESOURCE_BAR);
8577c478bd9Sstevel@tonic-gate 	}
8587c478bd9Sstevel@tonic-gate 
8597c478bd9Sstevel@tonic-gate 	/*
8607c478bd9Sstevel@tonic-gate 	 * Based on the rsm.conf property max-segments, determine the maximum
8617c478bd9Sstevel@tonic-gate 	 * number of segments that can be exported/imported. This is then used
8627c478bd9Sstevel@tonic-gate 	 * to determine the size for barrier failure pages.
8637c478bd9Sstevel@tonic-gate 	 */
8647c478bd9Sstevel@tonic-gate 
8657c478bd9Sstevel@tonic-gate 	/* First get the max number of segments from the rsm.conf file */
8667c478bd9Sstevel@tonic-gate 	max_segs = ddi_prop_get_int(DDI_DEV_T_ANY, devi,
8677c478bd9Sstevel@tonic-gate 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
8687c478bd9Sstevel@tonic-gate 	    "max-segments", 0);
8697c478bd9Sstevel@tonic-gate 	if (max_segs == 0) {
8707c478bd9Sstevel@tonic-gate 		/* Use default number of segments */
8717c478bd9Sstevel@tonic-gate 		max_segs = RSM_MAX_NUM_SEG;
8727c478bd9Sstevel@tonic-gate 	}
8737c478bd9Sstevel@tonic-gate 
8747c478bd9Sstevel@tonic-gate 	/*
8757c478bd9Sstevel@tonic-gate 	 * Based on the max number of segments allowed, determine the barrier
8767c478bd9Sstevel@tonic-gate 	 * page size. add 1 to max_segs since the barrier page itself uses
8777c478bd9Sstevel@tonic-gate 	 * a slot
8787c478bd9Sstevel@tonic-gate 	 */
8797c478bd9Sstevel@tonic-gate 	barrier_size = roundup((max_segs + 1) * sizeof (rsm_gnum_t),
8807c478bd9Sstevel@tonic-gate 	    PAGESIZE);
8817c478bd9Sstevel@tonic-gate 
8827c478bd9Sstevel@tonic-gate 	/*
8837c478bd9Sstevel@tonic-gate 	 * allocation of the barrier failure page
8847c478bd9Sstevel@tonic-gate 	 */
8857c478bd9Sstevel@tonic-gate 	bar_va = (rsm_gnum_t *)ddi_umem_alloc(barrier_size,
8867c478bd9Sstevel@tonic-gate 	    DDI_UMEM_SLEEP, &bar_cookie);
8877c478bd9Sstevel@tonic-gate 
8887c478bd9Sstevel@tonic-gate 	/*
8897c478bd9Sstevel@tonic-gate 	 * Set the barrier_offset
8907c478bd9Sstevel@tonic-gate 	 */
8917c478bd9Sstevel@tonic-gate 	barrier_offset = 0;
8927c478bd9Sstevel@tonic-gate 
8937c478bd9Sstevel@tonic-gate 	/*
8947c478bd9Sstevel@tonic-gate 	 * Allocate a trash memory and get a cookie for it. This will be used
8957c478bd9Sstevel@tonic-gate 	 * when remapping segments during force disconnects. Allocate the
8967c478bd9Sstevel@tonic-gate 	 * trash memory with a large size which is page aligned.
8977c478bd9Sstevel@tonic-gate 	 */
8987c478bd9Sstevel@tonic-gate 	(void) ddi_umem_alloc((size_t)TRASHSIZE,
8997c478bd9Sstevel@tonic-gate 	    DDI_UMEM_TRASH, &remap_cookie);
9007c478bd9Sstevel@tonic-gate 
9017c478bd9Sstevel@tonic-gate 	/* initialize user segment id allocation variable */
9027c478bd9Sstevel@tonic-gate 	rsm_nextavail_segmentid = (rsm_memseg_id_t)RSM_USER_APP_ID_BASE;
9037c478bd9Sstevel@tonic-gate 
9047c478bd9Sstevel@tonic-gate 	/*
9057c478bd9Sstevel@tonic-gate 	 * initialize the null_rsmpi_ops vector and the loopback adapter
9067c478bd9Sstevel@tonic-gate 	 */
9077c478bd9Sstevel@tonic-gate 	rsmka_init_loopback();
9087c478bd9Sstevel@tonic-gate 
9097c478bd9Sstevel@tonic-gate 
9107c478bd9Sstevel@tonic-gate 	ddi_report_dev(devi);
9117c478bd9Sstevel@tonic-gate 
9127c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_attach done\n"));
9137c478bd9Sstevel@tonic-gate 
9147c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
9157c478bd9Sstevel@tonic-gate }
9167c478bd9Sstevel@tonic-gate 
9177c478bd9Sstevel@tonic-gate /*
9187c478bd9Sstevel@tonic-gate  * The call to mod_remove in the _fine routine will cause the system
9197c478bd9Sstevel@tonic-gate  * to call rsm_detach
9207c478bd9Sstevel@tonic-gate  */
9217c478bd9Sstevel@tonic-gate /*ARGSUSED*/
9227c478bd9Sstevel@tonic-gate static int
rsm_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)9237c478bd9Sstevel@tonic-gate rsm_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
9247c478bd9Sstevel@tonic-gate {
9257c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_DDI);
9267c478bd9Sstevel@tonic-gate 
9277c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_detach enter\n"));
9287c478bd9Sstevel@tonic-gate 
9297c478bd9Sstevel@tonic-gate 	switch (cmd) {
9307c478bd9Sstevel@tonic-gate 	case DDI_DETACH:
9317c478bd9Sstevel@tonic-gate 		break;
9327c478bd9Sstevel@tonic-gate 	default:
9337c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
9347c478bd9Sstevel@tonic-gate 		    "rsm:rsm_detach - cmd %x not supported\n",
9357c478bd9Sstevel@tonic-gate 		    cmd));
9367c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
9377c478bd9Sstevel@tonic-gate 	}
9387c478bd9Sstevel@tonic-gate 
9397c478bd9Sstevel@tonic-gate 	mutex_enter(&rsm_drv_data.drv_lock);
9407c478bd9Sstevel@tonic-gate 	while (rsm_drv_data.drv_state != RSM_DRV_OK)
9417c478bd9Sstevel@tonic-gate 		cv_wait(&rsm_drv_data.drv_cv, &rsm_drv_data.drv_lock);
9427c478bd9Sstevel@tonic-gate 	rsm_drv_data.drv_state = RSM_DRV_UNREG_PROCESSING;
9437c478bd9Sstevel@tonic-gate 	mutex_exit(&rsm_drv_data.drv_lock);
9447c478bd9Sstevel@tonic-gate 
9457c478bd9Sstevel@tonic-gate 	/*
9467c478bd9Sstevel@tonic-gate 	 * Unregister the DR callback functions
9477c478bd9Sstevel@tonic-gate 	 */
9487c478bd9Sstevel@tonic-gate 	if (rsm_enable_dr) {
9497c478bd9Sstevel@tonic-gate #ifdef	RSM_DRTEST
9507c478bd9Sstevel@tonic-gate 		rsm_kphysm_setup_func_unregister(&rsm_dr_callback_vec,
9517c478bd9Sstevel@tonic-gate 		    (void *)NULL);
9527c478bd9Sstevel@tonic-gate #else
9537c478bd9Sstevel@tonic-gate 		kphysm_setup_func_unregister(&rsm_dr_callback_vec,
9547c478bd9Sstevel@tonic-gate 		    (void *)NULL);
9557c478bd9Sstevel@tonic-gate #endif
9567c478bd9Sstevel@tonic-gate 	}
9577c478bd9Sstevel@tonic-gate 
9587c478bd9Sstevel@tonic-gate 	mutex_enter(&rsm_drv_data.drv_lock);
9597c478bd9Sstevel@tonic-gate 	ASSERT(rsm_drv_data.drv_state == RSM_DRV_UNREG_PROCESSING);
9607c478bd9Sstevel@tonic-gate 	rsm_drv_data.drv_state = RSM_DRV_NEW;
9617c478bd9Sstevel@tonic-gate 	mutex_exit(&rsm_drv_data.drv_lock);
9627c478bd9Sstevel@tonic-gate 
9637c478bd9Sstevel@tonic-gate 	ASSERT(rsm_suspend_list.list_head == NULL);
9647c478bd9Sstevel@tonic-gate 
9657c478bd9Sstevel@tonic-gate 	/*
9667c478bd9Sstevel@tonic-gate 	 * Release all resources, seglist, controller, ...
9677c478bd9Sstevel@tonic-gate 	 */
9687c478bd9Sstevel@tonic-gate 
9697c478bd9Sstevel@tonic-gate 	/* remove intersend queues */
9707c478bd9Sstevel@tonic-gate 	/* remove registered services */
9717c478bd9Sstevel@tonic-gate 
9727c478bd9Sstevel@tonic-gate 
9737c478bd9Sstevel@tonic-gate 	ddi_remove_minor_node(dip, DRIVER_NAME);
9747c478bd9Sstevel@tonic-gate 	rsm_dip = NULL;
9757c478bd9Sstevel@tonic-gate 
9767c478bd9Sstevel@tonic-gate 	/*
9777c478bd9Sstevel@tonic-gate 	 * Free minor zero resource
9787c478bd9Sstevel@tonic-gate 	 */
9797c478bd9Sstevel@tonic-gate 	{
9807c478bd9Sstevel@tonic-gate 		rsmresource_t *p;
9817c478bd9Sstevel@tonic-gate 
9827c478bd9Sstevel@tonic-gate 		p = rsmresource_free(RSM_DRIVER_MINOR);
9837c478bd9Sstevel@tonic-gate 		if (p) {
9847c478bd9Sstevel@tonic-gate 			mutex_destroy(&p->rsmrc_lock);
9857c478bd9Sstevel@tonic-gate 			kmem_free((void *)p, sizeof (*p));
9867c478bd9Sstevel@tonic-gate 		}
9877c478bd9Sstevel@tonic-gate 	}
9887c478bd9Sstevel@tonic-gate 
9897c478bd9Sstevel@tonic-gate 	/*
9907c478bd9Sstevel@tonic-gate 	 * Free resource table
9917c478bd9Sstevel@tonic-gate 	 */
9927c478bd9Sstevel@tonic-gate 
9937c478bd9Sstevel@tonic-gate 	rsmresource_destroy();
9947c478bd9Sstevel@tonic-gate 
9957c478bd9Sstevel@tonic-gate 	/*
9967c478bd9Sstevel@tonic-gate 	 * Free the hash tables
9977c478bd9Sstevel@tonic-gate 	 */
9987c478bd9Sstevel@tonic-gate 	rsmhash_free(&rsm_export_segs, rsm_hash_size);
9997c478bd9Sstevel@tonic-gate 	rsmhash_free(&rsm_import_segs, rsm_hash_size);
10007c478bd9Sstevel@tonic-gate 
10017c478bd9Sstevel@tonic-gate 	kmem_free((void *)importer_list.bucket,
10027c478bd9Sstevel@tonic-gate 	    rsm_hash_size * sizeof (importing_token_t *));
10037c478bd9Sstevel@tonic-gate 	importer_list.bucket = NULL;
10047c478bd9Sstevel@tonic-gate 
10057c478bd9Sstevel@tonic-gate 
10067c478bd9Sstevel@tonic-gate 	/* free barrier page */
10077c478bd9Sstevel@tonic-gate 	if (bar_cookie != NULL) {
10087c478bd9Sstevel@tonic-gate 		ddi_umem_free(bar_cookie);
10097c478bd9Sstevel@tonic-gate 	}
10107c478bd9Sstevel@tonic-gate 	bar_va = NULL;
10117c478bd9Sstevel@tonic-gate 	bar_cookie = NULL;
10127c478bd9Sstevel@tonic-gate 
10137c478bd9Sstevel@tonic-gate 	/*
10147c478bd9Sstevel@tonic-gate 	 * Free the memory allocated for the trash
10157c478bd9Sstevel@tonic-gate 	 */
10167c478bd9Sstevel@tonic-gate 	if (remap_cookie != NULL) {
10177c478bd9Sstevel@tonic-gate 		ddi_umem_free(remap_cookie);
10187c478bd9Sstevel@tonic-gate 	}
10197c478bd9Sstevel@tonic-gate 	remap_cookie = NULL;
10207c478bd9Sstevel@tonic-gate 
10217c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_detach done\n"));
10227c478bd9Sstevel@tonic-gate 
10237c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
10247c478bd9Sstevel@tonic-gate }
10257c478bd9Sstevel@tonic-gate 
10267c478bd9Sstevel@tonic-gate /*ARGSUSED*/
10277c478bd9Sstevel@tonic-gate static int
rsm_info(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)10287c478bd9Sstevel@tonic-gate rsm_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
10297c478bd9Sstevel@tonic-gate {
10307c478bd9Sstevel@tonic-gate 	register int error;
10317c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_DDI);
10327c478bd9Sstevel@tonic-gate 
10337c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_info enter\n"));
10347c478bd9Sstevel@tonic-gate 
10357c478bd9Sstevel@tonic-gate 	switch (infocmd) {
10367c478bd9Sstevel@tonic-gate 	case DDI_INFO_DEVT2DEVINFO:
10377c478bd9Sstevel@tonic-gate 		if (rsm_dip == NULL)
10387c478bd9Sstevel@tonic-gate 			error = DDI_FAILURE;
10397c478bd9Sstevel@tonic-gate 		else {
10407c478bd9Sstevel@tonic-gate 			*result = (void *)rsm_dip;
10417c478bd9Sstevel@tonic-gate 			error = DDI_SUCCESS;
10427c478bd9Sstevel@tonic-gate 		}
10437c478bd9Sstevel@tonic-gate 		break;
10447c478bd9Sstevel@tonic-gate 	case DDI_INFO_DEVT2INSTANCE:
10457c478bd9Sstevel@tonic-gate 		*result = (void *)0;
10467c478bd9Sstevel@tonic-gate 		error = DDI_SUCCESS;
10477c478bd9Sstevel@tonic-gate 		break;
10487c478bd9Sstevel@tonic-gate 	default:
10497c478bd9Sstevel@tonic-gate 		error = DDI_FAILURE;
10507c478bd9Sstevel@tonic-gate 	}
10517c478bd9Sstevel@tonic-gate 
10527c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_info done\n"));
10537c478bd9Sstevel@tonic-gate 	return (error);
10547c478bd9Sstevel@tonic-gate }
10557c478bd9Sstevel@tonic-gate 
10567c478bd9Sstevel@tonic-gate adapter_t *
rsm_getadapter(rsm_ioctlmsg_t * msg,int mode)10577c478bd9Sstevel@tonic-gate rsm_getadapter(rsm_ioctlmsg_t *msg, int mode)
10587c478bd9Sstevel@tonic-gate {
10597c478bd9Sstevel@tonic-gate 	adapter_t *adapter;
10607c478bd9Sstevel@tonic-gate 	char adapter_devname[MAXNAMELEN];
10617c478bd9Sstevel@tonic-gate 	int instance;
10627c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category,
10637c478bd9Sstevel@tonic-gate 	    RSM_KERNEL_AGENT | RSM_IMPORT | RSM_EXPORT | RSM_IOCTL);
10647c478bd9Sstevel@tonic-gate 
10657c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_getadapter enter\n"));
10667c478bd9Sstevel@tonic-gate 
10677c478bd9Sstevel@tonic-gate 	instance = msg->cnum;
10687c478bd9Sstevel@tonic-gate 
10697c478bd9Sstevel@tonic-gate 	if ((msg->cname_len <= 0) || (msg->cname_len > MAXNAMELEN)) {
10707c478bd9Sstevel@tonic-gate 		return (NULL);
10717c478bd9Sstevel@tonic-gate 	}
10727c478bd9Sstevel@tonic-gate 
10737c478bd9Sstevel@tonic-gate 	if (ddi_copyin(msg->cname, adapter_devname, msg->cname_len, mode))
10747c478bd9Sstevel@tonic-gate 		return (NULL);
10757c478bd9Sstevel@tonic-gate 
10767c478bd9Sstevel@tonic-gate 	if (strcmp(adapter_devname, "loopback") == 0)
10777c478bd9Sstevel@tonic-gate 		return (&loopback_adapter);
10787c478bd9Sstevel@tonic-gate 
10797c478bd9Sstevel@tonic-gate 	adapter = rsmka_lookup_adapter(adapter_devname, instance);
10807c478bd9Sstevel@tonic-gate 
10817c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_getadapter done\n"));
10827c478bd9Sstevel@tonic-gate 
10837c478bd9Sstevel@tonic-gate 	return (adapter);
10847c478bd9Sstevel@tonic-gate }
10857c478bd9Sstevel@tonic-gate 
10867c478bd9Sstevel@tonic-gate 
10877c478bd9Sstevel@tonic-gate /*
10887c478bd9Sstevel@tonic-gate  * *********************** Resource Number Management ********************
10897c478bd9Sstevel@tonic-gate  * All resources are stored in a simple hash table. The table is an array
10907c478bd9Sstevel@tonic-gate  * of pointers to resource blks. Each blk contains:
10917c478bd9Sstevel@tonic-gate  *	base	- base number of this blk
10927c478bd9Sstevel@tonic-gate  *	used	- number of used slots in this blk.
10937c478bd9Sstevel@tonic-gate  *	blks    - array of pointers to resource items.
10947c478bd9Sstevel@tonic-gate  * An entry in a resource blk is empty if it's NULL.
10957c478bd9Sstevel@tonic-gate  *
10967c478bd9Sstevel@tonic-gate  * We start with no resource array. Each time we run out of slots, we
10977c478bd9Sstevel@tonic-gate  * reallocate a new larger array and copy the pointer to the new array and
10987c478bd9Sstevel@tonic-gate  * a new resource blk is allocated and added to the hash table.
10997c478bd9Sstevel@tonic-gate  *
11007c478bd9Sstevel@tonic-gate  * The resource control block contains:
11017c478bd9Sstevel@tonic-gate  *      root    - array of pointer of resource blks
11027c478bd9Sstevel@tonic-gate  *      sz      - current size of array.
11037c478bd9Sstevel@tonic-gate  *      len     - last valid entry in array.
11047c478bd9Sstevel@tonic-gate  *
11057c478bd9Sstevel@tonic-gate  * A search operation based on a resource number is as follows:
11067c478bd9Sstevel@tonic-gate  *      index = rnum / RESOURCE_BLKSZ;
11077c478bd9Sstevel@tonic-gate  *      ASSERT(index < resource_block.len);
11087c478bd9Sstevel@tonic-gate  *      ASSERT(index < resource_block.sz);
11097c478bd9Sstevel@tonic-gate  *	offset = rnum % RESOURCE_BLKSZ;
11107c478bd9Sstevel@tonic-gate  *      ASSERT(offset >= resource_block.root[index]->base);
11117c478bd9Sstevel@tonic-gate  *	ASSERT(offset < resource_block.root[index]->base + RESOURCE_BLKSZ);
11127c478bd9Sstevel@tonic-gate  *	return resource_block.root[index]->blks[offset];
11137c478bd9Sstevel@tonic-gate  *
11147c478bd9Sstevel@tonic-gate  * A resource blk is freed with its used count reachs zero.
11157c478bd9Sstevel@tonic-gate  */
11167c478bd9Sstevel@tonic-gate static int
rsmresource_alloc(minor_t * rnum)11177c478bd9Sstevel@tonic-gate rsmresource_alloc(minor_t *rnum)
11187c478bd9Sstevel@tonic-gate {
11197c478bd9Sstevel@tonic-gate 
11207c478bd9Sstevel@tonic-gate 	/* search for available resource slot */
11217c478bd9Sstevel@tonic-gate 	int i, j, empty = -1;
11227c478bd9Sstevel@tonic-gate 	rsmresource_blk_t *blk;
11237c478bd9Sstevel@tonic-gate 
11247c478bd9Sstevel@tonic-gate 	DBG_PRINTF((RSM_KERNEL_ALL, RSM_DEBUG_VERBOSE,
11257c478bd9Sstevel@tonic-gate 	    "rsmresource_alloc enter\n"));
11267c478bd9Sstevel@tonic-gate 
11277c478bd9Sstevel@tonic-gate 	rw_enter(&rsm_resource.rsmrc_lock, RW_WRITER);
11287c478bd9Sstevel@tonic-gate 
11297c478bd9Sstevel@tonic-gate 	/* Try to find an empty slot */
11307c478bd9Sstevel@tonic-gate 	for (i = 0; i < rsm_resource.rsmrc_len; i++) {
11317c478bd9Sstevel@tonic-gate 		blk = rsm_resource.rsmrc_root[i];
11327c478bd9Sstevel@tonic-gate 		if (blk != NULL && blk->rsmrcblk_avail > 0) {
11337c478bd9Sstevel@tonic-gate 			/* found an empty slot in this blk */
11347c478bd9Sstevel@tonic-gate 			for (j = 0; j < RSMRC_BLKSZ; j++) {
11357c478bd9Sstevel@tonic-gate 				if (blk->rsmrcblk_blks[j] == NULL) {
11367c478bd9Sstevel@tonic-gate 					*rnum = (minor_t)
11377c478bd9Sstevel@tonic-gate 					    (j + (i * RSMRC_BLKSZ));
11387c478bd9Sstevel@tonic-gate 					/*
11397c478bd9Sstevel@tonic-gate 					 * obey gen page limits
11407c478bd9Sstevel@tonic-gate 					 */
11417c478bd9Sstevel@tonic-gate 					if (*rnum >= max_segs + 1) {
11427c478bd9Sstevel@tonic-gate 						if (empty < 0) {
11437c478bd9Sstevel@tonic-gate 							rw_exit(&rsm_resource.
11447c478bd9Sstevel@tonic-gate 							    rsmrc_lock);
11457c478bd9Sstevel@tonic-gate 							DBG_PRINTF((
11467c478bd9Sstevel@tonic-gate 							    RSM_KERNEL_ALL,
11477c478bd9Sstevel@tonic-gate 							    RSM_ERR,
11487c478bd9Sstevel@tonic-gate 							    "rsmresource"
11497c478bd9Sstevel@tonic-gate 							    "_alloc failed:"
11507c478bd9Sstevel@tonic-gate 							    "not enough res"
11517c478bd9Sstevel@tonic-gate 							    "%d\n", *rnum));
115219397407SSherry Moore 					return (RSMERR_INSUFFICIENT_RESOURCES);
11537c478bd9Sstevel@tonic-gate 						} else {
11547c478bd9Sstevel@tonic-gate 							/* use empty slot */
11557c478bd9Sstevel@tonic-gate 							break;
11567c478bd9Sstevel@tonic-gate 						}
11577c478bd9Sstevel@tonic-gate 
11587c478bd9Sstevel@tonic-gate 					}
11597c478bd9Sstevel@tonic-gate 
11607c478bd9Sstevel@tonic-gate 					blk->rsmrcblk_blks[j] = RSMRC_RESERVED;
11617c478bd9Sstevel@tonic-gate 					blk->rsmrcblk_avail--;
11627c478bd9Sstevel@tonic-gate 					rw_exit(&rsm_resource.rsmrc_lock);
11637c478bd9Sstevel@tonic-gate 					DBG_PRINTF((RSM_KERNEL_ALL,
11647c478bd9Sstevel@tonic-gate 					    RSM_DEBUG_VERBOSE,
11657c478bd9Sstevel@tonic-gate 					    "rsmresource_alloc done\n"));
11667c478bd9Sstevel@tonic-gate 					return (RSM_SUCCESS);
11677c478bd9Sstevel@tonic-gate 				}
11687c478bd9Sstevel@tonic-gate 			}
11697c478bd9Sstevel@tonic-gate 		} else if (blk == NULL && empty < 0) {
11707c478bd9Sstevel@tonic-gate 			/* remember first empty slot */
11717c478bd9Sstevel@tonic-gate 			empty = i;
11727c478bd9Sstevel@tonic-gate 		}
11737c478bd9Sstevel@tonic-gate 	}
11747c478bd9Sstevel@tonic-gate 
11757c478bd9Sstevel@tonic-gate 	/* Couldn't find anything, allocate a new blk */
11767c478bd9Sstevel@tonic-gate 	/*
11777c478bd9Sstevel@tonic-gate 	 * Do we need to reallocate the root array
11787c478bd9Sstevel@tonic-gate 	 */
11797c478bd9Sstevel@tonic-gate 	if (empty < 0) {
11807c478bd9Sstevel@tonic-gate 		if (rsm_resource.rsmrc_len == rsm_resource.rsmrc_sz) {
11817c478bd9Sstevel@tonic-gate 			/*
11827c478bd9Sstevel@tonic-gate 			 * Allocate new array and copy current stuff into it
11837c478bd9Sstevel@tonic-gate 			 */
11847c478bd9Sstevel@tonic-gate 			rsmresource_blk_t	**p;
11857c478bd9Sstevel@tonic-gate 			uint_t newsz = (uint_t)rsm_resource.rsmrc_sz +
11867c478bd9Sstevel@tonic-gate 			    RSMRC_BLKSZ;
11877c478bd9Sstevel@tonic-gate 			/*
11887c478bd9Sstevel@tonic-gate 			 * Don't allocate more that max valid rnum
11897c478bd9Sstevel@tonic-gate 			 */
11907c478bd9Sstevel@tonic-gate 			if (rsm_resource.rsmrc_len*RSMRC_BLKSZ >=
11917c478bd9Sstevel@tonic-gate 			    max_segs + 1) {
11927c478bd9Sstevel@tonic-gate 				rw_exit(&rsm_resource.rsmrc_lock);
11937c478bd9Sstevel@tonic-gate 				return (RSMERR_INSUFFICIENT_RESOURCES);
11947c478bd9Sstevel@tonic-gate 			}
11957c478bd9Sstevel@tonic-gate 
11967c478bd9Sstevel@tonic-gate 			p = (rsmresource_blk_t **)kmem_zalloc(
11977c478bd9Sstevel@tonic-gate 			    newsz * sizeof (*p),
11987c478bd9Sstevel@tonic-gate 			    KM_SLEEP);
11997c478bd9Sstevel@tonic-gate 
12007c478bd9Sstevel@tonic-gate 			if (rsm_resource.rsmrc_root) {
12017c478bd9Sstevel@tonic-gate 				uint_t oldsz;
12027c478bd9Sstevel@tonic-gate 
12037c478bd9Sstevel@tonic-gate 				oldsz = (uint_t)(rsm_resource.rsmrc_sz *
12047c478bd9Sstevel@tonic-gate 				    (int)sizeof (*p));
12057c478bd9Sstevel@tonic-gate 
12067c478bd9Sstevel@tonic-gate 				/*
12077c478bd9Sstevel@tonic-gate 				 * Copy old data into new space and
12087c478bd9Sstevel@tonic-gate 				 * free old stuff
12097c478bd9Sstevel@tonic-gate 				 */
12107c478bd9Sstevel@tonic-gate 				bcopy(rsm_resource.rsmrc_root, p, oldsz);
12117c478bd9Sstevel@tonic-gate 				kmem_free(rsm_resource.rsmrc_root, oldsz);
12127c478bd9Sstevel@tonic-gate 			}
12137c478bd9Sstevel@tonic-gate 
12147c478bd9Sstevel@tonic-gate 			rsm_resource.rsmrc_root = p;
12157c478bd9Sstevel@tonic-gate 			rsm_resource.rsmrc_sz = (int)newsz;
12167c478bd9Sstevel@tonic-gate 		}
12177c478bd9Sstevel@tonic-gate 
12187c478bd9Sstevel@tonic-gate 		empty = rsm_resource.rsmrc_len;
12197c478bd9Sstevel@tonic-gate 		rsm_resource.rsmrc_len++;
12207c478bd9Sstevel@tonic-gate 	}
12217c478bd9Sstevel@tonic-gate 
12227c478bd9Sstevel@tonic-gate 	/*
12237c478bd9Sstevel@tonic-gate 	 * Allocate a new blk
12247c478bd9Sstevel@tonic-gate 	 */
12257c478bd9Sstevel@tonic-gate 	blk = (rsmresource_blk_t *)kmem_zalloc(sizeof (*blk), KM_SLEEP);
12267c478bd9Sstevel@tonic-gate 	ASSERT(rsm_resource.rsmrc_root[empty] == NULL);
12277c478bd9Sstevel@tonic-gate 	rsm_resource.rsmrc_root[empty] = blk;
12287c478bd9Sstevel@tonic-gate 	blk->rsmrcblk_avail = RSMRC_BLKSZ - 1;
12297c478bd9Sstevel@tonic-gate 
12307c478bd9Sstevel@tonic-gate 	/*
12317c478bd9Sstevel@tonic-gate 	 * Allocate slot
12327c478bd9Sstevel@tonic-gate 	 */
12337c478bd9Sstevel@tonic-gate 
12347c478bd9Sstevel@tonic-gate 	*rnum = (minor_t)(empty * RSMRC_BLKSZ);
12357c478bd9Sstevel@tonic-gate 
12367c478bd9Sstevel@tonic-gate 	/*
12377c478bd9Sstevel@tonic-gate 	 * watch out not to exceed bounds of barrier page
12387c478bd9Sstevel@tonic-gate 	 */
12397c478bd9Sstevel@tonic-gate 	if (*rnum >= max_segs + 1) {
12407c478bd9Sstevel@tonic-gate 		rw_exit(&rsm_resource.rsmrc_lock);
12417c478bd9Sstevel@tonic-gate 		DBG_PRINTF((RSM_KERNEL_ALL, RSM_ERR,
12427c478bd9Sstevel@tonic-gate 		    "rsmresource_alloc failed %d\n", *rnum));
12437c478bd9Sstevel@tonic-gate 
12447c478bd9Sstevel@tonic-gate 		return (RSMERR_INSUFFICIENT_RESOURCES);
12457c478bd9Sstevel@tonic-gate 	}
12467c478bd9Sstevel@tonic-gate 	blk->rsmrcblk_blks[0] = RSMRC_RESERVED;
12477c478bd9Sstevel@tonic-gate 
12487c478bd9Sstevel@tonic-gate 
12497c478bd9Sstevel@tonic-gate 	rw_exit(&rsm_resource.rsmrc_lock);
12507c478bd9Sstevel@tonic-gate 
12517c478bd9Sstevel@tonic-gate 	DBG_PRINTF((RSM_KERNEL_ALL, RSM_DEBUG_VERBOSE,
12527c478bd9Sstevel@tonic-gate 	    "rsmresource_alloc done\n"));
12537c478bd9Sstevel@tonic-gate 
12547c478bd9Sstevel@tonic-gate 	return (RSM_SUCCESS);
12557c478bd9Sstevel@tonic-gate }
12567c478bd9Sstevel@tonic-gate 
12577c478bd9Sstevel@tonic-gate static rsmresource_t *
rsmresource_free(minor_t rnum)12587c478bd9Sstevel@tonic-gate rsmresource_free(minor_t rnum)
12597c478bd9Sstevel@tonic-gate {
12607c478bd9Sstevel@tonic-gate 
12617c478bd9Sstevel@tonic-gate 	/* search for available resource slot */
12627c478bd9Sstevel@tonic-gate 	int i, j;
12637c478bd9Sstevel@tonic-gate 	rsmresource_blk_t *blk;
12647c478bd9Sstevel@tonic-gate 	rsmresource_t *p;
12657c478bd9Sstevel@tonic-gate 
12667c478bd9Sstevel@tonic-gate 	DBG_PRINTF((RSM_KERNEL_ALL, RSM_DEBUG_VERBOSE,
12677c478bd9Sstevel@tonic-gate 	    "rsmresource_free enter\n"));
12687c478bd9Sstevel@tonic-gate 
12697c478bd9Sstevel@tonic-gate 	i = (int)(rnum / RSMRC_BLKSZ);
12707c478bd9Sstevel@tonic-gate 	j = (int)(rnum % RSMRC_BLKSZ);
12717c478bd9Sstevel@tonic-gate 
12727c478bd9Sstevel@tonic-gate 	if (i >= rsm_resource.rsmrc_len) {
12737c478bd9Sstevel@tonic-gate 		DBG_PRINTF((RSM_KERNEL_ALL, RSM_DEBUG_VERBOSE,
12747c478bd9Sstevel@tonic-gate 		    "rsmresource_free done\n"));
12757c478bd9Sstevel@tonic-gate 		return (NULL);
12767c478bd9Sstevel@tonic-gate 	}
12777c478bd9Sstevel@tonic-gate 
12787c478bd9Sstevel@tonic-gate 	rw_enter(&rsm_resource.rsmrc_lock, RW_WRITER);
12797c478bd9Sstevel@tonic-gate 
12807c478bd9Sstevel@tonic-gate 	ASSERT(rsm_resource.rsmrc_root);
12817c478bd9Sstevel@tonic-gate 	ASSERT(i < rsm_resource.rsmrc_len);
12827c478bd9Sstevel@tonic-gate 	ASSERT(i < rsm_resource.rsmrc_sz);
12837c478bd9Sstevel@tonic-gate 	blk = rsm_resource.rsmrc_root[i];
12847c478bd9Sstevel@tonic-gate 	if (blk == NULL) {
12857c478bd9Sstevel@tonic-gate 		rw_exit(&rsm_resource.rsmrc_lock);
12867c478bd9Sstevel@tonic-gate 		DBG_PRINTF((RSM_KERNEL_ALL, RSM_DEBUG_VERBOSE,
12877c478bd9Sstevel@tonic-gate 		    "rsmresource_free done\n"));
12887c478bd9Sstevel@tonic-gate 		return (NULL);
12897c478bd9Sstevel@tonic-gate 	}
12907c478bd9Sstevel@tonic-gate 
12917c478bd9Sstevel@tonic-gate 	ASSERT(blk->rsmrcblk_blks[j]); /* reserved or full */
12927c478bd9Sstevel@tonic-gate 
12937c478bd9Sstevel@tonic-gate 	p = blk->rsmrcblk_blks[j];
12947c478bd9Sstevel@tonic-gate 	if (p == RSMRC_RESERVED) {
12957c478bd9Sstevel@tonic-gate 		p = NULL;
12967c478bd9Sstevel@tonic-gate 	}
12977c478bd9Sstevel@tonic-gate 
12987c478bd9Sstevel@tonic-gate 	blk->rsmrcblk_blks[j] = NULL;
12997c478bd9Sstevel@tonic-gate 	blk->rsmrcblk_avail++;
13007c478bd9Sstevel@tonic-gate 	if (blk->rsmrcblk_avail == RSMRC_BLKSZ) {
13017c478bd9Sstevel@tonic-gate 		/* free this blk */
13027c478bd9Sstevel@tonic-gate 		kmem_free(blk, sizeof (*blk));
13037c478bd9Sstevel@tonic-gate 		rsm_resource.rsmrc_root[i] = NULL;
13047c478bd9Sstevel@tonic-gate 	}
13057c478bd9Sstevel@tonic-gate 
13067c478bd9Sstevel@tonic-gate 	rw_exit(&rsm_resource.rsmrc_lock);
13077c478bd9Sstevel@tonic-gate 
13087c478bd9Sstevel@tonic-gate 	DBG_PRINTF((RSM_KERNEL_ALL, RSM_DEBUG_VERBOSE,
13097c478bd9Sstevel@tonic-gate 	    "rsmresource_free done\n"));
13107c478bd9Sstevel@tonic-gate 
13117c478bd9Sstevel@tonic-gate 	return (p);
13127c478bd9Sstevel@tonic-gate }
13137c478bd9Sstevel@tonic-gate 
13147c478bd9Sstevel@tonic-gate static rsmresource_t *
rsmresource_lookup(minor_t rnum,int lock)13157c478bd9Sstevel@tonic-gate rsmresource_lookup(minor_t rnum, int lock)
13167c478bd9Sstevel@tonic-gate {
13177c478bd9Sstevel@tonic-gate 	int i, j;
13187c478bd9Sstevel@tonic-gate 	rsmresource_blk_t *blk;
13197c478bd9Sstevel@tonic-gate 	rsmresource_t *p;
13207c478bd9Sstevel@tonic-gate 
13217c478bd9Sstevel@tonic-gate 	DBG_PRINTF((RSM_KERNEL_ALL, RSM_DEBUG_VERBOSE,
13227c478bd9Sstevel@tonic-gate 	    "rsmresource_lookup enter\n"));
13237c478bd9Sstevel@tonic-gate 
13247c478bd9Sstevel@tonic-gate 	/* Find resource and lock it in READER mode */
13257c478bd9Sstevel@tonic-gate 	/* search for available resource slot */
13267c478bd9Sstevel@tonic-gate 
13277c478bd9Sstevel@tonic-gate 	i = (int)(rnum / RSMRC_BLKSZ);
13287c478bd9Sstevel@tonic-gate 	j = (int)(rnum % RSMRC_BLKSZ);
13297c478bd9Sstevel@tonic-gate 
13307c478bd9Sstevel@tonic-gate 	if (i >= rsm_resource.rsmrc_len) {
13317c478bd9Sstevel@tonic-gate 		DBG_PRINTF((RSM_KERNEL_ALL, RSM_DEBUG_VERBOSE,
13327c478bd9Sstevel@tonic-gate 		    "rsmresource_lookup done\n"));
13337c478bd9Sstevel@tonic-gate 		return (NULL);
13347c478bd9Sstevel@tonic-gate 	}
13357c478bd9Sstevel@tonic-gate 
13367c478bd9Sstevel@tonic-gate 	rw_enter(&rsm_resource.rsmrc_lock, RW_READER);
13377c478bd9Sstevel@tonic-gate 
13387c478bd9Sstevel@tonic-gate 	blk = rsm_resource.rsmrc_root[i];
13397c478bd9Sstevel@tonic-gate 	if (blk != NULL) {
13407c478bd9Sstevel@tonic-gate 		ASSERT(i < rsm_resource.rsmrc_len);
13417c478bd9Sstevel@tonic-gate 		ASSERT(i < rsm_resource.rsmrc_sz);
13427c478bd9Sstevel@tonic-gate 
13437c478bd9Sstevel@tonic-gate 		p = blk->rsmrcblk_blks[j];
13447c478bd9Sstevel@tonic-gate 		if (lock == RSM_LOCK) {
13457c478bd9Sstevel@tonic-gate 			if (p != RSMRC_RESERVED) {
13467c478bd9Sstevel@tonic-gate 				mutex_enter(&p->rsmrc_lock);
13477c478bd9Sstevel@tonic-gate 			} else {
13487c478bd9Sstevel@tonic-gate 				p = NULL;
13497c478bd9Sstevel@tonic-gate 			}
13507c478bd9Sstevel@tonic-gate 		}
13517c478bd9Sstevel@tonic-gate 	} else {
13527c478bd9Sstevel@tonic-gate 		p = NULL;
13537c478bd9Sstevel@tonic-gate 	}
13547c478bd9Sstevel@tonic-gate 	rw_exit(&rsm_resource.rsmrc_lock);
13557c478bd9Sstevel@tonic-gate 
13567c478bd9Sstevel@tonic-gate 	DBG_PRINTF((RSM_KERNEL_ALL, RSM_DEBUG_VERBOSE,
13577c478bd9Sstevel@tonic-gate 	    "rsmresource_lookup done\n"));
13587c478bd9Sstevel@tonic-gate 
13597c478bd9Sstevel@tonic-gate 	return (p);
13607c478bd9Sstevel@tonic-gate }
13617c478bd9Sstevel@tonic-gate 
13627c478bd9Sstevel@tonic-gate static void
rsmresource_insert(minor_t rnum,rsmresource_t * p,rsm_resource_type_t type)13637c478bd9Sstevel@tonic-gate rsmresource_insert(minor_t rnum, rsmresource_t *p, rsm_resource_type_t type)
13647c478bd9Sstevel@tonic-gate {
13657c478bd9Sstevel@tonic-gate 	/* Find resource and lock it in READER mode */
13667c478bd9Sstevel@tonic-gate 	/* Caller can upgrade if need be */
13677c478bd9Sstevel@tonic-gate 	/* search for available resource slot */
13687c478bd9Sstevel@tonic-gate 	int i, j;
13697c478bd9Sstevel@tonic-gate 	rsmresource_blk_t *blk;
13707c478bd9Sstevel@tonic-gate 
13717c478bd9Sstevel@tonic-gate 	DBG_PRINTF((RSM_KERNEL_ALL, RSM_DEBUG_VERBOSE,
13727c478bd9Sstevel@tonic-gate 	    "rsmresource_insert enter\n"));
13737c478bd9Sstevel@tonic-gate 
13747c478bd9Sstevel@tonic-gate 	i = (int)(rnum / RSMRC_BLKSZ);
13757c478bd9Sstevel@tonic-gate 	j = (int)(rnum % RSMRC_BLKSZ);
13767c478bd9Sstevel@tonic-gate 
13777c478bd9Sstevel@tonic-gate 	p->rsmrc_type = type;
13787c478bd9Sstevel@tonic-gate 	p->rsmrc_num = rnum;
13797c478bd9Sstevel@tonic-gate 
13807c478bd9Sstevel@tonic-gate 	rw_enter(&rsm_resource.rsmrc_lock, RW_READER);
13817c478bd9Sstevel@tonic-gate 
13827c478bd9Sstevel@tonic-gate 	ASSERT(rsm_resource.rsmrc_root);
13837c478bd9Sstevel@tonic-gate 	ASSERT(i < rsm_resource.rsmrc_len);
13847c478bd9Sstevel@tonic-gate 	ASSERT(i < rsm_resource.rsmrc_sz);
13857c478bd9Sstevel@tonic-gate 
13867c478bd9Sstevel@tonic-gate 	blk = rsm_resource.rsmrc_root[i];
13877c478bd9Sstevel@tonic-gate 	ASSERT(blk);
13887c478bd9Sstevel@tonic-gate 
13897c478bd9Sstevel@tonic-gate 	ASSERT(blk->rsmrcblk_blks[j] == RSMRC_RESERVED);
13907c478bd9Sstevel@tonic-gate 
13917c478bd9Sstevel@tonic-gate 	blk->rsmrcblk_blks[j] = p;
13927c478bd9Sstevel@tonic-gate 
13937c478bd9Sstevel@tonic-gate 	DBG_PRINTF((RSM_KERNEL_ALL, RSM_DEBUG_VERBOSE,
13947c478bd9Sstevel@tonic-gate 	    "rsmresource_insert done\n"));
13957c478bd9Sstevel@tonic-gate 
13967c478bd9Sstevel@tonic-gate 	rw_exit(&rsm_resource.rsmrc_lock);
13977c478bd9Sstevel@tonic-gate }
13987c478bd9Sstevel@tonic-gate 
13997c478bd9Sstevel@tonic-gate static void
rsmresource_destroy()14007c478bd9Sstevel@tonic-gate rsmresource_destroy()
14017c478bd9Sstevel@tonic-gate {
14027c478bd9Sstevel@tonic-gate 	int i, j;
14037c478bd9Sstevel@tonic-gate 
14047c478bd9Sstevel@tonic-gate 	DBG_PRINTF((RSM_KERNEL_ALL, RSM_DEBUG_VERBOSE,
14057c478bd9Sstevel@tonic-gate 	    "rsmresource_destroy enter\n"));
14067c478bd9Sstevel@tonic-gate 
14077c478bd9Sstevel@tonic-gate 	rw_enter(&rsm_resource.rsmrc_lock, RW_WRITER);
14087c478bd9Sstevel@tonic-gate 
14097c478bd9Sstevel@tonic-gate 	for (i = 0; i < rsm_resource.rsmrc_len; i++) {
14107c478bd9Sstevel@tonic-gate 		rsmresource_blk_t	*blk;
14117c478bd9Sstevel@tonic-gate 
14127c478bd9Sstevel@tonic-gate 		blk = rsm_resource.rsmrc_root[i];
14137c478bd9Sstevel@tonic-gate 		if (blk == NULL) {
14147c478bd9Sstevel@tonic-gate 			continue;
14157c478bd9Sstevel@tonic-gate 		}
14167c478bd9Sstevel@tonic-gate 		for (j = 0; j < RSMRC_BLKSZ; j++) {
14177c478bd9Sstevel@tonic-gate 			if (blk->rsmrcblk_blks[j] != NULL) {
14187c478bd9Sstevel@tonic-gate 				DBG_PRINTF((RSM_KERNEL_ALL, RSM_DEBUG_VERBOSE,
14197c478bd9Sstevel@tonic-gate 				    "Not null slot %d, %lx\n", j,
14207c478bd9Sstevel@tonic-gate 				    (size_t)blk->rsmrcblk_blks[j]));
14217c478bd9Sstevel@tonic-gate 			}
14227c478bd9Sstevel@tonic-gate 		}
14237c478bd9Sstevel@tonic-gate 		kmem_free(blk, sizeof (*blk));
14247c478bd9Sstevel@tonic-gate 		rsm_resource.rsmrc_root[i] = NULL;
14257c478bd9Sstevel@tonic-gate 	}
14267c478bd9Sstevel@tonic-gate 	if (rsm_resource.rsmrc_root) {
14277c478bd9Sstevel@tonic-gate 		i = rsm_resource.rsmrc_sz * (int)sizeof (rsmresource_blk_t *);
14287c478bd9Sstevel@tonic-gate 		kmem_free(rsm_resource.rsmrc_root, (uint_t)i);
14297c478bd9Sstevel@tonic-gate 		rsm_resource.rsmrc_root = NULL;
14307c478bd9Sstevel@tonic-gate 		rsm_resource.rsmrc_len = 0;
14317c478bd9Sstevel@tonic-gate 		rsm_resource.rsmrc_sz = 0;
14327c478bd9Sstevel@tonic-gate 	}
14337c478bd9Sstevel@tonic-gate 
14347c478bd9Sstevel@tonic-gate 	DBG_PRINTF((RSM_KERNEL_ALL, RSM_DEBUG_VERBOSE,
14357c478bd9Sstevel@tonic-gate 	    "rsmresource_destroy done\n"));
14367c478bd9Sstevel@tonic-gate 
14377c478bd9Sstevel@tonic-gate 	rw_exit(&rsm_resource.rsmrc_lock);
14387c478bd9Sstevel@tonic-gate }
14397c478bd9Sstevel@tonic-gate 
14407c478bd9Sstevel@tonic-gate 
14417c478bd9Sstevel@tonic-gate /* ******************** Generic Key Hash Table Management ********* */
14427c478bd9Sstevel@tonic-gate static rsmresource_t *
rsmhash_lookup(rsmhash_table_t * rhash,rsm_memseg_id_t key,rsm_resource_state_t state)14437c478bd9Sstevel@tonic-gate rsmhash_lookup(rsmhash_table_t *rhash, rsm_memseg_id_t key,
14447c478bd9Sstevel@tonic-gate     rsm_resource_state_t state)
14457c478bd9Sstevel@tonic-gate {
14467c478bd9Sstevel@tonic-gate 	rsmresource_t	*p;
14477c478bd9Sstevel@tonic-gate 	uint_t		hashval;
14487c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL);
14497c478bd9Sstevel@tonic-gate 
14507c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmhash_lookup enter\n"));
14517c478bd9Sstevel@tonic-gate 
14527c478bd9Sstevel@tonic-gate 	hashval = rsmhash(key);
14537c478bd9Sstevel@tonic-gate 
14547c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_LVL2, "rsmhash_lookup %u=%d\n",
14557c478bd9Sstevel@tonic-gate 	    key, hashval));
14567c478bd9Sstevel@tonic-gate 
14577c478bd9Sstevel@tonic-gate 	rw_enter(&rhash->rsmhash_rw, RW_READER);
14587c478bd9Sstevel@tonic-gate 
14597c478bd9Sstevel@tonic-gate 	p = (rsmresource_t *)rsmhash_getbkt(rhash, hashval);
14607c478bd9Sstevel@tonic-gate 
14617c478bd9Sstevel@tonic-gate 	for (; p; p = p->rsmrc_next) {
14627c478bd9Sstevel@tonic-gate 		if (p->rsmrc_key == key) {
14637c478bd9Sstevel@tonic-gate 			/* acquire resource lock */
14647c478bd9Sstevel@tonic-gate 			RSMRC_LOCK(p);
14657c478bd9Sstevel@tonic-gate 			break;
14667c478bd9Sstevel@tonic-gate 		}
14677c478bd9Sstevel@tonic-gate 	}
14687c478bd9Sstevel@tonic-gate 
14697c478bd9Sstevel@tonic-gate 	rw_exit(&rhash->rsmhash_rw);
14707c478bd9Sstevel@tonic-gate 
14717c478bd9Sstevel@tonic-gate 	if (p != NULL && p->rsmrc_state != state) {
14727c478bd9Sstevel@tonic-gate 		/* state changed, release lock and return null */
14737c478bd9Sstevel@tonic-gate 		RSMRC_UNLOCK(p);
14747c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
14757c478bd9Sstevel@tonic-gate 		    "rsmhash_lookup done: state changed\n"));
14767c478bd9Sstevel@tonic-gate 		return (NULL);
14777c478bd9Sstevel@tonic-gate 	}
14787c478bd9Sstevel@tonic-gate 
14797c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmhash_lookup done\n"));
14807c478bd9Sstevel@tonic-gate 
14817c478bd9Sstevel@tonic-gate 	return (p);
14827c478bd9Sstevel@tonic-gate }
14837c478bd9Sstevel@tonic-gate 
14847c478bd9Sstevel@tonic-gate static void
rsmhash_rm(rsmhash_table_t * rhash,rsmresource_t * rcelm)14857c478bd9Sstevel@tonic-gate rsmhash_rm(rsmhash_table_t *rhash, rsmresource_t *rcelm)
14867c478bd9Sstevel@tonic-gate {
14877c478bd9Sstevel@tonic-gate 	rsmresource_t		*p, **back;
14887c478bd9Sstevel@tonic-gate 	uint_t			hashval;
14897c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL);
14907c478bd9Sstevel@tonic-gate 
14917c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmhash_rm enter\n"));
14927c478bd9Sstevel@tonic-gate 
14937c478bd9Sstevel@tonic-gate 	hashval = rsmhash(rcelm->rsmrc_key);
14947c478bd9Sstevel@tonic-gate 
14957c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_LVL2, "rsmhash_rm %u=%d\n",
14967c478bd9Sstevel@tonic-gate 	    rcelm->rsmrc_key, hashval));
14977c478bd9Sstevel@tonic-gate 
14987c478bd9Sstevel@tonic-gate 	/*
14997c478bd9Sstevel@tonic-gate 	 * It's ok not to find the segment.
15007c478bd9Sstevel@tonic-gate 	 */
15017c478bd9Sstevel@tonic-gate 	rw_enter(&rhash->rsmhash_rw, RW_WRITER);
15027c478bd9Sstevel@tonic-gate 
15037c478bd9Sstevel@tonic-gate 	back = (rsmresource_t **)rsmhash_bktaddr(rhash, hashval);
15047c478bd9Sstevel@tonic-gate 
15057c478bd9Sstevel@tonic-gate 	for (; (p = *back) != NULL;  back = &p->rsmrc_next) {
15067c478bd9Sstevel@tonic-gate 		if (p == rcelm) {
15077c478bd9Sstevel@tonic-gate 			*back = rcelm->rsmrc_next;
15087c478bd9Sstevel@tonic-gate 			break;
15097c478bd9Sstevel@tonic-gate 		}
15107c478bd9Sstevel@tonic-gate 	}
15117c478bd9Sstevel@tonic-gate 
15127c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmhash_rm done\n"));
15137c478bd9Sstevel@tonic-gate 
15147c478bd9Sstevel@tonic-gate 	rw_exit(&rhash->rsmhash_rw);
15157c478bd9Sstevel@tonic-gate }
15167c478bd9Sstevel@tonic-gate 
15177c478bd9Sstevel@tonic-gate static int
rsmhash_add(rsmhash_table_t * rhash,rsmresource_t * new,rsm_memseg_id_t key,int dup_check,rsm_resource_state_t state)15187c478bd9Sstevel@tonic-gate rsmhash_add(rsmhash_table_t *rhash, rsmresource_t *new, rsm_memseg_id_t key,
15197c478bd9Sstevel@tonic-gate     int dup_check, rsm_resource_state_t state)
15207c478bd9Sstevel@tonic-gate {
15217c478bd9Sstevel@tonic-gate 	rsmresource_t	*p = NULL, **bktp;
15227c478bd9Sstevel@tonic-gate 	uint_t		hashval;
15237c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL);
15247c478bd9Sstevel@tonic-gate 
15257c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmhash_add enter\n"));
15267c478bd9Sstevel@tonic-gate 
15277c478bd9Sstevel@tonic-gate 	/* lock table */
15287c478bd9Sstevel@tonic-gate 	rw_enter(&rhash->rsmhash_rw, RW_WRITER);
15297c478bd9Sstevel@tonic-gate 
15307c478bd9Sstevel@tonic-gate 	/*
15317c478bd9Sstevel@tonic-gate 	 * If the current resource state is other than the state passed in
15327c478bd9Sstevel@tonic-gate 	 * then the resource is (probably) already on the list. eg. for an
15337c478bd9Sstevel@tonic-gate 	 * import segment if the state is not RSM_STATE_NEW then it's on the
15347c478bd9Sstevel@tonic-gate 	 * list already.
15357c478bd9Sstevel@tonic-gate 	 */
15367c478bd9Sstevel@tonic-gate 	RSMRC_LOCK(new);
15377c478bd9Sstevel@tonic-gate 	if (new->rsmrc_state != state) {
15387c478bd9Sstevel@tonic-gate 		RSMRC_UNLOCK(new);
15397c478bd9Sstevel@tonic-gate 		rw_exit(&rhash->rsmhash_rw);
15407c478bd9Sstevel@tonic-gate 		return (RSMERR_BAD_SEG_HNDL);
15417c478bd9Sstevel@tonic-gate 	}
15427c478bd9Sstevel@tonic-gate 
15437c478bd9Sstevel@tonic-gate 	hashval = rsmhash(key);
15447c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_LVL2, "rsmhash_add %d\n", hashval));
15457c478bd9Sstevel@tonic-gate 
15467c478bd9Sstevel@tonic-gate 	if (dup_check) {
15477c478bd9Sstevel@tonic-gate 		/*
15487c478bd9Sstevel@tonic-gate 		 * Used for checking export segments; don't want to have
15497c478bd9Sstevel@tonic-gate 		 * the same key used for multiple segments.
15507c478bd9Sstevel@tonic-gate 		 */
15517c478bd9Sstevel@tonic-gate 
15527c478bd9Sstevel@tonic-gate 		p = (rsmresource_t *)rsmhash_getbkt(rhash, hashval);
15537c478bd9Sstevel@tonic-gate 
15547c478bd9Sstevel@tonic-gate 		for (; p; p = p->rsmrc_next) {
15557c478bd9Sstevel@tonic-gate 			if (p->rsmrc_key == key) {
15567c478bd9Sstevel@tonic-gate 				RSMRC_UNLOCK(new);
15577c478bd9Sstevel@tonic-gate 				break;
15587c478bd9Sstevel@tonic-gate 			}
15597c478bd9Sstevel@tonic-gate 		}
15607c478bd9Sstevel@tonic-gate 	}
15617c478bd9Sstevel@tonic-gate 
15627c478bd9Sstevel@tonic-gate 	if (p == NULL) {
15637c478bd9Sstevel@tonic-gate 		/* Key doesn't exist, add it */
15647c478bd9Sstevel@tonic-gate 
15657c478bd9Sstevel@tonic-gate 		bktp = (rsmresource_t **)rsmhash_bktaddr(rhash, hashval);
15667c478bd9Sstevel@tonic-gate 
15677c478bd9Sstevel@tonic-gate 		new->rsmrc_key = key;
15687c478bd9Sstevel@tonic-gate 		new->rsmrc_next = *bktp;
15697c478bd9Sstevel@tonic-gate 		*bktp = new;
15707c478bd9Sstevel@tonic-gate 	}
15717c478bd9Sstevel@tonic-gate 
15727c478bd9Sstevel@tonic-gate 	rw_exit(&rhash->rsmhash_rw);
15737c478bd9Sstevel@tonic-gate 
15747c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmhash_add done\n"));
15757c478bd9Sstevel@tonic-gate 
15767c478bd9Sstevel@tonic-gate 	return (p == NULL ? RSM_SUCCESS : RSMERR_SEGID_IN_USE);
15777c478bd9Sstevel@tonic-gate }
15787c478bd9Sstevel@tonic-gate 
15797c478bd9Sstevel@tonic-gate /*
15807c478bd9Sstevel@tonic-gate  * XOR each byte of the key.
15817c478bd9Sstevel@tonic-gate  */
15827c478bd9Sstevel@tonic-gate static uint_t
rsmhash(rsm_memseg_id_t key)15837c478bd9Sstevel@tonic-gate rsmhash(rsm_memseg_id_t key)
15847c478bd9Sstevel@tonic-gate {
15857c478bd9Sstevel@tonic-gate 	uint_t	hash = key;
15867c478bd9Sstevel@tonic-gate 
15877c478bd9Sstevel@tonic-gate 	hash ^=  (key >> 8);
15887c478bd9Sstevel@tonic-gate 	hash ^=  (key >> 16);
15897c478bd9Sstevel@tonic-gate 	hash ^=  (key >> 24);
15907c478bd9Sstevel@tonic-gate 
15917c478bd9Sstevel@tonic-gate 	return (hash % rsm_hash_size);
15927c478bd9Sstevel@tonic-gate 
15937c478bd9Sstevel@tonic-gate }
15947c478bd9Sstevel@tonic-gate 
15957c478bd9Sstevel@tonic-gate /*
15967c478bd9Sstevel@tonic-gate  * generic function to get a specific bucket
15977c478bd9Sstevel@tonic-gate  */
15987c478bd9Sstevel@tonic-gate static void *
rsmhash_getbkt(rsmhash_table_t * rhash,uint_t hashval)15997c478bd9Sstevel@tonic-gate rsmhash_getbkt(rsmhash_table_t *rhash, uint_t hashval)
16007c478bd9Sstevel@tonic-gate {
16017c478bd9Sstevel@tonic-gate 
16027c478bd9Sstevel@tonic-gate 	if (rhash->bucket == NULL)
16037c478bd9Sstevel@tonic-gate 		return (NULL);
16047c478bd9Sstevel@tonic-gate 	else
16057c478bd9Sstevel@tonic-gate 		return ((void *)rhash->bucket[hashval]);
16067c478bd9Sstevel@tonic-gate }
16077c478bd9Sstevel@tonic-gate 
16087c478bd9Sstevel@tonic-gate /*
16097c478bd9Sstevel@tonic-gate  * generic function to get a specific bucket's address
16107c478bd9Sstevel@tonic-gate  */
16117c478bd9Sstevel@tonic-gate static void **
rsmhash_bktaddr(rsmhash_table_t * rhash,uint_t hashval)16127c478bd9Sstevel@tonic-gate rsmhash_bktaddr(rsmhash_table_t *rhash, uint_t hashval)
16137c478bd9Sstevel@tonic-gate {
16147c478bd9Sstevel@tonic-gate 	if (rhash->bucket == NULL)
16157c478bd9Sstevel@tonic-gate 		return (NULL);
16167c478bd9Sstevel@tonic-gate 	else
16177c478bd9Sstevel@tonic-gate 		return ((void **)&(rhash->bucket[hashval]));
16187c478bd9Sstevel@tonic-gate }
16197c478bd9Sstevel@tonic-gate 
16207c478bd9Sstevel@tonic-gate /*
16217c478bd9Sstevel@tonic-gate  * generic function to alloc a hash table
16227c478bd9Sstevel@tonic-gate  */
16237c478bd9Sstevel@tonic-gate static void
rsmhash_alloc(rsmhash_table_t * rhash,int size)16247c478bd9Sstevel@tonic-gate rsmhash_alloc(rsmhash_table_t *rhash, int size)
16257c478bd9Sstevel@tonic-gate {
16267c478bd9Sstevel@tonic-gate 	rhash->bucket = (rsmresource_t **)
16277c478bd9Sstevel@tonic-gate 	    kmem_zalloc(size * sizeof (rsmresource_t *), KM_SLEEP);
16287c478bd9Sstevel@tonic-gate }
16297c478bd9Sstevel@tonic-gate 
16307c478bd9Sstevel@tonic-gate /*
16317c478bd9Sstevel@tonic-gate  * generic function to free a hash table
16327c478bd9Sstevel@tonic-gate  */
16337c478bd9Sstevel@tonic-gate static void
rsmhash_free(rsmhash_table_t * rhash,int size)16347c478bd9Sstevel@tonic-gate rsmhash_free(rsmhash_table_t *rhash, int size)
16357c478bd9Sstevel@tonic-gate {
16367c478bd9Sstevel@tonic-gate 
16377c478bd9Sstevel@tonic-gate 	kmem_free((void *)rhash->bucket, size * sizeof (caddr_t));
16387c478bd9Sstevel@tonic-gate 	rhash->bucket = NULL;
16397c478bd9Sstevel@tonic-gate 
16407c478bd9Sstevel@tonic-gate }
16417c478bd9Sstevel@tonic-gate /* *********************** Exported Segment Key Management ************ */
16427c478bd9Sstevel@tonic-gate 
16437c478bd9Sstevel@tonic-gate #define	rsmexport_add(new, key)		\
16447c478bd9Sstevel@tonic-gate 	rsmhash_add(&rsm_export_segs, (rsmresource_t *)new, key, 1, \
16457c478bd9Sstevel@tonic-gate 	    RSM_STATE_BIND)
16467c478bd9Sstevel@tonic-gate 
16477c478bd9Sstevel@tonic-gate #define	rsmexport_rm(arg)	\
16487c478bd9Sstevel@tonic-gate 	rsmhash_rm(&rsm_export_segs, (rsmresource_t *)(arg))
16497c478bd9Sstevel@tonic-gate 
16507c478bd9Sstevel@tonic-gate #define	rsmexport_lookup(key)	\
16517c478bd9Sstevel@tonic-gate 	(rsmseg_t *)rsmhash_lookup(&rsm_export_segs, key, RSM_STATE_EXPORT)
16527c478bd9Sstevel@tonic-gate 
16537c478bd9Sstevel@tonic-gate /* ************************** Import Segment List Management ********** */
16547c478bd9Sstevel@tonic-gate 
16557c478bd9Sstevel@tonic-gate /*
16567c478bd9Sstevel@tonic-gate  *  Add segment to import list. This will be useful for paging and loopback
16577c478bd9Sstevel@tonic-gate  * segment unloading.
16587c478bd9Sstevel@tonic-gate  */
16597c478bd9Sstevel@tonic-gate #define	rsmimport_add(arg, key)	\
16607c478bd9Sstevel@tonic-gate 	rsmhash_add(&rsm_import_segs, (rsmresource_t *)(arg), (key), 0, \
16617c478bd9Sstevel@tonic-gate 	    RSM_STATE_NEW)
16627c478bd9Sstevel@tonic-gate 
16637c478bd9Sstevel@tonic-gate #define	rsmimport_rm(arg)	\
16647c478bd9Sstevel@tonic-gate 	rsmhash_rm(&rsm_import_segs, (rsmresource_t *)(arg))
16657c478bd9Sstevel@tonic-gate 
16667c478bd9Sstevel@tonic-gate /*
16677c478bd9Sstevel@tonic-gate  *	#define	rsmimport_lookup(key)	\
16687c478bd9Sstevel@tonic-gate  *	(rsmseg_t *)rsmhash_lookup(&rsm_import_segs, (key), RSM_STATE_CONNECT)
16697c478bd9Sstevel@tonic-gate  */
16707c478bd9Sstevel@tonic-gate 
16717c478bd9Sstevel@tonic-gate /*
16727c478bd9Sstevel@tonic-gate  * increase the ref count and make the import segment point to the
16737c478bd9Sstevel@tonic-gate  * shared data structure. Return a pointer to the share data struct
16747c478bd9Sstevel@tonic-gate  * and the shared data struct is locked upon return
16757c478bd9Sstevel@tonic-gate  */
16767c478bd9Sstevel@tonic-gate static rsm_import_share_t *
rsmshare_get(rsm_memseg_id_t key,rsm_node_id_t node,adapter_t * adapter,rsmseg_t * segp)16777c478bd9Sstevel@tonic-gate rsmshare_get(rsm_memseg_id_t key, rsm_node_id_t node, adapter_t *adapter,
16787c478bd9Sstevel@tonic-gate     rsmseg_t *segp)
16797c478bd9Sstevel@tonic-gate {
16807c478bd9Sstevel@tonic-gate 	uint_t		hash;
16817c478bd9Sstevel@tonic-gate 	rsmresource_t		*p;
16827c478bd9Sstevel@tonic-gate 	rsm_import_share_t	*shdatap;
16837c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL);
16847c478bd9Sstevel@tonic-gate 
16857c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmshare_get enter\n"));
16867c478bd9Sstevel@tonic-gate 
16877c478bd9Sstevel@tonic-gate 	hash = rsmhash(key);
16887c478bd9Sstevel@tonic-gate 	/* lock table */
16897c478bd9Sstevel@tonic-gate 	rw_enter(&rsm_import_segs.rsmhash_rw, RW_WRITER);
16907c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_LVL2, "rsmshare_get:key=%u, hash=%d\n",
16917c478bd9Sstevel@tonic-gate 	    key, hash));
16927c478bd9Sstevel@tonic-gate 
16937c478bd9Sstevel@tonic-gate 	p = (rsmresource_t *)rsmhash_getbkt(&rsm_import_segs, hash);
16947c478bd9Sstevel@tonic-gate 
16957c478bd9Sstevel@tonic-gate 	for (; p; p = p->rsmrc_next) {
16967c478bd9Sstevel@tonic-gate 		/*
16977c478bd9Sstevel@tonic-gate 		 * Look for an entry that is importing the same exporter
16987c478bd9Sstevel@tonic-gate 		 * with the share data structure allocated.
16997c478bd9Sstevel@tonic-gate 		 */
17007c478bd9Sstevel@tonic-gate 		if ((p->rsmrc_key == key) &&
17017c478bd9Sstevel@tonic-gate 		    (p->rsmrc_node == node) &&
17027c478bd9Sstevel@tonic-gate 		    (p->rsmrc_adapter == adapter) &&
17037c478bd9Sstevel@tonic-gate 		    (((rsmseg_t *)p)->s_share != NULL)) {
17047c478bd9Sstevel@tonic-gate 			shdatap = ((rsmseg_t *)p)->s_share;
17057c478bd9Sstevel@tonic-gate 			break;
17067c478bd9Sstevel@tonic-gate 		}
17077c478bd9Sstevel@tonic-gate 	}
17087c478bd9Sstevel@tonic-gate 
17097c478bd9Sstevel@tonic-gate 	if (p == NULL) {
17107c478bd9Sstevel@tonic-gate 		/* we are the first importer, create the shared data struct */
17117c478bd9Sstevel@tonic-gate 		shdatap = kmem_zalloc(sizeof (rsm_import_share_t), KM_SLEEP);
17127c478bd9Sstevel@tonic-gate 		shdatap->rsmsi_state = RSMSI_STATE_NEW;
17137c478bd9Sstevel@tonic-gate 		shdatap->rsmsi_segid = key;
17147c478bd9Sstevel@tonic-gate 		shdatap->rsmsi_node = node;
17157c478bd9Sstevel@tonic-gate 		mutex_init(&shdatap->rsmsi_lock, NULL, MUTEX_DRIVER, NULL);
17167c478bd9Sstevel@tonic-gate 		cv_init(&shdatap->rsmsi_cv, NULL, CV_DRIVER, 0);
17177c478bd9Sstevel@tonic-gate 	}
17187c478bd9Sstevel@tonic-gate 
17197c478bd9Sstevel@tonic-gate 	rsmseglock_acquire(segp);
17207c478bd9Sstevel@tonic-gate 
17217c478bd9Sstevel@tonic-gate 	/* we grab the shared lock before returning from this function */
17227c478bd9Sstevel@tonic-gate 	mutex_enter(&shdatap->rsmsi_lock);
17237c478bd9Sstevel@tonic-gate 
17247c478bd9Sstevel@tonic-gate 	shdatap->rsmsi_refcnt++;
17257c478bd9Sstevel@tonic-gate 	segp->s_share = shdatap;
17267c478bd9Sstevel@tonic-gate 
17277c478bd9Sstevel@tonic-gate 	rsmseglock_release(segp);
17287c478bd9Sstevel@tonic-gate 
17297c478bd9Sstevel@tonic-gate 	rw_exit(&rsm_import_segs.rsmhash_rw);
17307c478bd9Sstevel@tonic-gate 
17317c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmshare_get done\n"));
17327c478bd9Sstevel@tonic-gate 
17337c478bd9Sstevel@tonic-gate 	return (shdatap);
17347c478bd9Sstevel@tonic-gate }
17357c478bd9Sstevel@tonic-gate 
17367c478bd9Sstevel@tonic-gate /*
17377c478bd9Sstevel@tonic-gate  * the shared data structure should be locked before calling
17387c478bd9Sstevel@tonic-gate  * rsmsharecv_signal().
17397c478bd9Sstevel@tonic-gate  * Change the state and signal any waiting segments.
17407c478bd9Sstevel@tonic-gate  */
17417c478bd9Sstevel@tonic-gate void
rsmsharecv_signal(rsmseg_t * seg,int oldstate,int newstate)17427c478bd9Sstevel@tonic-gate rsmsharecv_signal(rsmseg_t *seg, int oldstate, int newstate)
17437c478bd9Sstevel@tonic-gate {
17447c478bd9Sstevel@tonic-gate 	ASSERT(rsmsharelock_held(seg));
17457c478bd9Sstevel@tonic-gate 
17467c478bd9Sstevel@tonic-gate 	if (seg->s_share->rsmsi_state == oldstate) {
17477c478bd9Sstevel@tonic-gate 		seg->s_share->rsmsi_state = newstate;
17487c478bd9Sstevel@tonic-gate 		cv_broadcast(&seg->s_share->rsmsi_cv);
17497c478bd9Sstevel@tonic-gate 	}
17507c478bd9Sstevel@tonic-gate }
17517c478bd9Sstevel@tonic-gate 
17527c478bd9Sstevel@tonic-gate /*
17537c478bd9Sstevel@tonic-gate  * Add to the hash table
17547c478bd9Sstevel@tonic-gate  */
17557c478bd9Sstevel@tonic-gate static void
importer_list_add(rsm_node_id_t node,rsm_memseg_id_t key,rsm_addr_t hwaddr,void * cookie)17567c478bd9Sstevel@tonic-gate importer_list_add(rsm_node_id_t node, rsm_memseg_id_t key, rsm_addr_t hwaddr,
17577c478bd9Sstevel@tonic-gate     void *cookie)
17587c478bd9Sstevel@tonic-gate {
17597c478bd9Sstevel@tonic-gate 
17607c478bd9Sstevel@tonic-gate 	importing_token_t	*head;
17617c478bd9Sstevel@tonic-gate 	importing_token_t	*new_token;
17627c478bd9Sstevel@tonic-gate 	int			index;
17637c478bd9Sstevel@tonic-gate 
17647c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL);
17657c478bd9Sstevel@tonic-gate 
17667c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "importer_list_add enter\n"));
17677c478bd9Sstevel@tonic-gate 
17687c478bd9Sstevel@tonic-gate 	new_token = kmem_zalloc(sizeof (importing_token_t), KM_SLEEP);
17697c478bd9Sstevel@tonic-gate 	new_token->importing_node = node;
17707c478bd9Sstevel@tonic-gate 	new_token->key = key;
17717c478bd9Sstevel@tonic-gate 	new_token->import_segment_cookie = cookie;
17727c478bd9Sstevel@tonic-gate 	new_token->importing_adapter_hwaddr = hwaddr;
17737c478bd9Sstevel@tonic-gate 
17747c478bd9Sstevel@tonic-gate 	index = rsmhash(key);
17757c478bd9Sstevel@tonic-gate 
17767c478bd9Sstevel@tonic-gate 	mutex_enter(&importer_list.lock);
17777c478bd9Sstevel@tonic-gate 
17787c478bd9Sstevel@tonic-gate 	head = importer_list.bucket[index];
17797c478bd9Sstevel@tonic-gate 	importer_list.bucket[index] = new_token;
17807c478bd9Sstevel@tonic-gate 	new_token->next = head;
17817c478bd9Sstevel@tonic-gate 	mutex_exit(&importer_list.lock);
17827c478bd9Sstevel@tonic-gate 
17837c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "importer_list_add done\n"));
17847c478bd9Sstevel@tonic-gate }
17857c478bd9Sstevel@tonic-gate 
17867c478bd9Sstevel@tonic-gate static void
importer_list_rm(rsm_node_id_t node,rsm_memseg_id_t key,void * cookie)17877c478bd9Sstevel@tonic-gate importer_list_rm(rsm_node_id_t node,  rsm_memseg_id_t key, void *cookie)
17887c478bd9Sstevel@tonic-gate {
17897c478bd9Sstevel@tonic-gate 
17907c478bd9Sstevel@tonic-gate 	importing_token_t	*prev, *token = NULL;
17917c478bd9Sstevel@tonic-gate 	int			index;
17927c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL);
17937c478bd9Sstevel@tonic-gate 
17947c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "importer_list_rm enter\n"));
17957c478bd9Sstevel@tonic-gate 
17967c478bd9Sstevel@tonic-gate 	index = rsmhash(key);
17977c478bd9Sstevel@tonic-gate 
17987c478bd9Sstevel@tonic-gate 	mutex_enter(&importer_list.lock);
17997c478bd9Sstevel@tonic-gate 
18007c478bd9Sstevel@tonic-gate 	token = importer_list.bucket[index];
18017c478bd9Sstevel@tonic-gate 
18027c478bd9Sstevel@tonic-gate 	prev = token;
18037c478bd9Sstevel@tonic-gate 	while (token != NULL) {
18047c478bd9Sstevel@tonic-gate 		if (token->importing_node == node &&
18057c478bd9Sstevel@tonic-gate 		    token->import_segment_cookie == cookie) {
18067c478bd9Sstevel@tonic-gate 			if (prev == token)
18077c478bd9Sstevel@tonic-gate 				importer_list.bucket[index] = token->next;
18087c478bd9Sstevel@tonic-gate 			else
18097c478bd9Sstevel@tonic-gate 				prev->next = token->next;
18107c478bd9Sstevel@tonic-gate 			kmem_free((void *)token, sizeof (*token));
18117c478bd9Sstevel@tonic-gate 			break;
18127c478bd9Sstevel@tonic-gate 		} else {
18137c478bd9Sstevel@tonic-gate 			prev = token;
18147c478bd9Sstevel@tonic-gate 			token = token->next;
18157c478bd9Sstevel@tonic-gate 		}
18167c478bd9Sstevel@tonic-gate 	}
18177c478bd9Sstevel@tonic-gate 
18187c478bd9Sstevel@tonic-gate 	mutex_exit(&importer_list.lock);
18197c478bd9Sstevel@tonic-gate 
18207c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "importer_list_rm done\n"));
18217c478bd9Sstevel@tonic-gate 
18227c478bd9Sstevel@tonic-gate 
18237c478bd9Sstevel@tonic-gate }
18247c478bd9Sstevel@tonic-gate 
18257c478bd9Sstevel@tonic-gate /* **************************Segment Structure Management ************* */
18267c478bd9Sstevel@tonic-gate 
18277c478bd9Sstevel@tonic-gate /*
18287c478bd9Sstevel@tonic-gate  * Free segment structure
18297c478bd9Sstevel@tonic-gate  */
18307c478bd9Sstevel@tonic-gate static void
rsmseg_free(rsmseg_t * seg)18317c478bd9Sstevel@tonic-gate rsmseg_free(rsmseg_t *seg)
18327c478bd9Sstevel@tonic-gate {
18337c478bd9Sstevel@tonic-gate 
18347c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL);
18357c478bd9Sstevel@tonic-gate 
18367c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmseg_free enter\n"));
18377c478bd9Sstevel@tonic-gate 
18387c478bd9Sstevel@tonic-gate 	/* need to take seglock here to avoid race with rsmmap_unmap() */
18397c478bd9Sstevel@tonic-gate 	rsmseglock_acquire(seg);
18407c478bd9Sstevel@tonic-gate 	if (seg->s_ckl != NULL) {
18417c478bd9Sstevel@tonic-gate 		/* Segment is still busy */
18427c478bd9Sstevel@tonic-gate 		seg->s_state = RSM_STATE_END;
18437c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
18447c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
18457c478bd9Sstevel@tonic-gate 		    "rsmseg_free done\n"));
18467c478bd9Sstevel@tonic-gate 		return;
18477c478bd9Sstevel@tonic-gate 	}
18487c478bd9Sstevel@tonic-gate 
18497c478bd9Sstevel@tonic-gate 	rsmseglock_release(seg);
18507c478bd9Sstevel@tonic-gate 
18517c478bd9Sstevel@tonic-gate 	ASSERT(seg->s_state == RSM_STATE_END || seg->s_state == RSM_STATE_NEW);
18527c478bd9Sstevel@tonic-gate 
18537c478bd9Sstevel@tonic-gate 	/*
18547c478bd9Sstevel@tonic-gate 	 * If it's an importer decrement the refcount
18557c478bd9Sstevel@tonic-gate 	 * and if its down to zero free the shared data structure.
18567c478bd9Sstevel@tonic-gate 	 * This is where failures during rsm_connect() are unrefcounted
18577c478bd9Sstevel@tonic-gate 	 */
18587c478bd9Sstevel@tonic-gate 	if (seg->s_share != NULL) {
18597c478bd9Sstevel@tonic-gate 
18607c478bd9Sstevel@tonic-gate 		ASSERT(seg->s_type == RSM_RESOURCE_IMPORT_SEGMENT);
18617c478bd9Sstevel@tonic-gate 
18627c478bd9Sstevel@tonic-gate 		rsmsharelock_acquire(seg);
18637c478bd9Sstevel@tonic-gate 
18647c478bd9Sstevel@tonic-gate 		ASSERT(seg->s_share->rsmsi_refcnt > 0);
18657c478bd9Sstevel@tonic-gate 
18667c478bd9Sstevel@tonic-gate 		seg->s_share->rsmsi_refcnt--;
18677c478bd9Sstevel@tonic-gate 
18687c478bd9Sstevel@tonic-gate 		if (seg->s_share->rsmsi_refcnt == 0) {
18697c478bd9Sstevel@tonic-gate 			rsmsharelock_release(seg);
18707c478bd9Sstevel@tonic-gate 			mutex_destroy(&seg->s_share->rsmsi_lock);
18717c478bd9Sstevel@tonic-gate 			cv_destroy(&seg->s_share->rsmsi_cv);
18727c478bd9Sstevel@tonic-gate 			kmem_free((void *)(seg->s_share),
18737c478bd9Sstevel@tonic-gate 			    sizeof (rsm_import_share_t));
18747c478bd9Sstevel@tonic-gate 		} else {
18757c478bd9Sstevel@tonic-gate 			rsmsharelock_release(seg);
18767c478bd9Sstevel@tonic-gate 		}
18777c478bd9Sstevel@tonic-gate 		/*
18787c478bd9Sstevel@tonic-gate 		 * The following needs to be done after any
18797c478bd9Sstevel@tonic-gate 		 * rsmsharelock calls which use seg->s_share.
18807c478bd9Sstevel@tonic-gate 		 */
18817c478bd9Sstevel@tonic-gate 		seg->s_share = NULL;
18827c478bd9Sstevel@tonic-gate 	}
18837c478bd9Sstevel@tonic-gate 
18847c478bd9Sstevel@tonic-gate 	cv_destroy(&seg->s_cv);
18857c478bd9Sstevel@tonic-gate 	mutex_destroy(&seg->s_lock);
18867c478bd9Sstevel@tonic-gate 	rsmacl_free(seg->s_acl, seg->s_acl_len);
18877c478bd9Sstevel@tonic-gate 	rsmpiacl_free(seg->s_acl_in, seg->s_acl_len);
18887c478bd9Sstevel@tonic-gate 	if (seg->s_adapter)
18897c478bd9Sstevel@tonic-gate 		rsmka_release_adapter(seg->s_adapter);
18907c478bd9Sstevel@tonic-gate 
18917c478bd9Sstevel@tonic-gate 	kmem_free((void *)seg, sizeof (*seg));
18927c478bd9Sstevel@tonic-gate 
18937c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmseg_free done\n"));
18947c478bd9Sstevel@tonic-gate 
18957c478bd9Sstevel@tonic-gate }
18967c478bd9Sstevel@tonic-gate 
18977c478bd9Sstevel@tonic-gate 
18987c478bd9Sstevel@tonic-gate static rsmseg_t *
rsmseg_alloc(minor_t num,struct cred * cred)18997c478bd9Sstevel@tonic-gate rsmseg_alloc(minor_t num, struct cred *cred)
19007c478bd9Sstevel@tonic-gate {
19017c478bd9Sstevel@tonic-gate 	rsmseg_t	*new;
19027c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL);
19037c478bd9Sstevel@tonic-gate 
19047c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmseg_alloc enter\n"));
19057c478bd9Sstevel@tonic-gate 	/*
19067c478bd9Sstevel@tonic-gate 	 * allocate memory for new segment. This should be a segkmem cache.
19077c478bd9Sstevel@tonic-gate 	 */
19087c478bd9Sstevel@tonic-gate 	new = (rsmseg_t *)kmem_zalloc(sizeof (*new), KM_SLEEP);
19097c478bd9Sstevel@tonic-gate 
19107c478bd9Sstevel@tonic-gate 	new->s_state = RSM_STATE_NEW;
19117c478bd9Sstevel@tonic-gate 	new->s_minor	= num;
19127c478bd9Sstevel@tonic-gate 	new->s_acl_len	= 0;
19137c478bd9Sstevel@tonic-gate 	new->s_cookie = NULL;
19147c478bd9Sstevel@tonic-gate 	new->s_adapter = NULL;
19157c478bd9Sstevel@tonic-gate 
19167c478bd9Sstevel@tonic-gate 	new->s_mode = 0777 & ~PTOU((ttoproc(curthread)))->u_cmask;
19177c478bd9Sstevel@tonic-gate 	/* we don't have a key yet, will set at export/connect */
19187c478bd9Sstevel@tonic-gate 	new->s_uid  = crgetuid(cred);
19197c478bd9Sstevel@tonic-gate 	new->s_gid  = crgetgid(cred);
19207c478bd9Sstevel@tonic-gate 
19217c478bd9Sstevel@tonic-gate 	mutex_init(&new->s_lock, NULL, MUTEX_DRIVER, (void *)NULL);
19227c478bd9Sstevel@tonic-gate 	cv_init(&new->s_cv, NULL, CV_DRIVER, 0);
19237c478bd9Sstevel@tonic-gate 
19247c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmseg_alloc done\n"));
19257c478bd9Sstevel@tonic-gate 
19267c478bd9Sstevel@tonic-gate 	return (new);
19277c478bd9Sstevel@tonic-gate }
19287c478bd9Sstevel@tonic-gate 
19297c478bd9Sstevel@tonic-gate /* ******************************** Driver Open/Close/Poll *************** */
19307c478bd9Sstevel@tonic-gate 
19317c478bd9Sstevel@tonic-gate /*ARGSUSED1*/
19327c478bd9Sstevel@tonic-gate static int
rsm_open(dev_t * devp,int flag,int otyp,struct cred * cred)19337c478bd9Sstevel@tonic-gate rsm_open(dev_t *devp, int flag, int otyp, struct cred *cred)
19347c478bd9Sstevel@tonic-gate {
19357c478bd9Sstevel@tonic-gate 	minor_t rnum;
19367c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL| RSM_DDI);
19377c478bd9Sstevel@tonic-gate 
19387c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_open enter\n"));
19397c478bd9Sstevel@tonic-gate 	/*
19407c478bd9Sstevel@tonic-gate 	 * Char only
19417c478bd9Sstevel@tonic-gate 	 */
19427c478bd9Sstevel@tonic-gate 	if (otyp != OTYP_CHR) {
19437c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR, "rsm_open: bad otyp\n"));
19447c478bd9Sstevel@tonic-gate 		return (EINVAL);
19457c478bd9Sstevel@tonic-gate 	}
19467c478bd9Sstevel@tonic-gate 
19477c478bd9Sstevel@tonic-gate 	/*
19487c478bd9Sstevel@tonic-gate 	 * Only zero can be opened, clones are used for resources.
19497c478bd9Sstevel@tonic-gate 	 */
19507c478bd9Sstevel@tonic-gate 	if (getminor(*devp) != RSM_DRIVER_MINOR) {
19517c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
19527c478bd9Sstevel@tonic-gate 		    "rsm_open: bad minor %d\n", getminor(*devp)));
19537c478bd9Sstevel@tonic-gate 		return (ENODEV);
19547c478bd9Sstevel@tonic-gate 	}
19557c478bd9Sstevel@tonic-gate 
19567c478bd9Sstevel@tonic-gate 	if ((flag & FEXCL) != 0 && secpolicy_excl_open(cred) != 0) {
19577c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR, "rsm_open: bad perm\n"));
19587c478bd9Sstevel@tonic-gate 		return (EPERM);
19597c478bd9Sstevel@tonic-gate 	}
19607c478bd9Sstevel@tonic-gate 
19617c478bd9Sstevel@tonic-gate 	if (!(flag & FWRITE)) {
19627c478bd9Sstevel@tonic-gate 		/*
19637c478bd9Sstevel@tonic-gate 		 * The library function _rsm_librsm_init calls open for
19647c478bd9Sstevel@tonic-gate 		 * /dev/rsm with flag set to O_RDONLY.  We want a valid
19657c478bd9Sstevel@tonic-gate 		 * file descriptor to be returned for minor device zero.
19667c478bd9Sstevel@tonic-gate 		 */
19677c478bd9Sstevel@tonic-gate 
19687c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
19697c478bd9Sstevel@tonic-gate 		    "rsm_open RDONLY done\n"));
19707c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
19717c478bd9Sstevel@tonic-gate 	}
19727c478bd9Sstevel@tonic-gate 
19737c478bd9Sstevel@tonic-gate 	/*
19747c478bd9Sstevel@tonic-gate 	 * - allocate new minor number and segment.
19757c478bd9Sstevel@tonic-gate 	 * - add segment to list of all segments.
19767c478bd9Sstevel@tonic-gate 	 * - set minordev data to segment
19777c478bd9Sstevel@tonic-gate 	 * - update devp argument to new device
19787c478bd9Sstevel@tonic-gate 	 * - update s_cred to cred; make sure you do crhold(cred);
19797c478bd9Sstevel@tonic-gate 	 */
19807c478bd9Sstevel@tonic-gate 
19817c478bd9Sstevel@tonic-gate 	/* allocate a new resource number */
19827c478bd9Sstevel@tonic-gate 	if (rsmresource_alloc(&rnum) == RSM_SUCCESS) {
19837c478bd9Sstevel@tonic-gate 		/*
19847c478bd9Sstevel@tonic-gate 		 * We will bind this minor to a specific resource in first
19857c478bd9Sstevel@tonic-gate 		 * ioctl
19867c478bd9Sstevel@tonic-gate 		 */
19877c478bd9Sstevel@tonic-gate 		*devp = makedevice(getmajor(*devp), rnum);
19887c478bd9Sstevel@tonic-gate 	} else {
19897c478bd9Sstevel@tonic-gate 		return (EAGAIN);
19907c478bd9Sstevel@tonic-gate 	}
19917c478bd9Sstevel@tonic-gate 
19927c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_open done\n"));
19937c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
19947c478bd9Sstevel@tonic-gate }
19957c478bd9Sstevel@tonic-gate 
19967c478bd9Sstevel@tonic-gate static void
rsmseg_close(rsmseg_t * seg,int force_flag)19977c478bd9Sstevel@tonic-gate rsmseg_close(rsmseg_t *seg, int force_flag)
19987c478bd9Sstevel@tonic-gate {
19997c478bd9Sstevel@tonic-gate 	int e = RSM_SUCCESS;
20007c478bd9Sstevel@tonic-gate 
20017c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL| RSM_DDI);
20027c478bd9Sstevel@tonic-gate 
20037c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmseg_close enter\n"));
20047c478bd9Sstevel@tonic-gate 
20057c478bd9Sstevel@tonic-gate 	rsmseglock_acquire(seg);
20067c478bd9Sstevel@tonic-gate 	if (!force_flag && (seg->s_hdr.rsmrc_type ==
20077c478bd9Sstevel@tonic-gate 	    RSM_RESOURCE_EXPORT_SEGMENT)) {
20087c478bd9Sstevel@tonic-gate 		/*
20097c478bd9Sstevel@tonic-gate 		 * If we are processing rsm_close wait for force_destroy
20107c478bd9Sstevel@tonic-gate 		 * processing to complete since force_destroy processing
20117c478bd9Sstevel@tonic-gate 		 * needs to finish first before we can free the segment.
20127c478bd9Sstevel@tonic-gate 		 * force_destroy is only for export segments
20137c478bd9Sstevel@tonic-gate 		 */
20147c478bd9Sstevel@tonic-gate 		while (seg->s_flags & RSM_FORCE_DESTROY_WAIT) {
20157c478bd9Sstevel@tonic-gate 			cv_wait(&seg->s_cv, &seg->s_lock);
20167c478bd9Sstevel@tonic-gate 		}
20177c478bd9Sstevel@tonic-gate 	}
20187c478bd9Sstevel@tonic-gate 	rsmseglock_release(seg);
20197c478bd9Sstevel@tonic-gate 
20207c478bd9Sstevel@tonic-gate 	/* It's ok to read the state without a lock */
20217c478bd9Sstevel@tonic-gate 	switch (seg->s_state) {
20227c478bd9Sstevel@tonic-gate 	case RSM_STATE_EXPORT:
20237c478bd9Sstevel@tonic-gate 	case RSM_STATE_EXPORT_QUIESCING:
20247c478bd9Sstevel@tonic-gate 	case RSM_STATE_EXPORT_QUIESCED:
20257c478bd9Sstevel@tonic-gate 		e = rsm_unpublish(seg, 1);
20267c478bd9Sstevel@tonic-gate 		/* FALLTHRU */
20277c478bd9Sstevel@tonic-gate 	case RSM_STATE_BIND_QUIESCED:
20287c478bd9Sstevel@tonic-gate 		/* FALLTHRU */
20297c478bd9Sstevel@tonic-gate 	case RSM_STATE_BIND:
20307c478bd9Sstevel@tonic-gate 		e = rsm_unbind(seg);
20317c478bd9Sstevel@tonic-gate 		if (e != RSM_SUCCESS && force_flag == 1)
20327c478bd9Sstevel@tonic-gate 			return;
20337c478bd9Sstevel@tonic-gate 		ASSERT(seg->s_hdr.rsmrc_type == RSM_RESOURCE_EXPORT_SEGMENT);
20347c478bd9Sstevel@tonic-gate 		/* FALLTHRU */
20357c478bd9Sstevel@tonic-gate 	case RSM_STATE_NEW_QUIESCED:
20367c478bd9Sstevel@tonic-gate 		rsmseglock_acquire(seg);
20377c478bd9Sstevel@tonic-gate 		seg->s_state = RSM_STATE_NEW;
20387c478bd9Sstevel@tonic-gate 		cv_broadcast(&seg->s_cv);
20397c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
20407c478bd9Sstevel@tonic-gate 		break;
20417c478bd9Sstevel@tonic-gate 	case RSM_STATE_NEW:
20427c478bd9Sstevel@tonic-gate 		break;
20437c478bd9Sstevel@tonic-gate 	case RSM_STATE_ZOMBIE:
20447c478bd9Sstevel@tonic-gate 		/*
20457c478bd9Sstevel@tonic-gate 		 * Segments in this state have been removed off the
20467c478bd9Sstevel@tonic-gate 		 * exported segments list and have been unpublished
20477c478bd9Sstevel@tonic-gate 		 * and unbind. These segments have been removed during
20487c478bd9Sstevel@tonic-gate 		 * a callback to the rsm_export_force_destroy, which
20497c478bd9Sstevel@tonic-gate 		 * is called for the purpose of unlocking these
20507c478bd9Sstevel@tonic-gate 		 * exported memory segments when a process exits but
20517c478bd9Sstevel@tonic-gate 		 * leaves the segments locked down since rsm_close is
20527c478bd9Sstevel@tonic-gate 		 * is not called for the segments. This can happen
20537c478bd9Sstevel@tonic-gate 		 * when a process calls fork or exec and then exits.
20547c478bd9Sstevel@tonic-gate 		 * Once the segments are in the ZOMBIE state, all that
20557c478bd9Sstevel@tonic-gate 		 * remains is to destroy them when rsm_close is called.
20567c478bd9Sstevel@tonic-gate 		 * This is done here. Thus, for such segments the
20577c478bd9Sstevel@tonic-gate 		 * the state is changed to new so that later in this
20587c478bd9Sstevel@tonic-gate 		 * function rsmseg_free is called.
20597c478bd9Sstevel@tonic-gate 		 */
20607c478bd9Sstevel@tonic-gate 		rsmseglock_acquire(seg);
20617c478bd9Sstevel@tonic-gate 		seg->s_state = RSM_STATE_NEW;
20627c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
20637c478bd9Sstevel@tonic-gate 		break;
20647c478bd9Sstevel@tonic-gate 	case RSM_STATE_MAP_QUIESCE:
20657c478bd9Sstevel@tonic-gate 	case RSM_STATE_ACTIVE:
20667c478bd9Sstevel@tonic-gate 		/* Disconnect will handle the unmap */
20677c478bd9Sstevel@tonic-gate 	case RSM_STATE_CONN_QUIESCE:
20687c478bd9Sstevel@tonic-gate 	case RSM_STATE_CONNECT:
20697c478bd9Sstevel@tonic-gate 	case RSM_STATE_DISCONNECT:
20707c478bd9Sstevel@tonic-gate 		ASSERT(seg->s_hdr.rsmrc_type == RSM_RESOURCE_IMPORT_SEGMENT);
20717c478bd9Sstevel@tonic-gate 		(void) rsm_disconnect(seg);
20727c478bd9Sstevel@tonic-gate 		break;
20737c478bd9Sstevel@tonic-gate 	case RSM_STATE_MAPPING:
20747c478bd9Sstevel@tonic-gate 		/*FALLTHRU*/
20757c478bd9Sstevel@tonic-gate 	case RSM_STATE_END:
20767c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
20777c478bd9Sstevel@tonic-gate 		    "Invalid segment state %d in rsm_close\n", seg->s_state));
20787c478bd9Sstevel@tonic-gate 		break;
20797c478bd9Sstevel@tonic-gate 	default:
20807c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
20817c478bd9Sstevel@tonic-gate 		    "Invalid segment state %d in rsm_close\n", seg->s_state));
20827c478bd9Sstevel@tonic-gate 		break;
20837c478bd9Sstevel@tonic-gate 	}
20847c478bd9Sstevel@tonic-gate 
20857c478bd9Sstevel@tonic-gate 	/*
20867c478bd9Sstevel@tonic-gate 	 * check state.
20877c478bd9Sstevel@tonic-gate 	 * - make sure you do crfree(s_cred);
20887c478bd9Sstevel@tonic-gate 	 * release segment and minor number
20897c478bd9Sstevel@tonic-gate 	 */
20907c478bd9Sstevel@tonic-gate 	ASSERT(seg->s_state == RSM_STATE_NEW);
20917c478bd9Sstevel@tonic-gate 
20927c478bd9Sstevel@tonic-gate 	/*
20937c478bd9Sstevel@tonic-gate 	 * The export_force_destroy callback is created to unlock
20947c478bd9Sstevel@tonic-gate 	 * the exported segments of a process
20957c478bd9Sstevel@tonic-gate 	 * when the process does a fork or exec and then exits calls this
20967c478bd9Sstevel@tonic-gate 	 * function with the force flag set to 1 which indicates that the
20977c478bd9Sstevel@tonic-gate 	 * segment state must be converted to ZOMBIE. This state means that the
20987c478bd9Sstevel@tonic-gate 	 * segments still exist and have been unlocked and most importantly the
20997c478bd9Sstevel@tonic-gate 	 * only operation allowed is to destroy them on an rsm_close.
21007c478bd9Sstevel@tonic-gate 	 */
21017c478bd9Sstevel@tonic-gate 	if (force_flag) {
21027c478bd9Sstevel@tonic-gate 		rsmseglock_acquire(seg);
21037c478bd9Sstevel@tonic-gate 		seg->s_state = RSM_STATE_ZOMBIE;
21047c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
21057c478bd9Sstevel@tonic-gate 	} else {
21067c478bd9Sstevel@tonic-gate 		rsmseg_free(seg);
21077c478bd9Sstevel@tonic-gate 	}
21087c478bd9Sstevel@tonic-gate 
21097c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmseg_close done\n"));
21107c478bd9Sstevel@tonic-gate }
21117c478bd9Sstevel@tonic-gate 
21127c478bd9Sstevel@tonic-gate static int
rsm_close(dev_t dev,int flag,int otyp,cred_t * cred)21137c478bd9Sstevel@tonic-gate rsm_close(dev_t dev, int flag, int otyp, cred_t *cred)
21147c478bd9Sstevel@tonic-gate {
21157c478bd9Sstevel@tonic-gate 	minor_t	rnum = getminor(dev);
21167c478bd9Sstevel@tonic-gate 	rsmresource_t *res;
21177c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL| RSM_DDI);
21187c478bd9Sstevel@tonic-gate 
21197c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_close enter\n"));
21207c478bd9Sstevel@tonic-gate 
21217c478bd9Sstevel@tonic-gate 	flag = flag; cred = cred;
21227c478bd9Sstevel@tonic-gate 
21237c478bd9Sstevel@tonic-gate 	if (otyp != OTYP_CHR)
21247c478bd9Sstevel@tonic-gate 		return (EINVAL);
21257c478bd9Sstevel@tonic-gate 
21267c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rnum = %d\n", rnum));
21277c478bd9Sstevel@tonic-gate 
21287c478bd9Sstevel@tonic-gate 	/*
21297c478bd9Sstevel@tonic-gate 	 * At this point we are the last reference to the resource.
21307c478bd9Sstevel@tonic-gate 	 * Free resource number from resource table.
21317c478bd9Sstevel@tonic-gate 	 * It's ok to remove number before we free the segment.
21327c478bd9Sstevel@tonic-gate 	 * We need to lock the resource to protect against remote calls.
21337c478bd9Sstevel@tonic-gate 	 */
21347c478bd9Sstevel@tonic-gate 	if (rnum == RSM_DRIVER_MINOR ||
21357c478bd9Sstevel@tonic-gate 	    (res = rsmresource_free(rnum)) == NULL) {
21367c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_close done\n"));
21377c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
21387c478bd9Sstevel@tonic-gate 	}
21397c478bd9Sstevel@tonic-gate 
21407c478bd9Sstevel@tonic-gate 	switch (res->rsmrc_type) {
21417c478bd9Sstevel@tonic-gate 	case RSM_RESOURCE_EXPORT_SEGMENT:
21427c478bd9Sstevel@tonic-gate 	case RSM_RESOURCE_IMPORT_SEGMENT:
21437c478bd9Sstevel@tonic-gate 		rsmseg_close((rsmseg_t *)res, 0);
21447c478bd9Sstevel@tonic-gate 		break;
21457c478bd9Sstevel@tonic-gate 	case RSM_RESOURCE_BAR:
21467c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR, "bad resource in rsm_close\n"));
21477c478bd9Sstevel@tonic-gate 		break;
21487c478bd9Sstevel@tonic-gate 	default:
21497c478bd9Sstevel@tonic-gate 		break;
21507c478bd9Sstevel@tonic-gate 	}
21517c478bd9Sstevel@tonic-gate 
21527c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_close done\n"));
21537c478bd9Sstevel@tonic-gate 
21547c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
21557c478bd9Sstevel@tonic-gate }
21567c478bd9Sstevel@tonic-gate 
21577c478bd9Sstevel@tonic-gate /*
21587c478bd9Sstevel@tonic-gate  * rsm_inc_pgcnt
21597c478bd9Sstevel@tonic-gate  *
21607c478bd9Sstevel@tonic-gate  * Description: increment rsm page counter.
21617c478bd9Sstevel@tonic-gate  *
21627c478bd9Sstevel@tonic-gate  * Parameters:	pgcnt_t	pnum;	number of pages to be used
21637c478bd9Sstevel@tonic-gate  *
21647c478bd9Sstevel@tonic-gate  * Returns:	RSM_SUCCESS	if memory limit not exceeded
21657c478bd9Sstevel@tonic-gate  *		ENOSPC		if memory limit exceeded. In this case, the
21667c478bd9Sstevel@tonic-gate  *				page counter remains unchanged.
21677c478bd9Sstevel@tonic-gate  *
21687c478bd9Sstevel@tonic-gate  */
21697c478bd9Sstevel@tonic-gate static int
rsm_inc_pgcnt(pgcnt_t pnum)21707c478bd9Sstevel@tonic-gate rsm_inc_pgcnt(pgcnt_t pnum)
21717c478bd9Sstevel@tonic-gate {
21727c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_EXPORT);
21737c478bd9Sstevel@tonic-gate 	if (rsm_pgcnt_max == 0) { /* no upper limit has been set */
21747c478bd9Sstevel@tonic-gate 		return (RSM_SUCCESS);
21757c478bd9Sstevel@tonic-gate 	}
21767c478bd9Sstevel@tonic-gate 
21777c478bd9Sstevel@tonic-gate 	mutex_enter(&rsm_pgcnt_lock);
21787c478bd9Sstevel@tonic-gate 
21797c478bd9Sstevel@tonic-gate 	if (rsm_pgcnt + pnum > rsm_pgcnt_max) {
21807c478bd9Sstevel@tonic-gate 		/* ensure that limits have not been exceeded */
21817c478bd9Sstevel@tonic-gate 		mutex_exit(&rsm_pgcnt_lock);
21827c478bd9Sstevel@tonic-gate 		return (RSMERR_INSUFFICIENT_MEM);
21837c478bd9Sstevel@tonic-gate 	}
21847c478bd9Sstevel@tonic-gate 
21857c478bd9Sstevel@tonic-gate 	rsm_pgcnt += pnum;
21867c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG, "rsm_pgcnt incr to %d.\n",
21877c478bd9Sstevel@tonic-gate 	    rsm_pgcnt));
21887c478bd9Sstevel@tonic-gate 	mutex_exit(&rsm_pgcnt_lock);
21897c478bd9Sstevel@tonic-gate 
21907c478bd9Sstevel@tonic-gate 	return (RSM_SUCCESS);
21917c478bd9Sstevel@tonic-gate }
21927c478bd9Sstevel@tonic-gate 
21937c478bd9Sstevel@tonic-gate /*
21947c478bd9Sstevel@tonic-gate  * rsm_dec_pgcnt
21957c478bd9Sstevel@tonic-gate  *
21967c478bd9Sstevel@tonic-gate  * Description:	decrement rsm page counter.
21977c478bd9Sstevel@tonic-gate  *
21987c478bd9Sstevel@tonic-gate  * Parameters:	pgcnt_t	pnum;	number of pages freed
21997c478bd9Sstevel@tonic-gate  *
22007c478bd9Sstevel@tonic-gate  */
22017c478bd9Sstevel@tonic-gate static void
rsm_dec_pgcnt(pgcnt_t pnum)22027c478bd9Sstevel@tonic-gate rsm_dec_pgcnt(pgcnt_t pnum)
22037c478bd9Sstevel@tonic-gate {
22047c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_EXPORT);
22057c478bd9Sstevel@tonic-gate 
22067c478bd9Sstevel@tonic-gate 	if (rsm_pgcnt_max == 0) { /* no upper limit has been set */
22077c478bd9Sstevel@tonic-gate 		return;
22087c478bd9Sstevel@tonic-gate 	}
22097c478bd9Sstevel@tonic-gate 
22107c478bd9Sstevel@tonic-gate 	mutex_enter(&rsm_pgcnt_lock);
22117c478bd9Sstevel@tonic-gate 	ASSERT(rsm_pgcnt >= pnum);
22127c478bd9Sstevel@tonic-gate 	rsm_pgcnt -= pnum;
22137c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG, "rsm_pgcnt decr to %d.\n",
22147c478bd9Sstevel@tonic-gate 	    rsm_pgcnt));
22157c478bd9Sstevel@tonic-gate 	mutex_exit(&rsm_pgcnt_lock);
22167c478bd9Sstevel@tonic-gate }
22177c478bd9Sstevel@tonic-gate 
22187c478bd9Sstevel@tonic-gate static struct umem_callback_ops rsm_as_ops = {
22197c478bd9Sstevel@tonic-gate 	UMEM_CALLBACK_VERSION, /* version number */
22207c478bd9Sstevel@tonic-gate 	rsm_export_force_destroy,
22217c478bd9Sstevel@tonic-gate };
22227c478bd9Sstevel@tonic-gate 
22237c478bd9Sstevel@tonic-gate static int
rsm_bind_pages(ddi_umem_cookie_t * cookie,caddr_t vaddr,size_t len,proc_t * procp)22247c478bd9Sstevel@tonic-gate rsm_bind_pages(ddi_umem_cookie_t *cookie, caddr_t vaddr, size_t len,
22257c478bd9Sstevel@tonic-gate     proc_t *procp)
22267c478bd9Sstevel@tonic-gate {
22277c478bd9Sstevel@tonic-gate 	int error = RSM_SUCCESS;
22287c478bd9Sstevel@tonic-gate 	ulong_t pnum;
22297c478bd9Sstevel@tonic-gate 	struct umem_callback_ops *callbackops = &rsm_as_ops;
22307c478bd9Sstevel@tonic-gate 
22317c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_EXPORT);
22327c478bd9Sstevel@tonic-gate 
22337c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_bind_pages enter\n"));
22347c478bd9Sstevel@tonic-gate 
22357c478bd9Sstevel@tonic-gate 	/*
22367c478bd9Sstevel@tonic-gate 	 * Make sure vaddr and len are aligned on a page boundary
22377c478bd9Sstevel@tonic-gate 	 */
22387c478bd9Sstevel@tonic-gate 	if ((uintptr_t)vaddr & (PAGESIZE - 1)) {
22397c478bd9Sstevel@tonic-gate 		return (RSMERR_BAD_ADDR);
22407c478bd9Sstevel@tonic-gate 	}
22417c478bd9Sstevel@tonic-gate 
22427c478bd9Sstevel@tonic-gate 	if (len & (PAGESIZE - 1)) {
22437c478bd9Sstevel@tonic-gate 		return (RSMERR_BAD_LENGTH);
22447c478bd9Sstevel@tonic-gate 	}
22457c478bd9Sstevel@tonic-gate 
22467c478bd9Sstevel@tonic-gate 	/*
22477c478bd9Sstevel@tonic-gate 	 * Find number of pages
22487c478bd9Sstevel@tonic-gate 	 */
22497c478bd9Sstevel@tonic-gate 	pnum = btopr(len);
22507c478bd9Sstevel@tonic-gate 	error = rsm_inc_pgcnt(pnum);
22517c478bd9Sstevel@tonic-gate 	if (error != RSM_SUCCESS) {
22527c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
22537c478bd9Sstevel@tonic-gate 		    "rsm_bind_pages:mem limit exceeded\n"));
22547c478bd9Sstevel@tonic-gate 		return (RSMERR_INSUFFICIENT_MEM);
22557c478bd9Sstevel@tonic-gate 	}
22567c478bd9Sstevel@tonic-gate 
22577c478bd9Sstevel@tonic-gate 	error = umem_lockmemory(vaddr, len,
22587c478bd9Sstevel@tonic-gate 	    DDI_UMEMLOCK_WRITE|DDI_UMEMLOCK_READ|DDI_UMEMLOCK_LONGTERM,
22597c478bd9Sstevel@tonic-gate 	    cookie,
22607c478bd9Sstevel@tonic-gate 	    callbackops, procp);
22617c478bd9Sstevel@tonic-gate 
22627c478bd9Sstevel@tonic-gate 	if (error) {
22637c478bd9Sstevel@tonic-gate 		rsm_dec_pgcnt(pnum);
22647c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
22657c478bd9Sstevel@tonic-gate 		    "rsm_bind_pages:ddi_umem_lock failed\n"));
22667c478bd9Sstevel@tonic-gate 		/*
22677c478bd9Sstevel@tonic-gate 		 * ddi_umem_lock, in the case of failure, returns one of
22687c478bd9Sstevel@tonic-gate 		 * the following three errors. These are translated into
22697c478bd9Sstevel@tonic-gate 		 * the RSMERR namespace and returned.
22707c478bd9Sstevel@tonic-gate 		 */
22717c478bd9Sstevel@tonic-gate 		if (error == EFAULT)
22727c478bd9Sstevel@tonic-gate 			return (RSMERR_BAD_ADDR);
22737c478bd9Sstevel@tonic-gate 		else if (error == EACCES)
22747c478bd9Sstevel@tonic-gate 			return (RSMERR_PERM_DENIED);
22757c478bd9Sstevel@tonic-gate 		else
22767c478bd9Sstevel@tonic-gate 			return (RSMERR_INSUFFICIENT_MEM);
22777c478bd9Sstevel@tonic-gate 	}
22787c478bd9Sstevel@tonic-gate 
22797c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_bind_pages done\n"));
22807c478bd9Sstevel@tonic-gate 
22817c478bd9Sstevel@tonic-gate 	return (error);
22827c478bd9Sstevel@tonic-gate 
22837c478bd9Sstevel@tonic-gate }
22847c478bd9Sstevel@tonic-gate 
22857c478bd9Sstevel@tonic-gate static int
rsm_unbind_pages(rsmseg_t * seg)22867c478bd9Sstevel@tonic-gate rsm_unbind_pages(rsmseg_t *seg)
22877c478bd9Sstevel@tonic-gate {
22887c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_EXPORT);
22897c478bd9Sstevel@tonic-gate 
22907c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_unbind_pages enter\n"));
22917c478bd9Sstevel@tonic-gate 
22927c478bd9Sstevel@tonic-gate 	ASSERT(rsmseglock_held(seg));
22937c478bd9Sstevel@tonic-gate 
22947c478bd9Sstevel@tonic-gate 	if (seg->s_cookie != NULL) {
22957c478bd9Sstevel@tonic-gate 		/* unlock address range */
22967c478bd9Sstevel@tonic-gate 		ddi_umem_unlock(seg->s_cookie);
22977c478bd9Sstevel@tonic-gate 		rsm_dec_pgcnt(btopr(seg->s_len));
22987c478bd9Sstevel@tonic-gate 		seg->s_cookie = NULL;
22997c478bd9Sstevel@tonic-gate 	}
23007c478bd9Sstevel@tonic-gate 
23017c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_unbind_pages done\n"));
23027c478bd9Sstevel@tonic-gate 
23037c478bd9Sstevel@tonic-gate 	return (RSM_SUCCESS);
23047c478bd9Sstevel@tonic-gate }
23057c478bd9Sstevel@tonic-gate 
23067c478bd9Sstevel@tonic-gate 
23077c478bd9Sstevel@tonic-gate static int
rsm_bind(rsmseg_t * seg,rsm_ioctlmsg_t * msg,intptr_t dataptr,int mode)23087c478bd9Sstevel@tonic-gate rsm_bind(rsmseg_t *seg, rsm_ioctlmsg_t *msg, intptr_t dataptr, int mode)
23097c478bd9Sstevel@tonic-gate {
23107c478bd9Sstevel@tonic-gate 	int e;
23117c478bd9Sstevel@tonic-gate 	adapter_t *adapter;
23127c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_EXPORT);
23137c478bd9Sstevel@tonic-gate 
23147c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_bind enter\n"));
23157c478bd9Sstevel@tonic-gate 
23167c478bd9Sstevel@tonic-gate 	adapter = rsm_getadapter(msg, mode);
23177c478bd9Sstevel@tonic-gate 	if (adapter == NULL) {
23187c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
23197c478bd9Sstevel@tonic-gate 		    "rsm_bind done:no adapter\n"));
23207c478bd9Sstevel@tonic-gate 		return (RSMERR_CTLR_NOT_PRESENT);
23217c478bd9Sstevel@tonic-gate 	}
23227c478bd9Sstevel@tonic-gate 
23237c478bd9Sstevel@tonic-gate 	/* lock address range */
23247c478bd9Sstevel@tonic-gate 	if (msg->vaddr == NULL) {
23257c478bd9Sstevel@tonic-gate 		rsmka_release_adapter(adapter);
23267c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
23277c478bd9Sstevel@tonic-gate 		    "rsm: rsm_bind done: invalid vaddr\n"));
23287c478bd9Sstevel@tonic-gate 		return (RSMERR_BAD_ADDR);
23297c478bd9Sstevel@tonic-gate 	}
23307c478bd9Sstevel@tonic-gate 	if (msg->len <= 0) {
23317c478bd9Sstevel@tonic-gate 		rsmka_release_adapter(adapter);
23327c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
23337c478bd9Sstevel@tonic-gate 		    "rsm_bind: invalid length\n"));
23347c478bd9Sstevel@tonic-gate 		return (RSMERR_BAD_LENGTH);
23357c478bd9Sstevel@tonic-gate 	}
23367c478bd9Sstevel@tonic-gate 
23377c478bd9Sstevel@tonic-gate 	/* Lock segment */
23387c478bd9Sstevel@tonic-gate 	rsmseglock_acquire(seg);
23397c478bd9Sstevel@tonic-gate 
23407c478bd9Sstevel@tonic-gate 	while (seg->s_state == RSM_STATE_NEW_QUIESCED) {
23417c478bd9Sstevel@tonic-gate 		if (cv_wait_sig(&seg->s_cv, &seg->s_lock) == 0) {
23427c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG,
23437c478bd9Sstevel@tonic-gate 			    "rsm_bind done: cv_wait INTERRUPTED"));
23447c478bd9Sstevel@tonic-gate 			rsmka_release_adapter(adapter);
23457c478bd9Sstevel@tonic-gate 			rsmseglock_release(seg);
23467c478bd9Sstevel@tonic-gate 			return (RSMERR_INTERRUPTED);
23477c478bd9Sstevel@tonic-gate 		}
23487c478bd9Sstevel@tonic-gate 	}
23497c478bd9Sstevel@tonic-gate 
23507c478bd9Sstevel@tonic-gate 	ASSERT(seg->s_state == RSM_STATE_NEW);
23517c478bd9Sstevel@tonic-gate 
23527c478bd9Sstevel@tonic-gate 	ASSERT(seg->s_cookie == NULL);
23537c478bd9Sstevel@tonic-gate 
23547c478bd9Sstevel@tonic-gate 	e = rsm_bind_pages(&seg->s_cookie, msg->vaddr, msg->len, curproc);
23557c478bd9Sstevel@tonic-gate 	if (e == RSM_SUCCESS) {
23567c478bd9Sstevel@tonic-gate 		seg->s_flags |= RSM_USER_MEMORY;
23577c478bd9Sstevel@tonic-gate 		if (msg->perm & RSM_ALLOW_REBIND) {
23587c478bd9Sstevel@tonic-gate 			seg->s_flags |= RSMKA_ALLOW_UNBIND_REBIND;
23597c478bd9Sstevel@tonic-gate 		}
23607c478bd9Sstevel@tonic-gate 		if (msg->perm & RSM_CREATE_SEG_DONTWAIT) {
23617c478bd9Sstevel@tonic-gate 			seg->s_flags |= RSMKA_SET_RESOURCE_DONTWAIT;
23627c478bd9Sstevel@tonic-gate 		}
23637c478bd9Sstevel@tonic-gate 		seg->s_region.r_vaddr = msg->vaddr;
23647c478bd9Sstevel@tonic-gate 		/*
23657c478bd9Sstevel@tonic-gate 		 * Set the s_pid value in the segment structure. This is used
23667c478bd9Sstevel@tonic-gate 		 * to identify exported segments belonging to a particular
23677c478bd9Sstevel@tonic-gate 		 * process so that when the process exits, these segments can
23687c478bd9Sstevel@tonic-gate 		 * be unlocked forcefully even if rsm_close is not called on
23697c478bd9Sstevel@tonic-gate 		 * process exit since there maybe other processes referencing
23707c478bd9Sstevel@tonic-gate 		 * them (for example on a fork or exec).
23717c478bd9Sstevel@tonic-gate 		 * The s_pid value is also used to authenticate the process
23727c478bd9Sstevel@tonic-gate 		 * doing a publish or unpublish on the export segment. Only
23737c478bd9Sstevel@tonic-gate 		 * the creator of the export segment has a right to do a
23747c478bd9Sstevel@tonic-gate 		 * publish or unpublish and unbind on the segment.
23757c478bd9Sstevel@tonic-gate 		 */
23767c478bd9Sstevel@tonic-gate 		seg->s_pid = ddi_get_pid();
23777c478bd9Sstevel@tonic-gate 		seg->s_len = msg->len;
23787c478bd9Sstevel@tonic-gate 		seg->s_state = RSM_STATE_BIND;
23797c478bd9Sstevel@tonic-gate 		seg->s_adapter = adapter;
23807c478bd9Sstevel@tonic-gate 		seg->s_proc = curproc;
23817c478bd9Sstevel@tonic-gate 	} else {
23827c478bd9Sstevel@tonic-gate 		rsmka_release_adapter(adapter);
23837c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_WARNING,
23847c478bd9Sstevel@tonic-gate 		    "unable to lock down pages\n"));
23857c478bd9Sstevel@tonic-gate 	}
23867c478bd9Sstevel@tonic-gate 
23877c478bd9Sstevel@tonic-gate 	msg->rnum = seg->s_minor;
23887c478bd9Sstevel@tonic-gate 	/* Unlock segment */
23897c478bd9Sstevel@tonic-gate 	rsmseglock_release(seg);
23907c478bd9Sstevel@tonic-gate 
23917c478bd9Sstevel@tonic-gate 	if (e == RSM_SUCCESS) {
23927c478bd9Sstevel@tonic-gate 		/* copyout the resource number */
23937c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
23947c478bd9Sstevel@tonic-gate 		if ((mode & DATAMODEL_MASK) == DATAMODEL_ILP32) {
23957c478bd9Sstevel@tonic-gate 			rsm_ioctlmsg32_t msg32;
23967c478bd9Sstevel@tonic-gate 
23977c478bd9Sstevel@tonic-gate 			msg32.rnum = msg->rnum;
23987c478bd9Sstevel@tonic-gate 			if (ddi_copyout((caddr_t)&msg32.rnum,
23997c478bd9Sstevel@tonic-gate 			    (caddr_t)&((rsm_ioctlmsg32_t *)dataptr)->rnum,
24007c478bd9Sstevel@tonic-gate 			    sizeof (minor_t), mode)) {
24017c478bd9Sstevel@tonic-gate 				rsmka_release_adapter(adapter);
24027c478bd9Sstevel@tonic-gate 				e = RSMERR_BAD_ADDR;
24037c478bd9Sstevel@tonic-gate 			}
24047c478bd9Sstevel@tonic-gate 		}
24057c478bd9Sstevel@tonic-gate #endif
24067c478bd9Sstevel@tonic-gate 		if (ddi_copyout((caddr_t)&msg->rnum,
24077c478bd9Sstevel@tonic-gate 		    (caddr_t)&((rsm_ioctlmsg_t *)dataptr)->rnum,
24087c478bd9Sstevel@tonic-gate 		    sizeof (minor_t), mode)) {
24097c478bd9Sstevel@tonic-gate 			rsmka_release_adapter(adapter);
24107c478bd9Sstevel@tonic-gate 			e = RSMERR_BAD_ADDR;
24117c478bd9Sstevel@tonic-gate 		}
24127c478bd9Sstevel@tonic-gate 	}
24137c478bd9Sstevel@tonic-gate 
24147c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_bind done\n"));
24157c478bd9Sstevel@tonic-gate 
24167c478bd9Sstevel@tonic-gate 	return (e);
24177c478bd9Sstevel@tonic-gate }
24187c478bd9Sstevel@tonic-gate 
24197c478bd9Sstevel@tonic-gate static void
rsm_remap_local_importers(rsm_node_id_t src_nodeid,rsm_memseg_id_t ex_segid,ddi_umem_cookie_t cookie)24207c478bd9Sstevel@tonic-gate rsm_remap_local_importers(rsm_node_id_t src_nodeid,
24217c478bd9Sstevel@tonic-gate     rsm_memseg_id_t ex_segid,
24227c478bd9Sstevel@tonic-gate     ddi_umem_cookie_t cookie)
24237c478bd9Sstevel@tonic-gate 
24247c478bd9Sstevel@tonic-gate {
24257c478bd9Sstevel@tonic-gate 	rsmresource_t	*p = NULL;
24267c478bd9Sstevel@tonic-gate 	rsmhash_table_t *rhash = &rsm_import_segs;
24277c478bd9Sstevel@tonic-gate 	uint_t		index;
24287c478bd9Sstevel@tonic-gate 
24297c478bd9Sstevel@tonic-gate 	DBG_PRINTF((RSM_KERNEL_AGENT | RSM_FUNC_ALL, RSM_DEBUG_VERBOSE,
24307c478bd9Sstevel@tonic-gate 	    "rsm_remap_local_importers enter\n"));
24317c478bd9Sstevel@tonic-gate 
24327c478bd9Sstevel@tonic-gate 	index = rsmhash(ex_segid);
24337c478bd9Sstevel@tonic-gate 
24347c478bd9Sstevel@tonic-gate 	rw_enter(&rhash->rsmhash_rw, RW_READER);
24357c478bd9Sstevel@tonic-gate 
24367c478bd9Sstevel@tonic-gate 	p = rsmhash_getbkt(rhash, index);
24377c478bd9Sstevel@tonic-gate 
24387c478bd9Sstevel@tonic-gate 	for (; p; p = p->rsmrc_next) {
24397c478bd9Sstevel@tonic-gate 		rsmseg_t *seg = (rsmseg_t *)p;
24407c478bd9Sstevel@tonic-gate 		rsmseglock_acquire(seg);
24417c478bd9Sstevel@tonic-gate 		/*
24427c478bd9Sstevel@tonic-gate 		 * Change the s_cookie value of only the local importers
24437c478bd9Sstevel@tonic-gate 		 * which have been mapped (in state RSM_STATE_ACTIVE).
24447c478bd9Sstevel@tonic-gate 		 * Note that there is no need to change the s_cookie value
24457c478bd9Sstevel@tonic-gate 		 * if the imported segment is in RSM_STATE_MAPPING since
24467c478bd9Sstevel@tonic-gate 		 * eventually the s_cookie will be updated via the mapping
24477c478bd9Sstevel@tonic-gate 		 * functionality.
24487c478bd9Sstevel@tonic-gate 		 */
24497c478bd9Sstevel@tonic-gate 		if ((seg->s_segid == ex_segid) && (seg->s_node == src_nodeid) &&
24507c478bd9Sstevel@tonic-gate 		    (seg->s_state == RSM_STATE_ACTIVE)) {
24517c478bd9Sstevel@tonic-gate 			seg->s_cookie = cookie;
24527c478bd9Sstevel@tonic-gate 		}
24537c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
24547c478bd9Sstevel@tonic-gate 	}
24557c478bd9Sstevel@tonic-gate 	rw_exit(&rhash->rsmhash_rw);
24567c478bd9Sstevel@tonic-gate 
24577c478bd9Sstevel@tonic-gate 	DBG_PRINTF((RSM_KERNEL_AGENT | RSM_FUNC_ALL, RSM_DEBUG_VERBOSE,
24587c478bd9Sstevel@tonic-gate 	    "rsm_remap_local_importers done\n"));
24597c478bd9Sstevel@tonic-gate }
24607c478bd9Sstevel@tonic-gate 
24617c478bd9Sstevel@tonic-gate static int
rsm_rebind(rsmseg_t * seg,rsm_ioctlmsg_t * msg)24627c478bd9Sstevel@tonic-gate rsm_rebind(rsmseg_t *seg, rsm_ioctlmsg_t *msg)
24637c478bd9Sstevel@tonic-gate {
24647c478bd9Sstevel@tonic-gate 	int e;
24657c478bd9Sstevel@tonic-gate 	adapter_t *adapter;
24667c478bd9Sstevel@tonic-gate 	ddi_umem_cookie_t cookie;
24677c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_EXPORT);
24687c478bd9Sstevel@tonic-gate 
24697c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_rebind enter\n"));
24707c478bd9Sstevel@tonic-gate 
24717c478bd9Sstevel@tonic-gate 	/* Check for permissions to rebind */
24727c478bd9Sstevel@tonic-gate 	if (!(seg->s_flags & RSMKA_ALLOW_UNBIND_REBIND)) {
24737c478bd9Sstevel@tonic-gate 		return (RSMERR_REBIND_NOT_ALLOWED);
24747c478bd9Sstevel@tonic-gate 	}
24757c478bd9Sstevel@tonic-gate 
24767c478bd9Sstevel@tonic-gate 	if (seg->s_pid != ddi_get_pid() &&
24777c478bd9Sstevel@tonic-gate 	    ddi_get_pid() != 0) {
24787c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR, "rsm_rebind: Not owner\n"));
24797c478bd9Sstevel@tonic-gate 		return (RSMERR_NOT_CREATOR);
24807c478bd9Sstevel@tonic-gate 	}
24817c478bd9Sstevel@tonic-gate 
24827c478bd9Sstevel@tonic-gate 	/*
24837c478bd9Sstevel@tonic-gate 	 * We will not be allowing partial rebind and hence length passed
24847c478bd9Sstevel@tonic-gate 	 * in must be same as segment length
24857c478bd9Sstevel@tonic-gate 	 */
24867c478bd9Sstevel@tonic-gate 	if (msg->vaddr == NULL) {
24877c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
24887c478bd9Sstevel@tonic-gate 		    "rsm_rebind done: null msg->vaddr\n"));
24897c478bd9Sstevel@tonic-gate 		return (RSMERR_BAD_ADDR);
24907c478bd9Sstevel@tonic-gate 	}
24917c478bd9Sstevel@tonic-gate 	if (msg->len != seg->s_len) {
24927c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
24937c478bd9Sstevel@tonic-gate 		    "rsm_rebind: invalid length\n"));
24947c478bd9Sstevel@tonic-gate 		return (RSMERR_BAD_LENGTH);
24957c478bd9Sstevel@tonic-gate 	}
24967c478bd9Sstevel@tonic-gate 
24977c478bd9Sstevel@tonic-gate 	/* Lock segment */
24987c478bd9Sstevel@tonic-gate 	rsmseglock_acquire(seg);
24997c478bd9Sstevel@tonic-gate 
25007c478bd9Sstevel@tonic-gate 	while ((seg->s_state == RSM_STATE_BIND_QUIESCED) ||
25017c478bd9Sstevel@tonic-gate 	    (seg->s_state == RSM_STATE_EXPORT_QUIESCING) ||
25027c478bd9Sstevel@tonic-gate 	    (seg->s_state == RSM_STATE_EXPORT_QUIESCED)) {
25037c478bd9Sstevel@tonic-gate 		if (cv_wait_sig(&seg->s_cv, &seg->s_lock) == 0) {
25047c478bd9Sstevel@tonic-gate 			rsmseglock_release(seg);
25057c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG,
25067c478bd9Sstevel@tonic-gate 			    "rsm_rebind done: cv_wait INTERRUPTED"));
25077c478bd9Sstevel@tonic-gate 			return (RSMERR_INTERRUPTED);
25087c478bd9Sstevel@tonic-gate 		}
25097c478bd9Sstevel@tonic-gate 	}
25107c478bd9Sstevel@tonic-gate 
25117c478bd9Sstevel@tonic-gate 	/* verify segment state */
25127c478bd9Sstevel@tonic-gate 	if ((seg->s_state != RSM_STATE_BIND) &&
25137c478bd9Sstevel@tonic-gate 	    (seg->s_state != RSM_STATE_EXPORT)) {
25147c478bd9Sstevel@tonic-gate 		/* Unlock segment */
25157c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
25167c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
25177c478bd9Sstevel@tonic-gate 		    "rsm_rebind done: invalid state\n"));
25187c478bd9Sstevel@tonic-gate 		return (RSMERR_BAD_SEG_HNDL);
25197c478bd9Sstevel@tonic-gate 	}
25207c478bd9Sstevel@tonic-gate 
25217c478bd9Sstevel@tonic-gate 	ASSERT(seg->s_cookie != NULL);
25227c478bd9Sstevel@tonic-gate 
25237c478bd9Sstevel@tonic-gate 	if (msg->vaddr == seg->s_region.r_vaddr) {
25247c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
25257c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_rebind done\n"));
25267c478bd9Sstevel@tonic-gate 		return (RSM_SUCCESS);
25277c478bd9Sstevel@tonic-gate 	}
25287c478bd9Sstevel@tonic-gate 
25297c478bd9Sstevel@tonic-gate 	e = rsm_bind_pages(&cookie, msg->vaddr, msg->len, curproc);
25307c478bd9Sstevel@tonic-gate 	if (e == RSM_SUCCESS) {
25317c478bd9Sstevel@tonic-gate 		struct buf *xbuf;
25327c478bd9Sstevel@tonic-gate 		dev_t sdev = 0;
25337c478bd9Sstevel@tonic-gate 		rsm_memory_local_t mem;
25347c478bd9Sstevel@tonic-gate 
25357c478bd9Sstevel@tonic-gate 		xbuf = ddi_umem_iosetup(cookie, 0, msg->len, B_WRITE,
25367c478bd9Sstevel@tonic-gate 		    sdev, 0, NULL, DDI_UMEM_SLEEP);
25377c478bd9Sstevel@tonic-gate 		ASSERT(xbuf != NULL);
25387c478bd9Sstevel@tonic-gate 
25397c478bd9Sstevel@tonic-gate 		mem.ms_type = RSM_MEM_BUF;
25407c478bd9Sstevel@tonic-gate 		mem.ms_bp = xbuf;
25417c478bd9Sstevel@tonic-gate 
25427c478bd9Sstevel@tonic-gate 		adapter = seg->s_adapter;
25437c478bd9Sstevel@tonic-gate 		e = adapter->rsmpi_ops->rsm_rebind(
25447c478bd9Sstevel@tonic-gate 		    seg->s_handle.out, 0, &mem,
25457c478bd9Sstevel@tonic-gate 		    RSM_RESOURCE_DONTWAIT, NULL);
25467c478bd9Sstevel@tonic-gate 
25477c478bd9Sstevel@tonic-gate 		if (e == RSM_SUCCESS) {
25487c478bd9Sstevel@tonic-gate 			/*
25497c478bd9Sstevel@tonic-gate 			 * unbind the older pages, and unload local importers;
25507c478bd9Sstevel@tonic-gate 			 * but don't disconnect importers
25517c478bd9Sstevel@tonic-gate 			 */
25527c478bd9Sstevel@tonic-gate 			(void) rsm_unbind_pages(seg);
25537c478bd9Sstevel@tonic-gate 			seg->s_cookie = cookie;
25547c478bd9Sstevel@tonic-gate 			seg->s_region.r_vaddr = msg->vaddr;
25557c478bd9Sstevel@tonic-gate 			rsm_remap_local_importers(my_nodeid, seg->s_segid,
25567c478bd9Sstevel@tonic-gate 			    cookie);
25577c478bd9Sstevel@tonic-gate 		} else {
25587c478bd9Sstevel@tonic-gate 			/*
25597c478bd9Sstevel@tonic-gate 			 * Unbind the pages associated with "cookie" by the
25607c478bd9Sstevel@tonic-gate 			 * rsm_bind_pages calls prior to this. This is
25617c478bd9Sstevel@tonic-gate 			 * similar to what is done in the rsm_unbind_pages
25627c478bd9Sstevel@tonic-gate 			 * routine for the seg->s_cookie.
25637c478bd9Sstevel@tonic-gate 			 */
25647c478bd9Sstevel@tonic-gate 			ddi_umem_unlock(cookie);
25657c478bd9Sstevel@tonic-gate 			rsm_dec_pgcnt(btopr(msg->len));
25667c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_ERR,
25677c478bd9Sstevel@tonic-gate 			    "rsm_rebind failed with %d\n", e));
25687c478bd9Sstevel@tonic-gate 		}
25697c478bd9Sstevel@tonic-gate 		/*
25707c478bd9Sstevel@tonic-gate 		 * At present there is no dependency on the existence of xbuf.
25717c478bd9Sstevel@tonic-gate 		 * So we can free it here. If in the future this changes, it can
25727c478bd9Sstevel@tonic-gate 		 * be freed sometime during the segment destroy.
25737c478bd9Sstevel@tonic-gate 		 */
25747c478bd9Sstevel@tonic-gate 		freerbuf(xbuf);
25757c478bd9Sstevel@tonic-gate 	}
25767c478bd9Sstevel@tonic-gate 
25777c478bd9Sstevel@tonic-gate 	/* Unlock segment */
25787c478bd9Sstevel@tonic-gate 	rsmseglock_release(seg);
25797c478bd9Sstevel@tonic-gate 
25807c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_rebind done\n"));
25817c478bd9Sstevel@tonic-gate 
25827c478bd9Sstevel@tonic-gate 	return (e);
25837c478bd9Sstevel@tonic-gate }
25847c478bd9Sstevel@tonic-gate 
25857c478bd9Sstevel@tonic-gate static int
rsm_unbind(rsmseg_t * seg)25867c478bd9Sstevel@tonic-gate rsm_unbind(rsmseg_t *seg)
25877c478bd9Sstevel@tonic-gate {
25887c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_EXPORT);
25897c478bd9Sstevel@tonic-gate 
25907c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_unbind enter\n"));
25917c478bd9Sstevel@tonic-gate 
25927c478bd9Sstevel@tonic-gate 	rsmseglock_acquire(seg);
25937c478bd9Sstevel@tonic-gate 
25947c478bd9Sstevel@tonic-gate 	/* verify segment state */
25957c478bd9Sstevel@tonic-gate 	if ((seg->s_state != RSM_STATE_BIND) &&
25967c478bd9Sstevel@tonic-gate 	    (seg->s_state != RSM_STATE_BIND_QUIESCED)) {
25977c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
25987c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
25997c478bd9Sstevel@tonic-gate 		    "rsm_unbind: invalid state\n"));
26007c478bd9Sstevel@tonic-gate 		return (RSMERR_BAD_SEG_HNDL);
26017c478bd9Sstevel@tonic-gate 	}
26027c478bd9Sstevel@tonic-gate 
26037c478bd9Sstevel@tonic-gate 	/* unlock current range */
26047c478bd9Sstevel@tonic-gate 	(void) rsm_unbind_pages(seg);
26057c478bd9Sstevel@tonic-gate 
26067c478bd9Sstevel@tonic-gate 	if (seg->s_state == RSM_STATE_BIND) {
26077c478bd9Sstevel@tonic-gate 		seg->s_state = RSM_STATE_NEW;
26087c478bd9Sstevel@tonic-gate 	} else if (seg->s_state == RSM_STATE_BIND_QUIESCED) {
26097c478bd9Sstevel@tonic-gate 		seg->s_state = RSM_STATE_NEW_QUIESCED;
26107c478bd9Sstevel@tonic-gate 	}
26117c478bd9Sstevel@tonic-gate 
26127c478bd9Sstevel@tonic-gate 	rsmseglock_release(seg);
26137c478bd9Sstevel@tonic-gate 
26147c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_unbind done\n"));
26157c478bd9Sstevel@tonic-gate 
26167c478bd9Sstevel@tonic-gate 	return (RSM_SUCCESS);
26177c478bd9Sstevel@tonic-gate }
26187c478bd9Sstevel@tonic-gate 
26197c478bd9Sstevel@tonic-gate /* **************************** Exporter Access List Management ******* */
26207c478bd9Sstevel@tonic-gate static void
rsmacl_free(rsmapi_access_entry_t * acl,int acl_len)26217c478bd9Sstevel@tonic-gate rsmacl_free(rsmapi_access_entry_t *acl, int acl_len)
26227c478bd9Sstevel@tonic-gate {
26237c478bd9Sstevel@tonic-gate 	int	acl_sz;
26247c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_EXPORT);
26257c478bd9Sstevel@tonic-gate 
26267c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmacl_free enter\n"));
26277c478bd9Sstevel@tonic-gate 
26287c478bd9Sstevel@tonic-gate 	/* acl could be NULL */
26297c478bd9Sstevel@tonic-gate 
26307c478bd9Sstevel@tonic-gate 	if (acl != NULL && acl_len > 0) {
26317c478bd9Sstevel@tonic-gate 		acl_sz = acl_len * sizeof (rsmapi_access_entry_t);
26327c478bd9Sstevel@tonic-gate 		kmem_free((void *)acl, acl_sz);
26337c478bd9Sstevel@tonic-gate 	}
26347c478bd9Sstevel@tonic-gate 
26357c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmacl_free done\n"));
26367c478bd9Sstevel@tonic-gate }
26377c478bd9Sstevel@tonic-gate 
26387c478bd9Sstevel@tonic-gate static void
rsmpiacl_free(rsm_access_entry_t * acl,int acl_len)26397c478bd9Sstevel@tonic-gate rsmpiacl_free(rsm_access_entry_t *acl, int acl_len)
26407c478bd9Sstevel@tonic-gate {
26417c478bd9Sstevel@tonic-gate 	int	acl_sz;
26427c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_EXPORT);
26437c478bd9Sstevel@tonic-gate 
26447c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmpiacl_free enter\n"));
26457c478bd9Sstevel@tonic-gate 
26467c478bd9Sstevel@tonic-gate 	if (acl != NULL && acl_len > 0) {
26477c478bd9Sstevel@tonic-gate 		acl_sz = acl_len * sizeof (rsm_access_entry_t);
26487c478bd9Sstevel@tonic-gate 		kmem_free((void *)acl, acl_sz);
26497c478bd9Sstevel@tonic-gate 	}
26507c478bd9Sstevel@tonic-gate 
26517c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmpiacl_free done\n"));
26527c478bd9Sstevel@tonic-gate 
26537c478bd9Sstevel@tonic-gate }
26547c478bd9Sstevel@tonic-gate 
26557c478bd9Sstevel@tonic-gate static int
rsmacl_build(rsm_ioctlmsg_t * msg,int mode,rsmapi_access_entry_t ** list,int * len,int loopback)26567c478bd9Sstevel@tonic-gate rsmacl_build(rsm_ioctlmsg_t *msg, int mode,
26577c478bd9Sstevel@tonic-gate     rsmapi_access_entry_t **list, int *len, int loopback)
26587c478bd9Sstevel@tonic-gate {
26597c478bd9Sstevel@tonic-gate 	rsmapi_access_entry_t *acl;
26607c478bd9Sstevel@tonic-gate 	int	acl_len;
26617c478bd9Sstevel@tonic-gate 	int i;
26627c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_EXPORT);
26637c478bd9Sstevel@tonic-gate 
26647c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmacl_build enter\n"));
26657c478bd9Sstevel@tonic-gate 
26667c478bd9Sstevel@tonic-gate 	*len = 0;
26677c478bd9Sstevel@tonic-gate 	*list = NULL;
26687c478bd9Sstevel@tonic-gate 
26697c478bd9Sstevel@tonic-gate 	acl_len = msg->acl_len;
26707c478bd9Sstevel@tonic-gate 	if ((loopback && acl_len > 1) || (acl_len < 0) ||
26717c478bd9Sstevel@tonic-gate 	    (acl_len > MAX_NODES)) {
26727c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
26737c478bd9Sstevel@tonic-gate 		    "rsmacl_build done: acl invalid\n"));
26747c478bd9Sstevel@tonic-gate 		return (RSMERR_BAD_ACL);
26757c478bd9Sstevel@tonic-gate 	}
26767c478bd9Sstevel@tonic-gate 
26777c478bd9Sstevel@tonic-gate 	if (acl_len > 0 && acl_len <= MAX_NODES) {
26787c478bd9Sstevel@tonic-gate 		size_t acl_size = acl_len * sizeof (rsmapi_access_entry_t);
26797c478bd9Sstevel@tonic-gate 
26807c478bd9Sstevel@tonic-gate 		acl = kmem_alloc(acl_size, KM_SLEEP);
26817c478bd9Sstevel@tonic-gate 
26827c478bd9Sstevel@tonic-gate 		if (ddi_copyin((caddr_t)msg->acl, (caddr_t)acl,
26837c478bd9Sstevel@tonic-gate 		    acl_size, mode)) {
26847c478bd9Sstevel@tonic-gate 			kmem_free((void *) acl, acl_size);
26857c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
26867c478bd9Sstevel@tonic-gate 			    "rsmacl_build done: BAD_ADDR\n"));
26877c478bd9Sstevel@tonic-gate 			return (RSMERR_BAD_ADDR);
26887c478bd9Sstevel@tonic-gate 		}
26897c478bd9Sstevel@tonic-gate 
26907c478bd9Sstevel@tonic-gate 		/*
26917c478bd9Sstevel@tonic-gate 		 * Verify access list
26927c478bd9Sstevel@tonic-gate 		 */
26937c478bd9Sstevel@tonic-gate 		for (i = 0; i < acl_len; i++) {
26947c478bd9Sstevel@tonic-gate 			if (acl[i].ae_node > MAX_NODES ||
26957c478bd9Sstevel@tonic-gate 			    (loopback && (acl[i].ae_node != my_nodeid)) ||
26967c478bd9Sstevel@tonic-gate 			    acl[i].ae_permission > RSM_ACCESS_TRUSTED) {
26977c478bd9Sstevel@tonic-gate 				/* invalid entry */
26987c478bd9Sstevel@tonic-gate 				kmem_free((void *) acl, acl_size);
26997c478bd9Sstevel@tonic-gate 				DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
27007c478bd9Sstevel@tonic-gate 				    "rsmacl_build done: EINVAL\n"));
27017c478bd9Sstevel@tonic-gate 				return (RSMERR_BAD_ACL);
27027c478bd9Sstevel@tonic-gate 			}
27037c478bd9Sstevel@tonic-gate 		}
27047c478bd9Sstevel@tonic-gate 
27057c478bd9Sstevel@tonic-gate 		*len = acl_len;
27067c478bd9Sstevel@tonic-gate 		*list = acl;
27077c478bd9Sstevel@tonic-gate 	}
27087c478bd9Sstevel@tonic-gate 
27097c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmacl_build done\n"));
27107c478bd9Sstevel@tonic-gate 
27117c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
27127c478bd9Sstevel@tonic-gate }
27137c478bd9Sstevel@tonic-gate 
27147c478bd9Sstevel@tonic-gate static int
rsmpiacl_create(rsmapi_access_entry_t * src,rsm_access_entry_t ** dest,int acl_len,adapter_t * adapter)27157c478bd9Sstevel@tonic-gate rsmpiacl_create(rsmapi_access_entry_t *src, rsm_access_entry_t **dest,
27167c478bd9Sstevel@tonic-gate     int acl_len, adapter_t *adapter)
27177c478bd9Sstevel@tonic-gate {
27187c478bd9Sstevel@tonic-gate 	rsm_access_entry_t *acl;
27197c478bd9Sstevel@tonic-gate 	rsm_addr_t hwaddr;
27207c478bd9Sstevel@tonic-gate 	int i;
27217c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_EXPORT);
27227c478bd9Sstevel@tonic-gate 
27237c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmpiacl_create enter\n"));
27247c478bd9Sstevel@tonic-gate 
27257c478bd9Sstevel@tonic-gate 	if (src != NULL) {
27267c478bd9Sstevel@tonic-gate 		size_t acl_size = acl_len * sizeof (rsm_access_entry_t);
27277c478bd9Sstevel@tonic-gate 		acl = kmem_alloc(acl_size, KM_SLEEP);
27287c478bd9Sstevel@tonic-gate 
27297c478bd9Sstevel@tonic-gate 		/*
27307c478bd9Sstevel@tonic-gate 		 * translate access list
27317c478bd9Sstevel@tonic-gate 		 */
27327c478bd9Sstevel@tonic-gate 		for (i = 0; i < acl_len; i++) {
27337c478bd9Sstevel@tonic-gate 			if (src[i].ae_node == my_nodeid) {
27347c478bd9Sstevel@tonic-gate 				acl[i].ae_addr = adapter->hwaddr;
27357c478bd9Sstevel@tonic-gate 			} else {
27367c478bd9Sstevel@tonic-gate 				hwaddr = get_remote_hwaddr(adapter,
27377c478bd9Sstevel@tonic-gate 				    src[i].ae_node);
27387c478bd9Sstevel@tonic-gate 				if ((int64_t)hwaddr < 0) {
27397c478bd9Sstevel@tonic-gate 					/* invalid hwaddr */
27407c478bd9Sstevel@tonic-gate 					kmem_free((void *) acl, acl_size);
27417c478bd9Sstevel@tonic-gate 					DBG_PRINTF((category,
27427c478bd9Sstevel@tonic-gate 					    RSM_DEBUG_VERBOSE,
27437c478bd9Sstevel@tonic-gate 					    "rsmpiacl_create done:"
27447c478bd9Sstevel@tonic-gate 					    "EINVAL hwaddr\n"));
27457c478bd9Sstevel@tonic-gate 					return (RSMERR_INTERNAL_ERROR);
27467c478bd9Sstevel@tonic-gate 				}
27477c478bd9Sstevel@tonic-gate 				acl[i].ae_addr = hwaddr;
27487c478bd9Sstevel@tonic-gate 			}
27497c478bd9Sstevel@tonic-gate 			/* rsmpi understands only RSM_PERM_XXXX */
27507c478bd9Sstevel@tonic-gate 			acl[i].ae_permission =
27517c478bd9Sstevel@tonic-gate 			    src[i].ae_permission & RSM_PERM_RDWR;
27527c478bd9Sstevel@tonic-gate 		}
27537c478bd9Sstevel@tonic-gate 		*dest = acl;
27547c478bd9Sstevel@tonic-gate 	} else {
27557c478bd9Sstevel@tonic-gate 		*dest = NULL;
27567c478bd9Sstevel@tonic-gate 	}
27577c478bd9Sstevel@tonic-gate 
27587c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmpiacl_create done\n"));
27597c478bd9Sstevel@tonic-gate 
27607c478bd9Sstevel@tonic-gate 	return (RSM_SUCCESS);
27617c478bd9Sstevel@tonic-gate }
27627c478bd9Sstevel@tonic-gate 
27637c478bd9Sstevel@tonic-gate static int
rsmsegacl_validate(rsmipc_request_t * req,rsm_node_id_t rnode,rsmipc_reply_t * reply)27647c478bd9Sstevel@tonic-gate rsmsegacl_validate(rsmipc_request_t *req, rsm_node_id_t rnode,
27657c478bd9Sstevel@tonic-gate     rsmipc_reply_t *reply)
27667c478bd9Sstevel@tonic-gate {
27677c478bd9Sstevel@tonic-gate 
27687c478bd9Sstevel@tonic-gate 	int		i;
27697c478bd9Sstevel@tonic-gate 	rsmseg_t	*seg;
27707c478bd9Sstevel@tonic-gate 	rsm_memseg_id_t key = req->rsmipc_key;
27717c478bd9Sstevel@tonic-gate 	rsm_permission_t perm = req->rsmipc_perm;
27727c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_EXPORT);
27737c478bd9Sstevel@tonic-gate 
27747c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
27757c478bd9Sstevel@tonic-gate 	    "rsmsegacl_validate enter\n"));
27767c478bd9Sstevel@tonic-gate 
27777c478bd9Sstevel@tonic-gate 	/*
27787c478bd9Sstevel@tonic-gate 	 * Find segment and grab its lock. The reason why we grab the segment
27797c478bd9Sstevel@tonic-gate 	 * lock in side the search is to avoid the race when the segment is
27807c478bd9Sstevel@tonic-gate 	 * being deleted and we already have a pointer to it.
27817c478bd9Sstevel@tonic-gate 	 */
27827c478bd9Sstevel@tonic-gate 	seg = rsmexport_lookup(key);
27837c478bd9Sstevel@tonic-gate 	if (!seg) {
27847c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
27857c478bd9Sstevel@tonic-gate 		    "rsmsegacl_validate done: %u ENXIO\n", key));
27867c478bd9Sstevel@tonic-gate 		return (RSMERR_SEG_NOT_PUBLISHED);
27877c478bd9Sstevel@tonic-gate 	}
27887c478bd9Sstevel@tonic-gate 
27897c478bd9Sstevel@tonic-gate 	ASSERT(rsmseglock_held(seg));
27907c478bd9Sstevel@tonic-gate 	ASSERT(seg->s_state == RSM_STATE_EXPORT);
27917c478bd9Sstevel@tonic-gate 
27927c478bd9Sstevel@tonic-gate 	/*
27937c478bd9Sstevel@tonic-gate 	 * We implement a 2-level protection scheme.
27947c478bd9Sstevel@tonic-gate 	 * First, we check if local/remote host has access rights.
27957c478bd9Sstevel@tonic-gate 	 * Second, we check if the user has access rights.
27967c478bd9Sstevel@tonic-gate 	 *
27977c478bd9Sstevel@tonic-gate 	 * This routine only validates the rnode access_list
27987c478bd9Sstevel@tonic-gate 	 */
27997c478bd9Sstevel@tonic-gate 	if (seg->s_acl_len > 0) {
28007c478bd9Sstevel@tonic-gate 		/*
28017c478bd9Sstevel@tonic-gate 		 * Check host access list
28027c478bd9Sstevel@tonic-gate 		 */
28037c478bd9Sstevel@tonic-gate 		ASSERT(seg->s_acl != NULL);
28047c478bd9Sstevel@tonic-gate 		for (i = 0; i < seg->s_acl_len; i++) {
28057c478bd9Sstevel@tonic-gate 			if (seg->s_acl[i].ae_node == rnode) {
28067c478bd9Sstevel@tonic-gate 				perm &= seg->s_acl[i].ae_permission;
28077c478bd9Sstevel@tonic-gate 				goto found;
28087c478bd9Sstevel@tonic-gate 			}
28097c478bd9Sstevel@tonic-gate 		}
28107c478bd9Sstevel@tonic-gate 		/* rnode is not found in the list */
28117c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
28127c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
28137c478bd9Sstevel@tonic-gate 		    "rsmsegacl_validate done: EPERM\n"));
28147c478bd9Sstevel@tonic-gate 		return (RSMERR_SEG_NOT_PUBLISHED_TO_NODE);
28157c478bd9Sstevel@tonic-gate 	} else {
28167c478bd9Sstevel@tonic-gate 		/* use default owner creation umask */
28177c478bd9Sstevel@tonic-gate 		perm &= seg->s_mode;
28187c478bd9Sstevel@tonic-gate 	}
28197c478bd9Sstevel@tonic-gate 
28207c478bd9Sstevel@tonic-gate found:
28217c478bd9Sstevel@tonic-gate 	/* update perm for this node */
28227c478bd9Sstevel@tonic-gate 	reply->rsmipc_mode = perm;
28237c478bd9Sstevel@tonic-gate 	reply->rsmipc_uid = seg->s_uid;
28247c478bd9Sstevel@tonic-gate 	reply->rsmipc_gid = seg->s_gid;
28257c478bd9Sstevel@tonic-gate 	reply->rsmipc_segid = seg->s_segid;
28267c478bd9Sstevel@tonic-gate 	reply->rsmipc_seglen = seg->s_len;
28277c478bd9Sstevel@tonic-gate 
28287c478bd9Sstevel@tonic-gate 	/*
28297c478bd9Sstevel@tonic-gate 	 * Perm of requesting node is valid; source will validate user
28307c478bd9Sstevel@tonic-gate 	 */
28317c478bd9Sstevel@tonic-gate 	rsmseglock_release(seg);
28327c478bd9Sstevel@tonic-gate 
28337c478bd9Sstevel@tonic-gate 	/*
28347c478bd9Sstevel@tonic-gate 	 * Add the importer to the list right away, if connect fails
28357c478bd9Sstevel@tonic-gate 	 * the importer will ask the exporter to remove it.
28367c478bd9Sstevel@tonic-gate 	 */
28377c478bd9Sstevel@tonic-gate 	importer_list_add(rnode, key, req->rsmipc_adapter_hwaddr,
28387c478bd9Sstevel@tonic-gate 	    req->rsmipc_segment_cookie);
28397c478bd9Sstevel@tonic-gate 
28407c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmsegacl_validate done\n"));
28417c478bd9Sstevel@tonic-gate 
28427c478bd9Sstevel@tonic-gate 	return (RSM_SUCCESS);
28437c478bd9Sstevel@tonic-gate }
28447c478bd9Sstevel@tonic-gate 
28457c478bd9Sstevel@tonic-gate 
28467c478bd9Sstevel@tonic-gate /* ************************** Exporter Calls ************************* */
28477c478bd9Sstevel@tonic-gate 
28487c478bd9Sstevel@tonic-gate static int
rsm_publish(rsmseg_t * seg,rsm_ioctlmsg_t * msg,intptr_t dataptr,int mode)28497c478bd9Sstevel@tonic-gate rsm_publish(rsmseg_t *seg, rsm_ioctlmsg_t *msg, intptr_t dataptr, int mode)
28507c478bd9Sstevel@tonic-gate {
28517c478bd9Sstevel@tonic-gate 	int			e;
28527c478bd9Sstevel@tonic-gate 	int			acl_len;
28537c478bd9Sstevel@tonic-gate 	rsmapi_access_entry_t	*acl;
28547c478bd9Sstevel@tonic-gate 	rsm_access_entry_t	*rsmpi_acl;
28557c478bd9Sstevel@tonic-gate 	rsm_memory_local_t	mem;
28567c478bd9Sstevel@tonic-gate 	struct buf		*xbuf;
28577c478bd9Sstevel@tonic-gate 	dev_t 			sdev = 0;
28587c478bd9Sstevel@tonic-gate 	adapter_t		*adapter;
28597c478bd9Sstevel@tonic-gate 	rsm_memseg_id_t		segment_id = 0;
28607c478bd9Sstevel@tonic-gate 	int			loopback_flag = 0;
28617c478bd9Sstevel@tonic-gate 	int			create_flags = 0;
28627c478bd9Sstevel@tonic-gate 	rsm_resource_callback_t	callback_flag;
28637c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_EXPORT);
28647c478bd9Sstevel@tonic-gate 
28657c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_publish enter\n"));
28667c478bd9Sstevel@tonic-gate 
28677c478bd9Sstevel@tonic-gate 	if (seg->s_adapter == &loopback_adapter)
28687c478bd9Sstevel@tonic-gate 		loopback_flag = 1;
28697c478bd9Sstevel@tonic-gate 
28707c478bd9Sstevel@tonic-gate 	if (seg->s_pid != ddi_get_pid() &&
28717c478bd9Sstevel@tonic-gate 	    ddi_get_pid() != 0) {
28727c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
28737c478bd9Sstevel@tonic-gate 		    "rsm_publish: Not creator\n"));
28747c478bd9Sstevel@tonic-gate 		return (RSMERR_NOT_CREATOR);
28757c478bd9Sstevel@tonic-gate 	}
28767c478bd9Sstevel@tonic-gate 
28777c478bd9Sstevel@tonic-gate 	/*
28787c478bd9Sstevel@tonic-gate 	 * Get per node access list
28797c478bd9Sstevel@tonic-gate 	 */
28807c478bd9Sstevel@tonic-gate 	e = rsmacl_build(msg, mode, &acl, &acl_len, loopback_flag);
28817c478bd9Sstevel@tonic-gate 	if (e != DDI_SUCCESS) {
28827c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
28837c478bd9Sstevel@tonic-gate 		    "rsm_publish done: rsmacl_build failed\n"));
28847c478bd9Sstevel@tonic-gate 		return (e);
28857c478bd9Sstevel@tonic-gate 	}
28867c478bd9Sstevel@tonic-gate 
28877c478bd9Sstevel@tonic-gate 	/*
28887c478bd9Sstevel@tonic-gate 	 * The application provided msg->key is used for resolving a
28897c478bd9Sstevel@tonic-gate 	 * segment id according to the following:
28907c478bd9Sstevel@tonic-gate 	 *    key = 0   		Kernel Agent selects the segment id
28917c478bd9Sstevel@tonic-gate 	 *    key <= RSM_DLPI_ID_END	Reserved for system usage except
28927c478bd9Sstevel@tonic-gate 	 *				RSMLIB range
28937c478bd9Sstevel@tonic-gate 	 *    key < RSM_USER_APP_ID_BASE segment id = key
28947c478bd9Sstevel@tonic-gate 	 *    key >= RSM_USER_APP_ID_BASE Reserved for KA selections
28957c478bd9Sstevel@tonic-gate 	 *
28967c478bd9Sstevel@tonic-gate 	 * rsm_nextavail_segmentid is initialized to 0x80000000 and
28977c478bd9Sstevel@tonic-gate 	 * overflows to zero after 0x80000000 allocations.
28987c478bd9Sstevel@tonic-gate 	 * An algorithm is needed which allows reinitialization and provides
28997c478bd9Sstevel@tonic-gate 	 * for reallocation after overflow.  For now, ENOMEM is returned
29007c478bd9Sstevel@tonic-gate 	 * once the overflow condition has occurred.
29017c478bd9Sstevel@tonic-gate 	 */
29027c478bd9Sstevel@tonic-gate 	if (msg->key == 0) {
29037c478bd9Sstevel@tonic-gate 		mutex_enter(&rsm_lock);
29047c478bd9Sstevel@tonic-gate 		segment_id = rsm_nextavail_segmentid;
29057c478bd9Sstevel@tonic-gate 		if (segment_id != 0) {
29067c478bd9Sstevel@tonic-gate 			rsm_nextavail_segmentid++;
29077c478bd9Sstevel@tonic-gate 			mutex_exit(&rsm_lock);
29087c478bd9Sstevel@tonic-gate 		} else {
29097c478bd9Sstevel@tonic-gate 			mutex_exit(&rsm_lock);
29107c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_ERR,
29117c478bd9Sstevel@tonic-gate 			    "rsm_publish done: no more keys avlbl\n"));
29127c478bd9Sstevel@tonic-gate 			return (RSMERR_INSUFFICIENT_RESOURCES);
29137c478bd9Sstevel@tonic-gate 		}
29147c478bd9Sstevel@tonic-gate 	} else	if BETWEEN(msg->key, RSM_RSMLIB_ID_BASE, RSM_RSMLIB_ID_END)
29157c478bd9Sstevel@tonic-gate 		/* range reserved for internal use by base/ndi libraries */
29167c478bd9Sstevel@tonic-gate 		segment_id = msg->key;
29177c478bd9Sstevel@tonic-gate 	else	if (msg->key <= RSM_DLPI_ID_END)
29187c478bd9Sstevel@tonic-gate 		return (RSMERR_RESERVED_SEGID);
29197c478bd9Sstevel@tonic-gate 	else if (msg->key <= (uint_t)RSM_USER_APP_ID_BASE -1)
29207c478bd9Sstevel@tonic-gate 		segment_id = msg->key;
29217c478bd9Sstevel@tonic-gate 	else {
29227c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
29237c478bd9Sstevel@tonic-gate 		    "rsm_publish done: invalid key %u\n", msg->key));
29247c478bd9Sstevel@tonic-gate 		return (RSMERR_RESERVED_SEGID);
29257c478bd9Sstevel@tonic-gate 	}
29267c478bd9Sstevel@tonic-gate 
29277c478bd9Sstevel@tonic-gate 	/* Add key to exportlist; The segment lock is held on success */
29287c478bd9Sstevel@tonic-gate 	e = rsmexport_add(seg, segment_id);
29297c478bd9Sstevel@tonic-gate 	if (e) {
29307c478bd9Sstevel@tonic-gate 		rsmacl_free(acl, acl_len);
29317c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
29327c478bd9Sstevel@tonic-gate 		    "rsm_publish done: export_add failed: %d\n", e));
29337c478bd9Sstevel@tonic-gate 		return (e);
29347c478bd9Sstevel@tonic-gate 	}
29357c478bd9Sstevel@tonic-gate 
29367c478bd9Sstevel@tonic-gate 	seg->s_segid = segment_id;
29377c478bd9Sstevel@tonic-gate 
29387c478bd9Sstevel@tonic-gate 	if ((seg->s_state != RSM_STATE_BIND) &&
29397c478bd9Sstevel@tonic-gate 	    (seg->s_state != RSM_STATE_BIND_QUIESCED)) {
29407c478bd9Sstevel@tonic-gate 		/* state changed since then, free acl and return */
29417c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
29427c478bd9Sstevel@tonic-gate 		rsmexport_rm(seg);
29437c478bd9Sstevel@tonic-gate 		rsmacl_free(acl, acl_len);
29447c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
29457c478bd9Sstevel@tonic-gate 		    "rsm_publish done: segment in wrong state: %d\n",
29467c478bd9Sstevel@tonic-gate 		    seg->s_state));
29477c478bd9Sstevel@tonic-gate 		return (RSMERR_BAD_SEG_HNDL);
29487c478bd9Sstevel@tonic-gate 	}
29497c478bd9Sstevel@tonic-gate 
29507c478bd9Sstevel@tonic-gate 	/*
29517c478bd9Sstevel@tonic-gate 	 * If this is for a local memory handle and permissions are zero,
29527c478bd9Sstevel@tonic-gate 	 * then the surrogate segment is very large and we want to skip
29537c478bd9Sstevel@tonic-gate 	 * allocation of DVMA space.
29547c478bd9Sstevel@tonic-gate 	 *
29557c478bd9Sstevel@tonic-gate 	 * Careful!  If the user didn't use an ACL list, acl will be a NULL
29567c478bd9Sstevel@tonic-gate 	 * pointer.  Check that before dereferencing it.
29577c478bd9Sstevel@tonic-gate 	 */
29587c478bd9Sstevel@tonic-gate 	if (acl != (rsmapi_access_entry_t *)NULL) {
29597c478bd9Sstevel@tonic-gate 		if (acl[0].ae_node == my_nodeid && acl[0].ae_permission == 0)
29607c478bd9Sstevel@tonic-gate 			goto skipdriver;
29617c478bd9Sstevel@tonic-gate 	}
29627c478bd9Sstevel@tonic-gate 
29637c478bd9Sstevel@tonic-gate 	/* create segment  */
29647c478bd9Sstevel@tonic-gate 	xbuf = ddi_umem_iosetup(seg->s_cookie, 0, seg->s_len, B_WRITE,
29657c478bd9Sstevel@tonic-gate 	    sdev, 0, NULL, DDI_UMEM_SLEEP);
29667c478bd9Sstevel@tonic-gate 	ASSERT(xbuf != NULL);
29677c478bd9Sstevel@tonic-gate 
29687c478bd9Sstevel@tonic-gate 	mem.ms_type = RSM_MEM_BUF;
29697c478bd9Sstevel@tonic-gate 	mem.ms_bp = xbuf;
29707c478bd9Sstevel@tonic-gate 
29717c478bd9Sstevel@tonic-gate 	/* This call includes a bind operations */
29727c478bd9Sstevel@tonic-gate 
29737c478bd9Sstevel@tonic-gate 	adapter = seg->s_adapter;
29747c478bd9Sstevel@tonic-gate 	/*
29757c478bd9Sstevel@tonic-gate 	 * create a acl list with hwaddr for RSMPI publish
29767c478bd9Sstevel@tonic-gate 	 */
29777c478bd9Sstevel@tonic-gate 	e = rsmpiacl_create(acl, &rsmpi_acl, acl_len, adapter);
29787c478bd9Sstevel@tonic-gate 
29797c478bd9Sstevel@tonic-gate 	if (e != RSM_SUCCESS) {
29807c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
29817c478bd9Sstevel@tonic-gate 		rsmexport_rm(seg);
29827c478bd9Sstevel@tonic-gate 		rsmacl_free(acl, acl_len);
29837c478bd9Sstevel@tonic-gate 		freerbuf(xbuf);
29847c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
29857c478bd9Sstevel@tonic-gate 		    "rsm_publish done: rsmpiacl_create failed: %d\n", e));
29867c478bd9Sstevel@tonic-gate 		return (e);
29877c478bd9Sstevel@tonic-gate 	}
29887c478bd9Sstevel@tonic-gate 
29897c478bd9Sstevel@tonic-gate 	if (seg->s_state == RSM_STATE_BIND) {
29907c478bd9Sstevel@tonic-gate 		/* create segment  */
29917c478bd9Sstevel@tonic-gate 
29927c478bd9Sstevel@tonic-gate 		/* This call includes a bind operations */
29937c478bd9Sstevel@tonic-gate 
29947c478bd9Sstevel@tonic-gate 		if (seg->s_flags & RSMKA_ALLOW_UNBIND_REBIND) {
29957c478bd9Sstevel@tonic-gate 			create_flags = RSM_ALLOW_UNBIND_REBIND;
29967c478bd9Sstevel@tonic-gate 		}
29977c478bd9Sstevel@tonic-gate 
29987c478bd9Sstevel@tonic-gate 		if (seg->s_flags & RSMKA_SET_RESOURCE_DONTWAIT) {
29997c478bd9Sstevel@tonic-gate 			callback_flag  = RSM_RESOURCE_DONTWAIT;
30007c478bd9Sstevel@tonic-gate 		} else {
30017c478bd9Sstevel@tonic-gate 			callback_flag  = RSM_RESOURCE_SLEEP;
30027c478bd9Sstevel@tonic-gate 		}
30037c478bd9Sstevel@tonic-gate 
30047c478bd9Sstevel@tonic-gate 		e = adapter->rsmpi_ops->rsm_seg_create(
30057c478bd9Sstevel@tonic-gate 		    adapter->rsmpi_handle,
30067c478bd9Sstevel@tonic-gate 		    &seg->s_handle.out, seg->s_len,
30077c478bd9Sstevel@tonic-gate 		    create_flags, &mem,
30087c478bd9Sstevel@tonic-gate 		    callback_flag, NULL);
30097c478bd9Sstevel@tonic-gate 		/*
30107c478bd9Sstevel@tonic-gate 		 * At present there is no dependency on the existence of xbuf.
30117c478bd9Sstevel@tonic-gate 		 * So we can free it here. If in the future this changes, it can
30127c478bd9Sstevel@tonic-gate 		 * be freed sometime during the segment destroy.
30137c478bd9Sstevel@tonic-gate 		 */
30147c478bd9Sstevel@tonic-gate 		freerbuf(xbuf);
30157c478bd9Sstevel@tonic-gate 
30167c478bd9Sstevel@tonic-gate 		if (e != RSM_SUCCESS) {
30177c478bd9Sstevel@tonic-gate 			rsmseglock_release(seg);
30187c478bd9Sstevel@tonic-gate 			rsmexport_rm(seg);
30197c478bd9Sstevel@tonic-gate 			rsmacl_free(acl, acl_len);
30207c478bd9Sstevel@tonic-gate 			rsmpiacl_free(rsmpi_acl, acl_len);
30217c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_ERR,
30227c478bd9Sstevel@tonic-gate 			    "rsm_publish done: export_create failed: %d\n", e));
30237c478bd9Sstevel@tonic-gate 			/*
30247c478bd9Sstevel@tonic-gate 			 * The following assertion ensures that the two errors
30257c478bd9Sstevel@tonic-gate 			 * related to the length and its alignment do not occur
30267c478bd9Sstevel@tonic-gate 			 * since they have been checked during export_create
30277c478bd9Sstevel@tonic-gate 			 */
30287c478bd9Sstevel@tonic-gate 			ASSERT(e != RSMERR_BAD_MEM_ALIGNMENT &&
30297c478bd9Sstevel@tonic-gate 			    e != RSMERR_BAD_LENGTH);
30307c478bd9Sstevel@tonic-gate 			if (e == RSMERR_NOT_MEM)
30317c478bd9Sstevel@tonic-gate 				e = RSMERR_INSUFFICIENT_MEM;
30327c478bd9Sstevel@tonic-gate 
30337c478bd9Sstevel@tonic-gate 			return (e);
30347c478bd9Sstevel@tonic-gate 		}
30357c478bd9Sstevel@tonic-gate 		/* export segment, this should create an IMMU mapping */
30367c478bd9Sstevel@tonic-gate 		e = adapter->rsmpi_ops->rsm_publish(
30377c478bd9Sstevel@tonic-gate 		    seg->s_handle.out,
30387c478bd9Sstevel@tonic-gate 		    rsmpi_acl, acl_len,
30397c478bd9Sstevel@tonic-gate 		    seg->s_segid,
30407c478bd9Sstevel@tonic-gate 		    RSM_RESOURCE_DONTWAIT, NULL);
30417c478bd9Sstevel@tonic-gate 
30427c478bd9Sstevel@tonic-gate 		if (e != RSM_SUCCESS) {
30437c478bd9Sstevel@tonic-gate 			adapter->rsmpi_ops->rsm_seg_destroy(seg->s_handle.out);
30447c478bd9Sstevel@tonic-gate 			rsmseglock_release(seg);
30457c478bd9Sstevel@tonic-gate 			rsmexport_rm(seg);
30467c478bd9Sstevel@tonic-gate 			rsmacl_free(acl, acl_len);
30477c478bd9Sstevel@tonic-gate 			rsmpiacl_free(rsmpi_acl, acl_len);
30487c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_ERR,
30497c478bd9Sstevel@tonic-gate 			    "rsm_publish done: export_publish failed: %d\n",
30507c478bd9Sstevel@tonic-gate 			    e));
30517c478bd9Sstevel@tonic-gate 			return (e);
30527c478bd9Sstevel@tonic-gate 		}
30537c478bd9Sstevel@tonic-gate 	}
30547c478bd9Sstevel@tonic-gate 
30557c478bd9Sstevel@tonic-gate 	seg->s_acl_in = rsmpi_acl;
30567c478bd9Sstevel@tonic-gate 
30577c478bd9Sstevel@tonic-gate skipdriver:
30587c478bd9Sstevel@tonic-gate 	/* defer s_acl/s_acl_len -> avoid crash in rsmseg_free */
30597c478bd9Sstevel@tonic-gate 	seg->s_acl_len	= acl_len;
30607c478bd9Sstevel@tonic-gate 	seg->s_acl	= acl;
30617c478bd9Sstevel@tonic-gate 
30627c478bd9Sstevel@tonic-gate 	if (seg->s_state == RSM_STATE_BIND) {
30637c478bd9Sstevel@tonic-gate 		seg->s_state = RSM_STATE_EXPORT;
30647c478bd9Sstevel@tonic-gate 	} else if (seg->s_state == RSM_STATE_BIND_QUIESCED) {
30657c478bd9Sstevel@tonic-gate 		seg->s_state = RSM_STATE_EXPORT_QUIESCED;
30667c478bd9Sstevel@tonic-gate 		cv_broadcast(&seg->s_cv);
30677c478bd9Sstevel@tonic-gate 	}
30687c478bd9Sstevel@tonic-gate 
30697c478bd9Sstevel@tonic-gate 	rsmseglock_release(seg);
30707c478bd9Sstevel@tonic-gate 
30717c478bd9Sstevel@tonic-gate 	/*
30727c478bd9Sstevel@tonic-gate 	 * If the segment id was solicited, then return it in
30737c478bd9Sstevel@tonic-gate 	 * the original incoming message.
30747c478bd9Sstevel@tonic-gate 	 */
30757c478bd9Sstevel@tonic-gate 	if (msg->key == 0) {
30767c478bd9Sstevel@tonic-gate 		msg->key = segment_id;
30777c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
30787c478bd9Sstevel@tonic-gate 		if ((mode & DATAMODEL_MASK) == DATAMODEL_ILP32) {
30797c478bd9Sstevel@tonic-gate 			rsm_ioctlmsg32_t msg32;
30807c478bd9Sstevel@tonic-gate 
30817c478bd9Sstevel@tonic-gate 			msg32.key = msg->key;
30827c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
30837c478bd9Sstevel@tonic-gate 			    "rsm_publish done\n"));
30847c478bd9Sstevel@tonic-gate 			return (ddi_copyout((caddr_t)&msg32,
30857c478bd9Sstevel@tonic-gate 			    (caddr_t)dataptr, sizeof (msg32), mode));
30867c478bd9Sstevel@tonic-gate 		}
30877c478bd9Sstevel@tonic-gate #endif
30887c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
30897c478bd9Sstevel@tonic-gate 		    "rsm_publish done\n"));
30907c478bd9Sstevel@tonic-gate 		return (ddi_copyout((caddr_t)msg,
30917c478bd9Sstevel@tonic-gate 		    (caddr_t)dataptr, sizeof (*msg), mode));
30927c478bd9Sstevel@tonic-gate 	}
30937c478bd9Sstevel@tonic-gate 
30947c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_publish done\n"));
30957c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
30967c478bd9Sstevel@tonic-gate }
30977c478bd9Sstevel@tonic-gate 
30987c478bd9Sstevel@tonic-gate /*
30997c478bd9Sstevel@tonic-gate  * This function modifies the access control list of an already published
31007c478bd9Sstevel@tonic-gate  * segment.  There is no effect on import segments which are already
31017c478bd9Sstevel@tonic-gate  * connected.
31027c478bd9Sstevel@tonic-gate  */
31037c478bd9Sstevel@tonic-gate static int
rsm_republish(rsmseg_t * seg,rsm_ioctlmsg_t * msg,int mode)31047c478bd9Sstevel@tonic-gate rsm_republish(rsmseg_t *seg, rsm_ioctlmsg_t *msg, int mode)
31057c478bd9Sstevel@tonic-gate {
31067c478bd9Sstevel@tonic-gate 	rsmapi_access_entry_t	*new_acl, *old_acl, *tmp_acl;
31077c478bd9Sstevel@tonic-gate 	rsm_access_entry_t	*rsmpi_new_acl, *rsmpi_old_acl;
31087c478bd9Sstevel@tonic-gate 	int			new_acl_len, old_acl_len, tmp_acl_len;
31097c478bd9Sstevel@tonic-gate 	int			e, i;
31107c478bd9Sstevel@tonic-gate 	adapter_t		*adapter;
31117c478bd9Sstevel@tonic-gate 	int			loopback_flag = 0;
31127c478bd9Sstevel@tonic-gate 	rsm_memseg_id_t		key;
31137c478bd9Sstevel@tonic-gate 	rsm_permission_t	permission;
31147c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_EXPORT);
31157c478bd9Sstevel@tonic-gate 
31167c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_republish enter\n"));
31177c478bd9Sstevel@tonic-gate 
31187c478bd9Sstevel@tonic-gate 	if ((seg->s_state != RSM_STATE_EXPORT) &&
31197c478bd9Sstevel@tonic-gate 	    (seg->s_state != RSM_STATE_EXPORT_QUIESCED) &&
31207c478bd9Sstevel@tonic-gate 	    (seg->s_state != RSM_STATE_EXPORT_QUIESCING))
31217c478bd9Sstevel@tonic-gate 		return (RSMERR_SEG_NOT_PUBLISHED);
31227c478bd9Sstevel@tonic-gate 
31237c478bd9Sstevel@tonic-gate 	if (seg->s_pid != ddi_get_pid() &&
31247c478bd9Sstevel@tonic-gate 	    ddi_get_pid() != 0) {
31257c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
31267c478bd9Sstevel@tonic-gate 		    "rsm_republish: Not owner\n"));
31277c478bd9Sstevel@tonic-gate 		return (RSMERR_NOT_CREATOR);
31287c478bd9Sstevel@tonic-gate 	}
31297c478bd9Sstevel@tonic-gate 
31307c478bd9Sstevel@tonic-gate 	if (seg->s_adapter == &loopback_adapter)
31317c478bd9Sstevel@tonic-gate 		loopback_flag = 1;
31327c478bd9Sstevel@tonic-gate 
31337c478bd9Sstevel@tonic-gate 	/*
31347c478bd9Sstevel@tonic-gate 	 * Build new list first
31357c478bd9Sstevel@tonic-gate 	 */
31367c478bd9Sstevel@tonic-gate 	e = rsmacl_build(msg, mode, &new_acl, &new_acl_len, loopback_flag);
31377c478bd9Sstevel@tonic-gate 	if (e) {
31387c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
31397c478bd9Sstevel@tonic-gate 		    "rsm_republish done: rsmacl_build failed %d", e));
31407c478bd9Sstevel@tonic-gate 		return (e);
31417c478bd9Sstevel@tonic-gate 	}
31427c478bd9Sstevel@tonic-gate 
31437c478bd9Sstevel@tonic-gate 	/* Lock segment */
31447c478bd9Sstevel@tonic-gate 	rsmseglock_acquire(seg);
31457c478bd9Sstevel@tonic-gate 	/*
31467c478bd9Sstevel@tonic-gate 	 * a republish is in progress - REPUBLISH message is being
31477c478bd9Sstevel@tonic-gate 	 * sent to the importers so wait for it to complete OR
31487c478bd9Sstevel@tonic-gate 	 * wait till DR completes
31497c478bd9Sstevel@tonic-gate 	 */
31507c478bd9Sstevel@tonic-gate 	while (((seg->s_state == RSM_STATE_EXPORT) &&
31517c478bd9Sstevel@tonic-gate 	    (seg->s_flags & RSM_REPUBLISH_WAIT)) ||
31527c478bd9Sstevel@tonic-gate 	    (seg->s_state == RSM_STATE_EXPORT_QUIESCED) ||
31537c478bd9Sstevel@tonic-gate 	    (seg->s_state == RSM_STATE_EXPORT_QUIESCING)) {
31547c478bd9Sstevel@tonic-gate 		if (cv_wait_sig(&seg->s_cv, &seg->s_lock) == 0) {
31557c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
31567c478bd9Sstevel@tonic-gate 			    "rsm_republish done: cv_wait  INTERRUPTED"));
31577c478bd9Sstevel@tonic-gate 			rsmseglock_release(seg);
31587c478bd9Sstevel@tonic-gate 			rsmacl_free(new_acl, new_acl_len);
31597c478bd9Sstevel@tonic-gate 			return (RSMERR_INTERRUPTED);
31607c478bd9Sstevel@tonic-gate 		}
31617c478bd9Sstevel@tonic-gate 	}
31627c478bd9Sstevel@tonic-gate 
31637c478bd9Sstevel@tonic-gate 	/* recheck if state is valid */
31647c478bd9Sstevel@tonic-gate 	if (seg->s_state != RSM_STATE_EXPORT) {
31657c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
31667c478bd9Sstevel@tonic-gate 		rsmacl_free(new_acl, new_acl_len);
31677c478bd9Sstevel@tonic-gate 		return (RSMERR_SEG_NOT_PUBLISHED);
31687c478bd9Sstevel@tonic-gate 	}
31697c478bd9Sstevel@tonic-gate 
31707c478bd9Sstevel@tonic-gate 	key = seg->s_key;
31717c478bd9Sstevel@tonic-gate 	old_acl = seg->s_acl;
31727c478bd9Sstevel@tonic-gate 	old_acl_len = seg->s_acl_len;
31737c478bd9Sstevel@tonic-gate 
31747c478bd9Sstevel@tonic-gate 	seg->s_acl = new_acl;
31757c478bd9Sstevel@tonic-gate 	seg->s_acl_len = new_acl_len;
31767c478bd9Sstevel@tonic-gate 
31777c478bd9Sstevel@tonic-gate 	/*
31787c478bd9Sstevel@tonic-gate 	 * This call will only be meaningful if and when the interconnect
31797c478bd9Sstevel@tonic-gate 	 * layer makes use of the access list
31807c478bd9Sstevel@tonic-gate 	 */
31817c478bd9Sstevel@tonic-gate 	adapter = seg->s_adapter;
31827c478bd9Sstevel@tonic-gate 	/*
31837c478bd9Sstevel@tonic-gate 	 * create a acl list with hwaddr for RSMPI publish
31847c478bd9Sstevel@tonic-gate 	 */
31857c478bd9Sstevel@tonic-gate 	e = rsmpiacl_create(new_acl, &rsmpi_new_acl, new_acl_len, adapter);
31867c478bd9Sstevel@tonic-gate 
31877c478bd9Sstevel@tonic-gate 	if (e != RSM_SUCCESS) {
31887c478bd9Sstevel@tonic-gate 		seg->s_acl = old_acl;
31897c478bd9Sstevel@tonic-gate 		seg->s_acl_len = old_acl_len;
31907c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
31917c478bd9Sstevel@tonic-gate 		rsmacl_free(new_acl, new_acl_len);
31927c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
31937c478bd9Sstevel@tonic-gate 		    "rsm_republish done: rsmpiacl_create failed %d", e));
31947c478bd9Sstevel@tonic-gate 		return (e);
31957c478bd9Sstevel@tonic-gate 	}
31967c478bd9Sstevel@tonic-gate 	rsmpi_old_acl = seg->s_acl_in;
31977c478bd9Sstevel@tonic-gate 	seg->s_acl_in = rsmpi_new_acl;
31987c478bd9Sstevel@tonic-gate 
31997c478bd9Sstevel@tonic-gate 	e = adapter->rsmpi_ops->rsm_republish(seg->s_handle.out,
32007c478bd9Sstevel@tonic-gate 	    seg->s_acl_in, seg->s_acl_len,
32017c478bd9Sstevel@tonic-gate 	    RSM_RESOURCE_DONTWAIT, NULL);
32027c478bd9Sstevel@tonic-gate 
32037c478bd9Sstevel@tonic-gate 	if (e != RSM_SUCCESS) {
32047c478bd9Sstevel@tonic-gate 		seg->s_acl = old_acl;
32057c478bd9Sstevel@tonic-gate 		seg->s_acl_in = rsmpi_old_acl;
32067c478bd9Sstevel@tonic-gate 		seg->s_acl_len = old_acl_len;
32077c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
32087c478bd9Sstevel@tonic-gate 		rsmacl_free(new_acl, new_acl_len);
32097c478bd9Sstevel@tonic-gate 		rsmpiacl_free(rsmpi_new_acl, new_acl_len);
32107c478bd9Sstevel@tonic-gate 
32117c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
32127c478bd9Sstevel@tonic-gate 		    "rsm_republish done: rsmpi republish failed %d\n", e));
32137c478bd9Sstevel@tonic-gate 		return (e);
32147c478bd9Sstevel@tonic-gate 	}
32157c478bd9Sstevel@tonic-gate 
32167c478bd9Sstevel@tonic-gate 	/* create a tmp copy of the new acl */
32177c478bd9Sstevel@tonic-gate 	tmp_acl_len = new_acl_len;
32187c478bd9Sstevel@tonic-gate 	if (tmp_acl_len > 0) {
32197c478bd9Sstevel@tonic-gate 		tmp_acl = kmem_zalloc(new_acl_len*sizeof (*tmp_acl), KM_SLEEP);
32207c478bd9Sstevel@tonic-gate 		for (i = 0; i < tmp_acl_len; i++) {
32217c478bd9Sstevel@tonic-gate 			tmp_acl[i].ae_node = new_acl[i].ae_node;
32227c478bd9Sstevel@tonic-gate 			tmp_acl[i].ae_permission = new_acl[i].ae_permission;
32237c478bd9Sstevel@tonic-gate 		}
32247c478bd9Sstevel@tonic-gate 		/*
32257c478bd9Sstevel@tonic-gate 		 * The default permission of a node which was in the old
32267c478bd9Sstevel@tonic-gate 		 * ACL but not in the new ACL is 0 ie no access.
32277c478bd9Sstevel@tonic-gate 		 */
32287c478bd9Sstevel@tonic-gate 		permission = 0;
32297c478bd9Sstevel@tonic-gate 	} else {
32307c478bd9Sstevel@tonic-gate 		/*
32317c478bd9Sstevel@tonic-gate 		 * NULL acl means all importers can connect and
32327c478bd9Sstevel@tonic-gate 		 * default permission will be owner creation umask
32337c478bd9Sstevel@tonic-gate 		 */
32347c478bd9Sstevel@tonic-gate 		tmp_acl = NULL;
32357c478bd9Sstevel@tonic-gate 		permission = seg->s_mode;
32367c478bd9Sstevel@tonic-gate 	}
32377c478bd9Sstevel@tonic-gate 
32387c478bd9Sstevel@tonic-gate 	/* make other republishers to wait for republish to complete */
32397c478bd9Sstevel@tonic-gate 	seg->s_flags |= RSM_REPUBLISH_WAIT;
32407c478bd9Sstevel@tonic-gate 
32417c478bd9Sstevel@tonic-gate 	rsmseglock_release(seg);
32427c478bd9Sstevel@tonic-gate 
32437c478bd9Sstevel@tonic-gate 	/* send the new perms to the importing nodes */
32447c478bd9Sstevel@tonic-gate 	rsm_send_republish(key, tmp_acl, tmp_acl_len, permission);
32457c478bd9Sstevel@tonic-gate 
32467c478bd9Sstevel@tonic-gate 	rsmseglock_acquire(seg);
32477c478bd9Sstevel@tonic-gate 	seg->s_flags &= ~RSM_REPUBLISH_WAIT;
32487c478bd9Sstevel@tonic-gate 	/* wake up any one waiting for republish to complete */
32497c478bd9Sstevel@tonic-gate 	cv_broadcast(&seg->s_cv);
32507c478bd9Sstevel@tonic-gate 	rsmseglock_release(seg);
32517c478bd9Sstevel@tonic-gate 
32527c478bd9Sstevel@tonic-gate 	rsmacl_free(tmp_acl, tmp_acl_len);
32537c478bd9Sstevel@tonic-gate 	rsmacl_free(old_acl, old_acl_len);
32547c478bd9Sstevel@tonic-gate 	rsmpiacl_free(rsmpi_old_acl, old_acl_len);
32557c478bd9Sstevel@tonic-gate 
32567c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_republish done\n"));
32577c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
32587c478bd9Sstevel@tonic-gate }
32597c478bd9Sstevel@tonic-gate 
32607c478bd9Sstevel@tonic-gate static int
rsm_unpublish(rsmseg_t * seg,int mode)32617c478bd9Sstevel@tonic-gate rsm_unpublish(rsmseg_t *seg, int mode)
32627c478bd9Sstevel@tonic-gate {
32637c478bd9Sstevel@tonic-gate 	rsmapi_access_entry_t	*acl;
32647c478bd9Sstevel@tonic-gate 	rsm_access_entry_t	*rsmpi_acl;
32657c478bd9Sstevel@tonic-gate 	int			acl_len;
32667c478bd9Sstevel@tonic-gate 	int			e;
32677c478bd9Sstevel@tonic-gate 	adapter_t *adapter;
32687c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_EXPORT);
32697c478bd9Sstevel@tonic-gate 
32707c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_unpublish enter\n"));
32717c478bd9Sstevel@tonic-gate 
32727c478bd9Sstevel@tonic-gate 	if (seg->s_pid != ddi_get_pid() &&
32737c478bd9Sstevel@tonic-gate 	    ddi_get_pid() != 0) {
32747c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
32757c478bd9Sstevel@tonic-gate 		    "rsm_unpublish: Not creator\n"));
32767c478bd9Sstevel@tonic-gate 		return (RSMERR_NOT_CREATOR);
32777c478bd9Sstevel@tonic-gate 	}
32787c478bd9Sstevel@tonic-gate 
32797c478bd9Sstevel@tonic-gate 	rsmseglock_acquire(seg);
32807c478bd9Sstevel@tonic-gate 	/*
32817c478bd9Sstevel@tonic-gate 	 * wait for QUIESCING to complete here before rsmexport_rm
32827c478bd9Sstevel@tonic-gate 	 * is called because the SUSPEND_COMPLETE mesg which changes
32837c478bd9Sstevel@tonic-gate 	 * the seg state from EXPORT_QUIESCING to EXPORT_QUIESCED and
32847c478bd9Sstevel@tonic-gate 	 * signals the cv_wait needs to find it in the hashtable.
32857c478bd9Sstevel@tonic-gate 	 */
32867c478bd9Sstevel@tonic-gate 	while ((seg->s_state == RSM_STATE_EXPORT_QUIESCING) ||
32877c478bd9Sstevel@tonic-gate 	    ((seg->s_state == RSM_STATE_EXPORT) && (seg->s_rdmacnt > 0))) {
32887c478bd9Sstevel@tonic-gate 		if (cv_wait_sig(&seg->s_cv, &seg->s_lock) == 0) {
32897c478bd9Sstevel@tonic-gate 			rsmseglock_release(seg);
32907c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_ERR,
32917c478bd9Sstevel@tonic-gate 			    "rsm_unpublish done: cv_wait INTR qscing"
32927c478bd9Sstevel@tonic-gate 			    "getv/putv in progress"));
32937c478bd9Sstevel@tonic-gate 			return (RSMERR_INTERRUPTED);
32947c478bd9Sstevel@tonic-gate 		}
32957c478bd9Sstevel@tonic-gate 	}
32967c478bd9Sstevel@tonic-gate 
32977c478bd9Sstevel@tonic-gate 	/* verify segment state */
32987c478bd9Sstevel@tonic-gate 	if ((seg->s_state != RSM_STATE_EXPORT) &&
32997c478bd9Sstevel@tonic-gate 	    (seg->s_state != RSM_STATE_EXPORT_QUIESCED)) {
33007c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
33017c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
33027c478bd9Sstevel@tonic-gate 		    "rsm_unpublish done: bad state %x\n", seg->s_state));
33037c478bd9Sstevel@tonic-gate 		return (RSMERR_SEG_NOT_PUBLISHED);
33047c478bd9Sstevel@tonic-gate 	}
33057c478bd9Sstevel@tonic-gate 
33067c478bd9Sstevel@tonic-gate 	rsmseglock_release(seg);
33077c478bd9Sstevel@tonic-gate 
33087c478bd9Sstevel@tonic-gate 	rsmexport_rm(seg);
33097c478bd9Sstevel@tonic-gate 
33107c478bd9Sstevel@tonic-gate 	rsm_send_importer_disconnects(seg->s_segid, my_nodeid);
33117c478bd9Sstevel@tonic-gate 
33127c478bd9Sstevel@tonic-gate 	rsmseglock_acquire(seg);
33137c478bd9Sstevel@tonic-gate 	/*
33147c478bd9Sstevel@tonic-gate 	 * wait for republish to complete
33157c478bd9Sstevel@tonic-gate 	 */
33167c478bd9Sstevel@tonic-gate 	while ((seg->s_state == RSM_STATE_EXPORT) &&
33177c478bd9Sstevel@tonic-gate 	    (seg->s_flags & RSM_REPUBLISH_WAIT)) {
33187c478bd9Sstevel@tonic-gate 		if (cv_wait_sig(&seg->s_cv, &seg->s_lock) == 0) {
33197c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_ERR,
33207c478bd9Sstevel@tonic-gate 			    "rsm_unpublish done: cv_wait INTR repubing"));
33217c478bd9Sstevel@tonic-gate 			rsmseglock_release(seg);
33227c478bd9Sstevel@tonic-gate 			return (RSMERR_INTERRUPTED);
33237c478bd9Sstevel@tonic-gate 		}
33247c478bd9Sstevel@tonic-gate 	}
33257c478bd9Sstevel@tonic-gate 
33267c478bd9Sstevel@tonic-gate 	if ((seg->s_state != RSM_STATE_EXPORT) &&
33277c478bd9Sstevel@tonic-gate 	    (seg->s_state != RSM_STATE_EXPORT_QUIESCED)) {
33287c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
33297c478bd9Sstevel@tonic-gate 		    "rsm_unpublish done: invalid state"));
33307c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
33317c478bd9Sstevel@tonic-gate 		return (RSMERR_SEG_NOT_PUBLISHED);
33327c478bd9Sstevel@tonic-gate 	}
33337c478bd9Sstevel@tonic-gate 
33347c478bd9Sstevel@tonic-gate 	/*
33357c478bd9Sstevel@tonic-gate 	 * check for putv/get surrogate segment which was not published
33367c478bd9Sstevel@tonic-gate 	 * to the driver.
33377c478bd9Sstevel@tonic-gate 	 *
33387c478bd9Sstevel@tonic-gate 	 * Be certain to see if there is an ACL first!  If this segment was
33397c478bd9Sstevel@tonic-gate 	 * not published with an ACL, acl will be a null pointer.  Check
33407c478bd9Sstevel@tonic-gate 	 * that before dereferencing it.
33417c478bd9Sstevel@tonic-gate 	 */
33427c478bd9Sstevel@tonic-gate 	acl = seg->s_acl;
33437c478bd9Sstevel@tonic-gate 	if (acl != (rsmapi_access_entry_t *)NULL) {
33447c478bd9Sstevel@tonic-gate 		if (acl[0].ae_node == my_nodeid && acl[0].ae_permission == 0)
33457c478bd9Sstevel@tonic-gate 			goto bypass;
33467c478bd9Sstevel@tonic-gate 	}
33477c478bd9Sstevel@tonic-gate 
33487c478bd9Sstevel@tonic-gate 	/* The RSMPI unpublish/destroy has been done if seg is QUIESCED */
33497c478bd9Sstevel@tonic-gate 	if (seg->s_state == RSM_STATE_EXPORT_QUIESCED)
33507c478bd9Sstevel@tonic-gate 		goto bypass;
33517c478bd9Sstevel@tonic-gate 
33527c478bd9Sstevel@tonic-gate 	adapter = seg->s_adapter;
33537c478bd9Sstevel@tonic-gate 	for (;;) {
33547c478bd9Sstevel@tonic-gate 		if (seg->s_state != RSM_STATE_EXPORT) {
33557c478bd9Sstevel@tonic-gate 			rsmseglock_release(seg);
33567c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_ERR,
33577c478bd9Sstevel@tonic-gate 			    "rsm_unpublish done: bad state %x\n",
33587c478bd9Sstevel@tonic-gate 			    seg->s_state));
33597c478bd9Sstevel@tonic-gate 			return (RSMERR_SEG_NOT_PUBLISHED);
33607c478bd9Sstevel@tonic-gate 		}
33617c478bd9Sstevel@tonic-gate 
33627c478bd9Sstevel@tonic-gate 		/* unpublish from adapter */
33637c478bd9Sstevel@tonic-gate 		e = adapter->rsmpi_ops->rsm_unpublish(seg->s_handle.out);
33647c478bd9Sstevel@tonic-gate 
33657c478bd9Sstevel@tonic-gate 		if (e == RSM_SUCCESS) {
33667c478bd9Sstevel@tonic-gate 			break;
33677c478bd9Sstevel@tonic-gate 		}
33687c478bd9Sstevel@tonic-gate 
33697c478bd9Sstevel@tonic-gate 		if (e == RSMERR_SEG_IN_USE && mode == 1) {
33707c478bd9Sstevel@tonic-gate 			/*
33717c478bd9Sstevel@tonic-gate 			 * wait for unpublish to succeed, it's busy.
33727c478bd9Sstevel@tonic-gate 			 */
33737c478bd9Sstevel@tonic-gate 			seg->s_flags |= RSM_EXPORT_WAIT;
33747c478bd9Sstevel@tonic-gate 
33757c478bd9Sstevel@tonic-gate 			/* wait for a max of 1 ms - this is an empirical */
33767c478bd9Sstevel@tonic-gate 			/* value that was found by some minimal testing  */
33777c478bd9Sstevel@tonic-gate 			/* can be fine tuned when we have better numbers */
33787c478bd9Sstevel@tonic-gate 			/* A long term fix would be to send cv_signal	 */
33797c478bd9Sstevel@tonic-gate 			/* from the intr callback routine		 */
33807c478bd9Sstevel@tonic-gate 			/* currently nobody signals this wait		 */
3381d3d50737SRafael Vanoni 			(void) cv_reltimedwait(&seg->s_cv, &seg->s_lock,
3382d3d50737SRafael Vanoni 			    drv_usectohz(1000), TR_CLOCK_TICK);
33837c478bd9Sstevel@tonic-gate 
33847c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_ERR,
33857c478bd9Sstevel@tonic-gate 			    "rsm_unpublish: SEG_IN_USE\n"));
33867c478bd9Sstevel@tonic-gate 
33877c478bd9Sstevel@tonic-gate 			seg->s_flags &= ~RSM_EXPORT_WAIT;
33887c478bd9Sstevel@tonic-gate 		} else {
33897c478bd9Sstevel@tonic-gate 			if (mode == 1) {
33907c478bd9Sstevel@tonic-gate 				DBG_PRINTF((category, RSM_ERR,
33917c478bd9Sstevel@tonic-gate 				    "rsm:rsmpi unpublish err %x\n", e));
33927c478bd9Sstevel@tonic-gate 				seg->s_state = RSM_STATE_BIND;
33937c478bd9Sstevel@tonic-gate 			}
33947c478bd9Sstevel@tonic-gate 			rsmseglock_release(seg);
33957c478bd9Sstevel@tonic-gate 			return (e);
33967c478bd9Sstevel@tonic-gate 		}
33977c478bd9Sstevel@tonic-gate 	}
33987c478bd9Sstevel@tonic-gate 
33997c478bd9Sstevel@tonic-gate 	/* Free segment */
34007c478bd9Sstevel@tonic-gate 	e = adapter->rsmpi_ops->rsm_seg_destroy(seg->s_handle.out);
34017c478bd9Sstevel@tonic-gate 
34027c478bd9Sstevel@tonic-gate 	if (e != RSM_SUCCESS) {
34037c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
34047c478bd9Sstevel@tonic-gate 		    "rsm_unpublish: rsmpi destroy key=%x failed %x\n",
34057c478bd9Sstevel@tonic-gate 		    seg->s_key, e));
34067c478bd9Sstevel@tonic-gate 	}
34077c478bd9Sstevel@tonic-gate 
34087c478bd9Sstevel@tonic-gate bypass:
34097c478bd9Sstevel@tonic-gate 	acl = seg->s_acl;
34107c478bd9Sstevel@tonic-gate 	rsmpi_acl = seg->s_acl_in;
34117c478bd9Sstevel@tonic-gate 	acl_len = seg->s_acl_len;
34127c478bd9Sstevel@tonic-gate 
34137c478bd9Sstevel@tonic-gate 	seg->s_acl = NULL;
34147c478bd9Sstevel@tonic-gate 	seg->s_acl_in = NULL;
34157c478bd9Sstevel@tonic-gate 	seg->s_acl_len = 0;
34167c478bd9Sstevel@tonic-gate 
34177c478bd9Sstevel@tonic-gate 	if (seg->s_state == RSM_STATE_EXPORT) {
34187c478bd9Sstevel@tonic-gate 		seg->s_state = RSM_STATE_BIND;
34197c478bd9Sstevel@tonic-gate 	} else if (seg->s_state == RSM_STATE_EXPORT_QUIESCED) {
34207c478bd9Sstevel@tonic-gate 		seg->s_state = RSM_STATE_BIND_QUIESCED;
34217c478bd9Sstevel@tonic-gate 		cv_broadcast(&seg->s_cv);
34227c478bd9Sstevel@tonic-gate 	}
34237c478bd9Sstevel@tonic-gate 
34247c478bd9Sstevel@tonic-gate 	rsmseglock_release(seg);
34257c478bd9Sstevel@tonic-gate 
34267c478bd9Sstevel@tonic-gate 	rsmacl_free(acl, acl_len);
34277c478bd9Sstevel@tonic-gate 	rsmpiacl_free(rsmpi_acl, acl_len);
34287c478bd9Sstevel@tonic-gate 
34297c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_unpublish done\n"));
34307c478bd9Sstevel@tonic-gate 
34317c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
34327c478bd9Sstevel@tonic-gate }
34337c478bd9Sstevel@tonic-gate 
34347c478bd9Sstevel@tonic-gate /*
34357c478bd9Sstevel@tonic-gate  * Called from rsm_unpublish to force an unload and disconnection of all
34367c478bd9Sstevel@tonic-gate  * importers of the unpublished segment.
34377c478bd9Sstevel@tonic-gate  *
34387c478bd9Sstevel@tonic-gate  * First build the list of segments requiring a force disconnect, then
34397c478bd9Sstevel@tonic-gate  * send a request for each.
34407c478bd9Sstevel@tonic-gate  */
34417c478bd9Sstevel@tonic-gate static void
rsm_send_importer_disconnects(rsm_memseg_id_t ex_segid,rsm_node_id_t ex_nodeid)34427c478bd9Sstevel@tonic-gate rsm_send_importer_disconnects(rsm_memseg_id_t ex_segid,
34437c478bd9Sstevel@tonic-gate     rsm_node_id_t ex_nodeid)
34447c478bd9Sstevel@tonic-gate {
34457c478bd9Sstevel@tonic-gate 	rsmipc_request_t 	request;
34467c478bd9Sstevel@tonic-gate 	importing_token_t	*prev_token, *token, *tmp_token, *tokp;
34477c478bd9Sstevel@tonic-gate 	importing_token_t	*force_disconnect_list = NULL;
34487c478bd9Sstevel@tonic-gate 	int			index;
34497c478bd9Sstevel@tonic-gate 
34507c478bd9Sstevel@tonic-gate 	DBG_PRINTF((RSM_KERNEL_AGENT | RSM_EXPORT, RSM_DEBUG_VERBOSE,
34517c478bd9Sstevel@tonic-gate 	    "rsm_send_importer_disconnects enter\n"));
34527c478bd9Sstevel@tonic-gate 
34537c478bd9Sstevel@tonic-gate 	index = rsmhash(ex_segid);
34547c478bd9Sstevel@tonic-gate 
34557c478bd9Sstevel@tonic-gate 	mutex_enter(&importer_list.lock);
34567c478bd9Sstevel@tonic-gate 
34577c478bd9Sstevel@tonic-gate 	prev_token = NULL;
34587c478bd9Sstevel@tonic-gate 	token = importer_list.bucket[index];
34597c478bd9Sstevel@tonic-gate 
34607c478bd9Sstevel@tonic-gate 	while (token != NULL) {
34617c478bd9Sstevel@tonic-gate 		if (token->key == ex_segid) {
34627c478bd9Sstevel@tonic-gate 			/*
34637c478bd9Sstevel@tonic-gate 			 * take it off the importer list and add it
34647c478bd9Sstevel@tonic-gate 			 * to the force disconnect list.
34657c478bd9Sstevel@tonic-gate 			 */
34667c478bd9Sstevel@tonic-gate 			if (prev_token == NULL)
34677c478bd9Sstevel@tonic-gate 				importer_list.bucket[index] = token->next;
34687c478bd9Sstevel@tonic-gate 			else
34697c478bd9Sstevel@tonic-gate 				prev_token->next = token->next;
34707c478bd9Sstevel@tonic-gate 			tmp_token = token;
34717c478bd9Sstevel@tonic-gate 			token = token->next;
34727c478bd9Sstevel@tonic-gate 			if (force_disconnect_list == NULL) {
34737c478bd9Sstevel@tonic-gate 				force_disconnect_list = tmp_token;
34747c478bd9Sstevel@tonic-gate 				tmp_token->next = NULL;
34757c478bd9Sstevel@tonic-gate 			} else {
34767c478bd9Sstevel@tonic-gate 				tokp = force_disconnect_list;
34777c478bd9Sstevel@tonic-gate 				/*
34787c478bd9Sstevel@tonic-gate 				 * make sure that the tmp_token's node
34797c478bd9Sstevel@tonic-gate 				 * is not already on the force disconnect
34807c478bd9Sstevel@tonic-gate 				 * list.
34817c478bd9Sstevel@tonic-gate 				 */
34827c478bd9Sstevel@tonic-gate 				while (tokp != NULL) {
34837c478bd9Sstevel@tonic-gate 					if (tokp->importing_node ==
34847c478bd9Sstevel@tonic-gate 					    tmp_token->importing_node) {
34857c478bd9Sstevel@tonic-gate 						break;
34867c478bd9Sstevel@tonic-gate 					}
34877c478bd9Sstevel@tonic-gate 					tokp = tokp->next;
34887c478bd9Sstevel@tonic-gate 				}
34897c478bd9Sstevel@tonic-gate 				if (tokp == NULL) {
34907c478bd9Sstevel@tonic-gate 					tmp_token->next =
34917c478bd9Sstevel@tonic-gate 					    force_disconnect_list;
34927c478bd9Sstevel@tonic-gate 					force_disconnect_list = tmp_token;
34937c478bd9Sstevel@tonic-gate 				} else {
34947c478bd9Sstevel@tonic-gate 					kmem_free((void *)tmp_token,
34957c478bd9Sstevel@tonic-gate 					    sizeof (*token));
34967c478bd9Sstevel@tonic-gate 				}
34977c478bd9Sstevel@tonic-gate 			}
34987c478bd9Sstevel@tonic-gate 
34997c478bd9Sstevel@tonic-gate 		} else {
35007c478bd9Sstevel@tonic-gate 			prev_token = token;
35017c478bd9Sstevel@tonic-gate 			token = token->next;
35027c478bd9Sstevel@tonic-gate 		}
35037c478bd9Sstevel@tonic-gate 	}
35047c478bd9Sstevel@tonic-gate 	mutex_exit(&importer_list.lock);
35057c478bd9Sstevel@tonic-gate 
35067c478bd9Sstevel@tonic-gate 	token = force_disconnect_list;
35077c478bd9Sstevel@tonic-gate 	while (token != NULL) {
35087c478bd9Sstevel@tonic-gate 		if (token->importing_node == my_nodeid) {
35097c478bd9Sstevel@tonic-gate 			rsm_force_unload(ex_nodeid, ex_segid,
35107c478bd9Sstevel@tonic-gate 			    DISCONNECT);
35117c478bd9Sstevel@tonic-gate 		} else {
35127c478bd9Sstevel@tonic-gate 			request.rsmipc_hdr.rsmipc_type =
35137c478bd9Sstevel@tonic-gate 			    RSMIPC_MSG_DISCONNECT;
35147c478bd9Sstevel@tonic-gate 			request.rsmipc_key = token->key;
35155dd2c7e9Sjg97986 			for (;;) {
35165dd2c7e9Sjg97986 				if (rsmipc_send(token->importing_node,
35177c478bd9Sstevel@tonic-gate 				    &request,
35185dd2c7e9Sjg97986 				    RSM_NO_REPLY) == RSM_SUCCESS) {
35195dd2c7e9Sjg97986 					break;
35205dd2c7e9Sjg97986 				} else {
35215dd2c7e9Sjg97986 					delay(drv_usectohz(10000));
35225dd2c7e9Sjg97986 				}
35235dd2c7e9Sjg97986 			}
35247c478bd9Sstevel@tonic-gate 		}
35257c478bd9Sstevel@tonic-gate 		tmp_token = token;
35267c478bd9Sstevel@tonic-gate 		token = token->next;
35277c478bd9Sstevel@tonic-gate 		kmem_free((void *)tmp_token, sizeof (*token));
35287c478bd9Sstevel@tonic-gate 	}
35297c478bd9Sstevel@tonic-gate 
35307c478bd9Sstevel@tonic-gate 	DBG_PRINTF((RSM_KERNEL_AGENT | RSM_EXPORT, RSM_DEBUG_VERBOSE,
35317c478bd9Sstevel@tonic-gate 	    "rsm_send_importer_disconnects done\n"));
35327c478bd9Sstevel@tonic-gate }
35337c478bd9Sstevel@tonic-gate 
35347c478bd9Sstevel@tonic-gate /*
35357c478bd9Sstevel@tonic-gate  * This function is used as a callback for unlocking the pages locked
35367c478bd9Sstevel@tonic-gate  * down by a process which then does a fork or an exec.
35377c478bd9Sstevel@tonic-gate  * It marks the export segments corresponding to umem cookie given by
35387c478bd9Sstevel@tonic-gate  * the *arg to be in a ZOMBIE state(by calling rsmseg_close to be
35397c478bd9Sstevel@tonic-gate  * destroyed later when an rsm_close occurs).
35407c478bd9Sstevel@tonic-gate  */
35417c478bd9Sstevel@tonic-gate static void
rsm_export_force_destroy(ddi_umem_cookie_t * ck)35427c478bd9Sstevel@tonic-gate rsm_export_force_destroy(ddi_umem_cookie_t *ck)
35437c478bd9Sstevel@tonic-gate {
35447c478bd9Sstevel@tonic-gate 	rsmresource_blk_t *blk;
35457c478bd9Sstevel@tonic-gate 	rsmresource_t *p;
35467c478bd9Sstevel@tonic-gate 	rsmseg_t *eseg = NULL;
35477c478bd9Sstevel@tonic-gate 	int i, j;
35487c478bd9Sstevel@tonic-gate 	int found = 0;
35497c478bd9Sstevel@tonic-gate 
35507c478bd9Sstevel@tonic-gate 	DBG_PRINTF((RSM_KERNEL_AGENT | RSM_EXPORT, RSM_DEBUG_VERBOSE,
35517c478bd9Sstevel@tonic-gate 	    "rsm_export_force_destroy enter\n"));
35527c478bd9Sstevel@tonic-gate 
35537c478bd9Sstevel@tonic-gate 	/*
35547c478bd9Sstevel@tonic-gate 	 * Walk the resource list and locate the export segment (either
35557c478bd9Sstevel@tonic-gate 	 * in the BIND or the EXPORT state) which corresponds to the
35567c478bd9Sstevel@tonic-gate 	 * ddi_umem_cookie_t being freed up, and call rsmseg_close.
35577c478bd9Sstevel@tonic-gate 	 * Change the state to ZOMBIE by calling rsmseg_close with the
35587c478bd9Sstevel@tonic-gate 	 * force_flag argument (the second argument) set to 1. Also,
35597c478bd9Sstevel@tonic-gate 	 * unpublish and unbind the segment, but don't free it. Free it
35607c478bd9Sstevel@tonic-gate 	 * only on a rsm_close call for the segment.
35617c478bd9Sstevel@tonic-gate 	 */
35627c478bd9Sstevel@tonic-gate 	rw_enter(&rsm_resource.rsmrc_lock, RW_READER);
35637c478bd9Sstevel@tonic-gate 
35647c478bd9Sstevel@tonic-gate 	for (i = 0; i < rsm_resource.rsmrc_len; i++) {
35657c478bd9Sstevel@tonic-gate 		blk = rsm_resource.rsmrc_root[i];
35667c478bd9Sstevel@tonic-gate 		if (blk == NULL) {
35677c478bd9Sstevel@tonic-gate 			continue;
35687c478bd9Sstevel@tonic-gate 		}
35697c478bd9Sstevel@tonic-gate 
35707c478bd9Sstevel@tonic-gate 		for (j = 0; j < RSMRC_BLKSZ; j++) {
35717c478bd9Sstevel@tonic-gate 			p = blk->rsmrcblk_blks[j];
35727c478bd9Sstevel@tonic-gate 			if ((p != NULL) && (p != RSMRC_RESERVED) &&
35737c478bd9Sstevel@tonic-gate 			    (p->rsmrc_type == RSM_RESOURCE_EXPORT_SEGMENT)) {
35747c478bd9Sstevel@tonic-gate 				eseg = (rsmseg_t *)p;
35757c478bd9Sstevel@tonic-gate 				if (eseg->s_cookie != ck)
35767c478bd9Sstevel@tonic-gate 					continue; /* continue searching */
35777c478bd9Sstevel@tonic-gate 				/*
35787c478bd9Sstevel@tonic-gate 				 * Found the segment, set flag to indicate
35797c478bd9Sstevel@tonic-gate 				 * force destroy processing is in progress
35807c478bd9Sstevel@tonic-gate 				 */
35817c478bd9Sstevel@tonic-gate 				rsmseglock_acquire(eseg);
35827c478bd9Sstevel@tonic-gate 				eseg->s_flags |= RSM_FORCE_DESTROY_WAIT;
35837c478bd9Sstevel@tonic-gate 				rsmseglock_release(eseg);
35847c478bd9Sstevel@tonic-gate 				found = 1;
35857c478bd9Sstevel@tonic-gate 				break;
35867c478bd9Sstevel@tonic-gate 			}
35877c478bd9Sstevel@tonic-gate 		}
35887c478bd9Sstevel@tonic-gate 
35897c478bd9Sstevel@tonic-gate 		if (found)
35907c478bd9Sstevel@tonic-gate 			break;
35917c478bd9Sstevel@tonic-gate 	}
35927c478bd9Sstevel@tonic-gate 
35937c478bd9Sstevel@tonic-gate 	rw_exit(&rsm_resource.rsmrc_lock);
35947c478bd9Sstevel@tonic-gate 
35957c478bd9Sstevel@tonic-gate 	if (found) {
35967c478bd9Sstevel@tonic-gate 		ASSERT(eseg != NULL);
35977c478bd9Sstevel@tonic-gate 		/* call rsmseg_close with force flag set to 1 */
35987c478bd9Sstevel@tonic-gate 		rsmseg_close(eseg, 1);
35997c478bd9Sstevel@tonic-gate 		/*
36007c478bd9Sstevel@tonic-gate 		 * force destroy processing done, clear flag and signal any
36017c478bd9Sstevel@tonic-gate 		 * thread waiting in rsmseg_close.
36027c478bd9Sstevel@tonic-gate 		 */
36037c478bd9Sstevel@tonic-gate 		rsmseglock_acquire(eseg);
36047c478bd9Sstevel@tonic-gate 		eseg->s_flags &= ~RSM_FORCE_DESTROY_WAIT;
36057c478bd9Sstevel@tonic-gate 		cv_broadcast(&eseg->s_cv);
36067c478bd9Sstevel@tonic-gate 		rsmseglock_release(eseg);
36077c478bd9Sstevel@tonic-gate 	}
36087c478bd9Sstevel@tonic-gate 
36097c478bd9Sstevel@tonic-gate 	DBG_PRINTF((RSM_KERNEL_AGENT | RSM_EXPORT, RSM_DEBUG_VERBOSE,
36107c478bd9Sstevel@tonic-gate 	    "rsm_export_force_destroy done\n"));
36117c478bd9Sstevel@tonic-gate }
36127c478bd9Sstevel@tonic-gate 
36137c478bd9Sstevel@tonic-gate /* ******************************* Remote Calls *********************** */
36147c478bd9Sstevel@tonic-gate static void
rsm_intr_segconnect(rsm_node_id_t src,rsmipc_request_t * req)36157c478bd9Sstevel@tonic-gate rsm_intr_segconnect(rsm_node_id_t src, rsmipc_request_t *req)
36167c478bd9Sstevel@tonic-gate {
36177c478bd9Sstevel@tonic-gate 	rsmipc_reply_t reply;
36187c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category,
36197c478bd9Sstevel@tonic-gate 	    RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_INTR_CALLBACK);
36207c478bd9Sstevel@tonic-gate 
36217c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
36227c478bd9Sstevel@tonic-gate 	    "rsm_intr_segconnect enter\n"));
36237c478bd9Sstevel@tonic-gate 
36247c478bd9Sstevel@tonic-gate 	reply.rsmipc_status = (short)rsmsegacl_validate(req, src, &reply);
36257c478bd9Sstevel@tonic-gate 
36267c478bd9Sstevel@tonic-gate 	reply.rsmipc_hdr.rsmipc_type = RSMIPC_MSG_REPLY;
36277c478bd9Sstevel@tonic-gate 	reply.rsmipc_hdr.rsmipc_cookie = req->rsmipc_hdr.rsmipc_cookie;
36287c478bd9Sstevel@tonic-gate 
36297c478bd9Sstevel@tonic-gate 	(void) rsmipc_send(src, NULL, &reply);
36307c478bd9Sstevel@tonic-gate 
36317c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
36327c478bd9Sstevel@tonic-gate 	    "rsm_intr_segconnect done\n"));
36337c478bd9Sstevel@tonic-gate }
36347c478bd9Sstevel@tonic-gate 
36357c478bd9Sstevel@tonic-gate 
36367c478bd9Sstevel@tonic-gate /*
36377c478bd9Sstevel@tonic-gate  * When an exported segment is unpublished the exporter sends an ipc
36387c478bd9Sstevel@tonic-gate  * message (RSMIPC_MSG_DISCONNECT) to all importers.  The recv ipc dispatcher
36397c478bd9Sstevel@tonic-gate  * calls this function.  The import list is scanned; segments which match the
36407c478bd9Sstevel@tonic-gate  * exported segment id are unloaded and disconnected.
36417c478bd9Sstevel@tonic-gate  *
36427c478bd9Sstevel@tonic-gate  * Will also be called from rsm_rebind with disconnect_flag FALSE.
36437c478bd9Sstevel@tonic-gate  *
36447c478bd9Sstevel@tonic-gate  */
36457c478bd9Sstevel@tonic-gate static void
rsm_force_unload(rsm_node_id_t src_nodeid,rsm_memseg_id_t ex_segid,boolean_t disconnect_flag)36467c478bd9Sstevel@tonic-gate rsm_force_unload(rsm_node_id_t src_nodeid,
36477c478bd9Sstevel@tonic-gate     rsm_memseg_id_t ex_segid,
36487c478bd9Sstevel@tonic-gate     boolean_t disconnect_flag)
36497c478bd9Sstevel@tonic-gate 
36507c478bd9Sstevel@tonic-gate {
36517c478bd9Sstevel@tonic-gate 	rsmresource_t	*p = NULL;
36527c478bd9Sstevel@tonic-gate 	rsmhash_table_t *rhash = &rsm_import_segs;
36537c478bd9Sstevel@tonic-gate 	uint_t		index;
36547c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category,
36557c478bd9Sstevel@tonic-gate 	    RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_INTR_CALLBACK);
36567c478bd9Sstevel@tonic-gate 
36577c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_force_unload enter\n"));
36587c478bd9Sstevel@tonic-gate 
36597c478bd9Sstevel@tonic-gate 	index = rsmhash(ex_segid);
36607c478bd9Sstevel@tonic-gate 
36617c478bd9Sstevel@tonic-gate 	rw_enter(&rhash->rsmhash_rw, RW_READER);
36627c478bd9Sstevel@tonic-gate 
36637c478bd9Sstevel@tonic-gate 	p = rsmhash_getbkt(rhash, index);
36647c478bd9Sstevel@tonic-gate 
36657c478bd9Sstevel@tonic-gate 	for (; p; p = p->rsmrc_next) {
36667c478bd9Sstevel@tonic-gate 		rsmseg_t *seg = (rsmseg_t *)p;
36677c478bd9Sstevel@tonic-gate 		if ((seg->s_segid == ex_segid) && (seg->s_node == src_nodeid)) {
36687c478bd9Sstevel@tonic-gate 			/*
36697c478bd9Sstevel@tonic-gate 			 * In order to make rsmseg_unload and rsm_force_unload
36707c478bd9Sstevel@tonic-gate 			 * thread safe, acquire the segment lock here.
36717c478bd9Sstevel@tonic-gate 			 * rsmseg_unload is responsible for releasing the lock.
36727c478bd9Sstevel@tonic-gate 			 * rsmseg_unload releases the lock just before a call
36737c478bd9Sstevel@tonic-gate 			 * to rsmipc_send or in case of an early exit which
36747c478bd9Sstevel@tonic-gate 			 * occurs if the segment was in the state
36757c478bd9Sstevel@tonic-gate 			 * RSM_STATE_CONNECTING or RSM_STATE_NEW.
36767c478bd9Sstevel@tonic-gate 			 */
36777c478bd9Sstevel@tonic-gate 			rsmseglock_acquire(seg);
36787c478bd9Sstevel@tonic-gate 			if (disconnect_flag)
36797c478bd9Sstevel@tonic-gate 				seg->s_flags |= RSM_FORCE_DISCONNECT;
36807c478bd9Sstevel@tonic-gate 			rsmseg_unload(seg);
36817c478bd9Sstevel@tonic-gate 		}
36827c478bd9Sstevel@tonic-gate 	}
36837c478bd9Sstevel@tonic-gate 	rw_exit(&rhash->rsmhash_rw);
36847c478bd9Sstevel@tonic-gate 
36857c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_force_unload done\n"));
36867c478bd9Sstevel@tonic-gate }
36877c478bd9Sstevel@tonic-gate 
36887c478bd9Sstevel@tonic-gate static void
rsm_intr_reply(rsmipc_msghdr_t * msg)36897c478bd9Sstevel@tonic-gate rsm_intr_reply(rsmipc_msghdr_t *msg)
36907c478bd9Sstevel@tonic-gate {
36917c478bd9Sstevel@tonic-gate 	/*
36927c478bd9Sstevel@tonic-gate 	 * Find slot for cookie in reply.
36937c478bd9Sstevel@tonic-gate 	 * Match sequence with sequence in cookie
36947c478bd9Sstevel@tonic-gate 	 * If no match; return
36957c478bd9Sstevel@tonic-gate 	 * Try to grap lock of slot, if locked return
36967c478bd9Sstevel@tonic-gate 	 * copy data into reply slot area
36977c478bd9Sstevel@tonic-gate 	 * signal waiter
36987c478bd9Sstevel@tonic-gate 	 */
36997c478bd9Sstevel@tonic-gate 	rsmipc_slot_t 	*slot;
37007c478bd9Sstevel@tonic-gate 	rsmipc_cookie_t	*cookie;
37017c478bd9Sstevel@tonic-gate 	void *data = (void *) msg;
37027c478bd9Sstevel@tonic-gate 	size_t size = sizeof (rsmipc_reply_t);
37037c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category,
37047c478bd9Sstevel@tonic-gate 	    RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_INTR_CALLBACK);
37057c478bd9Sstevel@tonic-gate 
37067c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_intr_reply enter\n"));
37077c478bd9Sstevel@tonic-gate 
37087c478bd9Sstevel@tonic-gate 	cookie = &msg->rsmipc_cookie;
37097c478bd9Sstevel@tonic-gate 	if (cookie->ic.index >= RSMIPC_SZ) {
37107c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
37117c478bd9Sstevel@tonic-gate 		    "rsm: rsm_intr_reply bad cookie %d\n", cookie->ic.index));
37127c478bd9Sstevel@tonic-gate 		return;
37137c478bd9Sstevel@tonic-gate 	}
37147c478bd9Sstevel@tonic-gate 
37157c478bd9Sstevel@tonic-gate 	ASSERT(cookie->ic.index < RSMIPC_SZ);
37167c478bd9Sstevel@tonic-gate 	slot = &rsm_ipc.slots[cookie->ic.index];
37177c478bd9Sstevel@tonic-gate 	mutex_enter(&slot->rsmipc_lock);
37187c478bd9Sstevel@tonic-gate 	if (slot->rsmipc_cookie.value == cookie->value) {
37197c478bd9Sstevel@tonic-gate 		/* found a match */
37207c478bd9Sstevel@tonic-gate 		if (RSMIPC_GET(slot, RSMIPC_PENDING)) {
37217c478bd9Sstevel@tonic-gate 			bcopy(data, slot->rsmipc_data, size);
37227c478bd9Sstevel@tonic-gate 			RSMIPC_CLEAR(slot, RSMIPC_PENDING);
37237c478bd9Sstevel@tonic-gate 			cv_signal(&slot->rsmipc_cv);
37247c478bd9Sstevel@tonic-gate 		}
37257c478bd9Sstevel@tonic-gate 	} else {
37267c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG,
37277c478bd9Sstevel@tonic-gate 		    "rsm: rsm_intr_reply mismatched reply %d\n",
37287c478bd9Sstevel@tonic-gate 		    cookie->ic.index));
37297c478bd9Sstevel@tonic-gate 	}
37307c478bd9Sstevel@tonic-gate 	mutex_exit(&slot->rsmipc_lock);
37317c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_intr_reply done\n"));
37327c478bd9Sstevel@tonic-gate }
37337c478bd9Sstevel@tonic-gate 
37347c478bd9Sstevel@tonic-gate /*
37357c478bd9Sstevel@tonic-gate  * This function gets dispatched on the worker thread when we receive
37367c478bd9Sstevel@tonic-gate  * the SQREADY message. This function sends the SQREADY_ACK message.
37377c478bd9Sstevel@tonic-gate  */
37387c478bd9Sstevel@tonic-gate static void
rsm_sqready_ack_deferred(void * arg)37397c478bd9Sstevel@tonic-gate rsm_sqready_ack_deferred(void *arg)
37407c478bd9Sstevel@tonic-gate {
37417c478bd9Sstevel@tonic-gate 	path_t	*path = (path_t *)arg;
37427c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category,
37437c478bd9Sstevel@tonic-gate 	    RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_INTR_CALLBACK);
37447c478bd9Sstevel@tonic-gate 
37457c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
37467c478bd9Sstevel@tonic-gate 	    "rsm_sqready_ack_deferred enter\n"));
37477c478bd9Sstevel@tonic-gate 
37487c478bd9Sstevel@tonic-gate 	mutex_enter(&path->mutex);
37497c478bd9Sstevel@tonic-gate 
37507c478bd9Sstevel@tonic-gate 	/*
37517c478bd9Sstevel@tonic-gate 	 * If path is not active no point in sending the ACK
37527c478bd9Sstevel@tonic-gate 	 * because the whole SQREADY protocol will again start
37537c478bd9Sstevel@tonic-gate 	 * when the path becomes active.
37547c478bd9Sstevel@tonic-gate 	 */
37557c478bd9Sstevel@tonic-gate 	if (path->state != RSMKA_PATH_ACTIVE) {
37567c478bd9Sstevel@tonic-gate 		/*
37577c478bd9Sstevel@tonic-gate 		 * decrement the path refcnt incremented in rsm_proc_sqready
37587c478bd9Sstevel@tonic-gate 		 */
37597c478bd9Sstevel@tonic-gate 		PATH_RELE_NOLOCK(path);
37607c478bd9Sstevel@tonic-gate 		mutex_exit(&path->mutex);
37617c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
37627c478bd9Sstevel@tonic-gate 		    "rsm_sqready_ack_deferred done:!ACTIVE\n"));
37637c478bd9Sstevel@tonic-gate 		return;
37647c478bd9Sstevel@tonic-gate 	}
37657c478bd9Sstevel@tonic-gate 
37667c478bd9Sstevel@tonic-gate 	/* send an SQREADY_ACK message */
37677c478bd9Sstevel@tonic-gate 	(void) rsmipc_send_controlmsg(path, RSMIPC_MSG_SQREADY_ACK);
37687c478bd9Sstevel@tonic-gate 
37697c478bd9Sstevel@tonic-gate 	/* initialize credits to the max level */
37707c478bd9Sstevel@tonic-gate 	path->sendq_token.msgbuf_avail = RSMIPC_MAX_MESSAGES;
37717c478bd9Sstevel@tonic-gate 
37727c478bd9Sstevel@tonic-gate 	/* wake up any send that is waiting for credits */
37737c478bd9Sstevel@tonic-gate 	cv_broadcast(&path->sendq_token.sendq_cv);
37747c478bd9Sstevel@tonic-gate 
37757c478bd9Sstevel@tonic-gate 	/*
37767c478bd9Sstevel@tonic-gate 	 * decrement the path refcnt since we incremented it in
37777c478bd9Sstevel@tonic-gate 	 * rsm_proc_sqready
37787c478bd9Sstevel@tonic-gate 	 */
37797c478bd9Sstevel@tonic-gate 	PATH_RELE_NOLOCK(path);
37807c478bd9Sstevel@tonic-gate 
37817c478bd9Sstevel@tonic-gate 	mutex_exit(&path->mutex);
37827c478bd9Sstevel@tonic-gate 
37837c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
37847c478bd9Sstevel@tonic-gate 	    "rsm_sqready_ack_deferred done\n"));
37857c478bd9Sstevel@tonic-gate }
37867c478bd9Sstevel@tonic-gate 
37877c478bd9Sstevel@tonic-gate /*
37887c478bd9Sstevel@tonic-gate  * Process the SQREADY message
37897c478bd9Sstevel@tonic-gate  */
37907c478bd9Sstevel@tonic-gate static void
rsm_proc_sqready(rsmipc_controlmsg_t * msg,rsm_addr_t src_hwaddr,rsm_intr_hand_arg_t arg)37917c478bd9Sstevel@tonic-gate rsm_proc_sqready(rsmipc_controlmsg_t *msg, rsm_addr_t src_hwaddr,
37927c478bd9Sstevel@tonic-gate     rsm_intr_hand_arg_t arg)
37937c478bd9Sstevel@tonic-gate {
37947c478bd9Sstevel@tonic-gate 	rsmipc_msghdr_t		*msghdr = (rsmipc_msghdr_t *)msg;
37957c478bd9Sstevel@tonic-gate 	srv_handler_arg_t	*hdlr_argp = (srv_handler_arg_t *)arg;
37967c478bd9Sstevel@tonic-gate 	path_t			*path;
37977c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category,
37987c478bd9Sstevel@tonic-gate 	    RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_INTR_CALLBACK);
37997c478bd9Sstevel@tonic-gate 
38007c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_proc_sqready enter\n"));
38017c478bd9Sstevel@tonic-gate 
38027c478bd9Sstevel@tonic-gate 	/* look up the path - incr the path refcnt */
38037c478bd9Sstevel@tonic-gate 	path = rsm_find_path(hdlr_argp->adapter_name,
38047c478bd9Sstevel@tonic-gate 	    hdlr_argp->adapter_instance, src_hwaddr);
38057c478bd9Sstevel@tonic-gate 
38067c478bd9Sstevel@tonic-gate 	/*
38077c478bd9Sstevel@tonic-gate 	 * No path exists or path is not active - drop the message
38087c478bd9Sstevel@tonic-gate 	 */
38097c478bd9Sstevel@tonic-gate 	if (path == NULL) {
38107c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG,
38117c478bd9Sstevel@tonic-gate 		    "rsm_proc_sqready done: msg dropped no path\n"));
38127c478bd9Sstevel@tonic-gate 		return;
38137c478bd9Sstevel@tonic-gate 	}
38147c478bd9Sstevel@tonic-gate 
38157c478bd9Sstevel@tonic-gate 	mutex_exit(&path->mutex);
38167c478bd9Sstevel@tonic-gate 
38177c478bd9Sstevel@tonic-gate 	/* drain any tasks from the previous incarnation */
38187c478bd9Sstevel@tonic-gate 	taskq_wait(path->recv_taskq);
38197c478bd9Sstevel@tonic-gate 
38207c478bd9Sstevel@tonic-gate 	mutex_enter(&path->mutex);
38217c478bd9Sstevel@tonic-gate 	/*
38227c478bd9Sstevel@tonic-gate 	 * If we'd sent an SQREADY message and were waiting for SQREADY_ACK
38237c478bd9Sstevel@tonic-gate 	 * in the meanwhile we received an SQREADY message, blindly reset
38247c478bd9Sstevel@tonic-gate 	 * the WAIT_FOR_SQACK flag because we'll just send SQREADY_ACK
38257c478bd9Sstevel@tonic-gate 	 * and forget about the SQREADY that we sent.
38267c478bd9Sstevel@tonic-gate 	 */
38277c478bd9Sstevel@tonic-gate 	path->flags &= ~RSMKA_WAIT_FOR_SQACK;
38287c478bd9Sstevel@tonic-gate 
38297c478bd9Sstevel@tonic-gate 	if (path->state != RSMKA_PATH_ACTIVE) {
38307c478bd9Sstevel@tonic-gate 		/* decr refcnt and drop the mutex */
38317c478bd9Sstevel@tonic-gate 		PATH_RELE_NOLOCK(path);
38327c478bd9Sstevel@tonic-gate 		mutex_exit(&path->mutex);
38337c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG,
38347c478bd9Sstevel@tonic-gate 		    "rsm_proc_sqready done: msg dropped path !ACTIVE\n"));
38357c478bd9Sstevel@tonic-gate 		return;
38367c478bd9Sstevel@tonic-gate 	}
38377c478bd9Sstevel@tonic-gate 
38387c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG, "rsm_proc_sqready:path=%lx "
38397c478bd9Sstevel@tonic-gate 	    " src=%lx:%llx\n", path, msghdr->rsmipc_src, src_hwaddr));
38407c478bd9Sstevel@tonic-gate 
38417c478bd9Sstevel@tonic-gate 	/*
38427c478bd9Sstevel@tonic-gate 	 * The sender's local incarnation number is our remote incarnation
38437c478bd9Sstevel@tonic-gate 	 * number save it in the path data structure
38447c478bd9Sstevel@tonic-gate 	 */
38457c478bd9Sstevel@tonic-gate 	path->remote_incn = msg->rsmipc_local_incn;
38467c478bd9Sstevel@tonic-gate 	path->sendq_token.msgbuf_avail = 0;
38477c478bd9Sstevel@tonic-gate 	path->procmsg_cnt = 0;
38487c478bd9Sstevel@tonic-gate 
38497c478bd9Sstevel@tonic-gate 	/*
38507c478bd9Sstevel@tonic-gate 	 * path is active - dispatch task to send SQREADY_ACK - remember
38517c478bd9Sstevel@tonic-gate 	 * RSMPI calls can't be done in interrupt context
38527c478bd9Sstevel@tonic-gate 	 *
38537c478bd9Sstevel@tonic-gate 	 * We can use the recv_taskq to send because the remote endpoint
38547c478bd9Sstevel@tonic-gate 	 * cannot start sending messages till it receives SQREADY_ACK hence
38557c478bd9Sstevel@tonic-gate 	 * at this point there are no tasks on recv_taskq.
38567c478bd9Sstevel@tonic-gate 	 *
38577c478bd9Sstevel@tonic-gate 	 * The path refcnt will be decremented in rsm_sqready_ack_deferred.
38587c478bd9Sstevel@tonic-gate 	 */
38597c478bd9Sstevel@tonic-gate 	(void) taskq_dispatch(path->recv_taskq,
38607c478bd9Sstevel@tonic-gate 	    rsm_sqready_ack_deferred, path, KM_NOSLEEP);
38617c478bd9Sstevel@tonic-gate 
38627c478bd9Sstevel@tonic-gate 	mutex_exit(&path->mutex);
38637c478bd9Sstevel@tonic-gate 
38647c478bd9Sstevel@tonic-gate 
38657c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_proc_sqready done\n"));
38667c478bd9Sstevel@tonic-gate }
38677c478bd9Sstevel@tonic-gate 
38687c478bd9Sstevel@tonic-gate /*
38697c478bd9Sstevel@tonic-gate  * Process the SQREADY_ACK message
38707c478bd9Sstevel@tonic-gate  */
38717c478bd9Sstevel@tonic-gate static void
rsm_proc_sqready_ack(rsmipc_controlmsg_t * msg,rsm_addr_t src_hwaddr,rsm_intr_hand_arg_t arg)38727c478bd9Sstevel@tonic-gate rsm_proc_sqready_ack(rsmipc_controlmsg_t *msg, rsm_addr_t src_hwaddr,
38737c478bd9Sstevel@tonic-gate     rsm_intr_hand_arg_t arg)
38747c478bd9Sstevel@tonic-gate {
38757c478bd9Sstevel@tonic-gate 	rsmipc_msghdr_t		*msghdr = (rsmipc_msghdr_t *)msg;
38767c478bd9Sstevel@tonic-gate 	srv_handler_arg_t	*hdlr_argp = (srv_handler_arg_t *)arg;
38777c478bd9Sstevel@tonic-gate 	path_t			*path;
38787c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category,
38797c478bd9Sstevel@tonic-gate 	    RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_INTR_CALLBACK);
38807c478bd9Sstevel@tonic-gate 
38817c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
38827c478bd9Sstevel@tonic-gate 	    "rsm_proc_sqready_ack enter\n"));
38837c478bd9Sstevel@tonic-gate 
38847c478bd9Sstevel@tonic-gate 	/* look up the path - incr the path refcnt */
38857c478bd9Sstevel@tonic-gate 	path = rsm_find_path(hdlr_argp->adapter_name,
38867c478bd9Sstevel@tonic-gate 	    hdlr_argp->adapter_instance, src_hwaddr);
38877c478bd9Sstevel@tonic-gate 
38887c478bd9Sstevel@tonic-gate 	/*
38897c478bd9Sstevel@tonic-gate 	 * drop the message if - no path exists or path is not active
38907c478bd9Sstevel@tonic-gate 	 * or if its not waiting for SQREADY_ACK message
38917c478bd9Sstevel@tonic-gate 	 */
38927c478bd9Sstevel@tonic-gate 	if (path == NULL) {
38937c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG,
38947c478bd9Sstevel@tonic-gate 		    "rsm_proc_sqready_ack done: msg dropped no path\n"));
38957c478bd9Sstevel@tonic-gate 		return;
38967c478bd9Sstevel@tonic-gate 	}
38977c478bd9Sstevel@tonic-gate 
38987c478bd9Sstevel@tonic-gate 	if ((path->state != RSMKA_PATH_ACTIVE) ||
38997c478bd9Sstevel@tonic-gate 	    !(path->flags & RSMKA_WAIT_FOR_SQACK)) {
39007c478bd9Sstevel@tonic-gate 		/* decrement the refcnt */
39017c478bd9Sstevel@tonic-gate 		PATH_RELE_NOLOCK(path);
39027c478bd9Sstevel@tonic-gate 		mutex_exit(&path->mutex);
39037c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG,
39047c478bd9Sstevel@tonic-gate 		    "rsm_proc_sqready_ack done: msg dropped\n"));
39057c478bd9Sstevel@tonic-gate 		return;
39067c478bd9Sstevel@tonic-gate 	}
39077c478bd9Sstevel@tonic-gate 
39087c478bd9Sstevel@tonic-gate 	/*
39097c478bd9Sstevel@tonic-gate 	 * Check if this message is in response to the last RSMIPC_MSG_SQREADY
39107c478bd9Sstevel@tonic-gate 	 * sent, if not drop it.
39117c478bd9Sstevel@tonic-gate 	 */
39127c478bd9Sstevel@tonic-gate 	if (path->local_incn != msghdr->rsmipc_incn) {
39137c478bd9Sstevel@tonic-gate 		/* decrement the refcnt */
39147c478bd9Sstevel@tonic-gate 		PATH_RELE_NOLOCK(path);
39157c478bd9Sstevel@tonic-gate 		mutex_exit(&path->mutex);
39167c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG,
39177c478bd9Sstevel@tonic-gate 		    "rsm_proc_sqready_ack done: msg old incn %lld\n",
39187c478bd9Sstevel@tonic-gate 		    msghdr->rsmipc_incn));
39197c478bd9Sstevel@tonic-gate 		return;
39207c478bd9Sstevel@tonic-gate 	}
39217c478bd9Sstevel@tonic-gate 
39227c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG, "rsm_proc_sqready_ack:path=%lx "
39237c478bd9Sstevel@tonic-gate 	    " src=%lx:%llx\n", path, msghdr->rsmipc_src, src_hwaddr));
39247c478bd9Sstevel@tonic-gate 
39257c478bd9Sstevel@tonic-gate 	/*
39267c478bd9Sstevel@tonic-gate 	 * clear the WAIT_FOR_SQACK flag since we have recvd the ack
39277c478bd9Sstevel@tonic-gate 	 */
39287c478bd9Sstevel@tonic-gate 	path->flags &= ~RSMKA_WAIT_FOR_SQACK;
39297c478bd9Sstevel@tonic-gate 
39307c478bd9Sstevel@tonic-gate 	/* save the remote sendq incn number */
39317c478bd9Sstevel@tonic-gate 	path->remote_incn = msg->rsmipc_local_incn;
39327c478bd9Sstevel@tonic-gate 
39337c478bd9Sstevel@tonic-gate 	/* initialize credits to the max level */
39347c478bd9Sstevel@tonic-gate 	path->sendq_token.msgbuf_avail = RSMIPC_MAX_MESSAGES;
39357c478bd9Sstevel@tonic-gate 
39367c478bd9Sstevel@tonic-gate 	/* wake up any send that is waiting for credits */
39377c478bd9Sstevel@tonic-gate 	cv_broadcast(&path->sendq_token.sendq_cv);
39387c478bd9Sstevel@tonic-gate 
39397c478bd9Sstevel@tonic-gate 	/* decrement the refcnt */
39407c478bd9Sstevel@tonic-gate 	PATH_RELE_NOLOCK(path);
39417c478bd9Sstevel@tonic-gate 
39427c478bd9Sstevel@tonic-gate 	mutex_exit(&path->mutex);
39437c478bd9Sstevel@tonic-gate 
39447c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
39457c478bd9Sstevel@tonic-gate 	    "rsm_proc_sqready_ack done\n"));
39467c478bd9Sstevel@tonic-gate }
39477c478bd9Sstevel@tonic-gate 
39487c478bd9Sstevel@tonic-gate /*
39497c478bd9Sstevel@tonic-gate  * process the RSMIPC_MSG_CREDIT message
39507c478bd9Sstevel@tonic-gate  */
39517c478bd9Sstevel@tonic-gate static void
rsm_add_credits(rsmipc_controlmsg_t * msg,rsm_addr_t src_hwaddr,rsm_intr_hand_arg_t arg)39527c478bd9Sstevel@tonic-gate rsm_add_credits(rsmipc_controlmsg_t *msg, rsm_addr_t src_hwaddr,
39537c478bd9Sstevel@tonic-gate     rsm_intr_hand_arg_t arg)
39547c478bd9Sstevel@tonic-gate {
39557c478bd9Sstevel@tonic-gate 	rsmipc_msghdr_t		*msghdr = (rsmipc_msghdr_t *)msg;
39567c478bd9Sstevel@tonic-gate 	srv_handler_arg_t	*hdlr_argp = (srv_handler_arg_t *)arg;
39577c478bd9Sstevel@tonic-gate 	path_t			*path;
39587c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category,
395919397407SSherry Moore 	    RSM_KERNEL_AGENT | RSM_FUNC_ALL |
396019397407SSherry Moore 	    RSM_INTR_CALLBACK | RSM_FLOWCONTROL);
39617c478bd9Sstevel@tonic-gate 
39627c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_add_credits enter\n"));
39637c478bd9Sstevel@tonic-gate 
39647c478bd9Sstevel@tonic-gate 	/* look up the path - incr the path refcnt */
39657c478bd9Sstevel@tonic-gate 	path = rsm_find_path(hdlr_argp->adapter_name,
39667c478bd9Sstevel@tonic-gate 	    hdlr_argp->adapter_instance, src_hwaddr);
39677c478bd9Sstevel@tonic-gate 
39687c478bd9Sstevel@tonic-gate 	if (path == NULL) {
39697c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG,
39707c478bd9Sstevel@tonic-gate 		    "rsm_add_credits enter: path not found\n"));
39717c478bd9Sstevel@tonic-gate 		return;
39727c478bd9Sstevel@tonic-gate 	}
39737c478bd9Sstevel@tonic-gate 
39747c478bd9Sstevel@tonic-gate 	/* the path is not active - discard credits */
39757c478bd9Sstevel@tonic-gate 	if (path->state != RSMKA_PATH_ACTIVE) {
39767c478bd9Sstevel@tonic-gate 		PATH_RELE_NOLOCK(path);
39777c478bd9Sstevel@tonic-gate 		mutex_exit(&path->mutex);
39787c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG,
39797c478bd9Sstevel@tonic-gate 		    "rsm_add_credits enter:path=%lx !ACTIVE\n", path));
39807c478bd9Sstevel@tonic-gate 		return;
39817c478bd9Sstevel@tonic-gate 	}
39827c478bd9Sstevel@tonic-gate 
39837c478bd9Sstevel@tonic-gate 	/*
39847c478bd9Sstevel@tonic-gate 	 * Check if these credits are for current incarnation of the path.
39857c478bd9Sstevel@tonic-gate 	 */
39867c478bd9Sstevel@tonic-gate 	if (path->local_incn != msghdr->rsmipc_incn) {
39877c478bd9Sstevel@tonic-gate 		/* decrement the refcnt */
39887c478bd9Sstevel@tonic-gate 		PATH_RELE_NOLOCK(path);
39897c478bd9Sstevel@tonic-gate 		mutex_exit(&path->mutex);
39907c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG,
39917c478bd9Sstevel@tonic-gate 		    "rsm_add_credits enter: old incn %lld\n",
39927c478bd9Sstevel@tonic-gate 		    msghdr->rsmipc_incn));
39937c478bd9Sstevel@tonic-gate 		return;
39947c478bd9Sstevel@tonic-gate 	}
39957c478bd9Sstevel@tonic-gate 
39967c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG,
39977c478bd9Sstevel@tonic-gate 	    "rsm_add_credits:path=%lx new-creds=%d "
39987c478bd9Sstevel@tonic-gate 	    "curr credits=%d src=%lx:%llx\n", path, msg->rsmipc_credits,
39997c478bd9Sstevel@tonic-gate 	    path->sendq_token.msgbuf_avail, msghdr->rsmipc_src,
40007c478bd9Sstevel@tonic-gate 	    src_hwaddr));
40017c478bd9Sstevel@tonic-gate 
40027c478bd9Sstevel@tonic-gate 
40037c478bd9Sstevel@tonic-gate 	/* add credits to the path's sendq */
40047c478bd9Sstevel@tonic-gate 	path->sendq_token.msgbuf_avail += msg->rsmipc_credits;
40057c478bd9Sstevel@tonic-gate 
40067c478bd9Sstevel@tonic-gate 	ASSERT(path->sendq_token.msgbuf_avail <= RSMIPC_MAX_MESSAGES);
40077c478bd9Sstevel@tonic-gate 
40087c478bd9Sstevel@tonic-gate 	/* wake up any send that is waiting for credits */
40097c478bd9Sstevel@tonic-gate 	cv_broadcast(&path->sendq_token.sendq_cv);
40107c478bd9Sstevel@tonic-gate 
40117c478bd9Sstevel@tonic-gate 	/* decrement the refcnt */
40127c478bd9Sstevel@tonic-gate 	PATH_RELE_NOLOCK(path);
40137c478bd9Sstevel@tonic-gate 
40147c478bd9Sstevel@tonic-gate 	mutex_exit(&path->mutex);
40157c478bd9Sstevel@tonic-gate 
40167c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_add_credits done\n"));
40177c478bd9Sstevel@tonic-gate }
40187c478bd9Sstevel@tonic-gate 
40197c478bd9Sstevel@tonic-gate static void
rsm_intr_event(rsmipc_request_t * msg)40207c478bd9Sstevel@tonic-gate rsm_intr_event(rsmipc_request_t *msg)
40217c478bd9Sstevel@tonic-gate {
40227c478bd9Sstevel@tonic-gate 	rsmseg_t	*seg;
40237c478bd9Sstevel@tonic-gate 	rsmresource_t	*p;
40247c478bd9Sstevel@tonic-gate 	rsm_node_id_t	src_node;
40257c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category,
40267c478bd9Sstevel@tonic-gate 	    RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_INTR_CALLBACK);
40277c478bd9Sstevel@tonic-gate 
40287c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_intr_event enter\n"));
40297c478bd9Sstevel@tonic-gate 
40307c478bd9Sstevel@tonic-gate 	src_node = msg->rsmipc_hdr.rsmipc_src;
40317c478bd9Sstevel@tonic-gate 
40327c478bd9Sstevel@tonic-gate 	if ((seg = msg->rsmipc_segment_cookie) != NULL) {
40337c478bd9Sstevel@tonic-gate 		/* This is for an import segment */
40347c478bd9Sstevel@tonic-gate 		uint_t hashval = rsmhash(msg->rsmipc_key);
40357c478bd9Sstevel@tonic-gate 
40367c478bd9Sstevel@tonic-gate 		rw_enter(&rsm_import_segs.rsmhash_rw, RW_READER);
40377c478bd9Sstevel@tonic-gate 
40387c478bd9Sstevel@tonic-gate 		p = (rsmresource_t *)rsmhash_getbkt(&rsm_import_segs, hashval);
40397c478bd9Sstevel@tonic-gate 
40407c478bd9Sstevel@tonic-gate 		for (; p; p = p->rsmrc_next) {
40417c478bd9Sstevel@tonic-gate 			if ((p->rsmrc_key == msg->rsmipc_key) &&
40427c478bd9Sstevel@tonic-gate 			    (p->rsmrc_node == src_node)) {
40437c478bd9Sstevel@tonic-gate 				seg = (rsmseg_t *)p;
40447c478bd9Sstevel@tonic-gate 				rsmseglock_acquire(seg);
40457c478bd9Sstevel@tonic-gate 
4046*1a5e258fSJosef 'Jeff' Sipek 				atomic_inc_32(&seg->s_pollevent);
40477c478bd9Sstevel@tonic-gate 
40487c478bd9Sstevel@tonic-gate 				if (seg->s_pollflag & RSM_SEGMENT_POLL)
40497c478bd9Sstevel@tonic-gate 					pollwakeup(&seg->s_poll, POLLRDNORM);
40507c478bd9Sstevel@tonic-gate 
40517c478bd9Sstevel@tonic-gate 				rsmseglock_release(seg);
40527c478bd9Sstevel@tonic-gate 			}
40537c478bd9Sstevel@tonic-gate 		}
40547c478bd9Sstevel@tonic-gate 
40557c478bd9Sstevel@tonic-gate 		rw_exit(&rsm_import_segs.rsmhash_rw);
40567c478bd9Sstevel@tonic-gate 	} else {
40577c478bd9Sstevel@tonic-gate 		/* This is for an export segment */
40587c478bd9Sstevel@tonic-gate 		seg = rsmexport_lookup(msg->rsmipc_key);
40597c478bd9Sstevel@tonic-gate 		if (!seg) {
40607c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
40617c478bd9Sstevel@tonic-gate 			    "rsm_intr_event done: exp seg not found\n"));
40627c478bd9Sstevel@tonic-gate 			return;
40637c478bd9Sstevel@tonic-gate 		}
40647c478bd9Sstevel@tonic-gate 
40657c478bd9Sstevel@tonic-gate 		ASSERT(rsmseglock_held(seg));
40667c478bd9Sstevel@tonic-gate 
4067*1a5e258fSJosef 'Jeff' Sipek 		atomic_inc_32(&seg->s_pollevent);
40687c478bd9Sstevel@tonic-gate 
40697c478bd9Sstevel@tonic-gate 		/*
40707c478bd9Sstevel@tonic-gate 		 * We must hold the segment lock here, or else the segment
40717c478bd9Sstevel@tonic-gate 		 * can be freed while pollwakeup is using it. This implies
40727c478bd9Sstevel@tonic-gate 		 * that we MUST NOT grab the segment lock during rsm_chpoll,
40737c478bd9Sstevel@tonic-gate 		 * as outlined in the chpoll(2) man page.
40747c478bd9Sstevel@tonic-gate 		 */
40757c478bd9Sstevel@tonic-gate 		if (seg->s_pollflag & RSM_SEGMENT_POLL)
40767c478bd9Sstevel@tonic-gate 			pollwakeup(&seg->s_poll, POLLRDNORM);
40777c478bd9Sstevel@tonic-gate 
40787c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
40797c478bd9Sstevel@tonic-gate 	}
40807c478bd9Sstevel@tonic-gate 
40817c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_intr_event done\n"));
40827c478bd9Sstevel@tonic-gate }
40837c478bd9Sstevel@tonic-gate 
40847c478bd9Sstevel@tonic-gate /*
40857c478bd9Sstevel@tonic-gate  * The exporter did a republish and changed the ACL - this change is only
40867c478bd9Sstevel@tonic-gate  * visible to new importers.
40877c478bd9Sstevel@tonic-gate  */
40887c478bd9Sstevel@tonic-gate static void
importer_update(rsm_node_id_t src_node,rsm_memseg_id_t key,rsm_permission_t perm)40897c478bd9Sstevel@tonic-gate importer_update(rsm_node_id_t src_node, rsm_memseg_id_t key,
40907c478bd9Sstevel@tonic-gate     rsm_permission_t perm)
40917c478bd9Sstevel@tonic-gate {
40927c478bd9Sstevel@tonic-gate 
40937c478bd9Sstevel@tonic-gate 	rsmresource_t	*p;
40947c478bd9Sstevel@tonic-gate 	rsmseg_t	*seg;
40957c478bd9Sstevel@tonic-gate 	uint_t		hashval = rsmhash(key);
40967c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category,
40977c478bd9Sstevel@tonic-gate 	    RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_INTR_CALLBACK);
40987c478bd9Sstevel@tonic-gate 
40997c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "importer_update enter\n"));
41007c478bd9Sstevel@tonic-gate 
41017c478bd9Sstevel@tonic-gate 	rw_enter(&rsm_import_segs.rsmhash_rw, RW_READER);
41027c478bd9Sstevel@tonic-gate 
41037c478bd9Sstevel@tonic-gate 	p = (rsmresource_t *)rsmhash_getbkt(&rsm_import_segs, hashval);
41047c478bd9Sstevel@tonic-gate 
41057c478bd9Sstevel@tonic-gate 	for (; p; p = p->rsmrc_next) {
41067c478bd9Sstevel@tonic-gate 		/*
41077c478bd9Sstevel@tonic-gate 		 * find the importer and update the permission in the shared
41087c478bd9Sstevel@tonic-gate 		 * data structure. Any new importers will use the new perms
41097c478bd9Sstevel@tonic-gate 		 */
41107c478bd9Sstevel@tonic-gate 		if ((p->rsmrc_key == key) && (p->rsmrc_node == src_node)) {
41117c478bd9Sstevel@tonic-gate 			seg = (rsmseg_t *)p;
41127c478bd9Sstevel@tonic-gate 
41137c478bd9Sstevel@tonic-gate 			rsmseglock_acquire(seg);
41147c478bd9Sstevel@tonic-gate 			rsmsharelock_acquire(seg);
41157c478bd9Sstevel@tonic-gate 			seg->s_share->rsmsi_mode = perm;
41167c478bd9Sstevel@tonic-gate 			rsmsharelock_release(seg);
41177c478bd9Sstevel@tonic-gate 			rsmseglock_release(seg);
41187c478bd9Sstevel@tonic-gate 
41197c478bd9Sstevel@tonic-gate 			break;
41207c478bd9Sstevel@tonic-gate 		}
41217c478bd9Sstevel@tonic-gate 	}
41227c478bd9Sstevel@tonic-gate 
41237c478bd9Sstevel@tonic-gate 	rw_exit(&rsm_import_segs.rsmhash_rw);
41247c478bd9Sstevel@tonic-gate 
41257c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "importer_update done\n"));
41267c478bd9Sstevel@tonic-gate }
41277c478bd9Sstevel@tonic-gate 
41287c478bd9Sstevel@tonic-gate void
rsm_suspend_complete(rsm_node_id_t src_node,int flag)41297c478bd9Sstevel@tonic-gate rsm_suspend_complete(rsm_node_id_t src_node, int flag)
41307c478bd9Sstevel@tonic-gate {
41317c478bd9Sstevel@tonic-gate 	int		done = 1; /* indicate all SUSPENDS have been acked */
41327c478bd9Sstevel@tonic-gate 	list_element_t	*elem;
41337c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category,
41347c478bd9Sstevel@tonic-gate 	    RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_INTR_CALLBACK);
41357c478bd9Sstevel@tonic-gate 
41367c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
41377c478bd9Sstevel@tonic-gate 	    "rsm_suspend_complete enter\n"));
41387c478bd9Sstevel@tonic-gate 
41397c478bd9Sstevel@tonic-gate 	mutex_enter(&rsm_suspend_list.list_lock);
41407c478bd9Sstevel@tonic-gate 
41417c478bd9Sstevel@tonic-gate 	if (rsm_suspend_list.list_head == NULL) {
41427c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
41437c478bd9Sstevel@tonic-gate 		    "rsm_suspend_complete done: suspend_list is empty\n"));
41447c478bd9Sstevel@tonic-gate 		mutex_exit(&rsm_suspend_list.list_lock);
41457c478bd9Sstevel@tonic-gate 		return;
41467c478bd9Sstevel@tonic-gate 	}
41477c478bd9Sstevel@tonic-gate 
41487c478bd9Sstevel@tonic-gate 	elem = rsm_suspend_list.list_head;
41497c478bd9Sstevel@tonic-gate 	while (elem != NULL) {
41507c478bd9Sstevel@tonic-gate 		if (elem->nodeid == src_node) {
41517c478bd9Sstevel@tonic-gate 			/* clear the pending flag for the node */
41527c478bd9Sstevel@tonic-gate 			elem->flags &= ~RSM_SUSPEND_ACKPENDING;
41537c478bd9Sstevel@tonic-gate 			elem->flags |= flag;
41547c478bd9Sstevel@tonic-gate 		}
41557c478bd9Sstevel@tonic-gate 
41567c478bd9Sstevel@tonic-gate 		if (done && (elem->flags & RSM_SUSPEND_ACKPENDING))
41577c478bd9Sstevel@tonic-gate 			done = 0; /* still some nodes have not yet ACKED */
41587c478bd9Sstevel@tonic-gate 
41597c478bd9Sstevel@tonic-gate 		elem = elem->next;
41607c478bd9Sstevel@tonic-gate 	}
41617c478bd9Sstevel@tonic-gate 
41627c478bd9Sstevel@tonic-gate 	mutex_exit(&rsm_suspend_list.list_lock);
41637c478bd9Sstevel@tonic-gate 
41647c478bd9Sstevel@tonic-gate 	if (!done) {
41657c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
41667c478bd9Sstevel@tonic-gate 		    "rsm_suspend_complete done: acks pending\n"));
41677c478bd9Sstevel@tonic-gate 		return;
41687c478bd9Sstevel@tonic-gate 	}
41697c478bd9Sstevel@tonic-gate 	/*
41707c478bd9Sstevel@tonic-gate 	 * Now that we are done with suspending all the remote importers
41717c478bd9Sstevel@tonic-gate 	 * time to quiesce the local exporters
41727c478bd9Sstevel@tonic-gate 	 */
41737c478bd9Sstevel@tonic-gate 	exporter_quiesce();
41747c478bd9Sstevel@tonic-gate 
41757c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
41767c478bd9Sstevel@tonic-gate 	    "rsm_suspend_complete done\n"));
41777c478bd9Sstevel@tonic-gate }
41787c478bd9Sstevel@tonic-gate 
41797c478bd9Sstevel@tonic-gate static void
exporter_quiesce()41807c478bd9Sstevel@tonic-gate exporter_quiesce()
41817c478bd9Sstevel@tonic-gate {
41827c478bd9Sstevel@tonic-gate 	int		i, e;
41837c478bd9Sstevel@tonic-gate 	rsmresource_t	*current;
41847c478bd9Sstevel@tonic-gate 	rsmseg_t	*seg;
41857c478bd9Sstevel@tonic-gate 	adapter_t	*adapter;
41867c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category,
41877c478bd9Sstevel@tonic-gate 	    RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_INTR_CALLBACK);
41887c478bd9Sstevel@tonic-gate 
41897c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "exporter_quiesce enter\n"));
41907c478bd9Sstevel@tonic-gate 	/*
41917c478bd9Sstevel@tonic-gate 	 * The importers send a SUSPEND_COMPLETE to the exporter node
41927c478bd9Sstevel@tonic-gate 	 *	Unpublish, unbind the export segment and
41937c478bd9Sstevel@tonic-gate 	 *	move the segments to the EXPORT_QUIESCED state
41947c478bd9Sstevel@tonic-gate 	 */
41957c478bd9Sstevel@tonic-gate 
41967c478bd9Sstevel@tonic-gate 	rw_enter(&rsm_export_segs.rsmhash_rw, RW_READER);
41977c478bd9Sstevel@tonic-gate 
41987c478bd9Sstevel@tonic-gate 	for (i = 0; i < rsm_hash_size; i++) {
41997c478bd9Sstevel@tonic-gate 		current = rsm_export_segs.bucket[i];
42007c478bd9Sstevel@tonic-gate 		while (current != NULL) {
42017c478bd9Sstevel@tonic-gate 			seg = (rsmseg_t *)current;
42027c478bd9Sstevel@tonic-gate 			rsmseglock_acquire(seg);
42037c478bd9Sstevel@tonic-gate 			if (current->rsmrc_state ==
42047c478bd9Sstevel@tonic-gate 			    RSM_STATE_EXPORT_QUIESCING) {
42057c478bd9Sstevel@tonic-gate 				adapter = seg->s_adapter;
42067c478bd9Sstevel@tonic-gate 				/*
42077c478bd9Sstevel@tonic-gate 				 * some local memory handles are not published
42087c478bd9Sstevel@tonic-gate 				 * check if it was published
42097c478bd9Sstevel@tonic-gate 				 */
42107c478bd9Sstevel@tonic-gate 				if ((seg->s_acl == NULL) ||
42117c478bd9Sstevel@tonic-gate 				    (seg->s_acl[0].ae_node != my_nodeid) ||
42127c478bd9Sstevel@tonic-gate 				    (seg->s_acl[0].ae_permission != 0)) {
42137c478bd9Sstevel@tonic-gate 
42147c478bd9Sstevel@tonic-gate 					e = adapter->rsmpi_ops->rsm_unpublish(
42157c478bd9Sstevel@tonic-gate 					    seg->s_handle.out);
42167c478bd9Sstevel@tonic-gate 					DBG_PRINTF((category, RSM_DEBUG,
42177c478bd9Sstevel@tonic-gate 					    "exporter_quiesce:unpub %d\n", e));
42187c478bd9Sstevel@tonic-gate 
42197c478bd9Sstevel@tonic-gate 					e = adapter->rsmpi_ops->rsm_seg_destroy(
42207c478bd9Sstevel@tonic-gate 					    seg->s_handle.out);
42217c478bd9Sstevel@tonic-gate 
42227c478bd9Sstevel@tonic-gate 					DBG_PRINTF((category, RSM_DEBUG,
42237c478bd9Sstevel@tonic-gate 					    "exporter_quiesce:destroy %d\n",
42247c478bd9Sstevel@tonic-gate 					    e));
42257c478bd9Sstevel@tonic-gate 				}
42267c478bd9Sstevel@tonic-gate 
42277c478bd9Sstevel@tonic-gate 				(void) rsm_unbind_pages(seg);
42287c478bd9Sstevel@tonic-gate 				seg->s_state = RSM_STATE_EXPORT_QUIESCED;
42297c478bd9Sstevel@tonic-gate 				cv_broadcast(&seg->s_cv);
42307c478bd9Sstevel@tonic-gate 			}
42317c478bd9Sstevel@tonic-gate 			rsmseglock_release(seg);
42327c478bd9Sstevel@tonic-gate 			current = current->rsmrc_next;
42337c478bd9Sstevel@tonic-gate 		}
42347c478bd9Sstevel@tonic-gate 	}
42357c478bd9Sstevel@tonic-gate 	rw_exit(&rsm_export_segs.rsmhash_rw);
42367c478bd9Sstevel@tonic-gate 
42377c478bd9Sstevel@tonic-gate 	/*
42387c478bd9Sstevel@tonic-gate 	 * All the local segments we are done with the pre-del processing
42397c478bd9Sstevel@tonic-gate 	 * - time to move to PREDEL_COMPLETED.
42407c478bd9Sstevel@tonic-gate 	 */
42417c478bd9Sstevel@tonic-gate 
42427c478bd9Sstevel@tonic-gate 	mutex_enter(&rsm_drv_data.drv_lock);
42437c478bd9Sstevel@tonic-gate 
42447c478bd9Sstevel@tonic-gate 	ASSERT(rsm_drv_data.drv_state == RSM_DRV_PREDEL_STARTED);
42457c478bd9Sstevel@tonic-gate 
42467c478bd9Sstevel@tonic-gate 	rsm_drv_data.drv_state = RSM_DRV_PREDEL_COMPLETED;
42477c478bd9Sstevel@tonic-gate 
42487c478bd9Sstevel@tonic-gate 	cv_broadcast(&rsm_drv_data.drv_cv);
42497c478bd9Sstevel@tonic-gate 
42507c478bd9Sstevel@tonic-gate 	mutex_exit(&rsm_drv_data.drv_lock);
42517c478bd9Sstevel@tonic-gate 
42527c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "exporter_quiesce done\n"));
42537c478bd9Sstevel@tonic-gate }
42547c478bd9Sstevel@tonic-gate 
42557c478bd9Sstevel@tonic-gate static void
importer_suspend(rsm_node_id_t src_node)42567c478bd9Sstevel@tonic-gate importer_suspend(rsm_node_id_t src_node)
42577c478bd9Sstevel@tonic-gate {
42587c478bd9Sstevel@tonic-gate 	int		i;
42597c478bd9Sstevel@tonic-gate 	int		susp_flg; /* true means already suspended */
42607c478bd9Sstevel@tonic-gate 	int		num_importers;
42617c478bd9Sstevel@tonic-gate 	rsmresource_t	*p = NULL, *curp;
42627c478bd9Sstevel@tonic-gate 	rsmhash_table_t *rhash = &rsm_import_segs;
42637c478bd9Sstevel@tonic-gate 	rsmseg_t	*seg;
42647c478bd9Sstevel@tonic-gate 	rsmipc_request_t request;
42657c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category,
42667c478bd9Sstevel@tonic-gate 	    RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_INTR_CALLBACK);
42677c478bd9Sstevel@tonic-gate 
42687c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "importer_suspend enter\n"));
42697c478bd9Sstevel@tonic-gate 
42707c478bd9Sstevel@tonic-gate 	rw_enter(&rhash->rsmhash_rw, RW_READER);
42717c478bd9Sstevel@tonic-gate 	for (i = 0; i < rsm_hash_size; i++) {
42727c478bd9Sstevel@tonic-gate 		p = rhash->bucket[i];
42737c478bd9Sstevel@tonic-gate 
42747c478bd9Sstevel@tonic-gate 		/*
42757c478bd9Sstevel@tonic-gate 		 * Suspend all importers with same <node, key> pair.
42767c478bd9Sstevel@tonic-gate 		 * After the last one of the shared importers has been
42777c478bd9Sstevel@tonic-gate 		 * suspended - suspend the shared mappings/connection.
42787c478bd9Sstevel@tonic-gate 		 */
42797c478bd9Sstevel@tonic-gate 		for (; p; p = p->rsmrc_next) {
42807c478bd9Sstevel@tonic-gate 			rsmseg_t *first = (rsmseg_t *)p;
42817c478bd9Sstevel@tonic-gate 			if ((first->s_node != src_node) ||
42827c478bd9Sstevel@tonic-gate 			    (first->s_state == RSM_STATE_DISCONNECT))
42837c478bd9Sstevel@tonic-gate 				continue; /* go to next entry */
42847c478bd9Sstevel@tonic-gate 			/*
42857c478bd9Sstevel@tonic-gate 			 * search the rest of the bucket for
42867c478bd9Sstevel@tonic-gate 			 * other siblings (imprtrs with the same key)
42877c478bd9Sstevel@tonic-gate 			 * of "first" and suspend them.
42887c478bd9Sstevel@tonic-gate 			 * All importers with same key fall in
42897c478bd9Sstevel@tonic-gate 			 * the same bucket.
42907c478bd9Sstevel@tonic-gate 			 */
42917c478bd9Sstevel@tonic-gate 			num_importers = 0;
42927c478bd9Sstevel@tonic-gate 			for (curp = p; curp; curp = curp->rsmrc_next) {
42937c478bd9Sstevel@tonic-gate 				seg = (rsmseg_t *)curp;
42947c478bd9Sstevel@tonic-gate 
42957c478bd9Sstevel@tonic-gate 				rsmseglock_acquire(seg);
42967c478bd9Sstevel@tonic-gate 
42977c478bd9Sstevel@tonic-gate 				if ((seg->s_node != first->s_node) ||
42987c478bd9Sstevel@tonic-gate 				    (seg->s_key != first->s_key) ||
42997c478bd9Sstevel@tonic-gate 				    (seg->s_state == RSM_STATE_DISCONNECT)) {
43007c478bd9Sstevel@tonic-gate 					/*
43017c478bd9Sstevel@tonic-gate 					 * either not a peer segment or its a
43027c478bd9Sstevel@tonic-gate 					 * disconnected segment - skip it
43037c478bd9Sstevel@tonic-gate 					 */
43047c478bd9Sstevel@tonic-gate 					rsmseglock_release(seg);
43057c478bd9Sstevel@tonic-gate 					continue;
43067c478bd9Sstevel@tonic-gate 				}
43077c478bd9Sstevel@tonic-gate 
43087c478bd9Sstevel@tonic-gate 				rsmseg_suspend(seg, &susp_flg);
43097c478bd9Sstevel@tonic-gate 
43107c478bd9Sstevel@tonic-gate 				if (susp_flg) { /* seg already suspended */
43117c478bd9Sstevel@tonic-gate 					rsmseglock_release(seg);
43127c478bd9Sstevel@tonic-gate 					break; /* the inner for loop */
43137c478bd9Sstevel@tonic-gate 				}
43147c478bd9Sstevel@tonic-gate 
43157c478bd9Sstevel@tonic-gate 				num_importers++;
43167c478bd9Sstevel@tonic-gate 				rsmsharelock_acquire(seg);
43177c478bd9Sstevel@tonic-gate 				/*
43187c478bd9Sstevel@tonic-gate 				 * we've processed all importers that are
43197c478bd9Sstevel@tonic-gate 				 * siblings of "first"
43207c478bd9Sstevel@tonic-gate 				 */
43217c478bd9Sstevel@tonic-gate 				if (num_importers ==
43227c478bd9Sstevel@tonic-gate 				    seg->s_share->rsmsi_refcnt) {
43237c478bd9Sstevel@tonic-gate 					rsmsharelock_release(seg);
43247c478bd9Sstevel@tonic-gate 					rsmseglock_release(seg);
43257c478bd9Sstevel@tonic-gate 					break;
43267c478bd9Sstevel@tonic-gate 				}
43277c478bd9Sstevel@tonic-gate 				rsmsharelock_release(seg);
43287c478bd9Sstevel@tonic-gate 				rsmseglock_release(seg);
43297c478bd9Sstevel@tonic-gate 			}
43307c478bd9Sstevel@tonic-gate 
43317c478bd9Sstevel@tonic-gate 			/*
43327c478bd9Sstevel@tonic-gate 			 * All the importers with the same key and
43337c478bd9Sstevel@tonic-gate 			 * nodeid as "first" have been suspended.
43347c478bd9Sstevel@tonic-gate 			 * Now suspend the shared connect/mapping.
43357c478bd9Sstevel@tonic-gate 			 * This is done only once.
43367c478bd9Sstevel@tonic-gate 			 */
43377c478bd9Sstevel@tonic-gate 			if (!susp_flg) {
43387c478bd9Sstevel@tonic-gate 				rsmsegshare_suspend(seg);
43397c478bd9Sstevel@tonic-gate 			}
43407c478bd9Sstevel@tonic-gate 		}
43417c478bd9Sstevel@tonic-gate 	}
43427c478bd9Sstevel@tonic-gate 
43437c478bd9Sstevel@tonic-gate 	rw_exit(&rhash->rsmhash_rw);
43447c478bd9Sstevel@tonic-gate 
43457c478bd9Sstevel@tonic-gate 	/* send an ACK for SUSPEND message */
43467c478bd9Sstevel@tonic-gate 	request.rsmipc_hdr.rsmipc_type = RSMIPC_MSG_SUSPEND_DONE;
43477c478bd9Sstevel@tonic-gate 	(void) rsmipc_send(src_node, &request, RSM_NO_REPLY);
43487c478bd9Sstevel@tonic-gate 
43497c478bd9Sstevel@tonic-gate 
43507c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "importer_suspend done\n"));
43517c478bd9Sstevel@tonic-gate 
43527c478bd9Sstevel@tonic-gate }
43537c478bd9Sstevel@tonic-gate 
43547c478bd9Sstevel@tonic-gate static void
rsmseg_suspend(rsmseg_t * seg,int * susp_flg)43557c478bd9Sstevel@tonic-gate rsmseg_suspend(rsmseg_t *seg, int *susp_flg)
43567c478bd9Sstevel@tonic-gate {
43577c478bd9Sstevel@tonic-gate 	int		recheck_state;
43587c478bd9Sstevel@tonic-gate 	rsmcookie_t	*hdl;
43597c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category,
43607c478bd9Sstevel@tonic-gate 	    RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_INTR_CALLBACK);
43617c478bd9Sstevel@tonic-gate 
43627c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
43637c478bd9Sstevel@tonic-gate 	    "rsmseg_suspend enter: key=%u\n", seg->s_key));
43647c478bd9Sstevel@tonic-gate 
43657c478bd9Sstevel@tonic-gate 	*susp_flg = 0;
43667c478bd9Sstevel@tonic-gate 
43677c478bd9Sstevel@tonic-gate 	ASSERT(rsmseglock_held(seg));
43687c478bd9Sstevel@tonic-gate 	/* wait if putv/getv is in progress */
43697c478bd9Sstevel@tonic-gate 	while (seg->s_rdmacnt > 0)
43707c478bd9Sstevel@tonic-gate 		cv_wait(&seg->s_cv, &seg->s_lock);
43717c478bd9Sstevel@tonic-gate 
43727c478bd9Sstevel@tonic-gate 	do {
43737c478bd9Sstevel@tonic-gate 		recheck_state = 0;
43747c478bd9Sstevel@tonic-gate 
43757c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
43767c478bd9Sstevel@tonic-gate 		    "rsmseg_suspend:segment %x state=%d\n",
43777c478bd9Sstevel@tonic-gate 		    seg->s_key, seg->s_state));
43787c478bd9Sstevel@tonic-gate 
43797c478bd9Sstevel@tonic-gate 		switch (seg->s_state) {
43807c478bd9Sstevel@tonic-gate 		case RSM_STATE_NEW:
43817c478bd9Sstevel@tonic-gate 			/* not a valid state */
43827c478bd9Sstevel@tonic-gate 			break;
43837c478bd9Sstevel@tonic-gate 		case RSM_STATE_CONNECTING:
43847c478bd9Sstevel@tonic-gate 			seg->s_state = RSM_STATE_ABORT_CONNECT;
43857c478bd9Sstevel@tonic-gate 			break;
43867c478bd9Sstevel@tonic-gate 		case RSM_STATE_ABORT_CONNECT:
43877c478bd9Sstevel@tonic-gate 			break;
43887c478bd9Sstevel@tonic-gate 		case RSM_STATE_CONNECT:
43897c478bd9Sstevel@tonic-gate 			seg->s_handle.in = NULL;
43907c478bd9Sstevel@tonic-gate 			seg->s_state = RSM_STATE_CONN_QUIESCE;
43917c478bd9Sstevel@tonic-gate 			break;
43927c478bd9Sstevel@tonic-gate 		case RSM_STATE_MAPPING:
43937c478bd9Sstevel@tonic-gate 			/* wait until segment leaves the mapping state */
43947c478bd9Sstevel@tonic-gate 			while (seg->s_state == RSM_STATE_MAPPING)
43957c478bd9Sstevel@tonic-gate 				cv_wait(&seg->s_cv, &seg->s_lock);
43967c478bd9Sstevel@tonic-gate 			recheck_state = 1;
43977c478bd9Sstevel@tonic-gate 			break;
43987c478bd9Sstevel@tonic-gate 		case RSM_STATE_ACTIVE:
43997c478bd9Sstevel@tonic-gate 			/* unload the mappings */
44007c478bd9Sstevel@tonic-gate 			if (seg->s_ckl != NULL) {
44017c478bd9Sstevel@tonic-gate 				hdl = seg->s_ckl;
44027c478bd9Sstevel@tonic-gate 				for (; hdl != NULL; hdl = hdl->c_next) {
44037c478bd9Sstevel@tonic-gate 					(void) devmap_unload(hdl->c_dhp,
44047c478bd9Sstevel@tonic-gate 					    hdl->c_off, hdl->c_len);
44057c478bd9Sstevel@tonic-gate 				}
44067c478bd9Sstevel@tonic-gate 			}
44077c478bd9Sstevel@tonic-gate 			seg->s_mapinfo = NULL;
44087c478bd9Sstevel@tonic-gate 			seg->s_state = RSM_STATE_MAP_QUIESCE;
44097c478bd9Sstevel@tonic-gate 			break;
44107c478bd9Sstevel@tonic-gate 		case RSM_STATE_CONN_QUIESCE:
44117c478bd9Sstevel@tonic-gate 			/* FALLTHRU */
44127c478bd9Sstevel@tonic-gate 		case RSM_STATE_MAP_QUIESCE:
44137c478bd9Sstevel@tonic-gate 			/* rsmseg_suspend already done for seg */
44147c478bd9Sstevel@tonic-gate 			*susp_flg = 1;
44157c478bd9Sstevel@tonic-gate 			break;
44167c478bd9Sstevel@tonic-gate 		case RSM_STATE_DISCONNECT:
44177c478bd9Sstevel@tonic-gate 			break;
44187c478bd9Sstevel@tonic-gate 		default:
44197c478bd9Sstevel@tonic-gate 			ASSERT(0); /* invalid state */
44207c478bd9Sstevel@tonic-gate 		}
44217c478bd9Sstevel@tonic-gate 	} while (recheck_state);
44227c478bd9Sstevel@tonic-gate 
44237c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmseg_suspend done\n"));
44247c478bd9Sstevel@tonic-gate }
44257c478bd9Sstevel@tonic-gate 
44267c478bd9Sstevel@tonic-gate static void
rsmsegshare_suspend(rsmseg_t * seg)44277c478bd9Sstevel@tonic-gate rsmsegshare_suspend(rsmseg_t *seg)
44287c478bd9Sstevel@tonic-gate {
44297c478bd9Sstevel@tonic-gate 	int			e;
44307c478bd9Sstevel@tonic-gate 	adapter_t		*adapter;
44317c478bd9Sstevel@tonic-gate 	rsm_import_share_t	*sharedp;
44327c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category,
44337c478bd9Sstevel@tonic-gate 	    RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_INTR_CALLBACK);
44347c478bd9Sstevel@tonic-gate 
44357c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
44367c478bd9Sstevel@tonic-gate 	    "rsmsegshare_suspend enter\n"));
44377c478bd9Sstevel@tonic-gate 
44387c478bd9Sstevel@tonic-gate 	rsmseglock_acquire(seg);
44397c478bd9Sstevel@tonic-gate 	rsmsharelock_acquire(seg);
44407c478bd9Sstevel@tonic-gate 
44417c478bd9Sstevel@tonic-gate 	sharedp = seg->s_share;
44427c478bd9Sstevel@tonic-gate 	adapter = seg->s_adapter;
44437c478bd9Sstevel@tonic-gate 	switch (sharedp->rsmsi_state) {
44447c478bd9Sstevel@tonic-gate 	case RSMSI_STATE_NEW:
44457c478bd9Sstevel@tonic-gate 		break;
44467c478bd9Sstevel@tonic-gate 	case RSMSI_STATE_CONNECTING:
44477c478bd9Sstevel@tonic-gate 		sharedp->rsmsi_state = RSMSI_STATE_ABORT_CONNECT;
44487c478bd9Sstevel@tonic-gate 		break;
44497c478bd9Sstevel@tonic-gate 	case RSMSI_STATE_ABORT_CONNECT:
44507c478bd9Sstevel@tonic-gate 		break;
44517c478bd9Sstevel@tonic-gate 	case RSMSI_STATE_CONNECTED:
44527c478bd9Sstevel@tonic-gate 		/* do the rsmpi disconnect */
44537c478bd9Sstevel@tonic-gate 		if (sharedp->rsmsi_node != my_nodeid) {
44547c478bd9Sstevel@tonic-gate 			e = adapter->rsmpi_ops->
44557c478bd9Sstevel@tonic-gate 			    rsm_disconnect(sharedp->rsmsi_handle);
44567c478bd9Sstevel@tonic-gate 
44577c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG,
44587c478bd9Sstevel@tonic-gate 			    "rsm:rsmpi disconnect seg=%x:err=%d\n",
44597c478bd9Sstevel@tonic-gate 			    sharedp->rsmsi_segid, e));
44607c478bd9Sstevel@tonic-gate 		}
44617c478bd9Sstevel@tonic-gate 
44627c478bd9Sstevel@tonic-gate 		sharedp->rsmsi_handle = NULL;
44637c478bd9Sstevel@tonic-gate 
44647c478bd9Sstevel@tonic-gate 		sharedp->rsmsi_state = RSMSI_STATE_CONN_QUIESCE;
44657c478bd9Sstevel@tonic-gate 		break;
44667c478bd9Sstevel@tonic-gate 	case RSMSI_STATE_CONN_QUIESCE:
44677c478bd9Sstevel@tonic-gate 		break;
44687c478bd9Sstevel@tonic-gate 	case RSMSI_STATE_MAPPED:
44697c478bd9Sstevel@tonic-gate 		/* do the rsmpi unmap and disconnect */
44707c478bd9Sstevel@tonic-gate 		if (sharedp->rsmsi_node != my_nodeid) {
44717c478bd9Sstevel@tonic-gate 			e = adapter->rsmpi_ops->rsm_unmap(seg->s_handle.in);
44727c478bd9Sstevel@tonic-gate 
44737c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG,
44747c478bd9Sstevel@tonic-gate 			    "rsmshare_suspend: rsmpi unmap %d\n", e));
44757c478bd9Sstevel@tonic-gate 
44767c478bd9Sstevel@tonic-gate 			e = adapter->rsmpi_ops->
44777c478bd9Sstevel@tonic-gate 			    rsm_disconnect(sharedp->rsmsi_handle);
44787c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG,
44797c478bd9Sstevel@tonic-gate 			    "rsm:rsmpi disconnect seg=%x:err=%d\n",
44807c478bd9Sstevel@tonic-gate 			    sharedp->rsmsi_segid, e));
44817c478bd9Sstevel@tonic-gate 		}
44827c478bd9Sstevel@tonic-gate 
44837c478bd9Sstevel@tonic-gate 		sharedp->rsmsi_handle = NULL;
44847c478bd9Sstevel@tonic-gate 
44857c478bd9Sstevel@tonic-gate 		sharedp->rsmsi_state = RSMSI_STATE_MAP_QUIESCE;
44867c478bd9Sstevel@tonic-gate 		break;
44877c478bd9Sstevel@tonic-gate 	case RSMSI_STATE_MAP_QUIESCE:
44887c478bd9Sstevel@tonic-gate 		break;
44897c478bd9Sstevel@tonic-gate 	case RSMSI_STATE_DISCONNECTED:
44907c478bd9Sstevel@tonic-gate 		break;
44917c478bd9Sstevel@tonic-gate 	default:
44927c478bd9Sstevel@tonic-gate 		ASSERT(0); /* invalid state */
44937c478bd9Sstevel@tonic-gate 	}
44947c478bd9Sstevel@tonic-gate 
44957c478bd9Sstevel@tonic-gate 	rsmsharelock_release(seg);
44967c478bd9Sstevel@tonic-gate 	rsmseglock_release(seg);
44977c478bd9Sstevel@tonic-gate 
44987c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
44997c478bd9Sstevel@tonic-gate 	    "rsmsegshare_suspend done\n"));
45007c478bd9Sstevel@tonic-gate }
45017c478bd9Sstevel@tonic-gate 
45027c478bd9Sstevel@tonic-gate /*
45037c478bd9Sstevel@tonic-gate  * This should get called on receiving a RESUME message or from
45047c478bd9Sstevel@tonic-gate  * the pathmanger if the node undergoing DR dies.
45057c478bd9Sstevel@tonic-gate  */
45067c478bd9Sstevel@tonic-gate static void
importer_resume(rsm_node_id_t src_node)45077c478bd9Sstevel@tonic-gate importer_resume(rsm_node_id_t src_node)
45087c478bd9Sstevel@tonic-gate {
45097c478bd9Sstevel@tonic-gate 	int		i;
45107c478bd9Sstevel@tonic-gate 	rsmresource_t	*p = NULL;
45117c478bd9Sstevel@tonic-gate 	rsmhash_table_t *rhash = &rsm_import_segs;
45127c478bd9Sstevel@tonic-gate 	void		*cookie;
45137c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category,
45147c478bd9Sstevel@tonic-gate 	    RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_INTR_CALLBACK);
45157c478bd9Sstevel@tonic-gate 
45167c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "importer_resume enter\n"));
45177c478bd9Sstevel@tonic-gate 
45187c478bd9Sstevel@tonic-gate 	rw_enter(&rhash->rsmhash_rw, RW_READER);
45197c478bd9Sstevel@tonic-gate 
45207c478bd9Sstevel@tonic-gate 	for (i = 0; i < rsm_hash_size; i++) {
45217c478bd9Sstevel@tonic-gate 		p = rhash->bucket[i];
45227c478bd9Sstevel@tonic-gate 
45237c478bd9Sstevel@tonic-gate 		for (; p; p = p->rsmrc_next) {
45247c478bd9Sstevel@tonic-gate 			rsmseg_t *seg = (rsmseg_t *)p;
45257c478bd9Sstevel@tonic-gate 
45267c478bd9Sstevel@tonic-gate 			rsmseglock_acquire(seg);
45277c478bd9Sstevel@tonic-gate 
45287c478bd9Sstevel@tonic-gate 			/* process only importers of node undergoing DR */
45297c478bd9Sstevel@tonic-gate 			if (seg->s_node != src_node) {
45307c478bd9Sstevel@tonic-gate 				rsmseglock_release(seg);
45317c478bd9Sstevel@tonic-gate 				continue;
45327c478bd9Sstevel@tonic-gate 			}
45337c478bd9Sstevel@tonic-gate 
45347c478bd9Sstevel@tonic-gate 			if (rsmseg_resume(seg, &cookie) != RSM_SUCCESS) {
45357c478bd9Sstevel@tonic-gate 				rsmipc_request_t	request;
45367c478bd9Sstevel@tonic-gate 				/*
45377c478bd9Sstevel@tonic-gate 				 * rsmpi map/connect failed
45387c478bd9Sstevel@tonic-gate 				 * inform the exporter so that it can
45397c478bd9Sstevel@tonic-gate 				 * remove the importer.
45407c478bd9Sstevel@tonic-gate 				 */
45417c478bd9Sstevel@tonic-gate 				request.rsmipc_hdr.rsmipc_type =
45427c478bd9Sstevel@tonic-gate 				    RSMIPC_MSG_NOTIMPORTING;
45437c478bd9Sstevel@tonic-gate 				request.rsmipc_key = seg->s_segid;
45447c478bd9Sstevel@tonic-gate 				request.rsmipc_segment_cookie = cookie;
45457c478bd9Sstevel@tonic-gate 				rsmseglock_release(seg);
45467c478bd9Sstevel@tonic-gate 				(void) rsmipc_send(seg->s_node, &request,
45477c478bd9Sstevel@tonic-gate 				    RSM_NO_REPLY);
45487c478bd9Sstevel@tonic-gate 			} else {
45497c478bd9Sstevel@tonic-gate 				rsmseglock_release(seg);
45507c478bd9Sstevel@tonic-gate 			}
45517c478bd9Sstevel@tonic-gate 		}
45527c478bd9Sstevel@tonic-gate 	}
45537c478bd9Sstevel@tonic-gate 
45547c478bd9Sstevel@tonic-gate 	rw_exit(&rhash->rsmhash_rw);
45557c478bd9Sstevel@tonic-gate 
45567c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "importer_resume done\n"));
45577c478bd9Sstevel@tonic-gate }
45587c478bd9Sstevel@tonic-gate 
45597c478bd9Sstevel@tonic-gate static int
rsmseg_resume(rsmseg_t * seg,void ** cookie)45607c478bd9Sstevel@tonic-gate rsmseg_resume(rsmseg_t *seg, void **cookie)
45617c478bd9Sstevel@tonic-gate {
45627c478bd9Sstevel@tonic-gate 	int			e;
45637c478bd9Sstevel@tonic-gate 	int			retc;
45647c478bd9Sstevel@tonic-gate 	off_t			dev_offset;
45657c478bd9Sstevel@tonic-gate 	size_t			maplen;
45667c478bd9Sstevel@tonic-gate 	uint_t			maxprot;
45677c478bd9Sstevel@tonic-gate 	rsm_mapinfo_t		*p;
45687c478bd9Sstevel@tonic-gate 	rsmcookie_t		*hdl;
45697c478bd9Sstevel@tonic-gate 	rsm_import_share_t	*sharedp;
45707c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category,
45717c478bd9Sstevel@tonic-gate 	    RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_INTR_CALLBACK);
45727c478bd9Sstevel@tonic-gate 
45737c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
45747c478bd9Sstevel@tonic-gate 	    "rsmseg_resume enter: key=%u\n", seg->s_key));
45757c478bd9Sstevel@tonic-gate 
45767c478bd9Sstevel@tonic-gate 	*cookie = NULL;
45777c478bd9Sstevel@tonic-gate 
45787c478bd9Sstevel@tonic-gate 	ASSERT(rsmseglock_held(seg));
45797c478bd9Sstevel@tonic-gate 
45807c478bd9Sstevel@tonic-gate 	if ((seg->s_state != RSM_STATE_CONN_QUIESCE) &&
45817c478bd9Sstevel@tonic-gate 	    (seg->s_state != RSM_STATE_MAP_QUIESCE)) {
45827c478bd9Sstevel@tonic-gate 		return (RSM_SUCCESS);
45837c478bd9Sstevel@tonic-gate 	}
45847c478bd9Sstevel@tonic-gate 
45857c478bd9Sstevel@tonic-gate 	sharedp = seg->s_share;
45867c478bd9Sstevel@tonic-gate 
45877c478bd9Sstevel@tonic-gate 	rsmsharelock_acquire(seg);
45887c478bd9Sstevel@tonic-gate 
45897c478bd9Sstevel@tonic-gate 	/* resume the shared connection and/or mapping */
45907c478bd9Sstevel@tonic-gate 	retc = rsmsegshare_resume(seg);
45917c478bd9Sstevel@tonic-gate 
45927c478bd9Sstevel@tonic-gate 	if (seg->s_state == RSM_STATE_CONN_QUIESCE) {
45937c478bd9Sstevel@tonic-gate 		/* shared state can either be connected or mapped */
45947c478bd9Sstevel@tonic-gate 		if ((sharedp->rsmsi_state == RSMSI_STATE_CONNECTED) ||
45957c478bd9Sstevel@tonic-gate 		    (sharedp->rsmsi_state == RSMSI_STATE_MAPPED)) {
45967c478bd9Sstevel@tonic-gate 			ASSERT(retc == RSM_SUCCESS);
45977c478bd9Sstevel@tonic-gate 			seg->s_handle.in = sharedp->rsmsi_handle;
45987c478bd9Sstevel@tonic-gate 			rsmsharelock_release(seg);
45997c478bd9Sstevel@tonic-gate 			seg->s_state = RSM_STATE_CONNECT;
46007c478bd9Sstevel@tonic-gate 
46017c478bd9Sstevel@tonic-gate 		} else { /* error in rsmpi connect during resume */
46027c478bd9Sstevel@tonic-gate 			seg->s_handle.in = NULL;
46037c478bd9Sstevel@tonic-gate 			seg->s_state = RSM_STATE_DISCONNECT;
46047c478bd9Sstevel@tonic-gate 
46057c478bd9Sstevel@tonic-gate 			sharedp->rsmsi_refcnt--;
46067c478bd9Sstevel@tonic-gate 			cookie = (void *)sharedp->rsmsi_cookie;
46077c478bd9Sstevel@tonic-gate 
46087c478bd9Sstevel@tonic-gate 			if (sharedp->rsmsi_refcnt == 0) {
46097c478bd9Sstevel@tonic-gate 				ASSERT(sharedp->rsmsi_mapcnt == 0);
46107c478bd9Sstevel@tonic-gate 				rsmsharelock_release(seg);
46117c478bd9Sstevel@tonic-gate 
46127c478bd9Sstevel@tonic-gate 				/* clean up the shared data structure */
46137c478bd9Sstevel@tonic-gate 				mutex_destroy(&sharedp->rsmsi_lock);
46147c478bd9Sstevel@tonic-gate 				cv_destroy(&sharedp->rsmsi_cv);
46157c478bd9Sstevel@tonic-gate 				kmem_free((void *)(sharedp),
46167c478bd9Sstevel@tonic-gate 				    sizeof (rsm_import_share_t));
46177c478bd9Sstevel@tonic-gate 
46187c478bd9Sstevel@tonic-gate 			} else {
46197c478bd9Sstevel@tonic-gate 				rsmsharelock_release(seg);
46207c478bd9Sstevel@tonic-gate 			}
46217c478bd9Sstevel@tonic-gate 			/*
46227c478bd9Sstevel@tonic-gate 			 * The following needs to be done after any
46237c478bd9Sstevel@tonic-gate 			 * rsmsharelock calls which use seg->s_share.
46247c478bd9Sstevel@tonic-gate 			 */
46257c478bd9Sstevel@tonic-gate 			seg->s_share = NULL;
46267c478bd9Sstevel@tonic-gate 		}
46277c478bd9Sstevel@tonic-gate 
46287c478bd9Sstevel@tonic-gate 		/* signal any waiting segment */
46297c478bd9Sstevel@tonic-gate 		cv_broadcast(&seg->s_cv);
46307c478bd9Sstevel@tonic-gate 
46317c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
46327c478bd9Sstevel@tonic-gate 		    "rsmseg_resume done:state=%d\n", seg->s_state));
46337c478bd9Sstevel@tonic-gate 		return (retc);
46347c478bd9Sstevel@tonic-gate 	}
46357c478bd9Sstevel@tonic-gate 
46367c478bd9Sstevel@tonic-gate 	ASSERT(seg->s_state == RSM_STATE_MAP_QUIESCE);
46377c478bd9Sstevel@tonic-gate 
46387c478bd9Sstevel@tonic-gate 	/* Setup protections for remap */
46397c478bd9Sstevel@tonic-gate 	maxprot = PROT_USER;
46407c478bd9Sstevel@tonic-gate 	if (seg->s_mode & RSM_PERM_READ) {
46417c478bd9Sstevel@tonic-gate 		maxprot |= PROT_READ;
46427c478bd9Sstevel@tonic-gate 	}
46437c478bd9Sstevel@tonic-gate 	if (seg->s_mode & RSM_PERM_WRITE) {
46447c478bd9Sstevel@tonic-gate 		maxprot |= PROT_WRITE;
46457c478bd9Sstevel@tonic-gate 	}
46467c478bd9Sstevel@tonic-gate 
46477c478bd9Sstevel@tonic-gate 	if (sharedp->rsmsi_state != RSMSI_STATE_MAPPED) {
46487c478bd9Sstevel@tonic-gate 		/* error in rsmpi connect or map during resume */
46497c478bd9Sstevel@tonic-gate 
46507c478bd9Sstevel@tonic-gate 		/* remap to trash page */
46517c478bd9Sstevel@tonic-gate 		ASSERT(seg->s_ckl != NULL);
46527c478bd9Sstevel@tonic-gate 
46537c478bd9Sstevel@tonic-gate 		for (hdl = seg->s_ckl; hdl != NULL; hdl = hdl->c_next) {
46547c478bd9Sstevel@tonic-gate 			e = devmap_umem_remap(hdl->c_dhp, rsm_dip,
46557c478bd9Sstevel@tonic-gate 			    remap_cookie, hdl->c_off, hdl->c_len,
46567c478bd9Sstevel@tonic-gate 			    maxprot, 0, NULL);
46577c478bd9Sstevel@tonic-gate 
46587c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_ERR,
46597c478bd9Sstevel@tonic-gate 			    "rsmseg_resume:remap=%d\n", e));
46607c478bd9Sstevel@tonic-gate 		}
46617c478bd9Sstevel@tonic-gate 
46627c478bd9Sstevel@tonic-gate 		seg->s_handle.in = NULL;
46637c478bd9Sstevel@tonic-gate 		seg->s_state = RSM_STATE_DISCONNECT;
46647c478bd9Sstevel@tonic-gate 
46657c478bd9Sstevel@tonic-gate 		sharedp->rsmsi_refcnt--;
46667c478bd9Sstevel@tonic-gate 
46677c478bd9Sstevel@tonic-gate 		sharedp->rsmsi_mapcnt--;
46687c478bd9Sstevel@tonic-gate 		seg->s_mapinfo = NULL;
46697c478bd9Sstevel@tonic-gate 
46707c478bd9Sstevel@tonic-gate 		if (sharedp->rsmsi_refcnt == 0) {
46717c478bd9Sstevel@tonic-gate 			ASSERT(sharedp->rsmsi_mapcnt == 0);
46727c478bd9Sstevel@tonic-gate 			rsmsharelock_release(seg);
46737c478bd9Sstevel@tonic-gate 
46747c478bd9Sstevel@tonic-gate 			/* clean up the shared data structure */
46757c478bd9Sstevel@tonic-gate 			mutex_destroy(&sharedp->rsmsi_lock);
46767c478bd9Sstevel@tonic-gate 			cv_destroy(&sharedp->rsmsi_cv);
46777c478bd9Sstevel@tonic-gate 			kmem_free((void *)(sharedp),
46787c478bd9Sstevel@tonic-gate 			    sizeof (rsm_import_share_t));
46797c478bd9Sstevel@tonic-gate 
46807c478bd9Sstevel@tonic-gate 		} else {
46817c478bd9Sstevel@tonic-gate 			rsmsharelock_release(seg);
46827c478bd9Sstevel@tonic-gate 		}
46837c478bd9Sstevel@tonic-gate 		/*
46847c478bd9Sstevel@tonic-gate 		 * The following needs to be done after any
46857c478bd9Sstevel@tonic-gate 		 * rsmsharelock calls which use seg->s_share.
46867c478bd9Sstevel@tonic-gate 		 */
46877c478bd9Sstevel@tonic-gate 		seg->s_share = NULL;
46887c478bd9Sstevel@tonic-gate 
46897c478bd9Sstevel@tonic-gate 		/* signal any waiting segment */
46907c478bd9Sstevel@tonic-gate 		cv_broadcast(&seg->s_cv);
46917c478bd9Sstevel@tonic-gate 
46927c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
46937c478bd9Sstevel@tonic-gate 		    "rsmseg_resume done:seg=%x,err=%d\n",
46947c478bd9Sstevel@tonic-gate 		    seg->s_key, retc));
46957c478bd9Sstevel@tonic-gate 		return (retc);
46967c478bd9Sstevel@tonic-gate 
46977c478bd9Sstevel@tonic-gate 	}
46987c478bd9Sstevel@tonic-gate 
46997c478bd9Sstevel@tonic-gate 	seg->s_handle.in = sharedp->rsmsi_handle;
47007c478bd9Sstevel@tonic-gate 
47017c478bd9Sstevel@tonic-gate 	if (seg->s_node == my_nodeid) { /* loopback */
47027c478bd9Sstevel@tonic-gate 		ASSERT(seg->s_mapinfo == NULL);
47037c478bd9Sstevel@tonic-gate 
47047c478bd9Sstevel@tonic-gate 		for (hdl = seg->s_ckl; hdl != NULL; hdl = hdl->c_next) {
47057c478bd9Sstevel@tonic-gate 			e = devmap_umem_remap(hdl->c_dhp,
47067c478bd9Sstevel@tonic-gate 			    rsm_dip, seg->s_cookie,
47077c478bd9Sstevel@tonic-gate 			    hdl->c_off, hdl->c_len,
47087c478bd9Sstevel@tonic-gate 			    maxprot, 0, NULL);
47097c478bd9Sstevel@tonic-gate 
47107c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_ERR,
47117c478bd9Sstevel@tonic-gate 			    "rsmseg_resume:remap=%d\n", e));
47127c478bd9Sstevel@tonic-gate 		}
47137c478bd9Sstevel@tonic-gate 	} else { /* remote exporter */
47147c478bd9Sstevel@tonic-gate 		/* remap to the new rsmpi maps */
47157c478bd9Sstevel@tonic-gate 		seg->s_mapinfo = sharedp->rsmsi_mapinfo;
47167c478bd9Sstevel@tonic-gate 
47177c478bd9Sstevel@tonic-gate 		for (hdl = seg->s_ckl; hdl != NULL; hdl = hdl->c_next) {
47187c478bd9Sstevel@tonic-gate 			p = rsm_get_mapinfo(seg, hdl->c_off, hdl->c_len,
47197c478bd9Sstevel@tonic-gate 			    &dev_offset, &maplen);
47207c478bd9Sstevel@tonic-gate 			e = devmap_devmem_remap(hdl->c_dhp,
47217c478bd9Sstevel@tonic-gate 			    p->dip, p->dev_register, dev_offset,
47227c478bd9Sstevel@tonic-gate 			    maplen, maxprot, 0, NULL);
47237c478bd9Sstevel@tonic-gate 
47247c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_ERR,
47257c478bd9Sstevel@tonic-gate 			    "rsmseg_resume:remap=%d\n", e));
47267c478bd9Sstevel@tonic-gate 		}
47277c478bd9Sstevel@tonic-gate 	}
47287c478bd9Sstevel@tonic-gate 
47297c478bd9Sstevel@tonic-gate 	rsmsharelock_release(seg);
47307c478bd9Sstevel@tonic-gate 
47317c478bd9Sstevel@tonic-gate 	seg->s_state = RSM_STATE_ACTIVE;
47327c478bd9Sstevel@tonic-gate 	cv_broadcast(&seg->s_cv);
47337c478bd9Sstevel@tonic-gate 
47347c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmseg_resume done\n"));
47357c478bd9Sstevel@tonic-gate 
47367c478bd9Sstevel@tonic-gate 	return (retc);
47377c478bd9Sstevel@tonic-gate }
47387c478bd9Sstevel@tonic-gate 
47397c478bd9Sstevel@tonic-gate static int
rsmsegshare_resume(rsmseg_t * seg)47407c478bd9Sstevel@tonic-gate rsmsegshare_resume(rsmseg_t *seg)
47417c478bd9Sstevel@tonic-gate {
47427c478bd9Sstevel@tonic-gate 	int			e = RSM_SUCCESS;
47437c478bd9Sstevel@tonic-gate 	adapter_t		*adapter;
47447c478bd9Sstevel@tonic-gate 	rsm_import_share_t	*sharedp;
47457c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category,
47467c478bd9Sstevel@tonic-gate 	    RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_INTR_CALLBACK);
47477c478bd9Sstevel@tonic-gate 
47487c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmsegshare_resume enter\n"));
47497c478bd9Sstevel@tonic-gate 
47507c478bd9Sstevel@tonic-gate 	ASSERT(rsmseglock_held(seg));
47517c478bd9Sstevel@tonic-gate 	ASSERT(rsmsharelock_held(seg));
47527c478bd9Sstevel@tonic-gate 
47537c478bd9Sstevel@tonic-gate 	sharedp = seg->s_share;
47547c478bd9Sstevel@tonic-gate 
47557c478bd9Sstevel@tonic-gate 	/*
47567c478bd9Sstevel@tonic-gate 	 * If we are not in a xxxx_QUIESCE state that means shared
47577c478bd9Sstevel@tonic-gate 	 * connect/mapping processing has been already been done
47587c478bd9Sstevel@tonic-gate 	 * so return success.
47597c478bd9Sstevel@tonic-gate 	 */
47607c478bd9Sstevel@tonic-gate 	if ((sharedp->rsmsi_state != RSMSI_STATE_CONN_QUIESCE) &&
47617c478bd9Sstevel@tonic-gate 	    (sharedp->rsmsi_state != RSMSI_STATE_MAP_QUIESCE)) {
47627c478bd9Sstevel@tonic-gate 		return (RSM_SUCCESS);
47637c478bd9Sstevel@tonic-gate 	}
47647c478bd9Sstevel@tonic-gate 
47657c478bd9Sstevel@tonic-gate 	adapter = seg->s_adapter;
47667c478bd9Sstevel@tonic-gate 
47677c478bd9Sstevel@tonic-gate 	if (sharedp->rsmsi_node != my_nodeid) {
47687c478bd9Sstevel@tonic-gate 		rsm_addr_t	hwaddr;
47697c478bd9Sstevel@tonic-gate 		hwaddr = get_remote_hwaddr(adapter, sharedp->rsmsi_node);
47707c478bd9Sstevel@tonic-gate 
47717c478bd9Sstevel@tonic-gate 		e = adapter->rsmpi_ops->rsm_connect(
47727c478bd9Sstevel@tonic-gate 		    adapter->rsmpi_handle, hwaddr,
47737c478bd9Sstevel@tonic-gate 		    sharedp->rsmsi_segid, &sharedp->rsmsi_handle);
47747c478bd9Sstevel@tonic-gate 
47757c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG,
47767c478bd9Sstevel@tonic-gate 		    "rsmsegshare_resume:rsmpi connect seg=%x:err=%d\n",
47777c478bd9Sstevel@tonic-gate 		    sharedp->rsmsi_segid, e));
47787c478bd9Sstevel@tonic-gate 
47797c478bd9Sstevel@tonic-gate 		if (e != RSM_SUCCESS) {
47807c478bd9Sstevel@tonic-gate 			/* when do we send the NOT_IMPORTING message */
47817c478bd9Sstevel@tonic-gate 			sharedp->rsmsi_handle = NULL;
47827c478bd9Sstevel@tonic-gate 			sharedp->rsmsi_state = RSMSI_STATE_DISCONNECTED;
47837c478bd9Sstevel@tonic-gate 			/* signal any waiting segment */
47847c478bd9Sstevel@tonic-gate 			cv_broadcast(&sharedp->rsmsi_cv);
47857c478bd9Sstevel@tonic-gate 			return (e);
47867c478bd9Sstevel@tonic-gate 		}
47877c478bd9Sstevel@tonic-gate 	}
47887c478bd9Sstevel@tonic-gate 
47897c478bd9Sstevel@tonic-gate 	if (sharedp->rsmsi_state == RSMSI_STATE_CONN_QUIESCE) {
47907c478bd9Sstevel@tonic-gate 		sharedp->rsmsi_state = RSMSI_STATE_CONNECTED;
47917c478bd9Sstevel@tonic-gate 		/* signal any waiting segment */
47927c478bd9Sstevel@tonic-gate 		cv_broadcast(&sharedp->rsmsi_cv);
47937c478bd9Sstevel@tonic-gate 		return (e);
47947c478bd9Sstevel@tonic-gate 	}
47957c478bd9Sstevel@tonic-gate 
47967c478bd9Sstevel@tonic-gate 	ASSERT(sharedp->rsmsi_state == RSMSI_STATE_MAP_QUIESCE);
47977c478bd9Sstevel@tonic-gate 
47987c478bd9Sstevel@tonic-gate 	/* do the rsmpi map of the whole segment here */
47997c478bd9Sstevel@tonic-gate 	if (sharedp->rsmsi_node != my_nodeid) {
48007c478bd9Sstevel@tonic-gate 		size_t mapped_len;
48017c478bd9Sstevel@tonic-gate 		rsm_mapinfo_t *p;
48027c478bd9Sstevel@tonic-gate 
48037c478bd9Sstevel@tonic-gate 		/*
48047c478bd9Sstevel@tonic-gate 		 * We need to do rsmpi maps with <off, lens> identical to
48057c478bd9Sstevel@tonic-gate 		 * the old mapinfo list because the segment mapping handles
48067c478bd9Sstevel@tonic-gate 		 * dhp and such need the fragmentation of rsmpi maps to be
48077c478bd9Sstevel@tonic-gate 		 * identical to what it was during the mmap of the segment
48087c478bd9Sstevel@tonic-gate 		 */
48097c478bd9Sstevel@tonic-gate 		p = sharedp->rsmsi_mapinfo;
48107c478bd9Sstevel@tonic-gate 
48117c478bd9Sstevel@tonic-gate 		while (p != NULL) {
48127c478bd9Sstevel@tonic-gate 			mapped_len = 0;
48137c478bd9Sstevel@tonic-gate 
48147c478bd9Sstevel@tonic-gate 			e = adapter->rsmpi_ops->rsm_map(
48157c478bd9Sstevel@tonic-gate 			    sharedp->rsmsi_handle, p->start_offset,
48167c478bd9Sstevel@tonic-gate 			    p->individual_len, &mapped_len,
48177c478bd9Sstevel@tonic-gate 			    &p->dip, &p->dev_register, &p->dev_offset,
48187c478bd9Sstevel@tonic-gate 			    NULL, NULL);
48197c478bd9Sstevel@tonic-gate 
48207c478bd9Sstevel@tonic-gate 			if (e != 0) {
48217c478bd9Sstevel@tonic-gate 				DBG_PRINTF((category, RSM_ERR,
48227c478bd9Sstevel@tonic-gate 				    "rsmsegshare_resume: rsmpi map err=%d\n",
48237c478bd9Sstevel@tonic-gate 				    e));
48247c478bd9Sstevel@tonic-gate 				break;
48257c478bd9Sstevel@tonic-gate 			}
48267c478bd9Sstevel@tonic-gate 
48277c478bd9Sstevel@tonic-gate 			if (mapped_len != p->individual_len) {
48287c478bd9Sstevel@tonic-gate 				DBG_PRINTF((category, RSM_ERR,
48297c478bd9Sstevel@tonic-gate 				    "rsmsegshare_resume: rsmpi maplen"
48307c478bd9Sstevel@tonic-gate 				    "< reqlen=%lx\n", mapped_len));
48317c478bd9Sstevel@tonic-gate 				e = RSMERR_BAD_LENGTH;
48327c478bd9Sstevel@tonic-gate 				break;
48337c478bd9Sstevel@tonic-gate 			}
48347c478bd9Sstevel@tonic-gate 
48357c478bd9Sstevel@tonic-gate 			p = p->next;
48367c478bd9Sstevel@tonic-gate 
48377c478bd9Sstevel@tonic-gate 		}
48387c478bd9Sstevel@tonic-gate 
48397c478bd9Sstevel@tonic-gate 
48407c478bd9Sstevel@tonic-gate 		if (e != RSM_SUCCESS) { /* rsmpi map failed */
48417c478bd9Sstevel@tonic-gate 			int	err;
48427c478bd9Sstevel@tonic-gate 			/* Check if this is the first rsm_map */
48437c478bd9Sstevel@tonic-gate 			if (p != sharedp->rsmsi_mapinfo) {
48447c478bd9Sstevel@tonic-gate 				/*
48457c478bd9Sstevel@tonic-gate 				 * A single rsm_unmap undoes multiple rsm_maps.
48467c478bd9Sstevel@tonic-gate 				 */
48477c478bd9Sstevel@tonic-gate 				(void) seg->s_adapter->rsmpi_ops->
48487c478bd9Sstevel@tonic-gate 				    rsm_unmap(sharedp->rsmsi_handle);
48497c478bd9Sstevel@tonic-gate 			}
48507c478bd9Sstevel@tonic-gate 
48517c478bd9Sstevel@tonic-gate 			rsm_free_mapinfo(sharedp->rsmsi_mapinfo);
48527c478bd9Sstevel@tonic-gate 			sharedp->rsmsi_mapinfo = NULL;
48537c478bd9Sstevel@tonic-gate 
48547c478bd9Sstevel@tonic-gate 			err = adapter->rsmpi_ops->
48557c478bd9Sstevel@tonic-gate 			    rsm_disconnect(sharedp->rsmsi_handle);
48567c478bd9Sstevel@tonic-gate 
48577c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG,
48587c478bd9Sstevel@tonic-gate 			    "rsmsegshare_resume:disconn seg=%x:err=%d\n",
48597c478bd9Sstevel@tonic-gate 			    sharedp->rsmsi_segid, err));
48607c478bd9Sstevel@tonic-gate 
48617c478bd9Sstevel@tonic-gate 			sharedp->rsmsi_handle = NULL;
48627c478bd9Sstevel@tonic-gate 			sharedp->rsmsi_state = RSMSI_STATE_DISCONNECTED;
48637c478bd9Sstevel@tonic-gate 
48647c478bd9Sstevel@tonic-gate 			/* signal the waiting segments */
48657c478bd9Sstevel@tonic-gate 			cv_broadcast(&sharedp->rsmsi_cv);
48667c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG,
48677c478bd9Sstevel@tonic-gate 			    "rsmsegshare_resume done: rsmpi map err\n"));
48687c478bd9Sstevel@tonic-gate 			return (e);
48697c478bd9Sstevel@tonic-gate 		}
48707c478bd9Sstevel@tonic-gate 	}
48717c478bd9Sstevel@tonic-gate 
48727c478bd9Sstevel@tonic-gate 	sharedp->rsmsi_state = RSMSI_STATE_MAPPED;
48737c478bd9Sstevel@tonic-gate 
48747c478bd9Sstevel@tonic-gate 	/* signal any waiting segment */
48757c478bd9Sstevel@tonic-gate 	cv_broadcast(&sharedp->rsmsi_cv);
48767c478bd9Sstevel@tonic-gate 
48777c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmsegshare_resume done\n"));
48787c478bd9Sstevel@tonic-gate 
48797c478bd9Sstevel@tonic-gate 	return (e);
48807c478bd9Sstevel@tonic-gate }
48817c478bd9Sstevel@tonic-gate 
48827c478bd9Sstevel@tonic-gate /*
48837c478bd9Sstevel@tonic-gate  * this is the routine that gets called by recv_taskq which is the
48847c478bd9Sstevel@tonic-gate  * thread that processes messages that are flow-controlled.
48857c478bd9Sstevel@tonic-gate  */
48867c478bd9Sstevel@tonic-gate static void
rsm_intr_proc_deferred(void * arg)48877c478bd9Sstevel@tonic-gate rsm_intr_proc_deferred(void *arg)
48887c478bd9Sstevel@tonic-gate {
48897c478bd9Sstevel@tonic-gate 	path_t			*path = (path_t *)arg;
48907c478bd9Sstevel@tonic-gate 	rsmipc_request_t	*msg;
48917c478bd9Sstevel@tonic-gate 	rsmipc_msghdr_t		*msghdr;
48927c478bd9Sstevel@tonic-gate 	rsm_node_id_t		src_node;
48937c478bd9Sstevel@tonic-gate 	msgbuf_elem_t		*head;
48947c478bd9Sstevel@tonic-gate 	int			e;
48957c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category,
48967c478bd9Sstevel@tonic-gate 	    RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_INTR_CALLBACK);
48977c478bd9Sstevel@tonic-gate 
48987c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
48997c478bd9Sstevel@tonic-gate 	    "rsm_intr_proc_deferred enter\n"));
49007c478bd9Sstevel@tonic-gate 
49017c478bd9Sstevel@tonic-gate 	mutex_enter(&path->mutex);
49027c478bd9Sstevel@tonic-gate 
49037c478bd9Sstevel@tonic-gate 	/* use the head of the msgbuf_queue */
49047c478bd9Sstevel@tonic-gate 	head = rsmka_gethead_msgbuf(path);
49057c478bd9Sstevel@tonic-gate 
49067c478bd9Sstevel@tonic-gate 	mutex_exit(&path->mutex);
49077c478bd9Sstevel@tonic-gate 
49087c478bd9Sstevel@tonic-gate 	msg = (rsmipc_request_t *)&(head->msg);
49097c478bd9Sstevel@tonic-gate 	msghdr = (rsmipc_msghdr_t *)msg;
49107c478bd9Sstevel@tonic-gate 
49117c478bd9Sstevel@tonic-gate 	src_node = msghdr->rsmipc_src;
49127c478bd9Sstevel@tonic-gate 
49137c478bd9Sstevel@tonic-gate 	/*
49147c478bd9Sstevel@tonic-gate 	 * messages that need to send a reply should check the message version
49157c478bd9Sstevel@tonic-gate 	 * before processing the message. And all messages that need to
49167c478bd9Sstevel@tonic-gate 	 * send a reply should be processed here by the worker thread.
49177c478bd9Sstevel@tonic-gate 	 */
49187c478bd9Sstevel@tonic-gate 	switch (msghdr->rsmipc_type) {
49197c478bd9Sstevel@tonic-gate 	case RSMIPC_MSG_SEGCONNECT:
49207c478bd9Sstevel@tonic-gate 		if (msghdr->rsmipc_version != RSM_VERSION) {
49217c478bd9Sstevel@tonic-gate 			rsmipc_reply_t reply;
49227c478bd9Sstevel@tonic-gate 			reply.rsmipc_status = RSMERR_BAD_DRIVER_VERSION;
49237c478bd9Sstevel@tonic-gate 			reply.rsmipc_hdr.rsmipc_type = RSMIPC_MSG_REPLY;
49247c478bd9Sstevel@tonic-gate 			reply.rsmipc_hdr.rsmipc_cookie = msghdr->rsmipc_cookie;
49257c478bd9Sstevel@tonic-gate 			(void) rsmipc_send(msghdr->rsmipc_src, NULL, &reply);
49267c478bd9Sstevel@tonic-gate 		} else {
49277c478bd9Sstevel@tonic-gate 			rsm_intr_segconnect(src_node, msg);
49287c478bd9Sstevel@tonic-gate 		}
49297c478bd9Sstevel@tonic-gate 		break;
49307c478bd9Sstevel@tonic-gate 	case RSMIPC_MSG_DISCONNECT:
49317c478bd9Sstevel@tonic-gate 		rsm_force_unload(src_node, msg->rsmipc_key, DISCONNECT);
49327c478bd9Sstevel@tonic-gate 		break;
49337c478bd9Sstevel@tonic-gate 	case RSMIPC_MSG_SUSPEND:
49347c478bd9Sstevel@tonic-gate 		importer_suspend(src_node);
49357c478bd9Sstevel@tonic-gate 		break;
49367c478bd9Sstevel@tonic-gate 	case RSMIPC_MSG_SUSPEND_DONE:
49377c478bd9Sstevel@tonic-gate 		rsm_suspend_complete(src_node, 0);
49387c478bd9Sstevel@tonic-gate 		break;
49397c478bd9Sstevel@tonic-gate 	case RSMIPC_MSG_RESUME:
49407c478bd9Sstevel@tonic-gate 		importer_resume(src_node);
49417c478bd9Sstevel@tonic-gate 		break;
49427c478bd9Sstevel@tonic-gate 	default:
49437c478bd9Sstevel@tonic-gate 		ASSERT(0);
49447c478bd9Sstevel@tonic-gate 	}
49457c478bd9Sstevel@tonic-gate 
49467c478bd9Sstevel@tonic-gate 	mutex_enter(&path->mutex);
49477c478bd9Sstevel@tonic-gate 
49487c478bd9Sstevel@tonic-gate 	rsmka_dequeue_msgbuf(path);
49497c478bd9Sstevel@tonic-gate 
49507c478bd9Sstevel@tonic-gate 	/* incr procmsg_cnt can be at most RSMIPC_MAX_MESSAGES */
49517c478bd9Sstevel@tonic-gate 	if (path->procmsg_cnt < RSMIPC_MAX_MESSAGES)
49527c478bd9Sstevel@tonic-gate 		path->procmsg_cnt++;
49537c478bd9Sstevel@tonic-gate 
49547c478bd9Sstevel@tonic-gate 	ASSERT(path->procmsg_cnt <= RSMIPC_MAX_MESSAGES);
49557c478bd9Sstevel@tonic-gate 
49567c478bd9Sstevel@tonic-gate 	/* No need to send credits if path is going down */
49577c478bd9Sstevel@tonic-gate 	if ((path->state == RSMKA_PATH_ACTIVE) &&
49587c478bd9Sstevel@tonic-gate 	    (path->procmsg_cnt >= RSMIPC_LOTSFREE_MSGBUFS)) {
49597c478bd9Sstevel@tonic-gate 		/*
49607c478bd9Sstevel@tonic-gate 		 * send credits and reset procmsg_cnt if success otherwise
49617c478bd9Sstevel@tonic-gate 		 * credits will be sent after processing the next message
49627c478bd9Sstevel@tonic-gate 		 */
49637c478bd9Sstevel@tonic-gate 		e = rsmipc_send_controlmsg(path, RSMIPC_MSG_CREDIT);
49647c478bd9Sstevel@tonic-gate 		if (e == 0)
49657c478bd9Sstevel@tonic-gate 			path->procmsg_cnt = 0;
49667c478bd9Sstevel@tonic-gate 		else
49677c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_ERR,
49687c478bd9Sstevel@tonic-gate 			    "rsm_intr_proc_deferred:send credits err=%d\n", e));
49697c478bd9Sstevel@tonic-gate 	}
49707c478bd9Sstevel@tonic-gate 
49717c478bd9Sstevel@tonic-gate 	/*
49727c478bd9Sstevel@tonic-gate 	 * decrement the path refcnt since we incremented it in
49737c478bd9Sstevel@tonic-gate 	 * rsm_intr_callback_dispatch
49747c478bd9Sstevel@tonic-gate 	 */
49757c478bd9Sstevel@tonic-gate 	PATH_RELE_NOLOCK(path);
49767c478bd9Sstevel@tonic-gate 
49777c478bd9Sstevel@tonic-gate 	mutex_exit(&path->mutex);
49787c478bd9Sstevel@tonic-gate 
49797c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
49807c478bd9Sstevel@tonic-gate 	    "rsm_intr_proc_deferred done\n"));
49817c478bd9Sstevel@tonic-gate }
49827c478bd9Sstevel@tonic-gate 
49837c478bd9Sstevel@tonic-gate /*
49847c478bd9Sstevel@tonic-gate  * Flow-controlled messages are enqueued and dispatched onto a taskq here
49857c478bd9Sstevel@tonic-gate  */
49867c478bd9Sstevel@tonic-gate static void
rsm_intr_callback_dispatch(void * data,rsm_addr_t src_hwaddr,rsm_intr_hand_arg_t arg)49877c478bd9Sstevel@tonic-gate rsm_intr_callback_dispatch(void *data, rsm_addr_t src_hwaddr,
49887c478bd9Sstevel@tonic-gate     rsm_intr_hand_arg_t arg)
49897c478bd9Sstevel@tonic-gate {
49907c478bd9Sstevel@tonic-gate 	srv_handler_arg_t	*hdlr_argp = (srv_handler_arg_t *)arg;
49917c478bd9Sstevel@tonic-gate 	path_t			*path;
49927c478bd9Sstevel@tonic-gate 	rsmipc_msghdr_t *msghdr = (rsmipc_msghdr_t *)data;
49937c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category,
49947c478bd9Sstevel@tonic-gate 	    RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_INTR_CALLBACK);
49957c478bd9Sstevel@tonic-gate 
49967c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
49977c478bd9Sstevel@tonic-gate 	    "rsm_intr_callback_dispatch enter\n"));
49987c478bd9Sstevel@tonic-gate 	ASSERT(data && hdlr_argp);
49997c478bd9Sstevel@tonic-gate 
50007c478bd9Sstevel@tonic-gate 	/* look up the path - incr the path refcnt */
50017c478bd9Sstevel@tonic-gate 	path = rsm_find_path(hdlr_argp->adapter_name,
50027c478bd9Sstevel@tonic-gate 	    hdlr_argp->adapter_instance, src_hwaddr);
50037c478bd9Sstevel@tonic-gate 
50047c478bd9Sstevel@tonic-gate 	/* the path has been removed - drop this message */
50057c478bd9Sstevel@tonic-gate 	if (path == NULL) {
50067c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG,
50077c478bd9Sstevel@tonic-gate 		    "rsm_intr_callback_dispatch done: msg dropped\n"));
50087c478bd9Sstevel@tonic-gate 		return;
50097c478bd9Sstevel@tonic-gate 	}
50107c478bd9Sstevel@tonic-gate 	/* the path is not active - don't accept new messages */
50117c478bd9Sstevel@tonic-gate 	if (path->state != RSMKA_PATH_ACTIVE) {
50127c478bd9Sstevel@tonic-gate 		PATH_RELE_NOLOCK(path);
50137c478bd9Sstevel@tonic-gate 		mutex_exit(&path->mutex);
50147c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG,
50157c478bd9Sstevel@tonic-gate 		    "rsm_intr_callback_dispatch done: msg dropped"
50167c478bd9Sstevel@tonic-gate 		    " path=%lx !ACTIVE\n", path));
50177c478bd9Sstevel@tonic-gate 		return;
50187c478bd9Sstevel@tonic-gate 	}
50197c478bd9Sstevel@tonic-gate 
50207c478bd9Sstevel@tonic-gate 	/*
50217c478bd9Sstevel@tonic-gate 	 * Check if this message was sent to an older incarnation
50227c478bd9Sstevel@tonic-gate 	 * of the path/sendq.
50237c478bd9Sstevel@tonic-gate 	 */
50247c478bd9Sstevel@tonic-gate 	if (path->local_incn != msghdr->rsmipc_incn) {
50257c478bd9Sstevel@tonic-gate 		/* decrement the refcnt */
50267c478bd9Sstevel@tonic-gate 		PATH_RELE_NOLOCK(path);
50277c478bd9Sstevel@tonic-gate 		mutex_exit(&path->mutex);
50287c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG,
50297c478bd9Sstevel@tonic-gate 		    "rsm_intr_callback_dispatch done: old incn %lld\n",
50307c478bd9Sstevel@tonic-gate 		    msghdr->rsmipc_incn));
50317c478bd9Sstevel@tonic-gate 		return;
50327c478bd9Sstevel@tonic-gate 	}
50337c478bd9Sstevel@tonic-gate 
50347c478bd9Sstevel@tonic-gate 	/* copy and enqueue msg on the path's msgbuf queue */
50357c478bd9Sstevel@tonic-gate 	rsmka_enqueue_msgbuf(path, data);
50367c478bd9Sstevel@tonic-gate 
50377c478bd9Sstevel@tonic-gate 	/*
50387c478bd9Sstevel@tonic-gate 	 * schedule task to process messages - ignore retval from
50397c478bd9Sstevel@tonic-gate 	 * task_dispatch because we sender cannot send more than
50407c478bd9Sstevel@tonic-gate 	 * what receiver can handle.
50417c478bd9Sstevel@tonic-gate 	 */
50427c478bd9Sstevel@tonic-gate 	(void) taskq_dispatch(path->recv_taskq,
50437c478bd9Sstevel@tonic-gate 	    rsm_intr_proc_deferred, path, KM_NOSLEEP);
50447c478bd9Sstevel@tonic-gate 
50457c478bd9Sstevel@tonic-gate 	mutex_exit(&path->mutex);
50467c478bd9Sstevel@tonic-gate 
50477c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
50487c478bd9Sstevel@tonic-gate 	    "rsm_intr_callback_dispatch done\n"));
50497c478bd9Sstevel@tonic-gate }
50507c478bd9Sstevel@tonic-gate 
50517c478bd9Sstevel@tonic-gate /*
50527c478bd9Sstevel@tonic-gate  * This procedure is called from rsm_srv_func when a remote node creates a
50537c478bd9Sstevel@tonic-gate  * a send queue.  This event is used as a hint that an  earlier failed
50547c478bd9Sstevel@tonic-gate  * attempt to create a send queue to that remote node may now succeed and
50557c478bd9Sstevel@tonic-gate  * should be retried.  Indication of an earlier failed attempt is provided
50567c478bd9Sstevel@tonic-gate  * by the RSMKA_SQCREATE_PENDING flag.
50577c478bd9Sstevel@tonic-gate  */
50587c478bd9Sstevel@tonic-gate static void
rsm_sqcreateop_callback(rsm_addr_t src_hwaddr,rsm_intr_hand_arg_t arg)50597c478bd9Sstevel@tonic-gate rsm_sqcreateop_callback(rsm_addr_t src_hwaddr, rsm_intr_hand_arg_t arg)
50607c478bd9Sstevel@tonic-gate {
50617c478bd9Sstevel@tonic-gate 	srv_handler_arg_t	*hdlr_argp = (srv_handler_arg_t *)arg;
50627c478bd9Sstevel@tonic-gate 	path_t			*path;
50637c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category,
50647c478bd9Sstevel@tonic-gate 	    RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_INTR_CALLBACK);
50657c478bd9Sstevel@tonic-gate 
50667c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
50677c478bd9Sstevel@tonic-gate 	    "rsm_sqcreateop_callback enter\n"));
50687c478bd9Sstevel@tonic-gate 
50697c478bd9Sstevel@tonic-gate 	/* look up the path - incr the path refcnt */
50707c478bd9Sstevel@tonic-gate 	path = rsm_find_path(hdlr_argp->adapter_name,
50717c478bd9Sstevel@tonic-gate 	    hdlr_argp->adapter_instance, src_hwaddr);
50727c478bd9Sstevel@tonic-gate 
50737c478bd9Sstevel@tonic-gate 	if (path == NULL) {
50747c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG,
50757c478bd9Sstevel@tonic-gate 		    "rsm_sqcreateop_callback done: no path\n"));
50767c478bd9Sstevel@tonic-gate 		return;
50777c478bd9Sstevel@tonic-gate 	}
50787c478bd9Sstevel@tonic-gate 
50797c478bd9Sstevel@tonic-gate 	if ((path->state == RSMKA_PATH_UP) &&
50807c478bd9Sstevel@tonic-gate 	    (path->flags & RSMKA_SQCREATE_PENDING)) {
50817c478bd9Sstevel@tonic-gate 		/*
50827c478bd9Sstevel@tonic-gate 		 * previous attempt to create sendq had failed, retry
50837c478bd9Sstevel@tonic-gate 		 * it and move to RSMKA_PATH_ACTIVE state if successful.
50847c478bd9Sstevel@tonic-gate 		 * the refcnt will be decremented in the do_deferred_work
50857c478bd9Sstevel@tonic-gate 		 */
50867c478bd9Sstevel@tonic-gate 		(void) rsmka_do_path_active(path, RSMKA_NO_SLEEP);
50877c478bd9Sstevel@tonic-gate 	} else {
50887c478bd9Sstevel@tonic-gate 		/* decrement the refcnt */
50897c478bd9Sstevel@tonic-gate 		PATH_RELE_NOLOCK(path);
50907c478bd9Sstevel@tonic-gate 	}
50917c478bd9Sstevel@tonic-gate 	mutex_exit(&path->mutex);
50927c478bd9Sstevel@tonic-gate 
50937c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
50947c478bd9Sstevel@tonic-gate 	    "rsm_sqcreateop_callback done\n"));
50957c478bd9Sstevel@tonic-gate }
50967c478bd9Sstevel@tonic-gate 
50977c478bd9Sstevel@tonic-gate static void
rsm_intr_callback(void * data,rsm_addr_t src_hwaddr,rsm_intr_hand_arg_t arg)50987c478bd9Sstevel@tonic-gate rsm_intr_callback(void *data, rsm_addr_t src_hwaddr, rsm_intr_hand_arg_t arg)
50997c478bd9Sstevel@tonic-gate {
51007c478bd9Sstevel@tonic-gate 	rsmipc_msghdr_t *msghdr = (rsmipc_msghdr_t *)data;
51017c478bd9Sstevel@tonic-gate 	rsmipc_request_t *msg = (rsmipc_request_t *)data;
51027c478bd9Sstevel@tonic-gate 	rsmipc_controlmsg_t *ctrlmsg = (rsmipc_controlmsg_t *)data;
51037c478bd9Sstevel@tonic-gate 	rsm_node_id_t src_node;
51047c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category,
51057c478bd9Sstevel@tonic-gate 	    RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_INTR_CALLBACK);
51067c478bd9Sstevel@tonic-gate 
51077c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_intr_callback enter:"
51087c478bd9Sstevel@tonic-gate 	    "src=%d, type=%d\n", msghdr->rsmipc_src,
51097c478bd9Sstevel@tonic-gate 	    msghdr->rsmipc_type));
51107c478bd9Sstevel@tonic-gate 
51117c478bd9Sstevel@tonic-gate 	/*
51127c478bd9Sstevel@tonic-gate 	 * Check for the version number in the msg header. If it is not
51137c478bd9Sstevel@tonic-gate 	 * RSM_VERSION, drop the message. In the future, we need to manage
51147c478bd9Sstevel@tonic-gate 	 * incompatible version numbers in some way
51157c478bd9Sstevel@tonic-gate 	 */
51167c478bd9Sstevel@tonic-gate 	if (msghdr->rsmipc_version != RSM_VERSION) {
51177c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR, "wrong KA version\n"));
51187c478bd9Sstevel@tonic-gate 		/*
51197c478bd9Sstevel@tonic-gate 		 * Drop requests that don't have a reply right here
51207c478bd9Sstevel@tonic-gate 		 * Request with reply will send a BAD_VERSION reply
51217c478bd9Sstevel@tonic-gate 		 * when they get processed by the worker thread.
51227c478bd9Sstevel@tonic-gate 		 */
51237c478bd9Sstevel@tonic-gate 		if (msghdr->rsmipc_type != RSMIPC_MSG_SEGCONNECT) {
51247c478bd9Sstevel@tonic-gate 			return;
51257c478bd9Sstevel@tonic-gate 		}
51267c478bd9Sstevel@tonic-gate 
51277c478bd9Sstevel@tonic-gate 	}
51287c478bd9Sstevel@tonic-gate 
51297c478bd9Sstevel@tonic-gate 	src_node = msghdr->rsmipc_src;
51307c478bd9Sstevel@tonic-gate 
51317c478bd9Sstevel@tonic-gate 	switch (msghdr->rsmipc_type) {
51327c478bd9Sstevel@tonic-gate 	case RSMIPC_MSG_SEGCONNECT:
51337c478bd9Sstevel@tonic-gate 	case RSMIPC_MSG_DISCONNECT:
51347c478bd9Sstevel@tonic-gate 	case RSMIPC_MSG_SUSPEND:
51357c478bd9Sstevel@tonic-gate 	case RSMIPC_MSG_SUSPEND_DONE:
51367c478bd9Sstevel@tonic-gate 	case RSMIPC_MSG_RESUME:
51377c478bd9Sstevel@tonic-gate 		/*
51387c478bd9Sstevel@tonic-gate 		 * These message types are handled by a worker thread using
51397c478bd9Sstevel@tonic-gate 		 * the flow-control algorithm.
51407c478bd9Sstevel@tonic-gate 		 * Any message processing that does one or more of the
51417c478bd9Sstevel@tonic-gate 		 * following should be handled in a worker thread.
51427c478bd9Sstevel@tonic-gate 		 *	- allocates resources and might sleep
51437c478bd9Sstevel@tonic-gate 		 *	- makes RSMPI calls down to the interconnect driver
51447c478bd9Sstevel@tonic-gate 		 *	this by defn include requests with reply.
51457c478bd9Sstevel@tonic-gate 		 *	- takes a long duration of time
51467c478bd9Sstevel@tonic-gate 		 */
51477c478bd9Sstevel@tonic-gate 		rsm_intr_callback_dispatch(data, src_hwaddr, arg);
51487c478bd9Sstevel@tonic-gate 		break;
51497c478bd9Sstevel@tonic-gate 	case RSMIPC_MSG_NOTIMPORTING:
51507c478bd9Sstevel@tonic-gate 		importer_list_rm(src_node, msg->rsmipc_key,
51517c478bd9Sstevel@tonic-gate 		    msg->rsmipc_segment_cookie);
51527c478bd9Sstevel@tonic-gate 		break;
51537c478bd9Sstevel@tonic-gate 	case RSMIPC_MSG_SQREADY:
51547c478bd9Sstevel@tonic-gate 		rsm_proc_sqready(data, src_hwaddr, arg);
51557c478bd9Sstevel@tonic-gate 		break;
51567c478bd9Sstevel@tonic-gate 	case RSMIPC_MSG_SQREADY_ACK:
51577c478bd9Sstevel@tonic-gate 		rsm_proc_sqready_ack(data, src_hwaddr, arg);
51587c478bd9Sstevel@tonic-gate 		break;
51597c478bd9Sstevel@tonic-gate 	case RSMIPC_MSG_CREDIT:
51607c478bd9Sstevel@tonic-gate 		rsm_add_credits(ctrlmsg, src_hwaddr, arg);
51617c478bd9Sstevel@tonic-gate 		break;
51627c478bd9Sstevel@tonic-gate 	case RSMIPC_MSG_REPLY:
51637c478bd9Sstevel@tonic-gate 		rsm_intr_reply(msghdr);
51647c478bd9Sstevel@tonic-gate 		break;
51657c478bd9Sstevel@tonic-gate 	case RSMIPC_MSG_BELL:
51667c478bd9Sstevel@tonic-gate 		rsm_intr_event(msg);
51677c478bd9Sstevel@tonic-gate 		break;
51687c478bd9Sstevel@tonic-gate 	case RSMIPC_MSG_IMPORTING:
51697c478bd9Sstevel@tonic-gate 		importer_list_add(src_node, msg->rsmipc_key,
51707c478bd9Sstevel@tonic-gate 		    msg->rsmipc_adapter_hwaddr,
51717c478bd9Sstevel@tonic-gate 		    msg->rsmipc_segment_cookie);
51727c478bd9Sstevel@tonic-gate 		break;
51737c478bd9Sstevel@tonic-gate 	case RSMIPC_MSG_REPUBLISH:
51747c478bd9Sstevel@tonic-gate 		importer_update(src_node, msg->rsmipc_key, msg->rsmipc_perm);
51757c478bd9Sstevel@tonic-gate 		break;
51767c478bd9Sstevel@tonic-gate 	default:
51777c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG,
51787c478bd9Sstevel@tonic-gate 		    "rsm_intr_callback: bad msg %lx type %d data %lx\n",
51797c478bd9Sstevel@tonic-gate 		    (size_t)msg, (int)(msghdr->rsmipc_type), (size_t)data));
51807c478bd9Sstevel@tonic-gate 	}
51817c478bd9Sstevel@tonic-gate 
51827c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_intr_callback done\n"));
51837c478bd9Sstevel@tonic-gate 
51847c478bd9Sstevel@tonic-gate }
51857c478bd9Sstevel@tonic-gate 
rsm_srv_func(rsm_controller_object_t * chd,rsm_intr_q_op_t opcode,rsm_addr_t src,void * data,size_t size,rsm_intr_hand_arg_t arg)51867c478bd9Sstevel@tonic-gate rsm_intr_hand_ret_t rsm_srv_func(rsm_controller_object_t *chd,
51877c478bd9Sstevel@tonic-gate     rsm_intr_q_op_t opcode, rsm_addr_t src,
51887c478bd9Sstevel@tonic-gate     void *data, size_t size, rsm_intr_hand_arg_t arg)
51897c478bd9Sstevel@tonic-gate {
51907c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category,
51917c478bd9Sstevel@tonic-gate 	    RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_INTR_CALLBACK);
51927c478bd9Sstevel@tonic-gate 
51937c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_srv_func enter\n"));
51947c478bd9Sstevel@tonic-gate 
51957c478bd9Sstevel@tonic-gate 	switch (opcode) {
51967c478bd9Sstevel@tonic-gate 	case RSM_INTR_Q_OP_CREATE:
51977c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG, "rsm_srv_func:OP_CREATE\n"));
51987c478bd9Sstevel@tonic-gate 		rsm_sqcreateop_callback(src, arg);
51997c478bd9Sstevel@tonic-gate 		break;
52007c478bd9Sstevel@tonic-gate 	case RSM_INTR_Q_OP_DESTROY:
52017c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG, "rsm_srv_func:OP_DESTROY\n"));
52027c478bd9Sstevel@tonic-gate 		break;
52037c478bd9Sstevel@tonic-gate 	case RSM_INTR_Q_OP_RECEIVE:
52047c478bd9Sstevel@tonic-gate 		rsm_intr_callback(data, src, arg);
52057c478bd9Sstevel@tonic-gate 		break;
52067c478bd9Sstevel@tonic-gate 	default:
52077c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
52087c478bd9Sstevel@tonic-gate 		    "rsm_srv_func: unknown opcode = %x\n", opcode));
52097c478bd9Sstevel@tonic-gate 	}
52107c478bd9Sstevel@tonic-gate 
52117c478bd9Sstevel@tonic-gate 	chd = chd;
52127c478bd9Sstevel@tonic-gate 	size = size;
52137c478bd9Sstevel@tonic-gate 
52147c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_srv_func done\n"));
52157c478bd9Sstevel@tonic-gate 
52167c478bd9Sstevel@tonic-gate 	return (RSM_INTR_HAND_CLAIMED);
52177c478bd9Sstevel@tonic-gate }
52187c478bd9Sstevel@tonic-gate 
52197c478bd9Sstevel@tonic-gate /* *************************** IPC slots ************************* */
52207c478bd9Sstevel@tonic-gate static rsmipc_slot_t *
rsmipc_alloc()52217c478bd9Sstevel@tonic-gate rsmipc_alloc()
52227c478bd9Sstevel@tonic-gate {
52237c478bd9Sstevel@tonic-gate 	int i;
52247c478bd9Sstevel@tonic-gate 	rsmipc_slot_t *slot;
52257c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL);
52267c478bd9Sstevel@tonic-gate 
52277c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmipc_alloc enter\n"));
52287c478bd9Sstevel@tonic-gate 
52297c478bd9Sstevel@tonic-gate 	/* try to find a free slot, if not wait */
52307c478bd9Sstevel@tonic-gate 	mutex_enter(&rsm_ipc.lock);
52317c478bd9Sstevel@tonic-gate 
52327c478bd9Sstevel@tonic-gate 	while (rsm_ipc.count == 0) {
52337c478bd9Sstevel@tonic-gate 		rsm_ipc.wanted = 1;
52347c478bd9Sstevel@tonic-gate 		cv_wait(&rsm_ipc.cv, &rsm_ipc.lock);
52357c478bd9Sstevel@tonic-gate 	}
52367c478bd9Sstevel@tonic-gate 
52377c478bd9Sstevel@tonic-gate 	/* An empty slot is available, find it */
52387c478bd9Sstevel@tonic-gate 	slot = &rsm_ipc.slots[0];
52397c478bd9Sstevel@tonic-gate 	for (i = 0; i < RSMIPC_SZ; i++, slot++) {
52407c478bd9Sstevel@tonic-gate 		if (RSMIPC_GET(slot, RSMIPC_FREE)) {
52417c478bd9Sstevel@tonic-gate 			RSMIPC_CLEAR(slot, RSMIPC_FREE);
52427c478bd9Sstevel@tonic-gate 			break;
52437c478bd9Sstevel@tonic-gate 		}
52447c478bd9Sstevel@tonic-gate 	}
52457c478bd9Sstevel@tonic-gate 
52467c478bd9Sstevel@tonic-gate 	ASSERT(i < RSMIPC_SZ);
52477c478bd9Sstevel@tonic-gate 	rsm_ipc.count--;	/* one less is available */
52487c478bd9Sstevel@tonic-gate 	rsm_ipc.sequence++; /* new sequence */
52497c478bd9Sstevel@tonic-gate 
52507c478bd9Sstevel@tonic-gate 	slot->rsmipc_cookie.ic.sequence = (uint_t)rsm_ipc.sequence;
52517c478bd9Sstevel@tonic-gate 	slot->rsmipc_cookie.ic.index = (uint_t)i;
52527c478bd9Sstevel@tonic-gate 
52537c478bd9Sstevel@tonic-gate 	mutex_exit(&rsm_ipc.lock);
52547c478bd9Sstevel@tonic-gate 
52557c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmipc_alloc done\n"));
52567c478bd9Sstevel@tonic-gate 
52577c478bd9Sstevel@tonic-gate 	return (slot);
52587c478bd9Sstevel@tonic-gate }
52597c478bd9Sstevel@tonic-gate 
52607c478bd9Sstevel@tonic-gate static void
rsmipc_free(rsmipc_slot_t * slot)52617c478bd9Sstevel@tonic-gate rsmipc_free(rsmipc_slot_t *slot)
52627c478bd9Sstevel@tonic-gate {
52637c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL);
52647c478bd9Sstevel@tonic-gate 
52657c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmipc_free enter\n"));
52667c478bd9Sstevel@tonic-gate 
52677c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&slot->rsmipc_lock));
52687c478bd9Sstevel@tonic-gate 	ASSERT(&rsm_ipc.slots[slot->rsmipc_cookie.ic.index] == slot);
52697c478bd9Sstevel@tonic-gate 
52707c478bd9Sstevel@tonic-gate 	mutex_enter(&rsm_ipc.lock);
52717c478bd9Sstevel@tonic-gate 
52727c478bd9Sstevel@tonic-gate 	RSMIPC_SET(slot, RSMIPC_FREE);
52737c478bd9Sstevel@tonic-gate 
52747c478bd9Sstevel@tonic-gate 	slot->rsmipc_cookie.ic.sequence = 0;
52757c478bd9Sstevel@tonic-gate 
52767c478bd9Sstevel@tonic-gate 	mutex_exit(&slot->rsmipc_lock);
52777c478bd9Sstevel@tonic-gate 	rsm_ipc.count++;
52787c478bd9Sstevel@tonic-gate 	ASSERT(rsm_ipc.count <= RSMIPC_SZ);
52797c478bd9Sstevel@tonic-gate 	if (rsm_ipc.wanted) {
52807c478bd9Sstevel@tonic-gate 		rsm_ipc.wanted = 0;
52817c478bd9Sstevel@tonic-gate 		cv_broadcast(&rsm_ipc.cv);
52827c478bd9Sstevel@tonic-gate 	}
52837c478bd9Sstevel@tonic-gate 
52847c478bd9Sstevel@tonic-gate 	mutex_exit(&rsm_ipc.lock);
52857c478bd9Sstevel@tonic-gate 
52867c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmipc_free done\n"));
52877c478bd9Sstevel@tonic-gate }
52887c478bd9Sstevel@tonic-gate 
52897c478bd9Sstevel@tonic-gate static int
rsmipc_send(rsm_node_id_t dest,rsmipc_request_t * req,rsmipc_reply_t * reply)52907c478bd9Sstevel@tonic-gate rsmipc_send(rsm_node_id_t dest, rsmipc_request_t *req, rsmipc_reply_t *reply)
52917c478bd9Sstevel@tonic-gate {
52927c478bd9Sstevel@tonic-gate 	int		e = 0;
52937c478bd9Sstevel@tonic-gate 	int		credit_check = 0;
52947c478bd9Sstevel@tonic-gate 	int		retry_cnt = 0;
52957c478bd9Sstevel@tonic-gate 	int		min_retry_cnt = 10;
52967c478bd9Sstevel@tonic-gate 	rsm_send_t	is;
52977c478bd9Sstevel@tonic-gate 	rsmipc_slot_t	*rslot;
52987c478bd9Sstevel@tonic-gate 	adapter_t	*adapter;
52997c478bd9Sstevel@tonic-gate 	path_t		*path;
53007c478bd9Sstevel@tonic-gate 	sendq_token_t	*sendq_token;
53017c478bd9Sstevel@tonic-gate 	sendq_token_t	*used_sendq_token = NULL;
53027c478bd9Sstevel@tonic-gate 	rsm_send_q_handle_t	ipc_handle;
53037c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category,
53047c478bd9Sstevel@tonic-gate 	    RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_INTR_CALLBACK);
53057c478bd9Sstevel@tonic-gate 
53067c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmipc_send enter:dest=%d",
53077c478bd9Sstevel@tonic-gate 	    dest));
53087c478bd9Sstevel@tonic-gate 
53097c478bd9Sstevel@tonic-gate 	/*
53107c478bd9Sstevel@tonic-gate 	 * Check if this is a local case
53117c478bd9Sstevel@tonic-gate 	 */
53127c478bd9Sstevel@tonic-gate 	if (dest == my_nodeid) {
53137c478bd9Sstevel@tonic-gate 		switch (req->rsmipc_hdr.rsmipc_type) {
53147c478bd9Sstevel@tonic-gate 		case RSMIPC_MSG_SEGCONNECT:
53157c478bd9Sstevel@tonic-gate 			reply->rsmipc_status = (short)rsmsegacl_validate(
53167c478bd9Sstevel@tonic-gate 			    req, dest, reply);
53177c478bd9Sstevel@tonic-gate 			break;
53187c478bd9Sstevel@tonic-gate 		case RSMIPC_MSG_BELL:
53197c478bd9Sstevel@tonic-gate 			req->rsmipc_hdr.rsmipc_src = dest;
53207c478bd9Sstevel@tonic-gate 			rsm_intr_event(req);
53217c478bd9Sstevel@tonic-gate 			break;
53227c478bd9Sstevel@tonic-gate 		case RSMIPC_MSG_IMPORTING:
53237c478bd9Sstevel@tonic-gate 			importer_list_add(dest, req->rsmipc_key,
53247c478bd9Sstevel@tonic-gate 			    req->rsmipc_adapter_hwaddr,
53257c478bd9Sstevel@tonic-gate 			    req->rsmipc_segment_cookie);
53267c478bd9Sstevel@tonic-gate 			break;
53277c478bd9Sstevel@tonic-gate 		case RSMIPC_MSG_NOTIMPORTING:
53287c478bd9Sstevel@tonic-gate 			importer_list_rm(dest, req->rsmipc_key,
53297c478bd9Sstevel@tonic-gate 			    req->rsmipc_segment_cookie);
53307c478bd9Sstevel@tonic-gate 			break;
53317c478bd9Sstevel@tonic-gate 		case RSMIPC_MSG_REPUBLISH:
53327c478bd9Sstevel@tonic-gate 			importer_update(dest, req->rsmipc_key,
53337c478bd9Sstevel@tonic-gate 			    req->rsmipc_perm);
53347c478bd9Sstevel@tonic-gate 			break;
53357c478bd9Sstevel@tonic-gate 		case RSMIPC_MSG_SUSPEND:
53367c478bd9Sstevel@tonic-gate 			importer_suspend(dest);
53377c478bd9Sstevel@tonic-gate 			break;
53387c478bd9Sstevel@tonic-gate 		case RSMIPC_MSG_SUSPEND_DONE:
53397c478bd9Sstevel@tonic-gate 			rsm_suspend_complete(dest, 0);
53407c478bd9Sstevel@tonic-gate 			break;
53417c478bd9Sstevel@tonic-gate 		case RSMIPC_MSG_RESUME:
53427c478bd9Sstevel@tonic-gate 			importer_resume(dest);
53437c478bd9Sstevel@tonic-gate 			break;
53447c478bd9Sstevel@tonic-gate 		default:
53457c478bd9Sstevel@tonic-gate 			ASSERT(0);
53467c478bd9Sstevel@tonic-gate 		}
53477c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
53487c478bd9Sstevel@tonic-gate 		    "rsmipc_send done\n"));
53497c478bd9Sstevel@tonic-gate 		return (0);
53507c478bd9Sstevel@tonic-gate 	}
53517c478bd9Sstevel@tonic-gate 
53527c478bd9Sstevel@tonic-gate 	if (dest >= MAX_NODES) {
53537c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
53547c478bd9Sstevel@tonic-gate 		    "rsm: rsmipc_send bad node number %x\n", dest));
53557c478bd9Sstevel@tonic-gate 		return (RSMERR_REMOTE_NODE_UNREACHABLE);
53567c478bd9Sstevel@tonic-gate 	}
53577c478bd9Sstevel@tonic-gate 
53587c478bd9Sstevel@tonic-gate 	/*
53597c478bd9Sstevel@tonic-gate 	 * Oh boy! we are going remote.
53607c478bd9Sstevel@tonic-gate 	 */
53617c478bd9Sstevel@tonic-gate 
53627c478bd9Sstevel@tonic-gate 	/*
53637c478bd9Sstevel@tonic-gate 	 * identify if we need to have credits to send this message
53647c478bd9Sstevel@tonic-gate 	 * - only selected requests are flow controlled
53657c478bd9Sstevel@tonic-gate 	 */
53667c478bd9Sstevel@tonic-gate 	if (req != NULL) {
53677c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
53687c478bd9Sstevel@tonic-gate 		    "rsmipc_send:request type=%d\n",
53697c478bd9Sstevel@tonic-gate 		    req->rsmipc_hdr.rsmipc_type));
53707c478bd9Sstevel@tonic-gate 
53717c478bd9Sstevel@tonic-gate 		switch (req->rsmipc_hdr.rsmipc_type) {
53727c478bd9Sstevel@tonic-gate 		case RSMIPC_MSG_SEGCONNECT:
53737c478bd9Sstevel@tonic-gate 		case RSMIPC_MSG_DISCONNECT:
53747c478bd9Sstevel@tonic-gate 		case RSMIPC_MSG_IMPORTING:
53757c478bd9Sstevel@tonic-gate 		case RSMIPC_MSG_SUSPEND:
53767c478bd9Sstevel@tonic-gate 		case RSMIPC_MSG_SUSPEND_DONE:
53777c478bd9Sstevel@tonic-gate 		case RSMIPC_MSG_RESUME:
53787c478bd9Sstevel@tonic-gate 			credit_check = 1;
53797c478bd9Sstevel@tonic-gate 			break;
53807c478bd9Sstevel@tonic-gate 		default:
53817c478bd9Sstevel@tonic-gate 			credit_check = 0;
53827c478bd9Sstevel@tonic-gate 		}
53837c478bd9Sstevel@tonic-gate 	}
53847c478bd9Sstevel@tonic-gate 
53857c478bd9Sstevel@tonic-gate again:
53867c478bd9Sstevel@tonic-gate 	if (retry_cnt++ == min_retry_cnt) {
53877c478bd9Sstevel@tonic-gate 		/* backoff before further retries for 10ms */
53887c478bd9Sstevel@tonic-gate 		delay(drv_usectohz(10000));
53897c478bd9Sstevel@tonic-gate 		retry_cnt = 0; /* reset retry_cnt */
53907c478bd9Sstevel@tonic-gate 	}
53917c478bd9Sstevel@tonic-gate 	sendq_token = rsmka_get_sendq_token(dest, used_sendq_token);
53927c478bd9Sstevel@tonic-gate 	if (sendq_token == NULL) {
53937c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
53947c478bd9Sstevel@tonic-gate 		    "rsm: rsmipc_send no device to reach node %d\n", dest));
53957c478bd9Sstevel@tonic-gate 		return (RSMERR_REMOTE_NODE_UNREACHABLE);
53967c478bd9Sstevel@tonic-gate 	}
53977c478bd9Sstevel@tonic-gate 
53987c478bd9Sstevel@tonic-gate 	if ((sendq_token == used_sendq_token) &&
53997c478bd9Sstevel@tonic-gate 	    ((e == RSMERR_CONN_ABORTED) || (e == RSMERR_TIMEOUT) ||
54007c478bd9Sstevel@tonic-gate 	    (e == RSMERR_COMM_ERR_MAYBE_DELIVERED))) {
54017c478bd9Sstevel@tonic-gate 		rele_sendq_token(sendq_token);
54027c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG, "rsmipc_send done=%d\n", e));
54037c478bd9Sstevel@tonic-gate 		return (RSMERR_CONN_ABORTED);
54047c478bd9Sstevel@tonic-gate 	} else
54057c478bd9Sstevel@tonic-gate 		used_sendq_token = sendq_token;
54067c478bd9Sstevel@tonic-gate 
54077c478bd9Sstevel@tonic-gate /* lint -save -e413 */
54087c478bd9Sstevel@tonic-gate 	path = SQ_TOKEN_TO_PATH(sendq_token);
54097c478bd9Sstevel@tonic-gate 	adapter = path->local_adapter;
54107c478bd9Sstevel@tonic-gate /* lint -restore */
54117c478bd9Sstevel@tonic-gate 	ipc_handle = sendq_token->rsmpi_sendq_handle;
54127c478bd9Sstevel@tonic-gate 
54137c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
54147c478bd9Sstevel@tonic-gate 	    "rsmipc_send: path=%lx sendq_hdl=%lx\n", path, ipc_handle));
54157c478bd9Sstevel@tonic-gate 
54167c478bd9Sstevel@tonic-gate 	if (reply == NULL) {
54177c478bd9Sstevel@tonic-gate 		/* Send request without ack */
54187c478bd9Sstevel@tonic-gate 		/*
54197c478bd9Sstevel@tonic-gate 		 * Set the rsmipc_version number in the msghdr for KA
54207c478bd9Sstevel@tonic-gate 		 * communication versioning
54217c478bd9Sstevel@tonic-gate 		 */
54227c478bd9Sstevel@tonic-gate 		req->rsmipc_hdr.rsmipc_version = RSM_VERSION;
54237c478bd9Sstevel@tonic-gate 		req->rsmipc_hdr.rsmipc_src = my_nodeid;
54247c478bd9Sstevel@tonic-gate 		/*
54257c478bd9Sstevel@tonic-gate 		 * remote endpoints incn should match the value in our
54267c478bd9Sstevel@tonic-gate 		 * path's remote_incn field. No need to grab any lock
54277c478bd9Sstevel@tonic-gate 		 * since we have refcnted the path in rsmka_get_sendq_token
54287c478bd9Sstevel@tonic-gate 		 */
54297c478bd9Sstevel@tonic-gate 		req->rsmipc_hdr.rsmipc_incn = path->remote_incn;
54307c478bd9Sstevel@tonic-gate 
54317c478bd9Sstevel@tonic-gate 		is.is_data = (void *)req;
54327c478bd9Sstevel@tonic-gate 		is.is_size = sizeof (*req);
54337c478bd9Sstevel@tonic-gate 		is.is_flags = RSM_INTR_SEND_DELIVER | RSM_INTR_SEND_SLEEP;
54347c478bd9Sstevel@tonic-gate 		is.is_wait = 0;
54357c478bd9Sstevel@tonic-gate 
54367c478bd9Sstevel@tonic-gate 		if (credit_check) {
54377c478bd9Sstevel@tonic-gate 			mutex_enter(&path->mutex);
54387c478bd9Sstevel@tonic-gate 			/*
54397c478bd9Sstevel@tonic-gate 			 * wait till we recv credits or path goes down. If path
54407c478bd9Sstevel@tonic-gate 			 * goes down rsm_send will fail and we handle the error
54417c478bd9Sstevel@tonic-gate 			 * then
54427c478bd9Sstevel@tonic-gate 			 */
54437c478bd9Sstevel@tonic-gate 			while ((sendq_token->msgbuf_avail == 0) &&
54447c478bd9Sstevel@tonic-gate 			    (path->state == RSMKA_PATH_ACTIVE)) {
54457c478bd9Sstevel@tonic-gate 				e = cv_wait_sig(&sendq_token->sendq_cv,
54467c478bd9Sstevel@tonic-gate 				    &path->mutex);
54477c478bd9Sstevel@tonic-gate 				if (e == 0) {
54487c478bd9Sstevel@tonic-gate 					mutex_exit(&path->mutex);
54497c478bd9Sstevel@tonic-gate 					no_reply_cnt++;
54507c478bd9Sstevel@tonic-gate 					rele_sendq_token(sendq_token);
54517c478bd9Sstevel@tonic-gate 					DBG_PRINTF((category, RSM_DEBUG,
54527c478bd9Sstevel@tonic-gate 					    "rsmipc_send done: "
54537c478bd9Sstevel@tonic-gate 					    "cv_wait INTERRUPTED"));
54547c478bd9Sstevel@tonic-gate 					return (RSMERR_INTERRUPTED);
54557c478bd9Sstevel@tonic-gate 				}
54567c478bd9Sstevel@tonic-gate 			}
54577c478bd9Sstevel@tonic-gate 
54587c478bd9Sstevel@tonic-gate 			/*
54597c478bd9Sstevel@tonic-gate 			 * path is not active retry on another path.
54607c478bd9Sstevel@tonic-gate 			 */
54617c478bd9Sstevel@tonic-gate 			if (path->state != RSMKA_PATH_ACTIVE) {
54627c478bd9Sstevel@tonic-gate 				mutex_exit(&path->mutex);
54637c478bd9Sstevel@tonic-gate 				rele_sendq_token(sendq_token);
54647c478bd9Sstevel@tonic-gate 				e = RSMERR_CONN_ABORTED;
54657c478bd9Sstevel@tonic-gate 				DBG_PRINTF((category, RSM_ERR,
54667c478bd9Sstevel@tonic-gate 				    "rsm: rsmipc_send: path !ACTIVE"));
54677c478bd9Sstevel@tonic-gate 				goto again;
54687c478bd9Sstevel@tonic-gate 			}
54697c478bd9Sstevel@tonic-gate 
54707c478bd9Sstevel@tonic-gate 			ASSERT(sendq_token->msgbuf_avail > 0);
54717c478bd9Sstevel@tonic-gate 
54727c478bd9Sstevel@tonic-gate 			/*
54737c478bd9Sstevel@tonic-gate 			 * reserve a msgbuf
54747c478bd9Sstevel@tonic-gate 			 */
54757c478bd9Sstevel@tonic-gate 			sendq_token->msgbuf_avail--;
54767c478bd9Sstevel@tonic-gate 
54777c478bd9Sstevel@tonic-gate 			mutex_exit(&path->mutex);
54787c478bd9Sstevel@tonic-gate 
54797c478bd9Sstevel@tonic-gate 			e = adapter->rsmpi_ops->rsm_send(ipc_handle, &is,
54807c478bd9Sstevel@tonic-gate 			    NULL);
54817c478bd9Sstevel@tonic-gate 
54827c478bd9Sstevel@tonic-gate 			if (e != RSM_SUCCESS) {
54837c478bd9Sstevel@tonic-gate 				mutex_enter(&path->mutex);
54847c478bd9Sstevel@tonic-gate 				/*
54857c478bd9Sstevel@tonic-gate 				 * release the reserved msgbuf since
54867c478bd9Sstevel@tonic-gate 				 * the send failed
54877c478bd9Sstevel@tonic-gate 				 */
54887c478bd9Sstevel@tonic-gate 				sendq_token->msgbuf_avail++;
54897c478bd9Sstevel@tonic-gate 				cv_broadcast(&sendq_token->sendq_cv);
54907c478bd9Sstevel@tonic-gate 				mutex_exit(&path->mutex);
54917c478bd9Sstevel@tonic-gate 			}
54927c478bd9Sstevel@tonic-gate 		} else
54937c478bd9Sstevel@tonic-gate 			e = adapter->rsmpi_ops->rsm_send(ipc_handle, &is,
54947c478bd9Sstevel@tonic-gate 			    NULL);
54957c478bd9Sstevel@tonic-gate 
54967c478bd9Sstevel@tonic-gate 		no_reply_cnt++;
54977c478bd9Sstevel@tonic-gate 		rele_sendq_token(sendq_token);
54987c478bd9Sstevel@tonic-gate 		if (e != RSM_SUCCESS) {
54997c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_ERR,
55007c478bd9Sstevel@tonic-gate 			    "rsm: rsmipc_send no reply send"
55017c478bd9Sstevel@tonic-gate 			    " err = %d no reply count = %d\n",
55027c478bd9Sstevel@tonic-gate 			    e, no_reply_cnt));
55037c478bd9Sstevel@tonic-gate 			ASSERT(e != RSMERR_QUEUE_FENCE_UP &&
55047c478bd9Sstevel@tonic-gate 			    e != RSMERR_BAD_BARRIER_HNDL);
5505*1a5e258fSJosef 'Jeff' Sipek 			atomic_inc_64(&rsm_ipcsend_errcnt);
55067c478bd9Sstevel@tonic-gate 			goto again;
55077c478bd9Sstevel@tonic-gate 		} else {
55087c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
55097c478bd9Sstevel@tonic-gate 			    "rsmipc_send done\n"));
55107c478bd9Sstevel@tonic-gate 			return (e);
55117c478bd9Sstevel@tonic-gate 		}
55127c478bd9Sstevel@tonic-gate 
55137c478bd9Sstevel@tonic-gate 	}
55147c478bd9Sstevel@tonic-gate 
55157c478bd9Sstevel@tonic-gate 	if (req == NULL) {
55167c478bd9Sstevel@tonic-gate 		/* Send reply - No flow control is done for reply */
55177c478bd9Sstevel@tonic-gate 		/*
55187c478bd9Sstevel@tonic-gate 		 * Set the version in the msg header for KA communication
55197c478bd9Sstevel@tonic-gate 		 * versioning
55207c478bd9Sstevel@tonic-gate 		 */
55217c478bd9Sstevel@tonic-gate 		reply->rsmipc_hdr.rsmipc_version = RSM_VERSION;
55227c478bd9Sstevel@tonic-gate 		reply->rsmipc_hdr.rsmipc_src = my_nodeid;
55237c478bd9Sstevel@tonic-gate 		/* incn number is not used for reply msgs currently */
55247c478bd9Sstevel@tonic-gate 		reply->rsmipc_hdr.rsmipc_incn = path->remote_incn;
55257c478bd9Sstevel@tonic-gate 
55267c478bd9Sstevel@tonic-gate 		is.is_data = (void *)reply;
55277c478bd9Sstevel@tonic-gate 		is.is_size = sizeof (*reply);
55287c478bd9Sstevel@tonic-gate 		is.is_flags = RSM_INTR_SEND_DELIVER | RSM_INTR_SEND_SLEEP;
55297c478bd9Sstevel@tonic-gate 		is.is_wait = 0;
55307c478bd9Sstevel@tonic-gate 		e = adapter->rsmpi_ops->rsm_send(ipc_handle, &is, NULL);
55317c478bd9Sstevel@tonic-gate 		rele_sendq_token(sendq_token);
55327c478bd9Sstevel@tonic-gate 		if (e != RSM_SUCCESS) {
55337c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_ERR,
55347c478bd9Sstevel@tonic-gate 			    "rsm: rsmipc_send reply send"
55357c478bd9Sstevel@tonic-gate 			    " err = %d\n", e));
5536*1a5e258fSJosef 'Jeff' Sipek 			atomic_inc_64(&rsm_ipcsend_errcnt);
55377c478bd9Sstevel@tonic-gate 			goto again;
55387c478bd9Sstevel@tonic-gate 		} else {
55397c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
55407c478bd9Sstevel@tonic-gate 			    "rsmipc_send done\n"));
55417c478bd9Sstevel@tonic-gate 			return (e);
55427c478bd9Sstevel@tonic-gate 		}
55437c478bd9Sstevel@tonic-gate 	}
55447c478bd9Sstevel@tonic-gate 
55457c478bd9Sstevel@tonic-gate 	/* Reply needed */
55467c478bd9Sstevel@tonic-gate 	rslot = rsmipc_alloc(); /* allocate a new ipc slot */
55477c478bd9Sstevel@tonic-gate 
55487c478bd9Sstevel@tonic-gate 	mutex_enter(&rslot->rsmipc_lock);
55497c478bd9Sstevel@tonic-gate 
55507c478bd9Sstevel@tonic-gate 	rslot->rsmipc_data = (void *)reply;
55517c478bd9Sstevel@tonic-gate 	RSMIPC_SET(rslot, RSMIPC_PENDING);
55527c478bd9Sstevel@tonic-gate 
55537c478bd9Sstevel@tonic-gate 	while (RSMIPC_GET(rslot, RSMIPC_PENDING)) {
55547c478bd9Sstevel@tonic-gate 		/*
55557c478bd9Sstevel@tonic-gate 		 * Set the rsmipc_version number in the msghdr for KA
55567c478bd9Sstevel@tonic-gate 		 * communication versioning
55577c478bd9Sstevel@tonic-gate 		 */
55587c478bd9Sstevel@tonic-gate 		req->rsmipc_hdr.rsmipc_version = RSM_VERSION;
55597c478bd9Sstevel@tonic-gate 		req->rsmipc_hdr.rsmipc_src = my_nodeid;
55607c478bd9Sstevel@tonic-gate 		req->rsmipc_hdr.rsmipc_cookie = rslot->rsmipc_cookie;
55617c478bd9Sstevel@tonic-gate 		/*
55627c478bd9Sstevel@tonic-gate 		 * remote endpoints incn should match the value in our
55637c478bd9Sstevel@tonic-gate 		 * path's remote_incn field. No need to grab any lock
55647c478bd9Sstevel@tonic-gate 		 * since we have refcnted the path in rsmka_get_sendq_token
55657c478bd9Sstevel@tonic-gate 		 */
55667c478bd9Sstevel@tonic-gate 		req->rsmipc_hdr.rsmipc_incn = path->remote_incn;
55677c478bd9Sstevel@tonic-gate 
55687c478bd9Sstevel@tonic-gate 		is.is_data = (void *)req;
55697c478bd9Sstevel@tonic-gate 		is.is_size = sizeof (*req);
55707c478bd9Sstevel@tonic-gate 		is.is_flags = RSM_INTR_SEND_DELIVER | RSM_INTR_SEND_SLEEP;
55717c478bd9Sstevel@tonic-gate 		is.is_wait = 0;
55727c478bd9Sstevel@tonic-gate 		if (credit_check) {
55737c478bd9Sstevel@tonic-gate 
55747c478bd9Sstevel@tonic-gate 			mutex_enter(&path->mutex);
55757c478bd9Sstevel@tonic-gate 			/*
55767c478bd9Sstevel@tonic-gate 			 * wait till we recv credits or path goes down. If path
55777c478bd9Sstevel@tonic-gate 			 * goes down rsm_send will fail and we handle the error
55787c478bd9Sstevel@tonic-gate 			 * then.
55797c478bd9Sstevel@tonic-gate 			 */
55807c478bd9Sstevel@tonic-gate 			while ((sendq_token->msgbuf_avail == 0) &&
55817c478bd9Sstevel@tonic-gate 			    (path->state == RSMKA_PATH_ACTIVE)) {
55827c478bd9Sstevel@tonic-gate 				e = cv_wait_sig(&sendq_token->sendq_cv,
55837c478bd9Sstevel@tonic-gate 				    &path->mutex);
55847c478bd9Sstevel@tonic-gate 				if (e == 0) {
55857c478bd9Sstevel@tonic-gate 					mutex_exit(&path->mutex);
55867c478bd9Sstevel@tonic-gate 					RSMIPC_CLEAR(rslot, RSMIPC_PENDING);
55877c478bd9Sstevel@tonic-gate 					rsmipc_free(rslot);
55887c478bd9Sstevel@tonic-gate 					rele_sendq_token(sendq_token);
55897c478bd9Sstevel@tonic-gate 					DBG_PRINTF((category, RSM_DEBUG,
55907c478bd9Sstevel@tonic-gate 					    "rsmipc_send done: "
55917c478bd9Sstevel@tonic-gate 					    "cv_wait INTERRUPTED"));
55927c478bd9Sstevel@tonic-gate 					return (RSMERR_INTERRUPTED);
55937c478bd9Sstevel@tonic-gate 				}
55947c478bd9Sstevel@tonic-gate 			}
55957c478bd9Sstevel@tonic-gate 
55967c478bd9Sstevel@tonic-gate 			/*
55977c478bd9Sstevel@tonic-gate 			 * path is not active retry on another path.
55987c478bd9Sstevel@tonic-gate 			 */
55997c478bd9Sstevel@tonic-gate 			if (path->state != RSMKA_PATH_ACTIVE) {
56007c478bd9Sstevel@tonic-gate 				mutex_exit(&path->mutex);
56017c478bd9Sstevel@tonic-gate 				RSMIPC_CLEAR(rslot, RSMIPC_PENDING);
56027c478bd9Sstevel@tonic-gate 				rsmipc_free(rslot);
56037c478bd9Sstevel@tonic-gate 				rele_sendq_token(sendq_token);
56047c478bd9Sstevel@tonic-gate 				e = RSMERR_CONN_ABORTED;
56057c478bd9Sstevel@tonic-gate 				DBG_PRINTF((category, RSM_ERR,
56067c478bd9Sstevel@tonic-gate 				    "rsm: rsmipc_send: path !ACTIVE"));
56077c478bd9Sstevel@tonic-gate 				goto again;
56087c478bd9Sstevel@tonic-gate 			}
56097c478bd9Sstevel@tonic-gate 
56107c478bd9Sstevel@tonic-gate 			ASSERT(sendq_token->msgbuf_avail > 0);
56117c478bd9Sstevel@tonic-gate 
56127c478bd9Sstevel@tonic-gate 			/*
56137c478bd9Sstevel@tonic-gate 			 * reserve a msgbuf
56147c478bd9Sstevel@tonic-gate 			 */
56157c478bd9Sstevel@tonic-gate 			sendq_token->msgbuf_avail--;
56167c478bd9Sstevel@tonic-gate 
56177c478bd9Sstevel@tonic-gate 			mutex_exit(&path->mutex);
56187c478bd9Sstevel@tonic-gate 
56197c478bd9Sstevel@tonic-gate 			e = adapter->rsmpi_ops->rsm_send(ipc_handle, &is,
56207c478bd9Sstevel@tonic-gate 			    NULL);
56217c478bd9Sstevel@tonic-gate 
56227c478bd9Sstevel@tonic-gate 			if (e != RSM_SUCCESS) {
56237c478bd9Sstevel@tonic-gate 				mutex_enter(&path->mutex);
56247c478bd9Sstevel@tonic-gate 				/*
56257c478bd9Sstevel@tonic-gate 				 * release the reserved msgbuf since
56267c478bd9Sstevel@tonic-gate 				 * the send failed
56277c478bd9Sstevel@tonic-gate 				 */
56287c478bd9Sstevel@tonic-gate 				sendq_token->msgbuf_avail++;
56297c478bd9Sstevel@tonic-gate 				cv_broadcast(&sendq_token->sendq_cv);
56307c478bd9Sstevel@tonic-gate 				mutex_exit(&path->mutex);
56317c478bd9Sstevel@tonic-gate 			}
56327c478bd9Sstevel@tonic-gate 		} else
56337c478bd9Sstevel@tonic-gate 			e = adapter->rsmpi_ops->rsm_send(ipc_handle, &is,
56347c478bd9Sstevel@tonic-gate 			    NULL);
56357c478bd9Sstevel@tonic-gate 
56367c478bd9Sstevel@tonic-gate 		if (e != RSM_SUCCESS) {
56377c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_ERR,
56387c478bd9Sstevel@tonic-gate 			    "rsm: rsmipc_send rsmpi send err = %d\n", e));
56397c478bd9Sstevel@tonic-gate 			RSMIPC_CLEAR(rslot, RSMIPC_PENDING);
56407c478bd9Sstevel@tonic-gate 			rsmipc_free(rslot);
56417c478bd9Sstevel@tonic-gate 			rele_sendq_token(sendq_token);
5642*1a5e258fSJosef 'Jeff' Sipek 			atomic_inc_64(&rsm_ipcsend_errcnt);
56437c478bd9Sstevel@tonic-gate 			goto again;
56447c478bd9Sstevel@tonic-gate 		}
56457c478bd9Sstevel@tonic-gate 
56467c478bd9Sstevel@tonic-gate 		/* wait for a reply signal, a SIGINT, or 5 sec. timeout */
5647d3d50737SRafael Vanoni 		e = cv_reltimedwait_sig(&rslot->rsmipc_cv, &rslot->rsmipc_lock,
5648d3d50737SRafael Vanoni 		    drv_usectohz(5000000), TR_CLOCK_TICK);
56497c478bd9Sstevel@tonic-gate 		if (e < 0) {
56507c478bd9Sstevel@tonic-gate 			/* timed out - retry */
56517c478bd9Sstevel@tonic-gate 			e = RSMERR_TIMEOUT;
56527c478bd9Sstevel@tonic-gate 		} else if (e == 0) {
56537c478bd9Sstevel@tonic-gate 			/* signalled - return error */
56547c478bd9Sstevel@tonic-gate 			e = RSMERR_INTERRUPTED;
56557c478bd9Sstevel@tonic-gate 			break;
56567c478bd9Sstevel@tonic-gate 		} else {
56577c478bd9Sstevel@tonic-gate 			e = RSM_SUCCESS;
56587c478bd9Sstevel@tonic-gate 		}
56597c478bd9Sstevel@tonic-gate 	}
56607c478bd9Sstevel@tonic-gate 
56617c478bd9Sstevel@tonic-gate 	RSMIPC_CLEAR(rslot, RSMIPC_PENDING);
56627c478bd9Sstevel@tonic-gate 	rsmipc_free(rslot);
56637c478bd9Sstevel@tonic-gate 	rele_sendq_token(sendq_token);
56647c478bd9Sstevel@tonic-gate 
56657c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmipc_send done=%d\n", e));
56667c478bd9Sstevel@tonic-gate 	return (e);
56677c478bd9Sstevel@tonic-gate }
56687c478bd9Sstevel@tonic-gate 
56697c478bd9Sstevel@tonic-gate static int
rsm_send_notimporting(rsm_node_id_t dest,rsm_memseg_id_t segid,void * cookie)56707c478bd9Sstevel@tonic-gate rsm_send_notimporting(rsm_node_id_t dest, rsm_memseg_id_t segid,  void *cookie)
56717c478bd9Sstevel@tonic-gate {
56727c478bd9Sstevel@tonic-gate 	rsmipc_request_t request;
56737c478bd9Sstevel@tonic-gate 
56747c478bd9Sstevel@tonic-gate 	/*
56757c478bd9Sstevel@tonic-gate 	 *  inform the exporter to delete this importer
56767c478bd9Sstevel@tonic-gate 	 */
56777c478bd9Sstevel@tonic-gate 	request.rsmipc_hdr.rsmipc_type = RSMIPC_MSG_NOTIMPORTING;
56787c478bd9Sstevel@tonic-gate 	request.rsmipc_key = segid;
56797c478bd9Sstevel@tonic-gate 	request.rsmipc_segment_cookie = cookie;
56807c478bd9Sstevel@tonic-gate 	return (rsmipc_send(dest, &request, RSM_NO_REPLY));
56817c478bd9Sstevel@tonic-gate }
56827c478bd9Sstevel@tonic-gate 
56837c478bd9Sstevel@tonic-gate static void
rsm_send_republish(rsm_memseg_id_t segid,rsmapi_access_entry_t * acl,int acl_len,rsm_permission_t default_permission)56847c478bd9Sstevel@tonic-gate rsm_send_republish(rsm_memseg_id_t segid, rsmapi_access_entry_t	*acl,
56857c478bd9Sstevel@tonic-gate     int acl_len, rsm_permission_t default_permission)
56867c478bd9Sstevel@tonic-gate {
56877c478bd9Sstevel@tonic-gate 	int			i;
56887c478bd9Sstevel@tonic-gate 	importing_token_t	*token;
56897c478bd9Sstevel@tonic-gate 	rsmipc_request_t	request;
56907c478bd9Sstevel@tonic-gate 	republish_token_t	*republish_list = NULL;
56917c478bd9Sstevel@tonic-gate 	republish_token_t	*rp;
56927c478bd9Sstevel@tonic-gate 	rsm_permission_t	permission;
56937c478bd9Sstevel@tonic-gate 	int			index;
56947c478bd9Sstevel@tonic-gate 
56957c478bd9Sstevel@tonic-gate 	/*
56967c478bd9Sstevel@tonic-gate 	 * send the new access mode to all the nodes that have imported
56977c478bd9Sstevel@tonic-gate 	 * this segment.
56987c478bd9Sstevel@tonic-gate 	 * If the new acl does not have a node that was present in
56997c478bd9Sstevel@tonic-gate 	 * the old acl a access permission of 0 is sent.
57007c478bd9Sstevel@tonic-gate 	 */
57017c478bd9Sstevel@tonic-gate 
57027c478bd9Sstevel@tonic-gate 	index = rsmhash(segid);
57037c478bd9Sstevel@tonic-gate 
57047c478bd9Sstevel@tonic-gate 	/*
57057c478bd9Sstevel@tonic-gate 	 * create a list of node/permissions to send the republish message
57067c478bd9Sstevel@tonic-gate 	 */
57077c478bd9Sstevel@tonic-gate 	mutex_enter(&importer_list.lock);
57087c478bd9Sstevel@tonic-gate 
57097c478bd9Sstevel@tonic-gate 	token = importer_list.bucket[index];
57107c478bd9Sstevel@tonic-gate 	while (token != NULL) {
57117c478bd9Sstevel@tonic-gate 		if (segid == token->key) {
57127c478bd9Sstevel@tonic-gate 			permission = default_permission;
57137c478bd9Sstevel@tonic-gate 
57147c478bd9Sstevel@tonic-gate 			for (i = 0; i < acl_len; i++) {
57157c478bd9Sstevel@tonic-gate 				if (token->importing_node == acl[i].ae_node) {
57167c478bd9Sstevel@tonic-gate 					permission = acl[i].ae_permission;
57177c478bd9Sstevel@tonic-gate 					break;
57187c478bd9Sstevel@tonic-gate 				}
57197c478bd9Sstevel@tonic-gate 			}
57207c478bd9Sstevel@tonic-gate 			rp = kmem_zalloc(sizeof (republish_token_t), KM_SLEEP);
57217c478bd9Sstevel@tonic-gate 
57227c478bd9Sstevel@tonic-gate 			rp->key = segid;
57237c478bd9Sstevel@tonic-gate 			rp->importing_node = token->importing_node;
57247c478bd9Sstevel@tonic-gate 			rp->permission = permission;
57257c478bd9Sstevel@tonic-gate 			rp->next = republish_list;
57267c478bd9Sstevel@tonic-gate 			republish_list = rp;
57277c478bd9Sstevel@tonic-gate 		}
57287c478bd9Sstevel@tonic-gate 		token = token->next;
57297c478bd9Sstevel@tonic-gate 	}
57307c478bd9Sstevel@tonic-gate 
57317c478bd9Sstevel@tonic-gate 	mutex_exit(&importer_list.lock);
57327c478bd9Sstevel@tonic-gate 
57337c478bd9Sstevel@tonic-gate 	request.rsmipc_hdr.rsmipc_type = RSMIPC_MSG_REPUBLISH;
57347c478bd9Sstevel@tonic-gate 	request.rsmipc_key = segid;
57357c478bd9Sstevel@tonic-gate 
57367c478bd9Sstevel@tonic-gate 	while (republish_list != NULL) {
57377c478bd9Sstevel@tonic-gate 		request.rsmipc_perm = republish_list->permission;
57387c478bd9Sstevel@tonic-gate 		(void) rsmipc_send(republish_list->importing_node,
57397c478bd9Sstevel@tonic-gate 		    &request, RSM_NO_REPLY);
57407c478bd9Sstevel@tonic-gate 		rp = republish_list;
57417c478bd9Sstevel@tonic-gate 		republish_list = republish_list->next;
57427c478bd9Sstevel@tonic-gate 		kmem_free(rp, sizeof (republish_token_t));
57437c478bd9Sstevel@tonic-gate 	}
57447c478bd9Sstevel@tonic-gate }
57457c478bd9Sstevel@tonic-gate 
57467c478bd9Sstevel@tonic-gate static void
rsm_send_suspend()57477c478bd9Sstevel@tonic-gate rsm_send_suspend()
57487c478bd9Sstevel@tonic-gate {
57497c478bd9Sstevel@tonic-gate 	int			i, e;
57507c478bd9Sstevel@tonic-gate 	rsmipc_request_t 	request;
57517c478bd9Sstevel@tonic-gate 	list_element_t		*tokp;
57527c478bd9Sstevel@tonic-gate 	list_element_t		*head = NULL;
57537c478bd9Sstevel@tonic-gate 	importing_token_t	*token;
57547c478bd9Sstevel@tonic-gate 	DBG_PRINTF((RSM_KERNEL_AGENT | RSM_EXPORT, RSM_DEBUG_VERBOSE,
57557c478bd9Sstevel@tonic-gate 	    "rsm_send_suspend enter\n"));
57567c478bd9Sstevel@tonic-gate 
57577c478bd9Sstevel@tonic-gate 	/*
57587c478bd9Sstevel@tonic-gate 	 * create a list of node to send the suspend message
57597c478bd9Sstevel@tonic-gate 	 *
57607c478bd9Sstevel@tonic-gate 	 * Currently the whole importer list is scanned and we obtain
57617c478bd9Sstevel@tonic-gate 	 * all the nodes - this basically gets all nodes that at least
57627c478bd9Sstevel@tonic-gate 	 * import one segment from the local node.
57637c478bd9Sstevel@tonic-gate 	 *
57647c478bd9Sstevel@tonic-gate 	 * no need to grab the rsm_suspend_list lock here since we are
57657c478bd9Sstevel@tonic-gate 	 * single threaded when suspend is called.
57667c478bd9Sstevel@tonic-gate 	 */
57677c478bd9Sstevel@tonic-gate 
57687c478bd9Sstevel@tonic-gate 	mutex_enter(&importer_list.lock);
57697c478bd9Sstevel@tonic-gate 	for (i = 0; i < rsm_hash_size; i++) {
57707c478bd9Sstevel@tonic-gate 
57717c478bd9Sstevel@tonic-gate 		token = importer_list.bucket[i];
57727c478bd9Sstevel@tonic-gate 
57737c478bd9Sstevel@tonic-gate 		while (token != NULL) {
57747c478bd9Sstevel@tonic-gate 
57757c478bd9Sstevel@tonic-gate 			tokp = head;
57767c478bd9Sstevel@tonic-gate 
57777c478bd9Sstevel@tonic-gate 			/*
57787c478bd9Sstevel@tonic-gate 			 * make sure that the token's node
57797c478bd9Sstevel@tonic-gate 			 * is not already on the suspend list
57807c478bd9Sstevel@tonic-gate 			 */
57817c478bd9Sstevel@tonic-gate 			while (tokp != NULL) {
57827c478bd9Sstevel@tonic-gate 				if (tokp->nodeid == token->importing_node) {
57837c478bd9Sstevel@tonic-gate 					break;
57847c478bd9Sstevel@tonic-gate 				}
57857c478bd9Sstevel@tonic-gate 				tokp = tokp->next;
57867c478bd9Sstevel@tonic-gate 			}
57877c478bd9Sstevel@tonic-gate 
57887c478bd9Sstevel@tonic-gate 			if (tokp == NULL) { /* not in suspend list */
57897c478bd9Sstevel@tonic-gate 				tokp = kmem_zalloc(sizeof (list_element_t),
57907c478bd9Sstevel@tonic-gate 				    KM_SLEEP);
57917c478bd9Sstevel@tonic-gate 				tokp->nodeid = token->importing_node;
57927c478bd9Sstevel@tonic-gate 				tokp->next = head;
57937c478bd9Sstevel@tonic-gate 				head = tokp;
57947c478bd9Sstevel@tonic-gate 			}
57957c478bd9Sstevel@tonic-gate 
57967c478bd9Sstevel@tonic-gate 			token = token->next;
57977c478bd9Sstevel@tonic-gate 		}
57987c478bd9Sstevel@tonic-gate 	}
57997c478bd9Sstevel@tonic-gate 	mutex_exit(&importer_list.lock);
58007c478bd9Sstevel@tonic-gate 
58017c478bd9Sstevel@tonic-gate 	if (head == NULL) { /* no importers so go ahead and quiesce segments */
58027c478bd9Sstevel@tonic-gate 		exporter_quiesce();
58037c478bd9Sstevel@tonic-gate 		return;
58047c478bd9Sstevel@tonic-gate 	}
58057c478bd9Sstevel@tonic-gate 
58067c478bd9Sstevel@tonic-gate 	mutex_enter(&rsm_suspend_list.list_lock);
58077c478bd9Sstevel@tonic-gate 	ASSERT(rsm_suspend_list.list_head == NULL);
58087c478bd9Sstevel@tonic-gate 	/*
58097c478bd9Sstevel@tonic-gate 	 * update the suspend list righaway so that if a node dies the
58107c478bd9Sstevel@tonic-gate 	 * pathmanager can set the NODE dead flag
58117c478bd9Sstevel@tonic-gate 	 */
58127c478bd9Sstevel@tonic-gate 	rsm_suspend_list.list_head = head;
58137c478bd9Sstevel@tonic-gate 	mutex_exit(&rsm_suspend_list.list_lock);
58147c478bd9Sstevel@tonic-gate 
58157c478bd9Sstevel@tonic-gate 	tokp = head;
58167c478bd9Sstevel@tonic-gate 
58177c478bd9Sstevel@tonic-gate 	while (tokp != NULL) {
58187c478bd9Sstevel@tonic-gate 		request.rsmipc_hdr.rsmipc_type = RSMIPC_MSG_SUSPEND;
58197c478bd9Sstevel@tonic-gate 		e = rsmipc_send(tokp->nodeid, &request, RSM_NO_REPLY);
58207c478bd9Sstevel@tonic-gate 		/*
58217c478bd9Sstevel@tonic-gate 		 * Error in rsmipc_send currently happens due to inaccessibility
58227c478bd9Sstevel@tonic-gate 		 * of the remote node.
58237c478bd9Sstevel@tonic-gate 		 */
58247c478bd9Sstevel@tonic-gate 		if (e == RSM_SUCCESS) { /* send failed - don't wait for ack */
58257c478bd9Sstevel@tonic-gate 			tokp->flags |= RSM_SUSPEND_ACKPENDING;
58267c478bd9Sstevel@tonic-gate 		}
58277c478bd9Sstevel@tonic-gate 
58287c478bd9Sstevel@tonic-gate 		tokp = tokp->next;
58297c478bd9Sstevel@tonic-gate 	}
58307c478bd9Sstevel@tonic-gate 
58317c478bd9Sstevel@tonic-gate 	DBG_PRINTF((RSM_KERNEL_AGENT | RSM_EXPORT, RSM_DEBUG_VERBOSE,
58327c478bd9Sstevel@tonic-gate 	    "rsm_send_suspend done\n"));
58337c478bd9Sstevel@tonic-gate 
58347c478bd9Sstevel@tonic-gate }
58357c478bd9Sstevel@tonic-gate 
58367c478bd9Sstevel@tonic-gate static void
rsm_send_resume()58377c478bd9Sstevel@tonic-gate rsm_send_resume()
58387c478bd9Sstevel@tonic-gate {
58397c478bd9Sstevel@tonic-gate 	rsmipc_request_t 	request;
58407c478bd9Sstevel@tonic-gate 	list_element_t		*elem, *head;
58417c478bd9Sstevel@tonic-gate 
58427c478bd9Sstevel@tonic-gate 	/*
58437c478bd9Sstevel@tonic-gate 	 * save the suspend list so that we know where to send
58447c478bd9Sstevel@tonic-gate 	 * the resume messages and make the suspend list head
58457c478bd9Sstevel@tonic-gate 	 * NULL.
58467c478bd9Sstevel@tonic-gate 	 */
58477c478bd9Sstevel@tonic-gate 	mutex_enter(&rsm_suspend_list.list_lock);
58487c478bd9Sstevel@tonic-gate 	head = rsm_suspend_list.list_head;
58497c478bd9Sstevel@tonic-gate 	rsm_suspend_list.list_head = NULL;
58507c478bd9Sstevel@tonic-gate 	mutex_exit(&rsm_suspend_list.list_lock);
58517c478bd9Sstevel@tonic-gate 
58527c478bd9Sstevel@tonic-gate 	while (head != NULL) {
58537c478bd9Sstevel@tonic-gate 		elem = head;
58547c478bd9Sstevel@tonic-gate 		head = head->next;
58557c478bd9Sstevel@tonic-gate 
58567c478bd9Sstevel@tonic-gate 		request.rsmipc_hdr.rsmipc_type = RSMIPC_MSG_RESUME;
58577c478bd9Sstevel@tonic-gate 
58587c478bd9Sstevel@tonic-gate 		(void) rsmipc_send(elem->nodeid, &request, RSM_NO_REPLY);
58597c478bd9Sstevel@tonic-gate 
58607c478bd9Sstevel@tonic-gate 		kmem_free((void *)elem, sizeof (list_element_t));
58617c478bd9Sstevel@tonic-gate 
58627c478bd9Sstevel@tonic-gate 	}
58637c478bd9Sstevel@tonic-gate 
58647c478bd9Sstevel@tonic-gate }
58657c478bd9Sstevel@tonic-gate 
58667c478bd9Sstevel@tonic-gate /*
58677c478bd9Sstevel@tonic-gate  * This function takes path and sends a message using the sendq
58687c478bd9Sstevel@tonic-gate  * corresponding to it. The RSMIPC_MSG_SQREADY, RSMIPC_MSG_SQREADY_ACK
58697c478bd9Sstevel@tonic-gate  * and RSMIPC_MSG_CREDIT are sent using this function.
58707c478bd9Sstevel@tonic-gate  */
58717c478bd9Sstevel@tonic-gate int
rsmipc_send_controlmsg(path_t * path,int msgtype)58727c478bd9Sstevel@tonic-gate rsmipc_send_controlmsg(path_t *path, int msgtype)
58737c478bd9Sstevel@tonic-gate {
58747c478bd9Sstevel@tonic-gate 	int			e;
58757c478bd9Sstevel@tonic-gate 	int			retry_cnt = 0;
58767c478bd9Sstevel@tonic-gate 	int			min_retry_cnt = 10;
58777c478bd9Sstevel@tonic-gate 	adapter_t		*adapter;
58787c478bd9Sstevel@tonic-gate 	rsm_send_t		is;
58797c478bd9Sstevel@tonic-gate 	rsm_send_q_handle_t	ipc_handle;
58807c478bd9Sstevel@tonic-gate 	rsmipc_controlmsg_t	msg;
58817c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_FLOWCONTROL);
58827c478bd9Sstevel@tonic-gate 
58837c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
58847c478bd9Sstevel@tonic-gate 	    "rsmipc_send_controlmsg enter\n"));
58857c478bd9Sstevel@tonic-gate 
58867c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&path->mutex));
58877c478bd9Sstevel@tonic-gate 
58887c478bd9Sstevel@tonic-gate 	adapter = path->local_adapter;
58897c478bd9Sstevel@tonic-gate 
58907c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG, "rsmipc_send_controlmsg:path=%lx "
58917c478bd9Sstevel@tonic-gate 	    "msgtype=%d %lx:%llx->%lx:%llx procmsg=%d\n", path, msgtype,
58927c478bd9Sstevel@tonic-gate 	    my_nodeid, adapter->hwaddr, path->remote_node,
58937c478bd9Sstevel@tonic-gate 	    path->remote_hwaddr, path->procmsg_cnt));
58947c478bd9Sstevel@tonic-gate 
58957c478bd9Sstevel@tonic-gate 	if (path->state != RSMKA_PATH_ACTIVE) {
58967c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
58977c478bd9Sstevel@tonic-gate 		    "rsmipc_send_controlmsg done: ! RSMKA_PATH_ACTIVE"));
58987c478bd9Sstevel@tonic-gate 		return (1);
58997c478bd9Sstevel@tonic-gate 	}
59007c478bd9Sstevel@tonic-gate 
59017c478bd9Sstevel@tonic-gate 	ipc_handle = path->sendq_token.rsmpi_sendq_handle;
59027c478bd9Sstevel@tonic-gate 
59037c478bd9Sstevel@tonic-gate 	msg.rsmipc_hdr.rsmipc_version = RSM_VERSION;
59047c478bd9Sstevel@tonic-gate 	msg.rsmipc_hdr.rsmipc_src = my_nodeid;
59057c478bd9Sstevel@tonic-gate 	msg.rsmipc_hdr.rsmipc_type = msgtype;
59067c478bd9Sstevel@tonic-gate 	msg.rsmipc_hdr.rsmipc_incn = path->remote_incn;
59077c478bd9Sstevel@tonic-gate 
59087c478bd9Sstevel@tonic-gate 	if (msgtype == RSMIPC_MSG_CREDIT)
59097c478bd9Sstevel@tonic-gate 		msg.rsmipc_credits = path->procmsg_cnt;
59107c478bd9Sstevel@tonic-gate 
59117c478bd9Sstevel@tonic-gate 	msg.rsmipc_local_incn = path->local_incn;
59127c478bd9Sstevel@tonic-gate 
59137c478bd9Sstevel@tonic-gate 	msg.rsmipc_adapter_hwaddr = adapter->hwaddr;
59147c478bd9Sstevel@tonic-gate 	/* incr the sendq, path refcnt */
59157c478bd9Sstevel@tonic-gate 	PATH_HOLD_NOLOCK(path);
59167c478bd9Sstevel@tonic-gate 	SENDQ_TOKEN_HOLD(path);
59177c478bd9Sstevel@tonic-gate 
59187c478bd9Sstevel@tonic-gate 	do {
59197c478bd9Sstevel@tonic-gate 		/* drop the path lock before doing the rsm_send */
59207c478bd9Sstevel@tonic-gate 		mutex_exit(&path->mutex);
59217c478bd9Sstevel@tonic-gate 
59227c478bd9Sstevel@tonic-gate 		is.is_data = (void *)&msg;
59237c478bd9Sstevel@tonic-gate 		is.is_size = sizeof (msg);
59247c478bd9Sstevel@tonic-gate 		is.is_flags = RSM_INTR_SEND_DELIVER | RSM_INTR_SEND_SLEEP;
59257c478bd9Sstevel@tonic-gate 		is.is_wait = 0;
59267c478bd9Sstevel@tonic-gate 
59277c478bd9Sstevel@tonic-gate 		e = adapter->rsmpi_ops->rsm_send(ipc_handle, &is, NULL);
59287c478bd9Sstevel@tonic-gate 
59297c478bd9Sstevel@tonic-gate 		ASSERT(e != RSMERR_QUEUE_FENCE_UP &&
59307c478bd9Sstevel@tonic-gate 		    e != RSMERR_BAD_BARRIER_HNDL);
59317c478bd9Sstevel@tonic-gate 
59327c478bd9Sstevel@tonic-gate 		mutex_enter(&path->mutex);
59337c478bd9Sstevel@tonic-gate 
59347c478bd9Sstevel@tonic-gate 		if (e == RSM_SUCCESS) {
59357c478bd9Sstevel@tonic-gate 			break;
59367c478bd9Sstevel@tonic-gate 		}
59377c478bd9Sstevel@tonic-gate 		/* error counter for statistics */
5938*1a5e258fSJosef 'Jeff' Sipek 		atomic_inc_64(&rsm_ctrlmsg_errcnt);
59397c478bd9Sstevel@tonic-gate 
59407c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
59417c478bd9Sstevel@tonic-gate 		    "rsmipc_send_controlmsg:rsm_send error=%d", e));
59427c478bd9Sstevel@tonic-gate 
59437c478bd9Sstevel@tonic-gate 		if (++retry_cnt == min_retry_cnt) { /* backoff before retry */
5944d3d50737SRafael Vanoni 			(void) cv_reltimedwait(&path->sendq_token.sendq_cv,
5945d3d50737SRafael Vanoni 			    &path->mutex, drv_usectohz(10000), TR_CLOCK_TICK);
59467c478bd9Sstevel@tonic-gate 			retry_cnt = 0;
59477c478bd9Sstevel@tonic-gate 		}
59487c478bd9Sstevel@tonic-gate 	} while (path->state == RSMKA_PATH_ACTIVE);
59497c478bd9Sstevel@tonic-gate 
59507c478bd9Sstevel@tonic-gate 	/* decrement the sendq,path refcnt that we incr before rsm_send */
59517c478bd9Sstevel@tonic-gate 	SENDQ_TOKEN_RELE(path);
59527c478bd9Sstevel@tonic-gate 	PATH_RELE_NOLOCK(path);
59537c478bd9Sstevel@tonic-gate 
59547c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
59557c478bd9Sstevel@tonic-gate 	    "rsmipc_send_controlmsg done=%d", e));
59567c478bd9Sstevel@tonic-gate 	return (e);
59577c478bd9Sstevel@tonic-gate }
59587c478bd9Sstevel@tonic-gate 
59597c478bd9Sstevel@tonic-gate /*
59607c478bd9Sstevel@tonic-gate  * Called from rsm_force_unload and path_importer_disconnect. The memory
59617c478bd9Sstevel@tonic-gate  * mapping for the imported segment is removed and the segment is
59627c478bd9Sstevel@tonic-gate  * disconnected at the interconnect layer if disconnect_flag is TRUE.
59637c478bd9Sstevel@tonic-gate  * rsm_force_unload will get disconnect_flag TRUE from rsm_intr_callback
59647c478bd9Sstevel@tonic-gate  * and FALSE from rsm_rebind.
59657c478bd9Sstevel@tonic-gate  *
59667c478bd9Sstevel@tonic-gate  * When subsequent accesses cause page faulting, the dummy page is mapped
59677c478bd9Sstevel@tonic-gate  * to resolve the fault, and the mapping generation number is incremented
59687c478bd9Sstevel@tonic-gate  * so that the application can be notified on a close barrier operation.
59697c478bd9Sstevel@tonic-gate  *
59707c478bd9Sstevel@tonic-gate  * It is important to note that the caller of rsmseg_unload is responsible for
59717c478bd9Sstevel@tonic-gate  * acquiring the segment lock before making a call to rsmseg_unload. This is
59727c478bd9Sstevel@tonic-gate  * required to make the caller and rsmseg_unload thread safe. The segment lock
59737c478bd9Sstevel@tonic-gate  * will be released by the rsmseg_unload function.
59747c478bd9Sstevel@tonic-gate  */
59757c478bd9Sstevel@tonic-gate void
rsmseg_unload(rsmseg_t * im_seg)59767c478bd9Sstevel@tonic-gate rsmseg_unload(rsmseg_t *im_seg)
59777c478bd9Sstevel@tonic-gate {
59787c478bd9Sstevel@tonic-gate 	rsmcookie_t		*hdl;
59797c478bd9Sstevel@tonic-gate 	void			*shared_cookie;
59807c478bd9Sstevel@tonic-gate 	rsmipc_request_t	request;
59817c478bd9Sstevel@tonic-gate 	uint_t			maxprot;
59827c478bd9Sstevel@tonic-gate 
59837c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category,
59847c478bd9Sstevel@tonic-gate 	    RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_INTR_CALLBACK);
59857c478bd9Sstevel@tonic-gate 
59867c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmseg_unload enter\n"));
59877c478bd9Sstevel@tonic-gate 
59887c478bd9Sstevel@tonic-gate 	ASSERT(im_seg->s_hdr.rsmrc_type == RSM_RESOURCE_IMPORT_SEGMENT);
59897c478bd9Sstevel@tonic-gate 
59907c478bd9Sstevel@tonic-gate 	/* wait until segment leaves the mapping state */
59917c478bd9Sstevel@tonic-gate 	while (im_seg->s_state == RSM_STATE_MAPPING)
59927c478bd9Sstevel@tonic-gate 		cv_wait(&im_seg->s_cv, &im_seg->s_lock);
59937c478bd9Sstevel@tonic-gate 	/*
59947c478bd9Sstevel@tonic-gate 	 * An unload is only necessary if the segment is connected. However,
59957c478bd9Sstevel@tonic-gate 	 * if the segment was on the import list in state RSM_STATE_CONNECTING
59967c478bd9Sstevel@tonic-gate 	 * then a connection was in progress. Change to RSM_STATE_NEW
59977c478bd9Sstevel@tonic-gate 	 * here to cause an early exit from the connection process.
59987c478bd9Sstevel@tonic-gate 	 */
59997c478bd9Sstevel@tonic-gate 	if (im_seg->s_state == RSM_STATE_NEW) {
60007c478bd9Sstevel@tonic-gate 		rsmseglock_release(im_seg);
60017c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
60027c478bd9Sstevel@tonic-gate 		    "rsmseg_unload done: RSM_STATE_NEW\n"));
60037c478bd9Sstevel@tonic-gate 		return;
60047c478bd9Sstevel@tonic-gate 	} else if (im_seg->s_state == RSM_STATE_CONNECTING) {
60057c478bd9Sstevel@tonic-gate 		im_seg->s_state = RSM_STATE_ABORT_CONNECT;
60067c478bd9Sstevel@tonic-gate 		rsmsharelock_acquire(im_seg);
60077c478bd9Sstevel@tonic-gate 		im_seg->s_share->rsmsi_state = RSMSI_STATE_ABORT_CONNECT;
60087c478bd9Sstevel@tonic-gate 		rsmsharelock_release(im_seg);
60097c478bd9Sstevel@tonic-gate 		rsmseglock_release(im_seg);
60107c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
60117c478bd9Sstevel@tonic-gate 		    "rsmseg_unload done: RSM_STATE_CONNECTING\n"));
60127c478bd9Sstevel@tonic-gate 		return;
60137c478bd9Sstevel@tonic-gate 	}
60147c478bd9Sstevel@tonic-gate 
60157c478bd9Sstevel@tonic-gate 	if (im_seg->s_flags & RSM_FORCE_DISCONNECT) {
60167c478bd9Sstevel@tonic-gate 		if (im_seg->s_ckl != NULL) {
60177c478bd9Sstevel@tonic-gate 			int e;
60187c478bd9Sstevel@tonic-gate 			/* Setup protections for remap */
60197c478bd9Sstevel@tonic-gate 			maxprot = PROT_USER;
60207c478bd9Sstevel@tonic-gate 			if (im_seg->s_mode & RSM_PERM_READ) {
60217c478bd9Sstevel@tonic-gate 				maxprot |= PROT_READ;
60227c478bd9Sstevel@tonic-gate 			}
60237c478bd9Sstevel@tonic-gate 			if (im_seg->s_mode & RSM_PERM_WRITE) {
60247c478bd9Sstevel@tonic-gate 				maxprot |= PROT_WRITE;
60257c478bd9Sstevel@tonic-gate 			}
60267c478bd9Sstevel@tonic-gate 			hdl = im_seg->s_ckl;
60277c478bd9Sstevel@tonic-gate 			for (; hdl != NULL; hdl = hdl->c_next) {
60287c478bd9Sstevel@tonic-gate 				e = devmap_umem_remap(hdl->c_dhp, rsm_dip,
60297c478bd9Sstevel@tonic-gate 				    remap_cookie,
60307c478bd9Sstevel@tonic-gate 				    hdl->c_off, hdl->c_len,
60317c478bd9Sstevel@tonic-gate 				    maxprot, 0, NULL);
60327c478bd9Sstevel@tonic-gate 
60337c478bd9Sstevel@tonic-gate 				DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
60347c478bd9Sstevel@tonic-gate 				    "remap returns %d\n", e));
60357c478bd9Sstevel@tonic-gate 			}
60367c478bd9Sstevel@tonic-gate 		}
60377c478bd9Sstevel@tonic-gate 
60387c478bd9Sstevel@tonic-gate 		(void) rsm_closeconnection(im_seg, &shared_cookie);
60397c478bd9Sstevel@tonic-gate 
60407c478bd9Sstevel@tonic-gate 		if (shared_cookie != NULL) {
60417c478bd9Sstevel@tonic-gate 			/*
60427c478bd9Sstevel@tonic-gate 			 * inform the exporting node so this import
60437c478bd9Sstevel@tonic-gate 			 * can be deleted from the list of importers.
60447c478bd9Sstevel@tonic-gate 			 */
60457c478bd9Sstevel@tonic-gate 			request.rsmipc_hdr.rsmipc_type =
60467c478bd9Sstevel@tonic-gate 			    RSMIPC_MSG_NOTIMPORTING;
60477c478bd9Sstevel@tonic-gate 			request.rsmipc_key = im_seg->s_segid;
60487c478bd9Sstevel@tonic-gate 			request.rsmipc_segment_cookie = shared_cookie;
60497c478bd9Sstevel@tonic-gate 			rsmseglock_release(im_seg);
60507c478bd9Sstevel@tonic-gate 			(void) rsmipc_send(im_seg->s_node, &request,
60517c478bd9Sstevel@tonic-gate 			    RSM_NO_REPLY);
60527c478bd9Sstevel@tonic-gate 		} else {
60537c478bd9Sstevel@tonic-gate 			rsmseglock_release(im_seg);
60547c478bd9Sstevel@tonic-gate 		}
60557c478bd9Sstevel@tonic-gate 	}
60567c478bd9Sstevel@tonic-gate 	else
60577c478bd9Sstevel@tonic-gate 		rsmseglock_release(im_seg);
60587c478bd9Sstevel@tonic-gate 
60597c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmseg_unload done\n"));
60607c478bd9Sstevel@tonic-gate 
60617c478bd9Sstevel@tonic-gate }
60627c478bd9Sstevel@tonic-gate 
60637c478bd9Sstevel@tonic-gate /* ****************************** Importer Calls ************************ */
60647c478bd9Sstevel@tonic-gate 
60657c478bd9Sstevel@tonic-gate static int
rsm_access(uid_t owner,gid_t group,int perm,int mode,const struct cred * cr)60667c478bd9Sstevel@tonic-gate rsm_access(uid_t owner, gid_t group, int perm, int mode, const struct cred *cr)
60677c478bd9Sstevel@tonic-gate {
60687c478bd9Sstevel@tonic-gate 	int shifts = 0;
60697c478bd9Sstevel@tonic-gate 
60707c478bd9Sstevel@tonic-gate 	if (crgetuid(cr) != owner) {
60717c478bd9Sstevel@tonic-gate 		shifts += 3;
60727c478bd9Sstevel@tonic-gate 		if (!groupmember(group, cr))
60737c478bd9Sstevel@tonic-gate 			shifts += 3;
60747c478bd9Sstevel@tonic-gate 	}
60757c478bd9Sstevel@tonic-gate 
60767c478bd9Sstevel@tonic-gate 	mode &= ~(perm << shifts);
60777c478bd9Sstevel@tonic-gate 
60787c478bd9Sstevel@tonic-gate 	if (mode == 0)
60797c478bd9Sstevel@tonic-gate 		return (0);
60807c478bd9Sstevel@tonic-gate 
60817c478bd9Sstevel@tonic-gate 	return (secpolicy_rsm_access(cr, owner, mode));
60827c478bd9Sstevel@tonic-gate }
60837c478bd9Sstevel@tonic-gate 
60847c478bd9Sstevel@tonic-gate 
60857c478bd9Sstevel@tonic-gate static int
rsm_connect(rsmseg_t * seg,rsm_ioctlmsg_t * msg,cred_t * cred,intptr_t dataptr,int mode)60867c478bd9Sstevel@tonic-gate rsm_connect(rsmseg_t *seg, rsm_ioctlmsg_t *msg, cred_t *cred,
60877c478bd9Sstevel@tonic-gate     intptr_t dataptr, int mode)
60887c478bd9Sstevel@tonic-gate {
60897c478bd9Sstevel@tonic-gate 	int e;
60907c478bd9Sstevel@tonic-gate 	int			recheck_state = 0;
60917c478bd9Sstevel@tonic-gate 	void			*shared_cookie;
60927c478bd9Sstevel@tonic-gate 	rsmipc_request_t	request;
60937c478bd9Sstevel@tonic-gate 	rsmipc_reply_t		reply;
60947c478bd9Sstevel@tonic-gate 	rsm_permission_t	access;
60957c478bd9Sstevel@tonic-gate 	adapter_t		*adapter;
60967c478bd9Sstevel@tonic-gate 	rsm_addr_t		addr = 0;
60977c478bd9Sstevel@tonic-gate 	rsm_import_share_t	*sharedp;
60987c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_IMPORT);
60997c478bd9Sstevel@tonic-gate 
61007c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_connect enter\n"));
61017c478bd9Sstevel@tonic-gate 
61027c478bd9Sstevel@tonic-gate 	adapter = rsm_getadapter(msg, mode);
61037c478bd9Sstevel@tonic-gate 	if (adapter == NULL) {
61047c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
61057c478bd9Sstevel@tonic-gate 		    "rsm_connect done:ENODEV adapter=NULL\n"));
61067c478bd9Sstevel@tonic-gate 		return (RSMERR_CTLR_NOT_PRESENT);
61077c478bd9Sstevel@tonic-gate 	}
61087c478bd9Sstevel@tonic-gate 
61097c478bd9Sstevel@tonic-gate 	if ((adapter == &loopback_adapter) && (msg->nodeid != my_nodeid)) {
61107c478bd9Sstevel@tonic-gate 		rsmka_release_adapter(adapter);
61117c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
61127c478bd9Sstevel@tonic-gate 		    "rsm_connect done:ENODEV loopback\n"));
61137c478bd9Sstevel@tonic-gate 		return (RSMERR_CTLR_NOT_PRESENT);
61147c478bd9Sstevel@tonic-gate 	}
61157c478bd9Sstevel@tonic-gate 
61167c478bd9Sstevel@tonic-gate 
61177c478bd9Sstevel@tonic-gate 	ASSERT(seg->s_hdr.rsmrc_type == RSM_RESOURCE_IMPORT_SEGMENT);
61187c478bd9Sstevel@tonic-gate 	ASSERT(seg->s_state == RSM_STATE_NEW);
61197c478bd9Sstevel@tonic-gate 
61207c478bd9Sstevel@tonic-gate 	/*
61217c478bd9Sstevel@tonic-gate 	 * Translate perm to access
61227c478bd9Sstevel@tonic-gate 	 */
61237c478bd9Sstevel@tonic-gate 	if (msg->perm & ~RSM_PERM_RDWR) {
61247c478bd9Sstevel@tonic-gate 		rsmka_release_adapter(adapter);
61257c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
61267c478bd9Sstevel@tonic-gate 		    "rsm_connect done:EINVAL invalid perms\n"));
61277c478bd9Sstevel@tonic-gate 		return (RSMERR_BAD_PERMS);
61287c478bd9Sstevel@tonic-gate 	}
61297c478bd9Sstevel@tonic-gate 	access = 0;
61307c478bd9Sstevel@tonic-gate 	if (msg->perm & RSM_PERM_READ)
61317c478bd9Sstevel@tonic-gate 		access |= RSM_ACCESS_READ;
61327c478bd9Sstevel@tonic-gate 	if (msg->perm & RSM_PERM_WRITE)
61337c478bd9Sstevel@tonic-gate 		access |= RSM_ACCESS_WRITE;
61347c478bd9Sstevel@tonic-gate 
61357c478bd9Sstevel@tonic-gate 	seg->s_node = msg->nodeid;
61367c478bd9Sstevel@tonic-gate 
61377c478bd9Sstevel@tonic-gate 	/*
61387c478bd9Sstevel@tonic-gate 	 * Adding to the import list locks the segment; release the segment
61397c478bd9Sstevel@tonic-gate 	 * lock so we can get the reply for the send.
61407c478bd9Sstevel@tonic-gate 	 */
61417c478bd9Sstevel@tonic-gate 	e = rsmimport_add(seg, msg->key);
61427c478bd9Sstevel@tonic-gate 	if (e) {
61437c478bd9Sstevel@tonic-gate 		rsmka_release_adapter(adapter);
61447c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
61457c478bd9Sstevel@tonic-gate 		    "rsm_connect done:rsmimport_add failed %d\n", e));
61467c478bd9Sstevel@tonic-gate 		return (e);
61477c478bd9Sstevel@tonic-gate 	}
61487c478bd9Sstevel@tonic-gate 	seg->s_state = RSM_STATE_CONNECTING;
61497c478bd9Sstevel@tonic-gate 
61507c478bd9Sstevel@tonic-gate 	/*
61517c478bd9Sstevel@tonic-gate 	 * Set the s_adapter field here so as to have a valid comparison of
61527c478bd9Sstevel@tonic-gate 	 * the adapter and the s_adapter value during rsmshare_get. For
61537c478bd9Sstevel@tonic-gate 	 * any error, set s_adapter to NULL before doing a release_adapter
61547c478bd9Sstevel@tonic-gate 	 */
61557c478bd9Sstevel@tonic-gate 	seg->s_adapter = adapter;
61567c478bd9Sstevel@tonic-gate 
61577c478bd9Sstevel@tonic-gate 	rsmseglock_release(seg);
61587c478bd9Sstevel@tonic-gate 
61597c478bd9Sstevel@tonic-gate 	/*
61607c478bd9Sstevel@tonic-gate 	 * get the pointer to the shared data structure; the
61617c478bd9Sstevel@tonic-gate 	 * shared data is locked and refcount has been incremented
61627c478bd9Sstevel@tonic-gate 	 */
61637c478bd9Sstevel@tonic-gate 	sharedp = rsmshare_get(msg->key, msg->nodeid, adapter, seg);
61647c478bd9Sstevel@tonic-gate 
61657c478bd9Sstevel@tonic-gate 	ASSERT(rsmsharelock_held(seg));
61667c478bd9Sstevel@tonic-gate 
61677c478bd9Sstevel@tonic-gate 	do {
61687c478bd9Sstevel@tonic-gate 		/* flag indicates whether we need to recheck the state */
61697c478bd9Sstevel@tonic-gate 		recheck_state = 0;
61707c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
61717c478bd9Sstevel@tonic-gate 		    "rsm_connect:RSMSI_STATE=%d\n", sharedp->rsmsi_state));
61727c478bd9Sstevel@tonic-gate 		switch (sharedp->rsmsi_state) {
61737c478bd9Sstevel@tonic-gate 		case RSMSI_STATE_NEW:
61747c478bd9Sstevel@tonic-gate 			sharedp->rsmsi_state = RSMSI_STATE_CONNECTING;
61757c478bd9Sstevel@tonic-gate 			break;
61767c478bd9Sstevel@tonic-gate 		case RSMSI_STATE_CONNECTING:
61777c478bd9Sstevel@tonic-gate 			/* FALLTHRU */
61787c478bd9Sstevel@tonic-gate 		case RSMSI_STATE_CONN_QUIESCE:
61797c478bd9Sstevel@tonic-gate 			/* FALLTHRU */
61807c478bd9Sstevel@tonic-gate 		case RSMSI_STATE_MAP_QUIESCE:
61817c478bd9Sstevel@tonic-gate 			/* wait for the state to change */
61827c478bd9Sstevel@tonic-gate 			while ((sharedp->rsmsi_state ==
61837c478bd9Sstevel@tonic-gate 			    RSMSI_STATE_CONNECTING) ||
61847c478bd9Sstevel@tonic-gate 			    (sharedp->rsmsi_state ==
61857c478bd9Sstevel@tonic-gate 			    RSMSI_STATE_CONN_QUIESCE) ||
61867c478bd9Sstevel@tonic-gate 			    (sharedp->rsmsi_state ==
61877c478bd9Sstevel@tonic-gate 			    RSMSI_STATE_MAP_QUIESCE)) {
61887c478bd9Sstevel@tonic-gate 				if (cv_wait_sig(&sharedp->rsmsi_cv,
61897c478bd9Sstevel@tonic-gate 				    &sharedp->rsmsi_lock) == 0) {
61907c478bd9Sstevel@tonic-gate 					/* signalled - clean up and return */
61917c478bd9Sstevel@tonic-gate 					rsmsharelock_release(seg);
61927c478bd9Sstevel@tonic-gate 					rsmimport_rm(seg);
61937c478bd9Sstevel@tonic-gate 					seg->s_adapter = NULL;
61947c478bd9Sstevel@tonic-gate 					rsmka_release_adapter(adapter);
61957c478bd9Sstevel@tonic-gate 					seg->s_state = RSM_STATE_NEW;
61967c478bd9Sstevel@tonic-gate 					DBG_PRINTF((category, RSM_ERR,
61977c478bd9Sstevel@tonic-gate 					    "rsm_connect done: INTERRUPTED\n"));
61987c478bd9Sstevel@tonic-gate 					return (RSMERR_INTERRUPTED);
61997c478bd9Sstevel@tonic-gate 				}
62007c478bd9Sstevel@tonic-gate 			}
62017c478bd9Sstevel@tonic-gate 			/*
62027c478bd9Sstevel@tonic-gate 			 * the state changed, loop back and check what it is
62037c478bd9Sstevel@tonic-gate 			 */
62047c478bd9Sstevel@tonic-gate 			recheck_state = 1;
62057c478bd9Sstevel@tonic-gate 			break;
62067c478bd9Sstevel@tonic-gate 		case RSMSI_STATE_ABORT_CONNECT:
62077c478bd9Sstevel@tonic-gate 			/* exit the loop and clean up further down */
62087c478bd9Sstevel@tonic-gate 			break;
62097c478bd9Sstevel@tonic-gate 		case RSMSI_STATE_CONNECTED:
62107c478bd9Sstevel@tonic-gate 			/* already connected, good - fall through */
62117c478bd9Sstevel@tonic-gate 		case RSMSI_STATE_MAPPED:
62127c478bd9Sstevel@tonic-gate 			/* already mapped, wow - fall through */
62137c478bd9Sstevel@tonic-gate 			/* access validation etc is done further down */
62147c478bd9Sstevel@tonic-gate 			break;
62157c478bd9Sstevel@tonic-gate 		case RSMSI_STATE_DISCONNECTED:
62167c478bd9Sstevel@tonic-gate 			/* disconnected - so reconnect now */
62177c478bd9Sstevel@tonic-gate 			sharedp->rsmsi_state = RSMSI_STATE_CONNECTING;
62187c478bd9Sstevel@tonic-gate 			break;
62197c478bd9Sstevel@tonic-gate 		default:
62207c478bd9Sstevel@tonic-gate 			ASSERT(0); /* Invalid State */
62217c478bd9Sstevel@tonic-gate 		}
62227c478bd9Sstevel@tonic-gate 	} while (recheck_state);
62237c478bd9Sstevel@tonic-gate 
62247c478bd9Sstevel@tonic-gate 	if (sharedp->rsmsi_state == RSMSI_STATE_CONNECTING) {
62257c478bd9Sstevel@tonic-gate 		/* we are the first to connect */
62267c478bd9Sstevel@tonic-gate 		rsmsharelock_release(seg);
62277c478bd9Sstevel@tonic-gate 
62287c478bd9Sstevel@tonic-gate 		if (msg->nodeid != my_nodeid) {
62297c478bd9Sstevel@tonic-gate 			addr = get_remote_hwaddr(adapter, msg->nodeid);
62307c478bd9Sstevel@tonic-gate 
62317c478bd9Sstevel@tonic-gate 			if ((int64_t)addr < 0) {
62327c478bd9Sstevel@tonic-gate 				rsmsharelock_acquire(seg);
62337c478bd9Sstevel@tonic-gate 				rsmsharecv_signal(seg, RSMSI_STATE_CONNECTING,
62347c478bd9Sstevel@tonic-gate 				    RSMSI_STATE_NEW);
62357c478bd9Sstevel@tonic-gate 				rsmsharelock_release(seg);
62367c478bd9Sstevel@tonic-gate 				rsmimport_rm(seg);
62377c478bd9Sstevel@tonic-gate 				seg->s_adapter = NULL;
62387c478bd9Sstevel@tonic-gate 				rsmka_release_adapter(adapter);
62397c478bd9Sstevel@tonic-gate 				seg->s_state = RSM_STATE_NEW;
62407c478bd9Sstevel@tonic-gate 				DBG_PRINTF((category, RSM_ERR,
62417c478bd9Sstevel@tonic-gate 				    "rsm_connect done: hwaddr<0\n"));
62427c478bd9Sstevel@tonic-gate 				return (RSMERR_INTERNAL_ERROR);
62437c478bd9Sstevel@tonic-gate 			}
62447c478bd9Sstevel@tonic-gate 		} else {
62457c478bd9Sstevel@tonic-gate 			addr = adapter->hwaddr;
62467c478bd9Sstevel@tonic-gate 		}
62477c478bd9Sstevel@tonic-gate 
62487c478bd9Sstevel@tonic-gate 		/*
62497c478bd9Sstevel@tonic-gate 		 * send request to node [src, dest, key, msgid] and get back
62507c478bd9Sstevel@tonic-gate 		 * [status, msgid, cookie]
62517c478bd9Sstevel@tonic-gate 		 */
62527c478bd9Sstevel@tonic-gate 		request.rsmipc_key = msg->key;
62537c478bd9Sstevel@tonic-gate 		/*
62547c478bd9Sstevel@tonic-gate 		 * we need the s_mode of the exporter so pass
62557c478bd9Sstevel@tonic-gate 		 * RSM_ACCESS_TRUSTED
62567c478bd9Sstevel@tonic-gate 		 */
62577c478bd9Sstevel@tonic-gate 		request.rsmipc_perm = RSM_ACCESS_TRUSTED;
62587c478bd9Sstevel@tonic-gate 		request.rsmipc_hdr.rsmipc_type = RSMIPC_MSG_SEGCONNECT;
62597c478bd9Sstevel@tonic-gate 		request.rsmipc_adapter_hwaddr = addr;
62607c478bd9Sstevel@tonic-gate 		request.rsmipc_segment_cookie = sharedp;
62617c478bd9Sstevel@tonic-gate 
62627c478bd9Sstevel@tonic-gate 		e = (int)rsmipc_send(msg->nodeid, &request, &reply);
62637c478bd9Sstevel@tonic-gate 		if (e) {
62647c478bd9Sstevel@tonic-gate 			rsmsharelock_acquire(seg);
62657c478bd9Sstevel@tonic-gate 			rsmsharecv_signal(seg, RSMSI_STATE_CONNECTING,
62667c478bd9Sstevel@tonic-gate 			    RSMSI_STATE_NEW);
62677c478bd9Sstevel@tonic-gate 			rsmsharelock_release(seg);
62687c478bd9Sstevel@tonic-gate 			rsmimport_rm(seg);
62697c478bd9Sstevel@tonic-gate 			seg->s_adapter = NULL;
62707c478bd9Sstevel@tonic-gate 			rsmka_release_adapter(adapter);
62717c478bd9Sstevel@tonic-gate 			seg->s_state = RSM_STATE_NEW;
62727c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_ERR,
62737c478bd9Sstevel@tonic-gate 			    "rsm_connect done:rsmipc_send failed %d\n", e));
62747c478bd9Sstevel@tonic-gate 			return (e);
62757c478bd9Sstevel@tonic-gate 		}
62767c478bd9Sstevel@tonic-gate 
62777c478bd9Sstevel@tonic-gate 		if (reply.rsmipc_status != RSM_SUCCESS) {
62787c478bd9Sstevel@tonic-gate 			rsmsharelock_acquire(seg);
62797c478bd9Sstevel@tonic-gate 			rsmsharecv_signal(seg, RSMSI_STATE_CONNECTING,
62807c478bd9Sstevel@tonic-gate 			    RSMSI_STATE_NEW);
62817c478bd9Sstevel@tonic-gate 			rsmsharelock_release(seg);
62827c478bd9Sstevel@tonic-gate 			rsmimport_rm(seg);
62837c478bd9Sstevel@tonic-gate 			seg->s_adapter = NULL;
62847c478bd9Sstevel@tonic-gate 			rsmka_release_adapter(adapter);
62857c478bd9Sstevel@tonic-gate 			seg->s_state = RSM_STATE_NEW;
62867c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_ERR,
62877c478bd9Sstevel@tonic-gate 			    "rsm_connect done:rsmipc_send reply err %d\n",
62887c478bd9Sstevel@tonic-gate 			    reply.rsmipc_status));
62897c478bd9Sstevel@tonic-gate 			return (reply.rsmipc_status);
62907c478bd9Sstevel@tonic-gate 		}
62917c478bd9Sstevel@tonic-gate 
62927c478bd9Sstevel@tonic-gate 		rsmsharelock_acquire(seg);
62937c478bd9Sstevel@tonic-gate 		/* store the information recvd into the shared data struct */
62947c478bd9Sstevel@tonic-gate 		sharedp->rsmsi_mode = reply.rsmipc_mode;
62957c478bd9Sstevel@tonic-gate 		sharedp->rsmsi_uid = reply.rsmipc_uid;
62967c478bd9Sstevel@tonic-gate 		sharedp->rsmsi_gid = reply.rsmipc_gid;
62977c478bd9Sstevel@tonic-gate 		sharedp->rsmsi_seglen = reply.rsmipc_seglen;
62987c478bd9Sstevel@tonic-gate 		sharedp->rsmsi_cookie = sharedp;
62997c478bd9Sstevel@tonic-gate 	}
63007c478bd9Sstevel@tonic-gate 
63017c478bd9Sstevel@tonic-gate 	rsmsharelock_release(seg);
63027c478bd9Sstevel@tonic-gate 
63037c478bd9Sstevel@tonic-gate 	/*
63047c478bd9Sstevel@tonic-gate 	 * Get the segment lock and check for a force disconnect
63057c478bd9Sstevel@tonic-gate 	 * from the export side which would have changed the state
63067c478bd9Sstevel@tonic-gate 	 * back to RSM_STATE_NEW. Once the segment lock is acquired a
63077c478bd9Sstevel@tonic-gate 	 * force disconnect will be held off until the connection
63087c478bd9Sstevel@tonic-gate 	 * has completed.
63097c478bd9Sstevel@tonic-gate 	 */
63107c478bd9Sstevel@tonic-gate 	rsmseglock_acquire(seg);
63117c478bd9Sstevel@tonic-gate 	rsmsharelock_acquire(seg);
63127c478bd9Sstevel@tonic-gate 	ASSERT(seg->s_state == RSM_STATE_CONNECTING ||
63137c478bd9Sstevel@tonic-gate 	    seg->s_state == RSM_STATE_ABORT_CONNECT);
63147c478bd9Sstevel@tonic-gate 
63157c478bd9Sstevel@tonic-gate 	shared_cookie = sharedp->rsmsi_cookie;
63167c478bd9Sstevel@tonic-gate 
63177c478bd9Sstevel@tonic-gate 	if ((seg->s_state == RSM_STATE_ABORT_CONNECT) ||
63187c478bd9Sstevel@tonic-gate 	    (sharedp->rsmsi_state == RSMSI_STATE_ABORT_CONNECT)) {
63197c478bd9Sstevel@tonic-gate 		seg->s_state = RSM_STATE_NEW;
63207c478bd9Sstevel@tonic-gate 		seg->s_adapter = NULL;
63217c478bd9Sstevel@tonic-gate 		rsmsharelock_release(seg);
63227c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
63237c478bd9Sstevel@tonic-gate 		rsmimport_rm(seg);
63247c478bd9Sstevel@tonic-gate 		rsmka_release_adapter(adapter);
63257c478bd9Sstevel@tonic-gate 
63267c478bd9Sstevel@tonic-gate 		rsmsharelock_acquire(seg);
63277c478bd9Sstevel@tonic-gate 		if (!(sharedp->rsmsi_flags & RSMSI_FLAGS_ABORTDONE)) {
63287c478bd9Sstevel@tonic-gate 			/*
63297c478bd9Sstevel@tonic-gate 			 * set a flag indicating abort handling has been
63307c478bd9Sstevel@tonic-gate 			 * done
63317c478bd9Sstevel@tonic-gate 			 */
63327c478bd9Sstevel@tonic-gate 			sharedp->rsmsi_flags |= RSMSI_FLAGS_ABORTDONE;
63337c478bd9Sstevel@tonic-gate 			rsmsharelock_release(seg);
63347c478bd9Sstevel@tonic-gate 			/* send a message to exporter - only once */
63357c478bd9Sstevel@tonic-gate 			(void) rsm_send_notimporting(msg->nodeid,
63367c478bd9Sstevel@tonic-gate 			    msg->key, shared_cookie);
63377c478bd9Sstevel@tonic-gate 			rsmsharelock_acquire(seg);
63387c478bd9Sstevel@tonic-gate 			/*
63397c478bd9Sstevel@tonic-gate 			 * wake up any waiting importers and inform that
63407c478bd9Sstevel@tonic-gate 			 * connection has been aborted
63417c478bd9Sstevel@tonic-gate 			 */
63427c478bd9Sstevel@tonic-gate 			cv_broadcast(&sharedp->rsmsi_cv);
63437c478bd9Sstevel@tonic-gate 		}
63447c478bd9Sstevel@tonic-gate 		rsmsharelock_release(seg);
63457c478bd9Sstevel@tonic-gate 
63467c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
63477c478bd9Sstevel@tonic-gate 		    "rsm_connect done: RSM_STATE_ABORT_CONNECT\n"));
63487c478bd9Sstevel@tonic-gate 		return (RSMERR_INTERRUPTED);
63497c478bd9Sstevel@tonic-gate 	}
63507c478bd9Sstevel@tonic-gate 
63517c478bd9Sstevel@tonic-gate 
63527c478bd9Sstevel@tonic-gate 	/*
63537c478bd9Sstevel@tonic-gate 	 * We need to verify that this process has access
63547c478bd9Sstevel@tonic-gate 	 */
63557c478bd9Sstevel@tonic-gate 	e = rsm_access(sharedp->rsmsi_uid, sharedp->rsmsi_gid,
63567c478bd9Sstevel@tonic-gate 	    access & sharedp->rsmsi_mode,
63577c478bd9Sstevel@tonic-gate 	    (int)(msg->perm & RSM_PERM_RDWR), cred);
63587c478bd9Sstevel@tonic-gate 	if (e) {
63597c478bd9Sstevel@tonic-gate 		rsmsharelock_release(seg);
63607c478bd9Sstevel@tonic-gate 		seg->s_state = RSM_STATE_NEW;
63617c478bd9Sstevel@tonic-gate 		seg->s_adapter = NULL;
63627c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
63637c478bd9Sstevel@tonic-gate 		rsmimport_rm(seg);
63647c478bd9Sstevel@tonic-gate 		rsmka_release_adapter(adapter);
63657c478bd9Sstevel@tonic-gate 		/*
63667c478bd9Sstevel@tonic-gate 		 * No need to lock segment it has been removed
63677c478bd9Sstevel@tonic-gate 		 * from the hash table
63687c478bd9Sstevel@tonic-gate 		 */
63697c478bd9Sstevel@tonic-gate 		rsmsharelock_acquire(seg);
63707c478bd9Sstevel@tonic-gate 		if (sharedp->rsmsi_state == RSMSI_STATE_CONNECTING) {
63717c478bd9Sstevel@tonic-gate 			rsmsharelock_release(seg);
63727c478bd9Sstevel@tonic-gate 			/* this is the first importer */
63737c478bd9Sstevel@tonic-gate 
63747c478bd9Sstevel@tonic-gate 			(void) rsm_send_notimporting(msg->nodeid, msg->key,
63757c478bd9Sstevel@tonic-gate 			    shared_cookie);
63767c478bd9Sstevel@tonic-gate 			rsmsharelock_acquire(seg);
63777c478bd9Sstevel@tonic-gate 			sharedp->rsmsi_state = RSMSI_STATE_NEW;
63787c478bd9Sstevel@tonic-gate 			cv_broadcast(&sharedp->rsmsi_cv);
63797c478bd9Sstevel@tonic-gate 		}
63807c478bd9Sstevel@tonic-gate 		rsmsharelock_release(seg);
63817c478bd9Sstevel@tonic-gate 
63827c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
63837c478bd9Sstevel@tonic-gate 		    "rsm_connect done: ipcaccess failed\n"));
63847c478bd9Sstevel@tonic-gate 		return (RSMERR_PERM_DENIED);
63857c478bd9Sstevel@tonic-gate 	}
63867c478bd9Sstevel@tonic-gate 
63877c478bd9Sstevel@tonic-gate 	/* update state and cookie */
63887c478bd9Sstevel@tonic-gate 	seg->s_segid = sharedp->rsmsi_segid;
63897c478bd9Sstevel@tonic-gate 	seg->s_len = sharedp->rsmsi_seglen;
63907c478bd9Sstevel@tonic-gate 	seg->s_mode = access & sharedp->rsmsi_mode;
63917c478bd9Sstevel@tonic-gate 	seg->s_pid = ddi_get_pid();
63927c478bd9Sstevel@tonic-gate 	seg->s_mapinfo = NULL;
63937c478bd9Sstevel@tonic-gate 
63947c478bd9Sstevel@tonic-gate 	if (seg->s_node != my_nodeid) {
63957c478bd9Sstevel@tonic-gate 		if (sharedp->rsmsi_state == RSMSI_STATE_CONNECTING) {
63967c478bd9Sstevel@tonic-gate 			e = adapter->rsmpi_ops->rsm_connect(
63977c478bd9Sstevel@tonic-gate 			    adapter->rsmpi_handle,
63987c478bd9Sstevel@tonic-gate 			    addr, seg->s_segid, &sharedp->rsmsi_handle);
63997c478bd9Sstevel@tonic-gate 
64007c478bd9Sstevel@tonic-gate 			if (e != RSM_SUCCESS) {
64017c478bd9Sstevel@tonic-gate 				seg->s_state = RSM_STATE_NEW;
64027c478bd9Sstevel@tonic-gate 				seg->s_adapter = NULL;
64037c478bd9Sstevel@tonic-gate 				rsmsharelock_release(seg);
64047c478bd9Sstevel@tonic-gate 				rsmseglock_release(seg);
64057c478bd9Sstevel@tonic-gate 				rsmimport_rm(seg);
64067c478bd9Sstevel@tonic-gate 				rsmka_release_adapter(adapter);
64077c478bd9Sstevel@tonic-gate 				/*
64087c478bd9Sstevel@tonic-gate 				 *  inform the exporter to delete this importer
64097c478bd9Sstevel@tonic-gate 				 */
64107c478bd9Sstevel@tonic-gate 				(void) rsm_send_notimporting(msg->nodeid,
64117c478bd9Sstevel@tonic-gate 				    msg->key, shared_cookie);
64127c478bd9Sstevel@tonic-gate 
64137c478bd9Sstevel@tonic-gate 				/*
64147c478bd9Sstevel@tonic-gate 				 * Now inform any waiting importers to
64157c478bd9Sstevel@tonic-gate 				 * retry connect. This needs to be done
64167c478bd9Sstevel@tonic-gate 				 * after sending notimporting so that
64177c478bd9Sstevel@tonic-gate 				 * the notimporting is sent before a waiting
64187c478bd9Sstevel@tonic-gate 				 * importer sends a segconnect while retrying
64197c478bd9Sstevel@tonic-gate 				 *
64207c478bd9Sstevel@tonic-gate 				 * No need to lock segment it has been removed
64217c478bd9Sstevel@tonic-gate 				 * from the hash table
64227c478bd9Sstevel@tonic-gate 				 */
64237c478bd9Sstevel@tonic-gate 
64247c478bd9Sstevel@tonic-gate 				rsmsharelock_acquire(seg);
64257c478bd9Sstevel@tonic-gate 				sharedp->rsmsi_state = RSMSI_STATE_NEW;
64267c478bd9Sstevel@tonic-gate 				cv_broadcast(&sharedp->rsmsi_cv);
64277c478bd9Sstevel@tonic-gate 				rsmsharelock_release(seg);
64287c478bd9Sstevel@tonic-gate 
64297c478bd9Sstevel@tonic-gate 				DBG_PRINTF((category, RSM_ERR,
64307c478bd9Sstevel@tonic-gate 				    "rsm_connect error %d\n", e));
64317c478bd9Sstevel@tonic-gate 				if (e == RSMERR_SEG_NOT_PUBLISHED_TO_RSM_ADDR)
64327c478bd9Sstevel@tonic-gate 					return (
64337c478bd9Sstevel@tonic-gate 					    RSMERR_SEG_NOT_PUBLISHED_TO_NODE);
64347c478bd9Sstevel@tonic-gate 				else if ((e == RSMERR_RSM_ADDR_UNREACHABLE) ||
64357c478bd9Sstevel@tonic-gate 				    (e == RSMERR_UNKNOWN_RSM_ADDR))
64367c478bd9Sstevel@tonic-gate 					return (RSMERR_REMOTE_NODE_UNREACHABLE);
64377c478bd9Sstevel@tonic-gate 				else
64387c478bd9Sstevel@tonic-gate 					return (e);
64397c478bd9Sstevel@tonic-gate 			}
64407c478bd9Sstevel@tonic-gate 
64417c478bd9Sstevel@tonic-gate 		}
64427c478bd9Sstevel@tonic-gate 		seg->s_handle.in = sharedp->rsmsi_handle;
64437c478bd9Sstevel@tonic-gate 
64447c478bd9Sstevel@tonic-gate 	}
64457c478bd9Sstevel@tonic-gate 
64467c478bd9Sstevel@tonic-gate 	seg->s_state = RSM_STATE_CONNECT;
64477c478bd9Sstevel@tonic-gate 
64487c478bd9Sstevel@tonic-gate 
64497c478bd9Sstevel@tonic-gate 	seg->s_flags &= ~RSM_IMPORT_DUMMY;	/* clear dummy flag */
64507c478bd9Sstevel@tonic-gate 	if (bar_va) {
64517c478bd9Sstevel@tonic-gate 		/* increment generation number on barrier page */
6452*1a5e258fSJosef 'Jeff' Sipek 		atomic_inc_16(bar_va + seg->s_hdr.rsmrc_num);
64537c478bd9Sstevel@tonic-gate 		/* return user off into barrier page where status will be */
64547c478bd9Sstevel@tonic-gate 		msg->off = (int)seg->s_hdr.rsmrc_num;
64557c478bd9Sstevel@tonic-gate 		msg->gnum = bar_va[msg->off]; 	/* gnum race */
64567c478bd9Sstevel@tonic-gate 	} else {
64577c478bd9Sstevel@tonic-gate 		msg->off = 0;
64587c478bd9Sstevel@tonic-gate 		msg->gnum = 0;	/* gnum race */
64597c478bd9Sstevel@tonic-gate 	}
64607c478bd9Sstevel@tonic-gate 
64617c478bd9Sstevel@tonic-gate 	msg->len = (int)sharedp->rsmsi_seglen;
64627c478bd9Sstevel@tonic-gate 	msg->rnum = seg->s_minor;
64637c478bd9Sstevel@tonic-gate 	rsmsharecv_signal(seg, RSMSI_STATE_CONNECTING, RSMSI_STATE_CONNECTED);
64647c478bd9Sstevel@tonic-gate 	rsmsharelock_release(seg);
64657c478bd9Sstevel@tonic-gate 	rsmseglock_release(seg);
64667c478bd9Sstevel@tonic-gate 
64677c478bd9Sstevel@tonic-gate 	/* Return back to user the segment size & perm in case it's needed */
64687c478bd9Sstevel@tonic-gate 
64697c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
64707c478bd9Sstevel@tonic-gate 	if ((mode & DATAMODEL_MASK) == DATAMODEL_ILP32) {
64717c478bd9Sstevel@tonic-gate 		rsm_ioctlmsg32_t msg32;
64727c478bd9Sstevel@tonic-gate 
64737c478bd9Sstevel@tonic-gate 		if (msg->len > UINT_MAX)
64747c478bd9Sstevel@tonic-gate 			msg32.len = RSM_MAXSZ_PAGE_ALIGNED;
64757c478bd9Sstevel@tonic-gate 		else
64767c478bd9Sstevel@tonic-gate 			msg32.len = msg->len;
64777c478bd9Sstevel@tonic-gate 		msg32.off = msg->off;
64787c478bd9Sstevel@tonic-gate 		msg32.perm = msg->perm;
64797c478bd9Sstevel@tonic-gate 		msg32.gnum = msg->gnum;
64807c478bd9Sstevel@tonic-gate 		msg32.rnum = msg->rnum;
64817c478bd9Sstevel@tonic-gate 
64827c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
64837c478bd9Sstevel@tonic-gate 		    "rsm_connect done\n"));
64847c478bd9Sstevel@tonic-gate 
64857c478bd9Sstevel@tonic-gate 		if (ddi_copyout((caddr_t)&msg32, (caddr_t)dataptr,
64867c478bd9Sstevel@tonic-gate 		    sizeof (msg32), mode))
64877c478bd9Sstevel@tonic-gate 			return (RSMERR_BAD_ADDR);
64887c478bd9Sstevel@tonic-gate 		else
64897c478bd9Sstevel@tonic-gate 			return (RSM_SUCCESS);
64907c478bd9Sstevel@tonic-gate 	}
64917c478bd9Sstevel@tonic-gate #endif
64927c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_connect done\n"));
64937c478bd9Sstevel@tonic-gate 
64947c478bd9Sstevel@tonic-gate 	if (ddi_copyout((caddr_t)msg, (caddr_t)dataptr, sizeof (*msg),
64957c478bd9Sstevel@tonic-gate 	    mode))
64967c478bd9Sstevel@tonic-gate 		return (RSMERR_BAD_ADDR);
64977c478bd9Sstevel@tonic-gate 	else
64987c478bd9Sstevel@tonic-gate 		return (RSM_SUCCESS);
64997c478bd9Sstevel@tonic-gate }
65007c478bd9Sstevel@tonic-gate 
65017c478bd9Sstevel@tonic-gate static int
rsm_unmap(rsmseg_t * seg)65027c478bd9Sstevel@tonic-gate rsm_unmap(rsmseg_t *seg)
65037c478bd9Sstevel@tonic-gate {
65047c478bd9Sstevel@tonic-gate 	int			err;
65057c478bd9Sstevel@tonic-gate 	adapter_t		*adapter;
65067c478bd9Sstevel@tonic-gate 	rsm_import_share_t	*sharedp;
65077c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_IMPORT);
65087c478bd9Sstevel@tonic-gate 
65097c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
65107c478bd9Sstevel@tonic-gate 	    "rsm_unmap enter %u\n", seg->s_segid));
65117c478bd9Sstevel@tonic-gate 
65127c478bd9Sstevel@tonic-gate 	ASSERT(seg->s_hdr.rsmrc_type == RSM_RESOURCE_IMPORT_SEGMENT);
65137c478bd9Sstevel@tonic-gate 
65147c478bd9Sstevel@tonic-gate 	/* assert seg is locked */
65157c478bd9Sstevel@tonic-gate 	ASSERT(rsmseglock_held(seg));
65167c478bd9Sstevel@tonic-gate 	ASSERT(seg->s_state != RSM_STATE_MAPPING);
65177c478bd9Sstevel@tonic-gate 
65187c478bd9Sstevel@tonic-gate 	if ((seg->s_state != RSM_STATE_ACTIVE) &&
65197c478bd9Sstevel@tonic-gate 	    (seg->s_state != RSM_STATE_MAP_QUIESCE)) {
65207c478bd9Sstevel@tonic-gate 		/* segment unmap has already been done */
65217c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_unmap done\n"));
65227c478bd9Sstevel@tonic-gate 		return (RSM_SUCCESS);
65237c478bd9Sstevel@tonic-gate 	}
65247c478bd9Sstevel@tonic-gate 
65257c478bd9Sstevel@tonic-gate 	sharedp = seg->s_share;
65267c478bd9Sstevel@tonic-gate 
65277c478bd9Sstevel@tonic-gate 	rsmsharelock_acquire(seg);
65287c478bd9Sstevel@tonic-gate 
65297c478bd9Sstevel@tonic-gate 	/*
65307c478bd9Sstevel@tonic-gate 	 *	- shared data struct is in MAPPED or MAP_QUIESCE state
65317c478bd9Sstevel@tonic-gate 	 */
65327c478bd9Sstevel@tonic-gate 
65337c478bd9Sstevel@tonic-gate 	ASSERT(sharedp->rsmsi_state == RSMSI_STATE_MAPPED ||
65347c478bd9Sstevel@tonic-gate 	    sharedp->rsmsi_state == RSMSI_STATE_MAP_QUIESCE);
65357c478bd9Sstevel@tonic-gate 
65367c478bd9Sstevel@tonic-gate 	/*
65377c478bd9Sstevel@tonic-gate 	 * Unmap pages - previously rsm_memseg_import_unmap was called only if
65387c478bd9Sstevel@tonic-gate 	 * the segment cookie list was NULL; but it is always NULL when
65397c478bd9Sstevel@tonic-gate 	 * called from rsmmap_unmap and won't be NULL when called for
65407c478bd9Sstevel@tonic-gate 	 * a force disconnect - so the check for NULL cookie list was removed
65417c478bd9Sstevel@tonic-gate 	 */
65427c478bd9Sstevel@tonic-gate 
65437c478bd9Sstevel@tonic-gate 	ASSERT(sharedp->rsmsi_mapcnt > 0);
65447c478bd9Sstevel@tonic-gate 
65457c478bd9Sstevel@tonic-gate 	sharedp->rsmsi_mapcnt--;
65467c478bd9Sstevel@tonic-gate 
65477c478bd9Sstevel@tonic-gate 	if (sharedp->rsmsi_mapcnt == 0) {
65487c478bd9Sstevel@tonic-gate 		if (sharedp->rsmsi_state == RSMSI_STATE_MAPPED) {
65497c478bd9Sstevel@tonic-gate 			/* unmap the shared RSMPI mapping */
65507c478bd9Sstevel@tonic-gate 			adapter = seg->s_adapter;
65517c478bd9Sstevel@tonic-gate 			if (seg->s_node != my_nodeid) {
65527c478bd9Sstevel@tonic-gate 				ASSERT(sharedp->rsmsi_handle != NULL);
65537c478bd9Sstevel@tonic-gate 				err = adapter->rsmpi_ops->
65547c478bd9Sstevel@tonic-gate 				    rsm_unmap(sharedp->rsmsi_handle);
65557c478bd9Sstevel@tonic-gate 				DBG_PRINTF((category, RSM_DEBUG,
65567c478bd9Sstevel@tonic-gate 				    "rsm_unmap: rsmpi unmap %d\n", err));
65577c478bd9Sstevel@tonic-gate 				rsm_free_mapinfo(sharedp->rsmsi_mapinfo);
65587c478bd9Sstevel@tonic-gate 				sharedp->rsmsi_mapinfo = NULL;
65597c478bd9Sstevel@tonic-gate 			}
65607c478bd9Sstevel@tonic-gate 			sharedp->rsmsi_state = RSMSI_STATE_CONNECTED;
65617c478bd9Sstevel@tonic-gate 		} else { /* MAP_QUIESCE --munmap()--> CONN_QUIESCE */
65627c478bd9Sstevel@tonic-gate 			sharedp->rsmsi_state = RSMSI_STATE_CONN_QUIESCE;
65637c478bd9Sstevel@tonic-gate 		}
65647c478bd9Sstevel@tonic-gate 	}
65657c478bd9Sstevel@tonic-gate 
65667c478bd9Sstevel@tonic-gate 	rsmsharelock_release(seg);
65677c478bd9Sstevel@tonic-gate 
65687c478bd9Sstevel@tonic-gate 	/*
65697c478bd9Sstevel@tonic-gate 	 * The s_cookie field is used to store the cookie returned from the
65707c478bd9Sstevel@tonic-gate 	 * ddi_umem_lock when binding the pages for an export segment. This
65717c478bd9Sstevel@tonic-gate 	 * is the primary use of the s_cookie field and does not normally
65727c478bd9Sstevel@tonic-gate 	 * pertain to any importing segment except in the loopback case.
65737c478bd9Sstevel@tonic-gate 	 * For the loopback case, the import segment and export segment are
65747c478bd9Sstevel@tonic-gate 	 * on the same node, the s_cookie field of the segment structure for
65757c478bd9Sstevel@tonic-gate 	 * the importer is initialized to the s_cookie field in the exported
65767c478bd9Sstevel@tonic-gate 	 * segment during the map operation and is used during the call to
65777c478bd9Sstevel@tonic-gate 	 * devmap_umem_setup for the import mapping.
65787c478bd9Sstevel@tonic-gate 	 * Thus, during unmap, we simply need to set s_cookie to NULL to
65797c478bd9Sstevel@tonic-gate 	 * indicate that the mapping no longer exists.
65807c478bd9Sstevel@tonic-gate 	 */
65817c478bd9Sstevel@tonic-gate 	seg->s_cookie = NULL;
65827c478bd9Sstevel@tonic-gate 
65837c478bd9Sstevel@tonic-gate 	seg->s_mapinfo = NULL;
65847c478bd9Sstevel@tonic-gate 
65857c478bd9Sstevel@tonic-gate 	if (seg->s_state == RSM_STATE_ACTIVE)
65867c478bd9Sstevel@tonic-gate 		seg->s_state = RSM_STATE_CONNECT;
65877c478bd9Sstevel@tonic-gate 	else
65887c478bd9Sstevel@tonic-gate 		seg->s_state = RSM_STATE_CONN_QUIESCE;
65897c478bd9Sstevel@tonic-gate 
65907c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_unmap done\n"));
65917c478bd9Sstevel@tonic-gate 
65927c478bd9Sstevel@tonic-gate 	return (RSM_SUCCESS);
65937c478bd9Sstevel@tonic-gate }
65947c478bd9Sstevel@tonic-gate 
65957c478bd9Sstevel@tonic-gate /*
65967c478bd9Sstevel@tonic-gate  * cookie returned here if not null indicates that it is
65977c478bd9Sstevel@tonic-gate  * the last importer and it can be used in the RSMIPC_NOT_IMPORTING
65987c478bd9Sstevel@tonic-gate  * message.
65997c478bd9Sstevel@tonic-gate  */
66007c478bd9Sstevel@tonic-gate static int
rsm_closeconnection(rsmseg_t * seg,void ** cookie)66017c478bd9Sstevel@tonic-gate rsm_closeconnection(rsmseg_t *seg, void **cookie)
66027c478bd9Sstevel@tonic-gate {
66037c478bd9Sstevel@tonic-gate 	int			e;
66047c478bd9Sstevel@tonic-gate 	adapter_t		*adapter;
66057c478bd9Sstevel@tonic-gate 	rsm_import_share_t	*sharedp;
66067c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_IMPORT);
66077c478bd9Sstevel@tonic-gate 
66087c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
66097c478bd9Sstevel@tonic-gate 	    "rsm_closeconnection enter\n"));
66107c478bd9Sstevel@tonic-gate 
66117c478bd9Sstevel@tonic-gate 	*cookie = (void *)NULL;
66127c478bd9Sstevel@tonic-gate 
66137c478bd9Sstevel@tonic-gate 	ASSERT(seg->s_hdr.rsmrc_type == RSM_RESOURCE_IMPORT_SEGMENT);
66147c478bd9Sstevel@tonic-gate 
66157c478bd9Sstevel@tonic-gate 	/* assert seg is locked */
66167c478bd9Sstevel@tonic-gate 	ASSERT(rsmseglock_held(seg));
66177c478bd9Sstevel@tonic-gate 
66187c478bd9Sstevel@tonic-gate 	if (seg->s_state == RSM_STATE_DISCONNECT) {
66197c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
66207c478bd9Sstevel@tonic-gate 		    "rsm_closeconnection done: already disconnected\n"));
66217c478bd9Sstevel@tonic-gate 		return (RSM_SUCCESS);
66227c478bd9Sstevel@tonic-gate 	}
66237c478bd9Sstevel@tonic-gate 
66247c478bd9Sstevel@tonic-gate 	/* wait for all putv/getv ops to get done */
66257c478bd9Sstevel@tonic-gate 	while (seg->s_rdmacnt > 0) {
66267c478bd9Sstevel@tonic-gate 		cv_wait(&seg->s_cv, &seg->s_lock);
66277c478bd9Sstevel@tonic-gate 	}
66287c478bd9Sstevel@tonic-gate 
66297c478bd9Sstevel@tonic-gate 	(void) rsm_unmap(seg);
66307c478bd9Sstevel@tonic-gate 
66317c478bd9Sstevel@tonic-gate 	ASSERT(seg->s_state == RSM_STATE_CONNECT ||
66327c478bd9Sstevel@tonic-gate 	    seg->s_state == RSM_STATE_CONN_QUIESCE);
66337c478bd9Sstevel@tonic-gate 
66347c478bd9Sstevel@tonic-gate 	adapter = seg->s_adapter;
66357c478bd9Sstevel@tonic-gate 	sharedp = seg->s_share;
66367c478bd9Sstevel@tonic-gate 
66377c478bd9Sstevel@tonic-gate 	ASSERT(sharedp != NULL);
66387c478bd9Sstevel@tonic-gate 
66397c478bd9Sstevel@tonic-gate 	rsmsharelock_acquire(seg);
66407c478bd9Sstevel@tonic-gate 
66417c478bd9Sstevel@tonic-gate 	/*
66427c478bd9Sstevel@tonic-gate 	 * Disconnect on adapter
66437c478bd9Sstevel@tonic-gate 	 *
66447c478bd9Sstevel@tonic-gate 	 * The current algorithm is stateless, I don't have to contact
66457c478bd9Sstevel@tonic-gate 	 * server when I go away. He only gives me permissions. Of course,
66467c478bd9Sstevel@tonic-gate 	 * the adapters will talk to terminate the connect.
66477c478bd9Sstevel@tonic-gate 	 *
66487c478bd9Sstevel@tonic-gate 	 * disconnect is needed only if we are CONNECTED not in CONN_QUIESCE
66497c478bd9Sstevel@tonic-gate 	 */
66507c478bd9Sstevel@tonic-gate 	if ((sharedp->rsmsi_state == RSMSI_STATE_CONNECTED) &&
66517c478bd9Sstevel@tonic-gate 	    (sharedp->rsmsi_node != my_nodeid)) {
66527c478bd9Sstevel@tonic-gate 
66537c478bd9Sstevel@tonic-gate 		if (sharedp->rsmsi_refcnt == 1) {
66547c478bd9Sstevel@tonic-gate 			/* this is the last importer */
66557c478bd9Sstevel@tonic-gate 			ASSERT(sharedp->rsmsi_mapcnt == 0);
66567c478bd9Sstevel@tonic-gate 
66577c478bd9Sstevel@tonic-gate 			e = adapter->rsmpi_ops->
66587c478bd9Sstevel@tonic-gate 			    rsm_disconnect(sharedp->rsmsi_handle);
66597c478bd9Sstevel@tonic-gate 			if (e != RSM_SUCCESS) {
66607c478bd9Sstevel@tonic-gate 				DBG_PRINTF((category, RSM_DEBUG,
66617c478bd9Sstevel@tonic-gate 				    "rsm:disconnect failed seg=%x:err=%d\n",
66627c478bd9Sstevel@tonic-gate 				    seg->s_key, e));
66637c478bd9Sstevel@tonic-gate 			}
66647c478bd9Sstevel@tonic-gate 		}
66657c478bd9Sstevel@tonic-gate 	}
66667c478bd9Sstevel@tonic-gate 
66677c478bd9Sstevel@tonic-gate 	seg->s_handle.in = NULL;
66687c478bd9Sstevel@tonic-gate 
66697c478bd9Sstevel@tonic-gate 	sharedp->rsmsi_refcnt--;
66707c478bd9Sstevel@tonic-gate 
66717c478bd9Sstevel@tonic-gate 	if (sharedp->rsmsi_refcnt == 0) {
66727c478bd9Sstevel@tonic-gate 		*cookie = (void *)sharedp->rsmsi_cookie;
66737c478bd9Sstevel@tonic-gate 		sharedp->rsmsi_state = RSMSI_STATE_DISCONNECTED;
66747c478bd9Sstevel@tonic-gate 		sharedp->rsmsi_handle = NULL;
66757c478bd9Sstevel@tonic-gate 		rsmsharelock_release(seg);
66767c478bd9Sstevel@tonic-gate 
66777c478bd9Sstevel@tonic-gate 		/* clean up the shared data structure */
66787c478bd9Sstevel@tonic-gate 		mutex_destroy(&sharedp->rsmsi_lock);
66797c478bd9Sstevel@tonic-gate 		cv_destroy(&sharedp->rsmsi_cv);
66807c478bd9Sstevel@tonic-gate 		kmem_free((void *)(sharedp), sizeof (rsm_import_share_t));
66817c478bd9Sstevel@tonic-gate 
66827c478bd9Sstevel@tonic-gate 	} else {
66837c478bd9Sstevel@tonic-gate 		rsmsharelock_release(seg);
66847c478bd9Sstevel@tonic-gate 	}
66857c478bd9Sstevel@tonic-gate 
66867c478bd9Sstevel@tonic-gate 	/* increment generation number on barrier page */
66877c478bd9Sstevel@tonic-gate 	if (bar_va) {
6688*1a5e258fSJosef 'Jeff' Sipek 		atomic_inc_16(bar_va + seg->s_hdr.rsmrc_num);
66897c478bd9Sstevel@tonic-gate 	}
66907c478bd9Sstevel@tonic-gate 
66917c478bd9Sstevel@tonic-gate 	/*
66927c478bd9Sstevel@tonic-gate 	 * The following needs to be done after any
66937c478bd9Sstevel@tonic-gate 	 * rsmsharelock calls which use seg->s_share.
66947c478bd9Sstevel@tonic-gate 	 */
66957c478bd9Sstevel@tonic-gate 	seg->s_share = NULL;
66967c478bd9Sstevel@tonic-gate 
66977c478bd9Sstevel@tonic-gate 	seg->s_state = RSM_STATE_DISCONNECT;
66987c478bd9Sstevel@tonic-gate 	/* signal anyone waiting in the CONN_QUIESCE state */
66997c478bd9Sstevel@tonic-gate 	cv_broadcast(&seg->s_cv);
67007c478bd9Sstevel@tonic-gate 
67017c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
67027c478bd9Sstevel@tonic-gate 	    "rsm_closeconnection done\n"));
67037c478bd9Sstevel@tonic-gate 
67047c478bd9Sstevel@tonic-gate 	return (RSM_SUCCESS);
67057c478bd9Sstevel@tonic-gate }
67067c478bd9Sstevel@tonic-gate 
67077c478bd9Sstevel@tonic-gate int
rsm_disconnect(rsmseg_t * seg)67087c478bd9Sstevel@tonic-gate rsm_disconnect(rsmseg_t *seg)
67097c478bd9Sstevel@tonic-gate {
67107c478bd9Sstevel@tonic-gate 	rsmipc_request_t	request;
67117c478bd9Sstevel@tonic-gate 	void			*shared_cookie;
67127c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_IMPORT);
67137c478bd9Sstevel@tonic-gate 
67147c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_disconnect enter\n"));
67157c478bd9Sstevel@tonic-gate 
67167c478bd9Sstevel@tonic-gate 	ASSERT(seg->s_hdr.rsmrc_type == RSM_RESOURCE_IMPORT_SEGMENT);
67177c478bd9Sstevel@tonic-gate 
67187c478bd9Sstevel@tonic-gate 	/* assert seg isn't locked */
67197c478bd9Sstevel@tonic-gate 	ASSERT(!rsmseglock_held(seg));
67207c478bd9Sstevel@tonic-gate 
67217c478bd9Sstevel@tonic-gate 
67227c478bd9Sstevel@tonic-gate 	/* Remove segment from imported list */
67237c478bd9Sstevel@tonic-gate 	rsmimport_rm(seg);
67247c478bd9Sstevel@tonic-gate 
67257c478bd9Sstevel@tonic-gate 	/* acquire the segment */
67267c478bd9Sstevel@tonic-gate 	rsmseglock_acquire(seg);
67277c478bd9Sstevel@tonic-gate 
67287c478bd9Sstevel@tonic-gate 	/* wait until segment leaves the mapping state */
67297c478bd9Sstevel@tonic-gate 	while (seg->s_state == RSM_STATE_MAPPING)
67307c478bd9Sstevel@tonic-gate 		cv_wait(&seg->s_cv, &seg->s_lock);
67317c478bd9Sstevel@tonic-gate 
67327c478bd9Sstevel@tonic-gate 	if (seg->s_state == RSM_STATE_DISCONNECT) {
67337c478bd9Sstevel@tonic-gate 		seg->s_state = RSM_STATE_NEW;
67347c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
67357c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
67367c478bd9Sstevel@tonic-gate 		    "rsm_disconnect done: already disconnected\n"));
67377c478bd9Sstevel@tonic-gate 		return (RSM_SUCCESS);
67387c478bd9Sstevel@tonic-gate 	}
67397c478bd9Sstevel@tonic-gate 
67407c478bd9Sstevel@tonic-gate 	(void) rsm_closeconnection(seg, &shared_cookie);
67417c478bd9Sstevel@tonic-gate 
67427c478bd9Sstevel@tonic-gate 	/* update state */
67437c478bd9Sstevel@tonic-gate 	seg->s_state = RSM_STATE_NEW;
67447c478bd9Sstevel@tonic-gate 
67457c478bd9Sstevel@tonic-gate 	if (shared_cookie != NULL) {
67467c478bd9Sstevel@tonic-gate 		/*
67477c478bd9Sstevel@tonic-gate 		 *  This is the last importer so inform the exporting node
67487c478bd9Sstevel@tonic-gate 		 *  so this import can be deleted from the list of importers.
67497c478bd9Sstevel@tonic-gate 		 */
67507c478bd9Sstevel@tonic-gate 		request.rsmipc_hdr.rsmipc_type = RSMIPC_MSG_NOTIMPORTING;
67517c478bd9Sstevel@tonic-gate 		request.rsmipc_key = seg->s_segid;
67527c478bd9Sstevel@tonic-gate 		request.rsmipc_segment_cookie = shared_cookie;
67537c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
67547c478bd9Sstevel@tonic-gate 		(void) rsmipc_send(seg->s_node, &request, RSM_NO_REPLY);
67557c478bd9Sstevel@tonic-gate 	} else {
67567c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
67577c478bd9Sstevel@tonic-gate 	}
67587c478bd9Sstevel@tonic-gate 
67597c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_disconnect done\n"));
67607c478bd9Sstevel@tonic-gate 
67617c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
67627c478bd9Sstevel@tonic-gate }
67637c478bd9Sstevel@tonic-gate 
67647c478bd9Sstevel@tonic-gate /*ARGSUSED*/
67657c478bd9Sstevel@tonic-gate static int
rsm_chpoll(dev_t dev,short events,int anyyet,short * reventsp,struct pollhead ** phpp)67667c478bd9Sstevel@tonic-gate rsm_chpoll(dev_t dev, short events, int anyyet, short *reventsp,
67677c478bd9Sstevel@tonic-gate     struct pollhead **phpp)
67687c478bd9Sstevel@tonic-gate {
67697c478bd9Sstevel@tonic-gate 	minor_t		rnum;
67707c478bd9Sstevel@tonic-gate 	rsmresource_t	*res;
67717c478bd9Sstevel@tonic-gate 	rsmseg_t 	*seg;
67727c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_DDI);
67737c478bd9Sstevel@tonic-gate 
67747c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_chpoll enter\n"));
67757c478bd9Sstevel@tonic-gate 
67767c478bd9Sstevel@tonic-gate 	/* find minor, no lock */
67777c478bd9Sstevel@tonic-gate 	rnum = getminor(dev);
67787c478bd9Sstevel@tonic-gate 	res = rsmresource_lookup(rnum, RSM_NOLOCK);
67797c478bd9Sstevel@tonic-gate 
67807c478bd9Sstevel@tonic-gate 	/* poll is supported only for export/import segments */
67817c478bd9Sstevel@tonic-gate 	if ((res == NULL) || (res == RSMRC_RESERVED) ||
67827c478bd9Sstevel@tonic-gate 	    (res->rsmrc_type == RSM_RESOURCE_BAR)) {
67837c478bd9Sstevel@tonic-gate 		return (ENXIO);
67847c478bd9Sstevel@tonic-gate 	}
67857c478bd9Sstevel@tonic-gate 
67867c478bd9Sstevel@tonic-gate 	*reventsp = 0;
67877c478bd9Sstevel@tonic-gate 
67887c478bd9Sstevel@tonic-gate 	/*
67897c478bd9Sstevel@tonic-gate 	 * An exported segment must be in state RSM_STATE_EXPORT; an
67907c478bd9Sstevel@tonic-gate 	 * imported segment must be in state RSM_STATE_ACTIVE.
67917c478bd9Sstevel@tonic-gate 	 */
67927c478bd9Sstevel@tonic-gate 	seg = (rsmseg_t *)res;
67937c478bd9Sstevel@tonic-gate 
67947c478bd9Sstevel@tonic-gate 	if (seg->s_pollevent) {
67957c478bd9Sstevel@tonic-gate 		*reventsp = POLLRDNORM;
67967c478bd9Sstevel@tonic-gate 	} else if (!anyyet) {
67977c478bd9Sstevel@tonic-gate 		/* cannot take segment lock here */
67987c478bd9Sstevel@tonic-gate 		*phpp = &seg->s_poll;
67997c478bd9Sstevel@tonic-gate 		seg->s_pollflag |= RSM_SEGMENT_POLL;
68007c478bd9Sstevel@tonic-gate 	}
68017c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_chpoll done\n"));
68027c478bd9Sstevel@tonic-gate 	return (0);
68037c478bd9Sstevel@tonic-gate }
68047c478bd9Sstevel@tonic-gate 
68057c478bd9Sstevel@tonic-gate 
68067c478bd9Sstevel@tonic-gate 
68077c478bd9Sstevel@tonic-gate /* ************************* IOCTL Commands ********************* */
68087c478bd9Sstevel@tonic-gate 
68097c478bd9Sstevel@tonic-gate static rsmseg_t *
rsmresource_seg(rsmresource_t * res,minor_t rnum,cred_t * credp,rsm_resource_type_t type)68107c478bd9Sstevel@tonic-gate rsmresource_seg(rsmresource_t *res, minor_t rnum, cred_t *credp,
68117c478bd9Sstevel@tonic-gate     rsm_resource_type_t type)
68127c478bd9Sstevel@tonic-gate {
68137c478bd9Sstevel@tonic-gate 	/* get segment from resource handle */
68147c478bd9Sstevel@tonic-gate 	rsmseg_t *seg;
68157c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_IOCTL);
68167c478bd9Sstevel@tonic-gate 
68177c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmresource_seg enter\n"));
68187c478bd9Sstevel@tonic-gate 
68197c478bd9Sstevel@tonic-gate 
68207c478bd9Sstevel@tonic-gate 	if (res != RSMRC_RESERVED) {
68217c478bd9Sstevel@tonic-gate 		seg = (rsmseg_t *)res;
68227c478bd9Sstevel@tonic-gate 	} else {
68237c478bd9Sstevel@tonic-gate 		/* Allocate segment now and bind it */
68247c478bd9Sstevel@tonic-gate 		seg = rsmseg_alloc(rnum, credp);
68257c478bd9Sstevel@tonic-gate 
68267c478bd9Sstevel@tonic-gate 		/*
68277c478bd9Sstevel@tonic-gate 		 * if DR pre-processing is going on or DR is in progress
68287c478bd9Sstevel@tonic-gate 		 * then the new export segments should be in the NEW_QSCD state
68297c478bd9Sstevel@tonic-gate 		 */
68307c478bd9Sstevel@tonic-gate 		if (type == RSM_RESOURCE_EXPORT_SEGMENT) {
68317c478bd9Sstevel@tonic-gate 			mutex_enter(&rsm_drv_data.drv_lock);
68327c478bd9Sstevel@tonic-gate 			if ((rsm_drv_data.drv_state ==
68337c478bd9Sstevel@tonic-gate 			    RSM_DRV_PREDEL_STARTED) ||
68347c478bd9Sstevel@tonic-gate 			    (rsm_drv_data.drv_state ==
68357c478bd9Sstevel@tonic-gate 			    RSM_DRV_PREDEL_COMPLETED) ||
68367c478bd9Sstevel@tonic-gate 			    (rsm_drv_data.drv_state ==
68377c478bd9Sstevel@tonic-gate 			    RSM_DRV_DR_IN_PROGRESS)) {
68387c478bd9Sstevel@tonic-gate 				seg->s_state = RSM_STATE_NEW_QUIESCED;
68397c478bd9Sstevel@tonic-gate 			}
68407c478bd9Sstevel@tonic-gate 			mutex_exit(&rsm_drv_data.drv_lock);
68417c478bd9Sstevel@tonic-gate 		}
68427c478bd9Sstevel@tonic-gate 
68437c478bd9Sstevel@tonic-gate 		rsmresource_insert(rnum, (rsmresource_t *)seg, type);
68447c478bd9Sstevel@tonic-gate 	}
68457c478bd9Sstevel@tonic-gate 
68467c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmresource_seg done\n"));
68477c478bd9Sstevel@tonic-gate 
68487c478bd9Sstevel@tonic-gate 	return (seg);
68497c478bd9Sstevel@tonic-gate }
68507c478bd9Sstevel@tonic-gate 
68517c478bd9Sstevel@tonic-gate static int
rsmexport_ioctl(rsmseg_t * seg,rsm_ioctlmsg_t * msg,int cmd,intptr_t arg,int mode,cred_t * credp)68527c478bd9Sstevel@tonic-gate rsmexport_ioctl(rsmseg_t *seg, rsm_ioctlmsg_t *msg, int cmd, intptr_t arg,
68537c478bd9Sstevel@tonic-gate     int mode, cred_t *credp)
68547c478bd9Sstevel@tonic-gate {
68557c478bd9Sstevel@tonic-gate 	int error;
68567c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_EXPORT | RSM_IOCTL);
68577c478bd9Sstevel@tonic-gate 
68587c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmexport_ioctl enter\n"));
68597c478bd9Sstevel@tonic-gate 
68607c478bd9Sstevel@tonic-gate 	arg = arg;
68617c478bd9Sstevel@tonic-gate 	credp = credp;
68627c478bd9Sstevel@tonic-gate 
68637c478bd9Sstevel@tonic-gate 	ASSERT(seg != NULL);
68647c478bd9Sstevel@tonic-gate 
68657c478bd9Sstevel@tonic-gate 	switch (cmd) {
68667c478bd9Sstevel@tonic-gate 	case RSM_IOCTL_BIND:
68677c478bd9Sstevel@tonic-gate 		error = rsm_bind(seg, msg, arg, mode);
68687c478bd9Sstevel@tonic-gate 		break;
68697c478bd9Sstevel@tonic-gate 	case RSM_IOCTL_REBIND:
68707c478bd9Sstevel@tonic-gate 		error = rsm_rebind(seg, msg);
68717c478bd9Sstevel@tonic-gate 		break;
68727c478bd9Sstevel@tonic-gate 	case RSM_IOCTL_UNBIND:
68737c478bd9Sstevel@tonic-gate 		error = ENOTSUP;
68747c478bd9Sstevel@tonic-gate 		break;
68757c478bd9Sstevel@tonic-gate 	case RSM_IOCTL_PUBLISH:
68767c478bd9Sstevel@tonic-gate 		error = rsm_publish(seg, msg, arg, mode);
68777c478bd9Sstevel@tonic-gate 		break;
68787c478bd9Sstevel@tonic-gate 	case RSM_IOCTL_REPUBLISH:
68797c478bd9Sstevel@tonic-gate 		error = rsm_republish(seg, msg, mode);
68807c478bd9Sstevel@tonic-gate 		break;
68817c478bd9Sstevel@tonic-gate 	case RSM_IOCTL_UNPUBLISH:
68827c478bd9Sstevel@tonic-gate 		error = rsm_unpublish(seg, 1);
68837c478bd9Sstevel@tonic-gate 		break;
68847c478bd9Sstevel@tonic-gate 	default:
68857c478bd9Sstevel@tonic-gate 		error = EINVAL;
68867c478bd9Sstevel@tonic-gate 		break;
68877c478bd9Sstevel@tonic-gate 	}
68887c478bd9Sstevel@tonic-gate 
68897c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmexport_ioctl done: %d\n",
68907c478bd9Sstevel@tonic-gate 	    error));
68917c478bd9Sstevel@tonic-gate 
68927c478bd9Sstevel@tonic-gate 	return (error);
68937c478bd9Sstevel@tonic-gate }
68947c478bd9Sstevel@tonic-gate static int
rsmimport_ioctl(rsmseg_t * seg,rsm_ioctlmsg_t * msg,int cmd,intptr_t arg,int mode,cred_t * credp)68957c478bd9Sstevel@tonic-gate rsmimport_ioctl(rsmseg_t *seg, rsm_ioctlmsg_t *msg, int cmd, intptr_t arg,
68967c478bd9Sstevel@tonic-gate     int mode, cred_t *credp)
68977c478bd9Sstevel@tonic-gate {
68987c478bd9Sstevel@tonic-gate 	int error;
68997c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_IMPORT | RSM_IOCTL);
69007c478bd9Sstevel@tonic-gate 
69017c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmimport_ioctl enter\n"));
69027c478bd9Sstevel@tonic-gate 
69037c478bd9Sstevel@tonic-gate 	ASSERT(seg);
69047c478bd9Sstevel@tonic-gate 
69057c478bd9Sstevel@tonic-gate 	switch (cmd) {
69067c478bd9Sstevel@tonic-gate 	case RSM_IOCTL_CONNECT:
69077c478bd9Sstevel@tonic-gate 		error = rsm_connect(seg, msg, credp, arg, mode);
69087c478bd9Sstevel@tonic-gate 		break;
69097c478bd9Sstevel@tonic-gate 	default:
69107c478bd9Sstevel@tonic-gate 		error = EINVAL;
69117c478bd9Sstevel@tonic-gate 		break;
69127c478bd9Sstevel@tonic-gate 	}
69137c478bd9Sstevel@tonic-gate 
69147c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmimport_ioctl done: %d\n",
69157c478bd9Sstevel@tonic-gate 	    error));
69167c478bd9Sstevel@tonic-gate 	return (error);
69177c478bd9Sstevel@tonic-gate }
69187c478bd9Sstevel@tonic-gate 
69197c478bd9Sstevel@tonic-gate static int
rsmbar_ioctl(rsmseg_t * seg,rsm_ioctlmsg_t * msg,int cmd,intptr_t arg,int mode)69207c478bd9Sstevel@tonic-gate rsmbar_ioctl(rsmseg_t *seg, rsm_ioctlmsg_t *msg, int cmd, intptr_t arg,
69217c478bd9Sstevel@tonic-gate     int mode)
69227c478bd9Sstevel@tonic-gate {
69237c478bd9Sstevel@tonic-gate 	int e;
69247c478bd9Sstevel@tonic-gate 	adapter_t *adapter;
69257c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_IMPORT | RSM_IOCTL);
69267c478bd9Sstevel@tonic-gate 
69277c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmbar_ioctl enter\n"));
69287c478bd9Sstevel@tonic-gate 
69297c478bd9Sstevel@tonic-gate 
69307c478bd9Sstevel@tonic-gate 	if ((seg->s_flags & RSM_IMPORT_DUMMY) != 0) {
69317c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
69327c478bd9Sstevel@tonic-gate 		    "rsmbar_ioctl done: RSM_IMPORT_DUMMY\n"));
69337c478bd9Sstevel@tonic-gate 		return (RSMERR_CONN_ABORTED);
69347c478bd9Sstevel@tonic-gate 	} else if (seg->s_node == my_nodeid) {
69357c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
69367c478bd9Sstevel@tonic-gate 		    "rsmbar_ioctl done: loopback\n"));
69377c478bd9Sstevel@tonic-gate 		return (RSM_SUCCESS);
69387c478bd9Sstevel@tonic-gate 	}
69397c478bd9Sstevel@tonic-gate 
69407c478bd9Sstevel@tonic-gate 	adapter = seg->s_adapter;
69417c478bd9Sstevel@tonic-gate 
69427c478bd9Sstevel@tonic-gate 	switch (cmd) {
69437c478bd9Sstevel@tonic-gate 	case RSM_IOCTL_BAR_CHECK:
69447c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
69457c478bd9Sstevel@tonic-gate 		    "rsmbar_ioctl done: RSM_BAR_CHECK %d\n", bar_va));
69467c478bd9Sstevel@tonic-gate 		return (bar_va ? RSM_SUCCESS : EINVAL);
69477c478bd9Sstevel@tonic-gate 	case RSM_IOCTL_BAR_OPEN:
69487c478bd9Sstevel@tonic-gate 		e = adapter->rsmpi_ops->
69497c478bd9Sstevel@tonic-gate 		    rsm_open_barrier_ctrl(adapter->rsmpi_handle, &msg->bar);
69507c478bd9Sstevel@tonic-gate 		break;
69517c478bd9Sstevel@tonic-gate 	case RSM_IOCTL_BAR_ORDER:
69527c478bd9Sstevel@tonic-gate 		e = adapter->rsmpi_ops->rsm_order_barrier(&msg->bar);
69537c478bd9Sstevel@tonic-gate 		break;
69547c478bd9Sstevel@tonic-gate 	case RSM_IOCTL_BAR_CLOSE:
69557c478bd9Sstevel@tonic-gate 		e = adapter->rsmpi_ops->rsm_close_barrier(&msg->bar);
69567c478bd9Sstevel@tonic-gate 		break;
69577c478bd9Sstevel@tonic-gate 	default:
69587c478bd9Sstevel@tonic-gate 		e = EINVAL;
69597c478bd9Sstevel@tonic-gate 		break;
69607c478bd9Sstevel@tonic-gate 	}
69617c478bd9Sstevel@tonic-gate 
69627c478bd9Sstevel@tonic-gate 	if (e == RSM_SUCCESS) {
69637c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
69647c478bd9Sstevel@tonic-gate 		if ((mode & DATAMODEL_MASK) == DATAMODEL_ILP32) {
69657c478bd9Sstevel@tonic-gate 			rsm_ioctlmsg32_t msg32;
69667c478bd9Sstevel@tonic-gate 			int i;
69677c478bd9Sstevel@tonic-gate 
69687c478bd9Sstevel@tonic-gate 			for (i = 0; i < 4; i++) {
69697c478bd9Sstevel@tonic-gate 				msg32.bar.comp[i].u64 = msg->bar.comp[i].u64;
69707c478bd9Sstevel@tonic-gate 			}
69717c478bd9Sstevel@tonic-gate 
69727c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
69737c478bd9Sstevel@tonic-gate 			    "rsmbar_ioctl done\n"));
69747c478bd9Sstevel@tonic-gate 			if (ddi_copyout((caddr_t)&msg32, (caddr_t)arg,
69757c478bd9Sstevel@tonic-gate 			    sizeof (msg32), mode))
69767c478bd9Sstevel@tonic-gate 				return (RSMERR_BAD_ADDR);
69777c478bd9Sstevel@tonic-gate 			else
69787c478bd9Sstevel@tonic-gate 				return (RSM_SUCCESS);
69797c478bd9Sstevel@tonic-gate 		}
69807c478bd9Sstevel@tonic-gate #endif
69817c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
69827c478bd9Sstevel@tonic-gate 		    "rsmbar_ioctl done\n"));
69837c478bd9Sstevel@tonic-gate 		if (ddi_copyout((caddr_t)&msg->bar, (caddr_t)arg,
69847c478bd9Sstevel@tonic-gate 		    sizeof (*msg), mode))
69857c478bd9Sstevel@tonic-gate 			return (RSMERR_BAD_ADDR);
69867c478bd9Sstevel@tonic-gate 		else
69877c478bd9Sstevel@tonic-gate 			return (RSM_SUCCESS);
69887c478bd9Sstevel@tonic-gate 	}
69897c478bd9Sstevel@tonic-gate 
69907c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
69917c478bd9Sstevel@tonic-gate 	    "rsmbar_ioctl done: error=%d\n", e));
69927c478bd9Sstevel@tonic-gate 
69937c478bd9Sstevel@tonic-gate 	return (e);
69947c478bd9Sstevel@tonic-gate }
69957c478bd9Sstevel@tonic-gate 
69967c478bd9Sstevel@tonic-gate /*
69977c478bd9Sstevel@tonic-gate  * Ring the doorbell of the export segment to which this segment is
69987c478bd9Sstevel@tonic-gate  * connected.
69997c478bd9Sstevel@tonic-gate  */
70007c478bd9Sstevel@tonic-gate static int
exportbell_ioctl(rsmseg_t * seg,int cmd)70017c478bd9Sstevel@tonic-gate exportbell_ioctl(rsmseg_t *seg, int cmd /*ARGSUSED*/)
70027c478bd9Sstevel@tonic-gate {
70037c478bd9Sstevel@tonic-gate 	int e = 0;
70047c478bd9Sstevel@tonic-gate 	rsmipc_request_t request;
70057c478bd9Sstevel@tonic-gate 
70067c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_IMPORT | RSM_IOCTL);
70077c478bd9Sstevel@tonic-gate 
70087c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "exportbell_ioctl enter\n"));
70097c478bd9Sstevel@tonic-gate 
70107c478bd9Sstevel@tonic-gate 	request.rsmipc_key = seg->s_segid;
70117c478bd9Sstevel@tonic-gate 	request.rsmipc_hdr.rsmipc_type = RSMIPC_MSG_BELL;
70127c478bd9Sstevel@tonic-gate 	request.rsmipc_segment_cookie = NULL;
70137c478bd9Sstevel@tonic-gate 	e = rsmipc_send(seg->s_node, &request, RSM_NO_REPLY);
70147c478bd9Sstevel@tonic-gate 
70157c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
70167c478bd9Sstevel@tonic-gate 	    "exportbell_ioctl done: %d\n", e));
70177c478bd9Sstevel@tonic-gate 
70187c478bd9Sstevel@tonic-gate 	return (e);
70197c478bd9Sstevel@tonic-gate }
70207c478bd9Sstevel@tonic-gate 
70217c478bd9Sstevel@tonic-gate /*
70227c478bd9Sstevel@tonic-gate  * Ring the doorbells of all segments importing this segment
70237c478bd9Sstevel@tonic-gate  */
70247c478bd9Sstevel@tonic-gate static int
importbell_ioctl(rsmseg_t * seg,int cmd)70257c478bd9Sstevel@tonic-gate importbell_ioctl(rsmseg_t *seg, int cmd /*ARGSUSED*/)
70267c478bd9Sstevel@tonic-gate {
70277c478bd9Sstevel@tonic-gate 	importing_token_t	*token = NULL;
70287c478bd9Sstevel@tonic-gate 	rsmipc_request_t	request;
70297c478bd9Sstevel@tonic-gate 	int			index;
70307c478bd9Sstevel@tonic-gate 
70317c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_EXPORT | RSM_IOCTL);
70327c478bd9Sstevel@tonic-gate 
70337c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "importbell_ioctl enter\n"));
70347c478bd9Sstevel@tonic-gate 
70357c478bd9Sstevel@tonic-gate 	ASSERT(seg->s_state != RSM_STATE_NEW &&
70367c478bd9Sstevel@tonic-gate 	    seg->s_state != RSM_STATE_NEW_QUIESCED);
70377c478bd9Sstevel@tonic-gate 
70387c478bd9Sstevel@tonic-gate 	request.rsmipc_key = seg->s_segid;
70397c478bd9Sstevel@tonic-gate 	request.rsmipc_hdr.rsmipc_type = RSMIPC_MSG_BELL;
70407c478bd9Sstevel@tonic-gate 
70417c478bd9Sstevel@tonic-gate 	index = rsmhash(seg->s_segid);
70427c478bd9Sstevel@tonic-gate 
70437c478bd9Sstevel@tonic-gate 	token = importer_list.bucket[index];
70447c478bd9Sstevel@tonic-gate 
70457c478bd9Sstevel@tonic-gate 	while (token != NULL) {
70467c478bd9Sstevel@tonic-gate 		if (seg->s_key == token->key) {
70477c478bd9Sstevel@tonic-gate 			request.rsmipc_segment_cookie =
70487c478bd9Sstevel@tonic-gate 			    token->import_segment_cookie;
70497c478bd9Sstevel@tonic-gate 			(void) rsmipc_send(token->importing_node,
70507c478bd9Sstevel@tonic-gate 			    &request, RSM_NO_REPLY);
70517c478bd9Sstevel@tonic-gate 		}
70527c478bd9Sstevel@tonic-gate 		token = token->next;
70537c478bd9Sstevel@tonic-gate 	}
70547c478bd9Sstevel@tonic-gate 
70557c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
70567c478bd9Sstevel@tonic-gate 	    "importbell_ioctl done\n"));
70577c478bd9Sstevel@tonic-gate 	return (RSM_SUCCESS);
70587c478bd9Sstevel@tonic-gate }
70597c478bd9Sstevel@tonic-gate 
70607c478bd9Sstevel@tonic-gate static int
rsm_consumeevent_copyin(caddr_t arg,rsm_consume_event_msg_t * msgp,rsm_poll_event_t ** eventspp,int mode)70617c478bd9Sstevel@tonic-gate rsm_consumeevent_copyin(caddr_t arg, rsm_consume_event_msg_t *msgp,
70627c478bd9Sstevel@tonic-gate     rsm_poll_event_t **eventspp, int mode)
70637c478bd9Sstevel@tonic-gate {
70647c478bd9Sstevel@tonic-gate 	rsm_poll_event_t	*evlist = NULL;
70657c478bd9Sstevel@tonic-gate 	size_t			evlistsz;
70667c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_IOCTL);
70677c478bd9Sstevel@tonic-gate 
70687c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
70697c478bd9Sstevel@tonic-gate 	if ((mode & DATAMODEL_MASK) == DATAMODEL_ILP32) {
70707c478bd9Sstevel@tonic-gate 		int i;
70717c478bd9Sstevel@tonic-gate 		rsm_consume_event_msg32_t cemsg32 = {0};
70727c478bd9Sstevel@tonic-gate 		rsm_poll_event32_t	event32[RSM_MAX_POLLFDS];
70737c478bd9Sstevel@tonic-gate 		rsm_poll_event32_t	*evlist32;
70747c478bd9Sstevel@tonic-gate 		size_t			evlistsz32;
70757c478bd9Sstevel@tonic-gate 
70767c478bd9Sstevel@tonic-gate 		/* copyin the ioctl message */
70777c478bd9Sstevel@tonic-gate 		if (ddi_copyin(arg, (caddr_t)&cemsg32,
70787c478bd9Sstevel@tonic-gate 		    sizeof (rsm_consume_event_msg32_t), mode)) {
70797c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_ERR,
70807c478bd9Sstevel@tonic-gate 			    "consumeevent_copyin msgp: RSMERR_BAD_ADDR\n"));
70817c478bd9Sstevel@tonic-gate 			return (RSMERR_BAD_ADDR);
70827c478bd9Sstevel@tonic-gate 		}
70837c478bd9Sstevel@tonic-gate 		msgp->seglist = (caddr_t)(uintptr_t)cemsg32.seglist;
70847c478bd9Sstevel@tonic-gate 		msgp->numents = (int)cemsg32.numents;
70857c478bd9Sstevel@tonic-gate 
70867c478bd9Sstevel@tonic-gate 		evlistsz32 = sizeof (rsm_poll_event32_t) * msgp->numents;
70877c478bd9Sstevel@tonic-gate 		/*
70887c478bd9Sstevel@tonic-gate 		 * If numents is large alloc events list on heap otherwise
70897c478bd9Sstevel@tonic-gate 		 * use the address of array that was passed in.
70907c478bd9Sstevel@tonic-gate 		 */
70917c478bd9Sstevel@tonic-gate 		if (msgp->numents > RSM_MAX_POLLFDS) {
70927c478bd9Sstevel@tonic-gate 			if (msgp->numents > max_segs) { /* validate numents */
70937c478bd9Sstevel@tonic-gate 				DBG_PRINTF((category, RSM_ERR,
70947c478bd9Sstevel@tonic-gate 				    "consumeevent_copyin: "
70957c478bd9Sstevel@tonic-gate 				    "RSMERR_BAD_ARGS_ERRORS\n"));
70967c478bd9Sstevel@tonic-gate 				return (RSMERR_BAD_ARGS_ERRORS);
70977c478bd9Sstevel@tonic-gate 			}
70987c478bd9Sstevel@tonic-gate 			evlist32 = kmem_zalloc(evlistsz32, KM_SLEEP);
70997c478bd9Sstevel@tonic-gate 		} else {
71007c478bd9Sstevel@tonic-gate 			evlist32 = event32;
71017c478bd9Sstevel@tonic-gate 		}
71027c478bd9Sstevel@tonic-gate 
71037c478bd9Sstevel@tonic-gate 		/* copyin the seglist into the rsm_poll_event32_t array */
71047c478bd9Sstevel@tonic-gate 		if (ddi_copyin((caddr_t)msgp->seglist, (caddr_t)evlist32,
71057c478bd9Sstevel@tonic-gate 		    evlistsz32, mode)) {
71067c478bd9Sstevel@tonic-gate 			if ((msgp->numents > RSM_MAX_POLLFDS) && evlist32) {
71077c478bd9Sstevel@tonic-gate 				kmem_free(evlist32, evlistsz32);
71087c478bd9Sstevel@tonic-gate 			}
71097c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_ERR,
71107c478bd9Sstevel@tonic-gate 			    "consumeevent_copyin evlist: RSMERR_BAD_ADDR\n"));
71117c478bd9Sstevel@tonic-gate 			return (RSMERR_BAD_ADDR);
71127c478bd9Sstevel@tonic-gate 		}
71137c478bd9Sstevel@tonic-gate 
71147c478bd9Sstevel@tonic-gate 		/* evlist and evlistsz are based on rsm_poll_event_t type */
71157c478bd9Sstevel@tonic-gate 		evlistsz = sizeof (rsm_poll_event_t)* msgp->numents;
71167c478bd9Sstevel@tonic-gate 
71177c478bd9Sstevel@tonic-gate 		if (msgp->numents > RSM_MAX_POLLFDS) {
71187c478bd9Sstevel@tonic-gate 			evlist = kmem_zalloc(evlistsz, KM_SLEEP);
71197c478bd9Sstevel@tonic-gate 			*eventspp = evlist;
71207c478bd9Sstevel@tonic-gate 		} else {
71217c478bd9Sstevel@tonic-gate 			evlist = *eventspp;
71227c478bd9Sstevel@tonic-gate 		}
71237c478bd9Sstevel@tonic-gate 		/*
71247c478bd9Sstevel@tonic-gate 		 * copy the rsm_poll_event32_t array to the rsm_poll_event_t
71257c478bd9Sstevel@tonic-gate 		 * array
71267c478bd9Sstevel@tonic-gate 		 */
71277c478bd9Sstevel@tonic-gate 		for (i = 0; i < msgp->numents; i++) {
71287c478bd9Sstevel@tonic-gate 			evlist[i].rnum = evlist32[i].rnum;
71297c478bd9Sstevel@tonic-gate 			evlist[i].fdsidx = evlist32[i].fdsidx;
71307c478bd9Sstevel@tonic-gate 			evlist[i].revent = evlist32[i].revent;
71317c478bd9Sstevel@tonic-gate 		}
71327c478bd9Sstevel@tonic-gate 		/* free the temp 32-bit event list */
71337c478bd9Sstevel@tonic-gate 		if ((msgp->numents > RSM_MAX_POLLFDS) && evlist32) {
71347c478bd9Sstevel@tonic-gate 			kmem_free(evlist32, evlistsz32);
71357c478bd9Sstevel@tonic-gate 		}
71367c478bd9Sstevel@tonic-gate 
71377c478bd9Sstevel@tonic-gate 		return (RSM_SUCCESS);
71387c478bd9Sstevel@tonic-gate 	}
71397c478bd9Sstevel@tonic-gate #endif
71407c478bd9Sstevel@tonic-gate 	/* copyin the ioctl message */
71417c478bd9Sstevel@tonic-gate 	if (ddi_copyin(arg, (caddr_t)msgp, sizeof (rsm_consume_event_msg_t),
71427c478bd9Sstevel@tonic-gate 	    mode)) {
71437c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
71447c478bd9Sstevel@tonic-gate 		    "consumeevent_copyin msgp: RSMERR_BAD_ADDR\n"));
71457c478bd9Sstevel@tonic-gate 		return (RSMERR_BAD_ADDR);
71467c478bd9Sstevel@tonic-gate 	}
71477c478bd9Sstevel@tonic-gate 	/*
71487c478bd9Sstevel@tonic-gate 	 * If numents is large alloc events list on heap otherwise
71497c478bd9Sstevel@tonic-gate 	 * use the address of array that was passed in.
71507c478bd9Sstevel@tonic-gate 	 */
71517c478bd9Sstevel@tonic-gate 	if (msgp->numents > RSM_MAX_POLLFDS) {
71527c478bd9Sstevel@tonic-gate 		if (msgp->numents > max_segs) { /* validate numents */
71537c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_ERR,
71547c478bd9Sstevel@tonic-gate 			    "consumeevent_copyin: RSMERR_BAD_ARGS_ERRORS\n"));
71557c478bd9Sstevel@tonic-gate 			return (RSMERR_BAD_ARGS_ERRORS);
71567c478bd9Sstevel@tonic-gate 		}
71577c478bd9Sstevel@tonic-gate 		evlistsz = sizeof (rsm_poll_event_t)*msgp->numents;
71587c478bd9Sstevel@tonic-gate 		evlist = kmem_zalloc(evlistsz, KM_SLEEP);
71597c478bd9Sstevel@tonic-gate 		*eventspp  = evlist;
71607c478bd9Sstevel@tonic-gate 	}
71617c478bd9Sstevel@tonic-gate 
71627c478bd9Sstevel@tonic-gate 	/* copyin the seglist */
71637c478bd9Sstevel@tonic-gate 	if (ddi_copyin((caddr_t)msgp->seglist, (caddr_t)(*eventspp),
71647c478bd9Sstevel@tonic-gate 	    sizeof (rsm_poll_event_t)*msgp->numents, mode)) {
71657c478bd9Sstevel@tonic-gate 		if (evlist) {
71667c478bd9Sstevel@tonic-gate 			kmem_free(evlist, evlistsz);
71677c478bd9Sstevel@tonic-gate 			*eventspp = NULL;
71687c478bd9Sstevel@tonic-gate 		}
71697c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
71707c478bd9Sstevel@tonic-gate 		    "consumeevent_copyin evlist: RSMERR_BAD_ADDR\n"));
71717c478bd9Sstevel@tonic-gate 		return (RSMERR_BAD_ADDR);
71727c478bd9Sstevel@tonic-gate 	}
71737c478bd9Sstevel@tonic-gate 
71747c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
71757c478bd9Sstevel@tonic-gate 	    "consumeevent_copyin done\n"));
71767c478bd9Sstevel@tonic-gate 	return (RSM_SUCCESS);
71777c478bd9Sstevel@tonic-gate }
71787c478bd9Sstevel@tonic-gate 
71797c478bd9Sstevel@tonic-gate static int
rsm_consumeevent_copyout(rsm_consume_event_msg_t * msgp,rsm_poll_event_t * eventsp,int mode)71807c478bd9Sstevel@tonic-gate rsm_consumeevent_copyout(rsm_consume_event_msg_t *msgp,
71817c478bd9Sstevel@tonic-gate     rsm_poll_event_t *eventsp, int mode)
71827c478bd9Sstevel@tonic-gate {
71837c478bd9Sstevel@tonic-gate 	size_t			evlistsz;
71847c478bd9Sstevel@tonic-gate 	int			err = RSM_SUCCESS;
71857c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_IOCTL);
71867c478bd9Sstevel@tonic-gate 
71877c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
71887c478bd9Sstevel@tonic-gate 	    "consumeevent_copyout enter: numents(%d) eventsp(%p)\n",
71897c478bd9Sstevel@tonic-gate 	    msgp->numents, eventsp));
71907c478bd9Sstevel@tonic-gate 
71917c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
71927c478bd9Sstevel@tonic-gate 	if ((mode & DATAMODEL_MASK) == DATAMODEL_ILP32) {
71937c478bd9Sstevel@tonic-gate 		int i;
71947c478bd9Sstevel@tonic-gate 		rsm_poll_event32_t	event32[RSM_MAX_POLLFDS];
71957c478bd9Sstevel@tonic-gate 		rsm_poll_event32_t	*evlist32;
71967c478bd9Sstevel@tonic-gate 		size_t			evlistsz32;
71977c478bd9Sstevel@tonic-gate 
71987c478bd9Sstevel@tonic-gate 		evlistsz32 = sizeof (rsm_poll_event32_t)*msgp->numents;
71997c478bd9Sstevel@tonic-gate 		if (msgp->numents > RSM_MAX_POLLFDS) {
72007c478bd9Sstevel@tonic-gate 			evlist32 = kmem_zalloc(evlistsz32, KM_SLEEP);
72017c478bd9Sstevel@tonic-gate 		} else {
72027c478bd9Sstevel@tonic-gate 			evlist32 = event32;
72037c478bd9Sstevel@tonic-gate 		}
72047c478bd9Sstevel@tonic-gate 
72057c478bd9Sstevel@tonic-gate 		/*
72067c478bd9Sstevel@tonic-gate 		 * copy the rsm_poll_event_t array to the rsm_poll_event32_t
72077c478bd9Sstevel@tonic-gate 		 * array
72087c478bd9Sstevel@tonic-gate 		 */
72097c478bd9Sstevel@tonic-gate 		for (i = 0; i < msgp->numents; i++) {
72107c478bd9Sstevel@tonic-gate 			evlist32[i].rnum = eventsp[i].rnum;
72117c478bd9Sstevel@tonic-gate 			evlist32[i].fdsidx = eventsp[i].fdsidx;
72127c478bd9Sstevel@tonic-gate 			evlist32[i].revent = eventsp[i].revent;
72137c478bd9Sstevel@tonic-gate 		}
72147c478bd9Sstevel@tonic-gate 
72157c478bd9Sstevel@tonic-gate 		if (ddi_copyout((caddr_t)evlist32, (caddr_t)msgp->seglist,
72167c478bd9Sstevel@tonic-gate 		    evlistsz32, mode)) {
72177c478bd9Sstevel@tonic-gate 			err = RSMERR_BAD_ADDR;
72187c478bd9Sstevel@tonic-gate 		}
72197c478bd9Sstevel@tonic-gate 
72207c478bd9Sstevel@tonic-gate 		if (msgp->numents > RSM_MAX_POLLFDS) {
72217c478bd9Sstevel@tonic-gate 			if (evlist32) {	/* free the temp 32-bit event list */
72227c478bd9Sstevel@tonic-gate 				kmem_free(evlist32, evlistsz32);
72237c478bd9Sstevel@tonic-gate 			}
72247c478bd9Sstevel@tonic-gate 			/*
72257c478bd9Sstevel@tonic-gate 			 * eventsp and evlistsz are based on rsm_poll_event_t
72267c478bd9Sstevel@tonic-gate 			 * type
72277c478bd9Sstevel@tonic-gate 			 */
72287c478bd9Sstevel@tonic-gate 			evlistsz = sizeof (rsm_poll_event_t)*msgp->numents;
72297c478bd9Sstevel@tonic-gate 			/* event list on the heap and needs to be freed here */
72307c478bd9Sstevel@tonic-gate 			if (eventsp) {
72317c478bd9Sstevel@tonic-gate 				kmem_free(eventsp, evlistsz);
72327c478bd9Sstevel@tonic-gate 			}
72337c478bd9Sstevel@tonic-gate 		}
72347c478bd9Sstevel@tonic-gate 
72357c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
72367c478bd9Sstevel@tonic-gate 		    "consumeevent_copyout done: err=%d\n", err));
72377c478bd9Sstevel@tonic-gate 		return (err);
72387c478bd9Sstevel@tonic-gate 	}
72397c478bd9Sstevel@tonic-gate #endif
72407c478bd9Sstevel@tonic-gate 	evlistsz = sizeof (rsm_poll_event_t)*msgp->numents;
72417c478bd9Sstevel@tonic-gate 
72427c478bd9Sstevel@tonic-gate 	if (ddi_copyout((caddr_t)eventsp, (caddr_t)msgp->seglist, evlistsz,
72437c478bd9Sstevel@tonic-gate 	    mode)) {
72447c478bd9Sstevel@tonic-gate 		err = RSMERR_BAD_ADDR;
72457c478bd9Sstevel@tonic-gate 	}
72467c478bd9Sstevel@tonic-gate 
72477c478bd9Sstevel@tonic-gate 	if ((msgp->numents > RSM_MAX_POLLFDS) && eventsp) {
72487c478bd9Sstevel@tonic-gate 		/* event list on the heap and needs to be freed here */
72497c478bd9Sstevel@tonic-gate 		kmem_free(eventsp, evlistsz);
72507c478bd9Sstevel@tonic-gate 	}
72517c478bd9Sstevel@tonic-gate 
72527c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
72537c478bd9Sstevel@tonic-gate 	    "consumeevent_copyout done: err=%d\n", err));
72547c478bd9Sstevel@tonic-gate 	return (err);
72557c478bd9Sstevel@tonic-gate }
72567c478bd9Sstevel@tonic-gate 
72577c478bd9Sstevel@tonic-gate static int
rsm_consumeevent_ioctl(caddr_t arg,int mode)72587c478bd9Sstevel@tonic-gate rsm_consumeevent_ioctl(caddr_t arg, int mode)
72597c478bd9Sstevel@tonic-gate {
72607c478bd9Sstevel@tonic-gate 	int	rc;
72617c478bd9Sstevel@tonic-gate 	int	i;
72627c478bd9Sstevel@tonic-gate 	minor_t	rnum;
72637c478bd9Sstevel@tonic-gate 	rsm_consume_event_msg_t	msg = {0};
72647c478bd9Sstevel@tonic-gate 	rsmseg_t		*seg;
72657c478bd9Sstevel@tonic-gate 	rsm_poll_event_t	*event_list;
72667c478bd9Sstevel@tonic-gate 	rsm_poll_event_t	events[RSM_MAX_POLLFDS];
72677c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_IOCTL);
72687c478bd9Sstevel@tonic-gate 
72697c478bd9Sstevel@tonic-gate 	event_list = events;
72707c478bd9Sstevel@tonic-gate 
72717c478bd9Sstevel@tonic-gate 	if ((rc = rsm_consumeevent_copyin(arg, &msg, &event_list, mode)) !=
72727c478bd9Sstevel@tonic-gate 	    RSM_SUCCESS) {
72737c478bd9Sstevel@tonic-gate 		return (rc);
72747c478bd9Sstevel@tonic-gate 	}
72757c478bd9Sstevel@tonic-gate 
72767c478bd9Sstevel@tonic-gate 	for (i = 0; i < msg.numents; i++) {
72777c478bd9Sstevel@tonic-gate 		rnum = event_list[i].rnum;
72787c478bd9Sstevel@tonic-gate 		event_list[i].revent = 0;
72797c478bd9Sstevel@tonic-gate 		/* get the segment structure */
72807c478bd9Sstevel@tonic-gate 		seg = (rsmseg_t *)rsmresource_lookup(rnum, RSM_LOCK);
72817c478bd9Sstevel@tonic-gate 		if (seg) {
72827c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
72837c478bd9Sstevel@tonic-gate 			    "consumeevent_ioctl: rnum(%d) seg(%p)\n", rnum,
72847c478bd9Sstevel@tonic-gate 			    seg));
72857c478bd9Sstevel@tonic-gate 			if (seg->s_pollevent) {
72867c478bd9Sstevel@tonic-gate 				/* consume the event */
7287*1a5e258fSJosef 'Jeff' Sipek 				atomic_dec_32(&seg->s_pollevent);
72887c478bd9Sstevel@tonic-gate 				event_list[i].revent = POLLRDNORM;
72897c478bd9Sstevel@tonic-gate 			}
72907c478bd9Sstevel@tonic-gate 			rsmseglock_release(seg);
72917c478bd9Sstevel@tonic-gate 		}
72927c478bd9Sstevel@tonic-gate 	}
72937c478bd9Sstevel@tonic-gate 
72947c478bd9Sstevel@tonic-gate 	if ((rc = rsm_consumeevent_copyout(&msg, event_list, mode)) !=
72957c478bd9Sstevel@tonic-gate 	    RSM_SUCCESS) {
72967c478bd9Sstevel@tonic-gate 		return (rc);
72977c478bd9Sstevel@tonic-gate 	}
72987c478bd9Sstevel@tonic-gate 
72997c478bd9Sstevel@tonic-gate 	return (RSM_SUCCESS);
73007c478bd9Sstevel@tonic-gate }
73017c478bd9Sstevel@tonic-gate 
73027c478bd9Sstevel@tonic-gate static int
iovec_copyin(caddr_t user_vec,rsmka_iovec_t * iovec,int count,int mode)73037c478bd9Sstevel@tonic-gate iovec_copyin(caddr_t user_vec, rsmka_iovec_t *iovec, int count, int mode)
73047c478bd9Sstevel@tonic-gate {
73057c478bd9Sstevel@tonic-gate 	int size;
73067c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_IMPORT | RSM_IOCTL);
73077c478bd9Sstevel@tonic-gate 
73087c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "iovec_copyin enter\n"));
73097c478bd9Sstevel@tonic-gate 
73107c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
73117c478bd9Sstevel@tonic-gate 	if ((mode & DATAMODEL_MASK) == DATAMODEL_ILP32) {
73127c478bd9Sstevel@tonic-gate 		rsmka_iovec32_t	*iovec32, *iovec32_base;
73137c478bd9Sstevel@tonic-gate 		int i;
73147c478bd9Sstevel@tonic-gate 
73157c478bd9Sstevel@tonic-gate 		size = count * sizeof (rsmka_iovec32_t);
73167c478bd9Sstevel@tonic-gate 		iovec32_base = iovec32 = kmem_zalloc(size, KM_SLEEP);
73177c478bd9Sstevel@tonic-gate 		if (ddi_copyin((caddr_t)user_vec,
73187c478bd9Sstevel@tonic-gate 		    (caddr_t)iovec32, size, mode)) {
73197c478bd9Sstevel@tonic-gate 			kmem_free(iovec32, size);
73207c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG,
73217c478bd9Sstevel@tonic-gate 			    "iovec_copyin: returning RSMERR_BAD_ADDR\n"));
73227c478bd9Sstevel@tonic-gate 			return (RSMERR_BAD_ADDR);
73237c478bd9Sstevel@tonic-gate 		}
73247c478bd9Sstevel@tonic-gate 
73257c478bd9Sstevel@tonic-gate 		for (i = 0; i < count; i++, iovec++, iovec32++) {
73267c478bd9Sstevel@tonic-gate 			iovec->io_type = (int)iovec32->io_type;
73277c478bd9Sstevel@tonic-gate 			if (iovec->io_type == RSM_HANDLE_TYPE)
73287c478bd9Sstevel@tonic-gate 				iovec->local.segid = (rsm_memseg_id_t)
73297c478bd9Sstevel@tonic-gate 				    iovec32->local;
73307c478bd9Sstevel@tonic-gate 			else
73317c478bd9Sstevel@tonic-gate 				iovec->local.vaddr =
73327c478bd9Sstevel@tonic-gate 				    (caddr_t)(uintptr_t)iovec32->local;
73337c478bd9Sstevel@tonic-gate 			iovec->local_offset = (size_t)iovec32->local_offset;
73347c478bd9Sstevel@tonic-gate 			iovec->remote_offset = (size_t)iovec32->remote_offset;
73357c478bd9Sstevel@tonic-gate 			iovec->transfer_len = (size_t)iovec32->transfer_len;
73367c478bd9Sstevel@tonic-gate 
73377c478bd9Sstevel@tonic-gate 		}
73387c478bd9Sstevel@tonic-gate 		kmem_free(iovec32_base, size);
73397c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
73407c478bd9Sstevel@tonic-gate 		    "iovec_copyin done\n"));
73417c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
73427c478bd9Sstevel@tonic-gate 	}
73437c478bd9Sstevel@tonic-gate #endif
73447c478bd9Sstevel@tonic-gate 
73457c478bd9Sstevel@tonic-gate 	size = count * sizeof (rsmka_iovec_t);
73467c478bd9Sstevel@tonic-gate 	if (ddi_copyin((caddr_t)user_vec, (caddr_t)iovec, size, mode)) {
73477c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
73487c478bd9Sstevel@tonic-gate 		    "iovec_copyin done: RSMERR_BAD_ADDR\n"));
73497c478bd9Sstevel@tonic-gate 		return (RSMERR_BAD_ADDR);
73507c478bd9Sstevel@tonic-gate 	}
73517c478bd9Sstevel@tonic-gate 
73527c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "iovec_copyin done\n"));
73537c478bd9Sstevel@tonic-gate 
73547c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
73557c478bd9Sstevel@tonic-gate }
73567c478bd9Sstevel@tonic-gate 
73577c478bd9Sstevel@tonic-gate 
73587c478bd9Sstevel@tonic-gate static int
sgio_copyin(caddr_t arg,rsmka_scat_gath_t * sg_io,int mode)73597c478bd9Sstevel@tonic-gate sgio_copyin(caddr_t arg, rsmka_scat_gath_t *sg_io, int mode)
73607c478bd9Sstevel@tonic-gate {
73617c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_IMPORT | RSM_IOCTL);
73627c478bd9Sstevel@tonic-gate 
73637c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "sgio_copyin enter\n"));
73647c478bd9Sstevel@tonic-gate 
73657c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
73667c478bd9Sstevel@tonic-gate 	if ((mode & DATAMODEL_MASK) == DATAMODEL_ILP32) {
73677c478bd9Sstevel@tonic-gate 		rsmka_scat_gath32_t sg_io32;
73687c478bd9Sstevel@tonic-gate 
73697c478bd9Sstevel@tonic-gate 		if (ddi_copyin(arg, (caddr_t)&sg_io32, sizeof (sg_io32),
73707c478bd9Sstevel@tonic-gate 		    mode)) {
73717c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG,
73727c478bd9Sstevel@tonic-gate 			    "sgio_copyin done: returning EFAULT\n"));
73737c478bd9Sstevel@tonic-gate 			return (RSMERR_BAD_ADDR);
73747c478bd9Sstevel@tonic-gate 		}
73757c478bd9Sstevel@tonic-gate 		sg_io->local_nodeid = (rsm_node_id_t)sg_io32.local_nodeid;
73767c478bd9Sstevel@tonic-gate 		sg_io->io_request_count =  (size_t)sg_io32.io_request_count;
73777c478bd9Sstevel@tonic-gate 		sg_io->io_residual_count = (size_t)sg_io32.io_residual_count;
73787c478bd9Sstevel@tonic-gate 		sg_io->flags = (size_t)sg_io32.flags;
73797c478bd9Sstevel@tonic-gate 		sg_io->remote_handle = (rsm_memseg_import_handle_t)
73807c478bd9Sstevel@tonic-gate 		    (uintptr_t)sg_io32.remote_handle;
73817c478bd9Sstevel@tonic-gate 		sg_io->iovec = (rsmka_iovec_t *)(uintptr_t)sg_io32.iovec;
73827c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
73837c478bd9Sstevel@tonic-gate 		    "sgio_copyin done\n"));
73847c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
73857c478bd9Sstevel@tonic-gate 	}
73867c478bd9Sstevel@tonic-gate #endif
73877c478bd9Sstevel@tonic-gate 	if (ddi_copyin(arg, (caddr_t)sg_io, sizeof (rsmka_scat_gath_t),
73887c478bd9Sstevel@tonic-gate 	    mode)) {
73897c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG,
73907c478bd9Sstevel@tonic-gate 		    "sgio_copyin done: returning EFAULT\n"));
73917c478bd9Sstevel@tonic-gate 		return (RSMERR_BAD_ADDR);
73927c478bd9Sstevel@tonic-gate 	}
73937c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "sgio_copyin done\n"));
73947c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
73957c478bd9Sstevel@tonic-gate }
73967c478bd9Sstevel@tonic-gate 
73977c478bd9Sstevel@tonic-gate static int
sgio_resid_copyout(caddr_t arg,rsmka_scat_gath_t * sg_io,int mode)73987c478bd9Sstevel@tonic-gate sgio_resid_copyout(caddr_t arg, rsmka_scat_gath_t *sg_io, int mode)
73997c478bd9Sstevel@tonic-gate {
74007c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_IMPORT | RSM_IOCTL);
74017c478bd9Sstevel@tonic-gate 
74027c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
74037c478bd9Sstevel@tonic-gate 	    "sgio_resid_copyout enter\n"));
74047c478bd9Sstevel@tonic-gate 
74057c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
74067c478bd9Sstevel@tonic-gate 	if ((mode & DATAMODEL_MASK) == DATAMODEL_ILP32) {
74077c478bd9Sstevel@tonic-gate 		rsmka_scat_gath32_t sg_io32;
74087c478bd9Sstevel@tonic-gate 
74097c478bd9Sstevel@tonic-gate 		sg_io32.io_residual_count = sg_io->io_residual_count;
74107c478bd9Sstevel@tonic-gate 		sg_io32.flags = sg_io->flags;
74117c478bd9Sstevel@tonic-gate 
74127c478bd9Sstevel@tonic-gate 		if (ddi_copyout((caddr_t)&sg_io32.io_residual_count,
74137c478bd9Sstevel@tonic-gate 		    (caddr_t)&((rsmka_scat_gath32_t *)arg)->io_residual_count,
74147c478bd9Sstevel@tonic-gate 		    sizeof (uint32_t), mode)) {
74157c478bd9Sstevel@tonic-gate 
74167c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_ERR,
74177c478bd9Sstevel@tonic-gate 			    "sgio_resid_copyout error: rescnt\n"));
74187c478bd9Sstevel@tonic-gate 			return (RSMERR_BAD_ADDR);
74197c478bd9Sstevel@tonic-gate 		}
74207c478bd9Sstevel@tonic-gate 
74217c478bd9Sstevel@tonic-gate 		if (ddi_copyout((caddr_t)&sg_io32.flags,
74227c478bd9Sstevel@tonic-gate 		    (caddr_t)&((rsmka_scat_gath32_t *)arg)->flags,
74237c478bd9Sstevel@tonic-gate 		    sizeof (uint32_t), mode)) {
74247c478bd9Sstevel@tonic-gate 
74257c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_ERR,
74267c478bd9Sstevel@tonic-gate 			    "sgio_resid_copyout error: flags\n"));
74277c478bd9Sstevel@tonic-gate 			return (RSMERR_BAD_ADDR);
74287c478bd9Sstevel@tonic-gate 		}
74297c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
74307c478bd9Sstevel@tonic-gate 		    "sgio_resid_copyout done\n"));
74317c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
74327c478bd9Sstevel@tonic-gate 	}
74337c478bd9Sstevel@tonic-gate #endif
74347c478bd9Sstevel@tonic-gate 	if (ddi_copyout((caddr_t)&sg_io->io_residual_count,
74357c478bd9Sstevel@tonic-gate 	    (caddr_t)&((rsmka_scat_gath_t *)arg)->io_residual_count,
74367c478bd9Sstevel@tonic-gate 	    sizeof (ulong_t), mode)) {
74377c478bd9Sstevel@tonic-gate 
74387c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
74397c478bd9Sstevel@tonic-gate 		    "sgio_resid_copyout error:rescnt\n"));
74407c478bd9Sstevel@tonic-gate 		return (RSMERR_BAD_ADDR);
74417c478bd9Sstevel@tonic-gate 	}
74427c478bd9Sstevel@tonic-gate 
74437c478bd9Sstevel@tonic-gate 	if (ddi_copyout((caddr_t)&sg_io->flags,
74447c478bd9Sstevel@tonic-gate 	    (caddr_t)&((rsmka_scat_gath_t *)arg)->flags,
74457c478bd9Sstevel@tonic-gate 	    sizeof (uint_t), mode)) {
74467c478bd9Sstevel@tonic-gate 
74477c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR,
74487c478bd9Sstevel@tonic-gate 		    "sgio_resid_copyout error:flags\n"));
74497c478bd9Sstevel@tonic-gate 		return (RSMERR_BAD_ADDR);
74507c478bd9Sstevel@tonic-gate 	}
74517c478bd9Sstevel@tonic-gate 
74527c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "sgio_resid_copyout done\n"));
74537c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
74547c478bd9Sstevel@tonic-gate }
74557c478bd9Sstevel@tonic-gate 
74567c478bd9Sstevel@tonic-gate 
74577c478bd9Sstevel@tonic-gate static int
rsm_iovec_ioctl(dev_t dev,caddr_t arg,int cmd,int mode,cred_t * credp)74587c478bd9Sstevel@tonic-gate rsm_iovec_ioctl(dev_t dev, caddr_t arg, int cmd, int mode, cred_t *credp)
74597c478bd9Sstevel@tonic-gate {
74607c478bd9Sstevel@tonic-gate 	rsmka_scat_gath_t	sg_io;
74617c478bd9Sstevel@tonic-gate 	rsmka_iovec_t		ka_iovec_arr[RSM_MAX_IOVLEN];
74627c478bd9Sstevel@tonic-gate 	rsmka_iovec_t		*ka_iovec;
74637c478bd9Sstevel@tonic-gate 	rsmka_iovec_t		*ka_iovec_start;
74647c478bd9Sstevel@tonic-gate 	rsmpi_scat_gath_t	rsmpi_sg_io;
74657c478bd9Sstevel@tonic-gate 	rsmpi_iovec_t		iovec_arr[RSM_MAX_IOVLEN];
74667c478bd9Sstevel@tonic-gate 	rsmpi_iovec_t		*iovec;
74677c478bd9Sstevel@tonic-gate 	rsmpi_iovec_t		*iovec_start = NULL;
74687c478bd9Sstevel@tonic-gate 	rsmapi_access_entry_t	*acl;
74697c478bd9Sstevel@tonic-gate 	rsmresource_t		*res;
74707c478bd9Sstevel@tonic-gate 	minor_t			rnum;
74717c478bd9Sstevel@tonic-gate 	rsmseg_t		*im_seg, *ex_seg;
74727c478bd9Sstevel@tonic-gate 	int			e;
74737c478bd9Sstevel@tonic-gate 	int			error = 0;
74747c478bd9Sstevel@tonic-gate 	uint_t			i;
74757c478bd9Sstevel@tonic-gate 	uint_t			iov_proc = 0; /* num of iovecs processed */
74767c478bd9Sstevel@tonic-gate 	size_t			size = 0;
74777c478bd9Sstevel@tonic-gate 	size_t			ka_size;
74787c478bd9Sstevel@tonic-gate 
74797c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_IMPORT | RSM_IOCTL);
74807c478bd9Sstevel@tonic-gate 
74817c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_iovec_ioctl enter\n"));
74827c478bd9Sstevel@tonic-gate 
74837c478bd9Sstevel@tonic-gate 	credp = credp;
74847c478bd9Sstevel@tonic-gate 
74857c478bd9Sstevel@tonic-gate 	/*
74867c478bd9Sstevel@tonic-gate 	 * Copyin the scatter/gather structure  and build new structure
74877c478bd9Sstevel@tonic-gate 	 * for rsmpi.
74887c478bd9Sstevel@tonic-gate 	 */
74897c478bd9Sstevel@tonic-gate 	e = sgio_copyin(arg, &sg_io, mode);
74907c478bd9Sstevel@tonic-gate 	if (e != DDI_SUCCESS) {
74917c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
74927c478bd9Sstevel@tonic-gate 		    "rsm_iovec_ioctl done: sgio_copyin %d\n", e));
74937c478bd9Sstevel@tonic-gate 		return (e);
74947c478bd9Sstevel@tonic-gate 	}
74957c478bd9Sstevel@tonic-gate 
74967c478bd9Sstevel@tonic-gate 	if (sg_io.io_request_count > RSM_MAX_SGIOREQS) {
74977c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
74987c478bd9Sstevel@tonic-gate 		    "rsm_iovec_ioctl done: request_count(%d) too large\n",
74997c478bd9Sstevel@tonic-gate 		    sg_io.io_request_count));
75007c478bd9Sstevel@tonic-gate 		return (RSMERR_BAD_SGIO);
75017c478bd9Sstevel@tonic-gate 	}
75027c478bd9Sstevel@tonic-gate 
75037c478bd9Sstevel@tonic-gate 	rsmpi_sg_io.io_request_count = sg_io.io_request_count;
75047c478bd9Sstevel@tonic-gate 	rsmpi_sg_io.io_residual_count = sg_io.io_request_count;
75057c478bd9Sstevel@tonic-gate 	rsmpi_sg_io.io_segflg = 0;
75067c478bd9Sstevel@tonic-gate 
75077c478bd9Sstevel@tonic-gate 	/* Allocate memory and copyin io vector array  */
75087c478bd9Sstevel@tonic-gate 	if (sg_io.io_request_count > RSM_MAX_IOVLEN) {
75097c478bd9Sstevel@tonic-gate 		ka_size =  sg_io.io_request_count * sizeof (rsmka_iovec_t);
75107c478bd9Sstevel@tonic-gate 		ka_iovec_start = ka_iovec = kmem_zalloc(ka_size, KM_SLEEP);
75117c478bd9Sstevel@tonic-gate 	} else {
75127c478bd9Sstevel@tonic-gate 		ka_iovec_start = ka_iovec = ka_iovec_arr;
75137c478bd9Sstevel@tonic-gate 	}
75147c478bd9Sstevel@tonic-gate 	e = iovec_copyin((caddr_t)sg_io.iovec, ka_iovec,
75157c478bd9Sstevel@tonic-gate 	    sg_io.io_request_count, mode);
75167c478bd9Sstevel@tonic-gate 	if (e != DDI_SUCCESS) {
75177c478bd9Sstevel@tonic-gate 		if (sg_io.io_request_count > RSM_MAX_IOVLEN)
75187c478bd9Sstevel@tonic-gate 			kmem_free(ka_iovec, ka_size);
75197c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
75207c478bd9Sstevel@tonic-gate 		    "rsm_iovec_ioctl done: iovec_copyin %d\n", e));
75217c478bd9Sstevel@tonic-gate 		return (e);
75227c478bd9Sstevel@tonic-gate 	}
75237c478bd9Sstevel@tonic-gate 
75247c478bd9Sstevel@tonic-gate 	/* get the import segment descriptor */
75257c478bd9Sstevel@tonic-gate 	rnum = getminor(dev);
75267c478bd9Sstevel@tonic-gate 	res = rsmresource_lookup(rnum, RSM_LOCK);
75277c478bd9Sstevel@tonic-gate 
75287c478bd9Sstevel@tonic-gate 	/*
75297c478bd9Sstevel@tonic-gate 	 * The following sequence of locking may (or MAY NOT) cause a
75307c478bd9Sstevel@tonic-gate 	 * deadlock but this is currently not addressed here since the
75317c478bd9Sstevel@tonic-gate 	 * implementation will be changed to incorporate the use of
75327c478bd9Sstevel@tonic-gate 	 * reference counting for both the import and the export segments.
75337c478bd9Sstevel@tonic-gate 	 */
75347c478bd9Sstevel@tonic-gate 
75357c478bd9Sstevel@tonic-gate 	/* rsmseglock_acquire(im_seg) done in rsmresource_lookup */
75367c478bd9Sstevel@tonic-gate 
75377c478bd9Sstevel@tonic-gate 	im_seg = (rsmseg_t *)res;
75387c478bd9Sstevel@tonic-gate 
75397c478bd9Sstevel@tonic-gate 	if (im_seg == NULL) {
75407c478bd9Sstevel@tonic-gate 		if (sg_io.io_request_count > RSM_MAX_IOVLEN)
75417c478bd9Sstevel@tonic-gate 			kmem_free(ka_iovec, ka_size);
75427c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
75437c478bd9Sstevel@tonic-gate 		    "rsm_iovec_ioctl done: rsmresource_lookup failed\n"));
75447c478bd9Sstevel@tonic-gate 		return (EINVAL);
75457c478bd9Sstevel@tonic-gate 	}
75467c478bd9Sstevel@tonic-gate 	/* putv/getv supported is supported only on import segments */
75477c478bd9Sstevel@tonic-gate 	if (im_seg->s_type != RSM_RESOURCE_IMPORT_SEGMENT) {
75487c478bd9Sstevel@tonic-gate 		rsmseglock_release(im_seg);
75497c478bd9Sstevel@tonic-gate 		if (sg_io.io_request_count > RSM_MAX_IOVLEN)
75507c478bd9Sstevel@tonic-gate 			kmem_free(ka_iovec, ka_size);
75517c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
75527c478bd9Sstevel@tonic-gate 		    "rsm_iovec_ioctl done: not an import segment\n"));
75537c478bd9Sstevel@tonic-gate 		return (EINVAL);
75547c478bd9Sstevel@tonic-gate 	}
75557c478bd9Sstevel@tonic-gate 
75567c478bd9Sstevel@tonic-gate 	/*
75577c478bd9Sstevel@tonic-gate 	 * wait for a remote DR to complete ie. for segments to get UNQUIESCED
75587c478bd9Sstevel@tonic-gate 	 * as well as wait for a local DR to complete.
75597c478bd9Sstevel@tonic-gate 	 */
75607c478bd9Sstevel@tonic-gate 	while ((im_seg->s_state == RSM_STATE_CONN_QUIESCE) ||
75617c478bd9Sstevel@tonic-gate 	    (im_seg->s_state == RSM_STATE_MAP_QUIESCE) ||
75627c478bd9Sstevel@tonic-gate 	    (im_seg->s_flags & RSM_DR_INPROGRESS)) {
75637c478bd9Sstevel@tonic-gate 		if (cv_wait_sig(&im_seg->s_cv, &im_seg->s_lock) == 0) {
75647c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG,
75657c478bd9Sstevel@tonic-gate 			    "rsm_iovec_ioctl done: cv_wait INTR"));
75667c478bd9Sstevel@tonic-gate 			rsmseglock_release(im_seg);
75677c478bd9Sstevel@tonic-gate 			return (RSMERR_INTERRUPTED);
75687c478bd9Sstevel@tonic-gate 		}
75697c478bd9Sstevel@tonic-gate 	}
75707c478bd9Sstevel@tonic-gate 
75717c478bd9Sstevel@tonic-gate 	if ((im_seg->s_state != RSM_STATE_CONNECT) &&
75727c478bd9Sstevel@tonic-gate 	    (im_seg->s_state != RSM_STATE_ACTIVE)) {
75737c478bd9Sstevel@tonic-gate 
75747c478bd9Sstevel@tonic-gate 		ASSERT(im_seg->s_state == RSM_STATE_DISCONNECT ||
75757c478bd9Sstevel@tonic-gate 		    im_seg->s_state == RSM_STATE_NEW);
75767c478bd9Sstevel@tonic-gate 
75777c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG,
75787c478bd9Sstevel@tonic-gate 		    "rsm_iovec_ioctl done: im_seg not conn/map"));
75797c478bd9Sstevel@tonic-gate 		rsmseglock_release(im_seg);
75807c478bd9Sstevel@tonic-gate 		e = RSMERR_BAD_SGIO;
75817c478bd9Sstevel@tonic-gate 		goto out;
75827c478bd9Sstevel@tonic-gate 	}
75837c478bd9Sstevel@tonic-gate 
75847c478bd9Sstevel@tonic-gate 	im_seg->s_rdmacnt++;
75857c478bd9Sstevel@tonic-gate 	rsmseglock_release(im_seg);
75867c478bd9Sstevel@tonic-gate 
75877c478bd9Sstevel@tonic-gate 	/*
75887c478bd9Sstevel@tonic-gate 	 * Allocate and set up the io vector for rsmpi
75897c478bd9Sstevel@tonic-gate 	 */
75907c478bd9Sstevel@tonic-gate 	if (sg_io.io_request_count > RSM_MAX_IOVLEN) {
75917c478bd9Sstevel@tonic-gate 		size = sg_io.io_request_count * sizeof (rsmpi_iovec_t);
75927c478bd9Sstevel@tonic-gate 		iovec_start = iovec = kmem_zalloc(size, KM_SLEEP);
75937c478bd9Sstevel@tonic-gate 	} else {
75947c478bd9Sstevel@tonic-gate 		iovec_start = iovec = iovec_arr;
75957c478bd9Sstevel@tonic-gate 	}
75967c478bd9Sstevel@tonic-gate 
75977c478bd9Sstevel@tonic-gate 	rsmpi_sg_io.iovec = iovec;
75987c478bd9Sstevel@tonic-gate 	for (iov_proc = 0; iov_proc < sg_io.io_request_count; iov_proc++) {
75997c478bd9Sstevel@tonic-gate 		if (ka_iovec->io_type == RSM_HANDLE_TYPE) {
76007c478bd9Sstevel@tonic-gate 			ex_seg = rsmexport_lookup(ka_iovec->local.segid);
76017c478bd9Sstevel@tonic-gate 
76027c478bd9Sstevel@tonic-gate 			if (ex_seg == NULL) {
76037c478bd9Sstevel@tonic-gate 				e = RSMERR_BAD_SGIO;
76047c478bd9Sstevel@tonic-gate 				break;
76057c478bd9Sstevel@tonic-gate 			}
76067c478bd9Sstevel@tonic-gate 			ASSERT(ex_seg->s_state == RSM_STATE_EXPORT);
76077c478bd9Sstevel@tonic-gate 
76087c478bd9Sstevel@tonic-gate 			acl = ex_seg->s_acl;
76097c478bd9Sstevel@tonic-gate 			if (acl[0].ae_permission == 0) {
76107c478bd9Sstevel@tonic-gate 				struct buf *xbuf;
76117c478bd9Sstevel@tonic-gate 				dev_t sdev = 0;
76127c478bd9Sstevel@tonic-gate 
76137c478bd9Sstevel@tonic-gate 				xbuf = ddi_umem_iosetup(ex_seg->s_cookie,
76147c478bd9Sstevel@tonic-gate 				    0, ex_seg->s_len, B_WRITE,
76157c478bd9Sstevel@tonic-gate 				    sdev, 0, NULL, DDI_UMEM_SLEEP);
76167c478bd9Sstevel@tonic-gate 
76177c478bd9Sstevel@tonic-gate 				ASSERT(xbuf != NULL);
76187c478bd9Sstevel@tonic-gate 
76197c478bd9Sstevel@tonic-gate 				iovec->local_mem.ms_type = RSM_MEM_BUF;
76207c478bd9Sstevel@tonic-gate 				iovec->local_mem.ms_memory.bp = xbuf;
76217c478bd9Sstevel@tonic-gate 			} else {
76227c478bd9Sstevel@tonic-gate 				iovec->local_mem.ms_type = RSM_MEM_HANDLE;
76237c478bd9Sstevel@tonic-gate 				iovec->local_mem.ms_memory.handle =
76247c478bd9Sstevel@tonic-gate 				    ex_seg->s_handle.out;
76257c478bd9Sstevel@tonic-gate 			}
76267c478bd9Sstevel@tonic-gate 			ex_seg->s_rdmacnt++; /* refcnt the handle */
76277c478bd9Sstevel@tonic-gate 			rsmseglock_release(ex_seg);
76287c478bd9Sstevel@tonic-gate 		} else {
76297c478bd9Sstevel@tonic-gate 			iovec->local_mem.ms_type = RSM_MEM_VADDR;
76307c478bd9Sstevel@tonic-gate 			iovec->local_mem.ms_memory.vr.vaddr =
76317c478bd9Sstevel@tonic-gate 			    ka_iovec->local.vaddr;
76327c478bd9Sstevel@tonic-gate 		}
76337c478bd9Sstevel@tonic-gate 
76347c478bd9Sstevel@tonic-gate 		iovec->local_offset = ka_iovec->local_offset;
76357c478bd9Sstevel@tonic-gate 		iovec->remote_handle = im_seg->s_handle.in;
76367c478bd9Sstevel@tonic-gate 		iovec->remote_offset = ka_iovec->remote_offset;
76377c478bd9Sstevel@tonic-gate 		iovec->transfer_length = ka_iovec->transfer_len;
76387c478bd9Sstevel@tonic-gate 		iovec++;
76397c478bd9Sstevel@tonic-gate 		ka_iovec++;
76407c478bd9Sstevel@tonic-gate 	}
76417c478bd9Sstevel@tonic-gate 
76427c478bd9Sstevel@tonic-gate 	if (iov_proc <  sg_io.io_request_count) {
76437c478bd9Sstevel@tonic-gate 		/* error while processing handle */
76447c478bd9Sstevel@tonic-gate 		rsmseglock_acquire(im_seg);
76457c478bd9Sstevel@tonic-gate 		im_seg->s_rdmacnt--;   /* decrement the refcnt for importseg */
76467c478bd9Sstevel@tonic-gate 		if (im_seg->s_rdmacnt == 0) {
76477c478bd9Sstevel@tonic-gate 			cv_broadcast(&im_seg->s_cv);
76487c478bd9Sstevel@tonic-gate 		}
76497c478bd9Sstevel@tonic-gate 		rsmseglock_release(im_seg);
76507c478bd9Sstevel@tonic-gate 		goto out;
76517c478bd9Sstevel@tonic-gate 	}
76527c478bd9Sstevel@tonic-gate 
76537c478bd9Sstevel@tonic-gate 	/* call rsmpi */
76547c478bd9Sstevel@tonic-gate 	if (cmd == RSM_IOCTL_PUTV)
76557c478bd9Sstevel@tonic-gate 		e = im_seg->s_adapter->rsmpi_ops->rsm_memseg_import_putv(
76567c478bd9Sstevel@tonic-gate 		    im_seg->s_adapter->rsmpi_handle,
76577c478bd9Sstevel@tonic-gate 		    &rsmpi_sg_io);
76587c478bd9Sstevel@tonic-gate 	else if (cmd == RSM_IOCTL_GETV)
76597c478bd9Sstevel@tonic-gate 		e = im_seg->s_adapter->rsmpi_ops->rsm_memseg_import_getv(
76607c478bd9Sstevel@tonic-gate 		    im_seg->s_adapter->rsmpi_handle,
76617c478bd9Sstevel@tonic-gate 		    &rsmpi_sg_io);
76627c478bd9Sstevel@tonic-gate 	else {
76637c478bd9Sstevel@tonic-gate 		e = EINVAL;
76647c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG,
76657c478bd9Sstevel@tonic-gate 		    "iovec_ioctl: bad command = %x\n", cmd));
76667c478bd9Sstevel@tonic-gate 	}
76677c478bd9Sstevel@tonic-gate 
76687c478bd9Sstevel@tonic-gate 
76697c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
76707c478bd9Sstevel@tonic-gate 	    "rsm_iovec_ioctl RSMPI oper done %d\n", e));
76717c478bd9Sstevel@tonic-gate 
76727c478bd9Sstevel@tonic-gate 	sg_io.io_residual_count = rsmpi_sg_io.io_residual_count;
76737c478bd9Sstevel@tonic-gate 
76747c478bd9Sstevel@tonic-gate 	/*
76757c478bd9Sstevel@tonic-gate 	 * Check for implicit signal post flag and do the signal
76767c478bd9Sstevel@tonic-gate 	 * post if needed
76777c478bd9Sstevel@tonic-gate 	 */
76787c478bd9Sstevel@tonic-gate 	if (sg_io.flags & RSM_IMPLICIT_SIGPOST &&
76797c478bd9Sstevel@tonic-gate 	    e == RSM_SUCCESS) {
76807c478bd9Sstevel@tonic-gate 		rsmipc_request_t request;
76817c478bd9Sstevel@tonic-gate 
76827c478bd9Sstevel@tonic-gate 		request.rsmipc_key = im_seg->s_segid;
76837c478bd9Sstevel@tonic-gate 		request.rsmipc_hdr.rsmipc_type = RSMIPC_MSG_BELL;
76847c478bd9Sstevel@tonic-gate 		request.rsmipc_segment_cookie = NULL;
76857c478bd9Sstevel@tonic-gate 		e = rsmipc_send(im_seg->s_node, &request, RSM_NO_REPLY);
76867c478bd9Sstevel@tonic-gate 		/*
76877c478bd9Sstevel@tonic-gate 		 * Reset the implicit signal post flag to 0 to indicate
76887c478bd9Sstevel@tonic-gate 		 * that the signal post has been done and need not be
76897c478bd9Sstevel@tonic-gate 		 * done in the RSMAPI library
76907c478bd9Sstevel@tonic-gate 		 */
76917c478bd9Sstevel@tonic-gate 		sg_io.flags &= ~RSM_IMPLICIT_SIGPOST;
76927c478bd9Sstevel@tonic-gate 	}
76937c478bd9Sstevel@tonic-gate 
76947c478bd9Sstevel@tonic-gate 	rsmseglock_acquire(im_seg);
76957c478bd9Sstevel@tonic-gate 	im_seg->s_rdmacnt--;
76967c478bd9Sstevel@tonic-gate 	if (im_seg->s_rdmacnt == 0) {
76977c478bd9Sstevel@tonic-gate 		cv_broadcast(&im_seg->s_cv);
76987c478bd9Sstevel@tonic-gate 	}
76997c478bd9Sstevel@tonic-gate 	rsmseglock_release(im_seg);
77007c478bd9Sstevel@tonic-gate 	error = sgio_resid_copyout(arg, &sg_io, mode);
77017c478bd9Sstevel@tonic-gate out:
77027c478bd9Sstevel@tonic-gate 	iovec = iovec_start;
77037c478bd9Sstevel@tonic-gate 	ka_iovec = ka_iovec_start;
77047c478bd9Sstevel@tonic-gate 	for (i = 0; i < iov_proc; i++) {
77057c478bd9Sstevel@tonic-gate 		if (ka_iovec->io_type == RSM_HANDLE_TYPE) {
77067c478bd9Sstevel@tonic-gate 			ex_seg = rsmexport_lookup(ka_iovec->local.segid);
77077c478bd9Sstevel@tonic-gate 
77087c478bd9Sstevel@tonic-gate 			ASSERT(ex_seg != NULL);
77097c478bd9Sstevel@tonic-gate 			ASSERT(ex_seg->s_state == RSM_STATE_EXPORT);
77107c478bd9Sstevel@tonic-gate 
77117c478bd9Sstevel@tonic-gate 			ex_seg->s_rdmacnt--; /* unrefcnt the handle */
77127c478bd9Sstevel@tonic-gate 			if (ex_seg->s_rdmacnt == 0) {
77137c478bd9Sstevel@tonic-gate 				cv_broadcast(&ex_seg->s_cv);
77147c478bd9Sstevel@tonic-gate 			}
77157c478bd9Sstevel@tonic-gate 			rsmseglock_release(ex_seg);
77167c478bd9Sstevel@tonic-gate 		}
77177c478bd9Sstevel@tonic-gate 
77187c478bd9Sstevel@tonic-gate 		ASSERT(iovec != NULL); /* true if iov_proc > 0 */
77197c478bd9Sstevel@tonic-gate 
77207c478bd9Sstevel@tonic-gate 		/*
77217c478bd9Sstevel@tonic-gate 		 * At present there is no dependency on the existence of xbufs
77227c478bd9Sstevel@tonic-gate 		 * created by ddi_umem_iosetup for each of the iovecs. So we
77237c478bd9Sstevel@tonic-gate 		 * can these xbufs here.
77247c478bd9Sstevel@tonic-gate 		 */
77257c478bd9Sstevel@tonic-gate 		if (iovec->local_mem.ms_type == RSM_MEM_BUF) {
77267c478bd9Sstevel@tonic-gate 			freerbuf(iovec->local_mem.ms_memory.bp);
77277c478bd9Sstevel@tonic-gate 		}
77287c478bd9Sstevel@tonic-gate 
77297c478bd9Sstevel@tonic-gate 		iovec++;
77307c478bd9Sstevel@tonic-gate 		ka_iovec++;
77317c478bd9Sstevel@tonic-gate 	}
77327c478bd9Sstevel@tonic-gate 
77337c478bd9Sstevel@tonic-gate 	if (sg_io.io_request_count > RSM_MAX_IOVLEN) {
77347c478bd9Sstevel@tonic-gate 		if (iovec_start)
77357c478bd9Sstevel@tonic-gate 			kmem_free(iovec_start, size);
77367c478bd9Sstevel@tonic-gate 		kmem_free(ka_iovec_start, ka_size);
77377c478bd9Sstevel@tonic-gate 	}
77387c478bd9Sstevel@tonic-gate 
77397c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
77407c478bd9Sstevel@tonic-gate 	    "rsm_iovec_ioctl done %d\n", e));
77417c478bd9Sstevel@tonic-gate 	/* if RSMPI call fails return that else return copyout's retval */
77427c478bd9Sstevel@tonic-gate 	return ((e != RSM_SUCCESS) ? e : error);
77437c478bd9Sstevel@tonic-gate 
77447c478bd9Sstevel@tonic-gate }
77457c478bd9Sstevel@tonic-gate 
77467c478bd9Sstevel@tonic-gate 
77477c478bd9Sstevel@tonic-gate static int
rsmaddr_ioctl(int cmd,rsm_ioctlmsg_t * msg,int mode)77487c478bd9Sstevel@tonic-gate rsmaddr_ioctl(int cmd, rsm_ioctlmsg_t *msg, int mode)
77497c478bd9Sstevel@tonic-gate {
77507c478bd9Sstevel@tonic-gate 	adapter_t	*adapter;
77517c478bd9Sstevel@tonic-gate 	rsm_addr_t	addr;
77527c478bd9Sstevel@tonic-gate 	rsm_node_id_t	node;
77537c478bd9Sstevel@tonic-gate 	int		rval = DDI_SUCCESS;
77547c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_IOCTL);
77557c478bd9Sstevel@tonic-gate 
77567c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmaddr_ioctl enter\n"));
77577c478bd9Sstevel@tonic-gate 
77587c478bd9Sstevel@tonic-gate 	adapter =  rsm_getadapter(msg, mode);
77597c478bd9Sstevel@tonic-gate 	if (adapter == NULL) {
77607c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG,
77617c478bd9Sstevel@tonic-gate 		    "rsmaddr_ioctl done: adapter not found\n"));
77627c478bd9Sstevel@tonic-gate 		return (RSMERR_CTLR_NOT_PRESENT);
77637c478bd9Sstevel@tonic-gate 	}
77647c478bd9Sstevel@tonic-gate 
77657c478bd9Sstevel@tonic-gate 	switch (cmd) {
77667c478bd9Sstevel@tonic-gate 	case RSM_IOCTL_MAP_TO_ADDR: /* nodeid to hwaddr mapping */
77677c478bd9Sstevel@tonic-gate 		/* returns the hwaddr in msg->hwaddr */
77687c478bd9Sstevel@tonic-gate 		if (msg->nodeid == my_nodeid) {
77697c478bd9Sstevel@tonic-gate 			msg->hwaddr = adapter->hwaddr;
77707c478bd9Sstevel@tonic-gate 		} else {
77717c478bd9Sstevel@tonic-gate 			addr = get_remote_hwaddr(adapter, msg->nodeid);
77727c478bd9Sstevel@tonic-gate 			if ((int64_t)addr < 0) {
77737c478bd9Sstevel@tonic-gate 				rval = RSMERR_INTERNAL_ERROR;
77747c478bd9Sstevel@tonic-gate 			} else {
77757c478bd9Sstevel@tonic-gate 				msg->hwaddr = addr;
77767c478bd9Sstevel@tonic-gate 			}
77777c478bd9Sstevel@tonic-gate 		}
77787c478bd9Sstevel@tonic-gate 		break;
77797c478bd9Sstevel@tonic-gate 	case RSM_IOCTL_MAP_TO_NODEID: /* hwaddr to nodeid mapping */
77807c478bd9Sstevel@tonic-gate 		/* returns the nodeid in msg->nodeid */
77817c478bd9Sstevel@tonic-gate 		if (msg->hwaddr == adapter->hwaddr) {
77827c478bd9Sstevel@tonic-gate 			msg->nodeid = my_nodeid;
77837c478bd9Sstevel@tonic-gate 		} else {
77847c478bd9Sstevel@tonic-gate 			node = get_remote_nodeid(adapter, msg->hwaddr);
77857c478bd9Sstevel@tonic-gate 			if ((int)node < 0) {
77867c478bd9Sstevel@tonic-gate 				rval = RSMERR_INTERNAL_ERROR;
77877c478bd9Sstevel@tonic-gate 			} else {
77887c478bd9Sstevel@tonic-gate 				msg->nodeid = (rsm_node_id_t)node;
77897c478bd9Sstevel@tonic-gate 			}
77907c478bd9Sstevel@tonic-gate 		}
77917c478bd9Sstevel@tonic-gate 		break;
77927c478bd9Sstevel@tonic-gate 	default:
77937c478bd9Sstevel@tonic-gate 		rval = EINVAL;
77947c478bd9Sstevel@tonic-gate 		break;
77957c478bd9Sstevel@tonic-gate 	}
77967c478bd9Sstevel@tonic-gate 
77977c478bd9Sstevel@tonic-gate 	rsmka_release_adapter(adapter);
77987c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
77997c478bd9Sstevel@tonic-gate 	    "rsmaddr_ioctl done: %d\n", rval));
78007c478bd9Sstevel@tonic-gate 	return (rval);
78017c478bd9Sstevel@tonic-gate }
78027c478bd9Sstevel@tonic-gate 
78037c478bd9Sstevel@tonic-gate static int
rsm_ddi_copyin(caddr_t arg,rsm_ioctlmsg_t * msg,int mode)78047c478bd9Sstevel@tonic-gate rsm_ddi_copyin(caddr_t arg, rsm_ioctlmsg_t *msg, int mode)
78057c478bd9Sstevel@tonic-gate {
78067c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category,
78077c478bd9Sstevel@tonic-gate 	    RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_IOCTL | RSM_DDI);
78087c478bd9Sstevel@tonic-gate 
78097c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_ddi_copyin enter\n"));
78107c478bd9Sstevel@tonic-gate 
78117c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
78127c478bd9Sstevel@tonic-gate 
78137c478bd9Sstevel@tonic-gate 	if ((mode & DATAMODEL_MASK) == DATAMODEL_ILP32) {
78147c478bd9Sstevel@tonic-gate 		rsm_ioctlmsg32_t msg32;
78157c478bd9Sstevel@tonic-gate 		int i;
78167c478bd9Sstevel@tonic-gate 
78177c478bd9Sstevel@tonic-gate 		if (ddi_copyin(arg, (caddr_t)&msg32, sizeof (msg32), mode)) {
78187c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
78197c478bd9Sstevel@tonic-gate 			    "rsm_ddi_copyin done: EFAULT\n"));
78207c478bd9Sstevel@tonic-gate 			return (RSMERR_BAD_ADDR);
78217c478bd9Sstevel@tonic-gate 		}
78227c478bd9Sstevel@tonic-gate 		msg->len = msg32.len;
78237c478bd9Sstevel@tonic-gate 		msg->vaddr = (caddr_t)(uintptr_t)msg32.vaddr;
78247c478bd9Sstevel@tonic-gate 		msg->arg = (caddr_t)(uintptr_t)msg32.arg;
78257c478bd9Sstevel@tonic-gate 		msg->key = msg32.key;
78267c478bd9Sstevel@tonic-gate 		msg->acl_len = msg32.acl_len;
78277c478bd9Sstevel@tonic-gate 		msg->acl = (rsmapi_access_entry_t *)(uintptr_t)msg32.acl;
78287c478bd9Sstevel@tonic-gate 		msg->cnum = msg32.cnum;
78297c478bd9Sstevel@tonic-gate 		msg->cname = (caddr_t)(uintptr_t)msg32.cname;
78307c478bd9Sstevel@tonic-gate 		msg->cname_len = msg32.cname_len;
78317c478bd9Sstevel@tonic-gate 		msg->nodeid = msg32.nodeid;
78327c478bd9Sstevel@tonic-gate 		msg->hwaddr = msg32.hwaddr;
78337c478bd9Sstevel@tonic-gate 		msg->perm = msg32.perm;
78347c478bd9Sstevel@tonic-gate 		for (i = 0; i < 4; i++) {
78357c478bd9Sstevel@tonic-gate 			msg->bar.comp[i].u64 = msg32.bar.comp[i].u64;
78367c478bd9Sstevel@tonic-gate 		}
78377c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
78387c478bd9Sstevel@tonic-gate 		    "rsm_ddi_copyin done\n"));
78397c478bd9Sstevel@tonic-gate 		return (RSM_SUCCESS);
78407c478bd9Sstevel@tonic-gate 	}
78417c478bd9Sstevel@tonic-gate #endif
78427c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_ddi_copyin done\n"));
78437c478bd9Sstevel@tonic-gate 	if (ddi_copyin(arg, (caddr_t)msg, sizeof (*msg), mode))
78447c478bd9Sstevel@tonic-gate 		return (RSMERR_BAD_ADDR);
78457c478bd9Sstevel@tonic-gate 	else
78467c478bd9Sstevel@tonic-gate 		return (RSM_SUCCESS);
78477c478bd9Sstevel@tonic-gate }
78487c478bd9Sstevel@tonic-gate 
78497c478bd9Sstevel@tonic-gate static int
rsmattr_ddi_copyout(adapter_t * adapter,caddr_t arg,int mode)78507c478bd9Sstevel@tonic-gate rsmattr_ddi_copyout(adapter_t *adapter, caddr_t arg, int mode)
78517c478bd9Sstevel@tonic-gate {
78527c478bd9Sstevel@tonic-gate 	rsmka_int_controller_attr_t	rsm_cattr;
78537c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category,
78547c478bd9Sstevel@tonic-gate 	    RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_IOCTL | RSM_DDI);
78557c478bd9Sstevel@tonic-gate 
78567c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
78577c478bd9Sstevel@tonic-gate 	    "rsmattr_ddi_copyout enter\n"));
78587c478bd9Sstevel@tonic-gate 	/*
78597c478bd9Sstevel@tonic-gate 	 * need to copy appropriate data from rsm_controller_attr_t
78607c478bd9Sstevel@tonic-gate 	 * to rsmka_int_controller_attr_t
78617c478bd9Sstevel@tonic-gate 	 */
78627c478bd9Sstevel@tonic-gate #ifdef	_MULTI_DATAMODEL
78637c478bd9Sstevel@tonic-gate 	if ((mode & DATAMODEL_MASK) == DATAMODEL_ILP32) {
78647c478bd9Sstevel@tonic-gate 		rsmka_int_controller_attr32_t rsm_cattr32;
78657c478bd9Sstevel@tonic-gate 
78667c478bd9Sstevel@tonic-gate 		rsm_cattr32.attr_direct_access_sizes =
78677c478bd9Sstevel@tonic-gate 		    adapter->rsm_attr.attr_direct_access_sizes;
78687c478bd9Sstevel@tonic-gate 		rsm_cattr32.attr_atomic_sizes =
78697c478bd9Sstevel@tonic-gate 		    adapter->rsm_attr.attr_atomic_sizes;
78707c478bd9Sstevel@tonic-gate 		rsm_cattr32.attr_page_size =
78717c478bd9Sstevel@tonic-gate 		    adapter->rsm_attr.attr_page_size;
78727c478bd9Sstevel@tonic-gate 		if (adapter->rsm_attr.attr_max_export_segment_size >
78737c478bd9Sstevel@tonic-gate 		    UINT_MAX)
78747c478bd9Sstevel@tonic-gate 			rsm_cattr32.attr_max_export_segment_size =
78757c478bd9Sstevel@tonic-gate 			    RSM_MAXSZ_PAGE_ALIGNED;
78767c478bd9Sstevel@tonic-gate 		else
78777c478bd9Sstevel@tonic-gate 			rsm_cattr32.attr_max_export_segment_size =
78787c478bd9Sstevel@tonic-gate 			    adapter->rsm_attr.attr_max_export_segment_size;
78797c478bd9Sstevel@tonic-gate 		if (adapter->rsm_attr.attr_tot_export_segment_size >
78807c478bd9Sstevel@tonic-gate 		    UINT_MAX)
78817c478bd9Sstevel@tonic-gate 			rsm_cattr32.attr_tot_export_segment_size =
78827c478bd9Sstevel@tonic-gate 			    RSM_MAXSZ_PAGE_ALIGNED;
78837c478bd9Sstevel@tonic-gate 		else
78847c478bd9Sstevel@tonic-gate 			rsm_cattr32.attr_tot_export_segment_size =
78857c478bd9Sstevel@tonic-gate 			    adapter->rsm_attr.attr_tot_export_segment_size;
78867c478bd9Sstevel@tonic-gate 		if (adapter->rsm_attr.attr_max_export_segments >
78877c478bd9Sstevel@tonic-gate 		    UINT_MAX)
78887c478bd9Sstevel@tonic-gate 			rsm_cattr32.attr_max_export_segments =
78897c478bd9Sstevel@tonic-gate 			    UINT_MAX;
78907c478bd9Sstevel@tonic-gate 		else
78917c478bd9Sstevel@tonic-gate 			rsm_cattr32.attr_max_export_segments =
78927c478bd9Sstevel@tonic-gate 			    adapter->rsm_attr.attr_max_export_segments;
78937c478bd9Sstevel@tonic-gate 		if (adapter->rsm_attr.attr_max_import_map_size >
78947c478bd9Sstevel@tonic-gate 		    UINT_MAX)
78957c478bd9Sstevel@tonic-gate 			rsm_cattr32.attr_max_import_map_size =
78967c478bd9Sstevel@tonic-gate 			    RSM_MAXSZ_PAGE_ALIGNED;
78977c478bd9Sstevel@tonic-gate 		else
78987c478bd9Sstevel@tonic-gate 			rsm_cattr32.attr_max_import_map_size =
78997c478bd9Sstevel@tonic-gate 			    adapter->rsm_attr.attr_max_import_map_size;
79007c478bd9Sstevel@tonic-gate 		if (adapter->rsm_attr.attr_tot_import_map_size >
79017c478bd9Sstevel@tonic-gate 		    UINT_MAX)
79027c478bd9Sstevel@tonic-gate 			rsm_cattr32.attr_tot_import_map_size =
79037c478bd9Sstevel@tonic-gate 			    RSM_MAXSZ_PAGE_ALIGNED;
79047c478bd9Sstevel@tonic-gate 		else
79057c478bd9Sstevel@tonic-gate 			rsm_cattr32.attr_tot_import_map_size =
79067c478bd9Sstevel@tonic-gate 			    adapter->rsm_attr.attr_tot_import_map_size;
79077c478bd9Sstevel@tonic-gate 		if (adapter->rsm_attr.attr_max_import_segments >
79087c478bd9Sstevel@tonic-gate 		    UINT_MAX)
79097c478bd9Sstevel@tonic-gate 			rsm_cattr32.attr_max_import_segments =
79107c478bd9Sstevel@tonic-gate 			    UINT_MAX;
79117c478bd9Sstevel@tonic-gate 		else
79127c478bd9Sstevel@tonic-gate 			rsm_cattr32.attr_max_import_segments =
79137c478bd9Sstevel@tonic-gate 			    adapter->rsm_attr.attr_max_import_segments;
79147c478bd9Sstevel@tonic-gate 		rsm_cattr32.attr_controller_addr =
79157c478bd9Sstevel@tonic-gate 		    adapter->rsm_attr.attr_controller_addr;
79167c478bd9Sstevel@tonic-gate 
79177c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
79187c478bd9Sstevel@tonic-gate 		    "rsmattr_ddi_copyout done\n"));
79197c478bd9Sstevel@tonic-gate 		if (ddi_copyout((caddr_t)&rsm_cattr32, arg,
79207c478bd9Sstevel@tonic-gate 		    sizeof (rsmka_int_controller_attr32_t), mode)) {
79217c478bd9Sstevel@tonic-gate 			return (RSMERR_BAD_ADDR);
79227c478bd9Sstevel@tonic-gate 		}
79237c478bd9Sstevel@tonic-gate 		else
79247c478bd9Sstevel@tonic-gate 			return (RSM_SUCCESS);
79257c478bd9Sstevel@tonic-gate 	}
79267c478bd9Sstevel@tonic-gate #endif
79277c478bd9Sstevel@tonic-gate 	rsm_cattr.attr_direct_access_sizes =
79287c478bd9Sstevel@tonic-gate 	    adapter->rsm_attr.attr_direct_access_sizes;
79297c478bd9Sstevel@tonic-gate 	rsm_cattr.attr_atomic_sizes =
79307c478bd9Sstevel@tonic-gate 	    adapter->rsm_attr.attr_atomic_sizes;
79317c478bd9Sstevel@tonic-gate 	rsm_cattr.attr_page_size =
79327c478bd9Sstevel@tonic-gate 	    adapter->rsm_attr.attr_page_size;
79337c478bd9Sstevel@tonic-gate 	rsm_cattr.attr_max_export_segment_size =
79347c478bd9Sstevel@tonic-gate 	    adapter->rsm_attr.attr_max_export_segment_size;
79357c478bd9Sstevel@tonic-gate 	rsm_cattr.attr_tot_export_segment_size =
79367c478bd9Sstevel@tonic-gate 	    adapter->rsm_attr.attr_tot_export_segment_size;
79377c478bd9Sstevel@tonic-gate 	rsm_cattr.attr_max_export_segments =
79387c478bd9Sstevel@tonic-gate 	    adapter->rsm_attr.attr_max_export_segments;
79397c478bd9Sstevel@tonic-gate 	rsm_cattr.attr_max_import_map_size =
79407c478bd9Sstevel@tonic-gate 	    adapter->rsm_attr.attr_max_import_map_size;
79417c478bd9Sstevel@tonic-gate 	rsm_cattr.attr_tot_import_map_size =
79427c478bd9Sstevel@tonic-gate 	    adapter->rsm_attr.attr_tot_import_map_size;
79437c478bd9Sstevel@tonic-gate 	rsm_cattr.attr_max_import_segments =
79447c478bd9Sstevel@tonic-gate 	    adapter->rsm_attr.attr_max_import_segments;
79457c478bd9Sstevel@tonic-gate 	rsm_cattr.attr_controller_addr =
79467c478bd9Sstevel@tonic-gate 	    adapter->rsm_attr.attr_controller_addr;
79477c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
79487c478bd9Sstevel@tonic-gate 	    "rsmattr_ddi_copyout done\n"));
79497c478bd9Sstevel@tonic-gate 	if (ddi_copyout((caddr_t)&rsm_cattr, arg,
79507c478bd9Sstevel@tonic-gate 	    sizeof (rsmka_int_controller_attr_t), mode)) {
79517c478bd9Sstevel@tonic-gate 		return (RSMERR_BAD_ADDR);
79527c478bd9Sstevel@tonic-gate 	}
79537c478bd9Sstevel@tonic-gate 	else
79547c478bd9Sstevel@tonic-gate 		return (RSM_SUCCESS);
79557c478bd9Sstevel@tonic-gate }
79567c478bd9Sstevel@tonic-gate 
79577c478bd9Sstevel@tonic-gate /*ARGSUSED*/
79587c478bd9Sstevel@tonic-gate static int
rsm_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * rvalp)79597c478bd9Sstevel@tonic-gate rsm_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
79607c478bd9Sstevel@tonic-gate     int *rvalp)
79617c478bd9Sstevel@tonic-gate {
79627c478bd9Sstevel@tonic-gate 	rsmseg_t *seg;
79637c478bd9Sstevel@tonic-gate 	rsmresource_t	*res;
79647c478bd9Sstevel@tonic-gate 	minor_t		rnum;
79657c478bd9Sstevel@tonic-gate 	rsm_ioctlmsg_t msg = {0};
79667c478bd9Sstevel@tonic-gate 	int error;
79677c478bd9Sstevel@tonic-gate 	adapter_t *adapter;
79687c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_IOCTL);
79697c478bd9Sstevel@tonic-gate 
79707c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_ioctl enter\n"));
79717c478bd9Sstevel@tonic-gate 
79727c478bd9Sstevel@tonic-gate 	if (cmd == RSM_IOCTL_CONSUMEEVENT) {
79737c478bd9Sstevel@tonic-gate 		error = rsm_consumeevent_ioctl((caddr_t)arg, mode);
79747c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
79757c478bd9Sstevel@tonic-gate 		    "rsm_ioctl RSM_IOCTL_CONSUMEEVENT done: %d\n", error));
79767c478bd9Sstevel@tonic-gate 		return (error);
79777c478bd9Sstevel@tonic-gate 	}
79787c478bd9Sstevel@tonic-gate 
79797c478bd9Sstevel@tonic-gate 	/* topology cmd does not use the arg common to other cmds */
79807c478bd9Sstevel@tonic-gate 	if (RSM_IOCTL_CMDGRP(cmd) == RSM_IOCTL_TOPOLOGY) {
79817c478bd9Sstevel@tonic-gate 		error = rsmka_topology_ioctl((caddr_t)arg, cmd, mode);
79827c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
79837c478bd9Sstevel@tonic-gate 		    "rsm_ioctl done: %d\n", error));
79847c478bd9Sstevel@tonic-gate 		return (error);
79857c478bd9Sstevel@tonic-gate 	}
79867c478bd9Sstevel@tonic-gate 
79877c478bd9Sstevel@tonic-gate 	if (RSM_IOCTL_CMDGRP(cmd) == RSM_IOCTL_IOVEC) {
79887c478bd9Sstevel@tonic-gate 		error = rsm_iovec_ioctl(dev, (caddr_t)arg, cmd, mode, credp);
79897c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
79907c478bd9Sstevel@tonic-gate 		    "rsm_ioctl done: %d\n", error));
79917c478bd9Sstevel@tonic-gate 		return (error);
79927c478bd9Sstevel@tonic-gate 	}
79937c478bd9Sstevel@tonic-gate 
79947c478bd9Sstevel@tonic-gate 	/*
79957c478bd9Sstevel@tonic-gate 	 * try to load arguments
79967c478bd9Sstevel@tonic-gate 	 */
79977c478bd9Sstevel@tonic-gate 	if (cmd != RSM_IOCTL_RING_BELL &&
79987c478bd9Sstevel@tonic-gate 	    rsm_ddi_copyin((caddr_t)arg, &msg, mode)) {
79997c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
80007c478bd9Sstevel@tonic-gate 		    "rsm_ioctl done: EFAULT\n"));
80017c478bd9Sstevel@tonic-gate 		return (RSMERR_BAD_ADDR);
80027c478bd9Sstevel@tonic-gate 	}
80037c478bd9Sstevel@tonic-gate 
80047c478bd9Sstevel@tonic-gate 	if (cmd == RSM_IOCTL_ATTR) {
80057c478bd9Sstevel@tonic-gate 		adapter =  rsm_getadapter(&msg, mode);
80067c478bd9Sstevel@tonic-gate 		if (adapter == NULL) {
80077c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG,
80087c478bd9Sstevel@tonic-gate 			    "rsm_ioctl done: ENODEV\n"));
80097c478bd9Sstevel@tonic-gate 			return (RSMERR_CTLR_NOT_PRESENT);
80107c478bd9Sstevel@tonic-gate 		}
80117c478bd9Sstevel@tonic-gate 		error = rsmattr_ddi_copyout(adapter, msg.arg, mode);
80127c478bd9Sstevel@tonic-gate 		rsmka_release_adapter(adapter);
80137c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG,
80147c478bd9Sstevel@tonic-gate 		    "rsm_ioctl:after copyout %d\n", error));
80157c478bd9Sstevel@tonic-gate 		return (error);
80167c478bd9Sstevel@tonic-gate 	}
80177c478bd9Sstevel@tonic-gate 
80187c478bd9Sstevel@tonic-gate 	if (cmd == RSM_IOCTL_BAR_INFO) {
80197c478bd9Sstevel@tonic-gate 		/* Return library off,len of barrier page */
80207c478bd9Sstevel@tonic-gate 		msg.off = barrier_offset;
80217c478bd9Sstevel@tonic-gate 		msg.len = (int)barrier_size;
80227c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
80237c478bd9Sstevel@tonic-gate 		if ((mode & DATAMODEL_MASK) == DATAMODEL_ILP32) {
80247c478bd9Sstevel@tonic-gate 			rsm_ioctlmsg32_t msg32;
80257c478bd9Sstevel@tonic-gate 
80267c478bd9Sstevel@tonic-gate 			if (msg.len > UINT_MAX)
80277c478bd9Sstevel@tonic-gate 				msg.len = RSM_MAXSZ_PAGE_ALIGNED;
80287c478bd9Sstevel@tonic-gate 			else
80297c478bd9Sstevel@tonic-gate 				msg32.len = (int32_t)msg.len;
80307c478bd9Sstevel@tonic-gate 			msg32.off = (int32_t)msg.off;
80317c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
80327c478bd9Sstevel@tonic-gate 			    "rsm_ioctl done\n"));
80337c478bd9Sstevel@tonic-gate 			if (ddi_copyout((caddr_t)&msg32, (caddr_t)arg,
80347c478bd9Sstevel@tonic-gate 			    sizeof (msg32), mode))
80357c478bd9Sstevel@tonic-gate 				return (RSMERR_BAD_ADDR);
80367c478bd9Sstevel@tonic-gate 			else
80377c478bd9Sstevel@tonic-gate 				return (RSM_SUCCESS);
80387c478bd9Sstevel@tonic-gate 		}
80397c478bd9Sstevel@tonic-gate #endif
80407c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
80417c478bd9Sstevel@tonic-gate 		    "rsm_ioctl done\n"));
80427c478bd9Sstevel@tonic-gate 		if (ddi_copyout((caddr_t)&msg, (caddr_t)arg,
80437c478bd9Sstevel@tonic-gate 		    sizeof (msg), mode))
80447c478bd9Sstevel@tonic-gate 			return (RSMERR_BAD_ADDR);
80457c478bd9Sstevel@tonic-gate 		else
80467c478bd9Sstevel@tonic-gate 			return (RSM_SUCCESS);
80477c478bd9Sstevel@tonic-gate 	}
80487c478bd9Sstevel@tonic-gate 
80497c478bd9Sstevel@tonic-gate 	if (RSM_IOCTL_CMDGRP(cmd) == RSM_IOCTL_MAP_ADDR) {
80507c478bd9Sstevel@tonic-gate 		/* map the nodeid or hwaddr */
80517c478bd9Sstevel@tonic-gate 		error = rsmaddr_ioctl(cmd, &msg, mode);
80527c478bd9Sstevel@tonic-gate 		if (error == RSM_SUCCESS) {
80537c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
80547c478bd9Sstevel@tonic-gate 			if ((mode & DATAMODEL_MASK) == DATAMODEL_ILP32) {
80557c478bd9Sstevel@tonic-gate 				rsm_ioctlmsg32_t msg32;
80567c478bd9Sstevel@tonic-gate 
80577c478bd9Sstevel@tonic-gate 				msg32.hwaddr = (uint64_t)msg.hwaddr;
80587c478bd9Sstevel@tonic-gate 				msg32.nodeid = (uint32_t)msg.nodeid;
80597c478bd9Sstevel@tonic-gate 
80607c478bd9Sstevel@tonic-gate 				DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
80617c478bd9Sstevel@tonic-gate 				    "rsm_ioctl done\n"));
80627c478bd9Sstevel@tonic-gate 				if (ddi_copyout((caddr_t)&msg32, (caddr_t)arg,
80637c478bd9Sstevel@tonic-gate 				    sizeof (msg32), mode))
80647c478bd9Sstevel@tonic-gate 					return (RSMERR_BAD_ADDR);
80657c478bd9Sstevel@tonic-gate 				else
80667c478bd9Sstevel@tonic-gate 					return (RSM_SUCCESS);
80677c478bd9Sstevel@tonic-gate 			}
80687c478bd9Sstevel@tonic-gate #endif
80697c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
80707c478bd9Sstevel@tonic-gate 			    "rsm_ioctl done\n"));
80717c478bd9Sstevel@tonic-gate 			if (ddi_copyout((caddr_t)&msg, (caddr_t)arg,
80727c478bd9Sstevel@tonic-gate 			    sizeof (msg), mode))
80737c478bd9Sstevel@tonic-gate 				return (RSMERR_BAD_ADDR);
80747c478bd9Sstevel@tonic-gate 			else
80757c478bd9Sstevel@tonic-gate 				return (RSM_SUCCESS);
80767c478bd9Sstevel@tonic-gate 		}
80777c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
80787c478bd9Sstevel@tonic-gate 		    "rsm_ioctl done: %d\n", error));
80797c478bd9Sstevel@tonic-gate 		return (error);
80807c478bd9Sstevel@tonic-gate 	}
80817c478bd9Sstevel@tonic-gate 
80827c478bd9Sstevel@tonic-gate 	/* Find resource and look it in read mode */
80837c478bd9Sstevel@tonic-gate 	rnum = getminor(dev);
80847c478bd9Sstevel@tonic-gate 	res = rsmresource_lookup(rnum, RSM_NOLOCK);
80857c478bd9Sstevel@tonic-gate 	ASSERT(res != NULL);
80867c478bd9Sstevel@tonic-gate 
80877c478bd9Sstevel@tonic-gate 	/*
80887c478bd9Sstevel@tonic-gate 	 * Find command group
80897c478bd9Sstevel@tonic-gate 	 */
80907c478bd9Sstevel@tonic-gate 	switch (RSM_IOCTL_CMDGRP(cmd)) {
80917c478bd9Sstevel@tonic-gate 	case RSM_IOCTL_EXPORT_SEG:
80927c478bd9Sstevel@tonic-gate 		/*
80937c478bd9Sstevel@tonic-gate 		 * Export list is searched during publish, loopback and
80947c478bd9Sstevel@tonic-gate 		 * remote lookup call.
80957c478bd9Sstevel@tonic-gate 		 */
80967c478bd9Sstevel@tonic-gate 		seg = rsmresource_seg(res, rnum, credp,
80977c478bd9Sstevel@tonic-gate 		    RSM_RESOURCE_EXPORT_SEGMENT);
80987c478bd9Sstevel@tonic-gate 		if (seg->s_type == RSM_RESOURCE_EXPORT_SEGMENT) {
80997c478bd9Sstevel@tonic-gate 			error = rsmexport_ioctl(seg, &msg, cmd, arg, mode,
81007c478bd9Sstevel@tonic-gate 			    credp);
81017c478bd9Sstevel@tonic-gate 		} else { /* export ioctl on an import/barrier resource */
81027c478bd9Sstevel@tonic-gate 			error = RSMERR_BAD_SEG_HNDL;
81037c478bd9Sstevel@tonic-gate 		}
81047c478bd9Sstevel@tonic-gate 		break;
81057c478bd9Sstevel@tonic-gate 	case RSM_IOCTL_IMPORT_SEG:
81067c478bd9Sstevel@tonic-gate 		/* Import list is searched during remote unmap call. */
81077c478bd9Sstevel@tonic-gate 		seg = rsmresource_seg(res, rnum, credp,
81087c478bd9Sstevel@tonic-gate 		    RSM_RESOURCE_IMPORT_SEGMENT);
81097c478bd9Sstevel@tonic-gate 		if (seg->s_type == RSM_RESOURCE_IMPORT_SEGMENT) {
81107c478bd9Sstevel@tonic-gate 			error = rsmimport_ioctl(seg, &msg, cmd, arg, mode,
81117c478bd9Sstevel@tonic-gate 			    credp);
81127c478bd9Sstevel@tonic-gate 		} else  { /* import ioctl on an export/barrier resource */
81137c478bd9Sstevel@tonic-gate 			error = RSMERR_BAD_SEG_HNDL;
81147c478bd9Sstevel@tonic-gate 		}
81157c478bd9Sstevel@tonic-gate 		break;
81167c478bd9Sstevel@tonic-gate 	case RSM_IOCTL_BAR:
81177c478bd9Sstevel@tonic-gate 		if (res != RSMRC_RESERVED &&
81187c478bd9Sstevel@tonic-gate 		    res->rsmrc_type == RSM_RESOURCE_IMPORT_SEGMENT) {
81197c478bd9Sstevel@tonic-gate 			error = rsmbar_ioctl((rsmseg_t *)res, &msg, cmd, arg,
81207c478bd9Sstevel@tonic-gate 			    mode);
81217c478bd9Sstevel@tonic-gate 		} else { /* invalid res value */
81227c478bd9Sstevel@tonic-gate 			error = RSMERR_BAD_SEG_HNDL;
81237c478bd9Sstevel@tonic-gate 		}
81247c478bd9Sstevel@tonic-gate 		break;
81257c478bd9Sstevel@tonic-gate 	case RSM_IOCTL_BELL:
81267c478bd9Sstevel@tonic-gate 		if (res != RSMRC_RESERVED) {
81277c478bd9Sstevel@tonic-gate 			if (res->rsmrc_type == RSM_RESOURCE_IMPORT_SEGMENT)
81287c478bd9Sstevel@tonic-gate 				error = exportbell_ioctl((rsmseg_t *)res, cmd);
81297c478bd9Sstevel@tonic-gate 			else if (res->rsmrc_type == RSM_RESOURCE_EXPORT_SEGMENT)
81307c478bd9Sstevel@tonic-gate 				error = importbell_ioctl((rsmseg_t *)res, cmd);
81317c478bd9Sstevel@tonic-gate 			else /* RSM_RESOURCE_BAR */
81327c478bd9Sstevel@tonic-gate 				error = RSMERR_BAD_SEG_HNDL;
81337c478bd9Sstevel@tonic-gate 		} else { /* invalid res value */
81347c478bd9Sstevel@tonic-gate 			error = RSMERR_BAD_SEG_HNDL;
81357c478bd9Sstevel@tonic-gate 		}
81367c478bd9Sstevel@tonic-gate 		break;
81377c478bd9Sstevel@tonic-gate 	default:
81387c478bd9Sstevel@tonic-gate 		error = EINVAL;
81397c478bd9Sstevel@tonic-gate 	}
81407c478bd9Sstevel@tonic-gate 
81417c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_ioctl done: %d\n",
81427c478bd9Sstevel@tonic-gate 	    error));
81437c478bd9Sstevel@tonic-gate 	return (error);
81447c478bd9Sstevel@tonic-gate }
81457c478bd9Sstevel@tonic-gate 
81467c478bd9Sstevel@tonic-gate 
81477c478bd9Sstevel@tonic-gate /* **************************** Segment Mapping Operations ********* */
81487c478bd9Sstevel@tonic-gate static rsm_mapinfo_t *
rsm_get_mapinfo(rsmseg_t * seg,off_t off,size_t len,off_t * dev_offset,size_t * map_len)81497c478bd9Sstevel@tonic-gate rsm_get_mapinfo(rsmseg_t *seg, off_t off, size_t len, off_t *dev_offset,
81507c478bd9Sstevel@tonic-gate     size_t *map_len)
81517c478bd9Sstevel@tonic-gate {
81527c478bd9Sstevel@tonic-gate 	rsm_mapinfo_t	*p;
81537c478bd9Sstevel@tonic-gate 	/*
81547c478bd9Sstevel@tonic-gate 	 * Find the correct mapinfo structure to use during the mapping
81557c478bd9Sstevel@tonic-gate 	 * from the seg->s_mapinfo list.
81567c478bd9Sstevel@tonic-gate 	 * The seg->s_mapinfo list contains in reverse order the mappings
81577c478bd9Sstevel@tonic-gate 	 * as returned by the RSMPI rsm_map. In rsm_devmap, we need to
81587c478bd9Sstevel@tonic-gate 	 * access the correct entry within this list for the mapping
81597c478bd9Sstevel@tonic-gate 	 * requested.
81607c478bd9Sstevel@tonic-gate 	 *
81617c478bd9Sstevel@tonic-gate 	 * The algorithm for selecting a list entry is as follows:
81627c478bd9Sstevel@tonic-gate 	 *
81637c478bd9Sstevel@tonic-gate 	 * When start_offset of an entry <= off we have found the entry
81647c478bd9Sstevel@tonic-gate 	 * we were looking for. Adjust the dev_offset and map_len (needs
81657c478bd9Sstevel@tonic-gate 	 * to be PAGESIZE aligned).
81667c478bd9Sstevel@tonic-gate 	 */
81677c478bd9Sstevel@tonic-gate 	p = seg->s_mapinfo;
81687c478bd9Sstevel@tonic-gate 	for (; p; p = p->next) {
81697c478bd9Sstevel@tonic-gate 		if (p->start_offset <= off) {
81707c478bd9Sstevel@tonic-gate 			*dev_offset = p->dev_offset + off - p->start_offset;
81717c478bd9Sstevel@tonic-gate 			*map_len = (len > p->individual_len) ?
81727c478bd9Sstevel@tonic-gate 			    p->individual_len : ptob(btopr(len));
81737c478bd9Sstevel@tonic-gate 			return (p);
81747c478bd9Sstevel@tonic-gate 		}
81757c478bd9Sstevel@tonic-gate 		p = p->next;
81767c478bd9Sstevel@tonic-gate 	}
81777c478bd9Sstevel@tonic-gate 
81787c478bd9Sstevel@tonic-gate 	return (NULL);
81797c478bd9Sstevel@tonic-gate }
81807c478bd9Sstevel@tonic-gate 
81817c478bd9Sstevel@tonic-gate static void
rsm_free_mapinfo(rsm_mapinfo_t * mapinfo)81827c478bd9Sstevel@tonic-gate rsm_free_mapinfo(rsm_mapinfo_t  *mapinfo)
81837c478bd9Sstevel@tonic-gate {
81847c478bd9Sstevel@tonic-gate 	rsm_mapinfo_t *p;
81857c478bd9Sstevel@tonic-gate 
81867c478bd9Sstevel@tonic-gate 	while (mapinfo != NULL) {
81877c478bd9Sstevel@tonic-gate 		p = mapinfo;
81887c478bd9Sstevel@tonic-gate 		mapinfo = mapinfo->next;
81897c478bd9Sstevel@tonic-gate 		kmem_free(p, sizeof (*p));
81907c478bd9Sstevel@tonic-gate 	}
81917c478bd9Sstevel@tonic-gate }
81927c478bd9Sstevel@tonic-gate 
81937c478bd9Sstevel@tonic-gate static int
rsmmap_map(devmap_cookie_t dhp,dev_t dev,uint_t flags,offset_t off,size_t len,void ** pvtp)81947c478bd9Sstevel@tonic-gate rsmmap_map(devmap_cookie_t dhp, dev_t dev, uint_t flags, offset_t off,
81957c478bd9Sstevel@tonic-gate     size_t len, void **pvtp)
81967c478bd9Sstevel@tonic-gate {
81977c478bd9Sstevel@tonic-gate 	rsmcookie_t	*p;
81987c478bd9Sstevel@tonic-gate 	rsmresource_t	*res;
81997c478bd9Sstevel@tonic-gate 	rsmseg_t	*seg;
82007c478bd9Sstevel@tonic-gate 	minor_t rnum;
82017c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_DDI);
82027c478bd9Sstevel@tonic-gate 
82037c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmmap_map enter\n"));
82047c478bd9Sstevel@tonic-gate 
82057c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
82067c478bd9Sstevel@tonic-gate 	    "rsmmap_map: dhp = %x\n", dhp));
82077c478bd9Sstevel@tonic-gate 
82087c478bd9Sstevel@tonic-gate 	flags = flags;
82097c478bd9Sstevel@tonic-gate 
82107c478bd9Sstevel@tonic-gate 	rnum = getminor(dev);
82117c478bd9Sstevel@tonic-gate 	res = (rsmresource_t *)rsmresource_lookup(rnum, RSM_NOLOCK);
82127c478bd9Sstevel@tonic-gate 	ASSERT(res != NULL);
82137c478bd9Sstevel@tonic-gate 
82147c478bd9Sstevel@tonic-gate 	seg = (rsmseg_t *)res;
82157c478bd9Sstevel@tonic-gate 
82167c478bd9Sstevel@tonic-gate 	rsmseglock_acquire(seg);
82177c478bd9Sstevel@tonic-gate 
82187c478bd9Sstevel@tonic-gate 	ASSERT(seg->s_hdr.rsmrc_type == RSM_RESOURCE_IMPORT_SEGMENT);
82197c478bd9Sstevel@tonic-gate 
82207c478bd9Sstevel@tonic-gate 	/*
82217c478bd9Sstevel@tonic-gate 	 * Allocate structure and add cookie to segment list
82227c478bd9Sstevel@tonic-gate 	 */
82237c478bd9Sstevel@tonic-gate 	p = kmem_alloc(sizeof (*p), KM_SLEEP);
82247c478bd9Sstevel@tonic-gate 
82257c478bd9Sstevel@tonic-gate 	p->c_dhp = dhp;
82267c478bd9Sstevel@tonic-gate 	p->c_off = off;
82277c478bd9Sstevel@tonic-gate 	p->c_len = len;
82287c478bd9Sstevel@tonic-gate 	p->c_next = seg->s_ckl;
82297c478bd9Sstevel@tonic-gate 	seg->s_ckl = p;
82307c478bd9Sstevel@tonic-gate 
82317c478bd9Sstevel@tonic-gate 	*pvtp = (void *)seg;
82327c478bd9Sstevel@tonic-gate 
82337c478bd9Sstevel@tonic-gate 	rsmseglock_release(seg);
82347c478bd9Sstevel@tonic-gate 
82357c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmmap_map done\n"));
82367c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
82377c478bd9Sstevel@tonic-gate }
82387c478bd9Sstevel@tonic-gate 
82397c478bd9Sstevel@tonic-gate /*
82407c478bd9Sstevel@tonic-gate  * Page fault handling is done here. The prerequisite mapping setup
82417c478bd9Sstevel@tonic-gate  * has been done in rsm_devmap with calls to ddi_devmem_setup or
82427c478bd9Sstevel@tonic-gate  * ddi_umem_setup
82437c478bd9Sstevel@tonic-gate  */
82447c478bd9Sstevel@tonic-gate static int
rsmmap_access(devmap_cookie_t dhp,void * pvt,offset_t offset,size_t len,uint_t type,uint_t rw)82457c478bd9Sstevel@tonic-gate rsmmap_access(devmap_cookie_t dhp, void *pvt, offset_t offset, size_t len,
82467c478bd9Sstevel@tonic-gate     uint_t type, uint_t rw)
82477c478bd9Sstevel@tonic-gate {
82487c478bd9Sstevel@tonic-gate 	int e;
82497c478bd9Sstevel@tonic-gate 	rsmseg_t *seg = (rsmseg_t *)pvt;
82507c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_DDI);
82517c478bd9Sstevel@tonic-gate 
82527c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmmap_access enter\n"));
82537c478bd9Sstevel@tonic-gate 
82547c478bd9Sstevel@tonic-gate 	rsmseglock_acquire(seg);
82557c478bd9Sstevel@tonic-gate 
82567c478bd9Sstevel@tonic-gate 	ASSERT(seg->s_hdr.rsmrc_type == RSM_RESOURCE_IMPORT_SEGMENT);
82577c478bd9Sstevel@tonic-gate 
82587c478bd9Sstevel@tonic-gate 	while (seg->s_state == RSM_STATE_MAP_QUIESCE) {
82597c478bd9Sstevel@tonic-gate 		if (cv_wait_sig(&seg->s_cv, &seg->s_lock) == 0) {
82607c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG,
82617c478bd9Sstevel@tonic-gate 			    "rsmmap_access done: cv_wait INTR"));
82627c478bd9Sstevel@tonic-gate 			rsmseglock_release(seg);
82637c478bd9Sstevel@tonic-gate 			return (RSMERR_INTERRUPTED);
82647c478bd9Sstevel@tonic-gate 		}
82657c478bd9Sstevel@tonic-gate 	}
82667c478bd9Sstevel@tonic-gate 
82677c478bd9Sstevel@tonic-gate 	ASSERT(seg->s_state == RSM_STATE_DISCONNECT ||
82687c478bd9Sstevel@tonic-gate 	    seg->s_state == RSM_STATE_ACTIVE);
82697c478bd9Sstevel@tonic-gate 
82707c478bd9Sstevel@tonic-gate 	if (seg->s_state == RSM_STATE_DISCONNECT)
82717c478bd9Sstevel@tonic-gate 		seg->s_flags |= RSM_IMPORT_DUMMY;
82727c478bd9Sstevel@tonic-gate 
82737c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
82747c478bd9Sstevel@tonic-gate 	    "rsmmap_access: dhp = %x\n", dhp));
82757c478bd9Sstevel@tonic-gate 
82767c478bd9Sstevel@tonic-gate 	rsmseglock_release(seg);
82777c478bd9Sstevel@tonic-gate 
82787c478bd9Sstevel@tonic-gate 	if (e = devmap_load(dhp, offset, len, type, rw)) {
82797c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_ERR, "devmap_load failed\n"));
82807c478bd9Sstevel@tonic-gate 	}
82817c478bd9Sstevel@tonic-gate 
82827c478bd9Sstevel@tonic-gate 
82837c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmmap_access done\n"));
82847c478bd9Sstevel@tonic-gate 
82857c478bd9Sstevel@tonic-gate 	return (e);
82867c478bd9Sstevel@tonic-gate }
82877c478bd9Sstevel@tonic-gate 
82887c478bd9Sstevel@tonic-gate static int
rsmmap_dup(devmap_cookie_t dhp,void * oldpvt,devmap_cookie_t new_dhp,void ** newpvt)82897c478bd9Sstevel@tonic-gate rsmmap_dup(devmap_cookie_t dhp, void *oldpvt, devmap_cookie_t new_dhp,
82907c478bd9Sstevel@tonic-gate 	void **newpvt)
82917c478bd9Sstevel@tonic-gate {
82927c478bd9Sstevel@tonic-gate 	rsmseg_t	*seg = (rsmseg_t *)oldpvt;
82937c478bd9Sstevel@tonic-gate 	rsmcookie_t	*p, *old;
82947c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_DDI);
82957c478bd9Sstevel@tonic-gate 
82967c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmmap_dup enter\n"));
82977c478bd9Sstevel@tonic-gate 
82987c478bd9Sstevel@tonic-gate 	/*
82997c478bd9Sstevel@tonic-gate 	 * Same as map, create an entry to hold cookie and add it to
83007c478bd9Sstevel@tonic-gate 	 * connect segment list. The oldpvt is a pointer to segment.
83017c478bd9Sstevel@tonic-gate 	 * Return segment pointer in newpvt.
83027c478bd9Sstevel@tonic-gate 	 */
83037c478bd9Sstevel@tonic-gate 	rsmseglock_acquire(seg);
83047c478bd9Sstevel@tonic-gate 
83057c478bd9Sstevel@tonic-gate 	ASSERT(seg->s_hdr.rsmrc_type == RSM_RESOURCE_IMPORT_SEGMENT);
83067c478bd9Sstevel@tonic-gate 
83077c478bd9Sstevel@tonic-gate 	/*
83087c478bd9Sstevel@tonic-gate 	 * Find old cookie
83097c478bd9Sstevel@tonic-gate 	 */
83107c478bd9Sstevel@tonic-gate 	for (old = seg->s_ckl; old != NULL; old = old->c_next) {
83117c478bd9Sstevel@tonic-gate 		if (old->c_dhp == dhp) {
83127c478bd9Sstevel@tonic-gate 			break;
83137c478bd9Sstevel@tonic-gate 		}
83147c478bd9Sstevel@tonic-gate 	}
83157c478bd9Sstevel@tonic-gate 	if (old == NULL) {
83167c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
83177c478bd9Sstevel@tonic-gate 		    "rsmmap_dup done: EINVAL\n"));
83187c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
83197c478bd9Sstevel@tonic-gate 		return (EINVAL);
83207c478bd9Sstevel@tonic-gate 	}
83217c478bd9Sstevel@tonic-gate 
83227c478bd9Sstevel@tonic-gate 	p = kmem_alloc(sizeof (*p), KM_SLEEP);
83237c478bd9Sstevel@tonic-gate 
83247c478bd9Sstevel@tonic-gate 	p->c_dhp = new_dhp;
83257c478bd9Sstevel@tonic-gate 	p->c_off = old->c_off;
83267c478bd9Sstevel@tonic-gate 	p->c_len = old->c_len;
83277c478bd9Sstevel@tonic-gate 	p->c_next = seg->s_ckl;
83287c478bd9Sstevel@tonic-gate 	seg->s_ckl = p;
83297c478bd9Sstevel@tonic-gate 
83307c478bd9Sstevel@tonic-gate 	*newpvt = (void *)seg;
83317c478bd9Sstevel@tonic-gate 
83327c478bd9Sstevel@tonic-gate 	rsmseglock_release(seg);
83337c478bd9Sstevel@tonic-gate 
83347c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmmap_dup done\n"));
83357c478bd9Sstevel@tonic-gate 
83367c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
83377c478bd9Sstevel@tonic-gate }
83387c478bd9Sstevel@tonic-gate 
83397c478bd9Sstevel@tonic-gate static void
rsmmap_unmap(devmap_cookie_t dhp,void * pvtp,offset_t off,size_t len,devmap_cookie_t new_dhp1,void ** pvtp1,devmap_cookie_t new_dhp2,void ** pvtp2)83407c478bd9Sstevel@tonic-gate rsmmap_unmap(devmap_cookie_t dhp, void *pvtp, offset_t off, size_t len,
83417c478bd9Sstevel@tonic-gate 	devmap_cookie_t new_dhp1, void **pvtp1,
83427c478bd9Sstevel@tonic-gate 	devmap_cookie_t new_dhp2, void **pvtp2)
83437c478bd9Sstevel@tonic-gate {
83447c478bd9Sstevel@tonic-gate 	/*
83457c478bd9Sstevel@tonic-gate 	 * Remove pvtp structure from segment list.
83467c478bd9Sstevel@tonic-gate 	 */
83477c478bd9Sstevel@tonic-gate 	rsmseg_t	*seg = (rsmseg_t *)pvtp;
83487c478bd9Sstevel@tonic-gate 	int freeflag;
83497c478bd9Sstevel@tonic-gate 
83507c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_DDI);
83517c478bd9Sstevel@tonic-gate 
83527c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmmap_unmap enter\n"));
83537c478bd9Sstevel@tonic-gate 
83547c478bd9Sstevel@tonic-gate 	off = off; len = len;
83557c478bd9Sstevel@tonic-gate 	pvtp1 = pvtp1; pvtp2 = pvtp2;
83567c478bd9Sstevel@tonic-gate 
83577c478bd9Sstevel@tonic-gate 	rsmseglock_acquire(seg);
83587c478bd9Sstevel@tonic-gate 
83597c478bd9Sstevel@tonic-gate 	ASSERT(seg->s_hdr.rsmrc_type == RSM_RESOURCE_IMPORT_SEGMENT);
83607c478bd9Sstevel@tonic-gate 
83617c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
83627c478bd9Sstevel@tonic-gate 	    "rsmmap_unmap: dhp = %x\n", dhp));
83637c478bd9Sstevel@tonic-gate 	/*
83647c478bd9Sstevel@tonic-gate 	 * We can go ahead and remove the dhps even if we are in
83657c478bd9Sstevel@tonic-gate 	 * the MAPPING state because the dhps being removed here
83667c478bd9Sstevel@tonic-gate 	 * belong to a different mmap and we are holding the segment
83677c478bd9Sstevel@tonic-gate 	 * lock.
83687c478bd9Sstevel@tonic-gate 	 */
83697c478bd9Sstevel@tonic-gate 	if (new_dhp1 == NULL && new_dhp2 == NULL) {
83707c478bd9Sstevel@tonic-gate 		/* find and remove dhp handle */
83717c478bd9Sstevel@tonic-gate 		rsmcookie_t *tmp, **back = &seg->s_ckl;
83727c478bd9Sstevel@tonic-gate 
83737c478bd9Sstevel@tonic-gate 		while (*back != NULL) {
83747c478bd9Sstevel@tonic-gate 			tmp = *back;
83757c478bd9Sstevel@tonic-gate 			if (tmp->c_dhp == dhp) {
83767c478bd9Sstevel@tonic-gate 				*back = tmp->c_next;
83777c478bd9Sstevel@tonic-gate 				kmem_free(tmp, sizeof (*tmp));
83787c478bd9Sstevel@tonic-gate 				break;
83797c478bd9Sstevel@tonic-gate 			}
83807c478bd9Sstevel@tonic-gate 			back = &tmp->c_next;
83817c478bd9Sstevel@tonic-gate 		}
83827c478bd9Sstevel@tonic-gate 	} else {
83837c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_LVL2,
83847c478bd9Sstevel@tonic-gate 		    "rsmmap_unmap:parital unmap"
83857c478bd9Sstevel@tonic-gate 		    "new_dhp1 %lx, new_dhp2 %lx\n",
83867c478bd9Sstevel@tonic-gate 		    (size_t)new_dhp1, (size_t)new_dhp2));
83877c478bd9Sstevel@tonic-gate 	}
83887c478bd9Sstevel@tonic-gate 
83897c478bd9Sstevel@tonic-gate 	/*
83907c478bd9Sstevel@tonic-gate 	 * rsmmap_unmap is called for each mapping cookie on the list.
83917c478bd9Sstevel@tonic-gate 	 * When the list becomes empty and we are not in the MAPPING
83927c478bd9Sstevel@tonic-gate 	 * state then unmap in the rsmpi driver.
83937c478bd9Sstevel@tonic-gate 	 */
83947c478bd9Sstevel@tonic-gate 	if ((seg->s_ckl == NULL) && (seg->s_state != RSM_STATE_MAPPING))
83957c478bd9Sstevel@tonic-gate 		(void) rsm_unmap(seg);
83967c478bd9Sstevel@tonic-gate 
83977c478bd9Sstevel@tonic-gate 	if (seg->s_state == RSM_STATE_END && seg->s_ckl == NULL) {
83987c478bd9Sstevel@tonic-gate 		freeflag = 1;
83997c478bd9Sstevel@tonic-gate 	} else {
84007c478bd9Sstevel@tonic-gate 		freeflag = 0;
84017c478bd9Sstevel@tonic-gate 	}
84027c478bd9Sstevel@tonic-gate 
84037c478bd9Sstevel@tonic-gate 	rsmseglock_release(seg);
84047c478bd9Sstevel@tonic-gate 
84057c478bd9Sstevel@tonic-gate 	if (freeflag) {
84067c478bd9Sstevel@tonic-gate 		/* Free the segment structure */
84077c478bd9Sstevel@tonic-gate 		rsmseg_free(seg);
84087c478bd9Sstevel@tonic-gate 	}
84097c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsmmap_unmap done\n"));
84107c478bd9Sstevel@tonic-gate 
84117c478bd9Sstevel@tonic-gate }
84127c478bd9Sstevel@tonic-gate 
84137c478bd9Sstevel@tonic-gate static struct devmap_callback_ctl rsmmap_ops = {
84147c478bd9Sstevel@tonic-gate 	DEVMAP_OPS_REV,	/* devmap_ops version number	*/
84157c478bd9Sstevel@tonic-gate 	rsmmap_map,	/* devmap_ops map routine */
84167c478bd9Sstevel@tonic-gate 	rsmmap_access,	/* devmap_ops access routine */
84177c478bd9Sstevel@tonic-gate 	rsmmap_dup,		/* devmap_ops dup routine		*/
84187c478bd9Sstevel@tonic-gate 	rsmmap_unmap,	/* devmap_ops unmap routine */
84197c478bd9Sstevel@tonic-gate };
84207c478bd9Sstevel@tonic-gate 
84217c478bd9Sstevel@tonic-gate static int
rsm_devmap(dev_t dev,devmap_cookie_t dhc,offset_t off,size_t len,size_t * maplen,uint_t model)84227c478bd9Sstevel@tonic-gate rsm_devmap(dev_t dev, devmap_cookie_t dhc, offset_t off, size_t len,
84237c478bd9Sstevel@tonic-gate     size_t *maplen, uint_t model /*ARGSUSED*/)
84247c478bd9Sstevel@tonic-gate {
84257c478bd9Sstevel@tonic-gate 	struct devmap_callback_ctl *callbackops = &rsmmap_ops;
84267c478bd9Sstevel@tonic-gate 	int		err;
84277c478bd9Sstevel@tonic-gate 	uint_t		maxprot;
84287c478bd9Sstevel@tonic-gate 	minor_t		rnum;
84297c478bd9Sstevel@tonic-gate 	rsmseg_t	*seg;
84307c478bd9Sstevel@tonic-gate 	off_t		dev_offset;
84317c478bd9Sstevel@tonic-gate 	size_t		cur_len;
84327c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_DDI);
84337c478bd9Sstevel@tonic-gate 
84347c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_devmap enter\n"));
84357c478bd9Sstevel@tonic-gate 
84367c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
84377c478bd9Sstevel@tonic-gate 	    "rsm_devmap: off = %lx, len = %lx\n", off, len));
84387c478bd9Sstevel@tonic-gate 	rnum = getminor(dev);
84397c478bd9Sstevel@tonic-gate 	seg = (rsmseg_t *)rsmresource_lookup(rnum, RSM_NOLOCK);
84407c478bd9Sstevel@tonic-gate 	ASSERT(seg != NULL);
84417c478bd9Sstevel@tonic-gate 
84427c478bd9Sstevel@tonic-gate 	if (seg->s_hdr.rsmrc_type == RSM_RESOURCE_BAR) {
84437c478bd9Sstevel@tonic-gate 		if ((off == barrier_offset) &&
84447c478bd9Sstevel@tonic-gate 		    (len == barrier_size)) {
84457c478bd9Sstevel@tonic-gate 
84467c478bd9Sstevel@tonic-gate 			ASSERT(bar_va != NULL && bar_cookie != NULL);
84477c478bd9Sstevel@tonic-gate 
84487c478bd9Sstevel@tonic-gate 			/*
84497c478bd9Sstevel@tonic-gate 			 * The offset argument in devmap_umem_setup represents
84507c478bd9Sstevel@tonic-gate 			 * the offset within the kernel memory defined by the
84517c478bd9Sstevel@tonic-gate 			 * cookie. We use this offset as barrier_offset.
84527c478bd9Sstevel@tonic-gate 			 */
84537c478bd9Sstevel@tonic-gate 			err = devmap_umem_setup(dhc, rsm_dip, NULL, bar_cookie,
84547c478bd9Sstevel@tonic-gate 			    barrier_offset, len, PROT_USER|PROT_READ,
84557c478bd9Sstevel@tonic-gate 			    DEVMAP_DEFAULTS, 0);
84567c478bd9Sstevel@tonic-gate 
84577c478bd9Sstevel@tonic-gate 			if (err != 0) {
84587c478bd9Sstevel@tonic-gate 				DBG_PRINTF((category, RSM_ERR,
84597c478bd9Sstevel@tonic-gate 				    "rsm_devmap done: %d\n", err));
84607c478bd9Sstevel@tonic-gate 				return (RSMERR_MAP_FAILED);
84617c478bd9Sstevel@tonic-gate 			}
84627c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
84637c478bd9Sstevel@tonic-gate 			    "rsm_devmap done: %d\n", err));
84647c478bd9Sstevel@tonic-gate 
84657c478bd9Sstevel@tonic-gate 			*maplen = barrier_size;
84667c478bd9Sstevel@tonic-gate 
84677c478bd9Sstevel@tonic-gate 			return (err);
84687c478bd9Sstevel@tonic-gate 		} else {
84697c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
84707c478bd9Sstevel@tonic-gate 			    "rsm_devmap done: %d\n", err));
84717c478bd9Sstevel@tonic-gate 			return (RSMERR_MAP_FAILED);
84727c478bd9Sstevel@tonic-gate 		}
84737c478bd9Sstevel@tonic-gate 	}
84747c478bd9Sstevel@tonic-gate 
84757c478bd9Sstevel@tonic-gate 	ASSERT(seg->s_hdr.rsmrc_type == RSM_RESOURCE_IMPORT_SEGMENT);
84767c478bd9Sstevel@tonic-gate 	ASSERT(seg->s_state == RSM_STATE_MAPPING);
84777c478bd9Sstevel@tonic-gate 
84787c478bd9Sstevel@tonic-gate 	/*
84797c478bd9Sstevel@tonic-gate 	 * Make sure we still have permission for the map operation.
84807c478bd9Sstevel@tonic-gate 	 */
84817c478bd9Sstevel@tonic-gate 	maxprot = PROT_USER;
84827c478bd9Sstevel@tonic-gate 	if (seg->s_mode & RSM_PERM_READ) {
84837c478bd9Sstevel@tonic-gate 		maxprot |= PROT_READ;
84847c478bd9Sstevel@tonic-gate 	}
84857c478bd9Sstevel@tonic-gate 
84867c478bd9Sstevel@tonic-gate 	if (seg->s_mode & RSM_PERM_WRITE) {
84877c478bd9Sstevel@tonic-gate 		maxprot |= PROT_WRITE;
84887c478bd9Sstevel@tonic-gate 	}
84897c478bd9Sstevel@tonic-gate 
84907c478bd9Sstevel@tonic-gate 	/*
84917c478bd9Sstevel@tonic-gate 	 * For each devmap call, rsmmap_map is called. This maintains driver
84927c478bd9Sstevel@tonic-gate 	 * private information for the mapping. Thus, if there are multiple
84937c478bd9Sstevel@tonic-gate 	 * devmap calls there will be multiple rsmmap_map calls and for each
84947c478bd9Sstevel@tonic-gate 	 * call, the mapping information will be stored.
84957c478bd9Sstevel@tonic-gate 	 * In case of an error during the processing of the devmap call, error
84967c478bd9Sstevel@tonic-gate 	 * will be returned. This error return causes the caller of rsm_devmap
84977c478bd9Sstevel@tonic-gate 	 * to undo all the mappings by calling rsmmap_unmap for each one.
84987c478bd9Sstevel@tonic-gate 	 * rsmmap_unmap will free up the private information for the requested
84997c478bd9Sstevel@tonic-gate 	 * mapping.
85007c478bd9Sstevel@tonic-gate 	 */
85017c478bd9Sstevel@tonic-gate 	if (seg->s_node != my_nodeid) {
85027c478bd9Sstevel@tonic-gate 		rsm_mapinfo_t *p;
85037c478bd9Sstevel@tonic-gate 
85047c478bd9Sstevel@tonic-gate 		p = rsm_get_mapinfo(seg, off, len, &dev_offset, &cur_len);
85057c478bd9Sstevel@tonic-gate 		if (p == NULL) {
85067c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
85077c478bd9Sstevel@tonic-gate 			    "rsm_devmap: incorrect mapping info\n"));
85087c478bd9Sstevel@tonic-gate 			return (RSMERR_MAP_FAILED);
85097c478bd9Sstevel@tonic-gate 		}
85107c478bd9Sstevel@tonic-gate 		err = devmap_devmem_setup(dhc, p->dip,
85117c478bd9Sstevel@tonic-gate 		    callbackops, p->dev_register,
85127c478bd9Sstevel@tonic-gate 		    dev_offset, cur_len, maxprot,
85137c478bd9Sstevel@tonic-gate 		    DEVMAP_ALLOW_REMAP | DEVMAP_DEFAULTS, 0);
85147c478bd9Sstevel@tonic-gate 
85157c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
85167c478bd9Sstevel@tonic-gate 		    "rsm_devmap: dip=%lx,dreg=%lu,doff=%lx,"
85177c478bd9Sstevel@tonic-gate 		    "off=%lx,len=%lx\n",
85187c478bd9Sstevel@tonic-gate 		    p->dip, p->dev_register, dev_offset, off, cur_len));
85197c478bd9Sstevel@tonic-gate 
85207c478bd9Sstevel@tonic-gate 		if (err != 0) {
85217c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
85227c478bd9Sstevel@tonic-gate 			    "rsm_devmap: devmap_devmem_setup failed %d\n",
85237c478bd9Sstevel@tonic-gate 			    err));
85247c478bd9Sstevel@tonic-gate 			return (RSMERR_MAP_FAILED);
85257c478bd9Sstevel@tonic-gate 		}
85267c478bd9Sstevel@tonic-gate 		/* cur_len is always an integral multiple pagesize */
85277c478bd9Sstevel@tonic-gate 		ASSERT((cur_len & (PAGESIZE-1)) == 0);
85287c478bd9Sstevel@tonic-gate 		*maplen = cur_len;
85297c478bd9Sstevel@tonic-gate 		return (err);
85307c478bd9Sstevel@tonic-gate 
85317c478bd9Sstevel@tonic-gate 	} else {
85327c478bd9Sstevel@tonic-gate 		err = devmap_umem_setup(dhc, rsm_dip, callbackops,
85337c478bd9Sstevel@tonic-gate 		    seg->s_cookie, off, len, maxprot,
85347c478bd9Sstevel@tonic-gate 		    DEVMAP_ALLOW_REMAP|DEVMAP_DEFAULTS, 0);
85357c478bd9Sstevel@tonic-gate 		if (err != 0) {
85367c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG,
85377c478bd9Sstevel@tonic-gate 			    "rsm_devmap: devmap_umem_setup failed %d\n",
85387c478bd9Sstevel@tonic-gate 			    err));
85397c478bd9Sstevel@tonic-gate 			return (RSMERR_MAP_FAILED);
85407c478bd9Sstevel@tonic-gate 		}
85417c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
85427c478bd9Sstevel@tonic-gate 		    "rsm_devmap: loopback done\n"));
85437c478bd9Sstevel@tonic-gate 
85447c478bd9Sstevel@tonic-gate 		*maplen = ptob(btopr(len));
85457c478bd9Sstevel@tonic-gate 
85467c478bd9Sstevel@tonic-gate 		return (err);
85477c478bd9Sstevel@tonic-gate 	}
85487c478bd9Sstevel@tonic-gate }
85497c478bd9Sstevel@tonic-gate 
85507c478bd9Sstevel@tonic-gate /*
85517c478bd9Sstevel@tonic-gate  * We can use the devmap framework for mapping device memory to user space by
85527c478bd9Sstevel@tonic-gate  * specifying this routine in the rsm_cb_ops structure. The kernel mmap
85537c478bd9Sstevel@tonic-gate  * processing calls this entry point and devmap_setup is called within this
85547c478bd9Sstevel@tonic-gate  * function, which eventually calls rsm_devmap
85557c478bd9Sstevel@tonic-gate  */
85567c478bd9Sstevel@tonic-gate static int
rsm_segmap(dev_t dev,off_t off,struct as * as,caddr_t * addrp,off_t len,uint_t prot,uint_t maxprot,uint_t flags,struct cred * cred)85577c478bd9Sstevel@tonic-gate rsm_segmap(dev_t dev, off_t off, struct as *as, caddr_t *addrp, off_t len,
85587c478bd9Sstevel@tonic-gate     uint_t prot, uint_t maxprot, uint_t flags, struct cred *cred)
85597c478bd9Sstevel@tonic-gate {
85607c478bd9Sstevel@tonic-gate 	int			error = 0;
85617c478bd9Sstevel@tonic-gate 	int			old_state;
85627c478bd9Sstevel@tonic-gate 	minor_t			rnum;
85637c478bd9Sstevel@tonic-gate 	rsmseg_t		*seg, *eseg;
85647c478bd9Sstevel@tonic-gate 	adapter_t		*adapter;
85657c478bd9Sstevel@tonic-gate 	rsm_import_share_t	*sharedp;
85667c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_DDI);
85677c478bd9Sstevel@tonic-gate 
85687c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "rsm_segmap enter\n"));
85697c478bd9Sstevel@tonic-gate 
85707c478bd9Sstevel@tonic-gate 	/*
85717c478bd9Sstevel@tonic-gate 	 * find segment
85727c478bd9Sstevel@tonic-gate 	 */
85737c478bd9Sstevel@tonic-gate 	rnum = getminor(dev);
85747c478bd9Sstevel@tonic-gate 	seg = (rsmseg_t *)rsmresource_lookup(rnum, RSM_LOCK);
85757c478bd9Sstevel@tonic-gate 
85767c478bd9Sstevel@tonic-gate 	if (seg == NULL) {
85777c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
85787c478bd9Sstevel@tonic-gate 		    "rsm_segmap done: invalid segment\n"));
85797c478bd9Sstevel@tonic-gate 		return (EINVAL);
85807c478bd9Sstevel@tonic-gate 	}
85817c478bd9Sstevel@tonic-gate 
85827c478bd9Sstevel@tonic-gate 	/*
85837c478bd9Sstevel@tonic-gate 	 * the user is trying to map a resource that has not been
85847c478bd9Sstevel@tonic-gate 	 * defined yet. The library uses this to map in the
85857c478bd9Sstevel@tonic-gate 	 * barrier page.
85867c478bd9Sstevel@tonic-gate 	 */
85877c478bd9Sstevel@tonic-gate 	if (seg->s_hdr.rsmrc_type == RSM_RESOURCE_BAR) {
85887c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
85897c478bd9Sstevel@tonic-gate 
85907c478bd9Sstevel@tonic-gate 		/*
85917c478bd9Sstevel@tonic-gate 		 * The mapping for the barrier page is identified
85927c478bd9Sstevel@tonic-gate 		 * by the special offset barrier_offset
85937c478bd9Sstevel@tonic-gate 		 */
85947c478bd9Sstevel@tonic-gate 
85957c478bd9Sstevel@tonic-gate 		if (off == (off_t)barrier_offset ||
85967c478bd9Sstevel@tonic-gate 		    len == (off_t)barrier_size) {
85977c478bd9Sstevel@tonic-gate 			if (bar_cookie == NULL || bar_va == NULL) {
85987c478bd9Sstevel@tonic-gate 				DBG_PRINTF((category, RSM_DEBUG,
85997c478bd9Sstevel@tonic-gate 				    "rsm_segmap: bar cookie/va is NULL\n"));
86007c478bd9Sstevel@tonic-gate 				return (EINVAL);
86017c478bd9Sstevel@tonic-gate 			}
86027c478bd9Sstevel@tonic-gate 
86037c478bd9Sstevel@tonic-gate 			error = devmap_setup(dev, (offset_t)off, as, addrp,
86047c478bd9Sstevel@tonic-gate 			    (size_t)len, prot, maxprot, flags,  cred);
86057c478bd9Sstevel@tonic-gate 
86067c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
86077c478bd9Sstevel@tonic-gate 			    "rsm_segmap done: %d\n", error));
86087c478bd9Sstevel@tonic-gate 			return (error);
86097c478bd9Sstevel@tonic-gate 		} else {
86107c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG,
86117c478bd9Sstevel@tonic-gate 			    "rsm_segmap: bad offset/length\n"));
86127c478bd9Sstevel@tonic-gate 			return (EINVAL);
86137c478bd9Sstevel@tonic-gate 		}
86147c478bd9Sstevel@tonic-gate 	}
86157c478bd9Sstevel@tonic-gate 
86167c478bd9Sstevel@tonic-gate 	/* Make sure you can only map imported segments */
86177c478bd9Sstevel@tonic-gate 	if (seg->s_hdr.rsmrc_type != RSM_RESOURCE_IMPORT_SEGMENT) {
86187c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
86197c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
86207c478bd9Sstevel@tonic-gate 		    "rsm_segmap done: not an import segment\n"));
86217c478bd9Sstevel@tonic-gate 		return (EINVAL);
86227c478bd9Sstevel@tonic-gate 	}
86237c478bd9Sstevel@tonic-gate 	/* check means library is broken */
86247c478bd9Sstevel@tonic-gate 	ASSERT(seg->s_hdr.rsmrc_num == rnum);
86257c478bd9Sstevel@tonic-gate 
86267c478bd9Sstevel@tonic-gate 	/* wait for the segment to become unquiesced */
86277c478bd9Sstevel@tonic-gate 	while (seg->s_state == RSM_STATE_CONN_QUIESCE) {
86287c478bd9Sstevel@tonic-gate 		if (cv_wait_sig(&seg->s_cv, &seg->s_lock) == 0) {
86297c478bd9Sstevel@tonic-gate 			rsmseglock_release(seg);
86307c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG,
86317c478bd9Sstevel@tonic-gate 			    "rsm_segmap done: cv_wait INTR"));
86327c478bd9Sstevel@tonic-gate 			return (ENODEV);
86337c478bd9Sstevel@tonic-gate 		}
86347c478bd9Sstevel@tonic-gate 	}
86357c478bd9Sstevel@tonic-gate 
86367c478bd9Sstevel@tonic-gate 	/* wait until segment leaves the mapping state */
86377c478bd9Sstevel@tonic-gate 	while (seg->s_state == RSM_STATE_MAPPING)
86387c478bd9Sstevel@tonic-gate 		cv_wait(&seg->s_cv, &seg->s_lock);
86397c478bd9Sstevel@tonic-gate 
86407c478bd9Sstevel@tonic-gate 	/*
86417c478bd9Sstevel@tonic-gate 	 * we allow multiple maps of the same segment in the KA
86427c478bd9Sstevel@tonic-gate 	 * and it works because we do an rsmpi map of the whole
86437c478bd9Sstevel@tonic-gate 	 * segment during the first map and all the device mapping
86447c478bd9Sstevel@tonic-gate 	 * information needed in rsm_devmap is in the mapinfo list.
86457c478bd9Sstevel@tonic-gate 	 */
86467c478bd9Sstevel@tonic-gate 	if ((seg->s_state != RSM_STATE_CONNECT) &&
86477c478bd9Sstevel@tonic-gate 	    (seg->s_state != RSM_STATE_ACTIVE)) {
86487c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
86497c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG,
86507c478bd9Sstevel@tonic-gate 		    "rsm_segmap done: segment not connected\n"));
86517c478bd9Sstevel@tonic-gate 		return (ENODEV);
86527c478bd9Sstevel@tonic-gate 	}
86537c478bd9Sstevel@tonic-gate 
86547c478bd9Sstevel@tonic-gate 	/*
86557c478bd9Sstevel@tonic-gate 	 * Make sure we are not mapping a larger segment than what's
86567c478bd9Sstevel@tonic-gate 	 * exported
86577c478bd9Sstevel@tonic-gate 	 */
86587c478bd9Sstevel@tonic-gate 	if ((size_t)off + ptob(btopr(len)) > seg->s_len) {
86597c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
86607c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG,
86617c478bd9Sstevel@tonic-gate 		    "rsm_segmap done: off+len>seg size\n"));
86627c478bd9Sstevel@tonic-gate 		return (ENXIO);
86637c478bd9Sstevel@tonic-gate 	}
86647c478bd9Sstevel@tonic-gate 
86657c478bd9Sstevel@tonic-gate 	/*
86667c478bd9Sstevel@tonic-gate 	 * Make sure we still have permission for the map operation.
86677c478bd9Sstevel@tonic-gate 	 */
86687c478bd9Sstevel@tonic-gate 	maxprot = PROT_USER;
86697c478bd9Sstevel@tonic-gate 	if (seg->s_mode & RSM_PERM_READ) {
86707c478bd9Sstevel@tonic-gate 		maxprot |= PROT_READ;
86717c478bd9Sstevel@tonic-gate 	}
86727c478bd9Sstevel@tonic-gate 
86737c478bd9Sstevel@tonic-gate 	if (seg->s_mode & RSM_PERM_WRITE) {
86747c478bd9Sstevel@tonic-gate 		maxprot |= PROT_WRITE;
86757c478bd9Sstevel@tonic-gate 	}
86767c478bd9Sstevel@tonic-gate 
86777c478bd9Sstevel@tonic-gate 	if ((prot & maxprot) != prot) {
86787c478bd9Sstevel@tonic-gate 		/* No permission */
86797c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
86807c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG,
86817c478bd9Sstevel@tonic-gate 		    "rsm_segmap done: no permission\n"));
86827c478bd9Sstevel@tonic-gate 		return (EACCES);
86837c478bd9Sstevel@tonic-gate 	}
86847c478bd9Sstevel@tonic-gate 
86857c478bd9Sstevel@tonic-gate 	old_state = seg->s_state;
86867c478bd9Sstevel@tonic-gate 
86877c478bd9Sstevel@tonic-gate 	ASSERT(seg->s_share != NULL);
86887c478bd9Sstevel@tonic-gate 
86897c478bd9Sstevel@tonic-gate 	rsmsharelock_acquire(seg);
86907c478bd9Sstevel@tonic-gate 
86917c478bd9Sstevel@tonic-gate 	sharedp = seg->s_share;
86927c478bd9Sstevel@tonic-gate 
86937c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
86947c478bd9Sstevel@tonic-gate 	    "rsm_segmap:RSMSI_STATE=%d\n", sharedp->rsmsi_state));
86957c478bd9Sstevel@tonic-gate 
86967c478bd9Sstevel@tonic-gate 	if ((sharedp->rsmsi_state != RSMSI_STATE_CONNECTED) &&
86977c478bd9Sstevel@tonic-gate 	    (sharedp->rsmsi_state != RSMSI_STATE_MAPPED)) {
86987c478bd9Sstevel@tonic-gate 		rsmsharelock_release(seg);
86997c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
87007c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG,
87017c478bd9Sstevel@tonic-gate 		    "rsm_segmap done:RSMSI_STATE %d invalid\n",
87027c478bd9Sstevel@tonic-gate 		    sharedp->rsmsi_state));
87037c478bd9Sstevel@tonic-gate 		return (ENODEV);
87047c478bd9Sstevel@tonic-gate 	}
87057c478bd9Sstevel@tonic-gate 
87067c478bd9Sstevel@tonic-gate 	/*
87077c478bd9Sstevel@tonic-gate 	 * Do the map - since we want importers to share mappings
87087c478bd9Sstevel@tonic-gate 	 * we do the rsmpi map for the whole segment
87097c478bd9Sstevel@tonic-gate 	 */
87107c478bd9Sstevel@tonic-gate 	if (seg->s_node != my_nodeid) {
87117c478bd9Sstevel@tonic-gate 		uint_t dev_register;
87127c478bd9Sstevel@tonic-gate 		off_t dev_offset;
87137c478bd9Sstevel@tonic-gate 		dev_info_t *dip;
87147c478bd9Sstevel@tonic-gate 		size_t tmp_len;
87157c478bd9Sstevel@tonic-gate 		size_t total_length_mapped = 0;
87167c478bd9Sstevel@tonic-gate 		size_t length_to_map = seg->s_len;
87177c478bd9Sstevel@tonic-gate 		off_t tmp_off = 0;
87187c478bd9Sstevel@tonic-gate 		rsm_mapinfo_t *p;
87197c478bd9Sstevel@tonic-gate 
87207c478bd9Sstevel@tonic-gate 		/*
87217c478bd9Sstevel@tonic-gate 		 * length_to_map = seg->s_len is always an integral
87227c478bd9Sstevel@tonic-gate 		 * multiple of PAGESIZE. Length mapped in each entry in mapinfo
87237c478bd9Sstevel@tonic-gate 		 * list is a multiple of PAGESIZE - RSMPI map ensures this
87247c478bd9Sstevel@tonic-gate 		 */
87257c478bd9Sstevel@tonic-gate 
87267c478bd9Sstevel@tonic-gate 		adapter = seg->s_adapter;
87277c478bd9Sstevel@tonic-gate 		ASSERT(sharedp->rsmsi_state == RSMSI_STATE_CONNECTED ||
87287c478bd9Sstevel@tonic-gate 		    sharedp->rsmsi_state == RSMSI_STATE_MAPPED);
87297c478bd9Sstevel@tonic-gate 
87307c478bd9Sstevel@tonic-gate 		if (sharedp->rsmsi_state == RSMSI_STATE_CONNECTED) {
87317c478bd9Sstevel@tonic-gate 			error = 0;
87327c478bd9Sstevel@tonic-gate 			/* map the whole segment */
87337c478bd9Sstevel@tonic-gate 			while (total_length_mapped < seg->s_len) {
87347c478bd9Sstevel@tonic-gate 				tmp_len = 0;
87357c478bd9Sstevel@tonic-gate 
87367c478bd9Sstevel@tonic-gate 				error = adapter->rsmpi_ops->rsm_map(
87377c478bd9Sstevel@tonic-gate 				    seg->s_handle.in, tmp_off,
87387c478bd9Sstevel@tonic-gate 				    length_to_map, &tmp_len,
87397c478bd9Sstevel@tonic-gate 				    &dip, &dev_register, &dev_offset,
87407c478bd9Sstevel@tonic-gate 				    NULL, NULL);
87417c478bd9Sstevel@tonic-gate 
87427c478bd9Sstevel@tonic-gate 				if (error != 0)
87437c478bd9Sstevel@tonic-gate 					break;
87447c478bd9Sstevel@tonic-gate 
87457c478bd9Sstevel@tonic-gate 				/*
87467c478bd9Sstevel@tonic-gate 				 * Store the mapping info obtained from rsm_map
87477c478bd9Sstevel@tonic-gate 				 */
87487c478bd9Sstevel@tonic-gate 				p = kmem_alloc(sizeof (*p), KM_SLEEP);
87497c478bd9Sstevel@tonic-gate 				p->dev_register = dev_register;
87507c478bd9Sstevel@tonic-gate 				p->dev_offset = dev_offset;
87517c478bd9Sstevel@tonic-gate 				p->dip = dip;
87527c478bd9Sstevel@tonic-gate 				p->individual_len = tmp_len;
87537c478bd9Sstevel@tonic-gate 				p->start_offset = tmp_off;
87547c478bd9Sstevel@tonic-gate 				p->next = sharedp->rsmsi_mapinfo;
87557c478bd9Sstevel@tonic-gate 				sharedp->rsmsi_mapinfo = p;
87567c478bd9Sstevel@tonic-gate 
87577c478bd9Sstevel@tonic-gate 				total_length_mapped += tmp_len;
87587c478bd9Sstevel@tonic-gate 				length_to_map -= tmp_len;
87597c478bd9Sstevel@tonic-gate 				tmp_off += tmp_len;
87607c478bd9Sstevel@tonic-gate 			}
87617c478bd9Sstevel@tonic-gate 			seg->s_mapinfo = sharedp->rsmsi_mapinfo;
87627c478bd9Sstevel@tonic-gate 
87637c478bd9Sstevel@tonic-gate 			if (error != RSM_SUCCESS) {
87647c478bd9Sstevel@tonic-gate 				/* Check if this is the the first rsm_map */
87657c478bd9Sstevel@tonic-gate 				if (sharedp->rsmsi_mapinfo != NULL) {
87667c478bd9Sstevel@tonic-gate 					/*
87677c478bd9Sstevel@tonic-gate 					 * A single rsm_unmap undoes
87687c478bd9Sstevel@tonic-gate 					 * multiple rsm_maps.
87697c478bd9Sstevel@tonic-gate 					 */
87707c478bd9Sstevel@tonic-gate 					(void) seg->s_adapter->rsmpi_ops->
87717c478bd9Sstevel@tonic-gate 					    rsm_unmap(sharedp->rsmsi_handle);
87727c478bd9Sstevel@tonic-gate 					rsm_free_mapinfo(sharedp->
87737c478bd9Sstevel@tonic-gate 					    rsmsi_mapinfo);
87747c478bd9Sstevel@tonic-gate 				}
87757c478bd9Sstevel@tonic-gate 				sharedp->rsmsi_mapinfo = NULL;
87767c478bd9Sstevel@tonic-gate 				sharedp->rsmsi_state = RSMSI_STATE_CONNECTED;
87777c478bd9Sstevel@tonic-gate 				rsmsharelock_release(seg);
87787c478bd9Sstevel@tonic-gate 				rsmseglock_release(seg);
87797c478bd9Sstevel@tonic-gate 				DBG_PRINTF((category, RSM_DEBUG,
87807c478bd9Sstevel@tonic-gate 				    "rsm_segmap done: rsmpi map err %d\n",
87817c478bd9Sstevel@tonic-gate 				    error));
87827c478bd9Sstevel@tonic-gate 				ASSERT(error != RSMERR_BAD_LENGTH &&
87837c478bd9Sstevel@tonic-gate 				    error != RSMERR_BAD_MEM_ALIGNMENT &&
87847c478bd9Sstevel@tonic-gate 				    error != RSMERR_BAD_SEG_HNDL);
87857c478bd9Sstevel@tonic-gate 				if (error == RSMERR_UNSUPPORTED_OPERATION)
87867c478bd9Sstevel@tonic-gate 					return (ENOTSUP);
87877c478bd9Sstevel@tonic-gate 				else if (error == RSMERR_INSUFFICIENT_RESOURCES)
87887c478bd9Sstevel@tonic-gate 					return (EAGAIN);
87897c478bd9Sstevel@tonic-gate 				else if (error == RSMERR_CONN_ABORTED)
87907c478bd9Sstevel@tonic-gate 					return (ENODEV);
87917c478bd9Sstevel@tonic-gate 				else
87927c478bd9Sstevel@tonic-gate 					return (error);
87937c478bd9Sstevel@tonic-gate 			} else {
87947c478bd9Sstevel@tonic-gate 				sharedp->rsmsi_state = RSMSI_STATE_MAPPED;
87957c478bd9Sstevel@tonic-gate 			}
87967c478bd9Sstevel@tonic-gate 		} else {
87977c478bd9Sstevel@tonic-gate 			seg->s_mapinfo = sharedp->rsmsi_mapinfo;
87987c478bd9Sstevel@tonic-gate 		}
87997c478bd9Sstevel@tonic-gate 
88007c478bd9Sstevel@tonic-gate 		sharedp->rsmsi_mapcnt++;
88017c478bd9Sstevel@tonic-gate 
88027c478bd9Sstevel@tonic-gate 		rsmsharelock_release(seg);
88037c478bd9Sstevel@tonic-gate 
88047c478bd9Sstevel@tonic-gate 		/* move to an intermediate mapping state */
88057c478bd9Sstevel@tonic-gate 		seg->s_state = RSM_STATE_MAPPING;
88067c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
88077c478bd9Sstevel@tonic-gate 
88087c478bd9Sstevel@tonic-gate 		error = devmap_setup(dev, (offset_t)off, as, addrp,
88097c478bd9Sstevel@tonic-gate 		    len, prot, maxprot, flags, cred);
88107c478bd9Sstevel@tonic-gate 
88117c478bd9Sstevel@tonic-gate 		rsmseglock_acquire(seg);
88127c478bd9Sstevel@tonic-gate 		ASSERT(seg->s_state == RSM_STATE_MAPPING);
88137c478bd9Sstevel@tonic-gate 
88147c478bd9Sstevel@tonic-gate 		if (error == DDI_SUCCESS) {
88157c478bd9Sstevel@tonic-gate 			seg->s_state = RSM_STATE_ACTIVE;
88167c478bd9Sstevel@tonic-gate 		} else {
88177c478bd9Sstevel@tonic-gate 			rsmsharelock_acquire(seg);
88187c478bd9Sstevel@tonic-gate 
88197c478bd9Sstevel@tonic-gate 			ASSERT(sharedp->rsmsi_state == RSMSI_STATE_MAPPED);
88207c478bd9Sstevel@tonic-gate 
88217c478bd9Sstevel@tonic-gate 			sharedp->rsmsi_mapcnt--;
88227c478bd9Sstevel@tonic-gate 			if (sharedp->rsmsi_mapcnt == 0) {
88237c478bd9Sstevel@tonic-gate 				/* unmap the shared RSMPI mapping */
88247c478bd9Sstevel@tonic-gate 				ASSERT(sharedp->rsmsi_handle != NULL);
88257c478bd9Sstevel@tonic-gate 				(void) adapter->rsmpi_ops->
88267c478bd9Sstevel@tonic-gate 				    rsm_unmap(sharedp->rsmsi_handle);
88277c478bd9Sstevel@tonic-gate 				rsm_free_mapinfo(sharedp->rsmsi_mapinfo);
88287c478bd9Sstevel@tonic-gate 				sharedp->rsmsi_mapinfo = NULL;
88297c478bd9Sstevel@tonic-gate 				sharedp->rsmsi_state = RSMSI_STATE_CONNECTED;
88307c478bd9Sstevel@tonic-gate 			}
88317c478bd9Sstevel@tonic-gate 
88327c478bd9Sstevel@tonic-gate 			rsmsharelock_release(seg);
88337c478bd9Sstevel@tonic-gate 			seg->s_state = old_state;
88347c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_ERR,
88357c478bd9Sstevel@tonic-gate 			    "rsm: devmap_setup failed %d\n", error));
88367c478bd9Sstevel@tonic-gate 		}
88377c478bd9Sstevel@tonic-gate 		cv_broadcast(&seg->s_cv);
88387c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
88397c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_LVL2, "rsm_segmap done: %d\n",
88407c478bd9Sstevel@tonic-gate 		    error));
88417c478bd9Sstevel@tonic-gate 		return (error);
88427c478bd9Sstevel@tonic-gate 	} else {
88437c478bd9Sstevel@tonic-gate 		/*
88447c478bd9Sstevel@tonic-gate 		 * For loopback, the export segment mapping cookie (s_cookie)
88457c478bd9Sstevel@tonic-gate 		 * is also used as the s_cookie value for its import segments
88467c478bd9Sstevel@tonic-gate 		 * during mapping.
88477c478bd9Sstevel@tonic-gate 		 * Note that reference counting for s_cookie of the export
88487c478bd9Sstevel@tonic-gate 		 * segment is not required due to the following:
88497c478bd9Sstevel@tonic-gate 		 * We never have a case of the export segment being destroyed,
88507c478bd9Sstevel@tonic-gate 		 * leaving the import segments with a stale value for the
88517c478bd9Sstevel@tonic-gate 		 * s_cookie field, since a force disconnect is done prior to a
88527c478bd9Sstevel@tonic-gate 		 * destroy of an export segment. The force disconnect causes
88537c478bd9Sstevel@tonic-gate 		 * the s_cookie value to be reset to NULL. Also for the
88547c478bd9Sstevel@tonic-gate 		 * rsm_rebind operation, we change the s_cookie value of the
88557c478bd9Sstevel@tonic-gate 		 * export segment as well as of all its local (loopback)
88567c478bd9Sstevel@tonic-gate 		 * importers.
88577c478bd9Sstevel@tonic-gate 		 */
88587c478bd9Sstevel@tonic-gate 		DBG_ADDCATEGORY(category, RSM_LOOPBACK);
88597c478bd9Sstevel@tonic-gate 
88607c478bd9Sstevel@tonic-gate 		rsmsharelock_release(seg);
88617c478bd9Sstevel@tonic-gate 		/*
88627c478bd9Sstevel@tonic-gate 		 * In order to maintain the lock ordering between the export
88637c478bd9Sstevel@tonic-gate 		 * and import segment locks, we need to acquire the export
88647c478bd9Sstevel@tonic-gate 		 * segment lock first and only then acquire the import
88657c478bd9Sstevel@tonic-gate 		 * segment lock.
88667c478bd9Sstevel@tonic-gate 		 * The above is necessary to avoid any deadlock scenarios
88677c478bd9Sstevel@tonic-gate 		 * with rsm_rebind which also acquires both the export
88687c478bd9Sstevel@tonic-gate 		 * and import segment locks in the above mentioned order.
88697c478bd9Sstevel@tonic-gate 		 * Based on code inspection, there seem to be no other
88707c478bd9Sstevel@tonic-gate 		 * situations in which both the export and import segment
88717c478bd9Sstevel@tonic-gate 		 * locks are acquired either in the same or opposite order
88727c478bd9Sstevel@tonic-gate 		 * as mentioned above.
88737c478bd9Sstevel@tonic-gate 		 * Thus in order to conform to the above lock order, we
88747c478bd9Sstevel@tonic-gate 		 * need to change the state of the import segment to
88757c478bd9Sstevel@tonic-gate 		 * RSM_STATE_MAPPING, release the lock. Once this is done we
88767c478bd9Sstevel@tonic-gate 		 * can now safely acquire the export segment lock first
88777c478bd9Sstevel@tonic-gate 		 * followed by the import segment lock which is as per
88787c478bd9Sstevel@tonic-gate 		 * the lock order mentioned above.
88797c478bd9Sstevel@tonic-gate 		 */
88807c478bd9Sstevel@tonic-gate 		/* move to an intermediate mapping state */
88817c478bd9Sstevel@tonic-gate 		seg->s_state = RSM_STATE_MAPPING;
88827c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
88837c478bd9Sstevel@tonic-gate 
88847c478bd9Sstevel@tonic-gate 		eseg = rsmexport_lookup(seg->s_key);
88857c478bd9Sstevel@tonic-gate 
88867c478bd9Sstevel@tonic-gate 		if (eseg == NULL) {
88877c478bd9Sstevel@tonic-gate 			rsmseglock_acquire(seg);
88887c478bd9Sstevel@tonic-gate 			/*
88897c478bd9Sstevel@tonic-gate 			 * Revert to old_state and signal any waiters
88907c478bd9Sstevel@tonic-gate 			 * The shared state is not changed
88917c478bd9Sstevel@tonic-gate 			 */
88927c478bd9Sstevel@tonic-gate 
88937c478bd9Sstevel@tonic-gate 			seg->s_state = old_state;
88947c478bd9Sstevel@tonic-gate 			cv_broadcast(&seg->s_cv);
88957c478bd9Sstevel@tonic-gate 			rsmseglock_release(seg);
88967c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG,
88977c478bd9Sstevel@tonic-gate 			    "rsm_segmap done: key %d not found\n", seg->s_key));
88987c478bd9Sstevel@tonic-gate 			return (ENODEV);
88997c478bd9Sstevel@tonic-gate 		}
89007c478bd9Sstevel@tonic-gate 
89017c478bd9Sstevel@tonic-gate 		rsmsharelock_acquire(seg);
89027c478bd9Sstevel@tonic-gate 		ASSERT(sharedp->rsmsi_state == RSMSI_STATE_CONNECTED ||
89037c478bd9Sstevel@tonic-gate 		    sharedp->rsmsi_state == RSMSI_STATE_MAPPED);
89047c478bd9Sstevel@tonic-gate 
89057c478bd9Sstevel@tonic-gate 		sharedp->rsmsi_mapcnt++;
89067c478bd9Sstevel@tonic-gate 		sharedp->rsmsi_state = RSMSI_STATE_MAPPED;
89077c478bd9Sstevel@tonic-gate 		rsmsharelock_release(seg);
89087c478bd9Sstevel@tonic-gate 
89097c478bd9Sstevel@tonic-gate 		ASSERT(eseg->s_cookie != NULL);
89107c478bd9Sstevel@tonic-gate 
89117c478bd9Sstevel@tonic-gate 		/*
89127c478bd9Sstevel@tonic-gate 		 * It is not required or necessary to acquire the import
89137c478bd9Sstevel@tonic-gate 		 * segment lock here to change the value of s_cookie since
89147c478bd9Sstevel@tonic-gate 		 * no one will touch the import segment as long as it is
89157c478bd9Sstevel@tonic-gate 		 * in the RSM_STATE_MAPPING state.
89167c478bd9Sstevel@tonic-gate 		 */
89177c478bd9Sstevel@tonic-gate 		seg->s_cookie = eseg->s_cookie;
89187c478bd9Sstevel@tonic-gate 
89197c478bd9Sstevel@tonic-gate 		rsmseglock_release(eseg);
89207c478bd9Sstevel@tonic-gate 
89217c478bd9Sstevel@tonic-gate 		error = devmap_setup(dev, (offset_t)off, as, addrp, (size_t)len,
89227c478bd9Sstevel@tonic-gate 		    prot, maxprot, flags, cred);
89237c478bd9Sstevel@tonic-gate 
89247c478bd9Sstevel@tonic-gate 		rsmseglock_acquire(seg);
89257c478bd9Sstevel@tonic-gate 		ASSERT(seg->s_state == RSM_STATE_MAPPING);
89267c478bd9Sstevel@tonic-gate 		if (error == 0) {
89277c478bd9Sstevel@tonic-gate 			seg->s_state = RSM_STATE_ACTIVE;
89287c478bd9Sstevel@tonic-gate 		} else {
89297c478bd9Sstevel@tonic-gate 			rsmsharelock_acquire(seg);
89307c478bd9Sstevel@tonic-gate 
89317c478bd9Sstevel@tonic-gate 			ASSERT(sharedp->rsmsi_state == RSMSI_STATE_MAPPED);
89327c478bd9Sstevel@tonic-gate 
89337c478bd9Sstevel@tonic-gate 			sharedp->rsmsi_mapcnt--;
89347c478bd9Sstevel@tonic-gate 			if (sharedp->rsmsi_mapcnt == 0) {
89357c478bd9Sstevel@tonic-gate 				sharedp->rsmsi_mapinfo = NULL;
89367c478bd9Sstevel@tonic-gate 				sharedp->rsmsi_state = RSMSI_STATE_CONNECTED;
89377c478bd9Sstevel@tonic-gate 			}
89387c478bd9Sstevel@tonic-gate 			rsmsharelock_release(seg);
89397c478bd9Sstevel@tonic-gate 			seg->s_state = old_state;
89407c478bd9Sstevel@tonic-gate 			seg->s_cookie = NULL;
89417c478bd9Sstevel@tonic-gate 		}
89427c478bd9Sstevel@tonic-gate 		cv_broadcast(&seg->s_cv);
89437c478bd9Sstevel@tonic-gate 		rsmseglock_release(seg);
89447c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_LVL2,
89457c478bd9Sstevel@tonic-gate 		    "rsm_segmap done: %d\n", error));
89467c478bd9Sstevel@tonic-gate 		return (error);
89477c478bd9Sstevel@tonic-gate 	}
89487c478bd9Sstevel@tonic-gate }
89497c478bd9Sstevel@tonic-gate 
89507c478bd9Sstevel@tonic-gate int
rsmka_null_seg_create(rsm_controller_handle_t argcp,rsm_memseg_export_handle_t * handle,size_t size,uint_t flags,rsm_memory_local_t * memory,rsm_resource_callback_t callback,rsm_resource_callback_arg_t callback_arg)89517c478bd9Sstevel@tonic-gate rsmka_null_seg_create(
89527c478bd9Sstevel@tonic-gate     rsm_controller_handle_t argcp,
89537c478bd9Sstevel@tonic-gate     rsm_memseg_export_handle_t *handle,
89547c478bd9Sstevel@tonic-gate     size_t size,
89557c478bd9Sstevel@tonic-gate     uint_t flags,
89567c478bd9Sstevel@tonic-gate     rsm_memory_local_t *memory,
89577c478bd9Sstevel@tonic-gate     rsm_resource_callback_t callback,
89587c478bd9Sstevel@tonic-gate     rsm_resource_callback_arg_t callback_arg	/*ARGSUSED*/)
89597c478bd9Sstevel@tonic-gate {
89607c478bd9Sstevel@tonic-gate 	return (RSM_SUCCESS);
89617c478bd9Sstevel@tonic-gate }
89627c478bd9Sstevel@tonic-gate 
89637c478bd9Sstevel@tonic-gate 
89647c478bd9Sstevel@tonic-gate int
rsmka_null_seg_destroy(rsm_memseg_export_handle_t argmemseg)89657c478bd9Sstevel@tonic-gate rsmka_null_seg_destroy(
89667c478bd9Sstevel@tonic-gate     rsm_memseg_export_handle_t argmemseg	/*ARGSUSED*/)
89677c478bd9Sstevel@tonic-gate {
89687c478bd9Sstevel@tonic-gate 	return (RSM_SUCCESS);
89697c478bd9Sstevel@tonic-gate }
89707c478bd9Sstevel@tonic-gate 
89717c478bd9Sstevel@tonic-gate 
89727c478bd9Sstevel@tonic-gate int
rsmka_null_bind(rsm_memseg_export_handle_t argmemseg,off_t offset,rsm_memory_local_t * argmemory,rsm_resource_callback_t callback,rsm_resource_callback_arg_t callback_arg)89737c478bd9Sstevel@tonic-gate rsmka_null_bind(
89747c478bd9Sstevel@tonic-gate     rsm_memseg_export_handle_t argmemseg,
89757c478bd9Sstevel@tonic-gate     off_t offset,
89767c478bd9Sstevel@tonic-gate     rsm_memory_local_t *argmemory,
89777c478bd9Sstevel@tonic-gate     rsm_resource_callback_t callback,
89787c478bd9Sstevel@tonic-gate     rsm_resource_callback_arg_t callback_arg	/*ARGSUSED*/)
89797c478bd9Sstevel@tonic-gate {
89807c478bd9Sstevel@tonic-gate 	return (RSM_SUCCESS);
89817c478bd9Sstevel@tonic-gate }
89827c478bd9Sstevel@tonic-gate 
89837c478bd9Sstevel@tonic-gate 
89847c478bd9Sstevel@tonic-gate int
rsmka_null_unbind(rsm_memseg_export_handle_t argmemseg,off_t offset,size_t length)89857c478bd9Sstevel@tonic-gate rsmka_null_unbind(
89867c478bd9Sstevel@tonic-gate     rsm_memseg_export_handle_t argmemseg,
89877c478bd9Sstevel@tonic-gate     off_t offset,
89887c478bd9Sstevel@tonic-gate     size_t length	/*ARGSUSED*/)
89897c478bd9Sstevel@tonic-gate {
89907c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
89917c478bd9Sstevel@tonic-gate }
89927c478bd9Sstevel@tonic-gate 
89937c478bd9Sstevel@tonic-gate int
rsmka_null_rebind(rsm_memseg_export_handle_t argmemseg,off_t offset,rsm_memory_local_t * memory,rsm_resource_callback_t callback,rsm_resource_callback_arg_t callback_arg)89947c478bd9Sstevel@tonic-gate rsmka_null_rebind(
89957c478bd9Sstevel@tonic-gate     rsm_memseg_export_handle_t argmemseg,
89967c478bd9Sstevel@tonic-gate     off_t offset,
89977c478bd9Sstevel@tonic-gate     rsm_memory_local_t *memory,
89987c478bd9Sstevel@tonic-gate     rsm_resource_callback_t callback,
89997c478bd9Sstevel@tonic-gate     rsm_resource_callback_arg_t callback_arg	/*ARGSUSED*/)
90007c478bd9Sstevel@tonic-gate {
90017c478bd9Sstevel@tonic-gate 	return (RSM_SUCCESS);
90027c478bd9Sstevel@tonic-gate }
90037c478bd9Sstevel@tonic-gate 
90047c478bd9Sstevel@tonic-gate int
rsmka_null_publish(rsm_memseg_export_handle_t argmemseg,rsm_access_entry_t access_list[],uint_t access_list_length,rsm_memseg_id_t segment_id,rsm_resource_callback_t callback,rsm_resource_callback_arg_t callback_arg)90057c478bd9Sstevel@tonic-gate rsmka_null_publish(
90067c478bd9Sstevel@tonic-gate     rsm_memseg_export_handle_t argmemseg,
90077c478bd9Sstevel@tonic-gate     rsm_access_entry_t access_list[],
90087c478bd9Sstevel@tonic-gate     uint_t access_list_length,
90097c478bd9Sstevel@tonic-gate     rsm_memseg_id_t segment_id,
90107c478bd9Sstevel@tonic-gate     rsm_resource_callback_t callback,
90117c478bd9Sstevel@tonic-gate     rsm_resource_callback_arg_t callback_arg	/*ARGSUSED*/)
90127c478bd9Sstevel@tonic-gate {
90137c478bd9Sstevel@tonic-gate 	return (RSM_SUCCESS);
90147c478bd9Sstevel@tonic-gate }
90157c478bd9Sstevel@tonic-gate 
90167c478bd9Sstevel@tonic-gate 
90177c478bd9Sstevel@tonic-gate int
rsmka_null_republish(rsm_memseg_export_handle_t memseg,rsm_access_entry_t access_list[],uint_t access_list_length,rsm_resource_callback_t callback,rsm_resource_callback_arg_t callback_arg)90187c478bd9Sstevel@tonic-gate rsmka_null_republish(
90197c478bd9Sstevel@tonic-gate     rsm_memseg_export_handle_t memseg,
90207c478bd9Sstevel@tonic-gate     rsm_access_entry_t access_list[],
90217c478bd9Sstevel@tonic-gate     uint_t access_list_length,
90227c478bd9Sstevel@tonic-gate     rsm_resource_callback_t callback,
90237c478bd9Sstevel@tonic-gate     rsm_resource_callback_arg_t callback_arg	/*ARGSUSED*/)
90247c478bd9Sstevel@tonic-gate {
90257c478bd9Sstevel@tonic-gate 	return (RSM_SUCCESS);
90267c478bd9Sstevel@tonic-gate }
90277c478bd9Sstevel@tonic-gate 
90287c478bd9Sstevel@tonic-gate int
rsmka_null_unpublish(rsm_memseg_export_handle_t argmemseg)90297c478bd9Sstevel@tonic-gate rsmka_null_unpublish(
90307c478bd9Sstevel@tonic-gate     rsm_memseg_export_handle_t argmemseg	/*ARGSUSED*/)
90317c478bd9Sstevel@tonic-gate {
90327c478bd9Sstevel@tonic-gate 	return (RSM_SUCCESS);
90337c478bd9Sstevel@tonic-gate }
90347c478bd9Sstevel@tonic-gate 
90357c478bd9Sstevel@tonic-gate 
90367c478bd9Sstevel@tonic-gate void
rsmka_init_loopback()90377c478bd9Sstevel@tonic-gate rsmka_init_loopback()
90387c478bd9Sstevel@tonic-gate {
90397c478bd9Sstevel@tonic-gate 	rsm_ops_t	*ops = &null_rsmpi_ops;
90407c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL | RSM_LOOPBACK);
90417c478bd9Sstevel@tonic-gate 
90427c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
90437c478bd9Sstevel@tonic-gate 	    "rsmka_init_loopback enter\n"));
90447c478bd9Sstevel@tonic-gate 
90457c478bd9Sstevel@tonic-gate 	/* initialize null ops vector */
90467c478bd9Sstevel@tonic-gate 	ops->rsm_seg_create = rsmka_null_seg_create;
90477c478bd9Sstevel@tonic-gate 	ops->rsm_seg_destroy = rsmka_null_seg_destroy;
90487c478bd9Sstevel@tonic-gate 	ops->rsm_bind = rsmka_null_bind;
90497c478bd9Sstevel@tonic-gate 	ops->rsm_unbind = rsmka_null_unbind;
90507c478bd9Sstevel@tonic-gate 	ops->rsm_rebind = rsmka_null_rebind;
90517c478bd9Sstevel@tonic-gate 	ops->rsm_publish = rsmka_null_publish;
90527c478bd9Sstevel@tonic-gate 	ops->rsm_unpublish = rsmka_null_unpublish;
90537c478bd9Sstevel@tonic-gate 	ops->rsm_republish = rsmka_null_republish;
90547c478bd9Sstevel@tonic-gate 
90557c478bd9Sstevel@tonic-gate 	/* initialize attributes for loopback adapter */
90567c478bd9Sstevel@tonic-gate 	loopback_attr.attr_name = loopback_str;
90577c478bd9Sstevel@tonic-gate 	loopback_attr.attr_page_size = 0x8; /* 8K */
90587c478bd9Sstevel@tonic-gate 
90597c478bd9Sstevel@tonic-gate 	/* initialize loopback adapter */
90607c478bd9Sstevel@tonic-gate 	loopback_adapter.rsm_attr = loopback_attr;
90617c478bd9Sstevel@tonic-gate 	loopback_adapter.rsmpi_ops = &null_rsmpi_ops;
90627c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
90637c478bd9Sstevel@tonic-gate 	    "rsmka_init_loopback done\n"));
90647c478bd9Sstevel@tonic-gate }
90657c478bd9Sstevel@tonic-gate 
90667c478bd9Sstevel@tonic-gate /* ************** DR functions ********************************** */
90677c478bd9Sstevel@tonic-gate static void
rsm_quiesce_exp_seg(rsmresource_t * resp)90687c478bd9Sstevel@tonic-gate rsm_quiesce_exp_seg(rsmresource_t *resp)
90697c478bd9Sstevel@tonic-gate {
90707c478bd9Sstevel@tonic-gate 	int		recheck_state;
90717c478bd9Sstevel@tonic-gate 	rsmseg_t	*segp = (rsmseg_t *)resp;
90727c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL);
90737c478bd9Sstevel@tonic-gate 	DBG_DEFINE_STR(function, "rsm_unquiesce_exp_seg");
90747c478bd9Sstevel@tonic-gate 
90757c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
90767c478bd9Sstevel@tonic-gate 	    "%s enter: key=%u\n", function, segp->s_key));
90777c478bd9Sstevel@tonic-gate 
90787c478bd9Sstevel@tonic-gate 	rsmseglock_acquire(segp);
90797c478bd9Sstevel@tonic-gate 	do {
90807c478bd9Sstevel@tonic-gate 		recheck_state = 0;
90817c478bd9Sstevel@tonic-gate 		if ((segp->s_state == RSM_STATE_NEW_QUIESCED) ||
90827c478bd9Sstevel@tonic-gate 		    (segp->s_state == RSM_STATE_BIND_QUIESCED) ||
90837c478bd9Sstevel@tonic-gate 		    (segp->s_state == RSM_STATE_EXPORT_QUIESCING) ||
90847c478bd9Sstevel@tonic-gate 		    (segp->s_state == RSM_STATE_EXPORT_QUIESCED)) {
90857c478bd9Sstevel@tonic-gate 			rsmseglock_release(segp);
90867c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
90877c478bd9Sstevel@tonic-gate 			    "%s done:state =%d\n", function,
90887c478bd9Sstevel@tonic-gate 			    segp->s_state));
90897c478bd9Sstevel@tonic-gate 			return;
90907c478bd9Sstevel@tonic-gate 		}
90917c478bd9Sstevel@tonic-gate 
90927c478bd9Sstevel@tonic-gate 		if (segp->s_state == RSM_STATE_NEW) {
90937c478bd9Sstevel@tonic-gate 			segp->s_state = RSM_STATE_NEW_QUIESCED;
90947c478bd9Sstevel@tonic-gate 			rsmseglock_release(segp);
90957c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
90967c478bd9Sstevel@tonic-gate 			    "%s done:state =%d\n", function,
90977c478bd9Sstevel@tonic-gate 			    segp->s_state));
90987c478bd9Sstevel@tonic-gate 			return;
90997c478bd9Sstevel@tonic-gate 		}
91007c478bd9Sstevel@tonic-gate 
91017c478bd9Sstevel@tonic-gate 		if (segp->s_state == RSM_STATE_BIND) {
91027c478bd9Sstevel@tonic-gate 			/* unbind */
91037c478bd9Sstevel@tonic-gate 			(void) rsm_unbind_pages(segp);
91047c478bd9Sstevel@tonic-gate 			segp->s_state = RSM_STATE_BIND_QUIESCED;
91057c478bd9Sstevel@tonic-gate 			rsmseglock_release(segp);
91067c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
91077c478bd9Sstevel@tonic-gate 			    "%s done:state =%d\n", function,
91087c478bd9Sstevel@tonic-gate 			    segp->s_state));
91097c478bd9Sstevel@tonic-gate 			return;
91107c478bd9Sstevel@tonic-gate 		}
91117c478bd9Sstevel@tonic-gate 
91127c478bd9Sstevel@tonic-gate 		if (segp->s_state == RSM_STATE_EXPORT) {
91137c478bd9Sstevel@tonic-gate 			/*
91147c478bd9Sstevel@tonic-gate 			 * wait for putv/getv to complete if the segp is
91157c478bd9Sstevel@tonic-gate 			 * a local memory handle
91167c478bd9Sstevel@tonic-gate 			 */
91177c478bd9Sstevel@tonic-gate 			while ((segp->s_state == RSM_STATE_EXPORT) &&
91187c478bd9Sstevel@tonic-gate 			    (segp->s_rdmacnt != 0)) {
91197c478bd9Sstevel@tonic-gate 				cv_wait(&segp->s_cv, &segp->s_lock);
91207c478bd9Sstevel@tonic-gate 			}
91217c478bd9Sstevel@tonic-gate 
91227c478bd9Sstevel@tonic-gate 			if (segp->s_state != RSM_STATE_EXPORT) {
91237c478bd9Sstevel@tonic-gate 				/*
91247c478bd9Sstevel@tonic-gate 				 * state changed need to see what it
91257c478bd9Sstevel@tonic-gate 				 * should be changed to.
91267c478bd9Sstevel@tonic-gate 				 */
91277c478bd9Sstevel@tonic-gate 				recheck_state = 1;
91287c478bd9Sstevel@tonic-gate 				continue;
91297c478bd9Sstevel@tonic-gate 			}
91307c478bd9Sstevel@tonic-gate 
91317c478bd9Sstevel@tonic-gate 			segp->s_state = RSM_STATE_EXPORT_QUIESCING;
91327c478bd9Sstevel@tonic-gate 			rsmseglock_release(segp);
91337c478bd9Sstevel@tonic-gate 			/*
91347c478bd9Sstevel@tonic-gate 			 * send SUSPEND messages - currently it will be
91357c478bd9Sstevel@tonic-gate 			 * done at the end
91367c478bd9Sstevel@tonic-gate 			 */
91377c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
91387c478bd9Sstevel@tonic-gate 			    "%s done:state =%d\n", function,
91397c478bd9Sstevel@tonic-gate 			    segp->s_state));
91407c478bd9Sstevel@tonic-gate 			return;
91417c478bd9Sstevel@tonic-gate 		}
91427c478bd9Sstevel@tonic-gate 	} while (recheck_state);
91437c478bd9Sstevel@tonic-gate 
91447c478bd9Sstevel@tonic-gate 	rsmseglock_release(segp);
91457c478bd9Sstevel@tonic-gate }
91467c478bd9Sstevel@tonic-gate 
91477c478bd9Sstevel@tonic-gate static void
rsm_unquiesce_exp_seg(rsmresource_t * resp)91487c478bd9Sstevel@tonic-gate rsm_unquiesce_exp_seg(rsmresource_t *resp)
91497c478bd9Sstevel@tonic-gate {
91507c478bd9Sstevel@tonic-gate 	int			ret;
91517c478bd9Sstevel@tonic-gate 	rsmseg_t		*segp = (rsmseg_t *)resp;
91527c478bd9Sstevel@tonic-gate 	rsmapi_access_entry_t	*acl;
91537c478bd9Sstevel@tonic-gate 	rsm_access_entry_t	*rsmpi_acl;
91547c478bd9Sstevel@tonic-gate 	int			acl_len;
91557c478bd9Sstevel@tonic-gate 	int			create_flags = 0;
91567c478bd9Sstevel@tonic-gate 	struct buf		*xbuf;
91577c478bd9Sstevel@tonic-gate 	rsm_memory_local_t	mem;
91587c478bd9Sstevel@tonic-gate 	adapter_t		*adapter;
91597c478bd9Sstevel@tonic-gate 	dev_t			sdev = 0;
91607c478bd9Sstevel@tonic-gate 	rsm_resource_callback_t callback_flag;
91617c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL);
91627c478bd9Sstevel@tonic-gate 	DBG_DEFINE_STR(function, "rsm_unquiesce_exp_seg");
91637c478bd9Sstevel@tonic-gate 
91647c478bd9Sstevel@tonic-gate 	rsmseglock_acquire(segp);
91657c478bd9Sstevel@tonic-gate 
91667c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
91677c478bd9Sstevel@tonic-gate 	    "%s enter: key=%u, state=%d\n", function, segp->s_key,
91687c478bd9Sstevel@tonic-gate 	    segp->s_state));
91697c478bd9Sstevel@tonic-gate 
91707c478bd9Sstevel@tonic-gate 	if ((segp->s_state == RSM_STATE_NEW) ||
91717c478bd9Sstevel@tonic-gate 	    (segp->s_state == RSM_STATE_BIND) ||
91727c478bd9Sstevel@tonic-gate 	    (segp->s_state == RSM_STATE_EXPORT)) {
91737c478bd9Sstevel@tonic-gate 		rsmseglock_release(segp);
91747c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "%s done:state=%d\n",
91757c478bd9Sstevel@tonic-gate 		    function, segp->s_state));
91767c478bd9Sstevel@tonic-gate 		return;
91777c478bd9Sstevel@tonic-gate 	}
91787c478bd9Sstevel@tonic-gate 
91797c478bd9Sstevel@tonic-gate 	if (segp->s_state == RSM_STATE_NEW_QUIESCED) {
91807c478bd9Sstevel@tonic-gate 		segp->s_state = RSM_STATE_NEW;
91817c478bd9Sstevel@tonic-gate 		cv_broadcast(&segp->s_cv);
91827c478bd9Sstevel@tonic-gate 		rsmseglock_release(segp);
91837c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "%s done:state=%d\n",
91847c478bd9Sstevel@tonic-gate 		    function, segp->s_state));
91857c478bd9Sstevel@tonic-gate 		return;
91867c478bd9Sstevel@tonic-gate 	}
91877c478bd9Sstevel@tonic-gate 
91887c478bd9Sstevel@tonic-gate 	if (segp->s_state == RSM_STATE_BIND_QUIESCED) {
91897c478bd9Sstevel@tonic-gate 		/* bind the segment */
91907c478bd9Sstevel@tonic-gate 		ret = rsm_bind_pages(&segp->s_cookie, segp->s_region.r_vaddr,
91917c478bd9Sstevel@tonic-gate 		    segp->s_len, segp->s_proc);
91927c478bd9Sstevel@tonic-gate 		if (ret == RSM_SUCCESS) { /* bind successful */
91937c478bd9Sstevel@tonic-gate 			segp->s_state = RSM_STATE_BIND;
91947c478bd9Sstevel@tonic-gate 		} else { /* bind failed - resource unavailable */
91957c478bd9Sstevel@tonic-gate 			segp->s_state = RSM_STATE_NEW;
91967c478bd9Sstevel@tonic-gate 		}
91977c478bd9Sstevel@tonic-gate 		cv_broadcast(&segp->s_cv);
91987c478bd9Sstevel@tonic-gate 		rsmseglock_release(segp);
91997c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
92007c478bd9Sstevel@tonic-gate 		    "%s done: bind_qscd bind = %d\n", function, ret));
92017c478bd9Sstevel@tonic-gate 		return;
92027c478bd9Sstevel@tonic-gate 	}
92037c478bd9Sstevel@tonic-gate 
92047c478bd9Sstevel@tonic-gate 	while (segp->s_state == RSM_STATE_EXPORT_QUIESCING) {
92057c478bd9Sstevel@tonic-gate 		/* wait for the segment to move to EXPORT_QUIESCED state */
92067c478bd9Sstevel@tonic-gate 		cv_wait(&segp->s_cv, &segp->s_lock);
92077c478bd9Sstevel@tonic-gate 	}
92087c478bd9Sstevel@tonic-gate 
92097c478bd9Sstevel@tonic-gate 	if (segp->s_state == RSM_STATE_EXPORT_QUIESCED) {
92107c478bd9Sstevel@tonic-gate 		/* bind the segment */
92117c478bd9Sstevel@tonic-gate 		ret = rsm_bind_pages(&segp->s_cookie, segp->s_region.r_vaddr,
92127c478bd9Sstevel@tonic-gate 		    segp->s_len, segp->s_proc);
92137c478bd9Sstevel@tonic-gate 
92147c478bd9Sstevel@tonic-gate 		if (ret != RSM_SUCCESS) {
92157c478bd9Sstevel@tonic-gate 			/* bind failed - resource unavailable */
92167c478bd9Sstevel@tonic-gate 			acl_len = segp->s_acl_len;
92177c478bd9Sstevel@tonic-gate 			acl = segp->s_acl;
92187c478bd9Sstevel@tonic-gate 			rsmpi_acl = segp->s_acl_in;
92197c478bd9Sstevel@tonic-gate 			segp->s_acl_len = 0;
92207c478bd9Sstevel@tonic-gate 			segp->s_acl = NULL;
92217c478bd9Sstevel@tonic-gate 			segp->s_acl_in = NULL;
92227c478bd9Sstevel@tonic-gate 			rsmseglock_release(segp);
92237c478bd9Sstevel@tonic-gate 
92247c478bd9Sstevel@tonic-gate 			rsmexport_rm(segp);
92257c478bd9Sstevel@tonic-gate 			rsmacl_free(acl, acl_len);
92267c478bd9Sstevel@tonic-gate 			rsmpiacl_free(rsmpi_acl, acl_len);
92277c478bd9Sstevel@tonic-gate 
92287c478bd9Sstevel@tonic-gate 			rsmseglock_acquire(segp);
92297c478bd9Sstevel@tonic-gate 			segp->s_state = RSM_STATE_NEW;
92307c478bd9Sstevel@tonic-gate 			cv_broadcast(&segp->s_cv);
92317c478bd9Sstevel@tonic-gate 			rsmseglock_release(segp);
92327c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
92337c478bd9Sstevel@tonic-gate 			    "%s done: exp_qscd bind failed = %d\n",
92347c478bd9Sstevel@tonic-gate 			    function, ret));
92357c478bd9Sstevel@tonic-gate 			return;
92367c478bd9Sstevel@tonic-gate 		}
92377c478bd9Sstevel@tonic-gate 		/*
92387c478bd9Sstevel@tonic-gate 		 * publish the segment
92397c478bd9Sstevel@tonic-gate 		 * if  successful
92407c478bd9Sstevel@tonic-gate 		 *   segp->s_state = RSM_STATE_EXPORT;
92417c478bd9Sstevel@tonic-gate 		 * else failed
92427c478bd9Sstevel@tonic-gate 		 *   segp->s_state = RSM_STATE_BIND;
92437c478bd9Sstevel@tonic-gate 		 */
92447c478bd9Sstevel@tonic-gate 
92457c478bd9Sstevel@tonic-gate 		/* check whether it is a local_memory_handle */
92467c478bd9Sstevel@tonic-gate 		if (segp->s_acl != (rsmapi_access_entry_t *)NULL) {
92477c478bd9Sstevel@tonic-gate 			if ((segp->s_acl[0].ae_node == my_nodeid) &&
92487c478bd9Sstevel@tonic-gate 			    (segp->s_acl[0].ae_permission == 0)) {
92497c478bd9Sstevel@tonic-gate 				segp->s_state = RSM_STATE_EXPORT;
92507c478bd9Sstevel@tonic-gate 				cv_broadcast(&segp->s_cv);
92517c478bd9Sstevel@tonic-gate 				rsmseglock_release(segp);
92527c478bd9Sstevel@tonic-gate 				DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
92537c478bd9Sstevel@tonic-gate 				    "%s done:exp_qscd\n", function));
92547c478bd9Sstevel@tonic-gate 				return;
92557c478bd9Sstevel@tonic-gate 			}
92567c478bd9Sstevel@tonic-gate 		}
92577c478bd9Sstevel@tonic-gate 		xbuf = ddi_umem_iosetup(segp->s_cookie, 0, segp->s_len, B_WRITE,
92587c478bd9Sstevel@tonic-gate 		    sdev, 0, NULL, DDI_UMEM_SLEEP);
92597c478bd9Sstevel@tonic-gate 		ASSERT(xbuf != NULL);
92607c478bd9Sstevel@tonic-gate 
92617c478bd9Sstevel@tonic-gate 		mem.ms_type = RSM_MEM_BUF;
92627c478bd9Sstevel@tonic-gate 		mem.ms_bp = xbuf;
92637c478bd9Sstevel@tonic-gate 
92647c478bd9Sstevel@tonic-gate 		adapter = segp->s_adapter;
92657c478bd9Sstevel@tonic-gate 
92667c478bd9Sstevel@tonic-gate 		if (segp->s_flags & RSMKA_ALLOW_UNBIND_REBIND) {
92677c478bd9Sstevel@tonic-gate 			create_flags = RSM_ALLOW_UNBIND_REBIND;
92687c478bd9Sstevel@tonic-gate 		}
92697c478bd9Sstevel@tonic-gate 
92707c478bd9Sstevel@tonic-gate 		if (segp->s_flags & RSMKA_SET_RESOURCE_DONTWAIT) {
92717c478bd9Sstevel@tonic-gate 			callback_flag  = RSM_RESOURCE_DONTWAIT;
92727c478bd9Sstevel@tonic-gate 		} else {
92737c478bd9Sstevel@tonic-gate 			callback_flag  = RSM_RESOURCE_SLEEP;
92747c478bd9Sstevel@tonic-gate 		}
92757c478bd9Sstevel@tonic-gate 
92767c478bd9Sstevel@tonic-gate 		ret = adapter->rsmpi_ops->rsm_seg_create(
92777c478bd9Sstevel@tonic-gate 		    adapter->rsmpi_handle, &segp->s_handle.out,
92787c478bd9Sstevel@tonic-gate 		    segp->s_len, create_flags, &mem,
92797c478bd9Sstevel@tonic-gate 		    callback_flag, NULL);
92807c478bd9Sstevel@tonic-gate 
92817c478bd9Sstevel@tonic-gate 		if (ret != RSM_SUCCESS) {
92827c478bd9Sstevel@tonic-gate 			acl_len = segp->s_acl_len;
92837c478bd9Sstevel@tonic-gate 			acl = segp->s_acl;
92847c478bd9Sstevel@tonic-gate 			rsmpi_acl = segp->s_acl_in;
92857c478bd9Sstevel@tonic-gate 			segp->s_acl_len = 0;
92867c478bd9Sstevel@tonic-gate 			segp->s_acl = NULL;
92877c478bd9Sstevel@tonic-gate 			segp->s_acl_in = NULL;
92887c478bd9Sstevel@tonic-gate 			rsmseglock_release(segp);
92897c478bd9Sstevel@tonic-gate 
92907c478bd9Sstevel@tonic-gate 			rsmexport_rm(segp);
92917c478bd9Sstevel@tonic-gate 			rsmacl_free(acl, acl_len);
92927c478bd9Sstevel@tonic-gate 			rsmpiacl_free(rsmpi_acl, acl_len);
92937c478bd9Sstevel@tonic-gate 
92947c478bd9Sstevel@tonic-gate 			rsmseglock_acquire(segp);
92957c478bd9Sstevel@tonic-gate 			segp->s_state = RSM_STATE_BIND;
92967c478bd9Sstevel@tonic-gate 			cv_broadcast(&segp->s_cv);
92977c478bd9Sstevel@tonic-gate 			rsmseglock_release(segp);
92987c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_ERR,
92997c478bd9Sstevel@tonic-gate 			    "%s done: exp_qscd create failed = %d\n",
93007c478bd9Sstevel@tonic-gate 			    function, ret));
93017c478bd9Sstevel@tonic-gate 			return;
93027c478bd9Sstevel@tonic-gate 		}
93037c478bd9Sstevel@tonic-gate 
93047c478bd9Sstevel@tonic-gate 		ret = adapter->rsmpi_ops->rsm_publish(
93057c478bd9Sstevel@tonic-gate 		    segp->s_handle.out, segp->s_acl_in, segp->s_acl_len,
93067c478bd9Sstevel@tonic-gate 		    segp->s_segid, RSM_RESOURCE_DONTWAIT, NULL);
93077c478bd9Sstevel@tonic-gate 
93087c478bd9Sstevel@tonic-gate 		if (ret != RSM_SUCCESS) {
93097c478bd9Sstevel@tonic-gate 			acl_len = segp->s_acl_len;
93107c478bd9Sstevel@tonic-gate 			acl = segp->s_acl;
93117c478bd9Sstevel@tonic-gate 			rsmpi_acl = segp->s_acl_in;
93127c478bd9Sstevel@tonic-gate 			segp->s_acl_len = 0;
93137c478bd9Sstevel@tonic-gate 			segp->s_acl = NULL;
93147c478bd9Sstevel@tonic-gate 			segp->s_acl_in = NULL;
93157c478bd9Sstevel@tonic-gate 			adapter->rsmpi_ops->rsm_seg_destroy(segp->s_handle.out);
93167c478bd9Sstevel@tonic-gate 			rsmseglock_release(segp);
93177c478bd9Sstevel@tonic-gate 
93187c478bd9Sstevel@tonic-gate 			rsmexport_rm(segp);
93197c478bd9Sstevel@tonic-gate 			rsmacl_free(acl, acl_len);
93207c478bd9Sstevel@tonic-gate 			rsmpiacl_free(rsmpi_acl, acl_len);
93217c478bd9Sstevel@tonic-gate 
93227c478bd9Sstevel@tonic-gate 			rsmseglock_acquire(segp);
93237c478bd9Sstevel@tonic-gate 			segp->s_state = RSM_STATE_BIND;
93247c478bd9Sstevel@tonic-gate 			cv_broadcast(&segp->s_cv);
93257c478bd9Sstevel@tonic-gate 			rsmseglock_release(segp);
93267c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_ERR,
93277c478bd9Sstevel@tonic-gate 			    "%s done: exp_qscd publish failed = %d\n",
93287c478bd9Sstevel@tonic-gate 			    function, ret));
93297c478bd9Sstevel@tonic-gate 			return;
93307c478bd9Sstevel@tonic-gate 		}
93317c478bd9Sstevel@tonic-gate 
93327c478bd9Sstevel@tonic-gate 		segp->s_state = RSM_STATE_EXPORT;
93337c478bd9Sstevel@tonic-gate 		cv_broadcast(&segp->s_cv);
93347c478bd9Sstevel@tonic-gate 		rsmseglock_release(segp);
93357c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "%s done: exp_qscd\n",
93367c478bd9Sstevel@tonic-gate 		    function));
93377c478bd9Sstevel@tonic-gate 		return;
93387c478bd9Sstevel@tonic-gate 	}
93397c478bd9Sstevel@tonic-gate 
93407c478bd9Sstevel@tonic-gate 	rsmseglock_release(segp);
93417c478bd9Sstevel@tonic-gate 
93427c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "%s done\n", function));
93437c478bd9Sstevel@tonic-gate }
93447c478bd9Sstevel@tonic-gate 
93457c478bd9Sstevel@tonic-gate static void
rsm_quiesce_imp_seg(rsmresource_t * resp)93467c478bd9Sstevel@tonic-gate rsm_quiesce_imp_seg(rsmresource_t *resp)
93477c478bd9Sstevel@tonic-gate {
93487c478bd9Sstevel@tonic-gate 	rsmseg_t	*segp = (rsmseg_t *)resp;
93497c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL);
93507c478bd9Sstevel@tonic-gate 	DBG_DEFINE_STR(function, "rsm_quiesce_imp_seg");
93517c478bd9Sstevel@tonic-gate 
93527c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
93537c478bd9Sstevel@tonic-gate 	    "%s enter: key=%u\n", function, segp->s_key));
93547c478bd9Sstevel@tonic-gate 
93557c478bd9Sstevel@tonic-gate 	rsmseglock_acquire(segp);
93567c478bd9Sstevel@tonic-gate 	segp->s_flags |= RSM_DR_INPROGRESS;
93577c478bd9Sstevel@tonic-gate 
93587c478bd9Sstevel@tonic-gate 	while (segp->s_rdmacnt != 0) {
93597c478bd9Sstevel@tonic-gate 		/* wait for the RDMA to complete */
93607c478bd9Sstevel@tonic-gate 		cv_wait(&segp->s_cv, &segp->s_lock);
93617c478bd9Sstevel@tonic-gate 	}
93627c478bd9Sstevel@tonic-gate 
93637c478bd9Sstevel@tonic-gate 	rsmseglock_release(segp);
93647c478bd9Sstevel@tonic-gate 
93657c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "%s done\n", function));
93667c478bd9Sstevel@tonic-gate 
93677c478bd9Sstevel@tonic-gate }
93687c478bd9Sstevel@tonic-gate 
93697c478bd9Sstevel@tonic-gate static void
rsm_unquiesce_imp_seg(rsmresource_t * resp)93707c478bd9Sstevel@tonic-gate rsm_unquiesce_imp_seg(rsmresource_t *resp)
93717c478bd9Sstevel@tonic-gate {
93727c478bd9Sstevel@tonic-gate 	rsmseg_t	*segp = (rsmseg_t *)resp;
93737c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL);
93747c478bd9Sstevel@tonic-gate 	DBG_DEFINE_STR(function, "rsm_unquiesce_imp_seg");
93757c478bd9Sstevel@tonic-gate 
93767c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
93777c478bd9Sstevel@tonic-gate 	    "%s enter: key=%u\n", function, segp->s_key));
93787c478bd9Sstevel@tonic-gate 
93797c478bd9Sstevel@tonic-gate 	rsmseglock_acquire(segp);
93807c478bd9Sstevel@tonic-gate 
93817c478bd9Sstevel@tonic-gate 	segp->s_flags &= ~RSM_DR_INPROGRESS;
93827c478bd9Sstevel@tonic-gate 	/* wake up any waiting putv/getv ops */
93837c478bd9Sstevel@tonic-gate 	cv_broadcast(&segp->s_cv);
93847c478bd9Sstevel@tonic-gate 
93857c478bd9Sstevel@tonic-gate 	rsmseglock_release(segp);
93867c478bd9Sstevel@tonic-gate 
93877c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE, "%s done\n", function));
93887c478bd9Sstevel@tonic-gate 
93897c478bd9Sstevel@tonic-gate 
93907c478bd9Sstevel@tonic-gate }
93917c478bd9Sstevel@tonic-gate 
93927c478bd9Sstevel@tonic-gate static void
rsm_process_exp_seg(rsmresource_t * resp,int event)93937c478bd9Sstevel@tonic-gate rsm_process_exp_seg(rsmresource_t *resp, int event)
93947c478bd9Sstevel@tonic-gate {
93957c478bd9Sstevel@tonic-gate 	if (event == RSM_DR_QUIESCE)
93967c478bd9Sstevel@tonic-gate 		rsm_quiesce_exp_seg(resp);
93977c478bd9Sstevel@tonic-gate 	else /* UNQUIESCE */
93987c478bd9Sstevel@tonic-gate 		rsm_unquiesce_exp_seg(resp);
93997c478bd9Sstevel@tonic-gate }
94007c478bd9Sstevel@tonic-gate 
94017c478bd9Sstevel@tonic-gate static void
rsm_process_imp_seg(rsmresource_t * resp,int event)94027c478bd9Sstevel@tonic-gate rsm_process_imp_seg(rsmresource_t *resp, int event)
94037c478bd9Sstevel@tonic-gate {
94047c478bd9Sstevel@tonic-gate 	if (event == RSM_DR_QUIESCE)
94057c478bd9Sstevel@tonic-gate 		rsm_quiesce_imp_seg(resp);
94067c478bd9Sstevel@tonic-gate 	else /* UNQUIESCE */
94077c478bd9Sstevel@tonic-gate 		rsm_unquiesce_imp_seg(resp);
94087c478bd9Sstevel@tonic-gate }
94097c478bd9Sstevel@tonic-gate 
94107c478bd9Sstevel@tonic-gate static void
rsm_dr_process_local_segments(int event)94117c478bd9Sstevel@tonic-gate rsm_dr_process_local_segments(int event)
94127c478bd9Sstevel@tonic-gate {
94137c478bd9Sstevel@tonic-gate 
94147c478bd9Sstevel@tonic-gate 	int i, j;
94157c478bd9Sstevel@tonic-gate 	rsmresource_blk_t	*blk;
94167c478bd9Sstevel@tonic-gate 	rsmresource_t		*p;
94177c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL);
94187c478bd9Sstevel@tonic-gate 
94197c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
94207c478bd9Sstevel@tonic-gate 	    "rsm_dr_process_local_segments enter\n"));
94217c478bd9Sstevel@tonic-gate 
94227c478bd9Sstevel@tonic-gate 	/* iterate through the resource structure */
94237c478bd9Sstevel@tonic-gate 
94247c478bd9Sstevel@tonic-gate 	rw_enter(&rsm_resource.rsmrc_lock, RW_READER);
94257c478bd9Sstevel@tonic-gate 
94267c478bd9Sstevel@tonic-gate 	for (i = 0; i < rsm_resource.rsmrc_len; i++) {
94277c478bd9Sstevel@tonic-gate 		blk = rsm_resource.rsmrc_root[i];
94287c478bd9Sstevel@tonic-gate 		if (blk != NULL) {
94297c478bd9Sstevel@tonic-gate 			for (j = 0; j < RSMRC_BLKSZ; j++) {
94307c478bd9Sstevel@tonic-gate 				p = blk->rsmrcblk_blks[j];
94317c478bd9Sstevel@tonic-gate 				if ((p != NULL) && (p != RSMRC_RESERVED)) {
94327c478bd9Sstevel@tonic-gate 					/* valid resource */
94337c478bd9Sstevel@tonic-gate 					if (p->rsmrc_type ==
94347c478bd9Sstevel@tonic-gate 					    RSM_RESOURCE_EXPORT_SEGMENT)
94357c478bd9Sstevel@tonic-gate 						rsm_process_exp_seg(p, event);
94367c478bd9Sstevel@tonic-gate 					else if (p->rsmrc_type ==
94377c478bd9Sstevel@tonic-gate 					    RSM_RESOURCE_IMPORT_SEGMENT)
94387c478bd9Sstevel@tonic-gate 						rsm_process_imp_seg(p, event);
94397c478bd9Sstevel@tonic-gate 				}
94407c478bd9Sstevel@tonic-gate 			}
94417c478bd9Sstevel@tonic-gate 		}
94427c478bd9Sstevel@tonic-gate 	}
94437c478bd9Sstevel@tonic-gate 
94447c478bd9Sstevel@tonic-gate 	rw_exit(&rsm_resource.rsmrc_lock);
94457c478bd9Sstevel@tonic-gate 
94467c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
94477c478bd9Sstevel@tonic-gate 	    "rsm_dr_process_local_segments done\n"));
94487c478bd9Sstevel@tonic-gate }
94497c478bd9Sstevel@tonic-gate 
94507c478bd9Sstevel@tonic-gate /* *************** DR callback functions ************ */
94517c478bd9Sstevel@tonic-gate static void
rsm_dr_callback_post_add(void * arg,pgcnt_t delta)94527c478bd9Sstevel@tonic-gate rsm_dr_callback_post_add(void *arg, pgcnt_t delta /* ARGSUSED */)
94537c478bd9Sstevel@tonic-gate {
94547c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL);
94557c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
94567c478bd9Sstevel@tonic-gate 	    "rsm_dr_callback_post_add is a no-op\n"));
94577c478bd9Sstevel@tonic-gate 	/* Noop */
94587c478bd9Sstevel@tonic-gate }
94597c478bd9Sstevel@tonic-gate 
94607c478bd9Sstevel@tonic-gate static int
rsm_dr_callback_pre_del(void * arg,pgcnt_t delta)94617c478bd9Sstevel@tonic-gate rsm_dr_callback_pre_del(void *arg, pgcnt_t delta /* ARGSUSED */)
94627c478bd9Sstevel@tonic-gate {
94637c478bd9Sstevel@tonic-gate 	int	recheck_state = 0;
94647c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL);
94657c478bd9Sstevel@tonic-gate 
94667c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
94677c478bd9Sstevel@tonic-gate 	    "rsm_dr_callback_pre_del enter\n"));
94687c478bd9Sstevel@tonic-gate 
94697c478bd9Sstevel@tonic-gate 	mutex_enter(&rsm_drv_data.drv_lock);
94707c478bd9Sstevel@tonic-gate 
94717c478bd9Sstevel@tonic-gate 	do {
94727c478bd9Sstevel@tonic-gate 		recheck_state = 0;
94737c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
94747c478bd9Sstevel@tonic-gate 		    "rsm_dr_callback_pre_del:state=%d\n",
94757c478bd9Sstevel@tonic-gate 		    rsm_drv_data.drv_state));
94767c478bd9Sstevel@tonic-gate 
94777c478bd9Sstevel@tonic-gate 		switch (rsm_drv_data.drv_state) {
94787c478bd9Sstevel@tonic-gate 		case RSM_DRV_NEW:
94797c478bd9Sstevel@tonic-gate 			/*
94807c478bd9Sstevel@tonic-gate 			 * The state should usually never be RSM_DRV_NEW
94817c478bd9Sstevel@tonic-gate 			 * since in this state the callbacks have not yet
94827c478bd9Sstevel@tonic-gate 			 * been registered. So, ASSERT.
94837c478bd9Sstevel@tonic-gate 			 */
94847c478bd9Sstevel@tonic-gate 			ASSERT(0);
94857c478bd9Sstevel@tonic-gate 			return (0);
94867c478bd9Sstevel@tonic-gate 		case RSM_DRV_REG_PROCESSING:
94877c478bd9Sstevel@tonic-gate 			/*
94887c478bd9Sstevel@tonic-gate 			 * The driver is in the process of registering
94897c478bd9Sstevel@tonic-gate 			 * with the DR framework. So, wait till the
94907c478bd9Sstevel@tonic-gate 			 * registration process is complete.
94917c478bd9Sstevel@tonic-gate 			 */
94927c478bd9Sstevel@tonic-gate 			recheck_state = 1;
94937c478bd9Sstevel@tonic-gate 			cv_wait(&rsm_drv_data.drv_cv, &rsm_drv_data.drv_lock);
94947c478bd9Sstevel@tonic-gate 			break;
94957c478bd9Sstevel@tonic-gate 		case RSM_DRV_UNREG_PROCESSING:
94967c478bd9Sstevel@tonic-gate 			/*
94977c478bd9Sstevel@tonic-gate 			 * If the state is RSM_DRV_UNREG_PROCESSING, the
94987c478bd9Sstevel@tonic-gate 			 * module is in the process of detaching and
94997c478bd9Sstevel@tonic-gate 			 * unregistering the callbacks from the DR
95007c478bd9Sstevel@tonic-gate 			 * framework. So, simply return.
95017c478bd9Sstevel@tonic-gate 			 */
95027c478bd9Sstevel@tonic-gate 			mutex_exit(&rsm_drv_data.drv_lock);
95037c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG,
95047c478bd9Sstevel@tonic-gate 			    "rsm_dr_callback_pre_del:"
95057c478bd9Sstevel@tonic-gate 			    "pre-del on NEW/UNREG\n"));
95067c478bd9Sstevel@tonic-gate 			return (0);
95077c478bd9Sstevel@tonic-gate 		case RSM_DRV_OK:
95087c478bd9Sstevel@tonic-gate 			rsm_drv_data.drv_state = RSM_DRV_PREDEL_STARTED;
95097c478bd9Sstevel@tonic-gate 			break;
95107c478bd9Sstevel@tonic-gate 		case RSM_DRV_PREDEL_STARTED:
95117c478bd9Sstevel@tonic-gate 			/* FALLTHRU */
95127c478bd9Sstevel@tonic-gate 		case RSM_DRV_PREDEL_COMPLETED:
95137c478bd9Sstevel@tonic-gate 			/* FALLTHRU */
95147c478bd9Sstevel@tonic-gate 		case RSM_DRV_POSTDEL_IN_PROGRESS:
95157c478bd9Sstevel@tonic-gate 			recheck_state = 1;
95167c478bd9Sstevel@tonic-gate 			cv_wait(&rsm_drv_data.drv_cv, &rsm_drv_data.drv_lock);
95177c478bd9Sstevel@tonic-gate 			break;
95187c478bd9Sstevel@tonic-gate 		case RSM_DRV_DR_IN_PROGRESS:
95197c478bd9Sstevel@tonic-gate 			rsm_drv_data.drv_memdel_cnt++;
95207c478bd9Sstevel@tonic-gate 			mutex_exit(&rsm_drv_data.drv_lock);
95217c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
95227c478bd9Sstevel@tonic-gate 			    "rsm_dr_callback_pre_del done\n"));
95237c478bd9Sstevel@tonic-gate 			return (0);
95247c478bd9Sstevel@tonic-gate 			/* break; */
95257c478bd9Sstevel@tonic-gate 		default:
95267c478bd9Sstevel@tonic-gate 			ASSERT(0);
95277c478bd9Sstevel@tonic-gate 			break;
95287c478bd9Sstevel@tonic-gate 		}
95297c478bd9Sstevel@tonic-gate 
95307c478bd9Sstevel@tonic-gate 	} while (recheck_state);
95317c478bd9Sstevel@tonic-gate 
95327c478bd9Sstevel@tonic-gate 	rsm_drv_data.drv_memdel_cnt++;
95337c478bd9Sstevel@tonic-gate 
95347c478bd9Sstevel@tonic-gate 	mutex_exit(&rsm_drv_data.drv_lock);
95357c478bd9Sstevel@tonic-gate 
95367c478bd9Sstevel@tonic-gate 	/* Do all the quiescing stuff here */
95377c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG,
95387c478bd9Sstevel@tonic-gate 	    "rsm_dr_callback_pre_del: quiesce things now\n"));
95397c478bd9Sstevel@tonic-gate 
95407c478bd9Sstevel@tonic-gate 	rsm_dr_process_local_segments(RSM_DR_QUIESCE);
95417c478bd9Sstevel@tonic-gate 
95427c478bd9Sstevel@tonic-gate 	/*
95437c478bd9Sstevel@tonic-gate 	 * now that all local segments have been quiesced lets inform
95447c478bd9Sstevel@tonic-gate 	 * the importers
95457c478bd9Sstevel@tonic-gate 	 */
95467c478bd9Sstevel@tonic-gate 	rsm_send_suspend();
95477c478bd9Sstevel@tonic-gate 
95487c478bd9Sstevel@tonic-gate 	/*
95497c478bd9Sstevel@tonic-gate 	 * In response to the suspend message the remote node(s) will process
95507c478bd9Sstevel@tonic-gate 	 * the segments and send a suspend_complete message. Till all
95517c478bd9Sstevel@tonic-gate 	 * the nodes send the suspend_complete message we wait in the
95527c478bd9Sstevel@tonic-gate 	 * RSM_DRV_PREDEL_STARTED state. In the exporter_quiesce
95537c478bd9Sstevel@tonic-gate 	 * function we transition to the RSM_DRV_PREDEL_COMPLETED state.
95547c478bd9Sstevel@tonic-gate 	 */
95557c478bd9Sstevel@tonic-gate 	mutex_enter(&rsm_drv_data.drv_lock);
95567c478bd9Sstevel@tonic-gate 
95577c478bd9Sstevel@tonic-gate 	while (rsm_drv_data.drv_state == RSM_DRV_PREDEL_STARTED) {
95587c478bd9Sstevel@tonic-gate 		cv_wait(&rsm_drv_data.drv_cv, &rsm_drv_data.drv_lock);
95597c478bd9Sstevel@tonic-gate 	}
95607c478bd9Sstevel@tonic-gate 
95617c478bd9Sstevel@tonic-gate 	ASSERT(rsm_drv_data.drv_state == RSM_DRV_PREDEL_COMPLETED);
95627c478bd9Sstevel@tonic-gate 
95637c478bd9Sstevel@tonic-gate 	rsm_drv_data.drv_state = RSM_DRV_DR_IN_PROGRESS;
95647c478bd9Sstevel@tonic-gate 	cv_broadcast(&rsm_drv_data.drv_cv);
95657c478bd9Sstevel@tonic-gate 
95667c478bd9Sstevel@tonic-gate 	mutex_exit(&rsm_drv_data.drv_lock);
95677c478bd9Sstevel@tonic-gate 
95687c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
95697c478bd9Sstevel@tonic-gate 	    "rsm_dr_callback_pre_del done\n"));
95707c478bd9Sstevel@tonic-gate 
95717c478bd9Sstevel@tonic-gate 	return (0);
95727c478bd9Sstevel@tonic-gate }
95737c478bd9Sstevel@tonic-gate 
95747c478bd9Sstevel@tonic-gate static void
rsm_dr_callback_post_del(void * arg,pgcnt_t delta,int cancelled)95757c478bd9Sstevel@tonic-gate rsm_dr_callback_post_del(void *arg, pgcnt_t delta, int cancelled /* ARGSUSED */)
95767c478bd9Sstevel@tonic-gate {
95777c478bd9Sstevel@tonic-gate 	int	recheck_state = 0;
95787c478bd9Sstevel@tonic-gate 	DBG_DEFINE(category, RSM_KERNEL_AGENT | RSM_FUNC_ALL);
95797c478bd9Sstevel@tonic-gate 
95807c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
95817c478bd9Sstevel@tonic-gate 	    "rsm_dr_callback_post_del enter\n"));
95827c478bd9Sstevel@tonic-gate 
95837c478bd9Sstevel@tonic-gate 	mutex_enter(&rsm_drv_data.drv_lock);
95847c478bd9Sstevel@tonic-gate 
95857c478bd9Sstevel@tonic-gate 	do {
95867c478bd9Sstevel@tonic-gate 		recheck_state = 0;
95877c478bd9Sstevel@tonic-gate 		DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
95887c478bd9Sstevel@tonic-gate 		    "rsm_dr_callback_post_del:state=%d\n",
95897c478bd9Sstevel@tonic-gate 		    rsm_drv_data.drv_state));
95907c478bd9Sstevel@tonic-gate 
95917c478bd9Sstevel@tonic-gate 		switch (rsm_drv_data.drv_state) {
95927c478bd9Sstevel@tonic-gate 		case RSM_DRV_NEW:
95937c478bd9Sstevel@tonic-gate 			/*
95947c478bd9Sstevel@tonic-gate 			 * The driver state cannot not be RSM_DRV_NEW
95957c478bd9Sstevel@tonic-gate 			 * since in this state the callbacks have not
95967c478bd9Sstevel@tonic-gate 			 * yet been registered.
95977c478bd9Sstevel@tonic-gate 			 */
95987c478bd9Sstevel@tonic-gate 			ASSERT(0);
95997c478bd9Sstevel@tonic-gate 			return;
96007c478bd9Sstevel@tonic-gate 		case RSM_DRV_REG_PROCESSING:
96017c478bd9Sstevel@tonic-gate 			/*
96027c478bd9Sstevel@tonic-gate 			 * The driver is in the process of registering with
96037c478bd9Sstevel@tonic-gate 			 * the DR framework. Wait till the registration is
96047c478bd9Sstevel@tonic-gate 			 * complete.
96057c478bd9Sstevel@tonic-gate 			 */
96067c478bd9Sstevel@tonic-gate 			recheck_state = 1;
96077c478bd9Sstevel@tonic-gate 			cv_wait(&rsm_drv_data.drv_cv, &rsm_drv_data.drv_lock);
96087c478bd9Sstevel@tonic-gate 			break;
96097c478bd9Sstevel@tonic-gate 		case RSM_DRV_UNREG_PROCESSING:
96107c478bd9Sstevel@tonic-gate 			/*
96117c478bd9Sstevel@tonic-gate 			 * RSM_DRV_UNREG_PROCESSING state means the module
96127c478bd9Sstevel@tonic-gate 			 * is detaching and unregistering the callbacks
96137c478bd9Sstevel@tonic-gate 			 * from the DR framework. So simply return.
96147c478bd9Sstevel@tonic-gate 			 */
96157c478bd9Sstevel@tonic-gate 			/* FALLTHRU */
96167c478bd9Sstevel@tonic-gate 		case RSM_DRV_OK:
96177c478bd9Sstevel@tonic-gate 			/*
96187c478bd9Sstevel@tonic-gate 			 * RSM_DRV_OK means we missed the pre-del
96197c478bd9Sstevel@tonic-gate 			 * corresponding to this post-del coz we had not
96207c478bd9Sstevel@tonic-gate 			 * registered yet, so simply return.
96217c478bd9Sstevel@tonic-gate 			 */
96227c478bd9Sstevel@tonic-gate 			mutex_exit(&rsm_drv_data.drv_lock);
96237c478bd9Sstevel@tonic-gate 			DBG_PRINTF((category, RSM_DEBUG,
96247c478bd9Sstevel@tonic-gate 			    "rsm_dr_callback_post_del:"
96257c478bd9Sstevel@tonic-gate 			    "post-del on OK/UNREG\n"));
96267c478bd9Sstevel@tonic-gate 			return;
96277c478bd9Sstevel@tonic-gate 			/* break; */
96287c478bd9Sstevel@tonic-gate 		case RSM_DRV_PREDEL_STARTED:
96297c478bd9Sstevel@tonic-gate 			/* FALLTHRU */
96307c478bd9Sstevel@tonic-gate 		case RSM_DRV_PREDEL_COMPLETED:
96317c478bd9Sstevel@tonic-gate 			/* FALLTHRU */
96327c478bd9Sstevel@tonic-gate 		case RSM_DRV_POSTDEL_IN_PROGRESS:
96337c478bd9Sstevel@tonic-gate 			recheck_state = 1;
96347c478bd9Sstevel@tonic-gate 			cv_wait(&rsm_drv_data.drv_cv, &rsm_drv_data.drv_lock);
96357c478bd9Sstevel@tonic-gate 			break;
96367c478bd9Sstevel@tonic-gate 		case RSM_DRV_DR_IN_PROGRESS:
96377c478bd9Sstevel@tonic-gate 			rsm_drv_data.drv_memdel_cnt--;
96387c478bd9Sstevel@tonic-gate 			if (rsm_drv_data.drv_memdel_cnt > 0) {
96397c478bd9Sstevel@tonic-gate 				mutex_exit(&rsm_drv_data.drv_lock);
96407c478bd9Sstevel@tonic-gate 				DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
96417c478bd9Sstevel@tonic-gate 				    "rsm_dr_callback_post_del done:\n"));
96427c478bd9Sstevel@tonic-gate 				return;
96437c478bd9Sstevel@tonic-gate 			}
96447c478bd9Sstevel@tonic-gate 			rsm_drv_data.drv_state = RSM_DRV_POSTDEL_IN_PROGRESS;
96457c478bd9Sstevel@tonic-gate 			break;
96467c478bd9Sstevel@tonic-gate 		default:
96477c478bd9Sstevel@tonic-gate 			ASSERT(0);
96487c478bd9Sstevel@tonic-gate 			return;
96497c478bd9Sstevel@tonic-gate 			/* break; */
96507c478bd9Sstevel@tonic-gate 		}
96517c478bd9Sstevel@tonic-gate 	} while (recheck_state);
96527c478bd9Sstevel@tonic-gate 
96537c478bd9Sstevel@tonic-gate 	mutex_exit(&rsm_drv_data.drv_lock);
96547c478bd9Sstevel@tonic-gate 
96557c478bd9Sstevel@tonic-gate 	/* Do all the unquiescing stuff here */
96567c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG,
96577c478bd9Sstevel@tonic-gate 	    "rsm_dr_callback_post_del: unquiesce things now\n"));
96587c478bd9Sstevel@tonic-gate 
96597c478bd9Sstevel@tonic-gate 	rsm_dr_process_local_segments(RSM_DR_UNQUIESCE);
96607c478bd9Sstevel@tonic-gate 
96617c478bd9Sstevel@tonic-gate 	/*
96627c478bd9Sstevel@tonic-gate 	 * now that all local segments have been unquiesced lets inform
96637c478bd9Sstevel@tonic-gate 	 * the importers
96647c478bd9Sstevel@tonic-gate 	 */
96657c478bd9Sstevel@tonic-gate 	rsm_send_resume();
96667c478bd9Sstevel@tonic-gate 
96677c478bd9Sstevel@tonic-gate 	mutex_enter(&rsm_drv_data.drv_lock);
96687c478bd9Sstevel@tonic-gate 
96697c478bd9Sstevel@tonic-gate 	rsm_drv_data.drv_state = RSM_DRV_OK;
96707c478bd9Sstevel@tonic-gate 
96717c478bd9Sstevel@tonic-gate 	cv_broadcast(&rsm_drv_data.drv_cv);
96727c478bd9Sstevel@tonic-gate 
96737c478bd9Sstevel@tonic-gate 	mutex_exit(&rsm_drv_data.drv_lock);
96747c478bd9Sstevel@tonic-gate 
96757c478bd9Sstevel@tonic-gate 	DBG_PRINTF((category, RSM_DEBUG_VERBOSE,
96767c478bd9Sstevel@tonic-gate 	    "rsm_dr_callback_post_del done\n"));
96777c478bd9Sstevel@tonic-gate 
96787c478bd9Sstevel@tonic-gate 	return;
96797c478bd9Sstevel@tonic-gate 
96807c478bd9Sstevel@tonic-gate }
9681