Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 299cfe38 authored by Len Brown's avatar Len Brown
Browse files

Merge branches 'release' and 'hwmon-conflicts' into release

parents 8976b6fd 443dea72
Loading
Loading
Loading
Loading
+3 −1
Original line number Original line Diff line number Diff line
@@ -359,7 +359,9 @@ acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc)


	status = acpi_os_validate_address(obj_desc->region.space_id,
	status = acpi_os_validate_address(obj_desc->region.space_id,
					  obj_desc->region.address,
					  obj_desc->region.address,
					  (acpi_size) obj_desc->region.length);
					  (acpi_size) obj_desc->region.length,
					  acpi_ut_get_node_name(node));

	if (ACPI_FAILURE(status)) {
	if (ACPI_FAILURE(status)) {
		/*
		/*
		 * Invalid address/length. We will emit an error message and mark
		 * Invalid address/length. We will emit an error message and mark
+174 −2
Original line number Original line Diff line number Diff line
@@ -44,6 +44,8 @@
#include <asm/uaccess.h>
#include <asm/uaccess.h>


#include <linux/efi.h>
#include <linux/efi.h>
#include <linux/ioport.h>
#include <linux/list.h>


#define _COMPONENT		ACPI_OS_SERVICES
#define _COMPONENT		ACPI_OS_SERVICES
ACPI_MODULE_NAME("osl");
ACPI_MODULE_NAME("osl");
@@ -74,6 +76,18 @@ static void *acpi_irq_context;
static struct workqueue_struct *kacpid_wq;
static struct workqueue_struct *kacpid_wq;
static struct workqueue_struct *kacpi_notify_wq;
static struct workqueue_struct *kacpi_notify_wq;


struct acpi_res_list {
	resource_size_t start;
	resource_size_t end;
	acpi_adr_space_type resource_type; /* IO port, System memory, ...*/
	char name[5];   /* only can have a length of 4 chars, make use of this
			   one instead of res->name, no need to kalloc then */
	struct list_head resource_list;
};

static LIST_HEAD(resource_list_head);
static DEFINE_SPINLOCK(acpi_res_lock);

#define	OSI_STRING_LENGTH_MAX 64	/* arbitrary */
#define	OSI_STRING_LENGTH_MAX 64	/* arbitrary */
static char osi_additional_string[OSI_STRING_LENGTH_MAX];
static char osi_additional_string[OSI_STRING_LENGTH_MAX];


@@ -1091,6 +1105,128 @@ static int __init acpi_wake_gpes_always_on_setup(char *str)


__setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup);
__setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup);


/* Check of resource interference between native drivers and ACPI
 * OperationRegions (SystemIO and System Memory only).
 * IO ports and memory declared in ACPI might be used by the ACPI subsystem
 * in arbitrary AML code and can interfere with legacy drivers.
 * acpi_enforce_resources= can be set to:
 *
 *   - strict           (2)
 *     -> further driver trying to access the resources will not load
 *   - lax (default)    (1)
 *     -> further driver trying to access the resources will load, but you
 *     get a system message that something might go wrong...
 *
 *   - no               (0)
 *     -> ACPI Operation Region resources will not be registered
 *
 */
#define ENFORCE_RESOURCES_STRICT 2
#define ENFORCE_RESOURCES_LAX    1
#define ENFORCE_RESOURCES_NO     0

static unsigned int acpi_enforce_resources = ENFORCE_RESOURCES_LAX;

static int __init acpi_enforce_resources_setup(char *str)
{
	if (str == NULL || *str == '\0')
		return 0;

	if (!strcmp("strict", str))
		acpi_enforce_resources = ENFORCE_RESOURCES_STRICT;
	else if (!strcmp("lax", str))
		acpi_enforce_resources = ENFORCE_RESOURCES_LAX;
	else if (!strcmp("no", str))
		acpi_enforce_resources = ENFORCE_RESOURCES_NO;

	return 1;
}

__setup("acpi_enforce_resources=", acpi_enforce_resources_setup);

/* Check for resource conflicts between ACPI OperationRegions and native
 * drivers */
int acpi_check_resource_conflict(struct resource *res)
{
	struct acpi_res_list *res_list_elem;
	int ioport;
	int clash = 0;

	if (acpi_enforce_resources == ENFORCE_RESOURCES_NO)
		return 0;
	if (!(res->flags & IORESOURCE_IO) && !(res->flags & IORESOURCE_MEM))
		return 0;

	ioport = res->flags & IORESOURCE_IO;

	spin_lock(&acpi_res_lock);
	list_for_each_entry(res_list_elem, &resource_list_head,
			    resource_list) {
		if (ioport && (res_list_elem->resource_type
			       != ACPI_ADR_SPACE_SYSTEM_IO))
			continue;
		if (!ioport && (res_list_elem->resource_type
				!= ACPI_ADR_SPACE_SYSTEM_MEMORY))
			continue;

		if (res->end < res_list_elem->start
		    || res_list_elem->end < res->start)
			continue;
		clash = 1;
		break;
	}
	spin_unlock(&acpi_res_lock);

	if (clash) {
		if (acpi_enforce_resources != ENFORCE_RESOURCES_NO) {
			printk(KERN_INFO "%sACPI: %s resource %s [0x%llx-0x%llx]"
			       " conflicts with ACPI region %s"
			       " [0x%llx-0x%llx]\n",
			       acpi_enforce_resources == ENFORCE_RESOURCES_LAX
			       ? KERN_WARNING : KERN_ERR,
			       ioport ? "I/O" : "Memory", res->name,
			       (long long) res->start, (long long) res->end,
			       res_list_elem->name,
			       (long long) res_list_elem->start,
			       (long long) res_list_elem->end);
			printk(KERN_INFO "ACPI: Device needs an ACPI driver\n");
		}
		if (acpi_enforce_resources == ENFORCE_RESOURCES_STRICT)
			return -EBUSY;
	}
	return 0;
}
EXPORT_SYMBOL(acpi_check_resource_conflict);

int acpi_check_region(resource_size_t start, resource_size_t n,
		      const char *name)
{
	struct resource res = {
		.start = start,
		.end   = start + n - 1,
		.name  = name,
		.flags = IORESOURCE_IO,
	};

	return acpi_check_resource_conflict(&res);
}
EXPORT_SYMBOL(acpi_check_region);

int acpi_check_mem_region(resource_size_t start, resource_size_t n,
		      const char *name)
{
	struct resource res = {
		.start = start,
		.end   = start + n - 1,
		.name  = name,
		.flags = IORESOURCE_MEM,
	};

	return acpi_check_resource_conflict(&res);

}
EXPORT_SYMBOL(acpi_check_mem_region);

/*
/*
 * Acquire a spinlock.
 * Acquire a spinlock.
 *
 *
@@ -1292,9 +1428,45 @@ acpi_status
acpi_os_validate_address (
acpi_os_validate_address (
    u8                   space_id,
    u8                   space_id,
    acpi_physical_address   address,
    acpi_physical_address   address,
    acpi_size               length)
    acpi_size               length,
    char *name)
{
{
	struct acpi_res_list *res;
	if (acpi_enforce_resources == ENFORCE_RESOURCES_NO)
		return AE_OK;


	switch (space_id) {
	case ACPI_ADR_SPACE_SYSTEM_IO:
	case ACPI_ADR_SPACE_SYSTEM_MEMORY:
		/* Only interference checks against SystemIO and SytemMemory
		   are needed */
		res = kzalloc(sizeof(struct acpi_res_list), GFP_KERNEL);
		if (!res)
			return AE_OK;
		/* ACPI names are fixed to 4 bytes, still better use strlcpy */
		strlcpy(res->name, name, 5);
		res->start = address;
		res->end = address + length - 1;
		res->resource_type = space_id;
		spin_lock(&acpi_res_lock);
		list_add(&res->resource_list, &resource_list_head);
		spin_unlock(&acpi_res_lock);
		pr_debug("Added %s resource: start: 0x%llx, end: 0x%llx, "
			 "name: %s\n", (space_id == ACPI_ADR_SPACE_SYSTEM_IO)
			 ? "SystemIO" : "System Memory",
			 (unsigned long long)res->start,
			 (unsigned long long)res->end,
			 res->name);
		break;
	case ACPI_ADR_SPACE_PCI_CONFIG:
	case ACPI_ADR_SPACE_EC:
	case ACPI_ADR_SPACE_SMBUS:
	case ACPI_ADR_SPACE_CMOS:
	case ACPI_ADR_SPACE_PCI_BAR_TARGET:
	case ACPI_ADR_SPACE_DATA_TABLE:
	case ACPI_ADR_SPACE_FIXED_HARDWARE:
		break;
	}
	return AE_OK;
	return AE_OK;
}
}


+2 −2
Original line number Original line Diff line number Diff line
@@ -242,8 +242,8 @@ acpi_status acpi_os_validate_interface(char *interface);
acpi_status acpi_osi_invalidate(char* interface);
acpi_status acpi_osi_invalidate(char* interface);


acpi_status
acpi_status
acpi_os_validate_address(u8 space_id,
acpi_os_validate_address(u8 space_id, acpi_physical_address address,
			 acpi_physical_address address, acpi_size length);
			 acpi_size length, char *name);


u64 acpi_os_get_timer(void);
u64 acpi_os_get_timer(void);


+25 −0
Original line number Original line Diff line number Diff line
@@ -25,6 +25,7 @@
#ifndef _LINUX_ACPI_H
#ifndef _LINUX_ACPI_H
#define _LINUX_ACPI_H
#define _LINUX_ACPI_H


#include <linux/ioport.h>	/* for struct resource */


#ifdef	CONFIG_ACPI
#ifdef	CONFIG_ACPI


@@ -238,6 +239,13 @@ extern int pnpacpi_disabled;
#define PXM_INVAL	(-1)
#define PXM_INVAL	(-1)
#define NID_INVAL	(-1)
#define NID_INVAL	(-1)


int acpi_check_resource_conflict(struct resource *res);

int acpi_check_region(resource_size_t start, resource_size_t n,
		      const char *name);
int acpi_check_mem_region(resource_size_t start, resource_size_t n,
		      const char *name);

#else	/* CONFIG_ACPI */
#else	/* CONFIG_ACPI */


static inline int acpi_boot_init(void)
static inline int acpi_boot_init(void)
@@ -250,5 +258,22 @@ static inline int acpi_boot_table_init(void)
	return 0;
	return 0;
}
}


static inline int acpi_check_resource_conflict(struct resource *res)
{
	return 0;
}

static inline int acpi_check_region(resource_size_t start, resource_size_t n,
				    const char *name)
{
	return 0;
}

static inline int acpi_check_mem_region(resource_size_t start,
					resource_size_t n, const char *name)
{
	return 0;
}

#endif	/* !CONFIG_ACPI */
#endif	/* !CONFIG_ACPI */
#endif	/*_LINUX_ACPI_H*/
#endif	/*_LINUX_ACPI_H*/