diff options
| author | narayan <none@none> | 2006-08-10 13:51:43 -0700 |
|---|---|---|
| committer | narayan <none@none> | 2006-08-10 13:51:43 -0700 |
| commit | 4bac220845f606f60663ed6f3a2b88caa00ae87e (patch) | |
| tree | 707f122f61a6374fbb29960b711a9194010fe2de /usr/src/lib/libpcp | |
| parent | 3fdb082f5a6c22888eef8882371ffcdeec889024 (diff) | |
| download | illumos-joyent-4bac220845f606f60663ed6f3a2b88caa00ae87e.tar.gz | |
6419154 libpcp pcp_init routine should accept service names
6428416 CPUs greater than NCPU are stopped too early in boot
6436930 qcn drv needs to handle EWOULDBLOCK returned by hv_cnputchar
6437727 vDisk should support EFI labels
6437738 vDisk should support devid
6441930 fillsysinfo should cap max sun4v queue size to kernel limits
6441933 The broken MD detection code should be improved
6445825 domaining_enabled variable does not tell the whole story
6449959 vDisk DKIOCSETWCE/DKIOCGETWCE ioctls are not correctly implemented
6451118 Elevate libpcp from a platform lib to a sun4v lib
6451490 ldc_chkq incorrectly returns queue empty when data is available on streaming mode channel
6456875 VIO drivers should use LDC shared memory for better performance
6456880 LDC link layer fails to clear interrupt state properly
6456928 drd service is not enabled if installed through an upgrade
6457162 vswitch needs to cope with dropped pkts when talking to obp
6457166 vswitch calculating bounded range of descriptors incorrectly
Diffstat (limited to 'usr/src/lib/libpcp')
| -rw-r--r-- | usr/src/lib/libpcp/Makefile.com | 2 | ||||
| -rw-r--r-- | usr/src/lib/libpcp/common/libpcp.c | 46 | ||||
| -rw-r--r-- | usr/src/lib/libpcp/common/pcp_utils.c | 358 | ||||
| -rw-r--r-- | usr/src/lib/libpcp/common/pcp_utils.h | 61 | ||||
| -rw-r--r-- | usr/src/lib/libpcp/sparc/Makefile | 7 |
5 files changed, 452 insertions, 22 deletions
diff --git a/usr/src/lib/libpcp/Makefile.com b/usr/src/lib/libpcp/Makefile.com index 654f77cb8a..f7f8d25ed4 100644 --- a/usr/src/lib/libpcp/Makefile.com +++ b/usr/src/lib/libpcp/Makefile.com @@ -49,7 +49,7 @@ LINKED_LLIBLPCP_DIR = \ LIBS = $(DYNLIB) $(LINTLIB) CFLAGS += $(CCVERBOSE) -LDLIBS += -lc -lumem +LDLIBS += -lc -lumem -ldevinfo PLATLIBS = $(USR_PLAT_DIR)/$(PLATFORM)/lib INS.slink6= $(RM) -r $@; $(SYMLINK) ../../$(PLATFORM)/lib/libpcp.so.1 $@ $(CHOWNLINK) $(CHGRPLINK) INS.slink7= $(RM) -r $@; $(SYMLINK) ../../$(PLATFORM)/lib/libpcp.so $@ $(CHOWNLINK) $(CHGRPLINK) diff --git a/usr/src/lib/libpcp/common/libpcp.c b/usr/src/lib/libpcp/common/libpcp.c index 6c9eb09263..7888f7588f 100644 --- a/usr/src/lib/libpcp/common/libpcp.c +++ b/usr/src/lib/libpcp/common/libpcp.c @@ -53,6 +53,8 @@ #include "libpcp.h" #include "pcp_common.h" +#include "pcp_utils.h" + /* * Following libpcp interfaces are exposed to user applications. @@ -165,14 +167,7 @@ static struct sigaction old_act; /* * Variables to support vldc based streaming transport */ -typedef enum { - GLVC_NON_STREAM, - VLDC_STREAMING -} xport_t; - -static int xport_type = GLVC_NON_STREAM; -#define CHANNEL_DEV "channel-devices" - +static pcp_xport_t xport_type = GLVC_NON_STREAM; #define VLDC_MTU_SIZE (2048) static void @@ -194,25 +189,38 @@ pcp_init(char *channel_name) { sigset_t oldset; int channel_fd; + char *dev_path; + vldc_opt_op_t op; if (channel_name == NULL) return (PCPL_INVALID_ARGS); /* + * Given the argument, try to locate a device in the device tree + */ + dev_path = platsvc_name_to_path(channel_name, &xport_type); + + /* + * Path exists ? + */ + if (NULL == dev_path) + return (PCPL_INVALID_ARGS); + + /* * Open virtual channel name. */ - if ((channel_fd = open(channel_name, O_RDWR|O_EXCL)) < 0) { + if ((channel_fd = open(dev_path, O_RDWR|O_EXCL)) < 0) { + free(dev_path); return (PCPL_GLVC_ERROR); } + free(dev_path); + /* - * Check if the channel-name points to a vldc node - * or a glvc node + * Handle transport-specific processing */ - if (strstr(channel_name, CHANNEL_DEV) != NULL) { - vldc_opt_op_t op; - - xport_type = VLDC_STREAMING; + switch (xport_type) { + case VLDC_STREAMING: mtu_size = VLDC_MTU_SIZE; op.op_sel = VLDC_OP_SET; @@ -222,17 +230,19 @@ pcp_init(char *channel_name) (void) close(channel_fd); return (PCPL_GLVC_ERROR); } - } else { - xport_type = GLVC_NON_STREAM; + break; + case GLVC_NON_STREAM: + default: /* * Get the Channel MTU size */ if (pcp_get_prop(channel_fd, GLVC_XPORT_OPT_MTU_SZ, - &mtu_size) != 0) { + &mtu_size) != 0) { (void) close(channel_fd); return (PCPL_GLVC_ERROR); } + break; } /* diff --git a/usr/src/lib/libpcp/common/pcp_utils.c b/usr/src/lib/libpcp/common/pcp_utils.c new file mode 100644 index 0000000000..3ae93ab09e --- /dev/null +++ b/usr/src/lib/libpcp/common/pcp_utils.c @@ -0,0 +1,358 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Implements auxiliary routines declared in pcp_utils.h to facilitate + * finding the appropriate communication transport & device path for a + * given service. This supports the transition from the legacy service channel + * transport (glvc) to the logical domain channel (vldc) transport native + * to platforms running Logical Domains (LDoms). + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <strings.h> +#include <stdlib.h> +#include <libgen.h> +#include <unistd.h> +#include <stdio.h> +#include <libdevinfo.h> + +#include "pcp_utils.h" + +typedef enum { false = 0, true = 1 } bool_t; + +#define SERVICE_PREFIX "SUNW,sun4v-" +#define DEVICES_DIR "/devices" +#define GLVC ":glvc" +#define VCHAN "virtual-channel@" +#define VCHAN_C "virtual-channel-client@" + +/* + * The mechanism to relate a service to a device path is different for + * vldc and glvc, due to the way the device pathnames are encoded: + * Sample service: sunvts + * Service Name: SUNW,sun4v-sunvts + * GLVC device path: + * "/devices/virtual-devices@100/sunvts@a:glvc" + * VLDC device path: + * "/devices/virtual-devices@100/channel-devices@200/virtual-channel@3:sunvts" + * + * As VLDC is the communication mechanism used in an LDoms environment, it is + * the preferred channel, and its existence is checked for first. + */ + +/* + * Extract from dev_path the "service name" portion. + * For vldc, the service corresponds to the minor name of the device path + * (e.g. virtual-channel@3:sunvts for sunvts). If service is non-NULL, it must + * match the extracted service name for the function to succeed. + * The service name is returned in match (if non-NULL), and the function + * itself returns true on success; false on failure. + */ +static bool_t +get_vldc_svc_name(char *dev_path, char *service, char **match) +{ + bool_t ret = false; + char *pathname = strdup(dev_path); + char *devname, *s; + + if (NULL == pathname) + return (false); + + devname = basename(pathname); + s = strrchr(devname, ':'); + + if (s++ == NULL) { + goto end; + } + + if ((strncmp(devname, VCHAN, strlen(VCHAN)) == 0) || + (strncmp(devname, VCHAN_C, strlen(VCHAN_C)) == 0)) { + /* + * If in addition, a service string is specified to + * be matched, do a comparison + */ + if (service != NULL) { + if (strcmp(s, service) == 0) { + if (match) + *match = strdup(s); + ret = true; + goto end; + } else { + ret = false; + goto end; + } + } else if (match) { + *match = strdup(s); + } + + ret = true; + goto end; + } +end: + + free(pathname); + return (ret); +} + +/* + * Extract from dev_path the "service name" portion. + * For glvc, the service corresponds to the node name of the device path + * (e.g. sunvts@a:glvc for sunvts). If service is non-NULL, it must + * match the extracted service name for the function to succeed. + * The service name is returned in match (if non-NULL), and the function + * itself returns true on success; false on failure. + */ +static bool_t +get_glvc_svc_name(char *dev_path, char *service, char **match) +{ + bool_t ret = true; + char *pathname = strdup(dev_path); + char *devname, *substr, *t; + int len; + + if (NULL == pathname) + return (false); + + devname = basename(pathname); + substr = strstr(devname, GLVC); + + if (!((substr != NULL) && (strcmp(substr, GLVC) == 0))) { + ret = false; + goto end; + } + + if ((t = strrchr(devname, '@')) == NULL) { + ret = false; + goto end; + } + + len = t - devname; + + /* + * If a service string is specified, check if there + * is a match + */ + if ((service != NULL) && (strncmp(devname, service, len) != 0)) + ret = false; + + if ((ret == true) && (match != NULL)) { + *match = calloc(len + 1, 1); + if (*match) + (void) strncpy(*match, devname, len); + } + +end: + free(pathname); + return (ret); +} + +/* + * This routine accepts either a prefixed service name or a legacy full + * pathname (which might not even exist in the filesystem), and in either case + * returns a canonical service name. If the parameter is neither a service + * name (i.e. with a "SUNW,sun4v-" prefix), nor a path to a legacy glvc or + * vldc device, NULL is returned. + */ +char * +platsvc_extract_svc_name(char *devname) +{ + char *sname = NULL; + char *vldc_path, *glvc_path; + + /* + * First check whether a service name + */ + if (strncmp(devname, SERVICE_PREFIX, strlen(SERVICE_PREFIX)) == 0) { + sname = strdup(devname + strlen(SERVICE_PREFIX)); + return (sname); + } + + /* + * Not a service name, check if it's a valid pathname + */ + if (!(devname[0] == '/' || devname[0] == '.')) { + return (NULL); + } + + /* + * Ideally, we should only check for a valid glvc pathname, + * requiring all vldc access to be only via service names. But + * to prevent a flag day with code that's already passing in + * vldc full pathnames (e.g. sunMC), we allow them here. + */ + if (get_vldc_svc_name(devname, NULL, &vldc_path) == true) { + return (vldc_path); + } else if (get_glvc_svc_name(devname, NULL, &glvc_path) == true) { + return (glvc_path); + } + + return (NULL); +} + +/* + * Walk all "service" device nodes to find the one with the + * matching glvc minor name + */ +static char * +svc_name_to_glvc_dev_path(char *service) +{ + di_node_t root_node, service_node; + char *glvc_path; + char *minor_name; + di_minor_t minor; + char *dev_path = NULL; + + if (service == NULL) + return (NULL); + + /* Get device node */ + root_node = di_init("/", DINFOCPYALL); + if (root_node == DI_NODE_NIL) { + return (dev_path); + } + + service_node = di_drv_first_node("glvc", root_node); + + while (service_node != DI_NODE_NIL) { + /* Make sure node name matches service name */ + if (strcmp(service, di_node_name(service_node)) == 0) { + /* Walk minor nodes */ + minor = di_minor_next(service_node, DI_NODE_NIL); + + while (minor != DI_NODE_NIL) { + glvc_path = di_devfs_minor_path(minor); + minor_name = di_minor_name(minor); + + if (strcmp(minor_name, "glvc") == 0) { + dev_path = malloc(strlen(glvc_path) + + strlen(DEVICES_DIR) + 1); + (void) strcpy(dev_path, DEVICES_DIR); + (void) strcat(dev_path, glvc_path); + di_devfs_path_free(glvc_path); + break; + } + + di_devfs_path_free(glvc_path); + minor = di_minor_next(service_node, minor); + } + } + if (dev_path != NULL) + break; + + service_node = di_drv_next_node(service_node); + } + + di_fini(root_node); + return (dev_path); +} + +/* + * Walk all vldc device nodes to find the one with the + * matching minor name + */ +static char * +svc_name_to_vldc_dev_path(char *service) +{ + di_node_t root_node, vldc_node; + char *vldc_path; + char *minor_name; + di_minor_t minor; + char *dev_path = NULL; + + /* Get device node */ + root_node = di_init("/", DINFOCPYALL); + if (root_node == DI_NODE_NIL) { + return (dev_path); + } + + vldc_node = di_drv_first_node("vldc", root_node); + + while (vldc_node != DI_NODE_NIL) { + /* Walk minor nodes */ + minor = di_minor_next(vldc_node, DI_NODE_NIL); + + while (minor != DI_NODE_NIL) { + vldc_path = di_devfs_minor_path(minor); + minor_name = di_minor_name(minor); + + if (strcmp(minor_name, service) == 0) { + dev_path = malloc(strlen(vldc_path) + + strlen(DEVICES_DIR) + 1); + (void) strcpy(dev_path, DEVICES_DIR); + (void) strcat(dev_path, vldc_path); + di_devfs_path_free(vldc_path); + break; + } + + di_devfs_path_free(vldc_path); + minor = di_minor_next(vldc_node, minor); + } + if (dev_path != NULL) + break; + + vldc_node = di_drv_next_node(vldc_node); + } + + di_fini(root_node); + return (dev_path); +} + +/* + * Given a service name or a full legacy pathname, return + * the full pathname to the appropriate vldc or glvc device. + */ +char * +platsvc_name_to_path(char *svc_or_path, pcp_xport_t *type) +{ + char *pathn_p; + char *service; + + if ((service = platsvc_extract_svc_name(svc_or_path)) == NULL) + return (NULL); + + /* + * First lookup vldc nodes + */ + pathn_p = svc_name_to_vldc_dev_path(service); + if (pathn_p != NULL) { + *type = VLDC_STREAMING; + } else { + /* + * If no vldc, try to find a glvc node + */ + pathn_p = svc_name_to_glvc_dev_path(service); + if (pathn_p != NULL) { + *type = GLVC_NON_STREAM; + } + } + + free(service); + return (pathn_p); +} diff --git a/usr/src/lib/libpcp/common/pcp_utils.h b/usr/src/lib/libpcp/common/pcp_utils.h new file mode 100644 index 0000000000..bd501e5d72 --- /dev/null +++ b/usr/src/lib/libpcp/common/pcp_utils.h @@ -0,0 +1,61 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _PCP_UTILS_H +#define _PCP_UTILS_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Enum to differentiate supported transport types + */ +typedef enum { + GLVC_NON_STREAM, + VLDC_STREAMING +} pcp_xport_t; + +/* + * This file contains some auxiliary routines to enable libpcp to + * automatically find the device pathname of a given SP service + * (e.g. SUNW,sun4v-fma). In addition, glvc pathnames are + * converted to a service name and then a device path to maintain + * backward compatibility for applications still using full glvc + * device paths. The routines are defined in a separate source + * file, so any program can separately link with the .o file + * directly instead of using libpcp. + */ + +char *platsvc_extract_svc_name(char *devname); +char *platsvc_name_to_path(char *, pcp_xport_t *); + +#ifdef __cplusplus +} +#endif + +#endif /* _PCP_UTILS_H */ diff --git a/usr/src/lib/libpcp/sparc/Makefile b/usr/src/lib/libpcp/sparc/Makefile index 9b9d7c7098..bb9fbc3935 100644 --- a/usr/src/lib/libpcp/sparc/Makefile +++ b/usr/src/lib/libpcp/sparc/Makefile @@ -30,13 +30,14 @@ UTSBASE= ../../../uts PLATINCS += -I$(USR_PLAT_DIR)/sun4v/include -I$(UTSBASE)/sun4v -PLATFORM_OBJECTS= libpcp.o +PLATFORM_OBJECTS= libpcp.o pcp_utils.o # # platform library directory (/usr/platform/SUNW,Sun-Fire-T200/lib) # -PLATFORM=SUNW,Sun-Fire-T200 -LINKED_PLATFORMS = SUNW,Netra-CP3060 +PLATFORM=sun4v +LINKED_PLATFORMS = SUNW,Sun-Fire-T200 \ + SUNW,Netra-CP3060 include ../Makefile.com |
