1 1.13 jmcneill /* $NetBSD: OsdSynch.c,v 1.13 2009/08/18 16:41:02 jmcneill Exp $ */ 2 1.1 kochi 3 1.1 kochi /* 4 1.1 kochi * Copyright 2001 Wasabi Systems, Inc. 5 1.1 kochi * All rights reserved. 6 1.1 kochi * 7 1.1 kochi * Written by Jason R. Thorpe for Wasabi Systems, Inc. 8 1.1 kochi * 9 1.1 kochi * Redistribution and use in source and binary forms, with or without 10 1.1 kochi * modification, are permitted provided that the following conditions 11 1.1 kochi * are met: 12 1.1 kochi * 1. Redistributions of source code must retain the above copyright 13 1.1 kochi * notice, this list of conditions and the following disclaimer. 14 1.1 kochi * 2. Redistributions in binary form must reproduce the above copyright 15 1.1 kochi * notice, this list of conditions and the following disclaimer in the 16 1.1 kochi * documentation and/or other materials provided with the distribution. 17 1.1 kochi * 3. All advertising materials mentioning features or use of this software 18 1.1 kochi * must display the following acknowledgement: 19 1.1 kochi * This product includes software developed for the NetBSD Project by 20 1.1 kochi * Wasabi Systems, Inc. 21 1.1 kochi * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22 1.1 kochi * or promote products derived from this software without specific prior 23 1.1 kochi * written permission. 24 1.1 kochi * 25 1.1 kochi * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26 1.1 kochi * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 1.1 kochi * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 1.1 kochi * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29 1.1 kochi * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 1.1 kochi * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 1.1 kochi * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 1.1 kochi * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 1.1 kochi * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 1.1 kochi * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 1.1 kochi * POSSIBILITY OF SUCH DAMAGE. 36 1.1 kochi */ 37 1.1 kochi 38 1.1 kochi /*- 39 1.1 kochi * Copyright (c) 2000 Michael Smith 40 1.1 kochi * Copyright (c) 2000 BSDi 41 1.1 kochi * All rights reserved. 42 1.1 kochi * 43 1.1 kochi * Redistribution and use in source and binary forms, with or without 44 1.1 kochi * modification, are permitted provided that the following conditions 45 1.1 kochi * are met: 46 1.1 kochi * 1. Redistributions of source code must retain the above copyright 47 1.1 kochi * notice, this list of conditions and the following disclaimer. 48 1.1 kochi * 2. Redistributions in binary form must reproduce the above copyright 49 1.1 kochi * notice, this list of conditions and the following disclaimer in the 50 1.1 kochi * documentation and/or other materials provided with the distribution. 51 1.1 kochi * 52 1.1 kochi * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 53 1.1 kochi * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 54 1.1 kochi * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 55 1.1 kochi * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 56 1.1 kochi * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57 1.1 kochi * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58 1.1 kochi * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 1.1 kochi * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60 1.1 kochi * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61 1.1 kochi * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62 1.1 kochi * SUCH DAMAGE. 63 1.1 kochi */ 64 1.1 kochi 65 1.1 kochi /* 66 1.1 kochi * OS Services Layer 67 1.1 kochi * 68 1.1 kochi * 6.4: Mutual Exclusion and Synchronization 69 1.1 kochi */ 70 1.1 kochi 71 1.1 kochi #include <sys/cdefs.h> 72 1.13 jmcneill __KERNEL_RCSID(0, "$NetBSD: OsdSynch.c,v 1.13 2009/08/18 16:41:02 jmcneill Exp $"); 73 1.1 kochi 74 1.1 kochi #include <sys/param.h> 75 1.1 kochi #include <sys/malloc.h> 76 1.4 xtraeme #include <sys/mutex.h> 77 1.4 xtraeme #include <sys/condvar.h> 78 1.1 kochi #include <sys/kernel.h> 79 1.1 kochi #include <sys/proc.h> 80 1.1 kochi 81 1.11 jmcneill extern int acpi_suspended; 82 1.11 jmcneill 83 1.1 kochi #include <dev/acpi/acpica.h> 84 1.1 kochi 85 1.1 kochi MALLOC_DECLARE(M_ACPI); 86 1.1 kochi 87 1.1 kochi #define _COMPONENT ACPI_OS_SERVICES 88 1.1 kochi ACPI_MODULE_NAME("SYNCH") 89 1.1 kochi 90 1.1 kochi /* 91 1.1 kochi * Simple counting semaphore implemented using a mutex. This is 92 1.1 kochi * subsequently used in the OSI code to implement a mutex. Go figure. 93 1.1 kochi */ 94 1.1 kochi struct acpi_semaphore { 95 1.4 xtraeme kcondvar_t as_cv; 96 1.4 xtraeme kmutex_t as_slock; 97 1.1 kochi UINT32 as_units; 98 1.1 kochi UINT32 as_maxunits; 99 1.1 kochi }; 100 1.1 kochi 101 1.1 kochi struct acpi_lock { 102 1.4 xtraeme kmutex_t al_slock; 103 1.1 kochi }; 104 1.1 kochi 105 1.1 kochi /* 106 1.1 kochi * AcpiOsCreateSemaphore: 107 1.1 kochi * 108 1.1 kochi * Create a semaphore. 109 1.1 kochi */ 110 1.1 kochi ACPI_STATUS 111 1.1 kochi AcpiOsCreateSemaphore(UINT32 MaxUnits, UINT32 InitialUnits, 112 1.1 kochi ACPI_HANDLE *OutHandle) 113 1.1 kochi { 114 1.1 kochi struct acpi_semaphore *as; 115 1.1 kochi 116 1.1 kochi if (OutHandle == NULL) 117 1.13 jmcneill return AE_BAD_PARAMETER; 118 1.1 kochi if (InitialUnits > MaxUnits) 119 1.13 jmcneill return AE_BAD_PARAMETER; 120 1.1 kochi 121 1.1 kochi as = malloc(sizeof(*as), M_ACPI, M_NOWAIT); 122 1.1 kochi if (as == NULL) 123 1.13 jmcneill return AE_NO_MEMORY; 124 1.1 kochi 125 1.8 ad mutex_init(&as->as_slock, MUTEX_DEFAULT, IPL_NONE); 126 1.5 xtraeme cv_init(&as->as_cv, "acpisem"); 127 1.1 kochi as->as_units = InitialUnits; 128 1.1 kochi as->as_maxunits = MaxUnits; 129 1.1 kochi 130 1.1 kochi ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, 131 1.1 kochi "created semaphore %p max %u initial %u\n", 132 1.1 kochi as, as->as_maxunits, as->as_units)); 133 1.1 kochi 134 1.1 kochi *OutHandle = (ACPI_HANDLE) as; 135 1.13 jmcneill return AE_OK; 136 1.1 kochi } 137 1.1 kochi 138 1.1 kochi /* 139 1.1 kochi * AcpiOsDeleteSemaphore: 140 1.1 kochi * 141 1.1 kochi * Delete a semaphore. 142 1.1 kochi */ 143 1.1 kochi ACPI_STATUS 144 1.1 kochi AcpiOsDeleteSemaphore(ACPI_HANDLE Handle) 145 1.1 kochi { 146 1.1 kochi struct acpi_semaphore *as = (void *) Handle; 147 1.1 kochi 148 1.1 kochi if (as == NULL) 149 1.13 jmcneill return AE_BAD_PARAMETER; 150 1.1 kochi 151 1.7 ad cv_destroy(&as->as_cv); 152 1.6 xtraeme mutex_destroy(&as->as_slock); 153 1.1 kochi free(as, M_ACPI); 154 1.1 kochi 155 1.1 kochi ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "destroyed semaphore %p\n", as)); 156 1.1 kochi 157 1.13 jmcneill return AE_OK; 158 1.1 kochi } 159 1.1 kochi 160 1.1 kochi /* 161 1.1 kochi * AcpiOsWaitSemaphore: 162 1.1 kochi * 163 1.1 kochi * Wait for units from a semaphore. 164 1.1 kochi */ 165 1.1 kochi ACPI_STATUS 166 1.9 jmcneill AcpiOsWaitSemaphore(ACPI_SEMAPHORE Handle, UINT32 Units, UINT16 Timeout) 167 1.1 kochi { 168 1.1 kochi struct acpi_semaphore *as = (void *) Handle; 169 1.1 kochi ACPI_STATUS rv; 170 1.1 kochi int timo, error; 171 1.1 kochi 172 1.1 kochi /* 173 1.1 kochi * This implementation has a bug: It has to stall for the entire 174 1.1 kochi * timeout before it will return AE_TIME. A better implementation 175 1.1 kochi * would adjust the amount of time left after being awakened. 176 1.1 kochi */ 177 1.1 kochi 178 1.1 kochi if (as == NULL) 179 1.13 jmcneill return AE_BAD_PARAMETER; 180 1.12 drochner if (cold || doing_shutdown || acpi_suspended) 181 1.13 jmcneill return AE_OK; 182 1.1 kochi 183 1.1 kochi /* A timeout of 0xFFFF means "forever". */ 184 1.1 kochi if (Timeout == 0xFFFF) 185 1.1 kochi timo = 0; 186 1.1 kochi else { 187 1.1 kochi /* Compute the timeout using uSec per tick. */ 188 1.1 kochi timo = (Timeout * 1000) / (1000000 / hz); 189 1.1 kochi if (timo <= 0) 190 1.1 kochi timo = 1; 191 1.1 kochi } 192 1.1 kochi 193 1.4 xtraeme mutex_enter(&as->as_slock); 194 1.1 kochi 195 1.1 kochi ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, 196 1.1 kochi "get %d units from semaphore %p (has %d) timeout %d\n", 197 1.1 kochi Units, as, as->as_units, Timeout)); 198 1.1 kochi 199 1.1 kochi for (;;) { 200 1.1 kochi if (as->as_units >= Units) { 201 1.1 kochi as->as_units -= Units; 202 1.1 kochi rv = AE_OK; 203 1.1 kochi break; 204 1.1 kochi } 205 1.1 kochi 206 1.1 kochi ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, 207 1.1 kochi "semaphore blocked, sleeping %d ticks\n", timo)); 208 1.1 kochi 209 1.5 xtraeme error = cv_timedwait(&as->as_cv, &as->as_slock, timo); 210 1.1 kochi if (error == EWOULDBLOCK) { 211 1.1 kochi rv = AE_TIME; 212 1.1 kochi break; 213 1.1 kochi } 214 1.1 kochi } 215 1.1 kochi 216 1.4 xtraeme mutex_exit(&as->as_slock); 217 1.1 kochi 218 1.13 jmcneill return rv; 219 1.1 kochi } 220 1.1 kochi 221 1.1 kochi /* 222 1.1 kochi * AcpiOsSignalSemaphore: 223 1.1 kochi * 224 1.1 kochi * Send units to a semaphore. 225 1.1 kochi */ 226 1.1 kochi ACPI_STATUS 227 1.1 kochi AcpiOsSignalSemaphore(ACPI_HANDLE Handle, UINT32 Units) 228 1.1 kochi { 229 1.1 kochi struct acpi_semaphore *as = (void *) Handle; 230 1.1 kochi 231 1.1 kochi if (as == NULL) 232 1.13 jmcneill return AE_BAD_PARAMETER; 233 1.1 kochi 234 1.4 xtraeme mutex_enter(&as->as_slock); 235 1.1 kochi 236 1.1 kochi ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, 237 1.1 kochi "return %d units to semaphore %p (has %d)\n", 238 1.1 kochi Units, as, as->as_units)); 239 1.1 kochi 240 1.1 kochi as->as_units += Units; 241 1.1 kochi if (as->as_units > as->as_maxunits) 242 1.1 kochi as->as_units = as->as_maxunits; 243 1.4 xtraeme cv_broadcast(&as->as_cv); 244 1.1 kochi 245 1.4 xtraeme mutex_exit(&as->as_slock); 246 1.1 kochi 247 1.13 jmcneill return AE_OK; 248 1.1 kochi } 249 1.1 kochi 250 1.1 kochi /* 251 1.1 kochi * AcpiOsCreateLock: 252 1.1 kochi * 253 1.1 kochi * Create a lock. 254 1.1 kochi */ 255 1.1 kochi ACPI_STATUS 256 1.1 kochi AcpiOsCreateLock(ACPI_HANDLE *OutHandle) 257 1.1 kochi { 258 1.1 kochi struct acpi_lock *al; 259 1.1 kochi 260 1.1 kochi if (OutHandle == NULL) 261 1.13 jmcneill return AE_BAD_PARAMETER; 262 1.1 kochi 263 1.1 kochi al = malloc(sizeof(*al), M_ACPI, M_NOWAIT); 264 1.1 kochi if (al == NULL) 265 1.13 jmcneill return AE_NO_MEMORY; 266 1.1 kochi 267 1.8 ad mutex_init(&al->al_slock, MUTEX_DEFAULT, IPL_VM); 268 1.1 kochi 269 1.1 kochi ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, 270 1.1 kochi "created lock %p\n", al)); 271 1.1 kochi 272 1.1 kochi *OutHandle = (ACPI_HANDLE) al; 273 1.13 jmcneill return AE_OK; 274 1.1 kochi } 275 1.1 kochi 276 1.1 kochi /* 277 1.1 kochi * AcpiOsDeleteLock: 278 1.1 kochi * 279 1.1 kochi * Delete a lock. 280 1.1 kochi */ 281 1.1 kochi void 282 1.9 jmcneill AcpiOsDeleteLock(ACPI_SPINLOCK Handle) 283 1.1 kochi { 284 1.1 kochi struct acpi_lock *al = (void *) Handle; 285 1.1 kochi 286 1.1 kochi if (al == NULL) 287 1.1 kochi return; 288 1.1 kochi 289 1.6 xtraeme mutex_destroy(&al->al_slock); 290 1.1 kochi free(al, M_ACPI); 291 1.1 kochi 292 1.1 kochi ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "destroyed lock %p\n", al)); 293 1.1 kochi 294 1.1 kochi return; 295 1.1 kochi } 296 1.1 kochi 297 1.1 kochi /* 298 1.1 kochi * AcpiOsAcquireLock: 299 1.1 kochi * 300 1.1 kochi * Acquire a lock. 301 1.1 kochi */ 302 1.13 jmcneill ACPI_CPU_FLAGS 303 1.9 jmcneill AcpiOsAcquireLock(ACPI_SPINLOCK Handle) 304 1.1 kochi { 305 1.1 kochi struct acpi_lock *al = (void *) Handle; 306 1.1 kochi 307 1.1 kochi if (al == NULL) 308 1.1 kochi return 0; 309 1.1 kochi 310 1.4 xtraeme mutex_enter(&al->al_slock); 311 1.1 kochi 312 1.1 kochi return 0; 313 1.1 kochi } 314 1.1 kochi 315 1.1 kochi /* 316 1.1 kochi * AcpiOsReleaseLock: 317 1.1 kochi * 318 1.1 kochi * Release a lock. 319 1.1 kochi */ 320 1.1 kochi void 321 1.13 jmcneill AcpiOsReleaseLock(ACPI_HANDLE Handle, ACPI_CPU_FLAGS Flags) 322 1.1 kochi { 323 1.1 kochi struct acpi_lock *al = (void *) Handle; 324 1.1 kochi 325 1.1 kochi if (al == NULL) 326 1.1 kochi return; 327 1.1 kochi 328 1.4 xtraeme mutex_exit(&al->al_slock); 329 1.1 kochi 330 1.1 kochi return; 331 1.1 kochi } 332