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