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