13530Srb144127 /* 23530Srb144127 * CDDL HEADER START 33530Srb144127 * 43530Srb144127 * The contents of this file are subject to the terms of the 53530Srb144127 * Common Development and Distribution License (the "License"). 63530Srb144127 * You may not use this file except in compliance with the License. 73530Srb144127 * 83530Srb144127 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 93530Srb144127 * or http://www.opensolaris.org/os/licensing. 103530Srb144127 * See the License for the specific language governing permissions 113530Srb144127 * and limitations under the License. 123530Srb144127 * 133530Srb144127 * When distributing Covered Code, include this CDDL HEADER in each 143530Srb144127 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 153530Srb144127 * If applicable, add the following below this CDDL HEADER, with the 163530Srb144127 * fields enclosed by brackets "[]" replaced with your own identifying 173530Srb144127 * information: Portions Copyright [yyyy] [name of copyright owner] 183530Srb144127 * 193530Srb144127 * CDDL HEADER END 203530Srb144127 */ 213530Srb144127 /* 223530Srb144127 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 233530Srb144127 * Use is subject to license terms. 243530Srb144127 */ 253530Srb144127 263530Srb144127 #pragma ident "%Z%%M% %I% %E% SMI" 273530Srb144127 283530Srb144127 #include <stdio.h> 293530Srb144127 #include <sys/param.h> 303530Srb144127 #include <fcntl.h> 313530Srb144127 #include <poll.h> 323530Srb144127 #include <string.h> 333530Srb144127 #include <unistd.h> 343530Srb144127 #include <errno.h> 353530Srb144127 363530Srb144127 #include "sys/ds_pri.h" 373530Srb144127 #include "pri.h" 383530Srb144127 39*4109Skellena static int pri_fd = -1; 40*4109Skellena 41*4109Skellena 42*4109Skellena 433530Srb144127 /* 44*4109Skellena * Library init function 453530Srb144127 * Returns: Success (0), Failure (-1) 463530Srb144127 */ 473530Srb144127 int 483530Srb144127 pri_init(void) 493530Srb144127 { 50*4109Skellena int fd; 51*4109Skellena 52*4109Skellena if (pri_fd != -1) 53*4109Skellena return (-1); 54*4109Skellena 55*4109Skellena fd = open(DS_PRI_DRIVER, O_RDONLY); 56*4109Skellena if (fd < 0) 57*4109Skellena return (-1); 58*4109Skellena 59*4109Skellena pri_fd = fd; 60*4109Skellena 613530Srb144127 return (0); 623530Srb144127 } 633530Srb144127 643530Srb144127 /* 65*4109Skellena * Library fini function 663530Srb144127 * Returns: N/A 673530Srb144127 */ 683530Srb144127 void 693530Srb144127 pri_fini(void) 703530Srb144127 { 71*4109Skellena if (pri_fd < 0) 72*4109Skellena return; 73*4109Skellena 74*4109Skellena (void) close(pri_fd); 75*4109Skellena pri_fd = -1; 763530Srb144127 } 773530Srb144127 783530Srb144127 /* 793530Srb144127 * PRI retrieval function. 803530Srb144127 * Description: 813530Srb144127 * - Library routine to retrieve the Physical Resource Inventory (PRI) 823530Srb144127 * - Utilized by sun4v platforms which support Logical Domains 833530Srb144127 * - Interacts with the ds_pri pseudo driver to retrieve the 843530Srb144127 * PRI. ds_pri driver in turn gets the PRI from the 853530Srb144127 * Domain Services kernel module. Domain Services gets the 863530Srb144127 * PRI from the Service Processor via LDC (Logical Domain 873530Srb144127 * Channel). 883530Srb144127 * - Consumers of this api include FMA, Zeus, and picld 893530Srb144127 * - MT-Safe, Stateless 903530Srb144127 * 913530Srb144127 * Imports: 923530Srb144127 * - ds_pri driver interfaces 933530Srb144127 * 943530Srb144127 * Arguments: 953530Srb144127 * - wait: specifies whether caller wants to wait for a new PRI, 963530Srb144127 * PRI_GET is no-wait, PRI_WAITGET is wait-forever 973530Srb144127 * - token: opaque PRI token, accepted from and/or returned to caller, 983530Srb144127 * see write-only or read-write semantics below 993530Srb144127 * - buf: PRI buffer received from ds_pri driver, returned to caller 1003530Srb144127 * - allocp: caller provided pointer to memory allocator function 1013530Srb144127 * - freep: caller provided pointer to memory free function 1023530Srb144127 * 1033530Srb144127 * Calling Semantics: 1043530Srb144127 * - PRI_GET call ignores the token passed in, and returns 1053530Srb144127 * immediately with current PRI and its token (if any) 1063530Srb144127 * - PRI_WAITGET call returns only upon the receipt of a new PRI 1073530Srb144127 * whose token differs from the token passed in by the caller; 1083530Srb144127 * the passed in token should come from a previous pri_get() 1093530Srb144127 * call with return value >= 0; the new PRI buffer and its token 1103530Srb144127 * are returned to the caller 1113530Srb144127 * - If wait time must be bounded, the caller can spawn a thread 1123530Srb144127 * which makes a PRI_WAITGET call; caller can choose to kill the 1133530Srb144127 * spawned thread after a finite time 1143530Srb144127 * 1153530Srb144127 * Usage Semantics: 1163530Srb144127 * - Caller can use the returned PRI buffer as an argument to 1173530Srb144127 * to md_init_intern() to process it into a machine 1183530Srb144127 * descriptor (md_t) format 1193530Srb144127 * - Caller can choose to supply the same allocator and free 1203530Srb144127 * functions to the md_init_intern() call 1213530Srb144127 * - Once the caller is done using these data structures, 1223530Srb144127 * the following actions need to be performed by the caller: 1233530Srb144127 * - md_fini(mdp) if called md_init_intern() 1243530Srb144127 * - freep(bufp, size) 1253530Srb144127 * 1263530Srb144127 * Returns: 1273530Srb144127 * >0 if PRI is returned successfully (size of PRI buffer) 1283530Srb144127 * 0 if no PRI is available 129*4109Skellena * -1 if there is an error (errno contains the error code 130*4109Skellena * provided) 1313530Srb144127 * 1323530Srb144127 */ 1333530Srb144127 ssize_t 1343530Srb144127 pri_get(uint8_t wait, uint64_t *token, uint64_t **buf, 1353530Srb144127 void *(*allocp)(size_t), void (*freep)(void *, size_t)) 1363530Srb144127 { 1373530Srb144127 uint64_t *bufp; /* buf holding PRI */ 1383530Srb144127 size_t size; /* sizeof PRI */ 1393530Srb144127 struct dspri_info pri_info; /* info about PRI */ 1403530Srb144127 struct dspri_info pri_info2; /* for PRI delta check */ 1413530Srb144127 142*4109Skellena if (pri_fd < 0) { 143*4109Skellena errno = EBADF; 1443530Srb144127 return (-1); 145*4109Skellena } 1463530Srb144127 1473530Srb144127 if (wait == PRI_WAITGET) { 1483530Srb144127 /* wait until have new PRI with different token */ 149*4109Skellena if (ioctl(pri_fd, DSPRI_WAIT, token) < 0) { 1503530Srb144127 return (-1); 1513530Srb144127 } 1523530Srb144127 } 1533530Srb144127 1543530Srb144127 do { 1553530Srb144127 /* get info on current PRI */ 156*4109Skellena if (ioctl(pri_fd, DSPRI_GETINFO, &pri_info) < 0) { 1573530Srb144127 return (-1); 1583530Srb144127 } 1593530Srb144127 1603530Srb144127 size = (size_t)pri_info.size; 1613530Srb144127 1623530Srb144127 /* check to see if no PRI available yet */ 1633530Srb144127 if (size == 0) { 1643530Srb144127 *token = pri_info.token; 1653530Srb144127 return (0); 1663530Srb144127 } 1673530Srb144127 1683530Srb144127 /* allocate a buffer and read the PRI into it */ 1693530Srb144127 if ((bufp = (uint64_t *)allocp(size)) == NULL) { 170*4109Skellena if (errno == 0) 171*4109Skellena errno = ENOMEM; 1723530Srb144127 return (-1); 1733530Srb144127 } 174*4109Skellena if (read(pri_fd, bufp, size) < 0) { 1753530Srb144127 freep(bufp, size); 1763530Srb144127 return (-1); 1773530Srb144127 } 1783530Srb144127 1793530Srb144127 /* 1803530Srb144127 * Check whether PRI token changed between the time 1813530Srb144127 * we did the DSPRI_GETINFO ioctl() and the actual 1823530Srb144127 * read() from the ds_pri driver. The token delta check 1833530Srb144127 * tries to catch the above race condition; be sure 1843530Srb144127 * to not leak memory on retries. 1853530Srb144127 */ 186*4109Skellena if (ioctl(pri_fd, DSPRI_GETINFO, &pri_info2) < 0) { 1873530Srb144127 freep(bufp, size); 1883530Srb144127 return (-1); 1893530Srb144127 } 1903530Srb144127 if (pri_info2.token != pri_info.token) 1913530Srb144127 freep(bufp, size); 1923530Srb144127 1933530Srb144127 } while (pri_info2.token != pri_info.token); 1943530Srb144127 1953530Srb144127 /* return the PRI, its token, and its size to the caller */ 1963530Srb144127 *buf = bufp; 1973530Srb144127 *token = pri_info.token; 1983530Srb144127 return ((ssize_t)size); 1993530Srb144127 } 200