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