xref: /openbmc/linux/drivers/pci/hotplug/acpi_pcihp.c (revision ddc141e5)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Common ACPI functions for hot plug platforms
4  *
5  * Copyright (C) 2006 Intel Corporation
6  *
7  * All rights reserved.
8  *
9  * Send feedback to <kristen.c.accardi@intel.com>
10  *
11  */
12 
13 #include <linux/module.h>
14 #include <linux/moduleparam.h>
15 #include <linux/kernel.h>
16 #include <linux/types.h>
17 #include <linux/pci.h>
18 #include <linux/pci_hotplug.h>
19 #include <linux/acpi.h>
20 #include <linux/pci-acpi.h>
21 #include <linux/slab.h>
22 
23 #define MY_NAME	"acpi_pcihp"
24 
25 #define dbg(fmt, arg...) do { if (debug_acpi) printk(KERN_DEBUG "%s: %s: " fmt, MY_NAME, __func__, ## arg); } while (0)
26 #define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME, ## arg)
27 #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME, ## arg)
28 #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME, ## arg)
29 
30 #define	METHOD_NAME__SUN	"_SUN"
31 #define	METHOD_NAME_OSHP	"OSHP"
32 
33 static bool debug_acpi;
34 
35 /* acpi_run_oshp - get control of hotplug from the firmware
36  *
37  * @handle - the handle of the hotplug controller.
38  */
39 static acpi_status acpi_run_oshp(acpi_handle handle)
40 {
41 	acpi_status		status;
42 	struct acpi_buffer	string = { ACPI_ALLOCATE_BUFFER, NULL };
43 
44 	acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
45 
46 	/* run OSHP */
47 	status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
48 	if (ACPI_FAILURE(status))
49 		if (status != AE_NOT_FOUND)
50 			printk(KERN_ERR "%s:%s OSHP fails=0x%x\n",
51 			       __func__, (char *)string.pointer, status);
52 		else
53 			dbg("%s:%s OSHP not found\n",
54 			    __func__, (char *)string.pointer);
55 	else
56 		pr_debug("%s:%s OSHP passes\n", __func__,
57 			(char *)string.pointer);
58 
59 	kfree(string.pointer);
60 	return status;
61 }
62 
63 /**
64  * acpi_get_hp_hw_control_from_firmware
65  * @dev: the pci_dev of the bridge that has a hotplug controller
66  * @flags: requested control bits for _OSC
67  *
68  * Attempt to take hotplug control from firmware.
69  */
70 int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags)
71 {
72 	acpi_status status;
73 	acpi_handle chandle, handle;
74 	struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL };
75 
76 	flags &= OSC_PCI_SHPC_NATIVE_HP_CONTROL;
77 	if (!flags) {
78 		err("Invalid flags %u specified!\n", flags);
79 		return -EINVAL;
80 	}
81 
82 	/*
83 	 * Per PCI firmware specification, we should run the ACPI _OSC
84 	 * method to get control of hotplug hardware before using it. If
85 	 * an _OSC is missing, we look for an OSHP to do the same thing.
86 	 * To handle different BIOS behavior, we look for _OSC on a root
87 	 * bridge preferentially (according to PCI fw spec). Later for
88 	 * OSHP within the scope of the hotplug controller and its parents,
89 	 * up to the host bridge under which this controller exists.
90 	 */
91 	handle = acpi_find_root_bridge_handle(pdev);
92 	if (handle) {
93 		acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
94 		dbg("Trying to get hotplug control for %s\n",
95 				(char *)string.pointer);
96 		status = acpi_pci_osc_control_set(handle, &flags, flags);
97 		if (ACPI_SUCCESS(status))
98 			goto got_one;
99 		if (status == AE_SUPPORT)
100 			goto no_control;
101 		kfree(string.pointer);
102 		string = (struct acpi_buffer){ ACPI_ALLOCATE_BUFFER, NULL };
103 	}
104 
105 	handle = ACPI_HANDLE(&pdev->dev);
106 	if (!handle) {
107 		/*
108 		 * This hotplug controller was not listed in the ACPI name
109 		 * space at all. Try to get acpi handle of parent pci bus.
110 		 */
111 		struct pci_bus *pbus;
112 		for (pbus = pdev->bus; pbus; pbus = pbus->parent) {
113 			handle = acpi_pci_get_bridge_handle(pbus);
114 			if (handle)
115 				break;
116 		}
117 	}
118 
119 	while (handle) {
120 		acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
121 		dbg("Trying to get hotplug control for %s\n",
122 		    (char *)string.pointer);
123 		status = acpi_run_oshp(handle);
124 		if (ACPI_SUCCESS(status))
125 			goto got_one;
126 		if (acpi_is_root_bridge(handle))
127 			break;
128 		chandle = handle;
129 		status = acpi_get_parent(chandle, &handle);
130 		if (ACPI_FAILURE(status))
131 			break;
132 	}
133 no_control:
134 	dbg("Cannot get control of hotplug hardware for pci %s\n",
135 	    pci_name(pdev));
136 	kfree(string.pointer);
137 	return -ENODEV;
138 got_one:
139 	dbg("Gained control for hotplug HW for pci %s (%s)\n",
140 	    pci_name(pdev), (char *)string.pointer);
141 	kfree(string.pointer);
142 	return 0;
143 }
144 EXPORT_SYMBOL(acpi_get_hp_hw_control_from_firmware);
145 
146 static int pcihp_is_ejectable(acpi_handle handle)
147 {
148 	acpi_status status;
149 	unsigned long long removable;
150 	if (!acpi_has_method(handle, "_ADR"))
151 		return 0;
152 	if (acpi_has_method(handle, "_EJ0"))
153 		return 1;
154 	status = acpi_evaluate_integer(handle, "_RMV", NULL, &removable);
155 	if (ACPI_SUCCESS(status) && removable)
156 		return 1;
157 	return 0;
158 }
159 
160 /**
161  * acpi_pcihp_check_ejectable - check if handle is ejectable ACPI PCI slot
162  * @pbus: the PCI bus of the PCI slot corresponding to 'handle'
163  * @handle: ACPI handle to check
164  *
165  * Return 1 if handle is ejectable PCI slot, 0 otherwise.
166  */
167 int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle handle)
168 {
169 	acpi_handle bridge_handle, parent_handle;
170 
171 	bridge_handle = acpi_pci_get_bridge_handle(pbus);
172 	if (!bridge_handle)
173 		return 0;
174 	if ((ACPI_FAILURE(acpi_get_parent(handle, &parent_handle))))
175 		return 0;
176 	if (bridge_handle != parent_handle)
177 		return 0;
178 	return pcihp_is_ejectable(handle);
179 }
180 EXPORT_SYMBOL_GPL(acpi_pci_check_ejectable);
181 
182 static acpi_status
183 check_hotplug(acpi_handle handle, u32 lvl, void *context, void **rv)
184 {
185 	int *found = (int *)context;
186 	if (pcihp_is_ejectable(handle)) {
187 		*found = 1;
188 		return AE_CTRL_TERMINATE;
189 	}
190 	return AE_OK;
191 }
192 
193 /**
194  * acpi_pci_detect_ejectable - check if the PCI bus has ejectable slots
195  * @handle - handle of the PCI bus to scan
196  *
197  * Returns 1 if the PCI bus has ACPI based ejectable slots, 0 otherwise.
198  */
199 int acpi_pci_detect_ejectable(acpi_handle handle)
200 {
201 	int found = 0;
202 
203 	if (!handle)
204 		return found;
205 
206 	acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
207 			    check_hotplug, NULL, (void *)&found, NULL);
208 	return found;
209 }
210 EXPORT_SYMBOL_GPL(acpi_pci_detect_ejectable);
211 
212 module_param(debug_acpi, bool, 0644);
213 MODULE_PARM_DESC(debug_acpi, "Debugging mode for ACPI enabled or not");
214