ef8846857fcf954444cdc77e72249afef48377d2rb/*
ef8846857fcf954444cdc77e72249afef48377d2rb * CDDL HEADER START
ef8846857fcf954444cdc77e72249afef48377d2rb *
ef8846857fcf954444cdc77e72249afef48377d2rb * The contents of this file are subject to the terms of the
ef8846857fcf954444cdc77e72249afef48377d2rb * Common Development and Distribution License (the "License").
ef8846857fcf954444cdc77e72249afef48377d2rb * You may not use this file except in compliance with the License.
ef8846857fcf954444cdc77e72249afef48377d2rb *
ef8846857fcf954444cdc77e72249afef48377d2rb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
ef8846857fcf954444cdc77e72249afef48377d2rb * or http://www.opensolaris.org/os/licensing.
ef8846857fcf954444cdc77e72249afef48377d2rb * See the License for the specific language governing permissions
ef8846857fcf954444cdc77e72249afef48377d2rb * and limitations under the License.
ef8846857fcf954444cdc77e72249afef48377d2rb *
ef8846857fcf954444cdc77e72249afef48377d2rb * When distributing Covered Code, include this CDDL HEADER in each
ef8846857fcf954444cdc77e72249afef48377d2rb * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
ef8846857fcf954444cdc77e72249afef48377d2rb * If applicable, add the following below this CDDL HEADER, with the
ef8846857fcf954444cdc77e72249afef48377d2rb * fields enclosed by brackets "[]" replaced with your own identifying
ef8846857fcf954444cdc77e72249afef48377d2rb * information: Portions Copyright [yyyy] [name of copyright owner]
ef8846857fcf954444cdc77e72249afef48377d2rb *
ef8846857fcf954444cdc77e72249afef48377d2rb * CDDL HEADER END
ef8846857fcf954444cdc77e72249afef48377d2rb */
ef8846857fcf954444cdc77e72249afef48377d2rb/*
ef8846857fcf954444cdc77e72249afef48377d2rb * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
ef8846857fcf954444cdc77e72249afef48377d2rb * Use is subject to license terms.
ef8846857fcf954444cdc77e72249afef48377d2rb */
ef8846857fcf954444cdc77e72249afef48377d2rb
ef8846857fcf954444cdc77e72249afef48377d2rb#pragma ident "%Z%%M% %I% %E% SMI"
ef8846857fcf954444cdc77e72249afef48377d2rb
ef8846857fcf954444cdc77e72249afef48377d2rb#include <stdio.h>
ef8846857fcf954444cdc77e72249afef48377d2rb#include <sys/param.h>
ef8846857fcf954444cdc77e72249afef48377d2rb#include <fcntl.h>
ef8846857fcf954444cdc77e72249afef48377d2rb#include <poll.h>
ef8846857fcf954444cdc77e72249afef48377d2rb#include <string.h>
ef8846857fcf954444cdc77e72249afef48377d2rb#include <unistd.h>
ef8846857fcf954444cdc77e72249afef48377d2rb#include <errno.h>
ef8846857fcf954444cdc77e72249afef48377d2rb
ef8846857fcf954444cdc77e72249afef48377d2rb#include "sys/ds_pri.h"
ef8846857fcf954444cdc77e72249afef48377d2rb#include "pri.h"
ef8846857fcf954444cdc77e72249afef48377d2rb
e82e447ac83da0082df4f3e07829e533342ff9efkellenastatic int pri_fd = -1;
e82e447ac83da0082df4f3e07829e533342ff9efkellena
e82e447ac83da0082df4f3e07829e533342ff9efkellena
e82e447ac83da0082df4f3e07829e533342ff9efkellena
ef8846857fcf954444cdc77e72249afef48377d2rb/*
e82e447ac83da0082df4f3e07829e533342ff9efkellena * Library init function
ef8846857fcf954444cdc77e72249afef48377d2rb * Returns: Success (0), Failure (-1)
ef8846857fcf954444cdc77e72249afef48377d2rb */
ef8846857fcf954444cdc77e72249afef48377d2rbint
ef8846857fcf954444cdc77e72249afef48377d2rbpri_init(void)
ef8846857fcf954444cdc77e72249afef48377d2rb{
e82e447ac83da0082df4f3e07829e533342ff9efkellena int fd;
e82e447ac83da0082df4f3e07829e533342ff9efkellena
e82e447ac83da0082df4f3e07829e533342ff9efkellena if (pri_fd != -1)
e82e447ac83da0082df4f3e07829e533342ff9efkellena return (-1);
e82e447ac83da0082df4f3e07829e533342ff9efkellena
e82e447ac83da0082df4f3e07829e533342ff9efkellena fd = open(DS_PRI_DRIVER, O_RDONLY);
e82e447ac83da0082df4f3e07829e533342ff9efkellena if (fd < 0)
e82e447ac83da0082df4f3e07829e533342ff9efkellena return (-1);
e82e447ac83da0082df4f3e07829e533342ff9efkellena
e82e447ac83da0082df4f3e07829e533342ff9efkellena pri_fd = fd;
e82e447ac83da0082df4f3e07829e533342ff9efkellena
ef8846857fcf954444cdc77e72249afef48377d2rb return (0);
ef8846857fcf954444cdc77e72249afef48377d2rb}
ef8846857fcf954444cdc77e72249afef48377d2rb
ef8846857fcf954444cdc77e72249afef48377d2rb/*
e82e447ac83da0082df4f3e07829e533342ff9efkellena * Library fini function
ef8846857fcf954444cdc77e72249afef48377d2rb * Returns: N/A
ef8846857fcf954444cdc77e72249afef48377d2rb */
ef8846857fcf954444cdc77e72249afef48377d2rbvoid
ef8846857fcf954444cdc77e72249afef48377d2rbpri_fini(void)
ef8846857fcf954444cdc77e72249afef48377d2rb{
e82e447ac83da0082df4f3e07829e533342ff9efkellena if (pri_fd < 0)
e82e447ac83da0082df4f3e07829e533342ff9efkellena return;
e82e447ac83da0082df4f3e07829e533342ff9efkellena
e82e447ac83da0082df4f3e07829e533342ff9efkellena (void) close(pri_fd);
e82e447ac83da0082df4f3e07829e533342ff9efkellena pri_fd = -1;
ef8846857fcf954444cdc77e72249afef48377d2rb}
ef8846857fcf954444cdc77e72249afef48377d2rb
ef8846857fcf954444cdc77e72249afef48377d2rb/*
ef8846857fcf954444cdc77e72249afef48377d2rb * PRI retrieval function.
ef8846857fcf954444cdc77e72249afef48377d2rb * Description:
ef8846857fcf954444cdc77e72249afef48377d2rb * - Library routine to retrieve the Physical Resource Inventory (PRI)
ef8846857fcf954444cdc77e72249afef48377d2rb * - Utilized by sun4v platforms which support Logical Domains
ef8846857fcf954444cdc77e72249afef48377d2rb * - Interacts with the ds_pri pseudo driver to retrieve the
ef8846857fcf954444cdc77e72249afef48377d2rb * PRI. ds_pri driver in turn gets the PRI from the
ef8846857fcf954444cdc77e72249afef48377d2rb * Domain Services kernel module. Domain Services gets the
ef8846857fcf954444cdc77e72249afef48377d2rb * PRI from the Service Processor via LDC (Logical Domain
ef8846857fcf954444cdc77e72249afef48377d2rb * Channel).
ef8846857fcf954444cdc77e72249afef48377d2rb * - Consumers of this api include FMA, Zeus, and picld
ef8846857fcf954444cdc77e72249afef48377d2rb * - MT-Safe, Stateless
ef8846857fcf954444cdc77e72249afef48377d2rb *
ef8846857fcf954444cdc77e72249afef48377d2rb * Imports:
ef8846857fcf954444cdc77e72249afef48377d2rb * - ds_pri driver interfaces
ef8846857fcf954444cdc77e72249afef48377d2rb *
ef8846857fcf954444cdc77e72249afef48377d2rb * Arguments:
ef8846857fcf954444cdc77e72249afef48377d2rb * - wait: specifies whether caller wants to wait for a new PRI,
ef8846857fcf954444cdc77e72249afef48377d2rb * PRI_GET is no-wait, PRI_WAITGET is wait-forever
ef8846857fcf954444cdc77e72249afef48377d2rb * - token: opaque PRI token, accepted from and/or returned to caller,
ef8846857fcf954444cdc77e72249afef48377d2rb * see write-only or read-write semantics below
ef8846857fcf954444cdc77e72249afef48377d2rb * - buf: PRI buffer received from ds_pri driver, returned to caller
ef8846857fcf954444cdc77e72249afef48377d2rb * - allocp: caller provided pointer to memory allocator function
ef8846857fcf954444cdc77e72249afef48377d2rb * - freep: caller provided pointer to memory free function
ef8846857fcf954444cdc77e72249afef48377d2rb *
ef8846857fcf954444cdc77e72249afef48377d2rb * Calling Semantics:
ef8846857fcf954444cdc77e72249afef48377d2rb * - PRI_GET call ignores the token passed in, and returns
ef8846857fcf954444cdc77e72249afef48377d2rb * immediately with current PRI and its token (if any)
ef8846857fcf954444cdc77e72249afef48377d2rb * - PRI_WAITGET call returns only upon the receipt of a new PRI
ef8846857fcf954444cdc77e72249afef48377d2rb * whose token differs from the token passed in by the caller;
ef8846857fcf954444cdc77e72249afef48377d2rb * the passed in token should come from a previous pri_get()
ef8846857fcf954444cdc77e72249afef48377d2rb * call with return value >= 0; the new PRI buffer and its token
ef8846857fcf954444cdc77e72249afef48377d2rb * are returned to the caller
ef8846857fcf954444cdc77e72249afef48377d2rb * - If wait time must be bounded, the caller can spawn a thread
ef8846857fcf954444cdc77e72249afef48377d2rb * which makes a PRI_WAITGET call; caller can choose to kill the
ef8846857fcf954444cdc77e72249afef48377d2rb * spawned thread after a finite time
ef8846857fcf954444cdc77e72249afef48377d2rb *
ef8846857fcf954444cdc77e72249afef48377d2rb * Usage Semantics:
ef8846857fcf954444cdc77e72249afef48377d2rb * - Caller can use the returned PRI buffer as an argument to
ef8846857fcf954444cdc77e72249afef48377d2rb * to md_init_intern() to process it into a machine
ef8846857fcf954444cdc77e72249afef48377d2rb * descriptor (md_t) format
ef8846857fcf954444cdc77e72249afef48377d2rb * - Caller can choose to supply the same allocator and free
ef8846857fcf954444cdc77e72249afef48377d2rb * functions to the md_init_intern() call
ef8846857fcf954444cdc77e72249afef48377d2rb * - Once the caller is done using these data structures,
ef8846857fcf954444cdc77e72249afef48377d2rb * the following actions need to be performed by the caller:
ef8846857fcf954444cdc77e72249afef48377d2rb * - md_fini(mdp) if called md_init_intern()
ef8846857fcf954444cdc77e72249afef48377d2rb * - freep(bufp, size)
ef8846857fcf954444cdc77e72249afef48377d2rb *
ef8846857fcf954444cdc77e72249afef48377d2rb * Returns:
ef8846857fcf954444cdc77e72249afef48377d2rb * >0 if PRI is returned successfully (size of PRI buffer)
ef8846857fcf954444cdc77e72249afef48377d2rb * 0 if no PRI is available
e82e447ac83da0082df4f3e07829e533342ff9efkellena * -1 if there is an error (errno contains the error code
e82e447ac83da0082df4f3e07829e533342ff9efkellena * provided)
ef8846857fcf954444cdc77e72249afef48377d2rb *
ef8846857fcf954444cdc77e72249afef48377d2rb */
ef8846857fcf954444cdc77e72249afef48377d2rbssize_t
ef8846857fcf954444cdc77e72249afef48377d2rbpri_get(uint8_t wait, uint64_t *token, uint64_t **buf,
ef8846857fcf954444cdc77e72249afef48377d2rb void *(*allocp)(size_t), void (*freep)(void *, size_t))
ef8846857fcf954444cdc77e72249afef48377d2rb{
ef8846857fcf954444cdc77e72249afef48377d2rb uint64_t *bufp; /* buf holding PRI */
ef8846857fcf954444cdc77e72249afef48377d2rb size_t size; /* sizeof PRI */
ef8846857fcf954444cdc77e72249afef48377d2rb struct dspri_info pri_info; /* info about PRI */
ef8846857fcf954444cdc77e72249afef48377d2rb struct dspri_info pri_info2; /* for PRI delta check */
ef8846857fcf954444cdc77e72249afef48377d2rb
e82e447ac83da0082df4f3e07829e533342ff9efkellena if (pri_fd < 0) {
e82e447ac83da0082df4f3e07829e533342ff9efkellena errno = EBADF;
ef8846857fcf954444cdc77e72249afef48377d2rb return (-1);
e82e447ac83da0082df4f3e07829e533342ff9efkellena }
ef8846857fcf954444cdc77e72249afef48377d2rb
ef8846857fcf954444cdc77e72249afef48377d2rb if (wait == PRI_WAITGET) {
ef8846857fcf954444cdc77e72249afef48377d2rb /* wait until have new PRI with different token */
e82e447ac83da0082df4f3e07829e533342ff9efkellena if (ioctl(pri_fd, DSPRI_WAIT, token) < 0) {
ef8846857fcf954444cdc77e72249afef48377d2rb return (-1);
ef8846857fcf954444cdc77e72249afef48377d2rb }
ef8846857fcf954444cdc77e72249afef48377d2rb }
ef8846857fcf954444cdc77e72249afef48377d2rb
ef8846857fcf954444cdc77e72249afef48377d2rb do {
ef8846857fcf954444cdc77e72249afef48377d2rb /* get info on current PRI */
e82e447ac83da0082df4f3e07829e533342ff9efkellena if (ioctl(pri_fd, DSPRI_GETINFO, &pri_info) < 0) {
ef8846857fcf954444cdc77e72249afef48377d2rb return (-1);
ef8846857fcf954444cdc77e72249afef48377d2rb }
ef8846857fcf954444cdc77e72249afef48377d2rb
ef8846857fcf954444cdc77e72249afef48377d2rb size = (size_t)pri_info.size;
ef8846857fcf954444cdc77e72249afef48377d2rb
ef8846857fcf954444cdc77e72249afef48377d2rb /* check to see if no PRI available yet */
ef8846857fcf954444cdc77e72249afef48377d2rb if (size == 0) {
ef8846857fcf954444cdc77e72249afef48377d2rb *token = pri_info.token;
ef8846857fcf954444cdc77e72249afef48377d2rb return (0);
ef8846857fcf954444cdc77e72249afef48377d2rb }
ef8846857fcf954444cdc77e72249afef48377d2rb
ef8846857fcf954444cdc77e72249afef48377d2rb /* allocate a buffer and read the PRI into it */
ef8846857fcf954444cdc77e72249afef48377d2rb if ((bufp = (uint64_t *)allocp(size)) == NULL) {
e82e447ac83da0082df4f3e07829e533342ff9efkellena if (errno == 0)
e82e447ac83da0082df4f3e07829e533342ff9efkellena errno = ENOMEM;
ef8846857fcf954444cdc77e72249afef48377d2rb return (-1);
ef8846857fcf954444cdc77e72249afef48377d2rb }
e82e447ac83da0082df4f3e07829e533342ff9efkellena if (read(pri_fd, bufp, size) < 0) {
ef8846857fcf954444cdc77e72249afef48377d2rb freep(bufp, size);
ef8846857fcf954444cdc77e72249afef48377d2rb return (-1);
ef8846857fcf954444cdc77e72249afef48377d2rb }
ef8846857fcf954444cdc77e72249afef48377d2rb
ef8846857fcf954444cdc77e72249afef48377d2rb /*
ef8846857fcf954444cdc77e72249afef48377d2rb * Check whether PRI token changed between the time
ef8846857fcf954444cdc77e72249afef48377d2rb * we did the DSPRI_GETINFO ioctl() and the actual
ef8846857fcf954444cdc77e72249afef48377d2rb * read() from the ds_pri driver. The token delta check
ef8846857fcf954444cdc77e72249afef48377d2rb * tries to catch the above race condition; be sure
ef8846857fcf954444cdc77e72249afef48377d2rb * to not leak memory on retries.
ef8846857fcf954444cdc77e72249afef48377d2rb */
e82e447ac83da0082df4f3e07829e533342ff9efkellena if (ioctl(pri_fd, DSPRI_GETINFO, &pri_info2) < 0) {
ef8846857fcf954444cdc77e72249afef48377d2rb freep(bufp, size);
ef8846857fcf954444cdc77e72249afef48377d2rb return (-1);
ef8846857fcf954444cdc77e72249afef48377d2rb }
ef8846857fcf954444cdc77e72249afef48377d2rb if (pri_info2.token != pri_info.token)
ef8846857fcf954444cdc77e72249afef48377d2rb freep(bufp, size);
ef8846857fcf954444cdc77e72249afef48377d2rb
ef8846857fcf954444cdc77e72249afef48377d2rb } while (pri_info2.token != pri_info.token);
ef8846857fcf954444cdc77e72249afef48377d2rb
ef8846857fcf954444cdc77e72249afef48377d2rb /* return the PRI, its token, and its size to the caller */
ef8846857fcf954444cdc77e72249afef48377d2rb *buf = bufp;
ef8846857fcf954444cdc77e72249afef48377d2rb *token = pri_info.token;
ef8846857fcf954444cdc77e72249afef48377d2rb return ((ssize_t)size);
ef8846857fcf954444cdc77e72249afef48377d2rb}