1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright (c) 1999 by Sun Microsystems, Inc. 24*7c478bd9Sstevel@tonic-gate * All rights reserved. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * DDI nodeid management ... 31*7c478bd9Sstevel@tonic-gate */ 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/ksynch.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/ddi_implfuncs.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate /* 44*7c478bd9Sstevel@tonic-gate * Keep a sorted free list of available nodeids. 45*7c478bd9Sstevel@tonic-gate * Allocating a nodeid won't cause memory allocation. 46*7c478bd9Sstevel@tonic-gate * Freeing a nodeid does cause memory allocation. 47*7c478bd9Sstevel@tonic-gate */ 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate struct available { 50*7c478bd9Sstevel@tonic-gate uint32_t nodeid; 51*7c478bd9Sstevel@tonic-gate uint32_t count; 52*7c478bd9Sstevel@tonic-gate struct available *next; 53*7c478bd9Sstevel@tonic-gate struct available *prev; 54*7c478bd9Sstevel@tonic-gate }; 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate /* 57*7c478bd9Sstevel@tonic-gate * The initial seed of available nodeids: 1 .. 0x10000000 58*7c478bd9Sstevel@tonic-gate * 0, -1 (DEVI_PSEUDO_NODEID) and -2 (DEVI_SID_NODEID) are illegal values 59*7c478bd9Sstevel@tonic-gate * and may not be used. Although this code is fully capable of dealing 60*7c478bd9Sstevel@tonic-gate * with a full 32-bit range of nodeids, we use a low numeric range of 61*7c478bd9Sstevel@tonic-gate * nodeids as an optimization to avoid overlap with promif nodeids. 62*7c478bd9Sstevel@tonic-gate */ 63*7c478bd9Sstevel@tonic-gate #define OUR_NODEID_MIN ((uint32_t)1) 64*7c478bd9Sstevel@tonic-gate #define OUR_NODEID_MAX ((uint32_t)0x10000000) 65*7c478bd9Sstevel@tonic-gate #define OUR_NODEID_COUNT ((uint32_t)(OUR_NODEID_MAX - OUR_NODEID_MIN)) 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate static struct available seed = { 68*7c478bd9Sstevel@tonic-gate OUR_NODEID_MIN, OUR_NODEID_COUNT, NULL, NULL 69*7c478bd9Sstevel@tonic-gate }; 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate /* 72*7c478bd9Sstevel@tonic-gate * head of the available list ... 73*7c478bd9Sstevel@tonic-gate */ 74*7c478bd9Sstevel@tonic-gate static struct available *nhead; 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate /* 77*7c478bd9Sstevel@tonic-gate * A single lock for the list ... 78*7c478bd9Sstevel@tonic-gate */ 79*7c478bd9Sstevel@tonic-gate static kmutex_t nodeid_lock; 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate /* 82*7c478bd9Sstevel@tonic-gate * Helper functions to manage the list ... 83*7c478bd9Sstevel@tonic-gate */ 84*7c478bd9Sstevel@tonic-gate static struct available * 85*7c478bd9Sstevel@tonic-gate np_alloc(int kmflag) 86*7c478bd9Sstevel@tonic-gate { 87*7c478bd9Sstevel@tonic-gate return (kmem_zalloc(sizeof (struct available), kmflag)); 88*7c478bd9Sstevel@tonic-gate } 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate static void 91*7c478bd9Sstevel@tonic-gate np_free(struct available *np) 92*7c478bd9Sstevel@tonic-gate { 93*7c478bd9Sstevel@tonic-gate kmem_free(np, sizeof (struct available)); 94*7c478bd9Sstevel@tonic-gate } 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate /* 97*7c478bd9Sstevel@tonic-gate * Unlink a node from the list ... the lock must be held. 98*7c478bd9Sstevel@tonic-gate */ 99*7c478bd9Sstevel@tonic-gate static void 100*7c478bd9Sstevel@tonic-gate np_unlink(struct available *np) 101*7c478bd9Sstevel@tonic-gate { 102*7c478bd9Sstevel@tonic-gate if (np->prev) 103*7c478bd9Sstevel@tonic-gate np->prev->next = np->next; 104*7c478bd9Sstevel@tonic-gate else 105*7c478bd9Sstevel@tonic-gate nhead = np->next; 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate if (np->next) 108*7c478bd9Sstevel@tonic-gate np->next->prev = np->prev; 109*7c478bd9Sstevel@tonic-gate } 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate /* 112*7c478bd9Sstevel@tonic-gate * Insert fp before np ... the lock must be held. 113*7c478bd9Sstevel@tonic-gate */ 114*7c478bd9Sstevel@tonic-gate static void 115*7c478bd9Sstevel@tonic-gate np_insert(struct available *fp, struct available *np) 116*7c478bd9Sstevel@tonic-gate { 117*7c478bd9Sstevel@tonic-gate fp->prev = np->prev; 118*7c478bd9Sstevel@tonic-gate fp->next = np; 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate if (np->prev) 121*7c478bd9Sstevel@tonic-gate np->prev->next = fp; 122*7c478bd9Sstevel@tonic-gate else 123*7c478bd9Sstevel@tonic-gate nhead = fp; 124*7c478bd9Sstevel@tonic-gate np->prev = fp; 125*7c478bd9Sstevel@tonic-gate } 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate /* 128*7c478bd9Sstevel@tonic-gate * Add fp to the end of the list ... the lock must be held. 129*7c478bd9Sstevel@tonic-gate */ 130*7c478bd9Sstevel@tonic-gate static void 131*7c478bd9Sstevel@tonic-gate np_add(struct available *fp) 132*7c478bd9Sstevel@tonic-gate { 133*7c478bd9Sstevel@tonic-gate struct available *np; 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate if (nhead == NULL) { 136*7c478bd9Sstevel@tonic-gate nhead = fp; 137*7c478bd9Sstevel@tonic-gate return; 138*7c478bd9Sstevel@tonic-gate } 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate for (np = nhead; np->next != NULL; np = np->next) 141*7c478bd9Sstevel@tonic-gate /* empty */; 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate np->next = fp; 144*7c478bd9Sstevel@tonic-gate fp->prev = np; 145*7c478bd9Sstevel@tonic-gate } 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate /* 148*7c478bd9Sstevel@tonic-gate * If this entry and the next entry are consecutive, coalesce the 149*7c478bd9Sstevel@tonic-gate * two entries into a single entry ... the lock must be held. 150*7c478bd9Sstevel@tonic-gate * If the entry can be coalesced, the extra entry is freed. 151*7c478bd9Sstevel@tonic-gate */ 152*7c478bd9Sstevel@tonic-gate static void 153*7c478bd9Sstevel@tonic-gate np_coalesce(struct available *np) 154*7c478bd9Sstevel@tonic-gate { 155*7c478bd9Sstevel@tonic-gate struct available *xp; 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate xp = np->next; 158*7c478bd9Sstevel@tonic-gate if (xp == NULL) 159*7c478bd9Sstevel@tonic-gate return; 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate if ((np->nodeid + np->count) == xp->nodeid) { 162*7c478bd9Sstevel@tonic-gate np->count += xp->count; 163*7c478bd9Sstevel@tonic-gate np_unlink(xp); 164*7c478bd9Sstevel@tonic-gate np_free(xp); 165*7c478bd9Sstevel@tonic-gate } 166*7c478bd9Sstevel@tonic-gate } 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate void 169*7c478bd9Sstevel@tonic-gate impl_ddi_init_nodeid(void) 170*7c478bd9Sstevel@tonic-gate { 171*7c478bd9Sstevel@tonic-gate struct available *np; 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate mutex_init(&nodeid_lock, NULL, MUTEX_DEFAULT, NULL); 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate /* 176*7c478bd9Sstevel@tonic-gate * Copy the seed into kmem_alloc-ed memory so we don't have to 177*7c478bd9Sstevel@tonic-gate * worry about not freeing it later. 178*7c478bd9Sstevel@tonic-gate */ 179*7c478bd9Sstevel@tonic-gate np = np_alloc(KM_SLEEP); 180*7c478bd9Sstevel@tonic-gate *np = seed; 181*7c478bd9Sstevel@tonic-gate nhead = np; 182*7c478bd9Sstevel@tonic-gate } 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate int 185*7c478bd9Sstevel@tonic-gate impl_ddi_alloc_nodeid(int *nodeid) 186*7c478bd9Sstevel@tonic-gate { 187*7c478bd9Sstevel@tonic-gate struct available *np; 188*7c478bd9Sstevel@tonic-gate int x; 189*7c478bd9Sstevel@tonic-gate int unlinked = 0; 190*7c478bd9Sstevel@tonic-gate 191*7c478bd9Sstevel@tonic-gate mutex_enter(&nodeid_lock); 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate if (nhead == NULL) { 194*7c478bd9Sstevel@tonic-gate mutex_exit(&nodeid_lock); 195*7c478bd9Sstevel@tonic-gate *nodeid = 0; 196*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 197*7c478bd9Sstevel@tonic-gate } 198*7c478bd9Sstevel@tonic-gate 199*7c478bd9Sstevel@tonic-gate np = nhead; 200*7c478bd9Sstevel@tonic-gate x = (int)((unsigned int)np->nodeid); 201*7c478bd9Sstevel@tonic-gate ++np->nodeid; 202*7c478bd9Sstevel@tonic-gate --np->count; 203*7c478bd9Sstevel@tonic-gate if (np->count == 0) { 204*7c478bd9Sstevel@tonic-gate np_unlink(np); 205*7c478bd9Sstevel@tonic-gate unlinked = 1; 206*7c478bd9Sstevel@tonic-gate } 207*7c478bd9Sstevel@tonic-gate mutex_exit(&nodeid_lock); 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate if (unlinked) 210*7c478bd9Sstevel@tonic-gate np_free(np); 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate ASSERT(x != 0); 213*7c478bd9Sstevel@tonic-gate ASSERT(x != DEVI_PSEUDO_NODEID); 214*7c478bd9Sstevel@tonic-gate ASSERT(x != DEVI_SID_NODEID); 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate *nodeid = x; 217*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 218*7c478bd9Sstevel@tonic-gate } 219*7c478bd9Sstevel@tonic-gate 220*7c478bd9Sstevel@tonic-gate void 221*7c478bd9Sstevel@tonic-gate impl_ddi_free_nodeid(int n) 222*7c478bd9Sstevel@tonic-gate { 223*7c478bd9Sstevel@tonic-gate uint32_t nodeid = (uint32_t)n; 224*7c478bd9Sstevel@tonic-gate struct available *np, *fp; 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate ASSERT(n != 0); 227*7c478bd9Sstevel@tonic-gate ASSERT(n != DEVI_PSEUDO_NODEID); 228*7c478bd9Sstevel@tonic-gate ASSERT(n != DEVI_SID_NODEID); 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate /* 231*7c478bd9Sstevel@tonic-gate * Allocate memory wihout holding the lock in case we need it. 232*7c478bd9Sstevel@tonic-gate * If we don't use it, we'll free it. 233*7c478bd9Sstevel@tonic-gate */ 234*7c478bd9Sstevel@tonic-gate fp = np_alloc(KM_SLEEP); 235*7c478bd9Sstevel@tonic-gate 236*7c478bd9Sstevel@tonic-gate mutex_enter(&nodeid_lock); 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate /* 239*7c478bd9Sstevel@tonic-gate * Insert nodeid in the appropriate place in our sorted available 240*7c478bd9Sstevel@tonic-gate * list. Maintain the list as we do it. 241*7c478bd9Sstevel@tonic-gate */ 242*7c478bd9Sstevel@tonic-gate for (np = nhead; np != NULL; np = np->next) { 243*7c478bd9Sstevel@tonic-gate /* 244*7c478bd9Sstevel@tonic-gate * Add to the beginning of this entry? 245*7c478bd9Sstevel@tonic-gate */ 246*7c478bd9Sstevel@tonic-gate if ((nodeid + 1) == np->nodeid) { 247*7c478bd9Sstevel@tonic-gate np->nodeid = nodeid; 248*7c478bd9Sstevel@tonic-gate ++np->count; 249*7c478bd9Sstevel@tonic-gate mutex_exit(&nodeid_lock); 250*7c478bd9Sstevel@tonic-gate np_free(fp); 251*7c478bd9Sstevel@tonic-gate return; 252*7c478bd9Sstevel@tonic-gate } 253*7c478bd9Sstevel@tonic-gate /* 254*7c478bd9Sstevel@tonic-gate * Add to end of this entry? (If yes, try to coalesce 255*7c478bd9Sstevel@tonic-gate * this entry with the next entry.) 256*7c478bd9Sstevel@tonic-gate */ 257*7c478bd9Sstevel@tonic-gate if (nodeid == (np->nodeid + np->count)) { 258*7c478bd9Sstevel@tonic-gate ++np->count; 259*7c478bd9Sstevel@tonic-gate np_coalesce(np); 260*7c478bd9Sstevel@tonic-gate mutex_exit(&nodeid_lock); 261*7c478bd9Sstevel@tonic-gate np_free(fp); 262*7c478bd9Sstevel@tonic-gate return; 263*7c478bd9Sstevel@tonic-gate } 264*7c478bd9Sstevel@tonic-gate /* 265*7c478bd9Sstevel@tonic-gate * Does it belong before this entry? (new entry) 266*7c478bd9Sstevel@tonic-gate */ 267*7c478bd9Sstevel@tonic-gate if (nodeid < np->nodeid) { 268*7c478bd9Sstevel@tonic-gate fp->nodeid = nodeid; 269*7c478bd9Sstevel@tonic-gate fp->count = 1; 270*7c478bd9Sstevel@tonic-gate np_insert(fp, np); 271*7c478bd9Sstevel@tonic-gate mutex_exit(&nodeid_lock); 272*7c478bd9Sstevel@tonic-gate return; 273*7c478bd9Sstevel@tonic-gate } 274*7c478bd9Sstevel@tonic-gate if (nodeid < (np->nodeid + np->count)) 275*7c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, "impl_ddi_free_nodeid: " 276*7c478bd9Sstevel@tonic-gate "nodeid %x already free", n); 277*7c478bd9Sstevel@tonic-gate } 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate /* 280*7c478bd9Sstevel@tonic-gate * Add a new list item to the end of the list ... 281*7c478bd9Sstevel@tonic-gate */ 282*7c478bd9Sstevel@tonic-gate fp->nodeid = nodeid; 283*7c478bd9Sstevel@tonic-gate fp->count = 1; 284*7c478bd9Sstevel@tonic-gate np_add(fp); 285*7c478bd9Sstevel@tonic-gate mutex_exit(&nodeid_lock); 286*7c478bd9Sstevel@tonic-gate } 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate /* 289*7c478bd9Sstevel@tonic-gate * Remove (take) nodeid n off of the available list. 290*7c478bd9Sstevel@tonic-gate * Returns 0 if successful or -1 if it fails. 291*7c478bd9Sstevel@tonic-gate * 292*7c478bd9Sstevel@tonic-gate * A failure indicates we were called with KM_NOSLEEP and we 293*7c478bd9Sstevel@tonic-gate * couldn't allocate memory when we needed to. 294*7c478bd9Sstevel@tonic-gate */ 295*7c478bd9Sstevel@tonic-gate int 296*7c478bd9Sstevel@tonic-gate impl_ddi_take_nodeid(int n, int kmflag) 297*7c478bd9Sstevel@tonic-gate { 298*7c478bd9Sstevel@tonic-gate uint32_t nodeid = (uint32_t)n; 299*7c478bd9Sstevel@tonic-gate struct available *np, *fp; 300*7c478bd9Sstevel@tonic-gate int unlinked = 0; 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate ASSERT(n != 0); 303*7c478bd9Sstevel@tonic-gate ASSERT(n != DEVI_PSEUDO_NODEID); 304*7c478bd9Sstevel@tonic-gate ASSERT(n != DEVI_SID_NODEID); 305*7c478bd9Sstevel@tonic-gate 306*7c478bd9Sstevel@tonic-gate /* 307*7c478bd9Sstevel@tonic-gate * If this nodeid is not within the range of nodeids we 308*7c478bd9Sstevel@tonic-gate * manage, we simply succeed. The initial seed may be 309*7c478bd9Sstevel@tonic-gate * setup so that promif nodeids fall outside our range. 310*7c478bd9Sstevel@tonic-gate */ 311*7c478bd9Sstevel@tonic-gate if ((nodeid < OUR_NODEID_MIN) || (nodeid > OUR_NODEID_MAX)) 312*7c478bd9Sstevel@tonic-gate return (0); 313*7c478bd9Sstevel@tonic-gate 314*7c478bd9Sstevel@tonic-gate /* 315*7c478bd9Sstevel@tonic-gate * Allocate memory wihout holding the lock in case we need it. 316*7c478bd9Sstevel@tonic-gate * If we don't use it, we'll free it. 317*7c478bd9Sstevel@tonic-gate */ 318*7c478bd9Sstevel@tonic-gate fp = np_alloc(kmflag); /* if KM_NOSLEEP, fp may be NULL */ 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate mutex_enter(&nodeid_lock); 321*7c478bd9Sstevel@tonic-gate 322*7c478bd9Sstevel@tonic-gate /* 323*7c478bd9Sstevel@tonic-gate * Find nodeid in our list, if it exists, 'take' it. 324*7c478bd9Sstevel@tonic-gate */ 325*7c478bd9Sstevel@tonic-gate for (np = nhead; np != NULL; np = np->next) { 326*7c478bd9Sstevel@tonic-gate 327*7c478bd9Sstevel@tonic-gate /* 328*7c478bd9Sstevel@tonic-gate * If it's less than this entry, it's not available... 329*7c478bd9Sstevel@tonic-gate */ 330*7c478bd9Sstevel@tonic-gate if (nodeid < np->nodeid) 331*7c478bd9Sstevel@tonic-gate break; 332*7c478bd9Sstevel@tonic-gate 333*7c478bd9Sstevel@tonic-gate /* 334*7c478bd9Sstevel@tonic-gate * If it's the first entry in this list item, take it ... 335*7c478bd9Sstevel@tonic-gate */ 336*7c478bd9Sstevel@tonic-gate if ((nodeid) == np->nodeid) { 337*7c478bd9Sstevel@tonic-gate ++np->nodeid; 338*7c478bd9Sstevel@tonic-gate --np->count; 339*7c478bd9Sstevel@tonic-gate if (np->count == 0) { 340*7c478bd9Sstevel@tonic-gate np_unlink(np); 341*7c478bd9Sstevel@tonic-gate ++unlinked; 342*7c478bd9Sstevel@tonic-gate } 343*7c478bd9Sstevel@tonic-gate mutex_exit(&nodeid_lock); 344*7c478bd9Sstevel@tonic-gate if (fp) 345*7c478bd9Sstevel@tonic-gate np_free(fp); 346*7c478bd9Sstevel@tonic-gate if (unlinked) 347*7c478bd9Sstevel@tonic-gate np_free(np); 348*7c478bd9Sstevel@tonic-gate return (0); 349*7c478bd9Sstevel@tonic-gate } 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate /* 352*7c478bd9Sstevel@tonic-gate * If it's the last entry in this list item, take it ... 353*7c478bd9Sstevel@tonic-gate * The count can't be 1 otherwise it would have matched 354*7c478bd9Sstevel@tonic-gate * the beginning of list case, above. 355*7c478bd9Sstevel@tonic-gate */ 356*7c478bd9Sstevel@tonic-gate if (nodeid == (np->nodeid + np->count - 1)) { 357*7c478bd9Sstevel@tonic-gate --np->count; 358*7c478bd9Sstevel@tonic-gate ASSERT(np->count != 0); 359*7c478bd9Sstevel@tonic-gate mutex_exit(&nodeid_lock); 360*7c478bd9Sstevel@tonic-gate if (fp) 361*7c478bd9Sstevel@tonic-gate np_free(fp); 362*7c478bd9Sstevel@tonic-gate return (0); 363*7c478bd9Sstevel@tonic-gate } 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate /* 366*7c478bd9Sstevel@tonic-gate * Is it in the middle of this entry? If it is, we'll 367*7c478bd9Sstevel@tonic-gate * have to split np into two items, removing nodeid 368*7c478bd9Sstevel@tonic-gate * from the middle of the list item. 369*7c478bd9Sstevel@tonic-gate */ 370*7c478bd9Sstevel@tonic-gate if (nodeid < (np->nodeid + np->count - 1)) { 371*7c478bd9Sstevel@tonic-gate if (fp == NULL) { 372*7c478bd9Sstevel@tonic-gate /* 373*7c478bd9Sstevel@tonic-gate * We were called with KM_NOSLEEP and 374*7c478bd9Sstevel@tonic-gate * were unable to allocate memory. 375*7c478bd9Sstevel@tonic-gate */ 376*7c478bd9Sstevel@tonic-gate mutex_exit(&nodeid_lock); 377*7c478bd9Sstevel@tonic-gate return (-1); 378*7c478bd9Sstevel@tonic-gate } 379*7c478bd9Sstevel@tonic-gate /* 380*7c478bd9Sstevel@tonic-gate * Split np, removing nodeid from the middle of 381*7c478bd9Sstevel@tonic-gate * this entry. We already know it isn't on either 382*7c478bd9Sstevel@tonic-gate * end of of this entry, so we know we have to split it. 383*7c478bd9Sstevel@tonic-gate */ 384*7c478bd9Sstevel@tonic-gate fp->nodeid = np->nodeid; 385*7c478bd9Sstevel@tonic-gate fp->count = nodeid - np->nodeid; 386*7c478bd9Sstevel@tonic-gate np->nodeid = nodeid + 1; 387*7c478bd9Sstevel@tonic-gate np->count = np->count - fp->count - 1; 388*7c478bd9Sstevel@tonic-gate ASSERT((fp->count != 0) && (np->count != 0)); 389*7c478bd9Sstevel@tonic-gate ASSERT(np->nodeid == (fp->nodeid + fp->count + 1)); 390*7c478bd9Sstevel@tonic-gate np_insert(fp, np); 391*7c478bd9Sstevel@tonic-gate mutex_exit(&nodeid_lock); 392*7c478bd9Sstevel@tonic-gate return (0); 393*7c478bd9Sstevel@tonic-gate } 394*7c478bd9Sstevel@tonic-gate } 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate /* 397*7c478bd9Sstevel@tonic-gate * Apparently the nodeid is not available ... 398*7c478bd9Sstevel@tonic-gate */ 399*7c478bd9Sstevel@tonic-gate mutex_exit(&nodeid_lock); 400*7c478bd9Sstevel@tonic-gate 401*7c478bd9Sstevel@tonic-gate if (fp) 402*7c478bd9Sstevel@tonic-gate np_free(fp); 403*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "?impl_ddi_take_nodeid: nodeid %x may not " 404*7c478bd9Sstevel@tonic-gate "be unique\n", nodeid); 405*7c478bd9Sstevel@tonic-gate return (0); 406*7c478bd9Sstevel@tonic-gate } 407