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/moduleparam.h> 32 #include <linux/kernel.h> 33 #include <linux/types.h> 34 #include <linux/pci.h> 35 #include "pciehp.h" 36 #include <linux/interrupt.h> 37 #include <linux/time.h> 38 39 /* Global variables */ 40 int pciehp_debug; 41 int pciehp_poll_mode; 42 int pciehp_poll_time; 43 int pciehp_force; 44 struct controller *pciehp_ctrl_list; 45 46 #define DRIVER_VERSION "0.4" 47 #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" 48 #define DRIVER_DESC "PCI Express Hot Plug Controller Driver" 49 50 MODULE_AUTHOR(DRIVER_AUTHOR); 51 MODULE_DESCRIPTION(DRIVER_DESC); 52 MODULE_LICENSE("GPL"); 53 54 module_param(pciehp_debug, bool, 0644); 55 module_param(pciehp_poll_mode, bool, 0644); 56 module_param(pciehp_poll_time, int, 0644); 57 module_param(pciehp_force, bool, 0644); 58 MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not"); 59 MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not"); 60 MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds"); 61 MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if _OSC and OSHP are missing"); 62 63 #define PCIE_MODULE_NAME "pciehp" 64 65 static int pcie_start_thread (void); 66 static int set_attention_status (struct hotplug_slot *slot, u8 value); 67 static int enable_slot (struct hotplug_slot *slot); 68 static int disable_slot (struct hotplug_slot *slot); 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_latch_status (struct hotplug_slot *slot, u8 *value); 72 static int get_adapter_status (struct hotplug_slot *slot, u8 *value); 73 static int get_address (struct hotplug_slot *slot, u32 *value); 74 static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); 75 static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); 76 77 static struct hotplug_slot_ops pciehp_hotplug_slot_ops = { 78 .owner = THIS_MODULE, 79 .set_attention_status = set_attention_status, 80 .enable_slot = enable_slot, 81 .disable_slot = disable_slot, 82 .get_power_status = get_power_status, 83 .get_attention_status = get_attention_status, 84 .get_latch_status = get_latch_status, 85 .get_adapter_status = get_adapter_status, 86 .get_address = get_address, 87 .get_max_bus_speed = get_max_bus_speed, 88 .get_cur_bus_speed = get_cur_bus_speed, 89 }; 90 91 /* 92 * Check the status of the Electro Mechanical Interlock (EMI) 93 */ 94 static int get_lock_status(struct hotplug_slot *hotplug_slot, u8 *value) 95 { 96 struct slot *slot = hotplug_slot->private; 97 return (slot->hpc_ops->get_emi_status(slot, value)); 98 } 99 100 /* 101 * sysfs interface for the Electro Mechanical Interlock (EMI) 102 * 1 == locked, 0 == unlocked 103 */ 104 static ssize_t lock_read_file(struct hotplug_slot *slot, char *buf) 105 { 106 int retval; 107 u8 value; 108 109 retval = get_lock_status(slot, &value); 110 if (retval) 111 goto lock_read_exit; 112 retval = sprintf (buf, "%d\n", value); 113 114 lock_read_exit: 115 return retval; 116 } 117 118 /* 119 * Change the status of the Electro Mechanical Interlock (EMI) 120 * This is a toggle - in addition there must be at least 1 second 121 * in between toggles. 122 */ 123 static int set_lock_status(struct hotplug_slot *hotplug_slot, u8 status) 124 { 125 struct slot *slot = hotplug_slot->private; 126 int retval; 127 u8 value; 128 129 mutex_lock(&slot->ctrl->crit_sect); 130 131 /* has it been >1 sec since our last toggle? */ 132 if ((get_seconds() - slot->last_emi_toggle) < 1) 133 return -EINVAL; 134 135 /* see what our current state is */ 136 retval = get_lock_status(hotplug_slot, &value); 137 if (retval || (value == status)) 138 goto set_lock_exit; 139 140 slot->hpc_ops->toggle_emi(slot); 141 set_lock_exit: 142 mutex_unlock(&slot->ctrl->crit_sect); 143 return 0; 144 } 145 146 /* 147 * sysfs interface which allows the user to toggle the Electro Mechanical 148 * Interlock. Valid values are either 0 or 1. 0 == unlock, 1 == lock 149 */ 150 static ssize_t lock_write_file(struct hotplug_slot *slot, const char *buf, 151 size_t count) 152 { 153 unsigned long llock; 154 u8 lock; 155 int retval = 0; 156 157 llock = simple_strtoul(buf, NULL, 10); 158 lock = (u8)(llock & 0xff); 159 160 switch (lock) { 161 case 0: 162 case 1: 163 retval = set_lock_status(slot, lock); 164 break; 165 default: 166 err ("%d is an invalid lock value\n", lock); 167 retval = -EINVAL; 168 } 169 if (retval) 170 return retval; 171 return count; 172 } 173 174 static struct hotplug_slot_attribute hotplug_slot_attr_lock = { 175 .attr = {.name = "lock", .mode = S_IFREG | S_IRUGO | S_IWUSR}, 176 .show = lock_read_file, 177 .store = lock_write_file 178 }; 179 180 /** 181 * release_slot - free up the memory used by a slot 182 * @hotplug_slot: slot to free 183 */ 184 static void release_slot(struct hotplug_slot *hotplug_slot) 185 { 186 struct slot *slot = hotplug_slot->private; 187 188 dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); 189 190 kfree(slot->hotplug_slot->info); 191 kfree(slot->hotplug_slot); 192 kfree(slot); 193 } 194 195 static void make_slot_name(struct slot *slot) 196 { 197 snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d", 198 slot->bus, slot->number); 199 } 200 201 static int init_slots(struct controller *ctrl) 202 { 203 struct slot *slot; 204 struct hotplug_slot *hotplug_slot; 205 struct hotplug_slot_info *info; 206 int retval = -ENOMEM; 207 int i; 208 209 for (i = 0; i < ctrl->num_slots; i++) { 210 slot = kzalloc(sizeof(*slot), GFP_KERNEL); 211 if (!slot) 212 goto error; 213 214 hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL); 215 if (!hotplug_slot) 216 goto error_slot; 217 slot->hotplug_slot = hotplug_slot; 218 219 info = kzalloc(sizeof(*info), GFP_KERNEL); 220 if (!info) 221 goto error_hpslot; 222 hotplug_slot->info = info; 223 224 hotplug_slot->name = slot->name; 225 226 slot->hp_slot = i; 227 slot->ctrl = ctrl; 228 slot->bus = ctrl->pci_dev->subordinate->number; 229 slot->device = ctrl->slot_device_offset + i; 230 slot->hpc_ops = ctrl->hpc_ops; 231 slot->number = ctrl->first_slot; 232 233 /* register this slot with the hotplug pci core */ 234 hotplug_slot->private = slot; 235 hotplug_slot->release = &release_slot; 236 make_slot_name(slot); 237 hotplug_slot->ops = &pciehp_hotplug_slot_ops; 238 239 get_power_status(hotplug_slot, &info->power_status); 240 get_attention_status(hotplug_slot, &info->attention_status); 241 get_latch_status(hotplug_slot, &info->latch_status); 242 get_adapter_status(hotplug_slot, &info->adapter_status); 243 244 dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " 245 "slot_device_offset=%x\n", slot->bus, slot->device, 246 slot->hp_slot, slot->number, ctrl->slot_device_offset); 247 retval = pci_hp_register(hotplug_slot); 248 if (retval) { 249 err ("pci_hp_register failed with error %d\n", retval); 250 goto error_info; 251 } 252 /* create additional sysfs entries */ 253 if (EMI(ctrl->ctrlcap)) { 254 retval = sysfs_create_file(&hotplug_slot->kobj, 255 &hotplug_slot_attr_lock.attr); 256 if (retval) { 257 pci_hp_deregister(hotplug_slot); 258 err("cannot create additional sysfs entries\n"); 259 goto error_info; 260 } 261 } 262 263 list_add(&slot->slot_list, &ctrl->slot_list); 264 } 265 266 return 0; 267 error_info: 268 kfree(info); 269 error_hpslot: 270 kfree(hotplug_slot); 271 error_slot: 272 kfree(slot); 273 error: 274 return retval; 275 } 276 277 static void cleanup_slots(struct controller *ctrl) 278 { 279 struct list_head *tmp; 280 struct list_head *next; 281 struct slot *slot; 282 283 list_for_each_safe(tmp, next, &ctrl->slot_list) { 284 slot = list_entry(tmp, struct slot, slot_list); 285 list_del(&slot->slot_list); 286 if (EMI(ctrl->ctrlcap)) 287 sysfs_remove_file(&slot->hotplug_slot->kobj, 288 &hotplug_slot_attr_lock.attr); 289 pci_hp_deregister(slot->hotplug_slot); 290 } 291 } 292 293 /* 294 * set_attention_status - Turns the Amber LED for a slot on, off or blink 295 */ 296 static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) 297 { 298 struct slot *slot = hotplug_slot->private; 299 300 dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); 301 302 hotplug_slot->info->attention_status = status; 303 304 if (ATTN_LED(slot->ctrl->ctrlcap)) 305 slot->hpc_ops->set_attention_status(slot, status); 306 307 return 0; 308 } 309 310 311 static int enable_slot(struct hotplug_slot *hotplug_slot) 312 { 313 struct slot *slot = hotplug_slot->private; 314 315 dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); 316 317 return pciehp_enable_slot(slot); 318 } 319 320 321 static int disable_slot(struct hotplug_slot *hotplug_slot) 322 { 323 struct slot *slot = hotplug_slot->private; 324 325 dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); 326 327 return pciehp_disable_slot(slot); 328 } 329 330 static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) 331 { 332 struct slot *slot = hotplug_slot->private; 333 int retval; 334 335 dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); 336 337 retval = slot->hpc_ops->get_power_status(slot, value); 338 if (retval < 0) 339 *value = hotplug_slot->info->power_status; 340 341 return 0; 342 } 343 344 static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) 345 { 346 struct slot *slot = hotplug_slot->private; 347 int retval; 348 349 dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); 350 351 retval = slot->hpc_ops->get_attention_status(slot, value); 352 if (retval < 0) 353 *value = hotplug_slot->info->attention_status; 354 355 return 0; 356 } 357 358 static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) 359 { 360 struct slot *slot = hotplug_slot->private; 361 int retval; 362 363 dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); 364 365 retval = slot->hpc_ops->get_latch_status(slot, value); 366 if (retval < 0) 367 *value = hotplug_slot->info->latch_status; 368 369 return 0; 370 } 371 372 static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) 373 { 374 struct slot *slot = hotplug_slot->private; 375 int retval; 376 377 dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); 378 379 retval = slot->hpc_ops->get_adapter_status(slot, value); 380 if (retval < 0) 381 *value = hotplug_slot->info->adapter_status; 382 383 return 0; 384 } 385 386 static int get_address(struct hotplug_slot *hotplug_slot, u32 *value) 387 { 388 struct slot *slot = hotplug_slot->private; 389 struct pci_bus *bus = slot->ctrl->pci_dev->subordinate; 390 391 dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); 392 393 *value = (pci_domain_nr(bus) << 16) | (slot->bus << 8) | slot->device; 394 395 return 0; 396 } 397 398 static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) 399 { 400 struct slot *slot = hotplug_slot->private; 401 int retval; 402 403 dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); 404 405 retval = slot->hpc_ops->get_max_bus_speed(slot, value); 406 if (retval < 0) 407 *value = PCI_SPEED_UNKNOWN; 408 409 return 0; 410 } 411 412 static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) 413 { 414 struct slot *slot = hotplug_slot->private; 415 int retval; 416 417 dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); 418 419 retval = slot->hpc_ops->get_cur_bus_speed(slot, value); 420 if (retval < 0) 421 *value = PCI_SPEED_UNKNOWN; 422 423 return 0; 424 } 425 426 static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_id *id) 427 { 428 int rc; 429 struct controller *ctrl; 430 struct slot *t_slot; 431 u8 value; 432 struct pci_dev *pdev; 433 434 ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); 435 if (!ctrl) { 436 err("%s : out of memory\n", __FUNCTION__); 437 goto err_out_none; 438 } 439 INIT_LIST_HEAD(&ctrl->slot_list); 440 441 pdev = dev->port; 442 ctrl->pci_dev = pdev; 443 444 rc = pcie_init(ctrl, dev); 445 if (rc) { 446 dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME); 447 goto err_out_free_ctrl; 448 } 449 450 pci_set_drvdata(pdev, ctrl); 451 452 ctrl->bus = pdev->bus->number; /* ctrl bus */ 453 ctrl->slot_bus = pdev->subordinate->number; /* bus controlled by this HPC */ 454 455 ctrl->device = PCI_SLOT(pdev->devfn); 456 ctrl->function = PCI_FUNC(pdev->devfn); 457 dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", __FUNCTION__, 458 ctrl->bus, ctrl->device, ctrl->function, pdev->irq); 459 460 /* Setup the slot information structures */ 461 rc = init_slots(ctrl); 462 if (rc) { 463 err("%s: slot initialization failed\n", PCIE_MODULE_NAME); 464 goto err_out_release_ctlr; 465 } 466 467 t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); 468 469 /* Finish setting up the hot plug ctrl device */ 470 ctrl->next_event = 0; 471 472 if (!pciehp_ctrl_list) { 473 pciehp_ctrl_list = ctrl; 474 ctrl->next = NULL; 475 } else { 476 ctrl->next = pciehp_ctrl_list; 477 pciehp_ctrl_list = ctrl; 478 } 479 480 t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ 481 if ((POWER_CTRL(ctrl->ctrlcap)) && !value) { 482 rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ 483 if (rc) 484 goto err_out_free_ctrl_slot; 485 } 486 487 return 0; 488 489 err_out_free_ctrl_slot: 490 cleanup_slots(ctrl); 491 err_out_release_ctlr: 492 ctrl->hpc_ops->release_ctlr(ctrl); 493 err_out_free_ctrl: 494 kfree(ctrl); 495 err_out_none: 496 return -ENODEV; 497 } 498 499 500 static int pcie_start_thread(void) 501 { 502 int retval = 0; 503 504 dbg("Initialize + Start the notification/polling mechanism \n"); 505 506 retval = pciehp_event_start_thread(); 507 if (retval) { 508 dbg("pciehp_event_start_thread() failed\n"); 509 return retval; 510 } 511 512 return retval; 513 } 514 515 static void __exit unload_pciehpd(void) 516 { 517 struct controller *ctrl; 518 struct controller *tctrl; 519 520 ctrl = pciehp_ctrl_list; 521 522 while (ctrl) { 523 cleanup_slots(ctrl); 524 525 ctrl->hpc_ops->release_ctlr(ctrl); 526 527 tctrl = ctrl; 528 ctrl = ctrl->next; 529 530 kfree(tctrl); 531 } 532 533 /* Stop the notification mechanism */ 534 pciehp_event_stop_thread(); 535 536 } 537 538 static void pciehp_remove (struct pcie_device *device) 539 { 540 /* XXX - Needs to be adapted to device driver model */ 541 } 542 543 #ifdef CONFIG_PM 544 static int pciehp_suspend (struct pcie_device *dev, pm_message_t state) 545 { 546 printk("%s ENTRY\n", __FUNCTION__); 547 return 0; 548 } 549 550 static int pciehp_resume (struct pcie_device *dev) 551 { 552 printk("%s ENTRY\n", __FUNCTION__); 553 return 0; 554 } 555 #endif 556 557 static struct pcie_port_service_id port_pci_ids[] = { { 558 .vendor = PCI_ANY_ID, 559 .device = PCI_ANY_ID, 560 .port_type = PCIE_ANY_PORT, 561 .service_type = PCIE_PORT_SERVICE_HP, 562 .driver_data = 0, 563 }, { /* end: all zeroes */ } 564 }; 565 static const char device_name[] = "hpdriver"; 566 567 static struct pcie_port_service_driver hpdriver_portdrv = { 568 .name = (char *)device_name, 569 .id_table = &port_pci_ids[0], 570 571 .probe = pciehp_probe, 572 .remove = pciehp_remove, 573 574 #ifdef CONFIG_PM 575 .suspend = pciehp_suspend, 576 .resume = pciehp_resume, 577 #endif /* PM */ 578 }; 579 580 static int __init pcied_init(void) 581 { 582 int retval = 0; 583 584 #ifdef CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE 585 pciehp_poll_mode = 1; 586 #endif 587 588 retval = pcie_start_thread(); 589 if (retval) 590 goto error_hpc_init; 591 592 retval = pcie_port_service_register(&hpdriver_portdrv); 593 dbg("pcie_port_service_register = %d\n", retval); 594 info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); 595 if (retval) 596 dbg("%s: Failure to register service\n", __FUNCTION__); 597 598 error_hpc_init: 599 if (retval) { 600 pciehp_event_stop_thread(); 601 }; 602 603 return retval; 604 } 605 606 static void __exit pcied_cleanup(void) 607 { 608 dbg("unload_pciehpd()\n"); 609 unload_pciehpd(); 610 611 pcie_port_service_unregister(&hpdriver_portdrv); 612 613 info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); 614 } 615 616 module_init(pcied_init); 617 module_exit(pcied_cleanup); 618