Example #1
0
acpi_status
acpi_ev_attach_region (
	union acpi_operand_object       *handler_obj,
	union acpi_operand_object       *region_obj,
	u8                              acpi_ns_is_locked)
{
	acpi_status                     status;
	acpi_status                     status2;


	ACPI_FUNCTION_TRACE ("ev_attach_region");


	ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
		"Adding Region %p to address handler %p [%s]\n",
		region_obj, handler_obj, acpi_ut_get_region_name (region_obj->region.space_id)));


	/* Link this region to the front of the handler's list */

	region_obj->region.next = handler_obj->address_space.region_list;
	handler_obj->address_space.region_list = region_obj;

	/* Install the region's handler */

	if (region_obj->region.address_space) {
		return_ACPI_STATUS (AE_ALREADY_EXISTS);
	}

	region_obj->region.address_space = handler_obj;
	acpi_ut_add_reference (handler_obj);

	/*
	 * Tell all users that this region is usable by running the _REG
	 * method
	 */
	if (acpi_ns_is_locked) {
		status2 = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
		if (ACPI_FAILURE (status2)) {
			return_ACPI_STATUS (status2);
		}
	}

	status = acpi_ev_execute_reg_method (region_obj, 1);

	if (acpi_ns_is_locked) {
		status2 = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
		if (ACPI_FAILURE (status2)) {
			return_ACPI_STATUS (status2);
		}
	}

	return_ACPI_STATUS (status);
}
Example #2
0
static acpi_status
acpi_ev_reg_run(acpi_handle obj_handle,
		u32 level, void *context, void **return_value)
{
	union acpi_operand_object *obj_desc;
	struct acpi_namespace_node *node;
	acpi_status status;
	struct acpi_reg_walk_info *info;

	info = ACPI_CAST_PTR(struct acpi_reg_walk_info, context);

	/* Convert and validate the device handle */

	node = acpi_ns_validate_handle(obj_handle);
	if (!node) {
		return (AE_BAD_PARAMETER);
	}

	/*
	 * We only care about regions.and objects that are allowed to have address
	 * space handlers
	 */
	if ((node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) {
		return (AE_OK);
	}

	/* Check for an existing internal object */

	obj_desc = acpi_ns_get_attached_object(node);
	if (!obj_desc) {

		/* No object, just exit */

		return (AE_OK);
	}

	/* Object is a Region */

	if (obj_desc->region.space_id != info->space_id) {

		/* This region is for a different address space, just ignore it */

		return (AE_OK);
	}

	info->reg_run_count++;
	status = acpi_ev_execute_reg_method(obj_desc, ACPI_REG_CONNECT);
	return (status);
}
Example #3
0
ACPI_STATUS
acpi_ev_associate_region_and_handler (
	ACPI_OPERAND_OBJECT     *handler_obj,
	ACPI_OPERAND_OBJECT     *region_obj,
	u8                      acpi_ns_is_locked)
{
	ACPI_STATUS     status;


	ACPI_ASSERT (region_obj->region.space_id == handler_obj->addr_handler.space_id);
	ACPI_ASSERT (region_obj->region.addr_handler == 0);

	/*
	 *  Link this region to the front of the handler's list
	 */

	region_obj->region.next = handler_obj->addr_handler.region_list;
	handler_obj->addr_handler.region_list = region_obj;

	/*
	 *  set the region's handler
	 */

/*
	Handler_obj->Common.Reference_count =
			  (u16) (Handler_obj->Common.Reference_count +
			  Region_obj->Common.Reference_count - 1);
*/
	region_obj->region.addr_handler = handler_obj;

	/*
	 *  Last thing, tell all users that this region is usable
	 */
	if (acpi_ns_is_locked) {
		acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
	}

	status = acpi_ev_execute_reg_method (region_obj, 1);

	if (acpi_ns_is_locked) {
		acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
	}

	return (status);
}
Example #4
0
void
acpi_ev_detach_region(union acpi_operand_object *region_obj,
                      u8 acpi_ns_is_locked)
{
    union acpi_operand_object *handler_obj;
    union acpi_operand_object *obj_desc;
    union acpi_operand_object *start_desc;
    union acpi_operand_object **last_obj_ptr;
    acpi_adr_space_setup region_setup;
    void **region_context;
    union acpi_operand_object *region_obj2;
    acpi_status status;

    ACPI_FUNCTION_TRACE(ev_detach_region);

    region_obj2 = acpi_ns_get_secondary_object(region_obj);
    if (!region_obj2) {
        return_VOID;
    }
    region_context = &region_obj2->extra.region_context;

    /* Get the address handler from the region object */

    handler_obj = region_obj->region.handler;
    if (!handler_obj) {

        /* This region has no handler, all done */

        return_VOID;
    }

    /* Find this region in the handler's list */

    obj_desc = handler_obj->address_space.region_list;
    start_desc = obj_desc;
    last_obj_ptr = &handler_obj->address_space.region_list;

    while (obj_desc) {

        /* Is this the correct Region? */

        if (obj_desc == region_obj) {
            ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
                              "Removing Region %p from address handler %p\n",
                              region_obj, handler_obj));

            /* This is it, remove it from the handler's list */

            *last_obj_ptr = obj_desc->region.next;
            obj_desc->region.next = NULL;	/* Must clear field */

            if (acpi_ns_is_locked) {
                status =
                    acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
                if (ACPI_FAILURE(status)) {
                    return_VOID;
                }
            }

            /* Now stop region accesses by executing the _REG method */

            status =
                acpi_ev_execute_reg_method(region_obj,
                                           ACPI_REG_DISCONNECT);
            if (ACPI_FAILURE(status)) {
                ACPI_EXCEPTION((AE_INFO, status,
                                "from region _REG, [%s]",
                                acpi_ut_get_region_name
                                (region_obj->region.space_id)));
            }

            if (acpi_ns_is_locked) {
                status =
                    acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
                if (ACPI_FAILURE(status)) {
                    return_VOID;
                }
            }

            /*
             * If the region has been activated, call the setup handler with
             * the deactivate notification
             */
            if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) {
                region_setup = handler_obj->address_space.setup;
                status =
                    region_setup(region_obj,
                                 ACPI_REGION_DEACTIVATE,
                                 handler_obj->address_space.
                                 context, region_context);

                /*
                 * region_context should have been released by the deactivate
                 * operation. We don't need access to it anymore here.
                 */
                if (region_context) {
                    *region_context = NULL;
                }

                /* Init routine may fail, Just ignore errors */

                if (ACPI_FAILURE(status)) {
                    ACPI_EXCEPTION((AE_INFO, status,
                                    "from region handler - deactivate, [%s]",
                                    acpi_ut_get_region_name
                                    (region_obj->region.
                                     space_id)));
                }

                region_obj->region.flags &=
                    ~(AOPOBJ_SETUP_COMPLETE);
            }

            /*
             * Remove handler reference in the region
             *
             * NOTE: this doesn't mean that the region goes away, the region
             * is just inaccessible as indicated to the _REG method
             *
             * If the region is on the handler's list, this must be the
             * region's handler
             */
            region_obj->region.handler = NULL;
            acpi_ut_remove_reference(handler_obj);

            return_VOID;
        }

        /* Walk the linked list of handlers */

        last_obj_ptr = &obj_desc->region.next;
        obj_desc = obj_desc->region.next;

        /* Prevent infinite loop if list is corrupted */

        if (obj_desc == start_desc) {
            ACPI_ERROR((AE_INFO,
                        "Circular handler list in region object %p",
                        region_obj));
            return_VOID;
        }
    }

    /* If we get here, the region was not in the handler's region list */

    ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
                      "Cannot remove region %p from address handler %p\n",
                      region_obj, handler_obj));

    return_VOID;
}
Example #5
0
acpi_status
acpi_ev_initialize_region(union acpi_operand_object *region_obj,
			  u8 acpi_ns_locked)
{
	union acpi_operand_object *handler_obj;
	union acpi_operand_object *obj_desc;
	acpi_adr_space_type space_id;
	struct acpi_namespace_node *node;
	acpi_status status;
	struct acpi_namespace_node *method_node;
	acpi_name *reg_name_ptr = (acpi_name *) METHOD_NAME__REG;
	union acpi_operand_object *region_obj2;

	ACPI_FUNCTION_TRACE_U32(ev_initialize_region, acpi_ns_locked);

	if (!region_obj) {
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	}

	if (region_obj->common.flags & AOPOBJ_OBJECT_INITIALIZED) {
		return_ACPI_STATUS(AE_OK);
	}

	region_obj2 = acpi_ns_get_secondary_object(region_obj);
	if (!region_obj2) {
		return_ACPI_STATUS(AE_NOT_EXIST);
	}

	node = acpi_ns_get_parent_node(region_obj->region.node);
	space_id = region_obj->region.space_id;

	/* Setup defaults */

	region_obj->region.handler = NULL;
	region_obj2->extra.method_REG = NULL;
	region_obj->common.flags &= ~(AOPOBJ_SETUP_COMPLETE);
	region_obj->common.flags |= AOPOBJ_OBJECT_INITIALIZED;

	/* Find any "_REG" method associated with this region definition */

	status =
	    acpi_ns_search_one_scope(*reg_name_ptr, node, ACPI_TYPE_METHOD,
				     &method_node);
	if (ACPI_SUCCESS(status)) {
		/*
		 * The _REG method is optional and there can be only one per region
		 * definition.  This will be executed when the handler is attached
		 * or removed
		 */
		region_obj2->extra.method_REG = method_node;
	}

	/*
	 * The following loop depends upon the root Node having no parent
	 * ie: acpi_gbl_root_node->parent_entry being set to NULL
	 */
	while (node) {

		/* Check to see if a handler exists */

		handler_obj = NULL;
		obj_desc = acpi_ns_get_attached_object(node);
		if (obj_desc) {

			/* Can only be a handler if the object exists */

			switch (node->type) {
			case ACPI_TYPE_DEVICE:

				handler_obj = obj_desc->device.handler;
				break;

			case ACPI_TYPE_PROCESSOR:

				handler_obj = obj_desc->processor.handler;
				break;

			case ACPI_TYPE_THERMAL:

				handler_obj = obj_desc->thermal_zone.handler;
				break;

			default:
				/* Ignore other objects */
				break;
			}

			while (handler_obj) {

				/* Is this handler of the correct type? */

				if (handler_obj->address_space.space_id ==
				    space_id) {

					/* Found correct handler */

					ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
							  "Found handler %p for region %p in obj %p\n",
							  handler_obj,
							  region_obj,
							  obj_desc));

					status =
					    acpi_ev_attach_region(handler_obj,
								  region_obj,
								  acpi_ns_locked);

					/*
					 * Tell all users that this region is usable by running the _REG
					 * method
					 */
					if (acpi_ns_locked) {
						status =
						    acpi_ut_release_mutex
						    (ACPI_MTX_NAMESPACE);
						if (ACPI_FAILURE(status)) {
							return_ACPI_STATUS
							    (status);
						}
					}

					status =
					    acpi_ev_execute_reg_method
					    (region_obj, 1);

					if (acpi_ns_locked) {
						status =
						    acpi_ut_acquire_mutex
						    (ACPI_MTX_NAMESPACE);
						if (ACPI_FAILURE(status)) {
							return_ACPI_STATUS
							    (status);
						}
					}

					return_ACPI_STATUS(AE_OK);
				}

				/* Try next handler in the list */

				handler_obj = handler_obj->address_space.next;
			}
		}

		/*
		 * This node does not have the handler we need;
		 * Pop up one level
		 */
		node = acpi_ns_get_parent_node(node);
	}

	/* If we get here, there is no handler for this region */

	ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
			  "No handler for RegionType %s(%X) (RegionObj %p)\n",
			  acpi_ut_get_region_name(space_id), space_id,
			  region_obj));

	return_ACPI_STATUS(AE_NOT_EXIST);
}
Example #6
0
acpi_status
acpi_ev_initialize_region(union acpi_operand_object *region_obj,
			  u8 acpi_ns_locked)
{
	union acpi_operand_object *handler_obj;
	union acpi_operand_object *obj_desc;
	acpi_adr_space_type space_id;
	struct acpi_namespace_node *node;
	acpi_status status;

	ACPI_FUNCTION_TRACE_U32(ev_initialize_region, acpi_ns_locked);

	if (!region_obj) {
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	}

	if (region_obj->common.flags & AOPOBJ_OBJECT_INITIALIZED) {
		return_ACPI_STATUS(AE_OK);
	}

	acpi_ev_associate_reg_method(region_obj);
	region_obj->common.flags |= AOPOBJ_OBJECT_INITIALIZED;

	node = region_obj->region.node->parent;
	space_id = region_obj->region.space_id;

	/*
	 * The following loop depends upon the root Node having no parent
	 * ie: acpi_gbl_root_node->Parent being set to NULL
	 */
	while (node) {

		/* Check to see if a handler exists */

		handler_obj = NULL;
		obj_desc = acpi_ns_get_attached_object(node);
		if (obj_desc) {

			/* Can only be a handler if the object exists */

			switch (node->type) {
			case ACPI_TYPE_DEVICE:
			case ACPI_TYPE_PROCESSOR:
			case ACPI_TYPE_THERMAL:

				handler_obj = obj_desc->common_notify.handler;
				break;

			case ACPI_TYPE_METHOD:
				/*
				 * If we are executing module level code, the original
				 * Node's object was replaced by this Method object and we
				 * saved the handler in the method object.
				 *
				 * See acpi_ns_exec_module_code
				 */
				if (obj_desc->method.
				    info_flags & ACPI_METHOD_MODULE_LEVEL) {
					handler_obj =
					    obj_desc->method.dispatch.handler;
				}
				break;

			default:

				/* Ignore other objects */

				break;
			}

			handler_obj =
			    acpi_ev_find_region_handler(space_id, handler_obj);
			if (handler_obj) {

				/* Found correct handler */

				ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
						  "Found handler %p for region %p in obj %p\n",
						  handler_obj, region_obj,
						  obj_desc));

				status =
				    acpi_ev_attach_region(handler_obj,
							  region_obj,
							  acpi_ns_locked);

				/*
				 * Tell all users that this region is usable by
				 * running the _REG method
				 */
				if (acpi_ns_locked) {
					status =
					    acpi_ut_release_mutex
					    (ACPI_MTX_NAMESPACE);
					if (ACPI_FAILURE(status)) {
						return_ACPI_STATUS(status);
					}
				}

				status =
				    acpi_ev_execute_reg_method(region_obj,
							       ACPI_REG_CONNECT);

				if (acpi_ns_locked) {
					status =
					    acpi_ut_acquire_mutex
					    (ACPI_MTX_NAMESPACE);
					if (ACPI_FAILURE(status)) {
						return_ACPI_STATUS(status);
					}
				}

				return_ACPI_STATUS(AE_OK);
			}
		}

		/* This node does not have the handler we need; Pop up one level */

		node = node->parent;
	}

	/* If we get here, there is no handler for this region */

	ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
			  "No handler for RegionType %s(%X) (RegionObj %p)\n",
			  acpi_ut_get_region_name(space_id), space_id,
			  region_obj));

	return_ACPI_STATUS(AE_NOT_EXIST);
}
Example #7
0
void
acpi_ev_detach_region(
	union acpi_operand_object       *region_obj,
	u8                              acpi_ns_is_locked)
{
	union acpi_operand_object       *handler_obj;
	union acpi_operand_object       *obj_desc;
	union acpi_operand_object       **last_obj_ptr;
	acpi_adr_space_setup            region_setup;
	void                            **region_context;
	union acpi_operand_object       *region_obj2;
	acpi_status                     status;


	ACPI_FUNCTION_TRACE ("ev_detach_region");


	region_obj2 = acpi_ns_get_secondary_object (region_obj);
	if (!region_obj2) {
		return_VOID;
	}
	region_context = &region_obj2->extra.region_context;

	/* Get the address handler from the region object */

	handler_obj = region_obj->region.address_space;
	if (!handler_obj) {
		/* This region has no handler, all done */

		return_VOID;
	}

	/* Find this region in the handler's list */

	obj_desc = handler_obj->address_space.region_list;
	last_obj_ptr = &handler_obj->address_space.region_list;

	while (obj_desc) {
		/* Is this the correct Region? */

		if (obj_desc == region_obj) {
			ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
				"Removing Region %p from address handler %p\n",
				region_obj, handler_obj));

			/* This is it, remove it from the handler's list */

			*last_obj_ptr = obj_desc->region.next;
			obj_desc->region.next = NULL;           /* Must clear field */

			if (acpi_ns_is_locked) {
				status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
				if (ACPI_FAILURE (status)) {
					return_VOID;
				}
			}

			/* Now stop region accesses by executing the _REG method */

			status = acpi_ev_execute_reg_method (region_obj, 0);
			if (ACPI_FAILURE (status)) {
				ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s from region _REG, [%s]\n",
					acpi_format_exception (status),
					acpi_ut_get_region_name (region_obj->region.space_id)));
			}

			if (acpi_ns_is_locked) {
				status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
				if (ACPI_FAILURE (status)) {
					return_VOID;
				}
			}

			/* Call the setup handler with the deactivate notification */

			region_setup = handler_obj->address_space.setup;
			status = region_setup (region_obj, ACPI_REGION_DEACTIVATE,
					  handler_obj->address_space.context, region_context);

			/* Init routine may fail, Just ignore errors */

			if (ACPI_FAILURE (status)) {
				ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s from region init, [%s]\n",
					acpi_format_exception (status),
					acpi_ut_get_region_name (region_obj->region.space_id)));
			}

			region_obj->region.flags &= ~(AOPOBJ_SETUP_COMPLETE);

			/*
			 * Remove handler reference in the region
			 *
			 * NOTE: this doesn't mean that the region goes away
			 * The region is just inaccessible as indicated to
			 * the _REG method
			 *
			 * If the region is on the handler's list
			 * this better be the region's handler
			 */
			region_obj->region.address_space = NULL;
			acpi_ut_remove_reference (handler_obj);

			return_VOID;
		}

		/* Walk the linked list of handlers */

		last_obj_ptr = &obj_desc->region.next;
		obj_desc = obj_desc->region.next;
	}

	/* If we get here, the region was not in the handler's region list */

	ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
		"Cannot remove region %p from address handler %p\n",
		region_obj, handler_obj));

	return_VOID;
}
Example #8
0
void
acpi_ev_disassociate_region_from_handler(
	ACPI_OPERAND_OBJECT     *region_obj,
	u8                      acpi_ns_is_locked)
{
	ACPI_OPERAND_OBJECT     *handler_obj;
	ACPI_OPERAND_OBJECT     *obj_desc;
	ACPI_OPERAND_OBJECT     **last_obj_ptr;
	ADDRESS_SPACE_SETUP     region_setup;
	void                    *region_context;
	ACPI_STATUS             status;


	region_context = region_obj->region.extra->extra.region_context;

	/*
	 *  Get the address handler from the region object
	 */

	handler_obj = region_obj->region.addr_handler;
	if (!handler_obj) {
		/*
		 *  This region has no handler, all done
		 */
		return;
	}


	/*
	 *  Find this region in the handler's list
	 */

	obj_desc = handler_obj->addr_handler.region_list;
	last_obj_ptr = &handler_obj->addr_handler.region_list;

	while (obj_desc) {
		/*
		 *  See if this is the one
		 */
		if (obj_desc == region_obj) {
			/*
			 *  This is it, remove it from the handler's list
			 */
			*last_obj_ptr = obj_desc->region.next;
			obj_desc->region.next = NULL;           /* Must clear field */

			if (acpi_ns_is_locked) {
				acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
			}

			/*
			 *  Now stop region accesses by executing the _REG method
			 */
			acpi_ev_execute_reg_method (region_obj, 0);

			if (acpi_ns_is_locked) {
				acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
			}

			/*
			 *  Call the setup handler with the deactivate notification
			 */
			region_setup = handler_obj->addr_handler.setup;
			status = region_setup (region_obj, ACPI_REGION_DEACTIVATE,
					  handler_obj->addr_handler.context,
					  &region_context);

			/*
			 *  Init routine may fail, Just ignore errors
			 */

			region_obj->region.flags &= ~(AOPOBJ_INITIALIZED);

			/*
			 *  Remove handler reference in the region
			 *
			 *  NOTE: this doesn't mean that the region goes away
			 *  The region is just inaccessible as indicated to
			 *  the _REG method
			 *
			 *  If the region is on the handler's list
			 *  this better be the region's handler
			 */
			ACPI_ASSERT (region_obj->region.addr_handler == handler_obj);

			region_obj->region.addr_handler = NULL;

			return;

		} /* found the right handler */

		/*
		 *  Move through the linked list of handlers
		 */
		last_obj_ptr = &obj_desc->region.next;
		obj_desc = obj_desc->region.next;
	}

	/*
	 *  If we get here, the region was not in the handler's region list
	 */
	return;
}