brintos

brintos / linux-shallow public Read only

0
0
Text · 30.8 KiB · 7fe842d Raw
1121 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * drivers/acpi/resource.c - ACPI device resources interpretation.4 *5 * Copyright (C) 2012, Intel Corp.6 * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>7 *8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~9 *10 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~11 */12 13#include <linux/acpi.h>14#include <linux/device.h>15#include <linux/export.h>16#include <linux/ioport.h>17#include <linux/slab.h>18#include <linux/irq.h>19#include <linux/dmi.h>20 21#ifdef CONFIG_X8622#define valid_IRQ(i) (((i) != 0) && ((i) != 2))23static inline bool acpi_iospace_resource_valid(struct resource *res)24{25	/* On X86 IO space is limited to the [0 - 64K] IO port range */26	return res->end < 0x10003;27}28#else29#define valid_IRQ(i) (true)30/*31 * ACPI IO descriptors on arches other than X86 contain MMIO CPU physical32 * addresses mapping IO space in CPU physical address space, IO space33 * resources can be placed anywhere in the 64-bit physical address space.34 */35static inline bool36acpi_iospace_resource_valid(struct resource *res) { return true; }37#endif38 39#if IS_ENABLED(CONFIG_ACPI_GENERIC_GSI)40static inline bool is_gsi(struct acpi_resource_extended_irq *ext_irq)41{42	return ext_irq->resource_source.string_length == 0 &&43	       ext_irq->producer_consumer == ACPI_CONSUMER;44}45#else46static inline bool is_gsi(struct acpi_resource_extended_irq *ext_irq)47{48	return true;49}50#endif51 52static bool acpi_dev_resource_len_valid(u64 start, u64 end, u64 len, bool io)53{54	u64 reslen = end - start + 1;55 56	/*57	 * CHECKME: len might be required to check versus a minimum58	 * length as well. 1 for io is fine, but for memory it does59	 * not make any sense at all.60	 * Note: some BIOSes report incorrect length for ACPI address space61	 * descriptor, so remove check of 'reslen == len' to avoid regression.62	 */63	if (len && reslen && start <= end)64		return true;65 66	pr_debug("ACPI: invalid or unassigned resource %s [%016llx - %016llx] length [%016llx]\n",67		io ? "io" : "mem", start, end, len);68 69	return false;70}71 72static void acpi_dev_memresource_flags(struct resource *res, u64 len,73				       u8 write_protect)74{75	res->flags = IORESOURCE_MEM;76 77	if (!acpi_dev_resource_len_valid(res->start, res->end, len, false))78		res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET;79 80	if (write_protect == ACPI_READ_WRITE_MEMORY)81		res->flags |= IORESOURCE_MEM_WRITEABLE;82}83 84static void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len,85				     u8 write_protect)86{87	res->start = start;88	res->end = start + len - 1;89	acpi_dev_memresource_flags(res, len, write_protect);90}91 92/**93 * acpi_dev_resource_memory - Extract ACPI memory resource information.94 * @ares: Input ACPI resource object.95 * @res: Output generic resource object.96 *97 * Check if the given ACPI resource object represents a memory resource and98 * if that's the case, use the information in it to populate the generic99 * resource object pointed to by @res.100 *101 * Return:102 * 1) false with res->flags setting to zero: not the expected resource type103 * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource104 * 3) true: valid assigned resource105 */106bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res)107{108	struct acpi_resource_memory24 *memory24;109	struct acpi_resource_memory32 *memory32;110	struct acpi_resource_fixed_memory32 *fixed_memory32;111 112	switch (ares->type) {113	case ACPI_RESOURCE_TYPE_MEMORY24:114		memory24 = &ares->data.memory24;115		acpi_dev_get_memresource(res, memory24->minimum << 8,116					 memory24->address_length << 8,117					 memory24->write_protect);118		break;119	case ACPI_RESOURCE_TYPE_MEMORY32:120		memory32 = &ares->data.memory32;121		acpi_dev_get_memresource(res, memory32->minimum,122					 memory32->address_length,123					 memory32->write_protect);124		break;125	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:126		fixed_memory32 = &ares->data.fixed_memory32;127		acpi_dev_get_memresource(res, fixed_memory32->address,128					 fixed_memory32->address_length,129					 fixed_memory32->write_protect);130		break;131	default:132		res->flags = 0;133		return false;134	}135 136	return !(res->flags & IORESOURCE_DISABLED);137}138EXPORT_SYMBOL_GPL(acpi_dev_resource_memory);139 140static void acpi_dev_ioresource_flags(struct resource *res, u64 len,141				      u8 io_decode, u8 translation_type)142{143	res->flags = IORESOURCE_IO;144 145	if (!acpi_dev_resource_len_valid(res->start, res->end, len, true))146		res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET;147 148	if (!acpi_iospace_resource_valid(res))149		res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET;150 151	if (io_decode == ACPI_DECODE_16)152		res->flags |= IORESOURCE_IO_16BIT_ADDR;153	if (translation_type == ACPI_SPARSE_TRANSLATION)154		res->flags |= IORESOURCE_IO_SPARSE;155}156 157static void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len,158				    u8 io_decode)159{160	res->start = start;161	res->end = start + len - 1;162	acpi_dev_ioresource_flags(res, len, io_decode, 0);163}164 165/**166 * acpi_dev_resource_io - Extract ACPI I/O resource information.167 * @ares: Input ACPI resource object.168 * @res: Output generic resource object.169 *170 * Check if the given ACPI resource object represents an I/O resource and171 * if that's the case, use the information in it to populate the generic172 * resource object pointed to by @res.173 *174 * Return:175 * 1) false with res->flags setting to zero: not the expected resource type176 * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource177 * 3) true: valid assigned resource178 */179bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res)180{181	struct acpi_resource_io *io;182	struct acpi_resource_fixed_io *fixed_io;183 184	switch (ares->type) {185	case ACPI_RESOURCE_TYPE_IO:186		io = &ares->data.io;187		acpi_dev_get_ioresource(res, io->minimum,188					io->address_length,189					io->io_decode);190		break;191	case ACPI_RESOURCE_TYPE_FIXED_IO:192		fixed_io = &ares->data.fixed_io;193		acpi_dev_get_ioresource(res, fixed_io->address,194					fixed_io->address_length,195					ACPI_DECODE_10);196		break;197	default:198		res->flags = 0;199		return false;200	}201 202	return !(res->flags & IORESOURCE_DISABLED);203}204EXPORT_SYMBOL_GPL(acpi_dev_resource_io);205 206static bool acpi_decode_space(struct resource_win *win,207			      struct acpi_resource_address *addr,208			      struct acpi_address64_attribute *attr)209{210	u8 iodec = attr->granularity == 0xfff ? ACPI_DECODE_10 : ACPI_DECODE_16;211	bool wp = addr->info.mem.write_protect;212	u64 len = attr->address_length;213	u64 start, end, offset = 0;214	struct resource *res = &win->res;215 216	/*217	 * Filter out invalid descriptor according to ACPI Spec 5.0, section218	 * 6.4.3.5 Address Space Resource Descriptors.219	 */220	if ((addr->min_address_fixed != addr->max_address_fixed && len) ||221	    (addr->min_address_fixed && addr->max_address_fixed && !len))222		pr_debug("ACPI: Invalid address space min_addr_fix %d, max_addr_fix %d, len %llx\n",223			 addr->min_address_fixed, addr->max_address_fixed, len);224 225	/*226	 * For bridges that translate addresses across the bridge,227	 * translation_offset is the offset that must be added to the228	 * address on the secondary side to obtain the address on the229	 * primary side. Non-bridge devices must list 0 for all Address230	 * Translation offset bits.231	 */232	if (addr->producer_consumer == ACPI_PRODUCER)233		offset = attr->translation_offset;234	else if (attr->translation_offset)235		pr_debug("ACPI: translation_offset(%lld) is invalid for non-bridge device.\n",236			 attr->translation_offset);237	start = attr->minimum + offset;238	end = attr->maximum + offset;239 240	win->offset = offset;241	res->start = start;242	res->end = end;243	if (sizeof(resource_size_t) < sizeof(u64) &&244	    (offset != win->offset || start != res->start || end != res->end)) {245		pr_warn("acpi resource window ([%#llx-%#llx] ignored, not CPU addressable)\n",246			attr->minimum, attr->maximum);247		return false;248	}249 250	switch (addr->resource_type) {251	case ACPI_MEMORY_RANGE:252		acpi_dev_memresource_flags(res, len, wp);253		break;254	case ACPI_IO_RANGE:255		acpi_dev_ioresource_flags(res, len, iodec,256					  addr->info.io.translation_type);257		break;258	case ACPI_BUS_NUMBER_RANGE:259		res->flags = IORESOURCE_BUS;260		break;261	default:262		return false;263	}264 265	if (addr->producer_consumer == ACPI_PRODUCER)266		res->flags |= IORESOURCE_WINDOW;267 268	if (addr->info.mem.caching == ACPI_PREFETCHABLE_MEMORY)269		res->flags |= IORESOURCE_PREFETCH;270 271	return !(res->flags & IORESOURCE_DISABLED);272}273 274/**275 * acpi_dev_resource_address_space - Extract ACPI address space information.276 * @ares: Input ACPI resource object.277 * @win: Output generic resource object.278 *279 * Check if the given ACPI resource object represents an address space resource280 * and if that's the case, use the information in it to populate the generic281 * resource object pointed to by @win.282 *283 * Return:284 * 1) false with win->res.flags setting to zero: not the expected resource type285 * 2) false with IORESOURCE_DISABLED in win->res.flags: valid unassigned286 *    resource287 * 3) true: valid assigned resource288 */289bool acpi_dev_resource_address_space(struct acpi_resource *ares,290				     struct resource_win *win)291{292	struct acpi_resource_address64 addr;293 294	win->res.flags = 0;295	if (ACPI_FAILURE(acpi_resource_to_address64(ares, &addr)))296		return false;297 298	return acpi_decode_space(win, (struct acpi_resource_address *)&addr,299				 &addr.address);300}301EXPORT_SYMBOL_GPL(acpi_dev_resource_address_space);302 303/**304 * acpi_dev_resource_ext_address_space - Extract ACPI address space information.305 * @ares: Input ACPI resource object.306 * @win: Output generic resource object.307 *308 * Check if the given ACPI resource object represents an extended address space309 * resource and if that's the case, use the information in it to populate the310 * generic resource object pointed to by @win.311 *312 * Return:313 * 1) false with win->res.flags setting to zero: not the expected resource type314 * 2) false with IORESOURCE_DISABLED in win->res.flags: valid unassigned315 *    resource316 * 3) true: valid assigned resource317 */318bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,319					 struct resource_win *win)320{321	struct acpi_resource_extended_address64 *ext_addr;322 323	win->res.flags = 0;324	if (ares->type != ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64)325		return false;326 327	ext_addr = &ares->data.ext_address64;328 329	return acpi_decode_space(win, (struct acpi_resource_address *)ext_addr,330				 &ext_addr->address);331}332EXPORT_SYMBOL_GPL(acpi_dev_resource_ext_address_space);333 334/**335 * acpi_dev_irq_flags - Determine IRQ resource flags.336 * @triggering: Triggering type as provided by ACPI.337 * @polarity: Interrupt polarity as provided by ACPI.338 * @shareable: Whether or not the interrupt is shareable.339 * @wake_capable: Wake capability as provided by ACPI.340 */341unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable, u8 wake_capable)342{343	unsigned long flags;344 345	if (triggering == ACPI_LEVEL_SENSITIVE)346		flags = polarity == ACPI_ACTIVE_LOW ?347			IORESOURCE_IRQ_LOWLEVEL : IORESOURCE_IRQ_HIGHLEVEL;348	else349		flags = polarity == ACPI_ACTIVE_LOW ?350			IORESOURCE_IRQ_LOWEDGE : IORESOURCE_IRQ_HIGHEDGE;351 352	if (shareable == ACPI_SHARED)353		flags |= IORESOURCE_IRQ_SHAREABLE;354 355	if (wake_capable == ACPI_WAKE_CAPABLE)356		flags |= IORESOURCE_IRQ_WAKECAPABLE;357 358	return flags | IORESOURCE_IRQ;359}360EXPORT_SYMBOL_GPL(acpi_dev_irq_flags);361 362/**363 * acpi_dev_get_irq_type - Determine irq type.364 * @triggering: Triggering type as provided by ACPI.365 * @polarity: Interrupt polarity as provided by ACPI.366 */367unsigned int acpi_dev_get_irq_type(int triggering, int polarity)368{369	switch (polarity) {370	case ACPI_ACTIVE_LOW:371		return triggering == ACPI_EDGE_SENSITIVE ?372		       IRQ_TYPE_EDGE_FALLING :373		       IRQ_TYPE_LEVEL_LOW;374	case ACPI_ACTIVE_HIGH:375		return triggering == ACPI_EDGE_SENSITIVE ?376		       IRQ_TYPE_EDGE_RISING :377		       IRQ_TYPE_LEVEL_HIGH;378	case ACPI_ACTIVE_BOTH:379		if (triggering == ACPI_EDGE_SENSITIVE)380			return IRQ_TYPE_EDGE_BOTH;381		fallthrough;382	default:383		return IRQ_TYPE_NONE;384	}385}386EXPORT_SYMBOL_GPL(acpi_dev_get_irq_type);387 388/*389 * DMI matches for boards where the DSDT specifies the kbd IRQ as390 * level active-low and using the override changes this to rising edge,391 * stopping the keyboard from working.392 */393static const struct dmi_system_id irq1_level_low_skip_override[] = {394	{395		/* MEDION P15651 */396		.matches = {397			DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),398			DMI_MATCH(DMI_BOARD_NAME, "M15T"),399		},400	},401	{402		/* MEDION S17405 */403		.matches = {404			DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),405			DMI_MATCH(DMI_BOARD_NAME, "M17T"),406		},407	},408	{409		/* MEDION S17413 */410		.matches = {411			DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),412			DMI_MATCH(DMI_BOARD_NAME, "M1xA"),413		},414	},415	{416		/* Asus Vivobook K3402ZA */417		.matches = {418			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),419			DMI_MATCH(DMI_BOARD_NAME, "K3402ZA"),420		},421	},422	{423		/* Asus Vivobook K3502ZA */424		.matches = {425			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),426			DMI_MATCH(DMI_BOARD_NAME, "K3502ZA"),427		},428	},429	{430		/* Asus Vivobook S5402ZA */431		.matches = {432			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),433			DMI_MATCH(DMI_BOARD_NAME, "S5402ZA"),434		},435	},436	{437		/* Asus Vivobook S5602ZA */438		.matches = {439			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),440			DMI_MATCH(DMI_BOARD_NAME, "S5602ZA"),441		},442	},443	{444		/* Asus Vivobook X1704VAP */445		.matches = {446			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),447			DMI_MATCH(DMI_BOARD_NAME, "X1704VAP"),448		},449	},450	{451		/* Asus ExpertBook B1402C* */452		.matches = {453			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),454			DMI_MATCH(DMI_BOARD_NAME, "B1402C"),455		},456	},457	{458		/* Asus ExpertBook B1502C* */459		.matches = {460			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),461			DMI_MATCH(DMI_BOARD_NAME, "B1502C"),462		},463	},464	{465		/* Asus ExpertBook B2402 (B2402CBA / B2402FBA / B2402CVA / B2402FVA) */466		.matches = {467			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),468			DMI_MATCH(DMI_BOARD_NAME, "B2402"),469		},470	},471	{472		/* Asus ExpertBook B2502 (B2502CBA / B2502FBA / B2502CVA / B2502FVA) */473		.matches = {474			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),475			DMI_MATCH(DMI_BOARD_NAME, "B2502"),476		},477	},478	{479		/* Asus Vivobook Go E1404GA* */480		.matches = {481			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),482			DMI_MATCH(DMI_BOARD_NAME, "E1404GA"),483		},484	},485	{486		/* Asus Vivobook E1504GA* */487		.matches = {488			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),489			DMI_MATCH(DMI_BOARD_NAME, "E1504GA"),490		},491	},492	{493		/* Asus Vivobook Pro N6506M* */494		.matches = {495			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),496			DMI_MATCH(DMI_BOARD_NAME, "N6506M"),497		},498	},499	{500		/* LG Electronics 17U70P */501		.matches = {502			DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"),503			DMI_MATCH(DMI_BOARD_NAME, "17U70P"),504		},505	},506	{507		/* LG Electronics 16T90SP */508		.matches = {509			DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"),510			DMI_MATCH(DMI_BOARD_NAME, "16T90SP"),511		},512	},513	{ }514};515 516/*517 * DMI matches for AMD Zen boards where the DSDT specifies the kbd IRQ518 * as falling edge and this must be overridden to rising edge,519 * to have a working keyboard.520 */521static const struct dmi_system_id irq1_edge_low_force_override[] = {522	{523		/* MECHREV Jiaolong17KS Series GM7XG0M */524		.matches = {525			DMI_MATCH(DMI_BOARD_NAME, "GM7XG0M"),526		},527	},528	{529		/* XMG APEX 17 (M23) */530		.matches = {531			DMI_MATCH(DMI_BOARD_NAME, "GMxBGxx"),532		},533	},534	{535		/* TongFang GMxRGxx/XMG CORE 15 (M22)/TUXEDO Stellaris 15 Gen4 AMD */536		.matches = {537			DMI_MATCH(DMI_BOARD_NAME, "GMxRGxx"),538		},539	},540	{541		/* TongFang GMxXGxx/TUXEDO Polaris 15 Gen5 AMD */542		.matches = {543			DMI_MATCH(DMI_BOARD_NAME, "GMxXGxx"),544		},545	},546	{547		/* TongFang GMxXGxX/TUXEDO Polaris 15 Gen5 AMD */548		.matches = {549			DMI_MATCH(DMI_BOARD_NAME, "GMxXGxX"),550		},551	},552	{553		/* TongFang GMxXGxx sold as Eluktronics Inc. RP-15 */554		.matches = {555			DMI_MATCH(DMI_SYS_VENDOR, "Eluktronics Inc."),556			DMI_MATCH(DMI_BOARD_NAME, "RP-15"),557		},558	},559	{560		/* TongFang GM6XGxX/TUXEDO Stellaris 16 Gen5 AMD */561		.matches = {562			DMI_MATCH(DMI_BOARD_NAME, "GM6XGxX"),563		},564	},565	{566		/* MAINGEAR Vector Pro 2 15 */567		.matches = {568			DMI_MATCH(DMI_SYS_VENDOR, "Micro Electronics Inc"),569			DMI_MATCH(DMI_PRODUCT_NAME, "MG-VCP2-15A3070T"),570		}571	},572	{573		/* MAINGEAR Vector Pro 2 17 */574		.matches = {575			DMI_MATCH(DMI_SYS_VENDOR, "Micro Electronics Inc"),576			DMI_MATCH(DMI_PRODUCT_NAME, "MG-VCP2-17A3070T"),577		},578	},579	{580		/* TongFang GM6BGEQ / PCSpecialist Elimina Pro 16 M, RTX 3050 */581		.matches = {582			DMI_MATCH(DMI_BOARD_NAME, "GM6BGEQ"),583		},584	},585	{586		/* TongFang GM6BG5Q, RTX 4050 */587		.matches = {588			DMI_MATCH(DMI_BOARD_NAME, "GM6BG5Q"),589		},590	},591	{592		/* TongFang GM6BG0Q / PCSpecialist Elimina Pro 16 M, RTX 4060 */593		.matches = {594			DMI_MATCH(DMI_BOARD_NAME, "GM6BG0Q"),595		},596	},597	{598		/* Infinity E15-5A165-BM */599		.matches = {600			DMI_MATCH(DMI_BOARD_NAME, "GM5RG1E0009COM"),601		},602	},603	{604		/* Infinity E15-5A305-1M */605		.matches = {606			DMI_MATCH(DMI_BOARD_NAME, "GM5RGEE0016COM"),607		},608	},609	{610		/* Lunnen Ground 15 / AMD Ryzen 5 5500U */611		.matches = {612			DMI_MATCH(DMI_SYS_VENDOR, "Lunnen"),613			DMI_MATCH(DMI_BOARD_NAME, "LLL5DAW"),614		},615	},616	{617		/* Lunnen Ground 16 / AMD Ryzen 7 5800U */618		.matches = {619			DMI_MATCH(DMI_SYS_VENDOR, "Lunnen"),620			DMI_MATCH(DMI_BOARD_NAME, "LL6FA"),621		},622	},623	{624		/* MAIBENBEN X577 */625		.matches = {626			DMI_MATCH(DMI_SYS_VENDOR, "MAIBENBEN"),627			DMI_MATCH(DMI_BOARD_NAME, "X577"),628		},629	},630	{631		/* Maibenben X565 */632		.matches = {633			DMI_MATCH(DMI_SYS_VENDOR, "MAIBENBEN"),634			DMI_MATCH(DMI_BOARD_NAME, "X565"),635		},636	},637	{638		/* TongFang GXxHRXx/TUXEDO InfinityBook Pro Gen9 AMD */639		.matches = {640			DMI_MATCH(DMI_BOARD_NAME, "GXxHRXx"),641		},642	},643	{644		/* TongFang GMxHGxx/TUXEDO Stellaris Slim Gen1 AMD */645		.matches = {646			DMI_MATCH(DMI_BOARD_NAME, "GMxHGxx"),647		},648	},649	{ }650};651 652struct irq_override_cmp {653	const struct dmi_system_id *system;654	unsigned char irq;655	unsigned char triggering;656	unsigned char polarity;657	unsigned char shareable;658	bool override;659};660 661static const struct irq_override_cmp override_table[] = {662	{ irq1_level_low_skip_override, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false },663	{ irq1_edge_low_force_override, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true },664};665 666static bool acpi_dev_irq_override(u32 gsi, u8 triggering, u8 polarity,667				  u8 shareable)668{669	int i;670 671	for (i = 0; i < ARRAY_SIZE(override_table); i++) {672		const struct irq_override_cmp *entry = &override_table[i];673 674		if (dmi_check_system(entry->system) &&675		    entry->irq == gsi &&676		    entry->triggering == triggering &&677		    entry->polarity == polarity &&678		    entry->shareable == shareable)679			return entry->override;680	}681 682#ifdef CONFIG_X86683	/*684	 * Always use the MADT override info, except for the i8042 PS/2 ctrl685	 * IRQs (1 and 12). For these the DSDT IRQ settings should sometimes686	 * be used otherwise PS/2 keyboards / mice will not work.687	 */688	if (gsi != 1 && gsi != 12)689		return true;690 691	/* If the override comes from an INT_SRC_OVR MADT entry, honor it. */692	if (acpi_int_src_ovr[gsi])693		return true;694 695	/*696	 * IRQ override isn't needed on modern AMD Zen systems and697	 * this override breaks active low IRQs on AMD Ryzen 6000 and698	 * newer systems. Skip it.699	 */700	if (boot_cpu_has(X86_FEATURE_ZEN))701		return false;702#endif703 704	return true;705}706 707static void acpi_dev_get_irqresource(struct resource *res, u32 gsi,708				     u8 triggering, u8 polarity, u8 shareable,709				     u8 wake_capable, bool check_override)710{711	int irq, p, t;712 713	if (!valid_IRQ(gsi)) {714		irqresource_disabled(res, gsi);715		return;716	}717 718	/*719	 * In IO-APIC mode, use overridden attribute. Two reasons:720	 * 1. BIOS bug in DSDT721	 * 2. BIOS uses IO-APIC mode Interrupt Source Override722	 *723	 * We do this only if we are dealing with IRQ() or IRQNoFlags()724	 * resource (the legacy ISA resources). With modern ACPI 5 devices725	 * using extended IRQ descriptors we take the IRQ configuration726	 * from _CRS directly.727	 */728	if (check_override &&729	    acpi_dev_irq_override(gsi, triggering, polarity, shareable) &&730	    !acpi_get_override_irq(gsi, &t, &p)) {731		u8 trig = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;732		u8 pol = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;733 734		if (triggering != trig || polarity != pol) {735			pr_warn("ACPI: IRQ %d override to %s%s, %s%s\n", gsi,736				t ? "level" : "edge",737				trig == triggering ? "" : "(!)",738				p ? "low" : "high",739				pol == polarity ? "" : "(!)");740			triggering = trig;741			polarity = pol;742		}743	}744 745	res->flags = acpi_dev_irq_flags(triggering, polarity, shareable, wake_capable);746	irq = acpi_register_gsi(NULL, gsi, triggering, polarity);747	if (irq >= 0) {748		res->start = irq;749		res->end = irq;750	} else {751		irqresource_disabled(res, gsi);752	}753}754 755/**756 * acpi_dev_resource_interrupt - Extract ACPI interrupt resource information.757 * @ares: Input ACPI resource object.758 * @index: Index into the array of GSIs represented by the resource.759 * @res: Output generic resource object.760 *761 * Check if the given ACPI resource object represents an interrupt resource762 * and @index does not exceed the resource's interrupt count (true is returned763 * in that case regardless of the results of the other checks)).  If that's the764 * case, register the GSI corresponding to @index from the array of interrupts765 * represented by the resource and populate the generic resource object pointed766 * to by @res accordingly.  If the registration of the GSI is not successful,767 * IORESOURCE_DISABLED will be set it that object's flags.768 *769 * Return:770 * 1) false with res->flags setting to zero: not the expected resource type771 * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource772 * 3) true: valid assigned resource773 */774bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,775				 struct resource *res)776{777	struct acpi_resource_irq *irq;778	struct acpi_resource_extended_irq *ext_irq;779 780	switch (ares->type) {781	case ACPI_RESOURCE_TYPE_IRQ:782		/*783		 * Per spec, only one interrupt per descriptor is allowed in784		 * _CRS, but some firmware violates this, so parse them all.785		 */786		irq = &ares->data.irq;787		if (index >= irq->interrupt_count) {788			irqresource_disabled(res, 0);789			return false;790		}791		acpi_dev_get_irqresource(res, irq->interrupts[index],792					 irq->triggering, irq->polarity,793					 irq->shareable, irq->wake_capable,794					 true);795		break;796	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:797		ext_irq = &ares->data.extended_irq;798		if (index >= ext_irq->interrupt_count) {799			irqresource_disabled(res, 0);800			return false;801		}802		if (is_gsi(ext_irq))803			acpi_dev_get_irqresource(res, ext_irq->interrupts[index],804					 ext_irq->triggering, ext_irq->polarity,805					 ext_irq->shareable, ext_irq->wake_capable,806					 false);807		else808			irqresource_disabled(res, 0);809		break;810	default:811		res->flags = 0;812		return false;813	}814 815	return true;816}817EXPORT_SYMBOL_GPL(acpi_dev_resource_interrupt);818 819/**820 * acpi_dev_free_resource_list - Free resource from %acpi_dev_get_resources().821 * @list: The head of the resource list to free.822 */823void acpi_dev_free_resource_list(struct list_head *list)824{825	resource_list_free(list);826}827EXPORT_SYMBOL_GPL(acpi_dev_free_resource_list);828 829struct res_proc_context {830	struct list_head *list;831	int (*preproc)(struct acpi_resource *, void *);832	void *preproc_data;833	int count;834	int error;835};836 837static acpi_status acpi_dev_new_resource_entry(struct resource_win *win,838					       struct res_proc_context *c)839{840	struct resource_entry *rentry;841 842	rentry = resource_list_create_entry(NULL, 0);843	if (!rentry) {844		c->error = -ENOMEM;845		return AE_NO_MEMORY;846	}847	*rentry->res = win->res;848	rentry->offset = win->offset;849	resource_list_add_tail(rentry, c->list);850	c->count++;851	return AE_OK;852}853 854static acpi_status acpi_dev_process_resource(struct acpi_resource *ares,855					     void *context)856{857	struct res_proc_context *c = context;858	struct resource_win win;859	struct resource *res = &win.res;860	int i;861 862	if (c->preproc) {863		int ret;864 865		ret = c->preproc(ares, c->preproc_data);866		if (ret < 0) {867			c->error = ret;868			return AE_ABORT_METHOD;869		} else if (ret > 0) {870			return AE_OK;871		}872	}873 874	memset(&win, 0, sizeof(win));875 876	if (acpi_dev_resource_memory(ares, res)877	    || acpi_dev_resource_io(ares, res)878	    || acpi_dev_resource_address_space(ares, &win)879	    || acpi_dev_resource_ext_address_space(ares, &win))880		return acpi_dev_new_resource_entry(&win, c);881 882	for (i = 0; acpi_dev_resource_interrupt(ares, i, res); i++) {883		acpi_status status;884 885		status = acpi_dev_new_resource_entry(&win, c);886		if (ACPI_FAILURE(status))887			return status;888	}889 890	return AE_OK;891}892 893static int __acpi_dev_get_resources(struct acpi_device *adev,894				    struct list_head *list,895				    int (*preproc)(struct acpi_resource *, void *),896				    void *preproc_data, char *method)897{898	struct res_proc_context c;899	acpi_status status;900 901	if (!adev || !adev->handle || !list_empty(list))902		return -EINVAL;903 904	if (!acpi_has_method(adev->handle, method))905		return 0;906 907	c.list = list;908	c.preproc = preproc;909	c.preproc_data = preproc_data;910	c.count = 0;911	c.error = 0;912	status = acpi_walk_resources(adev->handle, method,913				     acpi_dev_process_resource, &c);914	if (ACPI_FAILURE(status)) {915		acpi_dev_free_resource_list(list);916		return c.error ? c.error : -EIO;917	}918 919	return c.count;920}921 922/**923 * acpi_dev_get_resources - Get current resources of a device.924 * @adev: ACPI device node to get the resources for.925 * @list: Head of the resultant list of resources (must be empty).926 * @preproc: The caller's preprocessing routine.927 * @preproc_data: Pointer passed to the caller's preprocessing routine.928 *929 * Evaluate the _CRS method for the given device node and process its output by930 * (1) executing the @preproc() routine provided by the caller, passing the931 * resource pointer and @preproc_data to it as arguments, for each ACPI resource932 * returned and (2) converting all of the returned ACPI resources into struct933 * resource objects if possible.  If the return value of @preproc() in step (1)934 * is different from 0, step (2) is not applied to the given ACPI resource and935 * if that value is negative, the whole processing is aborted and that value is936 * returned as the final error code.937 *938 * The resultant struct resource objects are put on the list pointed to by939 * @list, that must be empty initially, as members of struct resource_entry940 * objects.  Callers of this routine should use %acpi_dev_free_resource_list() to941 * free that list.942 *943 * The number of resources in the output list is returned on success, an error944 * code reflecting the error condition is returned otherwise.945 */946int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list,947			   int (*preproc)(struct acpi_resource *, void *),948			   void *preproc_data)949{950	return __acpi_dev_get_resources(adev, list, preproc, preproc_data,951					METHOD_NAME__CRS);952}953EXPORT_SYMBOL_GPL(acpi_dev_get_resources);954 955static int is_memory(struct acpi_resource *ares, void *not_used)956{957	struct resource_win win;958	struct resource *res = &win.res;959 960	memset(&win, 0, sizeof(win));961 962	if (acpi_dev_filter_resource_type(ares, IORESOURCE_MEM))963		return 1;964 965	return !(acpi_dev_resource_memory(ares, res)966	       || acpi_dev_resource_address_space(ares, &win)967	       || acpi_dev_resource_ext_address_space(ares, &win));968}969 970/**971 * acpi_dev_get_dma_resources - Get current DMA resources of a device.972 * @adev: ACPI device node to get the resources for.973 * @list: Head of the resultant list of resources (must be empty).974 *975 * Evaluate the _DMA method for the given device node and process its976 * output.977 *978 * The resultant struct resource objects are put on the list pointed to979 * by @list, that must be empty initially, as members of struct980 * resource_entry objects.  Callers of this routine should use981 * %acpi_dev_free_resource_list() to free that list.982 *983 * The number of resources in the output list is returned on success,984 * an error code reflecting the error condition is returned otherwise.985 */986int acpi_dev_get_dma_resources(struct acpi_device *adev, struct list_head *list)987{988	return __acpi_dev_get_resources(adev, list, is_memory, NULL,989					METHOD_NAME__DMA);990}991EXPORT_SYMBOL_GPL(acpi_dev_get_dma_resources);992 993/**994 * acpi_dev_get_memory_resources - Get current memory resources of a device.995 * @adev: ACPI device node to get the resources for.996 * @list: Head of the resultant list of resources (must be empty).997 *998 * This is a helper function that locates all memory type resources of @adev999 * with acpi_dev_get_resources().1000 *1001 * The number of resources in the output list is returned on success, an error1002 * code reflecting the error condition is returned otherwise.1003 */1004int acpi_dev_get_memory_resources(struct acpi_device *adev, struct list_head *list)1005{1006	return acpi_dev_get_resources(adev, list, is_memory, NULL);1007}1008EXPORT_SYMBOL_GPL(acpi_dev_get_memory_resources);1009 1010/**1011 * acpi_dev_filter_resource_type - Filter ACPI resource according to resource1012 *				   types1013 * @ares: Input ACPI resource object.1014 * @types: Valid resource types of IORESOURCE_XXX1015 *1016 * This is a helper function to support acpi_dev_get_resources(), which filters1017 * ACPI resource objects according to resource types.1018 */1019int acpi_dev_filter_resource_type(struct acpi_resource *ares,1020				  unsigned long types)1021{1022	unsigned long type = 0;1023 1024	switch (ares->type) {1025	case ACPI_RESOURCE_TYPE_MEMORY24:1026	case ACPI_RESOURCE_TYPE_MEMORY32:1027	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:1028		type = IORESOURCE_MEM;1029		break;1030	case ACPI_RESOURCE_TYPE_IO:1031	case ACPI_RESOURCE_TYPE_FIXED_IO:1032		type = IORESOURCE_IO;1033		break;1034	case ACPI_RESOURCE_TYPE_IRQ:1035	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:1036		type = IORESOURCE_IRQ;1037		break;1038	case ACPI_RESOURCE_TYPE_DMA:1039	case ACPI_RESOURCE_TYPE_FIXED_DMA:1040		type = IORESOURCE_DMA;1041		break;1042	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:1043		type = IORESOURCE_REG;1044		break;1045	case ACPI_RESOURCE_TYPE_ADDRESS16:1046	case ACPI_RESOURCE_TYPE_ADDRESS32:1047	case ACPI_RESOURCE_TYPE_ADDRESS64:1048	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:1049		if (ares->data.address.resource_type == ACPI_MEMORY_RANGE)1050			type = IORESOURCE_MEM;1051		else if (ares->data.address.resource_type == ACPI_IO_RANGE)1052			type = IORESOURCE_IO;1053		else if (ares->data.address.resource_type ==1054			 ACPI_BUS_NUMBER_RANGE)1055			type = IORESOURCE_BUS;1056		break;1057	default:1058		break;1059	}1060 1061	return (type & types) ? 0 : 1;1062}1063EXPORT_SYMBOL_GPL(acpi_dev_filter_resource_type);1064 1065static int acpi_dev_consumes_res(struct acpi_device *adev, struct resource *res)1066{1067	struct list_head resource_list;1068	struct resource_entry *rentry;1069	int ret, found = 0;1070 1071	INIT_LIST_HEAD(&resource_list);1072	ret = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);1073	if (ret < 0)1074		return 0;1075 1076	list_for_each_entry(rentry, &resource_list, node) {1077		if (resource_contains(rentry->res, res)) {1078			found = 1;1079			break;1080		}1081 1082	}1083 1084	acpi_dev_free_resource_list(&resource_list);1085	return found;1086}1087 1088static acpi_status acpi_res_consumer_cb(acpi_handle handle, u32 depth,1089					 void *context, void **ret)1090{1091	struct resource *res = context;1092	struct acpi_device **consumer = (struct acpi_device **) ret;1093	struct acpi_device *adev = acpi_fetch_acpi_dev(handle);1094 1095	if (!adev)1096		return AE_OK;1097 1098	if (acpi_dev_consumes_res(adev, res)) {1099		*consumer = adev;1100		return AE_CTRL_TERMINATE;1101	}1102 1103	return AE_OK;1104}1105 1106/**1107 * acpi_resource_consumer - Find the ACPI device that consumes @res.1108 * @res: Resource to search for.1109 *1110 * Search the current resource settings (_CRS) of every ACPI device node1111 * for @res.  If we find an ACPI device whose _CRS includes @res, return1112 * it.  Otherwise, return NULL.1113 */1114struct acpi_device *acpi_resource_consumer(struct resource *res)1115{1116	struct acpi_device *consumer = NULL;1117 1118	acpi_get_devices(NULL, acpi_res_consumer_cb, res, (void **) &consumer);1119	return consumer;1120}1121