1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Minor number allocation for various protocol modules. 31 */ 32 33 #include <sys/types.h> 34 #include <sys/kmem.h> 35 #include <sys/mutex.h> 36 #include <sys/ddi.h> 37 #include <sys/types.h> 38 #include <sys/mkdev.h> 39 #include <sys/param.h> 40 #include <inet/common.h> 41 42 typedef struct inet_arena { 43 vmem_t *ineta_arena; /* Minor number arena */ 44 minor_t ineta_maxminor; /* max minor number in the arena */ 45 } inet_arena_t; 46 47 /* Maximum minor number to use */ 48 static minor_t inet_maxminor = INET_MAXMINOR; 49 50 void * 51 inet_minor_create(char *name, dev_t min_dev, int kmflags) 52 { 53 inet_arena_t *arena = kmem_alloc(sizeof (inet_arena_t), kmflags); 54 55 if (arena != NULL) { 56 arena->ineta_maxminor = MIN(MAXMIN32, inet_maxminor); 57 arena->ineta_arena = vmem_create(name, 58 (void *)min_dev, arena->ineta_maxminor - min_dev + 1, 59 1, NULL, NULL, NULL, 1, kmflags | VMC_IDENTIFIER); 60 61 if (arena->ineta_arena == NULL) { 62 kmem_free(arena, sizeof (inet_arena_t)); 63 arena = NULL; 64 } 65 } 66 67 return (arena); 68 } 69 70 void 71 inet_minor_destroy(void *a) 72 { 73 inet_arena_t *arena = (inet_arena_t *)a; 74 75 if (arena != NULL) { 76 vmem_destroy(arena->ineta_arena); 77 kmem_free(arena, sizeof (inet_arena_t)); 78 } 79 } 80 81 dev_t 82 inet_minor_alloc(void *a) 83 { 84 inet_arena_t *arena = (inet_arena_t *)a; 85 dev_t dev; 86 87 while ((dev = (dev_t)vmem_alloc(arena->ineta_arena, 1, 88 VM_NOSLEEP)) == 0) { 89 if (arena->ineta_maxminor >= inet_maxminor) 90 return (0); 91 if (vmem_add(arena->ineta_arena, 92 (void *)(uintptr_t)(arena->ineta_maxminor + 1), 93 inet_maxminor - arena->ineta_maxminor, VM_NOSLEEP) == NULL) 94 return (0); 95 arena->ineta_maxminor = inet_maxminor; 96 } 97 return (dev); 98 } 99 100 void 101 inet_minor_free(void *a, dev_t dev) 102 { 103 ASSERT((dev != OPENFAIL) && (dev != 0) && (dev <= inet_maxminor)); 104 vmem_free(((inet_arena_t *)a)->ineta_arena, (void *)dev, 1); 105 } 106 107 /* 108 * This function is used to free a message that has gone through 109 * mi_copyin processing which modifies the M_IOCTL mblk's b_next 110 * and b_prev pointers. We use this function to set b_next/b_prev 111 * to NULL and free them. 112 */ 113 void 114 inet_freemsg(mblk_t *mp) 115 { 116 mblk_t *bp = mp; 117 118 for (; bp != NULL; bp = bp->b_cont) { 119 bp->b_prev = NULL; 120 bp->b_next = NULL; 121 } 122 freemsg(mp); 123 } 124