1 /* 2 * PCI Express Hot Plug Controller Driver 3 * 4 * Copyright (C) 1995,2001 Compaq Computer Corporation 5 * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) 6 * Copyright (C) 2001 IBM Corp. 7 * Copyright (C) 2003-2004 Intel Corporation 8 * 9 * All rights reserved. 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or (at 14 * your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, but 17 * WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 19 * NON INFRINGEMENT. See the GNU General Public License for more 20 * details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, write to the Free Software 24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 25 * 26 * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com> 27 * 28 */ 29 30 #include <linux/module.h> 31 #include <linux/kernel.h> 32 #include <linux/types.h> 33 #include <linux/pci.h> 34 #include <linux/workqueue.h> 35 #include "../pci.h" 36 #include "pciehp.h" 37 38 static void interrupt_event_handler(struct work_struct *work); 39 40 static int queue_interrupt_event(struct slot *p_slot, u32 event_type) 41 { 42 struct event_info *info; 43 44 info = kmalloc(sizeof(*info), GFP_ATOMIC); 45 if (!info) 46 return -ENOMEM; 47 48 info->event_type = event_type; 49 info->p_slot = p_slot; 50 INIT_WORK(&info->work, interrupt_event_handler); 51 52 schedule_work(&info->work); 53 54 return 0; 55 } 56 57 u8 pciehp_handle_attention_button(struct slot *p_slot) 58 { 59 u32 event_type; 60 struct controller *ctrl = p_slot->ctrl; 61 62 /* Attention Button Change */ 63 ctrl_dbg(ctrl, "Attention button interrupt received\n"); 64 65 /* 66 * Button pressed - See if need to TAKE ACTION!!! 67 */ 68 ctrl_info(ctrl, "Button pressed on Slot(%s)\n", slot_name(p_slot)); 69 event_type = INT_BUTTON_PRESS; 70 71 queue_interrupt_event(p_slot, event_type); 72 73 return 0; 74 } 75 76 u8 pciehp_handle_switch_change(struct slot *p_slot) 77 { 78 u8 getstatus; 79 u32 event_type; 80 struct controller *ctrl = p_slot->ctrl; 81 82 /* Switch Change */ 83 ctrl_dbg(ctrl, "Switch interrupt received\n"); 84 85 pciehp_get_latch_status(p_slot, &getstatus); 86 if (getstatus) { 87 /* 88 * Switch opened 89 */ 90 ctrl_info(ctrl, "Latch open on Slot(%s)\n", slot_name(p_slot)); 91 event_type = INT_SWITCH_OPEN; 92 } else { 93 /* 94 * Switch closed 95 */ 96 ctrl_info(ctrl, "Latch close on Slot(%s)\n", slot_name(p_slot)); 97 event_type = INT_SWITCH_CLOSE; 98 } 99 100 queue_interrupt_event(p_slot, event_type); 101 102 return 1; 103 } 104 105 u8 pciehp_handle_presence_change(struct slot *p_slot) 106 { 107 u32 event_type; 108 u8 presence_save; 109 struct controller *ctrl = p_slot->ctrl; 110 111 /* Presence Change */ 112 ctrl_dbg(ctrl, "Presence/Notify input change\n"); 113 114 /* Switch is open, assume a presence change 115 * Save the presence state 116 */ 117 pciehp_get_adapter_status(p_slot, &presence_save); 118 if (presence_save) { 119 /* 120 * Card Present 121 */ 122 ctrl_info(ctrl, "Card present on Slot(%s)\n", slot_name(p_slot)); 123 event_type = INT_PRESENCE_ON; 124 } else { 125 /* 126 * Not Present 127 */ 128 ctrl_info(ctrl, "Card not present on Slot(%s)\n", 129 slot_name(p_slot)); 130 event_type = INT_PRESENCE_OFF; 131 } 132 133 queue_interrupt_event(p_slot, event_type); 134 135 return 1; 136 } 137 138 u8 pciehp_handle_power_fault(struct slot *p_slot) 139 { 140 u32 event_type; 141 struct controller *ctrl = p_slot->ctrl; 142 143 /* power fault */ 144 ctrl_dbg(ctrl, "Power fault interrupt received\n"); 145 146 if (!pciehp_query_power_fault(p_slot)) { 147 /* 148 * power fault Cleared 149 */ 150 ctrl_info(ctrl, "Power fault cleared on Slot(%s)\n", 151 slot_name(p_slot)); 152 event_type = INT_POWER_FAULT_CLEAR; 153 } else { 154 /* 155 * power fault 156 */ 157 ctrl_info(ctrl, "Power fault on Slot(%s)\n", slot_name(p_slot)); 158 event_type = INT_POWER_FAULT; 159 ctrl_info(ctrl, "Power fault bit %x set\n", 0); 160 } 161 162 queue_interrupt_event(p_slot, event_type); 163 164 return 1; 165 } 166 167 /* The following routines constitute the bulk of the 168 hotplug controller logic 169 */ 170 171 static void set_slot_off(struct controller *ctrl, struct slot * pslot) 172 { 173 /* turn off slot, turn on Amber LED, turn off Green LED if supported*/ 174 if (POWER_CTRL(ctrl)) { 175 if (pciehp_power_off_slot(pslot)) { 176 ctrl_err(ctrl, 177 "Issue of Slot Power Off command failed\n"); 178 return; 179 } 180 /* 181 * After turning power off, we must wait for at least 1 second 182 * before taking any action that relies on power having been 183 * removed from the slot/adapter. 184 */ 185 msleep(1000); 186 } 187 188 if (PWR_LED(ctrl)) 189 pciehp_green_led_off(pslot); 190 191 if (ATTN_LED(ctrl)) { 192 if (pciehp_set_attention_status(pslot, 1)) { 193 ctrl_err(ctrl, 194 "Issue of Set Attention Led command failed\n"); 195 return; 196 } 197 } 198 } 199 200 /** 201 * board_added - Called after a board has been added to the system. 202 * @p_slot: &slot where board is added 203 * 204 * Turns power on for the board. 205 * Configures board. 206 */ 207 static int board_added(struct slot *p_slot) 208 { 209 int retval = 0; 210 struct controller *ctrl = p_slot->ctrl; 211 struct pci_bus *parent = ctrl->pcie->port->subordinate; 212 213 if (POWER_CTRL(ctrl)) { 214 /* Power on slot */ 215 retval = pciehp_power_on_slot(p_slot); 216 if (retval) 217 return retval; 218 } 219 220 if (PWR_LED(ctrl)) 221 pciehp_green_led_blink(p_slot); 222 223 /* Check link training status */ 224 retval = pciehp_check_link_status(ctrl); 225 if (retval) { 226 ctrl_err(ctrl, "Failed to check link status\n"); 227 set_slot_off(ctrl, p_slot); 228 return retval; 229 } 230 231 /* Check for a power fault */ 232 if (pciehp_query_power_fault(p_slot)) { 233 ctrl_dbg(ctrl, "Power fault detected\n"); 234 retval = -EIO; 235 goto err_exit; 236 } 237 238 retval = pciehp_configure_device(p_slot); 239 if (retval) { 240 ctrl_err(ctrl, "Cannot add device at %04x:%02x:00\n", 241 pci_domain_nr(parent), parent->number); 242 goto err_exit; 243 } 244 245 if (PWR_LED(ctrl)) 246 pciehp_green_led_on(p_slot); 247 248 return 0; 249 250 err_exit: 251 set_slot_off(ctrl, p_slot); 252 return retval; 253 } 254 255 /** 256 * remove_board - Turns off slot and LEDs 257 * @p_slot: slot where board is being removed 258 */ 259 static int remove_board(struct slot *p_slot) 260 { 261 int retval = 0; 262 struct controller *ctrl = p_slot->ctrl; 263 264 retval = pciehp_unconfigure_device(p_slot); 265 if (retval) 266 return retval; 267 268 if (POWER_CTRL(ctrl)) { 269 /* power off slot */ 270 retval = pciehp_power_off_slot(p_slot); 271 if (retval) { 272 ctrl_err(ctrl, 273 "Issue of Slot Disable command failed\n"); 274 return retval; 275 } 276 /* 277 * After turning power off, we must wait for at least 1 second 278 * before taking any action that relies on power having been 279 * removed from the slot/adapter. 280 */ 281 msleep(1000); 282 } 283 284 /* turn off Green LED */ 285 if (PWR_LED(ctrl)) 286 pciehp_green_led_off(p_slot); 287 288 return 0; 289 } 290 291 struct power_work_info { 292 struct slot *p_slot; 293 struct work_struct work; 294 }; 295 296 /** 297 * pciehp_power_thread - handle pushbutton events 298 * @work: &struct work_struct describing work to be done 299 * 300 * Scheduled procedure to handle blocking stuff for the pushbuttons. 301 * Handles all pending events and exits. 302 */ 303 static void pciehp_power_thread(struct work_struct *work) 304 { 305 struct power_work_info *info = 306 container_of(work, struct power_work_info, work); 307 struct slot *p_slot = info->p_slot; 308 309 mutex_lock(&p_slot->lock); 310 switch (p_slot->state) { 311 case POWEROFF_STATE: 312 mutex_unlock(&p_slot->lock); 313 ctrl_dbg(p_slot->ctrl, 314 "Disabling domain:bus:device=%04x:%02x:00\n", 315 pci_domain_nr(p_slot->ctrl->pcie->port->subordinate), 316 p_slot->ctrl->pcie->port->subordinate->number); 317 pciehp_disable_slot(p_slot); 318 mutex_lock(&p_slot->lock); 319 p_slot->state = STATIC_STATE; 320 break; 321 case POWERON_STATE: 322 mutex_unlock(&p_slot->lock); 323 if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl)) 324 pciehp_green_led_off(p_slot); 325 mutex_lock(&p_slot->lock); 326 p_slot->state = STATIC_STATE; 327 break; 328 default: 329 break; 330 } 331 mutex_unlock(&p_slot->lock); 332 333 kfree(info); 334 } 335 336 void pciehp_queue_pushbutton_work(struct work_struct *work) 337 { 338 struct slot *p_slot = container_of(work, struct slot, work.work); 339 struct power_work_info *info; 340 341 info = kmalloc(sizeof(*info), GFP_KERNEL); 342 if (!info) { 343 ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n", 344 __func__); 345 return; 346 } 347 info->p_slot = p_slot; 348 INIT_WORK(&info->work, pciehp_power_thread); 349 350 mutex_lock(&p_slot->lock); 351 switch (p_slot->state) { 352 case BLINKINGOFF_STATE: 353 p_slot->state = POWEROFF_STATE; 354 break; 355 case BLINKINGON_STATE: 356 p_slot->state = POWERON_STATE; 357 break; 358 default: 359 goto out; 360 } 361 queue_work(pciehp_wq, &info->work); 362 out: 363 mutex_unlock(&p_slot->lock); 364 } 365 366 static int update_slot_info(struct slot *slot) 367 { 368 struct hotplug_slot_info *info; 369 int result; 370 371 info = kmalloc(sizeof(*info), GFP_KERNEL); 372 if (!info) 373 return -ENOMEM; 374 375 pciehp_get_power_status(slot, &info->power_status); 376 pciehp_get_attention_status(slot, &info->attention_status); 377 pciehp_get_latch_status(slot, &info->latch_status); 378 pciehp_get_adapter_status(slot, &info->adapter_status); 379 380 result = pci_hp_change_slot_info(slot->hotplug_slot, info); 381 kfree (info); 382 return result; 383 } 384 385 /* 386 * Note: This function must be called with slot->lock held 387 */ 388 static void handle_button_press_event(struct slot *p_slot) 389 { 390 struct controller *ctrl = p_slot->ctrl; 391 u8 getstatus; 392 393 switch (p_slot->state) { 394 case STATIC_STATE: 395 pciehp_get_power_status(p_slot, &getstatus); 396 if (getstatus) { 397 p_slot->state = BLINKINGOFF_STATE; 398 ctrl_info(ctrl, 399 "PCI slot #%s - powering off due to button " 400 "press.\n", slot_name(p_slot)); 401 } else { 402 p_slot->state = BLINKINGON_STATE; 403 ctrl_info(ctrl, 404 "PCI slot #%s - powering on due to button " 405 "press.\n", slot_name(p_slot)); 406 } 407 /* blink green LED and turn off amber */ 408 if (PWR_LED(ctrl)) 409 pciehp_green_led_blink(p_slot); 410 if (ATTN_LED(ctrl)) 411 pciehp_set_attention_status(p_slot, 0); 412 413 schedule_delayed_work(&p_slot->work, 5*HZ); 414 break; 415 case BLINKINGOFF_STATE: 416 case BLINKINGON_STATE: 417 /* 418 * Cancel if we are still blinking; this means that we 419 * press the attention again before the 5 sec. limit 420 * expires to cancel hot-add or hot-remove 421 */ 422 ctrl_info(ctrl, "Button cancel on Slot(%s)\n", slot_name(p_slot)); 423 cancel_delayed_work(&p_slot->work); 424 if (p_slot->state == BLINKINGOFF_STATE) { 425 if (PWR_LED(ctrl)) 426 pciehp_green_led_on(p_slot); 427 } else { 428 if (PWR_LED(ctrl)) 429 pciehp_green_led_off(p_slot); 430 } 431 if (ATTN_LED(ctrl)) 432 pciehp_set_attention_status(p_slot, 0); 433 ctrl_info(ctrl, "PCI slot #%s - action canceled " 434 "due to button press\n", slot_name(p_slot)); 435 p_slot->state = STATIC_STATE; 436 break; 437 case POWEROFF_STATE: 438 case POWERON_STATE: 439 /* 440 * Ignore if the slot is on power-on or power-off state; 441 * this means that the previous attention button action 442 * to hot-add or hot-remove is undergoing 443 */ 444 ctrl_info(ctrl, "Button ignore on Slot(%s)\n", slot_name(p_slot)); 445 update_slot_info(p_slot); 446 break; 447 default: 448 ctrl_warn(ctrl, "Not a valid state\n"); 449 break; 450 } 451 } 452 453 /* 454 * Note: This function must be called with slot->lock held 455 */ 456 static void handle_surprise_event(struct slot *p_slot) 457 { 458 u8 getstatus; 459 struct power_work_info *info; 460 461 info = kmalloc(sizeof(*info), GFP_KERNEL); 462 if (!info) { 463 ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n", 464 __func__); 465 return; 466 } 467 info->p_slot = p_slot; 468 INIT_WORK(&info->work, pciehp_power_thread); 469 470 pciehp_get_adapter_status(p_slot, &getstatus); 471 if (!getstatus) 472 p_slot->state = POWEROFF_STATE; 473 else 474 p_slot->state = POWERON_STATE; 475 476 queue_work(pciehp_wq, &info->work); 477 } 478 479 static void interrupt_event_handler(struct work_struct *work) 480 { 481 struct event_info *info = container_of(work, struct event_info, work); 482 struct slot *p_slot = info->p_slot; 483 struct controller *ctrl = p_slot->ctrl; 484 485 mutex_lock(&p_slot->lock); 486 switch (info->event_type) { 487 case INT_BUTTON_PRESS: 488 handle_button_press_event(p_slot); 489 break; 490 case INT_POWER_FAULT: 491 if (!POWER_CTRL(ctrl)) 492 break; 493 if (ATTN_LED(ctrl)) 494 pciehp_set_attention_status(p_slot, 1); 495 if (PWR_LED(ctrl)) 496 pciehp_green_led_off(p_slot); 497 break; 498 case INT_PRESENCE_ON: 499 case INT_PRESENCE_OFF: 500 if (!HP_SUPR_RM(ctrl)) 501 break; 502 ctrl_dbg(ctrl, "Surprise Removal\n"); 503 update_slot_info(p_slot); 504 handle_surprise_event(p_slot); 505 break; 506 default: 507 update_slot_info(p_slot); 508 break; 509 } 510 mutex_unlock(&p_slot->lock); 511 512 kfree(info); 513 } 514 515 int pciehp_enable_slot(struct slot *p_slot) 516 { 517 u8 getstatus = 0; 518 int rc; 519 struct controller *ctrl = p_slot->ctrl; 520 521 rc = pciehp_get_adapter_status(p_slot, &getstatus); 522 if (rc || !getstatus) { 523 ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot)); 524 return -ENODEV; 525 } 526 if (MRL_SENS(p_slot->ctrl)) { 527 rc = pciehp_get_latch_status(p_slot, &getstatus); 528 if (rc || getstatus) { 529 ctrl_info(ctrl, "Latch open on slot(%s)\n", 530 slot_name(p_slot)); 531 return -ENODEV; 532 } 533 } 534 535 if (POWER_CTRL(p_slot->ctrl)) { 536 rc = pciehp_get_power_status(p_slot, &getstatus); 537 if (rc || getstatus) { 538 ctrl_info(ctrl, "Already enabled on slot(%s)\n", 539 slot_name(p_slot)); 540 return -EINVAL; 541 } 542 } 543 544 pciehp_get_latch_status(p_slot, &getstatus); 545 546 rc = board_added(p_slot); 547 if (rc) { 548 pciehp_get_latch_status(p_slot, &getstatus); 549 } 550 551 update_slot_info(p_slot); 552 553 return rc; 554 } 555 556 557 int pciehp_disable_slot(struct slot *p_slot) 558 { 559 u8 getstatus = 0; 560 int ret = 0; 561 struct controller *ctrl = p_slot->ctrl; 562 563 if (!p_slot->ctrl) 564 return 1; 565 566 if (!HP_SUPR_RM(p_slot->ctrl)) { 567 ret = pciehp_get_adapter_status(p_slot, &getstatus); 568 if (ret || !getstatus) { 569 ctrl_info(ctrl, "No adapter on slot(%s)\n", 570 slot_name(p_slot)); 571 return -ENODEV; 572 } 573 } 574 575 if (MRL_SENS(p_slot->ctrl)) { 576 ret = pciehp_get_latch_status(p_slot, &getstatus); 577 if (ret || getstatus) { 578 ctrl_info(ctrl, "Latch open on slot(%s)\n", 579 slot_name(p_slot)); 580 return -ENODEV; 581 } 582 } 583 584 if (POWER_CTRL(p_slot->ctrl)) { 585 ret = pciehp_get_power_status(p_slot, &getstatus); 586 if (ret || !getstatus) { 587 ctrl_info(ctrl, "Already disabled on slot(%s)\n", 588 slot_name(p_slot)); 589 return -EINVAL; 590 } 591 } 592 593 ret = remove_board(p_slot); 594 update_slot_info(p_slot); 595 596 return ret; 597 } 598 599 int pciehp_sysfs_enable_slot(struct slot *p_slot) 600 { 601 int retval = -ENODEV; 602 struct controller *ctrl = p_slot->ctrl; 603 604 mutex_lock(&p_slot->lock); 605 switch (p_slot->state) { 606 case BLINKINGON_STATE: 607 cancel_delayed_work(&p_slot->work); 608 case STATIC_STATE: 609 p_slot->state = POWERON_STATE; 610 mutex_unlock(&p_slot->lock); 611 retval = pciehp_enable_slot(p_slot); 612 mutex_lock(&p_slot->lock); 613 p_slot->state = STATIC_STATE; 614 break; 615 case POWERON_STATE: 616 ctrl_info(ctrl, "Slot %s is already in powering on state\n", 617 slot_name(p_slot)); 618 break; 619 case BLINKINGOFF_STATE: 620 case POWEROFF_STATE: 621 ctrl_info(ctrl, "Already enabled on slot %s\n", 622 slot_name(p_slot)); 623 break; 624 default: 625 ctrl_err(ctrl, "Not a valid state on slot %s\n", 626 slot_name(p_slot)); 627 break; 628 } 629 mutex_unlock(&p_slot->lock); 630 631 return retval; 632 } 633 634 int pciehp_sysfs_disable_slot(struct slot *p_slot) 635 { 636 int retval = -ENODEV; 637 struct controller *ctrl = p_slot->ctrl; 638 639 mutex_lock(&p_slot->lock); 640 switch (p_slot->state) { 641 case BLINKINGOFF_STATE: 642 cancel_delayed_work(&p_slot->work); 643 case STATIC_STATE: 644 p_slot->state = POWEROFF_STATE; 645 mutex_unlock(&p_slot->lock); 646 retval = pciehp_disable_slot(p_slot); 647 mutex_lock(&p_slot->lock); 648 p_slot->state = STATIC_STATE; 649 break; 650 case POWEROFF_STATE: 651 ctrl_info(ctrl, "Slot %s is already in powering off state\n", 652 slot_name(p_slot)); 653 break; 654 case BLINKINGON_STATE: 655 case POWERON_STATE: 656 ctrl_info(ctrl, "Already disabled on slot %s\n", 657 slot_name(p_slot)); 658 break; 659 default: 660 ctrl_err(ctrl, "Not a valid state on slot %s\n", 661 slot_name(p_slot)); 662 break; 663 } 664 mutex_unlock(&p_slot->lock); 665 666 return retval; 667 } 668