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