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