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 workqueue_struct *pciehp_wq; 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 set_attention_status (struct hotplug_slot *slot, u8 value); 66 static int enable_slot (struct hotplug_slot *slot); 67 static int disable_slot (struct hotplug_slot *slot); 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_latch_status (struct hotplug_slot *slot, u8 *value); 71 static int get_adapter_status (struct hotplug_slot *slot, u8 *value); 72 static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); 73 static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); 74 75 static struct hotplug_slot_ops pciehp_hotplug_slot_ops = { 76 .owner = THIS_MODULE, 77 .set_attention_status = set_attention_status, 78 .enable_slot = enable_slot, 79 .disable_slot = disable_slot, 80 .get_power_status = get_power_status, 81 .get_attention_status = get_attention_status, 82 .get_latch_status = get_latch_status, 83 .get_adapter_status = get_adapter_status, 84 .get_max_bus_speed = get_max_bus_speed, 85 .get_cur_bus_speed = get_cur_bus_speed, 86 }; 87 88 /* 89 * Check the status of the Electro Mechanical Interlock (EMI) 90 */ 91 static int get_lock_status(struct hotplug_slot *hotplug_slot, u8 *value) 92 { 93 struct slot *slot = hotplug_slot->private; 94 return (slot->hpc_ops->get_emi_status(slot, value)); 95 } 96 97 /* 98 * sysfs interface for the Electro Mechanical Interlock (EMI) 99 * 1 == locked, 0 == unlocked 100 */ 101 static ssize_t lock_read_file(struct hotplug_slot *slot, char *buf) 102 { 103 int retval; 104 u8 value; 105 106 retval = get_lock_status(slot, &value); 107 if (retval) 108 goto lock_read_exit; 109 retval = sprintf (buf, "%d\n", value); 110 111 lock_read_exit: 112 return retval; 113 } 114 115 /* 116 * Change the status of the Electro Mechanical Interlock (EMI) 117 * This is a toggle - in addition there must be at least 1 second 118 * in between toggles. 119 */ 120 static int set_lock_status(struct hotplug_slot *hotplug_slot, u8 status) 121 { 122 struct slot *slot = hotplug_slot->private; 123 int retval; 124 u8 value; 125 126 mutex_lock(&slot->ctrl->crit_sect); 127 128 /* has it been >1 sec since our last toggle? */ 129 if ((get_seconds() - slot->last_emi_toggle) < 1) { 130 mutex_unlock(&slot->ctrl->crit_sect); 131 return -EINVAL; 132 } 133 134 /* see what our current state is */ 135 retval = get_lock_status(hotplug_slot, &value); 136 if (retval || (value == status)) 137 goto set_lock_exit; 138 139 slot->hpc_ops->toggle_emi(slot); 140 set_lock_exit: 141 mutex_unlock(&slot->ctrl->crit_sect); 142 return 0; 143 } 144 145 /* 146 * sysfs interface which allows the user to toggle the Electro Mechanical 147 * Interlock. Valid values are either 0 or 1. 0 == unlock, 1 == lock 148 */ 149 static ssize_t lock_write_file(struct hotplug_slot *hotplug_slot, 150 const char *buf, size_t count) 151 { 152 struct slot *slot = hotplug_slot->private; 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(hotplug_slot, lock); 164 break; 165 default: 166 ctrl_err(slot->ctrl, "%d is an invalid lock value\n", 167 lock); 168 retval = -EINVAL; 169 } 170 if (retval) 171 return retval; 172 return count; 173 } 174 175 static struct hotplug_slot_attribute hotplug_slot_attr_lock = { 176 .attr = {.name = "lock", .mode = S_IFREG | S_IRUGO | S_IWUSR}, 177 .show = lock_read_file, 178 .store = lock_write_file 179 }; 180 181 /** 182 * release_slot - free up the memory used by a slot 183 * @hotplug_slot: slot to free 184 */ 185 static void release_slot(struct hotplug_slot *hotplug_slot) 186 { 187 struct slot *slot = hotplug_slot->private; 188 189 ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", 190 __func__, hotplug_slot_name(hotplug_slot)); 191 192 kfree(hotplug_slot->info); 193 kfree(hotplug_slot); 194 } 195 196 static int init_slots(struct controller *ctrl) 197 { 198 struct slot *slot; 199 struct hotplug_slot *hotplug_slot; 200 struct hotplug_slot_info *info; 201 char name[SLOT_NAME_SIZE]; 202 int retval = -ENOMEM; 203 204 list_for_each_entry(slot, &ctrl->slot_list, slot_list) { 205 hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL); 206 if (!hotplug_slot) 207 goto error; 208 209 info = kzalloc(sizeof(*info), GFP_KERNEL); 210 if (!info) 211 goto error_hpslot; 212 213 /* register this slot with the hotplug pci core */ 214 hotplug_slot->info = info; 215 hotplug_slot->private = slot; 216 hotplug_slot->release = &release_slot; 217 hotplug_slot->ops = &pciehp_hotplug_slot_ops; 218 slot->hotplug_slot = hotplug_slot; 219 snprintf(name, SLOT_NAME_SIZE, "%u", slot->number); 220 221 ctrl_dbg(ctrl, "Registering domain:bus:dev=%04x:%02x:%02x " 222 "hp_slot=%x sun=%x slot_device_offset=%x\n", 223 pci_domain_nr(ctrl->pci_dev->subordinate), 224 slot->bus, slot->device, slot->hp_slot, slot->number, 225 ctrl->slot_device_offset); 226 retval = pci_hp_register(hotplug_slot, 227 ctrl->pci_dev->subordinate, 228 slot->device, 229 name); 230 if (retval) { 231 ctrl_err(ctrl, "pci_hp_register failed with error %d\n", 232 retval); 233 goto error_info; 234 } 235 get_power_status(hotplug_slot, &info->power_status); 236 get_attention_status(hotplug_slot, &info->attention_status); 237 get_latch_status(hotplug_slot, &info->latch_status); 238 get_adapter_status(hotplug_slot, &info->adapter_status); 239 /* create additional sysfs entries */ 240 if (EMI(ctrl)) { 241 retval = sysfs_create_file(&hotplug_slot->pci_slot->kobj, 242 &hotplug_slot_attr_lock.attr); 243 if (retval) { 244 pci_hp_deregister(hotplug_slot); 245 ctrl_err(ctrl, "Cannot create additional sysfs " 246 "entries\n"); 247 goto error_info; 248 } 249 } 250 } 251 252 return 0; 253 error_info: 254 kfree(info); 255 error_hpslot: 256 kfree(hotplug_slot); 257 error: 258 return retval; 259 } 260 261 static void cleanup_slots(struct controller *ctrl) 262 { 263 struct slot *slot; 264 265 list_for_each_entry(slot, &ctrl->slot_list, slot_list) { 266 if (EMI(ctrl)) 267 sysfs_remove_file(&slot->hotplug_slot->pci_slot->kobj, 268 &hotplug_slot_attr_lock.attr); 269 pci_hp_deregister(slot->hotplug_slot); 270 } 271 } 272 273 /* 274 * set_attention_status - Turns the Amber LED for a slot on, off or blink 275 */ 276 static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) 277 { 278 struct slot *slot = hotplug_slot->private; 279 280 ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", 281 __func__, slot_name(slot)); 282 283 hotplug_slot->info->attention_status = status; 284 285 if (ATTN_LED(slot->ctrl)) 286 slot->hpc_ops->set_attention_status(slot, status); 287 288 return 0; 289 } 290 291 292 static int enable_slot(struct hotplug_slot *hotplug_slot) 293 { 294 struct slot *slot = hotplug_slot->private; 295 296 ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", 297 __func__, slot_name(slot)); 298 299 return pciehp_sysfs_enable_slot(slot); 300 } 301 302 303 static int disable_slot(struct hotplug_slot *hotplug_slot) 304 { 305 struct slot *slot = hotplug_slot->private; 306 307 ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", 308 __func__, slot_name(slot)); 309 310 return pciehp_sysfs_disable_slot(slot); 311 } 312 313 static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) 314 { 315 struct slot *slot = hotplug_slot->private; 316 int retval; 317 318 ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", 319 __func__, slot_name(slot)); 320 321 retval = slot->hpc_ops->get_power_status(slot, value); 322 if (retval < 0) 323 *value = hotplug_slot->info->power_status; 324 325 return 0; 326 } 327 328 static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) 329 { 330 struct slot *slot = hotplug_slot->private; 331 int retval; 332 333 ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", 334 __func__, slot_name(slot)); 335 336 retval = slot->hpc_ops->get_attention_status(slot, value); 337 if (retval < 0) 338 *value = hotplug_slot->info->attention_status; 339 340 return 0; 341 } 342 343 static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) 344 { 345 struct slot *slot = hotplug_slot->private; 346 int retval; 347 348 ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", 349 __func__, slot_name(slot)); 350 351 retval = slot->hpc_ops->get_latch_status(slot, value); 352 if (retval < 0) 353 *value = hotplug_slot->info->latch_status; 354 355 return 0; 356 } 357 358 static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) 359 { 360 struct slot *slot = hotplug_slot->private; 361 int retval; 362 363 ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", 364 __func__, slot_name(slot)); 365 366 retval = slot->hpc_ops->get_adapter_status(slot, value); 367 if (retval < 0) 368 *value = hotplug_slot->info->adapter_status; 369 370 return 0; 371 } 372 373 static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, 374 enum pci_bus_speed *value) 375 { 376 struct slot *slot = hotplug_slot->private; 377 int retval; 378 379 ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", 380 __func__, slot_name(slot)); 381 382 retval = slot->hpc_ops->get_max_bus_speed(slot, value); 383 if (retval < 0) 384 *value = PCI_SPEED_UNKNOWN; 385 386 return 0; 387 } 388 389 static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) 390 { 391 struct slot *slot = hotplug_slot->private; 392 int retval; 393 394 ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", 395 __func__, slot_name(slot)); 396 397 retval = slot->hpc_ops->get_cur_bus_speed(slot, value); 398 if (retval < 0) 399 *value = PCI_SPEED_UNKNOWN; 400 401 return 0; 402 } 403 404 static int pciehp_probe(struct pcie_device *dev) 405 { 406 int rc; 407 struct controller *ctrl; 408 struct slot *t_slot; 409 u8 value; 410 struct pci_dev *pdev = dev->port; 411 412 if (pciehp_force) 413 dev_info(&dev->device, 414 "Bypassing BIOS check for pciehp use on %s\n", 415 pci_name(pdev)); 416 else if (pciehp_get_hp_hw_control_from_firmware(pdev)) 417 goto err_out_none; 418 419 ctrl = pcie_init(dev); 420 if (!ctrl) { 421 dev_err(&dev->device, "Controller initialization failed\n"); 422 goto err_out_none; 423 } 424 set_service_data(dev, ctrl); 425 426 /* Setup the slot information structures */ 427 rc = init_slots(ctrl); 428 if (rc) { 429 if (rc == -EBUSY) 430 ctrl_warn(ctrl, "Slot already registered by another " 431 "hotplug driver\n"); 432 else 433 ctrl_err(ctrl, "Slot initialization failed\n"); 434 goto err_out_release_ctlr; 435 } 436 437 /* Enable events after we have setup the data structures */ 438 rc = pcie_init_notification(ctrl); 439 if (rc) { 440 ctrl_err(ctrl, "Notification initialization failed\n"); 441 goto err_out_release_ctlr; 442 } 443 444 /* Check if slot is occupied */ 445 t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); 446 t_slot->hpc_ops->get_adapter_status(t_slot, &value); 447 if (value) { 448 if (pciehp_force) 449 pciehp_enable_slot(t_slot); 450 } else { 451 /* Power off slot if not occupied */ 452 if (POWER_CTRL(ctrl)) { 453 rc = t_slot->hpc_ops->power_off_slot(t_slot); 454 if (rc) 455 goto err_out_free_ctrl_slot; 456 } 457 } 458 459 return 0; 460 461 err_out_free_ctrl_slot: 462 cleanup_slots(ctrl); 463 err_out_release_ctlr: 464 ctrl->hpc_ops->release_ctlr(ctrl); 465 err_out_none: 466 return -ENODEV; 467 } 468 469 static void pciehp_remove (struct pcie_device *dev) 470 { 471 struct controller *ctrl = get_service_data(dev); 472 473 cleanup_slots(ctrl); 474 ctrl->hpc_ops->release_ctlr(ctrl); 475 } 476 477 #ifdef CONFIG_PM 478 static int pciehp_suspend (struct pcie_device *dev) 479 { 480 dev_info(&dev->device, "%s ENTRY\n", __func__); 481 return 0; 482 } 483 484 static int pciehp_resume (struct pcie_device *dev) 485 { 486 dev_info(&dev->device, "%s ENTRY\n", __func__); 487 if (pciehp_force) { 488 struct controller *ctrl = get_service_data(dev); 489 struct slot *t_slot; 490 u8 status; 491 492 /* reinitialize the chipset's event detection logic */ 493 pcie_enable_notification(ctrl); 494 495 t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); 496 497 /* Check if slot is occupied */ 498 t_slot->hpc_ops->get_adapter_status(t_slot, &status); 499 if (status) 500 pciehp_enable_slot(t_slot); 501 else 502 pciehp_disable_slot(t_slot); 503 } 504 return 0; 505 } 506 #endif /* PM */ 507 508 static struct pcie_port_service_driver hpdriver_portdrv = { 509 .name = PCIE_MODULE_NAME, 510 .port_type = PCIE_ANY_PORT, 511 .service = PCIE_PORT_SERVICE_HP, 512 513 .probe = pciehp_probe, 514 .remove = pciehp_remove, 515 516 #ifdef CONFIG_PM 517 .suspend = pciehp_suspend, 518 .resume = pciehp_resume, 519 #endif /* PM */ 520 }; 521 522 static int __init pcied_init(void) 523 { 524 int retval = 0; 525 526 pciehp_firmware_init(); 527 retval = pcie_port_service_register(&hpdriver_portdrv); 528 dbg("pcie_port_service_register = %d\n", retval); 529 info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); 530 if (retval) 531 dbg("Failure to register service\n"); 532 return retval; 533 } 534 535 static void __exit pcied_cleanup(void) 536 { 537 dbg("unload_pciehpd()\n"); 538 pcie_port_service_unregister(&hpdriver_portdrv); 539 info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); 540 } 541 542 module_init(pcied_init); 543 module_exit(pcied_cleanup); 544