1 /* 2 * CompactPCI Hot Plug Driver 3 * 4 * Copyright (C) 2002,2005 SOMA Networks, Inc. 5 * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) 6 * Copyright (C) 2001 IBM Corp. 7 * 8 * All rights reserved. 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or (at 13 * your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, but 16 * WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 18 * NON INFRINGEMENT. See the GNU General Public License for more 19 * details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 24 * 25 * Send feedback to <scottm@somanetworks.com> 26 */ 27 28 #include <linux/module.h> 29 #include <linux/kernel.h> 30 #include <linux/slab.h> 31 #include <linux/pci.h> 32 #include <linux/pci_hotplug.h> 33 #include <linux/init.h> 34 #include <linux/interrupt.h> 35 #include <linux/atomic.h> 36 #include <linux/delay.h> 37 #include <linux/kthread.h> 38 #include "cpci_hotplug.h" 39 40 #define DRIVER_AUTHOR "Scott Murray <scottm@somanetworks.com>" 41 #define DRIVER_DESC "CompactPCI Hot Plug Core" 42 43 #define MY_NAME "cpci_hotplug" 44 45 #define dbg(format, arg...) \ 46 do { \ 47 if (cpci_debug) \ 48 printk (KERN_DEBUG "%s: " format "\n", \ 49 MY_NAME , ## arg); \ 50 } while (0) 51 #define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg) 52 #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg) 53 #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg) 54 55 /* local variables */ 56 static DECLARE_RWSEM(list_rwsem); 57 static LIST_HEAD(slot_list); 58 static int slots; 59 static atomic_t extracting; 60 int cpci_debug; 61 static struct cpci_hp_controller *controller; 62 static struct task_struct *cpci_thread; 63 static int thread_finished; 64 65 static int enable_slot(struct hotplug_slot *slot); 66 static int disable_slot(struct hotplug_slot *slot); 67 static int set_attention_status(struct hotplug_slot *slot, u8 value); 68 static int get_power_status(struct hotplug_slot *slot, u8 *value); 69 static int get_attention_status(struct hotplug_slot *slot, u8 *value); 70 static int get_adapter_status(struct hotplug_slot *slot, u8 *value); 71 static int get_latch_status(struct hotplug_slot *slot, u8 *value); 72 73 static struct hotplug_slot_ops cpci_hotplug_slot_ops = { 74 .enable_slot = enable_slot, 75 .disable_slot = disable_slot, 76 .set_attention_status = set_attention_status, 77 .get_power_status = get_power_status, 78 .get_attention_status = get_attention_status, 79 .get_adapter_status = get_adapter_status, 80 .get_latch_status = get_latch_status, 81 }; 82 83 static int 84 update_latch_status(struct hotplug_slot *hotplug_slot, u8 value) 85 { 86 struct hotplug_slot_info info; 87 88 memcpy(&info, hotplug_slot->info, sizeof(struct hotplug_slot_info)); 89 info.latch_status = value; 90 return pci_hp_change_slot_info(hotplug_slot, &info); 91 } 92 93 static int 94 update_adapter_status(struct hotplug_slot *hotplug_slot, u8 value) 95 { 96 struct hotplug_slot_info info; 97 98 memcpy(&info, hotplug_slot->info, sizeof(struct hotplug_slot_info)); 99 info.adapter_status = value; 100 return pci_hp_change_slot_info(hotplug_slot, &info); 101 } 102 103 static int 104 enable_slot(struct hotplug_slot *hotplug_slot) 105 { 106 struct slot *slot = hotplug_slot->private; 107 int retval = 0; 108 109 dbg("%s - physical_slot = %s", __func__, slot_name(slot)); 110 111 if (controller->ops->set_power) 112 retval = controller->ops->set_power(slot, 1); 113 return retval; 114 } 115 116 static int 117 disable_slot(struct hotplug_slot *hotplug_slot) 118 { 119 struct slot *slot = hotplug_slot->private; 120 int retval = 0; 121 122 dbg("%s - physical_slot = %s", __func__, slot_name(slot)); 123 124 down_write(&list_rwsem); 125 126 /* Unconfigure device */ 127 dbg("%s - unconfiguring slot %s", __func__, slot_name(slot)); 128 retval = cpci_unconfigure_slot(slot); 129 if (retval) { 130 err("%s - could not unconfigure slot %s", 131 __func__, slot_name(slot)); 132 goto disable_error; 133 } 134 dbg("%s - finished unconfiguring slot %s", __func__, slot_name(slot)); 135 136 /* Clear EXT (by setting it) */ 137 if (cpci_clear_ext(slot)) { 138 err("%s - could not clear EXT for slot %s", 139 __func__, slot_name(slot)); 140 retval = -ENODEV; 141 goto disable_error; 142 } 143 cpci_led_on(slot); 144 145 if (controller->ops->set_power) { 146 retval = controller->ops->set_power(slot, 0); 147 if (retval) 148 goto disable_error; 149 } 150 151 if (update_adapter_status(slot->hotplug_slot, 0)) 152 warn("failure to update adapter file"); 153 154 if (slot->extracting) { 155 slot->extracting = 0; 156 atomic_dec(&extracting); 157 } 158 disable_error: 159 up_write(&list_rwsem); 160 return retval; 161 } 162 163 static u8 164 cpci_get_power_status(struct slot *slot) 165 { 166 u8 power = 1; 167 168 if (controller->ops->get_power) 169 power = controller->ops->get_power(slot); 170 return power; 171 } 172 173 static int 174 get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) 175 { 176 struct slot *slot = hotplug_slot->private; 177 178 *value = cpci_get_power_status(slot); 179 return 0; 180 } 181 182 static int 183 get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) 184 { 185 struct slot *slot = hotplug_slot->private; 186 187 *value = cpci_get_attention_status(slot); 188 return 0; 189 } 190 191 static int 192 set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) 193 { 194 return cpci_set_attention_status(hotplug_slot->private, status); 195 } 196 197 static int 198 get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) 199 { 200 *value = hotplug_slot->info->adapter_status; 201 return 0; 202 } 203 204 static int 205 get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) 206 { 207 *value = hotplug_slot->info->latch_status; 208 return 0; 209 } 210 211 static void release_slot(struct hotplug_slot *hotplug_slot) 212 { 213 struct slot *slot = hotplug_slot->private; 214 215 kfree(slot->hotplug_slot->info); 216 kfree(slot->hotplug_slot); 217 pci_dev_put(slot->dev); 218 kfree(slot); 219 } 220 221 #define SLOT_NAME_SIZE 6 222 223 int 224 cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last) 225 { 226 struct slot *slot; 227 struct hotplug_slot *hotplug_slot; 228 struct hotplug_slot_info *info; 229 char name[SLOT_NAME_SIZE]; 230 int status; 231 int i; 232 233 if (!(controller && bus)) 234 return -ENODEV; 235 236 /* 237 * Create a structure for each slot, and register that slot 238 * with the pci_hotplug subsystem. 239 */ 240 for (i = first; i <= last; ++i) { 241 slot = kzalloc(sizeof (struct slot), GFP_KERNEL); 242 if (!slot) { 243 status = -ENOMEM; 244 goto error; 245 } 246 247 hotplug_slot = 248 kzalloc(sizeof (struct hotplug_slot), GFP_KERNEL); 249 if (!hotplug_slot) { 250 status = -ENOMEM; 251 goto error_slot; 252 } 253 slot->hotplug_slot = hotplug_slot; 254 255 info = kzalloc(sizeof (struct hotplug_slot_info), GFP_KERNEL); 256 if (!info) { 257 status = -ENOMEM; 258 goto error_hpslot; 259 } 260 hotplug_slot->info = info; 261 262 slot->bus = bus; 263 slot->number = i; 264 slot->devfn = PCI_DEVFN(i, 0); 265 266 snprintf(name, SLOT_NAME_SIZE, "%02x:%02x", bus->number, i); 267 268 hotplug_slot->private = slot; 269 hotplug_slot->release = &release_slot; 270 hotplug_slot->ops = &cpci_hotplug_slot_ops; 271 272 /* 273 * Initialize the slot info structure with some known 274 * good values. 275 */ 276 dbg("initializing slot %s", name); 277 info->power_status = cpci_get_power_status(slot); 278 info->attention_status = cpci_get_attention_status(slot); 279 280 dbg("registering slot %s", name); 281 status = pci_hp_register(slot->hotplug_slot, bus, i, name); 282 if (status) { 283 err("pci_hp_register failed with error %d", status); 284 goto error_info; 285 } 286 dbg("slot registered with name: %s", slot_name(slot)); 287 288 /* Add slot to our internal list */ 289 down_write(&list_rwsem); 290 list_add(&slot->slot_list, &slot_list); 291 slots++; 292 up_write(&list_rwsem); 293 } 294 return 0; 295 error_info: 296 kfree(info); 297 error_hpslot: 298 kfree(hotplug_slot); 299 error_slot: 300 kfree(slot); 301 error: 302 return status; 303 } 304 EXPORT_SYMBOL_GPL(cpci_hp_register_bus); 305 306 int 307 cpci_hp_unregister_bus(struct pci_bus *bus) 308 { 309 struct slot *slot; 310 struct slot *tmp; 311 int status = 0; 312 313 down_write(&list_rwsem); 314 if (!slots) { 315 up_write(&list_rwsem); 316 return -1; 317 } 318 list_for_each_entry_safe(slot, tmp, &slot_list, slot_list) { 319 if (slot->bus == bus) { 320 list_del(&slot->slot_list); 321 slots--; 322 323 dbg("deregistering slot %s", slot_name(slot)); 324 status = pci_hp_deregister(slot->hotplug_slot); 325 if (status) { 326 err("pci_hp_deregister failed with error %d", 327 status); 328 break; 329 } 330 } 331 } 332 up_write(&list_rwsem); 333 return status; 334 } 335 EXPORT_SYMBOL_GPL(cpci_hp_unregister_bus); 336 337 /* This is the interrupt mode interrupt handler */ 338 static irqreturn_t 339 cpci_hp_intr(int irq, void *data) 340 { 341 dbg("entered cpci_hp_intr"); 342 343 /* Check to see if it was our interrupt */ 344 if ((controller->irq_flags & IRQF_SHARED) && 345 !controller->ops->check_irq(controller->dev_id)) { 346 dbg("exited cpci_hp_intr, not our interrupt"); 347 return IRQ_NONE; 348 } 349 350 /* Disable ENUM interrupt */ 351 controller->ops->disable_irq(); 352 353 /* Trigger processing by the event thread */ 354 wake_up_process(cpci_thread); 355 return IRQ_HANDLED; 356 } 357 358 /* 359 * According to PICMG 2.1 R2.0, section 6.3.2, upon 360 * initialization, the system driver shall clear the 361 * INS bits of the cold-inserted devices. 362 */ 363 static int 364 init_slots(int clear_ins) 365 { 366 struct slot *slot; 367 struct pci_dev *dev; 368 369 dbg("%s - enter", __func__); 370 down_read(&list_rwsem); 371 if (!slots) { 372 up_read(&list_rwsem); 373 return -1; 374 } 375 list_for_each_entry(slot, &slot_list, slot_list) { 376 dbg("%s - looking at slot %s", __func__, slot_name(slot)); 377 if (clear_ins && cpci_check_and_clear_ins(slot)) 378 dbg("%s - cleared INS for slot %s", 379 __func__, slot_name(slot)); 380 dev = pci_get_slot(slot->bus, PCI_DEVFN(slot->number, 0)); 381 if (dev) { 382 if (update_adapter_status(slot->hotplug_slot, 1)) 383 warn("failure to update adapter file"); 384 if (update_latch_status(slot->hotplug_slot, 1)) 385 warn("failure to update latch file"); 386 slot->dev = dev; 387 } 388 } 389 up_read(&list_rwsem); 390 dbg("%s - exit", __func__); 391 return 0; 392 } 393 394 static int 395 check_slots(void) 396 { 397 struct slot *slot; 398 int extracted; 399 int inserted; 400 u16 hs_csr; 401 402 down_read(&list_rwsem); 403 if (!slots) { 404 up_read(&list_rwsem); 405 err("no slots registered, shutting down"); 406 return -1; 407 } 408 extracted = inserted = 0; 409 list_for_each_entry(slot, &slot_list, slot_list) { 410 dbg("%s - looking at slot %s", __func__, slot_name(slot)); 411 if (cpci_check_and_clear_ins(slot)) { 412 /* 413 * Some broken hardware (e.g. PLX 9054AB) asserts 414 * ENUM# twice... 415 */ 416 if (slot->dev) { 417 warn("slot %s already inserted", 418 slot_name(slot)); 419 inserted++; 420 continue; 421 } 422 423 /* Process insertion */ 424 dbg("%s - slot %s inserted", __func__, slot_name(slot)); 425 426 /* GSM, debug */ 427 hs_csr = cpci_get_hs_csr(slot); 428 dbg("%s - slot %s HS_CSR (1) = %04x", 429 __func__, slot_name(slot), hs_csr); 430 431 /* Configure device */ 432 dbg("%s - configuring slot %s", 433 __func__, slot_name(slot)); 434 if (cpci_configure_slot(slot)) { 435 err("%s - could not configure slot %s", 436 __func__, slot_name(slot)); 437 continue; 438 } 439 dbg("%s - finished configuring slot %s", 440 __func__, slot_name(slot)); 441 442 /* GSM, debug */ 443 hs_csr = cpci_get_hs_csr(slot); 444 dbg("%s - slot %s HS_CSR (2) = %04x", 445 __func__, slot_name(slot), hs_csr); 446 447 if (update_latch_status(slot->hotplug_slot, 1)) 448 warn("failure to update latch file"); 449 450 if (update_adapter_status(slot->hotplug_slot, 1)) 451 warn("failure to update adapter file"); 452 453 cpci_led_off(slot); 454 455 /* GSM, debug */ 456 hs_csr = cpci_get_hs_csr(slot); 457 dbg("%s - slot %s HS_CSR (3) = %04x", 458 __func__, slot_name(slot), hs_csr); 459 460 inserted++; 461 } else if (cpci_check_ext(slot)) { 462 /* Process extraction request */ 463 dbg("%s - slot %s extracted", 464 __func__, slot_name(slot)); 465 466 /* GSM, debug */ 467 hs_csr = cpci_get_hs_csr(slot); 468 dbg("%s - slot %s HS_CSR = %04x", 469 __func__, slot_name(slot), hs_csr); 470 471 if (!slot->extracting) { 472 if (update_latch_status(slot->hotplug_slot, 0)) 473 warn("failure to update latch file"); 474 475 slot->extracting = 1; 476 atomic_inc(&extracting); 477 } 478 extracted++; 479 } else if (slot->extracting) { 480 hs_csr = cpci_get_hs_csr(slot); 481 if (hs_csr == 0xffff) { 482 /* 483 * Hmmm, we're likely hosed at this point, should we 484 * bother trying to tell the driver or not? 485 */ 486 err("card in slot %s was improperly removed", 487 slot_name(slot)); 488 if (update_adapter_status(slot->hotplug_slot, 0)) 489 warn("failure to update adapter file"); 490 slot->extracting = 0; 491 atomic_dec(&extracting); 492 } 493 } 494 } 495 up_read(&list_rwsem); 496 dbg("inserted=%d, extracted=%d, extracting=%d", 497 inserted, extracted, atomic_read(&extracting)); 498 if (inserted || extracted) 499 return extracted; 500 else if (!atomic_read(&extracting)) { 501 err("cannot find ENUM# source, shutting down"); 502 return -1; 503 } 504 return 0; 505 } 506 507 /* This is the interrupt mode worker thread body */ 508 static int 509 event_thread(void *data) 510 { 511 int rc; 512 513 dbg("%s - event thread started", __func__); 514 while (1) { 515 dbg("event thread sleeping"); 516 set_current_state(TASK_INTERRUPTIBLE); 517 schedule(); 518 if (kthread_should_stop()) 519 break; 520 do { 521 rc = check_slots(); 522 if (rc > 0) { 523 /* Give userspace a chance to handle extraction */ 524 msleep(500); 525 } else if (rc < 0) { 526 dbg("%s - error checking slots", __func__); 527 thread_finished = 1; 528 goto out; 529 } 530 } while (atomic_read(&extracting) && !kthread_should_stop()); 531 if (kthread_should_stop()) 532 break; 533 534 /* Re-enable ENUM# interrupt */ 535 dbg("%s - re-enabling irq", __func__); 536 controller->ops->enable_irq(); 537 } 538 out: 539 return 0; 540 } 541 542 /* This is the polling mode worker thread body */ 543 static int 544 poll_thread(void *data) 545 { 546 int rc; 547 548 while (1) { 549 if (kthread_should_stop() || signal_pending(current)) 550 break; 551 if (controller->ops->query_enum()) { 552 do { 553 rc = check_slots(); 554 if (rc > 0) { 555 /* Give userspace a chance to handle extraction */ 556 msleep(500); 557 } else if (rc < 0) { 558 dbg("%s - error checking slots", __func__); 559 thread_finished = 1; 560 goto out; 561 } 562 } while (atomic_read(&extracting) && !kthread_should_stop()); 563 } 564 msleep(100); 565 } 566 out: 567 return 0; 568 } 569 570 static int 571 cpci_start_thread(void) 572 { 573 if (controller->irq) 574 cpci_thread = kthread_run(event_thread, NULL, "cpci_hp_eventd"); 575 else 576 cpci_thread = kthread_run(poll_thread, NULL, "cpci_hp_polld"); 577 if (IS_ERR(cpci_thread)) { 578 err("Can't start up our thread"); 579 return PTR_ERR(cpci_thread); 580 } 581 thread_finished = 0; 582 return 0; 583 } 584 585 static void 586 cpci_stop_thread(void) 587 { 588 kthread_stop(cpci_thread); 589 thread_finished = 1; 590 } 591 592 int 593 cpci_hp_register_controller(struct cpci_hp_controller *new_controller) 594 { 595 int status = 0; 596 597 if (controller) 598 return -1; 599 if (!(new_controller && new_controller->ops)) 600 return -EINVAL; 601 if (new_controller->irq) { 602 if (!(new_controller->ops->enable_irq && 603 new_controller->ops->disable_irq)) 604 status = -EINVAL; 605 if (request_irq(new_controller->irq, 606 cpci_hp_intr, 607 new_controller->irq_flags, 608 MY_NAME, 609 new_controller->dev_id)) { 610 err("Can't get irq %d for the hotplug cPCI controller", 611 new_controller->irq); 612 status = -ENODEV; 613 } 614 dbg("%s - acquired controller irq %d", 615 __func__, new_controller->irq); 616 } 617 if (!status) 618 controller = new_controller; 619 return status; 620 } 621 EXPORT_SYMBOL_GPL(cpci_hp_register_controller); 622 623 static void 624 cleanup_slots(void) 625 { 626 struct slot *slot; 627 struct slot *tmp; 628 629 /* 630 * Unregister all of our slots with the pci_hotplug subsystem, 631 * and free up all memory that we had allocated. 632 */ 633 down_write(&list_rwsem); 634 if (!slots) 635 goto cleanup_null; 636 list_for_each_entry_safe(slot, tmp, &slot_list, slot_list) { 637 list_del(&slot->slot_list); 638 pci_hp_deregister(slot->hotplug_slot); 639 } 640 cleanup_null: 641 up_write(&list_rwsem); 642 return; 643 } 644 645 int 646 cpci_hp_unregister_controller(struct cpci_hp_controller *old_controller) 647 { 648 int status = 0; 649 650 if (controller) { 651 if (!thread_finished) 652 cpci_stop_thread(); 653 if (controller->irq) 654 free_irq(controller->irq, controller->dev_id); 655 controller = NULL; 656 cleanup_slots(); 657 } else 658 status = -ENODEV; 659 return status; 660 } 661 EXPORT_SYMBOL_GPL(cpci_hp_unregister_controller); 662 663 int 664 cpci_hp_start(void) 665 { 666 static int first = 1; 667 int status; 668 669 dbg("%s - enter", __func__); 670 if (!controller) 671 return -ENODEV; 672 673 down_read(&list_rwsem); 674 if (list_empty(&slot_list)) { 675 up_read(&list_rwsem); 676 return -ENODEV; 677 } 678 up_read(&list_rwsem); 679 680 status = init_slots(first); 681 if (first) 682 first = 0; 683 if (status) 684 return status; 685 686 status = cpci_start_thread(); 687 if (status) 688 return status; 689 dbg("%s - thread started", __func__); 690 691 if (controller->irq) { 692 /* Start enum interrupt processing */ 693 dbg("%s - enabling irq", __func__); 694 controller->ops->enable_irq(); 695 } 696 dbg("%s - exit", __func__); 697 return 0; 698 } 699 EXPORT_SYMBOL_GPL(cpci_hp_start); 700 701 int 702 cpci_hp_stop(void) 703 { 704 if (!controller) 705 return -ENODEV; 706 if (controller->irq) { 707 /* Stop enum interrupt processing */ 708 dbg("%s - disabling irq", __func__); 709 controller->ops->disable_irq(); 710 } 711 cpci_stop_thread(); 712 return 0; 713 } 714 EXPORT_SYMBOL_GPL(cpci_hp_stop); 715 716 int __init 717 cpci_hotplug_init(int debug) 718 { 719 cpci_debug = debug; 720 return 0; 721 } 722 723 void __exit 724 cpci_hotplug_exit(void) 725 { 726 /* 727 * Clean everything up. 728 */ 729 cpci_hp_stop(); 730 cpci_hp_unregister_controller(controller); 731 } 732