dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / librsm / common / rsmlib.c
blobc25c9939539e545094f0d96094282e06d972b8ca
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <stdarg.h>
33 #include <string.h>
34 #include <strings.h>
35 #include <ctype.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <sys/mman.h>
39 #include <sys/uio.h>
40 #include <sys/sysmacros.h>
41 #include <sys/resource.h>
42 #include <errno.h>
43 #include <assert.h>
44 #include <fcntl.h>
45 #include <dlfcn.h>
46 #include <sched.h>
47 #include <stropts.h>
48 #include <poll.h>
50 #include <rsmapi.h>
51 #include <sys/rsm/rsmndi.h>
52 #include <rsmlib_in.h>
53 #include <sys/rsm/rsm.h>
55 /* lint -w2 */
56 extern void __rsmloopback_init_ops(rsm_segops_t *);
57 extern void __rsmdefault_setops(rsm_segops_t *);
59 typedef void (*rsm_access_func_t)(void *, void *, rsm_access_size_t);
61 #ifdef DEBUG
63 #define RSMLOG_BUF_SIZE 256
64 FILE *rsmlog_fd = NULL;
65 static mutex_t rsmlog_lock;
66 int rsmlibdbg_category = RSM_LIBRARY;
67 int rsmlibdbg_level = RSM_ERR;
68 void dbg_printf(int category, int level, char *fmt, ...);
70 #endif /* DEBUG */
72 rsm_node_id_t rsm_local_nodeid = 0;
74 static rsm_controller_t *controller_list = NULL;
76 static rsm_segops_t loopback_ops;
78 #define MAX_STRLEN 80
80 #define RSM_IOTYPE_PUTGET 1
81 #define RSM_IOTYPE_SCATGATH 2
83 #define RSMFILE_BUFSIZE 256
85 #pragma init(_rsm_librsm_init)
87 static mutex_t _rsm_lock;
89 static int _rsm_fd = -1;
90 static rsm_gnum_t *bar_va, bar_fixed = 0;
91 static rsm_pollfd_table_t pollfd_table;
93 static int _rsm_get_hwaddr(rsmapi_controller_handle_t handle,
94 rsm_node_id_t, rsm_addr_t *hwaddrp);
95 static int _rsm_get_nodeid(rsmapi_controller_handle_t,
96 rsm_addr_t, rsm_node_id_t *);
97 static int __rsm_import_implicit_map(rsmseg_handle_t *, int);
98 static int __rsm_intr_signal_wait_common(struct pollfd [], minor_t [],
99 nfds_t, int, int *);
101 static rsm_lib_funcs_t lib_functions = {
102 RSM_LIB_FUNCS_VERSION,
103 _rsm_get_hwaddr,
104 _rsm_get_nodeid
107 rsm_topology_t *tp;
111 * service module function templates:
115 * The _rsm_librsm_init function is called the first time an application
116 * references the RSMAPI library
119 _rsm_librsm_init()
121 rsm_ioctlmsg_t msg;
122 int e, tmpfd;
123 int i;
124 char logname[MAXNAMELEN];
126 mutex_init(&_rsm_lock, USYNC_THREAD, NULL);
128 #ifdef DEBUG
129 mutex_init(&rsmlog_lock, USYNC_THREAD, NULL);
130 sprintf(logname, "%s.%d", TRACELOG, getpid());
131 rsmlog_fd = fopen(logname, "w+F");
132 if (rsmlog_fd == NULL) {
133 fprintf(stderr, "Log file open failed\n");
134 return (errno);
137 #endif /* DEBUG */
139 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
140 "_rsm_librsm_init: enter\n"));
142 /* initialize the pollfd_table */
143 mutex_init(&pollfd_table.lock, USYNC_THREAD, NULL);
145 for (i = 0; i < RSM_MAX_BUCKETS; i++) {
146 pollfd_table.buckets[i] = NULL;
149 /* open /dev/rsm and mmap barrier generation pages */
150 mutex_lock(&_rsm_lock);
151 _rsm_fd = open(DEVRSM, O_RDONLY);
152 if (_rsm_fd < 0) {
153 DBPRINTF((RSM_LIBRARY, RSM_ERR,
154 "unable to open /dev/rsm\n"));
155 mutex_unlock(&_rsm_lock);
156 return (errno);
160 * DUP the opened file descriptor to something greater than
161 * STDERR_FILENO so that we never use the STDIN_FILENO,
162 * STDOUT_FILENO or STDERR_FILENO.
164 tmpfd = fcntl(_rsm_fd, F_DUPFD, 3);
165 if (tmpfd < 0) {
166 DBPRINTF((RSM_LIBRARY, RSM_ERR,
167 "F_DUPFD failed\n"));
168 } else {
169 (void) close(_rsm_fd);
170 _rsm_fd = tmpfd;
173 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
174 "_rsm_fd is %d\n", _rsm_fd));
176 if (fcntl(_rsm_fd, F_SETFD, FD_CLOEXEC) < 0) {
177 DBPRINTF((RSM_LIBRARY, RSM_ERR,
178 "F_SETFD failed\n"));
181 /* get mapping generation number page info */
182 if (ioctl(_rsm_fd, RSM_IOCTL_BAR_INFO, &msg) < 0) {
183 DBPRINTF((RSM_LIBRARY, RSM_ERR,
184 "RSM_IOCTL_BAR_INFO failed\n"));
185 mutex_unlock(&_rsm_lock);
186 return (errno);
190 * bar_va is mapped to the mapping generation number page
191 * in order to support close barrier
193 /* LINTED */
194 bar_va = mmap(NULL, msg.len,
195 PROT_READ, MAP_SHARED, _rsm_fd, msg.off);
196 if (bar_va == (rsm_gnum_t *)MAP_FAILED) {
197 bar_va = NULL;
198 mutex_unlock(&_rsm_lock);
199 DBPRINTF((RSM_LIBRARY, RSM_ERR,
200 "unable to map barrier page\n"));
201 return (RSMERR_MAP_FAILED);
204 mutex_unlock(&_rsm_lock);
206 /* get local nodeid */
207 e = rsm_get_interconnect_topology(&tp);
208 if (e != RSM_SUCCESS) {
209 DBPRINTF((RSM_LIBRARY, RSM_ERR,
210 "unable to obtain topology data\n"));
211 return (e);
212 } else
213 rsm_local_nodeid = tp->topology_hdr.local_nodeid;
215 rsm_free_interconnect_topology(tp);
217 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
218 "_rsm_librsm_init: exit\n"));
220 return (RSM_SUCCESS);
223 static int
224 _rsm_loopbackload(caddr_t name, int unit, rsm_controller_t **chdl)
226 rsm_controller_t *p;
227 rsm_ioctlmsg_t msg;
229 DBPRINTF((RSM_LIBRARY|RSM_LOOPBACK, RSM_DEBUG_VERBOSE,
230 "_rsm_loopbackload: enter\n"));
232 * For now do this, but we should open some file and read the
233 * list of supported controllers and there numbers.
236 p = (rsm_controller_t *)malloc(sizeof (*p) + strlen(name) + 1);
237 if (!p) {
238 DBPRINTF((RSM_LIBRARY|RSM_LOOPBACK, RSM_ERR,
239 "not enough memory\n"));
240 return (RSMERR_INSUFFICIENT_MEM);
243 msg.cname = name;
244 msg.cname_len = strlen(name) +1;
245 msg.cnum = unit;
246 msg.arg = (caddr_t)&p->cntr_attr;
247 if (ioctl(_rsm_fd, RSM_IOCTL_ATTR, &msg) < 0) {
248 int error = errno;
249 free((void *)p);
250 DBPRINTF((RSM_LIBRARY|RSM_LOOPBACK, RSM_ERR,
251 "RSM_IOCTL_ATTR failed\n"));
252 return (error);
255 __rsmloopback_init_ops(&loopback_ops);
256 __rsmdefault_setops(&loopback_ops);
257 p->cntr_segops = &loopback_ops;
260 * Should add this entry into list
262 p->cntr_fd = _rsm_fd;
263 p->cntr_name = strcpy((char *)(p+1), name);
264 p->cntr_unit = unit;
265 p->cntr_refcnt = 1;
268 mutex_init(&p->cntr_lock, USYNC_THREAD, NULL);
269 cond_init(&p->cntr_cv, USYNC_THREAD, NULL);
270 p->cntr_rqlist = NULL;
271 p->cntr_segops->rsm_get_lib_attr(&p->cntr_lib_attr);
272 p->cntr_next = controller_list;
273 controller_list = p;
275 *chdl = p;
277 DBPRINTF((RSM_LIBRARY|RSM_LOOPBACK, RSM_DEBUG_VERBOSE,
278 "_rsm_loopbackload: exit\n"));
279 return (RSM_SUCCESS);
283 static int
284 _rsm_modload(caddr_t name, int unit, rsmapi_controller_handle_t *controller)
286 int error = RSM_SUCCESS;
287 char clib[MAX_STRLEN];
288 rsm_controller_t *p = NULL;
289 void *dlh;
290 rsm_attach_entry_t fptr;
291 rsm_ioctlmsg_t msg;
293 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
294 "_rsm_modload: enter\n"));
296 (void) sprintf(clib, "%s.so", name);
298 /* found entry, try to load library */
299 dlh = dlopen(clib, RTLD_LAZY);
300 if (dlh == NULL) {
301 DBPRINTF((RSM_LIBRARY, RSM_ERR,
302 "unable to find plugin library\n"));
303 error = RSMERR_CTLR_NOT_PRESENT;
304 goto skiplib;
307 (void) sprintf(clib, "%s_opendevice", name);
309 fptr = (rsm_attach_entry_t)dlsym(dlh, clib); /* lint !e611 */
310 if (fptr != NULL) {
311 /* allocate new lib structure */
312 /* get ops handler, attr and ops */
313 p = (rsm_controller_t *)malloc(sizeof (*p) + strlen(name) + 1);
314 if (p != NULL) {
315 error = fptr(unit, &p->cntr_segops);
316 } else {
317 error = RSMERR_INSUFFICIENT_MEM;
318 DBPRINTF((RSM_LIBRARY, RSM_ERR,
319 "not enough memory\n"));
321 } else {
322 DBPRINTF((RSM_LIBRARY, RSM_ERR,
323 "can't find symbol %s\n", clib));
324 error = RSMERR_CTLR_NOT_PRESENT;
325 (void) dlclose(dlh);
328 skiplib:
329 if ((error != RSM_SUCCESS) || (p == NULL)) {
330 if (p != NULL)
331 free((void *)p);
332 DBPRINTF((RSM_LIBRARY, RSM_ERR,
333 "_rsm_modload error %d\n", error));
334 return (error);
337 /* check the version number */
338 if (p->cntr_segops->rsm_version != RSM_LIB_VERSION) {
339 /* bad version number */
340 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
341 "wrong version; "
342 "found %d, expected %d\n",
343 p->cntr_segops->rsm_version, RSM_LIB_VERSION));
344 free(p);
345 return (RSMERR_BAD_LIBRARY_VERSION);
346 } else {
347 /* pass the fuctions to NDI library */
348 if ((p->cntr_segops->rsm_register_lib_funcs == NULL) ||
349 (p->cntr_segops->rsm_register_lib_funcs(
350 &lib_functions) != RSM_SUCCESS)) {
351 DBPRINTF((RSM_LIBRARY, RSM_ERR,
352 "RSMNDI library not registering lib functions\n"));
355 /* get controller attributes */
356 msg.cnum = unit;
357 msg.cname = name;
358 msg.cname_len = strlen(name) +1;
359 msg.arg = (caddr_t)&p->cntr_attr;
360 if (ioctl(_rsm_fd, RSM_IOCTL_ATTR, &msg) < 0) {
361 error = errno;
362 free((void *)p);
363 DBPRINTF((RSM_LIBRARY, RSM_ERR,
364 "RSM_IOCTL_ATTR failed\n"));
365 return (error);
368 /* set controller access functions */
369 __rsmdefault_setops(p->cntr_segops);
371 mutex_init(&p->cntr_lock, USYNC_THREAD, NULL);
372 cond_init(&p->cntr_cv, USYNC_THREAD, NULL);
373 p->cntr_rqlist = NULL;
374 p->cntr_segops->rsm_get_lib_attr(&p->cntr_lib_attr);
375 /* insert into list of controllers */
376 p->cntr_name = strcpy((char *)(p+1), name);
377 p->cntr_fd = _rsm_fd;
378 p->cntr_unit = unit;
379 p->cntr_refcnt = 1; /* first reference */
380 p->cntr_next = controller_list;
381 controller_list = p;
382 *controller = (rsmapi_controller_handle_t)p;
383 errno = RSM_SUCCESS;
386 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
387 "_rsm_modload: exit\n"));
388 return (error);
392 * inserts a given segment handle into the pollfd table, this is called
393 * when rsm_memseg_get_pollfd() is called the first time on a segment handle.
394 * Returns RSM_SUCCESS if successful otherwise the error code is returned
396 static int
397 _rsm_insert_pollfd_table(int segfd, minor_t segrnum)
399 int i;
400 int hash;
401 rsm_pollfd_chunk_t *chunk;
403 hash = RSM_POLLFD_HASH(segfd);
405 mutex_lock(&pollfd_table.lock);
407 chunk = pollfd_table.buckets[hash];
408 while (chunk) {
409 if (chunk->nfree > 0)
410 break;
411 chunk = chunk->next;
414 if (!chunk) { /* couldn't find a free chunk - allocate a new one */
415 chunk = malloc(sizeof (rsm_pollfd_chunk_t));
416 if (!chunk) {
417 mutex_unlock(&pollfd_table.lock);
418 return (RSMERR_INSUFFICIENT_MEM);
420 chunk->nfree = RSM_POLLFD_PER_CHUNK - 1;
421 chunk->fdarray[0].fd = segfd;
422 chunk->fdarray[0].segrnum = segrnum;
423 for (i = 1; i < RSM_POLLFD_PER_CHUNK; i++) {
424 chunk->fdarray[i].fd = -1;
425 chunk->fdarray[i].segrnum = 0;
427 /* insert this into the hash table */
428 chunk->next = pollfd_table.buckets[hash];
429 pollfd_table.buckets[hash] = chunk;
430 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
431 "rsm_insert_pollfd: new chunk(%p) @ %d for %d:%d\n",
432 chunk, hash, segfd, segrnum));
433 } else { /* a chunk with free slot was found */
434 for (i = 0; i < RSM_POLLFD_PER_CHUNK; i++) {
435 if (chunk->fdarray[i].fd == -1) {
436 chunk->fdarray[i].fd = segfd;
437 chunk->fdarray[i].segrnum = segrnum;
438 chunk->nfree--;
439 break;
442 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
443 "rsm_insert_pollfd: inserted @ %d for %d:%d chunk(%p)\n",
444 hash, segfd, segrnum, chunk));
445 assert(i < RSM_POLLFD_PER_CHUNK);
448 mutex_unlock(&pollfd_table.lock);
449 return (RSM_SUCCESS);
453 * Given a file descriptor returns the corresponding segment handles
454 * resource number, if the fd is not found returns 0. 0 is not a valid
455 * minor number for a rsmapi segment since it is used for the barrier
456 * resource.
458 static minor_t
459 _rsm_lookup_pollfd_table(int segfd)
461 int i;
462 rsm_pollfd_chunk_t *chunk;
464 if (segfd < 0)
465 return (0);
467 mutex_lock(&pollfd_table.lock);
469 chunk = pollfd_table.buckets[RSM_POLLFD_HASH(segfd)];
470 while (chunk) {
471 assert(chunk->nfree < RSM_POLLFD_PER_CHUNK);
473 for (i = 0; i < RSM_POLLFD_PER_CHUNK; i++) {
474 if (chunk->fdarray[i].fd == segfd) {
475 mutex_unlock(&pollfd_table.lock);
476 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
477 "rsm_lookup_pollfd: found(%d) rnum(%d)\n",
478 segfd, chunk->fdarray[i].segrnum));
479 return (chunk->fdarray[i].segrnum);
482 chunk = chunk->next;
485 mutex_unlock(&pollfd_table.lock);
487 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
488 "rsm_lookup_pollfd: not found(%d)\n", segfd));
490 return (0);
494 * Remove the entry corresponding to the given file descriptor from the
495 * pollfd table.
497 static void
498 _rsm_remove_pollfd_table(int segfd)
500 int i;
501 int hash;
502 rsm_pollfd_chunk_t *chunk;
503 rsm_pollfd_chunk_t *prev_chunk;
505 if (segfd < 0)
506 return;
508 hash = RSM_POLLFD_HASH(segfd);
510 mutex_lock(&pollfd_table.lock);
512 prev_chunk = chunk = pollfd_table.buckets[hash];
513 while (chunk) {
514 assert(chunk->nfree < RSM_POLLFD_PER_CHUNK);
516 for (i = 0; i < RSM_POLLFD_PER_CHUNK; i++) {
517 if (chunk->fdarray[i].fd == segfd) {
518 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
519 "rsm_remove_pollfd: %d:%d\n",
520 chunk->fdarray[i].fd,
521 chunk->fdarray[i].segrnum));
522 chunk->fdarray[i].fd = -1;
523 chunk->fdarray[i].segrnum = 0;
524 chunk->nfree++;
525 if (chunk->nfree == RSM_POLLFD_PER_CHUNK) {
526 /* chunk is empty free it */
527 if (prev_chunk == chunk) {
528 pollfd_table.buckets[hash] =
529 chunk->next;
530 } else {
531 prev_chunk->next = chunk->next;
533 DBPRINTF((RSM_LIBRARY,
534 RSM_DEBUG_VERBOSE,
535 "rsm_remove_pollfd:free(%p)\n",
536 chunk));
537 free(chunk);
538 mutex_unlock(&pollfd_table.lock);
539 return;
543 prev_chunk = chunk;
544 chunk = chunk->next;
547 mutex_unlock(&pollfd_table.lock);
551 rsm_get_controller(char *name, rsmapi_controller_handle_t *chdl)
553 rsm_controller_t *p;
554 char cntr_name[MAXNAMELEN]; /* cntr_name=<cntr_type><unit> */
555 char *cntr_type;
556 int unit = 0;
557 int i, e;
559 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
560 "rsm_get_controller: enter\n"));
562 * Lookup controller name and return ops vector and controller
563 * structure
566 if (!chdl) {
567 DBPRINTF((RSM_LIBRARY, RSM_ERR,
568 "Invalid controller handle\n"));
569 return (RSMERR_BAD_CTLR_HNDL);
571 if (!name) {
572 /* use loopback if null */
573 cntr_type = LOOPBACK;
574 } else {
575 (void) strcpy(cntr_name, name);
576 /* scan from the end till a non-digit is found */
577 for (i = strlen(cntr_name) - 1; i >= 0; i--) {
578 if (! isdigit((int)cntr_name[i]))
579 break;
581 i++;
582 unit = atoi((char *)cntr_name+i);
583 cntr_name[i] = '\0'; /* null terminate the cntr_type part */
584 cntr_type = (char *)cntr_name;
585 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
586 "cntr_type=%s, instance=%d\n",
587 cntr_type, unit));
590 /* protect the controller_list by locking the device/library */
591 mutex_lock(&_rsm_lock);
593 for (p = controller_list; p; p = p->cntr_next) {
594 if (!strcasecmp(p->cntr_name, cntr_type) &&
595 !strcasecmp(cntr_type, LOOPBACK)) {
596 p->cntr_refcnt++;
597 *chdl = (rsmapi_controller_handle_t)p;
598 mutex_unlock(&_rsm_lock);
599 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
600 "rsm_get_controller: exit\n"));
601 return (RSM_SUCCESS);
602 } else if (!strcasecmp(p->cntr_name, cntr_type) &&
603 (p->cntr_unit == unit)) {
604 p->cntr_refcnt++;
605 *chdl = (rsmapi_controller_handle_t)p;
606 mutex_unlock(&_rsm_lock);
607 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
608 "rsm_get_controller: exit\n"));
609 return (RSM_SUCCESS);
614 if (!strcasecmp(cntr_type, LOOPBACK)) {
615 e = _rsm_loopbackload(cntr_type, unit,
616 (rsm_controller_t **)chdl);
617 } else {
618 e = _rsm_modload(cntr_type, unit, chdl);
621 mutex_unlock(&_rsm_lock);
623 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
624 " rsm_get_controller: exit\n"));
625 return (e);
629 rsm_release_controller(rsmapi_controller_handle_t cntr_handle)
631 int e = RSM_SUCCESS;
632 rsm_controller_t *chdl = (rsm_controller_t *)cntr_handle;
633 rsm_controller_t *curr, *prev;
635 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
636 "rsm_release_controller: enter\n"));
638 mutex_lock(&_rsm_lock);
640 if (chdl->cntr_refcnt == 0) {
641 mutex_unlock(&_rsm_lock);
642 DBPRINTF((RSM_LIBRARY, RSM_ERR,
643 "controller reference count is zero\n"));
644 return (RSMERR_BAD_CTLR_HNDL);
647 chdl->cntr_refcnt--;
649 if (chdl->cntr_refcnt > 0) {
650 mutex_unlock(&_rsm_lock);
651 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
652 "rsm_release_controller: exit\n"));
653 return (RSM_SUCCESS);
656 e = chdl->cntr_segops->rsm_closedevice(cntr_handle);
659 * remove the controller in any case from the controller list
662 prev = curr = controller_list;
663 while (curr != NULL) {
664 if (curr == chdl) {
665 if (curr == prev) {
666 controller_list = curr->cntr_next;
667 } else {
668 prev->cntr_next = curr->cntr_next;
670 free(curr);
671 break;
673 prev = curr;
674 curr = curr->cntr_next;
676 mutex_unlock(&_rsm_lock);
678 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
679 "rsm_release_controller: exit\n"));
681 return (e);
685 rsm_get_controller_attr(rsmapi_controller_handle_t chandle,
686 rsmapi_controller_attr_t *attr)
688 rsm_controller_t *p;
690 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
691 "rsm_get_controller_attr: enter\n"));
693 if (!chandle) {
694 DBPRINTF((RSM_LIBRARY, RSM_ERR,
695 "invalid controller handle\n"));
696 return (RSMERR_BAD_CTLR_HNDL);
699 if (!attr) {
700 DBPRINTF((RSM_LIBRARY, RSM_ERR,
701 "invalid attribute pointer\n"));
702 return (RSMERR_BAD_ADDR);
705 p = (rsm_controller_t *)chandle;
707 mutex_lock(&_rsm_lock);
708 if (p->cntr_refcnt == 0) {
709 mutex_unlock(&_rsm_lock);
710 DBPRINTF((RSM_LIBRARY, RSM_ERR,
711 "cntr refcnt is 0\n"));
712 return (RSMERR_CTLR_NOT_PRESENT);
715 /* copy only the user part of the attr structure */
716 attr->attr_direct_access_sizes =
717 p->cntr_attr.attr_direct_access_sizes;
718 attr->attr_atomic_sizes =
719 p->cntr_attr.attr_atomic_sizes;
720 attr->attr_page_size =
721 p->cntr_attr.attr_page_size;
722 attr->attr_max_export_segment_size =
723 p->cntr_attr.attr_max_export_segment_size;
724 attr->attr_tot_export_segment_size =
725 p->cntr_attr.attr_tot_export_segment_size;
726 attr->attr_max_export_segments =
727 p->cntr_attr.attr_max_export_segments;
728 attr->attr_max_import_map_size =
729 p->cntr_attr.attr_max_import_map_size;
730 attr->attr_tot_import_map_size =
731 p->cntr_attr.attr_tot_import_map_size;
732 attr->attr_max_import_segments =
733 p->cntr_attr.attr_max_import_segments;
735 mutex_unlock(&_rsm_lock);
737 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
738 "rsm_get_controller_attr: exit\n"));
740 return (RSM_SUCCESS);
746 * Create a segment handle for the virtual address range specified
747 * by vaddr and size
750 rsm_memseg_export_create(rsmapi_controller_handle_t controller,
751 rsm_memseg_export_handle_t *memseg,
752 void *vaddr,
753 size_t length,
754 uint_t flags)
757 rsm_controller_t *chdl = (rsm_controller_t *)controller;
758 rsmseg_handle_t *p;
759 rsm_ioctlmsg_t msg;
760 int e;
761 #ifndef _LP64
762 int tmpfd;
763 #endif
765 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
766 "rsm_memseg_export_create: enter\n"));
768 if (!controller) {
769 DBPRINTF((RSM_LIBRARY, RSM_ERR,
770 "invalid controller handle\n"));
771 return (RSMERR_BAD_CTLR_HNDL);
773 if (!memseg) {
774 DBPRINTF((RSM_LIBRARY, RSM_ERR,
775 "invalid segment handle\n"));
776 return (RSMERR_BAD_SEG_HNDL);
779 *memseg = 0;
782 * Check vaddr and size alignment, both must be mmu page size
783 * aligned
785 if (!vaddr) {
786 DBPRINTF((RSM_LIBRARY, RSM_ERR,
787 "invalid arguments\n"));
788 return (RSMERR_BAD_ADDR);
791 if (!length) {
792 DBPRINTF((RSM_LIBRARY, RSM_ERR,
793 "invalid arguments\n"));
794 return (RSMERR_BAD_LENGTH);
797 if (((size_t)vaddr & (PAGESIZE - 1)) ||
798 (length & (PAGESIZE - 1))) {
799 DBPRINTF((RSM_LIBRARY, RSM_ERR,
800 "invalid mem alignment for vaddr or length\n"));
801 return (RSMERR_BAD_MEM_ALIGNMENT);
805 * The following check does not apply for loopback controller
806 * since for the loopback adapter, the attr_max_export_segment_size
807 * is always 0.
809 if (strcasecmp(chdl->cntr_name, LOOPBACK)) {
810 if (length > chdl->cntr_attr.attr_max_export_segment_size) {
811 DBPRINTF((RSM_LIBRARY, RSM_ERR,
812 "length exceeds controller limits\n"));
813 DBPRINTF((RSM_LIBRARY, RSM_ERR,
814 "controller limits %d\n",
815 chdl->cntr_attr.attr_max_export_segment_size));
816 return (RSMERR_BAD_LENGTH);
820 p = (rsmseg_handle_t *)malloc(sizeof (*p));
821 if (p == NULL) {
822 DBPRINTF((RSM_LIBRARY, RSM_ERR,
823 "not enough memory\n"));
824 return (RSMERR_INSUFFICIENT_MEM);
827 p->rsmseg_fd = open(DEVRSM, O_RDWR);
828 if (p->rsmseg_fd < 0) {
829 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
830 "unable to open device /dev/rsm\n"));
831 free((void *)p);
832 return (RSMERR_INSUFFICIENT_RESOURCES);
835 #ifndef _LP64
837 * libc can't handle fd's greater than 255, in order to
838 * insure that these values remain available make /dev/rsm
839 * fd > 255. Note: not needed for LP64
841 tmpfd = fcntl(p->rsmseg_fd, F_DUPFD, 256);
842 e = errno;
843 if (tmpfd < 0) {
844 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
845 "F_DUPFD failed\n"));
846 } else {
847 (void) close(p->rsmseg_fd);
848 p->rsmseg_fd = tmpfd;
850 #endif /* _LP64 */
852 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE, ""
853 "rsmseg_fd is %d\n", p->rsmseg_fd));
855 if (fcntl(p->rsmseg_fd, F_SETFD, FD_CLOEXEC) < 0) {
856 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
857 "F_SETFD failed\n"));
860 p->rsmseg_state = EXPORT_CREATE;
861 p->rsmseg_size = length;
862 /* increment controller handle */
863 p->rsmseg_controller = chdl;
865 /* try to bind user address range */
866 msg.cnum = chdl->cntr_unit;
867 msg.cname = chdl->cntr_name;
868 msg.cname_len = strlen(chdl->cntr_name) +1;
869 msg.vaddr = vaddr;
870 msg.len = length;
871 msg.perm = flags;
872 msg.off = 0;
873 e = RSM_IOCTL_BIND;
875 /* Try to bind */
876 if (ioctl(p->rsmseg_fd, e, &msg) < 0) {
877 e = errno;
878 (void) close(p->rsmseg_fd);
879 free((void *)p);
880 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
881 "RSM_IOCTL_BIND failed\n"));
882 return (e);
884 /* OK */
885 p->rsmseg_type = RSM_EXPORT_SEG;
886 p->rsmseg_vaddr = vaddr;
887 p->rsmseg_size = length;
888 p->rsmseg_state = EXPORT_BIND;
889 p->rsmseg_pollfd_refcnt = 0;
890 p->rsmseg_rnum = msg.rnum;
892 mutex_init(&p->rsmseg_lock, USYNC_THREAD, NULL);
894 *memseg = (rsm_memseg_export_handle_t)p;
896 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
897 "rsm_memseg_export_create: exit\n"));
899 return (RSM_SUCCESS);
903 rsm_memseg_export_destroy(rsm_memseg_export_handle_t memseg)
905 rsmseg_handle_t *seg;
907 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
908 "rsm_memseg_export_destroy: enter\n"));
910 if (!memseg) {
911 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
912 "invalid segment handle\n"));
913 return (RSMERR_BAD_SEG_HNDL);
916 seg = (rsmseg_handle_t *)memseg;
918 mutex_lock(&seg->rsmseg_lock);
919 if (seg->rsmseg_pollfd_refcnt) {
920 mutex_unlock(&seg->rsmseg_lock);
921 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
922 "segment reference count not zero\n"));
923 return (RSMERR_POLLFD_IN_USE);
925 else
926 seg->rsmseg_state = EXPORT_BIND;
928 mutex_unlock(&seg->rsmseg_lock);
930 (void) close(seg->rsmseg_fd);
931 mutex_destroy(&seg->rsmseg_lock);
932 free((void *)seg);
934 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
935 "rsm_memseg_export_destroy: exit\n"));
937 return (RSM_SUCCESS);
941 rsm_memseg_export_rebind(rsm_memseg_export_handle_t memseg, void *vaddr,
942 offset_t off, size_t length)
944 rsm_ioctlmsg_t msg;
945 rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
947 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
948 "rsm_memseg_export_rebind: enter\n"));
950 off = off;
952 if (!seg) {
953 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
954 "invalid segment handle\n"));
955 return (RSMERR_BAD_SEG_HNDL);
957 if (!vaddr) {
958 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
959 "invalid vaddr\n"));
960 return (RSMERR_BAD_ADDR);
964 * Same as bind except it's ok to have elimint in list.
965 * Call into driver to remove any existing mappings.
967 msg.vaddr = vaddr;
968 msg.len = length;
969 msg.off = 0;
971 mutex_lock(&seg->rsmseg_lock);
972 if (ioctl(seg->rsmseg_fd, RSM_IOCTL_REBIND, &msg) < 0) {
973 mutex_unlock(&seg->rsmseg_lock);
974 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
975 "RSM_IOCTL_REBIND failed\n"));
976 return (errno);
979 mutex_unlock(&seg->rsmseg_lock);
981 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
982 "rsm_memseg_export_rebind: exit\n"));
984 return (RSM_SUCCESS);
988 rsm_memseg_export_publish(rsm_memseg_export_handle_t memseg,
989 rsm_memseg_id_t *seg_id,
990 rsmapi_access_entry_t access_list[],
991 uint_t access_list_length)
994 rsm_ioctlmsg_t msg;
995 rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
997 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
998 "rsm_memseg_export_publish: enter\n"));
1000 if (seg_id == NULL) {
1001 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1002 "invalid segment id\n"));
1003 return (RSMERR_BAD_SEGID);
1006 if (!seg) {
1007 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1008 "invalid segment handle\n"));
1009 return (RSMERR_BAD_SEG_HNDL);
1012 if (access_list_length > 0 && !access_list) {
1013 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1014 "invalid access control list\n"));
1015 return (RSMERR_BAD_ACL);
1018 mutex_lock(&seg->rsmseg_lock);
1019 if (seg->rsmseg_state != EXPORT_BIND) {
1020 mutex_unlock(&seg->rsmseg_lock);
1021 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1022 "invalid segment state\n"));
1023 return (RSMERR_SEG_ALREADY_PUBLISHED);
1027 * seg id < RSM_DLPI_END and in the RSM_USER_APP_ID range
1028 * are reserved for internal use.
1030 if ((*seg_id > 0) &&
1031 ((*seg_id <= RSM_DLPI_ID_END) ||
1032 BETWEEN (*seg_id, RSM_USER_APP_ID_BASE, RSM_USER_APP_ID_END))) {
1033 mutex_unlock(&seg->rsmseg_lock);
1034 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1035 "invalid segment id\n"));
1036 return (RSMERR_RESERVED_SEGID);
1039 msg.key = *seg_id;
1040 msg.acl = access_list;
1041 msg.acl_len = access_list_length;
1043 if (ioctl(seg->rsmseg_fd, RSM_IOCTL_PUBLISH, &msg) < 0) {
1044 mutex_unlock(&seg->rsmseg_lock);
1045 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1046 "RSM_IOCTL_PUBLISH failed\n"));
1047 return (errno);
1050 seg->rsmseg_keyid = msg.key;
1051 seg->rsmseg_state = EXPORT_PUBLISH;
1052 mutex_unlock(&seg->rsmseg_lock);
1054 if (*seg_id == 0)
1055 *seg_id = msg.key;
1057 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
1058 "rsm_memseg_export_publish: exit\n"));
1060 return (RSM_SUCCESS);
1065 rsm_memseg_export_unpublish(rsm_memseg_export_handle_t memseg)
1067 rsm_ioctlmsg_t msg;
1068 rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
1070 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
1071 "rsm_memseg_export_unpublish: enter\n"));
1073 if (!seg) {
1074 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1075 "invalid arguments\n"));
1076 return (RSMERR_BAD_SEG_HNDL);
1079 mutex_lock(&seg->rsmseg_lock);
1080 if (seg->rsmseg_state != EXPORT_PUBLISH) {
1081 mutex_unlock(&seg->rsmseg_lock);
1082 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1083 "segment not published %d\n",
1084 seg->rsmseg_keyid));
1085 return (RSMERR_SEG_NOT_PUBLISHED);
1088 msg.key = seg->rsmseg_keyid;
1089 if (ioctl(seg->rsmseg_fd, RSM_IOCTL_UNPUBLISH, &msg) < 0) {
1090 mutex_unlock(&seg->rsmseg_lock);
1091 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1092 "RSM_IOCTL_UNPUBLISH failed\n"));
1093 return (errno);
1096 seg->rsmseg_state = EXPORT_BIND;
1097 mutex_unlock(&seg->rsmseg_lock);
1099 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
1100 "rsm_memseg_export_unpublish: exit\n"));
1102 return (RSM_SUCCESS);
1107 rsm_memseg_export_republish(rsm_memseg_export_handle_t memseg,
1108 rsmapi_access_entry_t access_list[],
1109 uint_t access_list_length)
1111 rsm_ioctlmsg_t msg;
1112 rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
1114 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
1115 "rsm_memseg_export_republish: enter\n"));
1117 if (!seg) {
1118 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1119 "invalid segment or segment state\n"));
1120 return (RSMERR_BAD_SEG_HNDL);
1123 mutex_lock(&seg->rsmseg_lock);
1124 if (seg->rsmseg_state != EXPORT_PUBLISH) {
1125 mutex_unlock(&seg->rsmseg_lock);
1126 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1127 "segment not published\n"));
1128 return (RSMERR_SEG_NOT_PUBLISHED);
1131 if (access_list_length > 0 && !access_list) {
1132 mutex_unlock(&seg->rsmseg_lock);
1133 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1134 "invalid access control list\n"));
1135 return (RSMERR_BAD_ACL);
1138 msg.key = seg->rsmseg_keyid;
1139 msg.acl = access_list;
1140 msg.acl_len = access_list_length;
1142 if (ioctl(seg->rsmseg_fd, RSM_IOCTL_REPUBLISH, &msg) < 0) {
1143 mutex_unlock(&seg->rsmseg_lock);
1144 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1145 "RSM_IOCTL_REPUBLISH failed\n"));
1146 return (errno);
1148 mutex_unlock(&seg->rsmseg_lock);
1150 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
1151 "rsm_memseg_export_republish: exit\n"));
1153 return (RSM_SUCCESS);
1158 * import side memory segment operations:
1161 rsm_memseg_import_connect(rsmapi_controller_handle_t controller,
1162 rsm_node_id_t node_id,
1163 rsm_memseg_id_t segment_id,
1164 rsm_permission_t perm,
1165 rsm_memseg_import_handle_t *im_memseg)
1167 rsm_ioctlmsg_t msg;
1168 rsmseg_handle_t *p;
1169 rsm_controller_t *cntr = (rsm_controller_t *)controller;
1170 #ifndef _LP64 /* added for fd > 255 fix */
1171 int tmpfd;
1172 #endif
1173 int e;
1175 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1176 "rsm_memseg_import_connect: enter\n"));
1178 if (!cntr) {
1179 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1180 "invalid controller handle\n"));
1181 return (RSMERR_BAD_CTLR_HNDL);
1184 *im_memseg = 0;
1186 p = (rsmseg_handle_t *)malloc(sizeof (*p));
1187 if (!p) {
1188 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1189 "not enough memory\n"));
1190 return (RSMERR_INSUFFICIENT_MEM);
1193 if (perm & ~RSM_PERM_RDWR) {
1194 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1195 "invalid permissions\n"));
1196 return (RSMERR_PERM_DENIED);
1200 * Get size, va from driver
1202 msg.cnum = cntr->cntr_unit;
1203 msg.cname = cntr->cntr_name;
1204 msg.cname_len = strlen(cntr->cntr_name) +1;
1205 msg.nodeid = node_id;
1206 msg.key = segment_id;
1207 msg.perm = perm;
1209 p->rsmseg_fd = open(DEVRSM, O_RDWR);
1210 if (p->rsmseg_fd < 0) {
1211 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1212 "unable to open /dev/rsm"));
1213 free((void *)p);
1214 return (RSMERR_INSUFFICIENT_RESOURCES);
1217 #ifndef _LP64
1219 * libc can't handle fd's greater than 255, in order to
1220 * insure that these values remain available make /dev/rsm
1221 * fd > 255. Note: not needed for LP64
1223 tmpfd = fcntl(p->rsmseg_fd, F_DUPFD, 256); /* make fd > 255 */
1224 e = errno;
1225 if (tmpfd < 0) {
1226 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1227 "F_DUPFD failed\n"));
1228 } else {
1229 (void) close(p->rsmseg_fd);
1230 p->rsmseg_fd = tmpfd;
1232 #endif /* _LP64 */
1234 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
1235 "rsmseg_fd is %d\n", p->rsmseg_fd));
1237 if (fcntl(p->rsmseg_fd, F_SETFD, FD_CLOEXEC) < 0) {
1238 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1239 "F_SETFD failed\n"));
1241 if (ioctl(p->rsmseg_fd, RSM_IOCTL_CONNECT, &msg) < 0) {
1242 e = errno;
1243 (void) close(p->rsmseg_fd);
1244 free((void *)p);
1245 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1246 "RSM_IOCTL_CONNECT failed\n"));
1247 return (e);
1251 * We connected ok.
1253 p->rsmseg_type = RSM_IMPORT_SEG;
1254 p->rsmseg_state = IMPORT_CONNECT;
1255 p->rsmseg_keyid = segment_id;
1256 p->rsmseg_nodeid = node_id;
1257 p->rsmseg_size = msg.len;
1258 p->rsmseg_perm = perm;
1259 p->rsmseg_controller = cntr;
1260 p->rsmseg_barrier = NULL;
1261 p->rsmseg_barmode = RSM_BARRIER_MODE_IMPLICIT;
1262 p->rsmseg_bar = (bar_va ? bar_va + msg.off : &bar_fixed);
1263 p->rsmseg_gnum = msg.gnum;
1264 p->rsmseg_pollfd_refcnt = 0;
1265 p->rsmseg_maplen = 0; /* initialized, set in import_map */
1266 p->rsmseg_mapoffset = 0;
1267 p->rsmseg_flags = 0;
1268 p->rsmseg_rnum = msg.rnum;
1269 mutex_init(&p->rsmseg_lock, USYNC_THREAD, NULL);
1271 p->rsmseg_ops = cntr->cntr_segops;
1274 * XXX: Based on permission and controller direct_access attribute
1275 * we fix the segment ops vector
1278 p->rsmseg_vaddr = 0; /* defer mapping till using maps or trys to rw */
1280 *im_memseg = (rsm_memseg_import_handle_t)p;
1282 e = p->rsmseg_ops->rsm_memseg_import_connect(controller,
1283 node_id, segment_id, perm, im_memseg);
1285 if (e != RSM_SUCCESS) {
1286 (void) close(p->rsmseg_fd);
1287 mutex_destroy(&p->rsmseg_lock);
1288 free((void *)p);
1291 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1292 "rsm_memseg_import_connect: exit\n"));
1294 return (e);
1299 rsm_memseg_import_disconnect(rsm_memseg_import_handle_t im_memseg)
1301 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1302 int e;
1304 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1305 "rsm_memseg_import_disconnect: enter\n"));
1307 if (!seg) {
1308 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1309 "invalid segment handle\n"));
1310 return (RSMERR_BAD_SEG_HNDL);
1313 if (seg->rsmseg_state != IMPORT_CONNECT) {
1314 if (seg->rsmseg_flags & RSM_IMPLICIT_MAP) {
1315 e = rsm_memseg_import_unmap(im_memseg);
1316 if (e != RSM_SUCCESS) {
1317 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1318 "unmap failure\n"));
1319 return (e);
1321 } else {
1322 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1323 "segment busy\n"));
1324 return (RSMERR_SEG_STILL_MAPPED);
1328 mutex_lock(&seg->rsmseg_lock);
1329 if (seg->rsmseg_pollfd_refcnt) {
1330 mutex_unlock(&seg->rsmseg_lock);
1331 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1332 "segment reference count not zero\n"));
1333 return (RSMERR_POLLFD_IN_USE);
1335 mutex_unlock(&seg->rsmseg_lock);
1337 e = seg->rsmseg_ops->rsm_memseg_import_disconnect(im_memseg);
1339 if (e == RSM_SUCCESS) {
1340 (void) close(seg->rsmseg_fd);
1341 mutex_destroy(&seg->rsmseg_lock);
1342 free((void *)seg);
1345 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1346 "rsm_memseg_import_disconnect: exit\n"));
1348 return (e);
1352 * import side memory segment operations (read access functions):
1355 static int
1356 __rsm_import_verify_access(rsmseg_handle_t *seg,
1357 off_t offset,
1358 caddr_t datap,
1359 size_t len,
1360 rsm_permission_t perm,
1361 rsm_access_size_t das)
1363 int error;
1365 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1366 " __rsm_import_verify_access: enter\n"));
1368 if (!seg) {
1369 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1370 "invalid segment handle\n"));
1371 return (RSMERR_BAD_SEG_HNDL);
1373 if (!datap) {
1374 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1375 "invalid data pointer\n"));
1376 return (RSMERR_BAD_ADDR);
1380 * Check alignment of pointer
1382 if ((uintptr_t)datap & (das - 1)) {
1383 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1384 "invalid alignment of data pointer\n"));
1385 return (RSMERR_BAD_MEM_ALIGNMENT);
1388 if (offset & (das - 1)) {
1389 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1390 "invalid offset\n"));
1391 return (RSMERR_BAD_MEM_ALIGNMENT);
1394 /* make sure that the import seg is connected */
1395 if (seg->rsmseg_state != IMPORT_CONNECT &&
1396 seg->rsmseg_state != IMPORT_MAP) {
1397 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1398 "incorrect segment state\n"));
1399 return (RSMERR_BAD_SEG_HNDL);
1402 /* do an implicit map if required */
1403 if (seg->rsmseg_state == IMPORT_CONNECT) {
1404 error = __rsm_import_implicit_map(seg, RSM_IOTYPE_PUTGET);
1405 if (error != RSM_SUCCESS) {
1406 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1407 "implicit map failure\n"));
1408 return (error);
1412 if ((seg->rsmseg_perm & perm) != perm) {
1413 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1414 "invalid permissions\n"));
1415 return (RSMERR_PERM_DENIED);
1418 if (seg->rsmseg_state == IMPORT_MAP) {
1419 if ((offset < seg->rsmseg_mapoffset) ||
1420 (offset + len > seg->rsmseg_mapoffset +
1421 seg->rsmseg_maplen)) {
1422 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1423 "incorrect offset+length\n"));
1424 return (RSMERR_BAD_OFFSET);
1426 } else { /* IMPORT_CONNECT */
1427 if ((len + offset) > seg->rsmseg_size) {
1428 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1429 "incorrect offset+length\n"));
1430 return (RSMERR_BAD_LENGTH);
1434 if ((seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) &&
1435 (seg->rsmseg_barrier == NULL)) {
1436 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1437 "invalid barrier\n"));
1438 return (RSMERR_BARRIER_UNINITIALIZED);
1441 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1442 " __rsm_import_verify_access: exit\n"));
1444 return (RSM_SUCCESS);
1447 static int
1448 __rsm_import_implicit_map(rsmseg_handle_t *seg, int iotype)
1450 caddr_t va;
1451 int flag = MAP_SHARED;
1452 int prot = PROT_READ|PROT_WRITE;
1453 int mapping_reqd = 0;
1455 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1456 " __rsm_import_implicit_map: enter\n"));
1458 if (iotype == RSM_IOTYPE_PUTGET)
1459 mapping_reqd = seg->rsmseg_controller->cntr_lib_attr->
1460 rsm_putget_map_reqd;
1461 else if (iotype == RSM_IOTYPE_SCATGATH)
1462 mapping_reqd = seg->rsmseg_controller->cntr_lib_attr->
1463 rsm_scatgath_map_reqd;
1466 if (mapping_reqd) {
1467 va = mmap(NULL, seg->rsmseg_size, prot,
1468 flag, seg->rsmseg_fd, 0);
1470 if (va == MAP_FAILED) {
1471 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1472 "implicit map failed\n"));
1473 if (errno == ENOMEM || errno == ENXIO ||
1474 errno == EOVERFLOW)
1475 return (RSMERR_BAD_LENGTH);
1476 else if (errno == ENODEV)
1477 return (RSMERR_CONN_ABORTED);
1478 else if (errno == EAGAIN)
1479 return (RSMERR_INSUFFICIENT_RESOURCES);
1480 else if (errno == ENOTSUP)
1481 return (RSMERR_MAP_FAILED);
1482 else if (errno == EACCES)
1483 return (RSMERR_BAD_PERMS);
1484 else
1485 return (RSMERR_MAP_FAILED);
1487 seg->rsmseg_vaddr = va;
1488 seg->rsmseg_maplen = seg->rsmseg_size;
1489 seg->rsmseg_mapoffset = 0;
1490 seg->rsmseg_state = IMPORT_MAP;
1491 seg->rsmseg_flags |= RSM_IMPLICIT_MAP;
1494 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1495 " __rsm_import_implicit_map: exit\n"));
1497 return (RSM_SUCCESS);
1501 rsm_memseg_import_get8(rsm_memseg_import_handle_t im_memseg,
1502 off_t offset,
1503 uint8_t *datap,
1504 ulong_t rep_cnt)
1506 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1507 int e;
1509 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1510 "rsm_memseg_import_get8: enter\n"));
1512 e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt,
1513 RSM_PERM_READ,
1514 RSM_DAS8);
1515 if (e == RSM_SUCCESS) {
1516 rsm_segops_t *ops = seg->rsmseg_ops;
1517 rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1519 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1520 /* generation number snapshot */
1521 bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1524 e = ops->rsm_memseg_import_get8(im_memseg, offset, datap,
1525 rep_cnt, 0);
1527 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1528 /* check the generation number for force disconnects */
1529 if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1530 return (RSMERR_CONN_ABORTED);
1535 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1536 "rsm_memseg_import_get8: exit\n"));
1538 return (e);
1542 rsm_memseg_import_get16(rsm_memseg_import_handle_t im_memseg,
1543 off_t offset,
1544 uint16_t *datap,
1545 ulong_t rep_cnt)
1547 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1548 int e;
1550 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1551 "rsm_memseg_import_get16: enter\n"));
1553 e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt*2,
1554 RSM_PERM_READ,
1555 RSM_DAS16);
1556 if (e == RSM_SUCCESS) {
1557 rsm_segops_t *ops = seg->rsmseg_ops;
1558 rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1560 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1561 /* generation number snapshot */
1562 bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1565 e = ops->rsm_memseg_import_get16(im_memseg, offset, datap,
1566 rep_cnt, 0);
1568 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1569 /* check the generation number for force disconnects */
1570 if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1571 return (RSMERR_CONN_ABORTED);
1577 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1578 "rsm_memseg_import_get16: exit\n"));
1580 return (e);
1584 rsm_memseg_import_get32(rsm_memseg_import_handle_t im_memseg,
1585 off_t offset,
1586 uint32_t *datap,
1587 ulong_t rep_cnt)
1589 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1590 int e;
1592 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1593 "rsm_memseg_import_get32: enter\n"));
1595 e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt*4,
1596 RSM_PERM_READ,
1597 RSM_DAS32);
1598 if (e == RSM_SUCCESS) {
1599 rsm_segops_t *ops = seg->rsmseg_ops;
1600 rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1602 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1603 /* generation number snapshot */
1604 bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1607 e = ops->rsm_memseg_import_get32(im_memseg, offset, datap,
1608 rep_cnt, 0);
1610 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1611 /* check the generation number for force disconnects */
1612 if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1613 return (RSMERR_CONN_ABORTED);
1618 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1619 "rsm_memseg_import_get32: exit\n"));
1621 return (e);
1625 rsm_memseg_import_get64(rsm_memseg_import_handle_t im_memseg,
1626 off_t offset,
1627 uint64_t *datap,
1628 ulong_t rep_cnt)
1630 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1631 int e;
1633 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1634 "rsm_memseg_import_get64: enter\n"));
1636 e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt*8,
1637 RSM_PERM_READ,
1638 RSM_DAS64);
1639 if (e == RSM_SUCCESS) {
1640 rsm_segops_t *ops = seg->rsmseg_ops;
1641 rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1643 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1644 /* generation number snapshot */
1645 bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1648 e = ops->rsm_memseg_import_get64(im_memseg, offset, datap,
1649 rep_cnt, 0);
1651 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1652 /* check the generation number for force disconnects */
1653 if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1654 return (RSMERR_CONN_ABORTED);
1659 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1660 "rsm_memseg_import_get64: exit\n"));
1662 return (e);
1666 rsm_memseg_import_get(rsm_memseg_import_handle_t im_memseg,
1667 off_t offset,
1668 void *dst_addr,
1669 size_t length)
1671 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1672 int e;
1674 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1675 "rsm_memseg_import_get: enter\n"));
1677 e = __rsm_import_verify_access(seg, offset, (caddr_t)dst_addr, length,
1678 RSM_PERM_READ,
1679 RSM_DAS8);
1680 if (e == RSM_SUCCESS) {
1681 rsm_segops_t *ops = seg->rsmseg_ops;
1682 rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1684 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1685 /* generation number snapshot */
1686 bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1689 e = ops->rsm_memseg_import_get(im_memseg, offset, dst_addr,
1690 length);
1692 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1693 /* check the generation number for force disconnects */
1694 if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1695 return (RSMERR_CONN_ABORTED);
1700 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1701 "rsm_memseg_import_get: exit\n"));
1703 return (e);
1708 rsm_memseg_import_getv(rsm_scat_gath_t *sg_io)
1710 rsm_controller_t *cntrl;
1711 rsmseg_handle_t *seg;
1712 uint_t save_sg_io_flags;
1714 int e;
1716 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1717 "rsm_memseg_import_getv: enter\n"));
1719 if (sg_io == NULL) {
1720 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1721 "invalid sg_io structure\n"));
1722 return (RSMERR_BAD_SGIO);
1725 seg = (rsmseg_handle_t *)sg_io->remote_handle;
1726 if (seg == NULL) {
1727 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1728 "invalid remote segment handle in sg_io\n"));
1729 return (RSMERR_BAD_SEG_HNDL);
1732 cntrl = (rsm_controller_t *)seg->rsmseg_controller;
1733 if (cntrl == NULL) {
1734 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1735 "invalid controller handle\n"));
1736 return (RSMERR_BAD_SEG_HNDL);
1739 if ((sg_io->io_request_count > RSM_MAX_SGIOREQS) ||
1740 (sg_io->io_request_count == 0)) {
1741 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1742 "io_request_count value incorrect\n"));
1743 return (RSMERR_BAD_SGIO);
1746 if (seg->rsmseg_state == IMPORT_CONNECT) {
1747 e = __rsm_import_implicit_map(seg, RSM_IOTYPE_SCATGATH);
1748 if (e != RSM_SUCCESS) {
1749 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1750 "implicit map failure\n"));
1751 return (e);
1756 * Copy the flags field of the sg_io structure in a local
1757 * variable.
1758 * This is required since the flags field can be
1759 * changed by the plugin library routine to indicate that
1760 * the signal post was done.
1761 * This change in the flags field of the sg_io structure
1762 * should not be reflected to the user. Hence once the flags
1763 * field has been used for the purpose of determining whether
1764 * the plugin executed a signal post, it must be restored to
1765 * its original value which is stored in the local variable.
1767 save_sg_io_flags = sg_io->flags;
1769 e = cntrl->cntr_segops->rsm_memseg_import_getv(sg_io);
1772 * At this point, if an implicit signal post was requested by
1773 * the user, there could be two possibilities that arise:
1774 * 1. the plugin routine has already executed the implicit
1775 * signal post either successfully or unsuccessfully
1776 * 2. the plugin does not have the capability of doing an
1777 * implicit signal post and hence the signal post needs
1778 * to be done here.
1779 * The above two cases can be idenfied by the flags
1780 * field within the sg_io structure as follows:
1781 * In case 1, the RSM_IMPLICIT_SIGPOST bit is reset to 0 by the
1782 * plugin, indicating that the signal post was done.
1783 * In case 2, the bit remains set to a 1 as originally given
1784 * by the user, and hence a signal post needs to be done here.
1786 if (sg_io->flags & RSM_IMPLICIT_SIGPOST &&
1787 e == RSM_SUCCESS) {
1788 /* Do the implicit signal post */
1791 * The value of the second argument to this call
1792 * depends on the value of the sg_io->flags field.
1793 * If the RSM_SIGPOST_NO_ACCUMULATE flag has been
1794 * ored into the sg_io->flags field, this indicates
1795 * that the rsm_intr_signal_post is to be done with
1796 * the flags argument set to RSM_SIGPOST_NO_ACCUMULATE
1797 * Else, the flags argument is set to 0. These
1798 * semantics can be achieved simply by masking off
1799 * all other bits in the sg_io->flags field except the
1800 * RSM_SIGPOST_NO_ACCUMULATE bit and using the result
1801 * as the flags argument for the rsm_intr_signal_post.
1804 int sigpost_flags = sg_io->flags & RSM_SIGPOST_NO_ACCUMULATE;
1805 e = rsm_intr_signal_post(seg, sigpost_flags);
1808 /* Restore the flags field within the users scatter gather structure */
1809 sg_io->flags = save_sg_io_flags;
1811 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1812 "rsm_memseg_import_getv: exit\n"));
1814 return (e);
1819 * import side memory segment operations (write access functions):
1823 rsm_memseg_import_put8(rsm_memseg_import_handle_t im_memseg,
1824 off_t offset,
1825 uint8_t *datap,
1826 ulong_t rep_cnt)
1828 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1829 int e;
1831 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1832 "rsm_memseg_import_put8: enter\n"));
1834 /* addr of data will always pass the alignment check, avoids */
1835 /* need for a special case in verify_access for PUTs */
1836 e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt,
1837 RSM_PERM_WRITE,
1838 RSM_DAS8);
1839 if (e == RSM_SUCCESS) {
1840 rsm_segops_t *ops = seg->rsmseg_ops;
1841 rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1843 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1844 /* generation number snapshot */
1845 bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1848 e = ops->rsm_memseg_import_put8(im_memseg, offset, datap,
1849 rep_cnt, 0);
1851 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1852 /* check the generation number for force disconnects */
1853 if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1854 return (RSMERR_CONN_ABORTED);
1859 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1860 "rsm_memseg_import_put8: exit\n"));
1862 return (e);
1866 rsm_memseg_import_put16(rsm_memseg_import_handle_t im_memseg,
1867 off_t offset,
1868 uint16_t *datap,
1869 ulong_t rep_cnt)
1871 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1872 int e;
1874 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1875 "rsm_memseg_import_put16: enter\n"));
1877 /* addr of data will always pass the alignment check, avoids */
1878 /* need for a special case in verify_access for PUTs */
1879 e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt*2,
1880 RSM_PERM_WRITE,
1881 RSM_DAS16);
1882 if (e == RSM_SUCCESS) {
1883 rsm_segops_t *ops = seg->rsmseg_ops;
1884 rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1886 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1887 /* generation number snapshot */
1888 bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1891 e = ops->rsm_memseg_import_put16(im_memseg, offset, datap,
1892 rep_cnt, 0);
1894 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1895 /* check the generation number for force disconnects */
1896 if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1897 return (RSMERR_CONN_ABORTED);
1903 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1904 "rsm_memseg_import_put16: exit\n"));
1906 return (e);
1910 rsm_memseg_import_put32(rsm_memseg_import_handle_t im_memseg,
1911 off_t offset,
1912 uint32_t *datap,
1913 ulong_t rep_cnt)
1915 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1916 int e;
1918 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1919 "rsm_memseg_import_put32: enter\n"));
1921 /* addr of data will always pass the alignment check, avoids */
1922 /* need for a special case in verify_access for PUTs */
1923 e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt*4,
1924 RSM_PERM_WRITE,
1925 RSM_DAS32);
1926 if (e == RSM_SUCCESS) {
1927 rsm_segops_t *ops = seg->rsmseg_ops;
1928 rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1930 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1931 /* generation number snapshot */
1932 bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1935 e = ops->rsm_memseg_import_put32(im_memseg, offset, datap,
1936 rep_cnt, 0);
1938 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1939 /* check the generation number for force disconnects */
1940 if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1941 return (RSMERR_CONN_ABORTED);
1946 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1947 "rsm_memseg_import_put32: exit\n"));
1949 return (e);
1953 rsm_memseg_import_put64(rsm_memseg_import_handle_t im_memseg,
1954 off_t offset,
1955 uint64_t *datap,
1956 ulong_t rep_cnt)
1958 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1959 int e;
1961 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1962 "rsm_memseg_import_put64: enter\n"));
1964 /* addr of data will always pass the alignment check, avoids */
1965 /* need for a special case in verify_access for PUTs */
1966 e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt*8,
1967 RSM_PERM_WRITE,
1968 RSM_DAS64);
1969 if (e == RSM_SUCCESS) {
1970 rsm_segops_t *ops = seg->rsmseg_ops;
1971 rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1973 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1974 /* generation number snapshot */
1975 bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1978 e = ops->rsm_memseg_import_put64(im_memseg, offset, datap,
1979 rep_cnt, 0);
1981 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1982 /* check the generation number for force disconnects */
1983 if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1984 return (RSMERR_CONN_ABORTED);
1989 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1990 "rsm_memseg_import_put64: exit\n"));
1992 return (e);
1996 rsm_memseg_import_put(rsm_memseg_import_handle_t im_memseg,
1997 off_t offset,
1998 void *src_addr,
1999 size_t length)
2001 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
2002 int e;
2004 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2005 "rsm_memseg_import_put: enter\n"));
2007 e = __rsm_import_verify_access(seg, offset, (caddr_t)src_addr, length,
2008 RSM_PERM_WRITE,
2009 RSM_DAS8);
2010 if (e == RSM_SUCCESS) {
2011 rsm_segops_t *ops = seg->rsmseg_ops;
2012 rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
2014 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
2015 /* generation number snapshot */
2016 bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
2019 e = ops->rsm_memseg_import_put(im_memseg, offset, src_addr,
2020 length);
2022 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
2023 /* check the generation number for force disconnects */
2024 if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
2025 return (RSMERR_CONN_ABORTED);
2031 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2032 "rsm_memseg_import_put: exit\n"));
2033 return (e);
2038 rsm_memseg_import_putv(rsm_scat_gath_t *sg_io)
2040 rsm_controller_t *cntrl;
2041 rsmseg_handle_t *seg;
2042 uint_t save_sg_io_flags;
2044 int e;
2046 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2047 "rsm_memseg_import_putv: enter\n"));
2050 if (sg_io == NULL) {
2051 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2052 "invalid sg_io structure\n"));
2053 return (RSMERR_BAD_SGIO);
2056 seg = (rsmseg_handle_t *)sg_io->remote_handle;
2057 if (seg == NULL) {
2058 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2059 "invalid remote segment handle in sg_io\n"));
2060 return (RSMERR_BAD_SEG_HNDL);
2063 cntrl = (rsm_controller_t *)seg->rsmseg_controller;
2064 if (cntrl == NULL) {
2065 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2066 "invalid controller handle\n"));
2067 return (RSMERR_BAD_SEG_HNDL);
2070 if ((sg_io->io_request_count > RSM_MAX_SGIOREQS) ||
2071 (sg_io->io_request_count == 0)) {
2072 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2073 "io_request_count value incorrect\n"));
2074 return (RSMERR_BAD_SGIO);
2077 /* do an implicit map if required */
2078 if (seg->rsmseg_state == IMPORT_CONNECT) {
2079 e = __rsm_import_implicit_map(seg, RSM_IOTYPE_SCATGATH);
2080 if (e != RSM_SUCCESS) {
2081 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2082 "implicit map failed\n"));
2083 return (e);
2088 * Copy the flags field of the sg_io structure in a local
2089 * variable.
2090 * This is required since the flags field can be
2091 * changed by the plugin library routine to indicate that
2092 * the signal post was done.
2093 * This change in the flags field of the sg_io structure
2094 * should not be reflected to the user. Hence once the flags
2095 * field has been used for the purpose of determining whether
2096 * the plugin executed a signal post, it must be restored to
2097 * its original value which is stored in the local variable.
2099 save_sg_io_flags = sg_io->flags;
2101 e = cntrl->cntr_segops->rsm_memseg_import_putv(sg_io);
2104 * At this point, if an implicit signal post was requested by
2105 * the user, there could be two possibilities that arise:
2106 * 1. the plugin routine has already executed the implicit
2107 * signal post either successfully or unsuccessfully
2108 * 2. the plugin does not have the capability of doing an
2109 * implicit signal post and hence the signal post needs
2110 * to be done here.
2111 * The above two cases can be idenfied by the flags
2112 * field within the sg_io structure as follows:
2113 * In case 1, the RSM_IMPLICIT_SIGPOST bit is reset to 0 by the
2114 * plugin, indicating that the signal post was done.
2115 * In case 2, the bit remains set to a 1 as originally given
2116 * by the user, and hence a signal post needs to be done here.
2118 if (sg_io->flags & RSM_IMPLICIT_SIGPOST &&
2119 e == RSM_SUCCESS) {
2120 /* Do the implicit signal post */
2123 * The value of the second argument to this call
2124 * depends on the value of the sg_io->flags field.
2125 * If the RSM_SIGPOST_NO_ACCUMULATE flag has been
2126 * ored into the sg_io->flags field, this indicates
2127 * that the rsm_intr_signal_post is to be done with
2128 * the flags argument set to RSM_SIGPOST_NO_ACCUMULATE
2129 * Else, the flags argument is set to 0. These
2130 * semantics can be achieved simply by masking off
2131 * all other bits in the sg_io->flags field except the
2132 * RSM_SIGPOST_NO_ACCUMULATE bit and using the result
2133 * as the flags argument for the rsm_intr_signal_post.
2136 int sigpost_flags = sg_io->flags & RSM_SIGPOST_NO_ACCUMULATE;
2137 e = rsm_intr_signal_post(seg, sigpost_flags);
2141 /* Restore the flags field within the users scatter gather structure */
2142 sg_io->flags = save_sg_io_flags;
2144 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2145 "rsm_memseg_import_putv: exit\n"));
2147 return (e);
2152 * import side memory segment operations (mapping):
2155 rsm_memseg_import_map(rsm_memseg_import_handle_t im_memseg,
2156 void **address,
2157 rsm_attribute_t attr,
2158 rsm_permission_t perm,
2159 off_t offset,
2160 size_t length)
2162 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
2163 int flag = MAP_SHARED;
2164 int prot;
2165 caddr_t va;
2167 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2168 "rsm_memseg_import_map: enter\n"));
2170 if (!seg) {
2171 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2172 "invalid segment\n"));
2173 return (RSMERR_BAD_SEG_HNDL);
2175 if (!address) {
2176 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2177 "invalid address\n"));
2178 return (RSMERR_BAD_ADDR);
2182 * Only one map per segment handle!
2183 * XXX need to take a lock here
2185 mutex_lock(&seg->rsmseg_lock);
2187 if (seg->rsmseg_state == IMPORT_MAP) {
2188 mutex_unlock(&seg->rsmseg_lock);
2189 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2190 "segment already mapped\n"));
2191 return (RSMERR_SEG_ALREADY_MAPPED);
2194 /* Only import segments allowed to map */
2195 if (seg->rsmseg_state != IMPORT_CONNECT) {
2196 mutex_unlock(&seg->rsmseg_lock);
2197 return (RSMERR_BAD_SEG_HNDL);
2200 /* check for permissions */
2201 if (perm > RSM_PERM_RDWR) {
2202 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2203 "bad permissions when mapping\n"));
2204 mutex_unlock(&seg->rsmseg_lock);
2205 return (RSMERR_BAD_PERMS);
2208 if (length == 0) {
2209 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2210 "mapping with length 0\n"));
2211 mutex_unlock(&seg->rsmseg_lock);
2212 return (RSMERR_BAD_LENGTH);
2215 if (offset + length > seg->rsmseg_size) {
2216 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2217 "map length + offset exceed segment size\n"));
2218 mutex_unlock(&seg->rsmseg_lock);
2219 return (RSMERR_BAD_LENGTH);
2222 if ((size_t)offset & (PAGESIZE - 1)) {
2223 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2224 "bad mem alignment\n"));
2225 return (RSMERR_BAD_MEM_ALIGNMENT);
2228 if (attr & RSM_MAP_FIXED) {
2229 if ((uintptr_t)(*address) & (PAGESIZE - 1)) {
2230 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2231 "bad mem alignment\n"));
2232 return (RSMERR_BAD_MEM_ALIGNMENT);
2234 flag |= MAP_FIXED;
2237 prot = PROT_NONE;
2238 if (perm & RSM_PERM_READ)
2239 prot |= PROT_READ;
2240 if (perm & RSM_PERM_WRITE)
2241 prot |= PROT_WRITE;
2243 va = mmap(*address, length, prot, flag, seg->rsmseg_fd, offset);
2244 if (va == MAP_FAILED) {
2245 int e = errno;
2246 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2247 "error %d during map\n", e));
2249 mutex_unlock(&seg->rsmseg_lock);
2250 if (e == ENXIO || e == EOVERFLOW ||
2251 e == ENOMEM)
2252 return (RSMERR_BAD_LENGTH);
2253 else if (e == ENODEV)
2254 return (RSMERR_CONN_ABORTED);
2255 else if (e == EAGAIN)
2256 return (RSMERR_INSUFFICIENT_RESOURCES);
2257 else if (e == ENOTSUP)
2258 return (RSMERR_MAP_FAILED);
2259 else if (e == EACCES)
2260 return (RSMERR_BAD_PERMS);
2261 else
2262 return (RSMERR_MAP_FAILED);
2264 *address = va;
2267 * Fix segment ops vector to handle direct access.
2270 * XXX: Set this only for full segment mapping. Keep a list
2271 * of mappings to use for access functions
2273 seg->rsmseg_vaddr = va;
2274 seg->rsmseg_maplen = length;
2275 seg->rsmseg_mapoffset = offset;
2276 seg->rsmseg_state = IMPORT_MAP;
2278 mutex_unlock(&seg->rsmseg_lock);
2280 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2281 "rsm_memseg_import_map: exit\n"));
2283 return (RSM_SUCCESS);
2287 rsm_memseg_import_unmap(rsm_memseg_import_handle_t im_memseg)
2290 * Until we fix the rsm driver to catch unload, we unload
2291 * the whole segment.
2294 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
2296 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2297 "rsm_memseg_import_unmap: enter\n"));
2299 if (!seg) {
2300 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2301 "invalid segment or segment state\n"));
2302 return (RSMERR_BAD_SEG_HNDL);
2305 mutex_lock(&seg->rsmseg_lock);
2306 if (seg->rsmseg_state != IMPORT_MAP) {
2307 mutex_unlock(&seg->rsmseg_lock);
2308 return (RSMERR_SEG_NOT_MAPPED);
2311 seg->rsmseg_mapoffset = 0; /* reset the offset */
2312 seg->rsmseg_state = IMPORT_CONNECT;
2313 seg->rsmseg_flags &= ~RSM_IMPLICIT_MAP;
2314 (void) munmap(seg->rsmseg_vaddr, seg->rsmseg_maplen);
2316 mutex_unlock(&seg->rsmseg_lock);
2318 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2319 "rsm_memseg_import_unmap: exit\n"));
2321 return (RSM_SUCCESS);
2326 * import side memory segment operations (barriers):
2329 rsm_memseg_import_init_barrier(rsm_memseg_import_handle_t im_memseg,
2330 rsm_barrier_type_t type,
2331 rsmapi_barrier_t *barrier)
2333 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
2334 rsmbar_handle_t *bar;
2336 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2337 "rsm_memseg_import_init_barrier: enter\n"));
2339 if (!seg) {
2340 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2341 "invalid segment or barrier\n"));
2342 return (RSMERR_BAD_SEG_HNDL);
2344 if (!barrier) {
2345 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2346 "invalid barrier pointer\n"));
2347 return (RSMERR_BAD_BARRIER_PTR);
2350 bar = (rsmbar_handle_t *)barrier;
2351 bar->rsmbar_seg = seg;
2353 seg->rsmseg_barrier = barrier; /* used in put/get fns */
2355 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2356 "rsm_memseg_import_init_barrier: exit\n"));
2358 return (seg->rsmseg_ops->rsm_memseg_import_init_barrier(im_memseg,
2359 type, (rsm_barrier_handle_t)barrier));
2363 rsm_memseg_import_open_barrier(rsmapi_barrier_t *barrier)
2365 rsmbar_handle_t *bar = (rsmbar_handle_t *)barrier;
2366 rsm_segops_t *ops;
2368 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2369 "rsm_memseg_import_open_barrier: enter\n"));
2371 if (!bar) {
2372 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2373 "invalid barrier\n"));
2374 return (RSMERR_BAD_BARRIER_PTR);
2376 if (!bar->rsmbar_seg) {
2377 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2378 "uninitialized barrier\n"));
2379 return (RSMERR_BARRIER_UNINITIALIZED);
2382 /* generation number snapshot */
2383 bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum; /* bar[0] */
2385 ops = bar->rsmbar_seg->rsmseg_ops;
2387 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2388 "rsm_memseg_import_open_barrier: exit\n"));
2390 return (ops->rsm_memseg_import_open_barrier(
2391 (rsm_barrier_handle_t)barrier));
2395 rsm_memseg_import_order_barrier(rsmapi_barrier_t *barrier)
2397 rsmbar_handle_t *bar = (rsmbar_handle_t *)barrier;
2398 rsm_segops_t *ops;
2400 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2401 "rsm_memseg_import_order_barrier: enter\n"));
2403 if (!bar) {
2404 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2405 "invalid barrier\n"));
2406 return (RSMERR_BAD_BARRIER_PTR);
2408 if (!bar->rsmbar_seg) {
2409 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2410 "uninitialized barrier\n"));
2411 return (RSMERR_BARRIER_UNINITIALIZED);
2414 ops = bar->rsmbar_seg->rsmseg_ops;
2416 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2417 "rsm_memseg_import_order_barrier: exit\n"));
2419 return (ops->rsm_memseg_import_order_barrier(
2420 (rsm_barrier_handle_t)barrier));
2424 rsm_memseg_import_close_barrier(rsmapi_barrier_t *barrier)
2426 rsmbar_handle_t *bar = (rsmbar_handle_t *)barrier;
2427 rsm_segops_t *ops;
2429 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2430 "rsm_memseg_import_close_barrier: enter\n"));
2432 if (!bar) {
2433 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2434 "invalid barrier\n"));
2435 return (RSMERR_BAD_BARRIER_PTR);
2437 if (!bar->rsmbar_seg) {
2438 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2439 "uninitialized barrier\n"));
2440 return (RSMERR_BARRIER_UNINITIALIZED);
2443 /* generation number snapshot */
2444 if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
2445 return (RSMERR_CONN_ABORTED);
2448 ops = bar->rsmbar_seg->rsmseg_ops;
2450 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2451 "rsm_memseg_import_close_barrier: exit\n"));
2453 return (ops->rsm_memseg_import_close_barrier(
2454 (rsm_barrier_handle_t)barrier));
2458 rsm_memseg_import_destroy_barrier(rsmapi_barrier_t *barrier)
2460 rsmbar_handle_t *bar = (rsmbar_handle_t *)barrier;
2461 rsm_segops_t *ops;
2463 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2464 "rsm_memseg_import_destroy_barrier: enter\n"));
2466 if (!bar) {
2467 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2468 "invalid barrier\n"));
2469 return (RSMERR_BAD_BARRIER_PTR);
2471 if (!bar->rsmbar_seg) {
2472 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2473 "uninitialized barrier\n"));
2474 return (RSMERR_BARRIER_UNINITIALIZED);
2477 bar->rsmbar_seg->rsmseg_barrier = NULL;
2479 ops = bar->rsmbar_seg->rsmseg_ops;
2481 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2482 "rsm_memseg_import_destroy_barrier: exit\n"));
2484 return (ops->rsm_memseg_import_destroy_barrier
2485 ((rsm_barrier_handle_t)barrier));
2489 rsm_memseg_import_get_mode(rsm_memseg_import_handle_t im_memseg,
2490 rsm_barrier_mode_t *mode)
2492 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
2494 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2495 "rsm_memseg_import_get_mode: enter\n"));
2497 if (seg) {
2498 *mode = seg->rsmseg_barmode;
2499 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2500 "rsm_memseg_import_get_mode: exit\n"));
2502 return (seg->rsmseg_ops->rsm_memseg_import_get_mode(im_memseg,
2503 mode));
2506 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2507 "invalid arguments \n"));
2509 return (RSMERR_BAD_SEG_HNDL);
2514 rsm_memseg_import_set_mode(rsm_memseg_import_handle_t im_memseg,
2515 rsm_barrier_mode_t mode)
2517 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
2519 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2520 "rsm_memseg_import_set_mode: enter\n"));
2521 if (seg) {
2522 if ((mode == RSM_BARRIER_MODE_IMPLICIT ||
2523 mode == RSM_BARRIER_MODE_EXPLICIT)) {
2524 seg->rsmseg_barmode = mode;
2525 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2526 "rsm_memseg_import_set_mode: exit\n"));
2528 return (seg->rsmseg_ops->rsm_memseg_import_set_mode(
2529 im_memseg,
2530 mode));
2531 } else {
2532 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2533 "bad barrier mode\n"));
2534 return (RSMERR_BAD_MODE);
2538 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2539 "invalid arguments\n"));
2541 return (RSMERR_BAD_SEG_HNDL);
2545 rsm_intr_signal_post(void *memseg, uint_t flags)
2547 rsm_ioctlmsg_t msg;
2548 rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
2550 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2551 "rsm_intr_signal_post: enter\n"));
2553 flags = flags;
2555 if (!seg) {
2556 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2557 "invalid segment handle\n"));
2558 return (RSMERR_BAD_SEG_HNDL);
2561 if (ioctl(seg->rsmseg_fd, RSM_IOCTL_RING_BELL, &msg) < 0) {
2562 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2563 "RSM_IOCTL_RING_BELL failed\n"));
2564 return (errno);
2567 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2568 "rsm_intr_signal_post: exit\n"));
2570 return (RSM_SUCCESS);
2574 rsm_intr_signal_wait(void *memseg, int timeout)
2576 rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
2577 struct pollfd fds;
2578 minor_t rnum;
2580 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2581 "rsm_intr_signal_wait: enter\n"));
2583 if (!seg) {
2584 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2585 "invalid segment\n"));
2586 return (RSMERR_BAD_SEG_HNDL);
2589 fds.fd = seg->rsmseg_fd;
2590 fds.events = POLLRDNORM;
2592 rnum = seg->rsmseg_rnum;
2594 return (__rsm_intr_signal_wait_common(&fds, &rnum, 1, timeout, NULL));
2598 rsm_intr_signal_wait_pollfd(struct pollfd fds[], nfds_t nfds, int timeout,
2599 int *numfdsp)
2601 return (__rsm_intr_signal_wait_common(fds, NULL, nfds, timeout,
2602 numfdsp));
2606 * This is the generic wait routine, it takes the following arguments
2607 * - pollfd array
2608 * - rnums array corresponding to the pollfd if known, if this is
2609 * NULL then the fds are looked up from the pollfd_table.
2610 * - number of fds in pollfd array,
2611 * - timeout
2612 * - pointer to a location where the number of fds with successful
2613 * events is returned.
2615 static int
2616 __rsm_intr_signal_wait_common(struct pollfd fds[], minor_t rnums[],
2617 nfds_t nfds, int timeout, int *numfdsp)
2619 int i;
2620 int numsegs = 0;
2621 int numfd;
2622 int fds_processed = 0;
2623 minor_t segrnum;
2624 rsm_poll_event_t event_arr[RSM_MAX_POLLFDS];
2625 rsm_poll_event_t *event_list = NULL;
2626 rsm_poll_event_t *events;
2627 rsm_consume_event_msg_t msg;
2629 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE, "wait_common enter\n"));
2631 if (numfdsp) {
2632 *numfdsp = 0;
2635 numfd = poll(fds, nfds, timeout);
2637 switch (numfd) {
2638 case -1: /* poll returned error - map to RSMERR_... */
2639 DBPRINTF((RSM_LIBRARY, RSM_ERR, "signal wait pollfd err\n"));
2640 switch (errno) {
2641 case EAGAIN:
2642 return (RSMERR_INSUFFICIENT_RESOURCES);
2643 case EFAULT:
2644 return (RSMERR_BAD_ADDR);
2645 case EINTR:
2646 return (RSMERR_INTERRUPTED);
2647 case EINVAL:
2648 default:
2649 return (RSMERR_BAD_ARGS_ERRORS);
2651 case 0: /* timedout - return from here */
2652 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2653 "signal wait timed out\n"));
2654 return (RSMERR_TIMEOUT);
2655 default:
2656 break;
2659 if (numfd <= RSM_MAX_POLLFDS) {
2660 /* use the event array on the stack */
2661 events = (rsm_poll_event_t *)event_arr;
2662 } else {
2664 * actual number of fds corresponding to rsmapi segments might
2665 * be < numfd, don't want to scan the list to figure that out
2666 * lets just allocate on the heap
2668 event_list = (rsm_poll_event_t *)malloc(
2669 sizeof (rsm_poll_event_t)*numfd);
2670 if (!event_list) {
2672 * return with error even if poll might have succeeded
2673 * since the application can retry and the events will
2674 * still be available.
2676 return (RSMERR_INSUFFICIENT_MEM);
2678 events = event_list;
2682 * process the fds for events and if it corresponds to an rsmapi
2683 * segment consume the event
2685 for (i = 0; i < nfds; i++) {
2686 if (fds[i].revents == POLLRDNORM) {
2688 * poll returned an event and if its POLLRDNORM, it
2689 * might correspond to an rsmapi segment
2691 if (rnums) { /* resource num is passed in */
2692 segrnum = rnums[i];
2693 } else { /* lookup pollfd table to get resource num */
2694 segrnum = _rsm_lookup_pollfd_table(fds[i].fd);
2696 if (segrnum) {
2697 events[numsegs].rnum = segrnum;
2698 events[numsegs].revent = 0;
2699 events[numsegs].fdsidx = i; /* fdlist index */
2700 numsegs++;
2704 if ((fds[i].revents) && (++fds_processed == numfd)) {
2706 * only "numfd" events have revents field set, once we
2707 * process that many break out of the loop
2709 break;
2713 if (numsegs == 0) { /* No events for rsmapi segs in the fdlist */
2714 if (event_list) {
2715 free(event_list);
2717 if (numfdsp) {
2718 *numfdsp = numfd;
2720 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2721 "wait_common exit: no rsmapi segs\n"));
2722 return (RSM_SUCCESS);
2725 msg.seglist = (caddr_t)events;
2726 msg.numents = numsegs;
2728 if (ioctl(_rsm_fd, RSM_IOCTL_CONSUMEEVENT, &msg) < 0) {
2729 int error = errno;
2730 if (event_list) {
2731 free(event_list);
2733 DBPRINTF((RSM_LIBRARY|RSM_LOOPBACK, RSM_ERR,
2734 "RSM_IOCTL_CONSUMEEVENT failed(%d)\n", error));
2735 return (error);
2738 /* count the number of segs for which consumeevent was successful */
2739 numfd -= numsegs;
2741 for (i = 0; i < numsegs; i++) {
2742 if (events[i].revent != 0) {
2743 fds[events[i].fdsidx].revents = POLLRDNORM;
2744 numfd++;
2745 } else { /* failed to consume event so set revents to 0 */
2746 fds[events[i].fdsidx].revents = 0;
2750 if (event_list) {
2751 free(event_list);
2754 if (numfd > 0) {
2755 if (numfdsp) {
2756 *numfdsp = numfd;
2758 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2759 "wait_common exit\n"));
2760 return (RSM_SUCCESS);
2761 } else {
2762 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2763 "wait_common exit\n"));
2764 return (RSMERR_TIMEOUT);
2769 * This function provides the data (file descriptor and event) for
2770 * the specified pollfd struct. The pollfd struct may then be
2771 * subsequently used with the poll system call to wait for an event
2772 * signalled by rsm_intr_signal_post. The memory segment must be
2773 * currently published for a successful return with a valid pollfd.
2774 * A reference count for the descriptor is incremented.
2777 rsm_memseg_get_pollfd(void *memseg,
2778 struct pollfd *poll_fd)
2780 int i;
2781 int err = RSM_SUCCESS;
2782 rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
2784 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2785 "rsm_memseg_get_pollfd: enter\n"));
2787 if (!seg) {
2788 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2789 "invalid segment\n"));
2790 return (RSMERR_BAD_SEG_HNDL);
2793 mutex_lock(&seg->rsmseg_lock);
2795 poll_fd->fd = seg->rsmseg_fd;
2796 poll_fd->events = POLLRDNORM;
2797 seg->rsmseg_pollfd_refcnt++;
2798 if (seg->rsmseg_pollfd_refcnt == 1) {
2799 /* insert the segment into the pollfd table */
2800 err = _rsm_insert_pollfd_table(seg->rsmseg_fd,
2801 seg->rsmseg_rnum);
2804 mutex_unlock(&seg->rsmseg_lock);
2806 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2807 "rsm_memseg_get_pollfd: exit(%d)\n", err));
2809 return (err);
2813 * This function decrements the segment pollfd reference count.
2814 * A segment unpublish or destroy operation will fail if the reference count is
2815 * non zero.
2818 rsm_memseg_release_pollfd(void * memseg)
2820 int i;
2821 rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
2823 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2824 "rsm_memseg_release_pollfd: enter\n"));
2826 if (!seg) {
2827 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2828 "invalid segment handle\n"));
2829 return (RSMERR_BAD_SEG_HNDL);
2832 mutex_lock(&seg->rsmseg_lock);
2834 if (seg->rsmseg_pollfd_refcnt) {
2835 seg->rsmseg_pollfd_refcnt--;
2836 if (seg->rsmseg_pollfd_refcnt == 0) {
2837 /* last reference removed - update the pollfd_table */
2838 _rsm_remove_pollfd_table(seg->rsmseg_fd);
2842 mutex_unlock(&seg->rsmseg_lock);
2844 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2845 "rsm_memseg_release_pollfd: exit\n"));
2847 return (RSM_SUCCESS);
2851 * The interconnect topology data is obtained from the Kernel Agent
2852 * and stored in a memory buffer allocated by this function. A pointer
2853 * to the buffer is stored in the location specified by the caller in
2854 * the function argument. It is the callers responsibility to
2855 * call rsm_free_interconnect_topolgy() to free the allocated memory.
2858 rsm_get_interconnect_topology(rsm_topology_t **topology_data)
2860 uint32_t topology_data_size;
2861 rsm_topology_t *topology_ptr;
2862 int error;
2864 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2865 "rsm_get_interconnect_topology: enter\n"));
2867 if (topology_data == NULL)
2868 return (RSMERR_BAD_TOPOLOGY_PTR);
2870 *topology_data = NULL;
2872 again:
2873 /* obtain the size of the topology data */
2874 if (ioctl(_rsm_fd, RSM_IOCTL_TOPOLOGY_SIZE, &topology_data_size) < 0) {
2875 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2876 "RSM_IOCTL_TOPOLOGY_SIZE failed\n"));
2877 return (errno);
2880 /* allocate double-word aligned memory to hold the topology data */
2881 topology_ptr = (rsm_topology_t *)memalign(8, topology_data_size);
2882 if (topology_ptr == NULL) {
2883 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2884 "not enough memory\n"));
2885 return (RSMERR_INSUFFICIENT_MEM);
2889 * Request the topology data.
2890 * Pass in the size to be used as a check in case
2891 * the data has grown since the size was obtained - if
2892 * it has, the errno value will be E2BIG.
2894 topology_ptr->topology_hdr.local_nodeid =
2895 (rsm_node_id_t)topology_data_size;
2896 if (ioctl(_rsm_fd, RSM_IOCTL_TOPOLOGY_DATA, topology_ptr) < 0) {
2897 error = errno;
2898 free((void *)topology_ptr);
2899 if (error == E2BIG)
2900 goto again;
2901 else {
2902 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2903 "RSM_IOCTL_TOPOLOGY_DATA failed\n"));
2904 return (error);
2906 } else
2907 *topology_data = topology_ptr;
2909 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2910 " rsm_get_interconnect_topology: exit\n"));
2912 return (RSM_SUCCESS);
2916 void
2917 rsm_free_interconnect_topology(rsm_topology_t *topology_ptr)
2920 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2921 "rsm_free_interconnect_topology: enter\n"));
2923 if (topology_ptr) {
2924 free((void *)topology_ptr);
2927 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2928 "rsm_free_interconnect_topology: exit\n"));
2932 rsm_create_localmemory_handle(rsmapi_controller_handle_t cntrl_handle,
2933 rsm_localmemory_handle_t *local_hndl_p,
2934 caddr_t local_vaddr, size_t len)
2936 int e;
2937 rsm_controller_t *cntrl = (rsm_controller_t *)cntrl_handle;
2939 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2940 "rsm_create_localmemory_handle: enter\n"));
2942 if ((size_t)local_vaddr & (PAGESIZE - 1)) {
2943 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2944 "invalid arguments\n"));
2945 return (RSMERR_BAD_ADDR);
2948 if (!cntrl_handle) {
2949 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2950 "invalid controller handle\n"));
2951 return (RSMERR_BAD_CTLR_HNDL);
2953 if (!local_hndl_p) {
2954 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2955 "invalid local memory handle pointer\n"));
2956 return (RSMERR_BAD_LOCALMEM_HNDL);
2958 if (len == 0) {
2959 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2960 "invalid length\n"));
2961 return (RSMERR_BAD_LENGTH);
2964 e = cntrl->cntr_segops->rsm_create_localmemory_handle(
2965 cntrl_handle,
2966 local_hndl_p,
2967 local_vaddr,
2968 len);
2970 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2971 "rsm_create_localmemory_handle: exit\n"));
2973 return (e);
2977 rsm_free_localmemory_handle(rsmapi_controller_handle_t cntrl_handle,
2978 rsm_localmemory_handle_t local_handle)
2980 int e;
2982 rsm_controller_t *cntrl = (rsm_controller_t *)cntrl_handle;
2984 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2985 "rsm_free_localmemory_handle: enter\n"));
2988 if (!cntrl_handle) {
2989 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2990 "invalid controller handle\n"));
2991 return (RSMERR_BAD_CTLR_HNDL);
2994 if (!local_handle) {
2995 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2996 "invalid localmemory handle\n"));
2997 return (RSMERR_BAD_LOCALMEM_HNDL);
3000 e = cntrl->cntr_segops->rsm_free_localmemory_handle(local_handle);
3002 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
3003 "rsm_free_localmemory_handle: exit\n"));
3005 return (e);
3009 rsm_get_segmentid_range(const char *appid, rsm_memseg_id_t *baseid,
3010 uint32_t *length)
3012 char buf[RSMFILE_BUFSIZE];
3013 char *s;
3014 char *fieldv[4];
3015 int fieldc = 0;
3016 int found = 0;
3017 int err = RSMERR_BAD_APPID;
3018 FILE *fp;
3020 if (appid == NULL || baseid == NULL || length == NULL)
3021 return (RSMERR_BAD_ADDR);
3023 if ((fp = fopen(RSMSEGIDFILE, "rF")) == NULL) {
3024 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
3025 "cannot open <%s>\n", RSMSEGIDFILE));
3026 return (RSMERR_BAD_CONF);
3029 while (s = fgets(buf, RSMFILE_BUFSIZE, fp)) {
3030 fieldc = 0;
3031 while (isspace(*s)) /* skip the leading spaces */
3032 s++;
3034 if (*s == '#') { /* comment line - skip it */
3035 continue;
3039 * parse the reserved segid file and
3040 * set the pointers appropriately.
3041 * fieldv[0] : keyword
3042 * fieldv[1] : application identifier
3043 * fieldv[2] : baseid
3044 * fieldv[3] : length
3046 while ((*s != '\n') && (*s != '\0') && (fieldc < 4)) {
3048 while (isspace(*s)) /* skip the leading spaces */
3049 s++;
3051 fieldv[fieldc++] = s;
3053 if (fieldc == 4) {
3054 if (fieldv[3][strlen(fieldv[3])-1] == '\n')
3055 fieldv[3][strlen(fieldv[3])-1] = '\0';
3056 break;
3059 while (*s && !isspace(*s))
3060 ++s; /* move to the next white space */
3062 if (*s)
3063 *s++ = '\0';
3066 if (fieldc < 4) { /* some fields are missing */
3067 err = RSMERR_BAD_CONF;
3068 break;
3071 if (strcasecmp(fieldv[1], appid) == 0) { /* found a match */
3072 if (strcasecmp(fieldv[0], RSMSEG_RESERVED) == 0) {
3073 errno = 0;
3074 *baseid = strtol(fieldv[2], (char **)NULL, 16);
3075 if (errno != 0) {
3076 err = RSMERR_BAD_CONF;
3077 break;
3080 errno = 0;
3081 *length = (int)strtol(fieldv[3],
3082 (char **)NULL, 10);
3083 if (errno != 0) {
3084 err = RSMERR_BAD_CONF;
3085 break;
3088 found = 1;
3089 } else { /* error in format */
3090 err = RSMERR_BAD_CONF;
3092 break;
3096 (void) fclose(fp);
3098 if (found)
3099 return (RSM_SUCCESS);
3101 return (err);
3104 static int
3105 _rsm_get_hwaddr(rsmapi_controller_handle_t handle, rsm_node_id_t nodeid,
3106 rsm_addr_t *hwaddrp)
3108 rsm_ioctlmsg_t msg = {0};
3109 rsm_controller_t *ctrlp;
3111 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
3112 "_rsm_get_hwaddr: enter\n"));
3114 ctrlp = (rsm_controller_t *)handle;
3116 if (ctrlp == NULL) {
3117 DBPRINTF((RSM_LIBRARY, RSM_ERR,
3118 "invalid controller handle\n"));
3119 return (RSMERR_BAD_CTLR_HNDL);
3122 msg.cname = ctrlp->cntr_name;
3123 msg.cname_len = strlen(ctrlp->cntr_name) +1;
3124 msg.cnum = ctrlp->cntr_unit;
3125 msg.nodeid = nodeid;
3127 if (ioctl(_rsm_fd, RSM_IOCTL_MAP_TO_ADDR, &msg) < 0) {
3128 int error = errno;
3129 DBPRINTF((RSM_LIBRARY, RSM_ERR,
3130 "RSM_IOCTL_MAP_TO_ADDR failed\n"));
3131 return (error);
3134 *hwaddrp = msg.hwaddr;
3136 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
3137 "_rsm_get_hwaddr: exit\n"));
3139 return (RSM_SUCCESS);
3143 static int
3144 _rsm_get_nodeid(rsmapi_controller_handle_t handle, rsm_addr_t hwaddr,
3145 rsm_node_id_t *nodeidp)
3148 rsm_ioctlmsg_t msg = {0};
3149 rsm_controller_t *ctrlp;
3151 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
3152 "_rsm_get_nodeid: enter\n"));
3154 ctrlp = (rsm_controller_t *)handle;
3156 if (ctrlp == NULL) {
3157 DBPRINTF((RSM_LIBRARY, RSM_ERR,
3158 "invalid arguments\n"));
3159 return (RSMERR_BAD_CTLR_HNDL);
3162 msg.cname = ctrlp->cntr_name;
3163 msg.cname_len = strlen(ctrlp->cntr_name) +1;
3164 msg.cnum = ctrlp->cntr_unit;
3165 msg.hwaddr = hwaddr;
3167 if (ioctl(_rsm_fd, RSM_IOCTL_MAP_TO_NODEID, &msg) < 0) {
3168 int error = errno;
3169 DBPRINTF((RSM_LIBRARY, RSM_ERR,
3170 "RSM_IOCTL_MAP_TO_NODEID failed\n"));
3171 return (error);
3174 *nodeidp = msg.nodeid;
3176 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
3177 "_rsm_get_nodeid: exit\n"));
3179 return (RSM_SUCCESS);
3183 #ifdef DEBUG
3184 void
3185 dbg_printf(int msg_category, int msg_level, char *fmt, ...)
3187 if ((msg_category & rsmlibdbg_category) &&
3188 (msg_level <= rsmlibdbg_level)) {
3189 va_list arg_list;
3190 va_start(arg_list, fmt);
3191 mutex_lock(&rsmlog_lock);
3192 fprintf(rsmlog_fd, "Thread %d ", thr_self());
3193 vfprintf(rsmlog_fd, fmt, arg_list);
3194 fflush(rsmlog_fd);
3195 mutex_unlock(&rsmlog_lock);
3196 va_end(arg_list);
3199 #endif /* DEBUG */