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