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 if (slot->dev) 218 pci_dev_put(slot->dev); 219 kfree(slot); 220 } 221 222 #define SLOT_NAME_SIZE 6 223 224 int 225 cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last) 226 { 227 struct slot *slot; 228 struct hotplug_slot *hotplug_slot; 229 struct hotplug_slot_info *info; 230 char name[SLOT_NAME_SIZE]; 231 int status; 232 int i; 233 234 if (!(controller && bus)) 235 return -ENODEV; 236 237 /* 238 * Create a structure for each slot, and register that slot 239 * with the pci_hotplug subsystem. 240 */ 241 for (i = first; i <= last; ++i) { 242 slot = kzalloc(sizeof (struct slot), GFP_KERNEL); 243 if (!slot) { 244 status = -ENOMEM; 245 goto error; 246 } 247 248 hotplug_slot = 249 kzalloc(sizeof (struct hotplug_slot), GFP_KERNEL); 250 if (!hotplug_slot) { 251 status = -ENOMEM; 252 goto error_slot; 253 } 254 slot->hotplug_slot = hotplug_slot; 255 256 info = kzalloc(sizeof (struct hotplug_slot_info), GFP_KERNEL); 257 if (!info) { 258 status = -ENOMEM; 259 goto error_hpslot; 260 } 261 hotplug_slot->info = info; 262 263 slot->bus = bus; 264 slot->number = i; 265 slot->devfn = PCI_DEVFN(i, 0); 266 267 snprintf(name, SLOT_NAME_SIZE, "%02x:%02x", bus->number, i); 268 269 hotplug_slot->private = slot; 270 hotplug_slot->release = &release_slot; 271 hotplug_slot->ops = &cpci_hotplug_slot_ops; 272 273 /* 274 * Initialize the slot info structure with some known 275 * good values. 276 */ 277 dbg("initializing slot %s", name); 278 info->power_status = cpci_get_power_status(slot); 279 info->attention_status = cpci_get_attention_status(slot); 280 281 dbg("registering slot %s", name); 282 status = pci_hp_register(slot->hotplug_slot, bus, i, name); 283 if (status) { 284 err("pci_hp_register failed with error %d", status); 285 goto error_info; 286 } 287 dbg("slot registered with name: %s", slot_name(slot)); 288 289 /* Add slot to our internal list */ 290 down_write(&list_rwsem); 291 list_add(&slot->slot_list, &slot_list); 292 slots++; 293 up_write(&list_rwsem); 294 } 295 return 0; 296 error_info: 297 kfree(info); 298 error_hpslot: 299 kfree(hotplug_slot); 300 error_slot: 301 kfree(slot); 302 error: 303 return status; 304 } 305 EXPORT_SYMBOL_GPL(cpci_hp_register_bus); 306 307 int 308 cpci_hp_unregister_bus(struct pci_bus *bus) 309 { 310 struct slot *slot; 311 struct slot *tmp; 312 int status = 0; 313 314 down_write(&list_rwsem); 315 if (!slots) { 316 up_write(&list_rwsem); 317 return -1; 318 } 319 list_for_each_entry_safe(slot, tmp, &slot_list, slot_list) { 320 if (slot->bus == bus) { 321 list_del(&slot->slot_list); 322 slots--; 323 324 dbg("deregistering slot %s", slot_name(slot)); 325 status = pci_hp_deregister(slot->hotplug_slot); 326 if (status) { 327 err("pci_hp_deregister failed with error %d", 328 status); 329 break; 330 } 331 } 332 } 333 up_write(&list_rwsem); 334 return status; 335 } 336 EXPORT_SYMBOL_GPL(cpci_hp_unregister_bus); 337 338 /* This is the interrupt mode interrupt handler */ 339 static irqreturn_t 340 cpci_hp_intr(int irq, void *data) 341 { 342 dbg("entered cpci_hp_intr"); 343 344 /* Check to see if it was our interrupt */ 345 if ((controller->irq_flags & IRQF_SHARED) && 346 !controller->ops->check_irq(controller->dev_id)) { 347 dbg("exited cpci_hp_intr, not our interrupt"); 348 return IRQ_NONE; 349 } 350 351 /* Disable ENUM interrupt */ 352 controller->ops->disable_irq(); 353 354 /* Trigger processing by the event thread */ 355 wake_up_process(cpci_thread); 356 return IRQ_HANDLED; 357 } 358 359 /* 360 * According to PICMG 2.1 R2.0, section 6.3.2, upon 361 * initialization, the system driver shall clear the 362 * INS bits of the cold-inserted devices. 363 */ 364 static int 365 init_slots(int clear_ins) 366 { 367 struct slot *slot; 368 struct pci_dev *dev; 369 370 dbg("%s - enter", __func__); 371 down_read(&list_rwsem); 372 if (!slots) { 373 up_read(&list_rwsem); 374 return -1; 375 } 376 list_for_each_entry(slot, &slot_list, slot_list) { 377 dbg("%s - looking at slot %s", __func__, slot_name(slot)); 378 if (clear_ins && cpci_check_and_clear_ins(slot)) 379 dbg("%s - cleared INS for slot %s", 380 __func__, slot_name(slot)); 381 dev = pci_get_slot(slot->bus, PCI_DEVFN(slot->number, 0)); 382 if (dev) { 383 if (update_adapter_status(slot->hotplug_slot, 1)) 384 warn("failure to update adapter file"); 385 if (update_latch_status(slot->hotplug_slot, 1)) 386 warn("failure to update latch file"); 387 slot->dev = dev; 388 } 389 } 390 up_read(&list_rwsem); 391 dbg("%s - exit", __func__); 392 return 0; 393 } 394 395 static int 396 check_slots(void) 397 { 398 struct slot *slot; 399 int extracted; 400 int inserted; 401 u16 hs_csr; 402 403 down_read(&list_rwsem); 404 if (!slots) { 405 up_read(&list_rwsem); 406 err("no slots registered, shutting down"); 407 return -1; 408 } 409 extracted = inserted = 0; 410 list_for_each_entry(slot, &slot_list, slot_list) { 411 dbg("%s - looking at slot %s", __func__, slot_name(slot)); 412 if (cpci_check_and_clear_ins(slot)) { 413 /* 414 * Some broken hardware (e.g. PLX 9054AB) asserts 415 * ENUM# twice... 416 */ 417 if (slot->dev) { 418 warn("slot %s already inserted", 419 slot_name(slot)); 420 inserted++; 421 continue; 422 } 423 424 /* Process insertion */ 425 dbg("%s - slot %s inserted", __func__, slot_name(slot)); 426 427 /* GSM, debug */ 428 hs_csr = cpci_get_hs_csr(slot); 429 dbg("%s - slot %s HS_CSR (1) = %04x", 430 __func__, slot_name(slot), hs_csr); 431 432 /* Configure device */ 433 dbg("%s - configuring slot %s", 434 __func__, slot_name(slot)); 435 if (cpci_configure_slot(slot)) { 436 err("%s - could not configure slot %s", 437 __func__, slot_name(slot)); 438 continue; 439 } 440 dbg("%s - finished configuring slot %s", 441 __func__, slot_name(slot)); 442 443 /* GSM, debug */ 444 hs_csr = cpci_get_hs_csr(slot); 445 dbg("%s - slot %s HS_CSR (2) = %04x", 446 __func__, slot_name(slot), hs_csr); 447 448 if (update_latch_status(slot->hotplug_slot, 1)) 449 warn("failure to update latch file"); 450 451 if (update_adapter_status(slot->hotplug_slot, 1)) 452 warn("failure to update adapter file"); 453 454 cpci_led_off(slot); 455 456 /* GSM, debug */ 457 hs_csr = cpci_get_hs_csr(slot); 458 dbg("%s - slot %s HS_CSR (3) = %04x", 459 __func__, slot_name(slot), hs_csr); 460 461 inserted++; 462 } else if (cpci_check_ext(slot)) { 463 /* Process extraction request */ 464 dbg("%s - slot %s extracted", 465 __func__, slot_name(slot)); 466 467 /* GSM, debug */ 468 hs_csr = cpci_get_hs_csr(slot); 469 dbg("%s - slot %s HS_CSR = %04x", 470 __func__, slot_name(slot), hs_csr); 471 472 if (!slot->extracting) { 473 if (update_latch_status(slot->hotplug_slot, 0)) 474 warn("failure to update latch file"); 475 476 slot->extracting = 1; 477 atomic_inc(&extracting); 478 } 479 extracted++; 480 } else if (slot->extracting) { 481 hs_csr = cpci_get_hs_csr(slot); 482 if (hs_csr == 0xffff) { 483 /* 484 * Hmmm, we're likely hosed at this point, should we 485 * bother trying to tell the driver or not? 486 */ 487 err("card in slot %s was improperly removed", 488 slot_name(slot)); 489 if (update_adapter_status(slot->hotplug_slot, 0)) 490 warn("failure to update adapter file"); 491 slot->extracting = 0; 492 atomic_dec(&extracting); 493 } 494 } 495 } 496 up_read(&list_rwsem); 497 dbg("inserted=%d, extracted=%d, extracting=%d", 498 inserted, extracted, atomic_read(&extracting)); 499 if (inserted || extracted) 500 return extracted; 501 else if (!atomic_read(&extracting)) { 502 err("cannot find ENUM# source, shutting down"); 503 return -1; 504 } 505 return 0; 506 } 507 508 /* This is the interrupt mode worker thread body */ 509 static int 510 event_thread(void *data) 511 { 512 int rc; 513 514 dbg("%s - event thread started", __func__); 515 while (1) { 516 dbg("event thread sleeping"); 517 set_current_state(TASK_INTERRUPTIBLE); 518 schedule(); 519 if (kthread_should_stop()) 520 break; 521 do { 522 rc = check_slots(); 523 if (rc > 0) { 524 /* Give userspace a chance to handle extraction */ 525 msleep(500); 526 } else if (rc < 0) { 527 dbg("%s - error checking slots", __func__); 528 thread_finished = 1; 529 goto out; 530 } 531 } while (atomic_read(&extracting) && !kthread_should_stop()); 532 if (kthread_should_stop()) 533 break; 534 535 /* Re-enable ENUM# interrupt */ 536 dbg("%s - re-enabling irq", __func__); 537 controller->ops->enable_irq(); 538 } 539 out: 540 return 0; 541 } 542 543 /* This is the polling mode worker thread body */ 544 static int 545 poll_thread(void *data) 546 { 547 int rc; 548 549 while (1) { 550 if (kthread_should_stop() || signal_pending(current)) 551 break; 552 if (controller->ops->query_enum()) { 553 do { 554 rc = check_slots(); 555 if (rc > 0) { 556 /* Give userspace a chance to handle extraction */ 557 msleep(500); 558 } else if (rc < 0) { 559 dbg("%s - error checking slots", __func__); 560 thread_finished = 1; 561 goto out; 562 } 563 } while (atomic_read(&extracting) && !kthread_should_stop()); 564 } 565 msleep(100); 566 } 567 out: 568 return 0; 569 } 570 571 static int 572 cpci_start_thread(void) 573 { 574 if (controller->irq) 575 cpci_thread = kthread_run(event_thread, NULL, "cpci_hp_eventd"); 576 else 577 cpci_thread = kthread_run(poll_thread, NULL, "cpci_hp_polld"); 578 if (IS_ERR(cpci_thread)) { 579 err("Can't start up our thread"); 580 return PTR_ERR(cpci_thread); 581 } 582 thread_finished = 0; 583 return 0; 584 } 585 586 static void 587 cpci_stop_thread(void) 588 { 589 kthread_stop(cpci_thread); 590 thread_finished = 1; 591 } 592 593 int 594 cpci_hp_register_controller(struct cpci_hp_controller *new_controller) 595 { 596 int status = 0; 597 598 if (controller) 599 return -1; 600 if (!(new_controller && new_controller->ops)) 601 return -EINVAL; 602 if (new_controller->irq) { 603 if (!(new_controller->ops->enable_irq && 604 new_controller->ops->disable_irq)) 605 status = -EINVAL; 606 if (request_irq(new_controller->irq, 607 cpci_hp_intr, 608 new_controller->irq_flags, 609 MY_NAME, 610 new_controller->dev_id)) { 611 err("Can't get irq %d for the hotplug cPCI controller", 612 new_controller->irq); 613 status = -ENODEV; 614 } 615 dbg("%s - acquired controller irq %d", 616 __func__, new_controller->irq); 617 } 618 if (!status) 619 controller = new_controller; 620 return status; 621 } 622 EXPORT_SYMBOL_GPL(cpci_hp_register_controller); 623 624 static void 625 cleanup_slots(void) 626 { 627 struct slot *slot; 628 struct slot *tmp; 629 630 /* 631 * Unregister all of our slots with the pci_hotplug subsystem, 632 * and free up all memory that we had allocated. 633 */ 634 down_write(&list_rwsem); 635 if (!slots) 636 goto cleanup_null; 637 list_for_each_entry_safe(slot, tmp, &slot_list, slot_list) { 638 list_del(&slot->slot_list); 639 pci_hp_deregister(slot->hotplug_slot); 640 } 641 cleanup_null: 642 up_write(&list_rwsem); 643 return; 644 } 645 646 int 647 cpci_hp_unregister_controller(struct cpci_hp_controller *old_controller) 648 { 649 int status = 0; 650 651 if (controller) { 652 if (!thread_finished) 653 cpci_stop_thread(); 654 if (controller->irq) 655 free_irq(controller->irq, controller->dev_id); 656 controller = NULL; 657 cleanup_slots(); 658 } else 659 status = -ENODEV; 660 return status; 661 } 662 EXPORT_SYMBOL_GPL(cpci_hp_unregister_controller); 663 664 int 665 cpci_hp_start(void) 666 { 667 static int first = 1; 668 int status; 669 670 dbg("%s - enter", __func__); 671 if (!controller) 672 return -ENODEV; 673 674 down_read(&list_rwsem); 675 if (list_empty(&slot_list)) { 676 up_read(&list_rwsem); 677 return -ENODEV; 678 } 679 up_read(&list_rwsem); 680 681 status = init_slots(first); 682 if (first) 683 first = 0; 684 if (status) 685 return status; 686 687 status = cpci_start_thread(); 688 if (status) 689 return status; 690 dbg("%s - thread started", __func__); 691 692 if (controller->irq) { 693 /* Start enum interrupt processing */ 694 dbg("%s - enabling irq", __func__); 695 controller->ops->enable_irq(); 696 } 697 dbg("%s - exit", __func__); 698 return 0; 699 } 700 EXPORT_SYMBOL_GPL(cpci_hp_start); 701 702 int 703 cpci_hp_stop(void) 704 { 705 if (!controller) 706 return -ENODEV; 707 if (controller->irq) { 708 /* Stop enum interrupt processing */ 709 dbg("%s - disabling irq", __func__); 710 controller->ops->disable_irq(); 711 } 712 cpci_stop_thread(); 713 return 0; 714 } 715 EXPORT_SYMBOL_GPL(cpci_hp_stop); 716 717 int __init 718 cpci_hotplug_init(int debug) 719 { 720 cpci_debug = debug; 721 return 0; 722 } 723 724 void __exit 725 cpci_hotplug_exit(void) 726 { 727 /* 728 * Clean everything up. 729 */ 730 cpci_hp_stop(); 731 cpci_hp_unregister_controller(controller); 732 } 733