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