brintos

brintos / linux-shallow public Read only

0
0
Text · 19.2 KiB · c62be3d Raw
629 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/*******************************************************************************3 *4 * Module Name: rsxface - Public interfaces to the resource manager5 *6 ******************************************************************************/7 8#define EXPORT_ACPI_INTERFACES9 10#include <acpi/acpi.h>11#include "accommon.h"12#include "acresrc.h"13#include "acnamesp.h"14 15#define _COMPONENT          ACPI_RESOURCES16ACPI_MODULE_NAME("rsxface")17 18/* Local macros for 16,32-bit to 64-bit conversion */19#define ACPI_COPY_FIELD(out, in, field)  ((out)->field = (in)->field)20#define ACPI_COPY_ADDRESS(out, in)                       \21	ACPI_COPY_FIELD(out, in, resource_type);             \22	ACPI_COPY_FIELD(out, in, producer_consumer);         \23	ACPI_COPY_FIELD(out, in, decode);                    \24	ACPI_COPY_FIELD(out, in, min_address_fixed);         \25	ACPI_COPY_FIELD(out, in, max_address_fixed);         \26	ACPI_COPY_FIELD(out, in, info);                      \27	ACPI_COPY_FIELD(out, in, address.granularity);       \28	ACPI_COPY_FIELD(out, in, address.minimum);           \29	ACPI_COPY_FIELD(out, in, address.maximum);           \30	ACPI_COPY_FIELD(out, in, address.translation_offset); \31	ACPI_COPY_FIELD(out, in, address.address_length);    \32	ACPI_COPY_FIELD(out, in, resource_source);33/* Local prototypes */34static acpi_status35acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context);36 37static acpi_status38acpi_rs_validate_parameters(acpi_handle device_handle,39			    struct acpi_buffer *buffer,40			    struct acpi_namespace_node **return_node);41 42/*******************************************************************************43 *44 * FUNCTION:    acpi_rs_validate_parameters45 *46 * PARAMETERS:  device_handle   - Handle to a device47 *              buffer          - Pointer to a data buffer48 *              return_node     - Pointer to where the device node is returned49 *50 * RETURN:      Status51 *52 * DESCRIPTION: Common parameter validation for resource interfaces53 *54 ******************************************************************************/55 56static acpi_status57acpi_rs_validate_parameters(acpi_handle device_handle,58			    struct acpi_buffer *buffer,59			    struct acpi_namespace_node **return_node)60{61	acpi_status status;62	struct acpi_namespace_node *node;63 64	ACPI_FUNCTION_TRACE(rs_validate_parameters);65 66	/*67	 * Must have a valid handle to an ACPI device68	 */69	if (!device_handle) {70		return_ACPI_STATUS(AE_BAD_PARAMETER);71	}72 73	node = acpi_ns_validate_handle(device_handle);74	if (!node) {75		return_ACPI_STATUS(AE_BAD_PARAMETER);76	}77 78	if (node->type != ACPI_TYPE_DEVICE) {79		return_ACPI_STATUS(AE_TYPE);80	}81 82	/*83	 * Validate the user buffer object84	 *85	 * if there is a non-zero buffer length we also need a valid pointer in86	 * the buffer. If it's a zero buffer length, we'll be returning the87	 * needed buffer size (later), so keep going.88	 */89	status = acpi_ut_validate_buffer(buffer);90	if (ACPI_FAILURE(status)) {91		return_ACPI_STATUS(status);92	}93 94	*return_node = node;95	return_ACPI_STATUS(AE_OK);96}97 98/*******************************************************************************99 *100 * FUNCTION:    acpi_get_irq_routing_table101 *102 * PARAMETERS:  device_handle   - Handle to the Bus device we are querying103 *              ret_buffer      - Pointer to a buffer to receive the104 *                                current resources for the device105 *106 * RETURN:      Status107 *108 * DESCRIPTION: This function is called to get the IRQ routing table for a109 *              specific bus. The caller must first acquire a handle for the110 *              desired bus. The routine table is placed in the buffer pointed111 *              to by the ret_buffer variable parameter.112 *113 *              If the function fails an appropriate status will be returned114 *              and the value of ret_buffer is undefined.115 *116 *              This function attempts to execute the _PRT method contained in117 *              the object indicated by the passed device_handle.118 *119 ******************************************************************************/120 121acpi_status122acpi_get_irq_routing_table(acpi_handle device_handle,123			   struct acpi_buffer *ret_buffer)124{125	acpi_status status;126	struct acpi_namespace_node *node;127 128	ACPI_FUNCTION_TRACE(acpi_get_irq_routing_table);129 130	/* Validate parameters then dispatch to internal routine */131 132	status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);133	if (ACPI_FAILURE(status)) {134		return_ACPI_STATUS(status);135	}136 137	status = acpi_rs_get_prt_method_data(node, ret_buffer);138	return_ACPI_STATUS(status);139}140 141ACPI_EXPORT_SYMBOL(acpi_get_irq_routing_table)142 143/*******************************************************************************144 *145 * FUNCTION:    acpi_get_current_resources146 *147 * PARAMETERS:  device_handle   - Handle to the device object for the148 *                                device we are querying149 *              ret_buffer      - Pointer to a buffer to receive the150 *                                current resources for the device151 *152 * RETURN:      Status153 *154 * DESCRIPTION: This function is called to get the current resources for a155 *              specific device. The caller must first acquire a handle for156 *              the desired device. The resource data is placed in the buffer157 *              pointed to by the ret_buffer variable parameter.158 *159 *              If the function fails an appropriate status will be returned160 *              and the value of ret_buffer is undefined.161 *162 *              This function attempts to execute the _CRS method contained in163 *              the object indicated by the passed device_handle.164 *165 ******************************************************************************/166acpi_status167acpi_get_current_resources(acpi_handle device_handle,168			   struct acpi_buffer *ret_buffer)169{170	acpi_status status;171	struct acpi_namespace_node *node;172 173	ACPI_FUNCTION_TRACE(acpi_get_current_resources);174 175	/* Validate parameters then dispatch to internal routine */176 177	status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);178	if (ACPI_FAILURE(status)) {179		return_ACPI_STATUS(status);180	}181 182	status = acpi_rs_get_crs_method_data(node, ret_buffer);183	return_ACPI_STATUS(status);184}185 186ACPI_EXPORT_SYMBOL(acpi_get_current_resources)187 188/*******************************************************************************189 *190 * FUNCTION:    acpi_get_possible_resources191 *192 * PARAMETERS:  device_handle   - Handle to the device object for the193 *                                device we are querying194 *              ret_buffer      - Pointer to a buffer to receive the195 *                                resources for the device196 *197 * RETURN:      Status198 *199 * DESCRIPTION: This function is called to get a list of the possible resources200 *              for a specific device. The caller must first acquire a handle201 *              for the desired device. The resource data is placed in the202 *              buffer pointed to by the ret_buffer variable.203 *204 *              If the function fails an appropriate status will be returned205 *              and the value of ret_buffer is undefined.206 *207 ******************************************************************************/208acpi_status209acpi_get_possible_resources(acpi_handle device_handle,210			    struct acpi_buffer *ret_buffer)211{212	acpi_status status;213	struct acpi_namespace_node *node;214 215	ACPI_FUNCTION_TRACE(acpi_get_possible_resources);216 217	/* Validate parameters then dispatch to internal routine */218 219	status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);220	if (ACPI_FAILURE(status)) {221		return_ACPI_STATUS(status);222	}223 224	status = acpi_rs_get_prs_method_data(node, ret_buffer);225	return_ACPI_STATUS(status);226}227 228ACPI_EXPORT_SYMBOL(acpi_get_possible_resources)229 230/*******************************************************************************231 *232 * FUNCTION:    acpi_set_current_resources233 *234 * PARAMETERS:  device_handle   - Handle to the device object for the235 *                                device we are setting resources236 *              in_buffer       - Pointer to a buffer containing the237 *                                resources to be set for the device238 *239 * RETURN:      Status240 *241 * DESCRIPTION: This function is called to set the current resources for a242 *              specific device. The caller must first acquire a handle for243 *              the desired device. The resource data is passed to the routine244 *              the buffer pointed to by the in_buffer variable.245 *246 ******************************************************************************/247acpi_status248acpi_set_current_resources(acpi_handle device_handle,249			   struct acpi_buffer *in_buffer)250{251	acpi_status status;252	struct acpi_namespace_node *node;253 254	ACPI_FUNCTION_TRACE(acpi_set_current_resources);255 256	/* Validate the buffer, don't allow zero length */257 258	if ((!in_buffer) || (!in_buffer->pointer) || (!in_buffer->length)) {259		return_ACPI_STATUS(AE_BAD_PARAMETER);260	}261 262	/* Validate parameters then dispatch to internal routine */263 264	status = acpi_rs_validate_parameters(device_handle, in_buffer, &node);265	if (ACPI_FAILURE(status)) {266		return_ACPI_STATUS(status);267	}268 269	status = acpi_rs_set_srs_method_data(node, in_buffer);270	return_ACPI_STATUS(status);271}272 273ACPI_EXPORT_SYMBOL(acpi_set_current_resources)274 275/*******************************************************************************276 *277 * FUNCTION:    acpi_get_event_resources278 *279 * PARAMETERS:  device_handle   - Handle to the device object for the280 *                                device we are getting resources281 *              in_buffer       - Pointer to a buffer containing the282 *                                resources to be set for the device283 *284 * RETURN:      Status285 *286 * DESCRIPTION: This function is called to get the event resources for a287 *              specific device. The caller must first acquire a handle for288 *              the desired device. The resource data is passed to the routine289 *              the buffer pointed to by the in_buffer variable. Uses the290 *              _AEI method.291 *292 ******************************************************************************/293acpi_status294acpi_get_event_resources(acpi_handle device_handle,295			 struct acpi_buffer *ret_buffer)296{297	acpi_status status;298	struct acpi_namespace_node *node;299 300	ACPI_FUNCTION_TRACE(acpi_get_event_resources);301 302	/* Validate parameters then dispatch to internal routine */303 304	status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);305	if (ACPI_FAILURE(status)) {306		return_ACPI_STATUS(status);307	}308 309	status = acpi_rs_get_aei_method_data(node, ret_buffer);310	return_ACPI_STATUS(status);311}312 313ACPI_EXPORT_SYMBOL(acpi_get_event_resources)314 315/******************************************************************************316 *317 * FUNCTION:    acpi_resource_to_address64318 *319 * PARAMETERS:  resource        - Pointer to a resource320 *              out             - Pointer to the users's return buffer321 *                                (a struct acpi_resource_address64)322 *323 * RETURN:      Status324 *325 * DESCRIPTION: If the resource is an address16, address32, or address64,326 *              copy it to the address64 return buffer. This saves the327 *              caller from having to duplicate code for different-sized328 *              addresses.329 *330 ******************************************************************************/331acpi_status332acpi_resource_to_address64(struct acpi_resource *resource,333			   struct acpi_resource_address64 *out)334{335	struct acpi_resource_address16 *address16;336	struct acpi_resource_address32 *address32;337 338	if (!resource || !out) {339		return (AE_BAD_PARAMETER);340	}341 342	/* Convert 16 or 32 address descriptor to 64 */343 344	switch (resource->type) {345	case ACPI_RESOURCE_TYPE_ADDRESS16:346 347		address16 =348		    ACPI_CAST_PTR(struct acpi_resource_address16,349				  &resource->data);350		ACPI_COPY_ADDRESS(out, address16);351		break;352 353	case ACPI_RESOURCE_TYPE_ADDRESS32:354 355		address32 =356		    ACPI_CAST_PTR(struct acpi_resource_address32,357				  &resource->data);358		ACPI_COPY_ADDRESS(out, address32);359		break;360 361	case ACPI_RESOURCE_TYPE_ADDRESS64:362 363		/* Simple copy for 64 bit source */364 365		memcpy(out, &resource->data,366		       sizeof(struct acpi_resource_address64));367		break;368 369	default:370 371		return (AE_BAD_PARAMETER);372	}373 374	return (AE_OK);375}376 377ACPI_EXPORT_SYMBOL(acpi_resource_to_address64)378 379/*******************************************************************************380 *381 * FUNCTION:    acpi_get_vendor_resource382 *383 * PARAMETERS:  device_handle   - Handle for the parent device object384 *              name            - Method name for the parent resource385 *                                (METHOD_NAME__CRS or METHOD_NAME__PRS)386 *              uuid            - Pointer to the UUID to be matched.387 *                                includes both subtype and 16-byte UUID388 *              ret_buffer      - Where the vendor resource is returned389 *390 * RETURN:      Status391 *392 * DESCRIPTION: Walk a resource template for the specified device to find a393 *              vendor-defined resource that matches the supplied UUID and394 *              UUID subtype. Returns a struct acpi_resource of type Vendor.395 *396 ******************************************************************************/397acpi_status398acpi_get_vendor_resource(acpi_handle device_handle,399			 char *name,400			 struct acpi_vendor_uuid *uuid,401			 struct acpi_buffer *ret_buffer)402{403	struct acpi_vendor_walk_info info;404	acpi_status status;405 406	/* Other parameters are validated by acpi_walk_resources */407 408	if (!uuid || !ret_buffer) {409		return (AE_BAD_PARAMETER);410	}411 412	info.uuid = uuid;413	info.buffer = ret_buffer;414	info.status = AE_NOT_EXIST;415 416	/* Walk the _CRS or _PRS resource list for this device */417 418	status =419	    acpi_walk_resources(device_handle, name,420				acpi_rs_match_vendor_resource, &info);421	if (ACPI_FAILURE(status)) {422		return (status);423	}424 425	return (info.status);426}427 428ACPI_EXPORT_SYMBOL(acpi_get_vendor_resource)429 430/*******************************************************************************431 *432 * FUNCTION:    acpi_rs_match_vendor_resource433 *434 * PARAMETERS:  acpi_walk_resource_callback435 *436 * RETURN:      Status437 *438 * DESCRIPTION: Match a vendor resource via the ACPI 3.0 UUID439 *440 ******************************************************************************/441static acpi_status442acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context)443{444	struct acpi_vendor_walk_info *info = context;445	struct acpi_resource_vendor_typed *vendor;446	struct acpi_buffer *buffer;447	acpi_status status;448 449	/* Ignore all descriptors except Vendor */450 451	if (resource->type != ACPI_RESOURCE_TYPE_VENDOR) {452		return (AE_OK);453	}454 455	vendor = &resource->data.vendor_typed;456 457	/*458	 * For a valid match, these conditions must hold:459	 *460	 * 1) Length of descriptor data must be at least as long as a UUID struct461	 * 2) The UUID subtypes must match462	 * 3) The UUID data must match463	 */464	if ((vendor->byte_length < (ACPI_UUID_LENGTH + 1)) ||465	    (vendor->uuid_subtype != info->uuid->subtype) ||466	    (memcmp(vendor->uuid, info->uuid->data, ACPI_UUID_LENGTH))) {467		return (AE_OK);468	}469 470	/* Validate/Allocate/Clear caller buffer */471 472	buffer = info->buffer;473	status = acpi_ut_initialize_buffer(buffer, resource->length);474	if (ACPI_FAILURE(status)) {475		return (status);476	}477 478	/* Found the correct resource, copy and return it */479 480	memcpy(buffer->pointer, resource, resource->length);481	buffer->length = resource->length;482 483	/* Found the desired descriptor, terminate resource walk */484 485	info->status = AE_OK;486	return (AE_CTRL_TERMINATE);487}488 489/*******************************************************************************490 *491 * FUNCTION:    acpi_walk_resource_buffer492 *493 * PARAMETERS:  buffer          - Formatted buffer returned by one of the494 *                                various Get*Resource functions495 *              user_function   - Called for each resource496 *              context         - Passed to user_function497 *498 * RETURN:      Status499 *500 * DESCRIPTION: Walks the input resource template. The user_function is called501 *              once for each resource in the list.502 *503 ******************************************************************************/504 505acpi_status506acpi_walk_resource_buffer(struct acpi_buffer *buffer,507			  acpi_walk_resource_callback user_function,508			  void *context)509{510	acpi_status status = AE_OK;511	struct acpi_resource *resource;512	struct acpi_resource *resource_end;513 514	ACPI_FUNCTION_TRACE(acpi_walk_resource_buffer);515 516	/* Parameter validation */517 518	if (!buffer || !buffer->pointer || !user_function) {519		return_ACPI_STATUS(AE_BAD_PARAMETER);520	}521 522	/* Buffer contains the resource list and length */523 524	resource = ACPI_CAST_PTR(struct acpi_resource, buffer->pointer);525	resource_end =526	    ACPI_ADD_PTR(struct acpi_resource, buffer->pointer, buffer->length);527 528	/* Walk the resource list until the end_tag is found (or buffer end) */529 530	while (resource < resource_end) {531 532		/* Sanity check the resource type */533 534		if (resource->type > ACPI_RESOURCE_TYPE_MAX) {535			status = AE_AML_INVALID_RESOURCE_TYPE;536			break;537		}538 539		/* Sanity check the length. It must not be zero, or we loop forever */540 541		if (!resource->length) {542			return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);543		}544 545		/* Invoke the user function, abort on any error returned */546 547		status = user_function(resource, context);548		if (ACPI_FAILURE(status)) {549			if (status == AE_CTRL_TERMINATE) {550 551				/* This is an OK termination by the user function */552 553				status = AE_OK;554			}555			break;556		}557 558		/* end_tag indicates end-of-list */559 560		if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) {561			break;562		}563 564		/* Get the next resource descriptor */565 566		resource = ACPI_NEXT_RESOURCE(resource);567	}568 569	return_ACPI_STATUS(status);570}571 572ACPI_EXPORT_SYMBOL(acpi_walk_resource_buffer)573 574/*******************************************************************************575 *576 * FUNCTION:    acpi_walk_resources577 *578 * PARAMETERS:  device_handle   - Handle to the device object for the579 *                                device we are querying580 *              name            - Method name of the resources we want.581 *                                (METHOD_NAME__CRS, METHOD_NAME__PRS, or582 *                                METHOD_NAME__AEI or METHOD_NAME__DMA)583 *              user_function   - Called for each resource584 *              context         - Passed to user_function585 *586 * RETURN:      Status587 *588 * DESCRIPTION: Retrieves the current or possible resource list for the589 *              specified device. The user_function is called once for590 *              each resource in the list.591 *592 ******************************************************************************/593acpi_status594acpi_walk_resources(acpi_handle device_handle,595		    char *name,596		    acpi_walk_resource_callback user_function, void *context)597{598	acpi_status status;599	struct acpi_buffer buffer;600 601	ACPI_FUNCTION_TRACE(acpi_walk_resources);602 603	/* Parameter validation */604 605	if (!device_handle || !user_function || !name ||606	    (!ACPI_COMPARE_NAMESEG(name, METHOD_NAME__CRS) &&607	     !ACPI_COMPARE_NAMESEG(name, METHOD_NAME__PRS) &&608	     !ACPI_COMPARE_NAMESEG(name, METHOD_NAME__AEI) &&609	     !ACPI_COMPARE_NAMESEG(name, METHOD_NAME__DMA))) {610		return_ACPI_STATUS(AE_BAD_PARAMETER);611	}612 613	/* Get the _CRS/_PRS/_AEI/_DMA resource list */614 615	buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;616	status = acpi_rs_get_method_data(device_handle, name, &buffer);617	if (ACPI_FAILURE(status)) {618		return_ACPI_STATUS(status);619	}620 621	/* Walk the resource list and cleanup */622 623	status = acpi_walk_resource_buffer(&buffer, user_function, context);624	ACPI_FREE(buffer.pointer);625	return_ACPI_STATUS(status);626}627 628ACPI_EXPORT_SYMBOL(acpi_walk_resources)629