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