1*ef884685Srb144127 /* 2*ef884685Srb144127 * CDDL HEADER START 3*ef884685Srb144127 * 4*ef884685Srb144127 * The contents of this file are subject to the terms of the 5*ef884685Srb144127 * Common Development and Distribution License (the "License"). 6*ef884685Srb144127 * You may not use this file except in compliance with the License. 7*ef884685Srb144127 * 8*ef884685Srb144127 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*ef884685Srb144127 * or http://www.opensolaris.org/os/licensing. 10*ef884685Srb144127 * See the License for the specific language governing permissions 11*ef884685Srb144127 * and limitations under the License. 12*ef884685Srb144127 * 13*ef884685Srb144127 * When distributing Covered Code, include this CDDL HEADER in each 14*ef884685Srb144127 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*ef884685Srb144127 * If applicable, add the following below this CDDL HEADER, with the 16*ef884685Srb144127 * fields enclosed by brackets "[]" replaced with your own identifying 17*ef884685Srb144127 * information: Portions Copyright [yyyy] [name of copyright owner] 18*ef884685Srb144127 * 19*ef884685Srb144127 * CDDL HEADER END 20*ef884685Srb144127 */ 21*ef884685Srb144127 /* 22*ef884685Srb144127 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23*ef884685Srb144127 * Use is subject to license terms. 24*ef884685Srb144127 */ 25*ef884685Srb144127 26*ef884685Srb144127 #pragma ident "%Z%%M% %I% %E% SMI" 27*ef884685Srb144127 28*ef884685Srb144127 #include <stdio.h> 29*ef884685Srb144127 #include <sys/param.h> 30*ef884685Srb144127 #include <fcntl.h> 31*ef884685Srb144127 #include <poll.h> 32*ef884685Srb144127 #include <string.h> 33*ef884685Srb144127 #include <unistd.h> 34*ef884685Srb144127 #include <errno.h> 35*ef884685Srb144127 36*ef884685Srb144127 #include "sys/ds_pri.h" 37*ef884685Srb144127 #include "pri.h" 38*ef884685Srb144127 39*ef884685Srb144127 /* 40*ef884685Srb144127 * Library init function - currently no-op. 41*ef884685Srb144127 * Returns: Success (0), Failure (-1) 42*ef884685Srb144127 */ 43*ef884685Srb144127 int 44*ef884685Srb144127 pri_init(void) 45*ef884685Srb144127 { 46*ef884685Srb144127 return (0); 47*ef884685Srb144127 } 48*ef884685Srb144127 49*ef884685Srb144127 /* 50*ef884685Srb144127 * Library fini function - currently no-op. 51*ef884685Srb144127 * Returns: N/A 52*ef884685Srb144127 */ 53*ef884685Srb144127 void 54*ef884685Srb144127 pri_fini(void) 55*ef884685Srb144127 { 56*ef884685Srb144127 } 57*ef884685Srb144127 58*ef884685Srb144127 /* 59*ef884685Srb144127 * PRI retrieval function. 60*ef884685Srb144127 * Description: 61*ef884685Srb144127 * - Library routine to retrieve the Physical Resource Inventory (PRI) 62*ef884685Srb144127 * - Utilized by sun4v platforms which support Logical Domains 63*ef884685Srb144127 * - Interacts with the ds_pri pseudo driver to retrieve the 64*ef884685Srb144127 * PRI. ds_pri driver in turn gets the PRI from the 65*ef884685Srb144127 * Domain Services kernel module. Domain Services gets the 66*ef884685Srb144127 * PRI from the Service Processor via LDC (Logical Domain 67*ef884685Srb144127 * Channel). 68*ef884685Srb144127 * - Consumers of this api include FMA, Zeus, and picld 69*ef884685Srb144127 * - MT-Safe, Stateless 70*ef884685Srb144127 * 71*ef884685Srb144127 * Imports: 72*ef884685Srb144127 * - ds_pri driver interfaces 73*ef884685Srb144127 * 74*ef884685Srb144127 * Arguments: 75*ef884685Srb144127 * - wait: specifies whether caller wants to wait for a new PRI, 76*ef884685Srb144127 * PRI_GET is no-wait, PRI_WAITGET is wait-forever 77*ef884685Srb144127 * - token: opaque PRI token, accepted from and/or returned to caller, 78*ef884685Srb144127 * see write-only or read-write semantics below 79*ef884685Srb144127 * - buf: PRI buffer received from ds_pri driver, returned to caller 80*ef884685Srb144127 * - allocp: caller provided pointer to memory allocator function 81*ef884685Srb144127 * - freep: caller provided pointer to memory free function 82*ef884685Srb144127 * 83*ef884685Srb144127 * Calling Semantics: 84*ef884685Srb144127 * - PRI_GET call ignores the token passed in, and returns 85*ef884685Srb144127 * immediately with current PRI and its token (if any) 86*ef884685Srb144127 * - PRI_WAITGET call returns only upon the receipt of a new PRI 87*ef884685Srb144127 * whose token differs from the token passed in by the caller; 88*ef884685Srb144127 * the passed in token should come from a previous pri_get() 89*ef884685Srb144127 * call with return value >= 0; the new PRI buffer and its token 90*ef884685Srb144127 * are returned to the caller 91*ef884685Srb144127 * - If wait time must be bounded, the caller can spawn a thread 92*ef884685Srb144127 * which makes a PRI_WAITGET call; caller can choose to kill the 93*ef884685Srb144127 * spawned thread after a finite time 94*ef884685Srb144127 * 95*ef884685Srb144127 * Usage Semantics: 96*ef884685Srb144127 * - Caller can use the returned PRI buffer as an argument to 97*ef884685Srb144127 * to md_init_intern() to process it into a machine 98*ef884685Srb144127 * descriptor (md_t) format 99*ef884685Srb144127 * - Caller can choose to supply the same allocator and free 100*ef884685Srb144127 * functions to the md_init_intern() call 101*ef884685Srb144127 * - Once the caller is done using these data structures, 102*ef884685Srb144127 * the following actions need to be performed by the caller: 103*ef884685Srb144127 * - md_fini(mdp) if called md_init_intern() 104*ef884685Srb144127 * - freep(bufp, size) 105*ef884685Srb144127 * 106*ef884685Srb144127 * Returns: 107*ef884685Srb144127 * >0 if PRI is returned successfully (size of PRI buffer) 108*ef884685Srb144127 * 0 if no PRI is available 109*ef884685Srb144127 * -1 if there is an error (errno contains the error code) 110*ef884685Srb144127 * 111*ef884685Srb144127 */ 112*ef884685Srb144127 ssize_t 113*ef884685Srb144127 pri_get(uint8_t wait, uint64_t *token, uint64_t **buf, 114*ef884685Srb144127 void *(*allocp)(size_t), void (*freep)(void *, size_t)) 115*ef884685Srb144127 { 116*ef884685Srb144127 int fd; /* for device open */ 117*ef884685Srb144127 uint64_t *bufp; /* buf holding PRI */ 118*ef884685Srb144127 size_t size; /* sizeof PRI */ 119*ef884685Srb144127 struct dspri_info pri_info; /* info about PRI */ 120*ef884685Srb144127 struct dspri_info pri_info2; /* for PRI delta check */ 121*ef884685Srb144127 122*ef884685Srb144127 if ((fd = open(DS_PRI_DRIVER, O_RDONLY)) < 0) 123*ef884685Srb144127 return (-1); 124*ef884685Srb144127 125*ef884685Srb144127 if (wait == PRI_WAITGET) { 126*ef884685Srb144127 /* wait until have new PRI with different token */ 127*ef884685Srb144127 if (ioctl(fd, DSPRI_WAIT, token) < 0) { 128*ef884685Srb144127 (void) close(fd); 129*ef884685Srb144127 return (-1); 130*ef884685Srb144127 } 131*ef884685Srb144127 } 132*ef884685Srb144127 133*ef884685Srb144127 do { 134*ef884685Srb144127 /* get info on current PRI */ 135*ef884685Srb144127 if (ioctl(fd, DSPRI_GETINFO, &pri_info) < 0) { 136*ef884685Srb144127 (void) close(fd); 137*ef884685Srb144127 return (-1); 138*ef884685Srb144127 } 139*ef884685Srb144127 140*ef884685Srb144127 size = (size_t)pri_info.size; 141*ef884685Srb144127 142*ef884685Srb144127 /* check to see if no PRI available yet */ 143*ef884685Srb144127 if (size == 0) { 144*ef884685Srb144127 *token = pri_info.token; 145*ef884685Srb144127 (void) close(fd); 146*ef884685Srb144127 return (0); 147*ef884685Srb144127 } 148*ef884685Srb144127 149*ef884685Srb144127 /* allocate a buffer and read the PRI into it */ 150*ef884685Srb144127 if ((bufp = (uint64_t *)allocp(size)) == NULL) { 151*ef884685Srb144127 (void) close(fd); 152*ef884685Srb144127 return (-1); 153*ef884685Srb144127 } 154*ef884685Srb144127 if (read(fd, bufp, size) < 0) { 155*ef884685Srb144127 freep(bufp, size); 156*ef884685Srb144127 (void) close(fd); 157*ef884685Srb144127 return (-1); 158*ef884685Srb144127 } 159*ef884685Srb144127 160*ef884685Srb144127 /* 161*ef884685Srb144127 * Check whether PRI token changed between the time 162*ef884685Srb144127 * we did the DSPRI_GETINFO ioctl() and the actual 163*ef884685Srb144127 * read() from the ds_pri driver. The token delta check 164*ef884685Srb144127 * tries to catch the above race condition; be sure 165*ef884685Srb144127 * to not leak memory on retries. 166*ef884685Srb144127 */ 167*ef884685Srb144127 if (ioctl(fd, DSPRI_GETINFO, &pri_info2) < 0) { 168*ef884685Srb144127 freep(bufp, size); 169*ef884685Srb144127 (void) close(fd); 170*ef884685Srb144127 return (-1); 171*ef884685Srb144127 } 172*ef884685Srb144127 if (pri_info2.token != pri_info.token) 173*ef884685Srb144127 freep(bufp, size); 174*ef884685Srb144127 175*ef884685Srb144127 } while (pri_info2.token != pri_info.token); 176*ef884685Srb144127 177*ef884685Srb144127 /* return the PRI, its token, and its size to the caller */ 178*ef884685Srb144127 *buf = bufp; 179*ef884685Srb144127 *token = pri_info.token; 180*ef884685Srb144127 (void) close(fd); 181*ef884685Srb144127 return ((ssize_t)size); 182*ef884685Srb144127 } 183