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