1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * PCI Express Hot Plug Controller Driver 4 * 5 * Copyright (C) 1995,2001 Compaq Computer Corporation 6 * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) 7 * Copyright (C) 2001 IBM Corp. 8 * Copyright (C) 2003-2004 Intel Corporation 9 * 10 * All rights reserved. 11 * 12 * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com> 13 * 14 */ 15 16 #define dev_fmt(fmt) "pciehp: " fmt 17 18 #include <linux/kernel.h> 19 #include <linux/types.h> 20 #include <linux/pm_runtime.h> 21 #include <linux/pci.h> 22 #include "pciehp.h" 23 24 /* The following routines constitute the bulk of the 25 hotplug controller logic 26 */ 27 28 #define SAFE_REMOVAL true 29 #define SURPRISE_REMOVAL false 30 31 static void set_slot_off(struct controller *ctrl) 32 { 33 /* turn off slot, turn on Amber LED, turn off Green LED if supported*/ 34 if (POWER_CTRL(ctrl)) { 35 pciehp_power_off_slot(ctrl); 36 37 /* 38 * After turning power off, we must wait for at least 1 second 39 * before taking any action that relies on power having been 40 * removed from the slot/adapter. 41 */ 42 msleep(1000); 43 } 44 45 pciehp_green_led_off(ctrl); 46 pciehp_set_attention_status(ctrl, 1); 47 } 48 49 /** 50 * board_added - Called after a board has been added to the system. 51 * @ctrl: PCIe hotplug controller where board is added 52 * 53 * Turns power on for the board. 54 * Configures board. 55 */ 56 static int board_added(struct controller *ctrl) 57 { 58 int retval = 0; 59 struct pci_bus *parent = ctrl->pcie->port->subordinate; 60 61 if (POWER_CTRL(ctrl)) { 62 /* Power on slot */ 63 retval = pciehp_power_on_slot(ctrl); 64 if (retval) 65 return retval; 66 } 67 68 pciehp_green_led_blink(ctrl); 69 70 /* Check link training status */ 71 retval = pciehp_check_link_status(ctrl); 72 if (retval) { 73 ctrl_err(ctrl, "Failed to check link status\n"); 74 goto err_exit; 75 } 76 77 /* Check for a power fault */ 78 if (ctrl->power_fault_detected || pciehp_query_power_fault(ctrl)) { 79 ctrl_err(ctrl, "Slot(%s): Power fault\n", slot_name(ctrl)); 80 retval = -EIO; 81 goto err_exit; 82 } 83 84 retval = pciehp_configure_device(ctrl); 85 if (retval) { 86 if (retval != -EEXIST) { 87 ctrl_err(ctrl, "Cannot add device at %04x:%02x:00\n", 88 pci_domain_nr(parent), parent->number); 89 goto err_exit; 90 } 91 } 92 93 pciehp_green_led_on(ctrl); 94 pciehp_set_attention_status(ctrl, 0); 95 return 0; 96 97 err_exit: 98 set_slot_off(ctrl); 99 return retval; 100 } 101 102 /** 103 * remove_board - Turns off slot and LEDs 104 * @ctrl: PCIe hotplug controller where board is being removed 105 * @safe_removal: whether the board is safely removed (versus surprise removed) 106 */ 107 static void remove_board(struct controller *ctrl, bool safe_removal) 108 { 109 pciehp_unconfigure_device(ctrl, safe_removal); 110 111 if (POWER_CTRL(ctrl)) { 112 pciehp_power_off_slot(ctrl); 113 114 /* 115 * After turning power off, we must wait for at least 1 second 116 * before taking any action that relies on power having been 117 * removed from the slot/adapter. 118 */ 119 msleep(1000); 120 121 /* Ignore link or presence changes caused by power off */ 122 atomic_and(~(PCI_EXP_SLTSTA_DLLSC | PCI_EXP_SLTSTA_PDC), 123 &ctrl->pending_events); 124 } 125 126 /* turn off Green LED */ 127 pciehp_green_led_off(ctrl); 128 } 129 130 static int pciehp_enable_slot(struct controller *ctrl); 131 static int pciehp_disable_slot(struct controller *ctrl, bool safe_removal); 132 133 void pciehp_request(struct controller *ctrl, int action) 134 { 135 atomic_or(action, &ctrl->pending_events); 136 if (!pciehp_poll_mode) 137 irq_wake_thread(ctrl->pcie->irq, ctrl); 138 } 139 140 void pciehp_queue_pushbutton_work(struct work_struct *work) 141 { 142 struct controller *ctrl = container_of(work, struct controller, 143 button_work.work); 144 145 mutex_lock(&ctrl->state_lock); 146 switch (ctrl->state) { 147 case BLINKINGOFF_STATE: 148 pciehp_request(ctrl, DISABLE_SLOT); 149 break; 150 case BLINKINGON_STATE: 151 pciehp_request(ctrl, PCI_EXP_SLTSTA_PDC); 152 break; 153 default: 154 break; 155 } 156 mutex_unlock(&ctrl->state_lock); 157 } 158 159 void pciehp_handle_button_press(struct controller *ctrl) 160 { 161 mutex_lock(&ctrl->state_lock); 162 switch (ctrl->state) { 163 case OFF_STATE: 164 case ON_STATE: 165 if (ctrl->state == ON_STATE) { 166 ctrl->state = BLINKINGOFF_STATE; 167 ctrl_info(ctrl, "Slot(%s): Powering off due to button press\n", 168 slot_name(ctrl)); 169 } else { 170 ctrl->state = BLINKINGON_STATE; 171 ctrl_info(ctrl, "Slot(%s) Powering on due to button press\n", 172 slot_name(ctrl)); 173 } 174 /* blink green LED and turn off amber */ 175 pciehp_green_led_blink(ctrl); 176 pciehp_set_attention_status(ctrl, 0); 177 schedule_delayed_work(&ctrl->button_work, 5 * HZ); 178 break; 179 case BLINKINGOFF_STATE: 180 case BLINKINGON_STATE: 181 /* 182 * Cancel if we are still blinking; this means that we 183 * press the attention again before the 5 sec. limit 184 * expires to cancel hot-add or hot-remove 185 */ 186 ctrl_info(ctrl, "Slot(%s): Button cancel\n", slot_name(ctrl)); 187 cancel_delayed_work(&ctrl->button_work); 188 if (ctrl->state == BLINKINGOFF_STATE) { 189 ctrl->state = ON_STATE; 190 pciehp_green_led_on(ctrl); 191 } else { 192 ctrl->state = OFF_STATE; 193 pciehp_green_led_off(ctrl); 194 } 195 pciehp_set_attention_status(ctrl, 0); 196 ctrl_info(ctrl, "Slot(%s): Action canceled due to button press\n", 197 slot_name(ctrl)); 198 break; 199 default: 200 ctrl_err(ctrl, "Slot(%s): Ignoring invalid state %#x\n", 201 slot_name(ctrl), ctrl->state); 202 break; 203 } 204 mutex_unlock(&ctrl->state_lock); 205 } 206 207 void pciehp_handle_disable_request(struct controller *ctrl) 208 { 209 mutex_lock(&ctrl->state_lock); 210 switch (ctrl->state) { 211 case BLINKINGON_STATE: 212 case BLINKINGOFF_STATE: 213 cancel_delayed_work(&ctrl->button_work); 214 break; 215 } 216 ctrl->state = POWEROFF_STATE; 217 mutex_unlock(&ctrl->state_lock); 218 219 ctrl->request_result = pciehp_disable_slot(ctrl, SAFE_REMOVAL); 220 } 221 222 void pciehp_handle_presence_or_link_change(struct controller *ctrl, u32 events) 223 { 224 bool present, link_active; 225 226 /* 227 * If the slot is on and presence or link has changed, turn it off. 228 * Even if it's occupied again, we cannot assume the card is the same. 229 */ 230 mutex_lock(&ctrl->state_lock); 231 switch (ctrl->state) { 232 case BLINKINGOFF_STATE: 233 cancel_delayed_work(&ctrl->button_work); 234 /* fall through */ 235 case ON_STATE: 236 ctrl->state = POWEROFF_STATE; 237 mutex_unlock(&ctrl->state_lock); 238 if (events & PCI_EXP_SLTSTA_DLLSC) 239 ctrl_info(ctrl, "Slot(%s): Link Down\n", 240 slot_name(ctrl)); 241 if (events & PCI_EXP_SLTSTA_PDC) 242 ctrl_info(ctrl, "Slot(%s): Card not present\n", 243 slot_name(ctrl)); 244 pciehp_disable_slot(ctrl, SURPRISE_REMOVAL); 245 break; 246 default: 247 mutex_unlock(&ctrl->state_lock); 248 break; 249 } 250 251 /* Turn the slot on if it's occupied or link is up */ 252 mutex_lock(&ctrl->state_lock); 253 present = pciehp_card_present(ctrl); 254 link_active = pciehp_check_link_active(ctrl); 255 if (!present && !link_active) { 256 mutex_unlock(&ctrl->state_lock); 257 return; 258 } 259 260 switch (ctrl->state) { 261 case BLINKINGON_STATE: 262 cancel_delayed_work(&ctrl->button_work); 263 /* fall through */ 264 case OFF_STATE: 265 ctrl->state = POWERON_STATE; 266 mutex_unlock(&ctrl->state_lock); 267 if (present) 268 ctrl_info(ctrl, "Slot(%s): Card present\n", 269 slot_name(ctrl)); 270 if (link_active) 271 ctrl_info(ctrl, "Slot(%s): Link Up\n", 272 slot_name(ctrl)); 273 ctrl->request_result = pciehp_enable_slot(ctrl); 274 break; 275 default: 276 mutex_unlock(&ctrl->state_lock); 277 break; 278 } 279 } 280 281 static int __pciehp_enable_slot(struct controller *ctrl) 282 { 283 u8 getstatus = 0; 284 285 if (MRL_SENS(ctrl)) { 286 pciehp_get_latch_status(ctrl, &getstatus); 287 if (getstatus) { 288 ctrl_info(ctrl, "Slot(%s): Latch open\n", 289 slot_name(ctrl)); 290 return -ENODEV; 291 } 292 } 293 294 if (POWER_CTRL(ctrl)) { 295 pciehp_get_power_status(ctrl, &getstatus); 296 if (getstatus) { 297 ctrl_info(ctrl, "Slot(%s): Already enabled\n", 298 slot_name(ctrl)); 299 return 0; 300 } 301 } 302 303 return board_added(ctrl); 304 } 305 306 static int pciehp_enable_slot(struct controller *ctrl) 307 { 308 int ret; 309 310 pm_runtime_get_sync(&ctrl->pcie->port->dev); 311 ret = __pciehp_enable_slot(ctrl); 312 if (ret && ATTN_BUTTN(ctrl)) 313 pciehp_green_led_off(ctrl); /* may be blinking */ 314 pm_runtime_put(&ctrl->pcie->port->dev); 315 316 mutex_lock(&ctrl->state_lock); 317 ctrl->state = ret ? OFF_STATE : ON_STATE; 318 mutex_unlock(&ctrl->state_lock); 319 320 return ret; 321 } 322 323 static int __pciehp_disable_slot(struct controller *ctrl, bool safe_removal) 324 { 325 u8 getstatus = 0; 326 327 if (POWER_CTRL(ctrl)) { 328 pciehp_get_power_status(ctrl, &getstatus); 329 if (!getstatus) { 330 ctrl_info(ctrl, "Slot(%s): Already disabled\n", 331 slot_name(ctrl)); 332 return -EINVAL; 333 } 334 } 335 336 remove_board(ctrl, safe_removal); 337 return 0; 338 } 339 340 static int pciehp_disable_slot(struct controller *ctrl, bool safe_removal) 341 { 342 int ret; 343 344 pm_runtime_get_sync(&ctrl->pcie->port->dev); 345 ret = __pciehp_disable_slot(ctrl, safe_removal); 346 pm_runtime_put(&ctrl->pcie->port->dev); 347 348 mutex_lock(&ctrl->state_lock); 349 ctrl->state = OFF_STATE; 350 mutex_unlock(&ctrl->state_lock); 351 352 return ret; 353 } 354 355 int pciehp_sysfs_enable_slot(struct hotplug_slot *hotplug_slot) 356 { 357 struct controller *ctrl = to_ctrl(hotplug_slot); 358 359 mutex_lock(&ctrl->state_lock); 360 switch (ctrl->state) { 361 case BLINKINGON_STATE: 362 case OFF_STATE: 363 mutex_unlock(&ctrl->state_lock); 364 /* 365 * The IRQ thread becomes a no-op if the user pulls out the 366 * card before the thread wakes up, so initialize to -ENODEV. 367 */ 368 ctrl->request_result = -ENODEV; 369 pciehp_request(ctrl, PCI_EXP_SLTSTA_PDC); 370 wait_event(ctrl->requester, 371 !atomic_read(&ctrl->pending_events)); 372 return ctrl->request_result; 373 case POWERON_STATE: 374 ctrl_info(ctrl, "Slot(%s): Already in powering on state\n", 375 slot_name(ctrl)); 376 break; 377 case BLINKINGOFF_STATE: 378 case ON_STATE: 379 case POWEROFF_STATE: 380 ctrl_info(ctrl, "Slot(%s): Already enabled\n", 381 slot_name(ctrl)); 382 break; 383 default: 384 ctrl_err(ctrl, "Slot(%s): Invalid state %#x\n", 385 slot_name(ctrl), ctrl->state); 386 break; 387 } 388 mutex_unlock(&ctrl->state_lock); 389 390 return -ENODEV; 391 } 392 393 int pciehp_sysfs_disable_slot(struct hotplug_slot *hotplug_slot) 394 { 395 struct controller *ctrl = to_ctrl(hotplug_slot); 396 397 mutex_lock(&ctrl->state_lock); 398 switch (ctrl->state) { 399 case BLINKINGOFF_STATE: 400 case ON_STATE: 401 mutex_unlock(&ctrl->state_lock); 402 pciehp_request(ctrl, DISABLE_SLOT); 403 wait_event(ctrl->requester, 404 !atomic_read(&ctrl->pending_events)); 405 return ctrl->request_result; 406 case POWEROFF_STATE: 407 ctrl_info(ctrl, "Slot(%s): Already in powering off state\n", 408 slot_name(ctrl)); 409 break; 410 case BLINKINGON_STATE: 411 case OFF_STATE: 412 case POWERON_STATE: 413 ctrl_info(ctrl, "Slot(%s): Already disabled\n", 414 slot_name(ctrl)); 415 break; 416 default: 417 ctrl_err(ctrl, "Slot(%s): Invalid state %#x\n", 418 slot_name(ctrl), ctrl->state); 419 break; 420 } 421 mutex_unlock(&ctrl->state_lock); 422 423 return -ENODEV; 424 } 425