diff options
| -rw-r--r-- | drivers/acpi/acpica/tbxface.c | 42 | ||||
| -rw-r--r-- | drivers/acpi/acpica/tbxfload.c | 178 | ||||
| -rw-r--r-- | include/acpi/acpixf.h | 13 |
3 files changed, 187 insertions, 46 deletions
diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index 472a91ccde95..9bf34f76d936 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c | |||
| @@ -215,48 +215,6 @@ acpi_status acpi_reallocate_root_table(void) | |||
| 215 | 215 | ||
| 216 | /******************************************************************************* | 216 | /******************************************************************************* |
| 217 | * | 217 | * |
| 218 | * FUNCTION: acpi_load_table | ||
| 219 | * | ||
| 220 | * PARAMETERS: table_ptr - pointer to a buffer containing the entire | ||
| 221 | * table to be loaded | ||
| 222 | * | ||
| 223 | * RETURN: Status | ||
| 224 | * | ||
| 225 | * DESCRIPTION: This function is called to load a table from the caller's | ||
| 226 | * buffer. The buffer must contain an entire ACPI Table including | ||
| 227 | * a valid header. The header fields will be verified, and if it | ||
| 228 | * is determined that the table is invalid, the call will fail. | ||
| 229 | * | ||
| 230 | ******************************************************************************/ | ||
| 231 | acpi_status acpi_load_table(struct acpi_table_header *table_ptr) | ||
| 232 | { | ||
| 233 | acpi_status status; | ||
| 234 | u32 table_index; | ||
| 235 | struct acpi_table_desc table_desc; | ||
| 236 | |||
| 237 | if (!table_ptr) | ||
| 238 | return AE_BAD_PARAMETER; | ||
| 239 | |||
| 240 | ACPI_MEMSET(&table_desc, 0, sizeof(struct acpi_table_desc)); | ||
| 241 | table_desc.pointer = table_ptr; | ||
| 242 | table_desc.length = table_ptr->length; | ||
| 243 | table_desc.flags = ACPI_TABLE_ORIGIN_UNKNOWN; | ||
| 244 | |||
| 245 | /* | ||
| 246 | * Install the new table into the local data structures | ||
| 247 | */ | ||
| 248 | status = acpi_tb_add_table(&table_desc, &table_index); | ||
| 249 | if (ACPI_FAILURE(status)) { | ||
| 250 | return status; | ||
| 251 | } | ||
| 252 | status = acpi_ns_load_table(table_index, acpi_gbl_root_node); | ||
| 253 | return status; | ||
| 254 | } | ||
| 255 | |||
| 256 | ACPI_EXPORT_SYMBOL(acpi_load_table) | ||
| 257 | |||
| 258 | /******************************************************************************* | ||
| 259 | * | ||
| 260 | * FUNCTION: acpi_get_table_header | 218 | * FUNCTION: acpi_get_table_header |
| 261 | * | 219 | * |
| 262 | * PARAMETERS: Signature - ACPI signature of needed table | 220 | * PARAMETERS: Signature - ACPI signature of needed table |
diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c index 54a01ae94f8b..f87cc63e69a1 100644 --- a/drivers/acpi/acpica/tbxfload.c +++ b/drivers/acpi/acpica/tbxfload.c | |||
| @@ -199,6 +199,184 @@ static acpi_status acpi_tb_load_namespace(void) | |||
| 199 | return_ACPI_STATUS(status); | 199 | return_ACPI_STATUS(status); |
| 200 | } | 200 | } |
| 201 | 201 | ||
| 202 | /******************************************************************************* | ||
| 203 | * | ||
| 204 | * FUNCTION: acpi_load_table | ||
| 205 | * | ||
| 206 | * PARAMETERS: table - Pointer to a buffer containing the ACPI | ||
| 207 | * table to be loaded. | ||
| 208 | * | ||
| 209 | * RETURN: Status | ||
| 210 | * | ||
| 211 | * DESCRIPTION: Dynamically load an ACPI table from the caller's buffer. Must | ||
| 212 | * be a valid ACPI table with a valid ACPI table header. | ||
| 213 | * Note1: Mainly intended to support hotplug addition of SSDTs. | ||
| 214 | * Note2: Does not copy the incoming table. User is reponsible | ||
| 215 | * to ensure that the table is not deleted or unmapped. | ||
| 216 | * | ||
| 217 | ******************************************************************************/ | ||
| 218 | |||
| 219 | acpi_status acpi_load_table(struct acpi_table_header *table) | ||
| 220 | { | ||
| 221 | acpi_status status; | ||
| 222 | struct acpi_table_desc table_desc; | ||
| 223 | u32 table_index; | ||
| 224 | |||
| 225 | ACPI_FUNCTION_TRACE(acpi_load_table); | ||
| 226 | |||
| 227 | /* Parameter validation */ | ||
| 228 | |||
| 229 | if (!table) { | ||
| 230 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
| 231 | } | ||
| 232 | |||
| 233 | /* Init local table descriptor */ | ||
| 234 | |||
| 235 | ACPI_MEMSET(&table_desc, 0, sizeof(struct acpi_table_desc)); | ||
| 236 | table_desc.address = ACPI_PTR_TO_PHYSADDR(table); | ||
| 237 | table_desc.pointer = table; | ||
| 238 | table_desc.length = table->length; | ||
| 239 | table_desc.flags = ACPI_TABLE_ORIGIN_UNKNOWN; | ||
| 240 | |||
| 241 | /* Must acquire the interpreter lock during this operation */ | ||
| 242 | |||
| 243 | status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); | ||
| 244 | if (ACPI_FAILURE(status)) { | ||
| 245 | return_ACPI_STATUS(status); | ||
| 246 | } | ||
| 247 | |||
| 248 | /* Install the table and load it into the namespace */ | ||
| 249 | |||
| 250 | ACPI_INFO((AE_INFO, "Host-directed Dynamic ACPI Table Load:")); | ||
| 251 | status = acpi_tb_add_table(&table_desc, &table_index); | ||
| 252 | if (ACPI_FAILURE(status)) { | ||
| 253 | goto unlock_and_exit; | ||
| 254 | } | ||
| 255 | |||
| 256 | status = acpi_ns_load_table(table_index, acpi_gbl_root_node); | ||
| 257 | |||
| 258 | /* Invoke table handler if present */ | ||
| 259 | |||
| 260 | if (acpi_gbl_table_handler) { | ||
| 261 | (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, table, | ||
| 262 | acpi_gbl_table_handler_context); | ||
| 263 | } | ||
| 264 | |||
| 265 | unlock_and_exit: | ||
| 266 | (void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); | ||
| 267 | return_ACPI_STATUS(status); | ||
| 268 | } | ||
| 269 | |||
| 270 | ACPI_EXPORT_SYMBOL(acpi_load_table) | ||
| 271 | |||
| 272 | /******************************************************************************* | ||
| 273 | * | ||
| 274 | * FUNCTION: acpi_unload_parent_table | ||
| 275 | * | ||
| 276 | * PARAMETERS: object - Handle to any namespace object owned by | ||
| 277 | * the table to be unloaded | ||
| 278 | * | ||
| 279 | * RETURN: Status | ||
| 280 | * | ||
| 281 | * DESCRIPTION: Via any namespace object within an SSDT or OEMx table, unloads | ||
| 282 | * the table and deletes all namespace objects associated with | ||
| 283 | * that table. Unloading of the DSDT is not allowed. | ||
| 284 | * Note: Mainly intended to support hotplug removal of SSDTs. | ||
| 285 | * | ||
| 286 | ******************************************************************************/ | ||
| 287 | acpi_status acpi_unload_parent_table(acpi_handle object) | ||
| 288 | { | ||
| 289 | struct acpi_namespace_node *node = | ||
| 290 | ACPI_CAST_PTR(struct acpi_namespace_node, object); | ||
| 291 | acpi_status status = AE_NOT_EXIST; | ||
| 292 | acpi_owner_id owner_id; | ||
| 293 | u32 i; | ||
| 294 | |||
| 295 | ACPI_FUNCTION_TRACE(acpi_unload_parent_table); | ||
| 296 | |||
| 297 | /* Parameter validation */ | ||
| 298 | |||
| 299 | if (!object) { | ||
| 300 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
| 301 | } | ||
| 302 | |||
| 303 | /* | ||
| 304 | * The node owner_id is currently the same as the parent table ID. | ||
| 305 | * However, this could change in the future. | ||
| 306 | */ | ||
| 307 | owner_id = node->owner_id; | ||
| 308 | if (!owner_id) { | ||
| 309 | |||
| 310 | /* owner_id==0 means DSDT is the owner. DSDT cannot be unloaded */ | ||
| 311 | |||
| 312 | return_ACPI_STATUS(AE_TYPE); | ||
| 313 | } | ||
| 314 | |||
| 315 | /* Must acquire the interpreter lock during this operation */ | ||
| 316 | |||
| 317 | status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); | ||
| 318 | if (ACPI_FAILURE(status)) { | ||
| 319 | return_ACPI_STATUS(status); | ||
| 320 | } | ||
| 321 | |||
| 322 | /* Find the table in the global table list */ | ||
| 323 | |||
| 324 | for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) { | ||
| 325 | if (owner_id != acpi_gbl_root_table_list.tables[i].owner_id) { | ||
| 326 | continue; | ||
| 327 | } | ||
| 328 | |||
| 329 | /* | ||
| 330 | * Allow unload of SSDT and OEMx tables only. Do not allow unload | ||
| 331 | * of the DSDT. No other types of tables should get here, since | ||
| 332 | * only these types can contain AML and thus are the only types | ||
| 333 | * that can create namespace objects. | ||
| 334 | */ | ||
| 335 | if (ACPI_COMPARE_NAME | ||
| 336 | (acpi_gbl_root_table_list.tables[i].signature.ascii, | ||
| 337 | ACPI_SIG_DSDT)) { | ||
| 338 | status = AE_TYPE; | ||
| 339 | break; | ||
| 340 | } | ||
| 341 | |||
| 342 | /* Ensure the table is actually loaded */ | ||
| 343 | |||
| 344 | if (!acpi_tb_is_table_loaded(i)) { | ||
| 345 | status = AE_NOT_EXIST; | ||
| 346 | break; | ||
| 347 | } | ||
| 348 | |||
| 349 | /* Invoke table handler if present */ | ||
| 350 | |||
| 351 | if (acpi_gbl_table_handler) { | ||
| 352 | (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_UNLOAD, | ||
| 353 | acpi_gbl_root_table_list. | ||
| 354 | tables[i].pointer, | ||
| 355 | acpi_gbl_table_handler_context); | ||
| 356 | } | ||
| 357 | |||
| 358 | /* | ||
| 359 | * Delete all namespace objects owned by this table. Note that | ||
| 360 | * these objects can appear anywhere in the namespace by virtue | ||
| 361 | * of the AML "Scope" operator. Thus, we need to track ownership | ||
| 362 | * by an ID, not simply a position within the hierarchy. | ||
| 363 | */ | ||
| 364 | status = acpi_tb_delete_namespace_by_owner(i); | ||
| 365 | if (ACPI_FAILURE(status)) { | ||
| 366 | break; | ||
| 367 | } | ||
| 368 | |||
| 369 | status = acpi_tb_release_owner_id(i); | ||
| 370 | acpi_tb_set_table_loaded_flag(i, FALSE); | ||
| 371 | break; | ||
| 372 | } | ||
| 373 | |||
| 374 | (void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); | ||
| 375 | return_ACPI_STATUS(status); | ||
| 376 | } | ||
| 377 | |||
| 378 | ACPI_EXPORT_SYMBOL(acpi_unload_parent_table) | ||
| 379 | |||
| 202 | static int __init acpi_no_auto_ssdt_setup(char *s) { | 380 | static int __init acpi_no_auto_ssdt_setup(char *s) { |
| 203 | 381 | ||
| 204 | printk(KERN_NOTICE "ACPI: SSDT auto-load disabled\n"); | 382 | printk(KERN_NOTICE "ACPI: SSDT auto-load disabled\n"); |
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 8f83f95c109d..079bb9067c91 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h | |||
| @@ -154,15 +154,20 @@ void *acpi_callocate(u32 size); | |||
| 154 | void acpi_free(void *address); | 154 | void acpi_free(void *address); |
| 155 | 155 | ||
| 156 | /* | 156 | /* |
| 157 | * ACPI table manipulation interfaces | 157 | * ACPI table load/unload interfaces |
| 158 | */ | 158 | */ |
| 159 | acpi_status acpi_reallocate_root_table(void); | 159 | acpi_status acpi_load_table(struct acpi_table_header *table); |
| 160 | 160 | ||
| 161 | acpi_status acpi_find_root_pointer(acpi_size *rsdp_address); | 161 | acpi_status acpi_unload_parent_table(acpi_handle object); |
| 162 | 162 | ||
| 163 | acpi_status acpi_load_tables(void); | 163 | acpi_status acpi_load_tables(void); |
| 164 | 164 | ||
| 165 | acpi_status acpi_load_table(struct acpi_table_header *table_ptr); | 165 | /* |
| 166 | * ACPI table manipulation interfaces | ||
| 167 | */ | ||
| 168 | acpi_status acpi_reallocate_root_table(void); | ||
| 169 | |||
| 170 | acpi_status acpi_find_root_pointer(acpi_size *rsdp_address); | ||
| 166 | 171 | ||
| 167 | acpi_status acpi_unload_table_id(acpi_owner_id id); | 172 | acpi_status acpi_unload_table_id(acpi_owner_id id); |
| 168 | 173 | ||
