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 return -EINVAL; 131 132 /* see what our current state is */ 133 retval = get_lock_status(hotplug_slot, &value); 134 if (retval || (value == status)) 135 goto set_lock_exit; 136 137 slot->hpc_ops->toggle_emi(slot); 138 set_lock_exit: 139 mutex_unlock(&slot->ctrl->crit_sect); 140 return 0; 141 } 142 143 /* 144 * sysfs interface which allows the user to toggle the Electro Mechanical 145 * Interlock. Valid values are either 0 or 1. 0 == unlock, 1 == lock 146 */ 147 static ssize_t lock_write_file(struct hotplug_slot *slot, const char *buf, 148 size_t count) 149 { 150 unsigned long llock; 151 u8 lock; 152 int retval = 0; 153 154 llock = simple_strtoul(buf, NULL, 10); 155 lock = (u8)(llock & 0xff); 156 157 switch (lock) { 158 case 0: 159 case 1: 160 retval = set_lock_status(slot, lock); 161 break; 162 default: 163 err ("%d is an invalid lock value\n", lock); 164 retval = -EINVAL; 165 } 166 if (retval) 167 return retval; 168 return count; 169 } 170 171 static struct hotplug_slot_attribute hotplug_slot_attr_lock = { 172 .attr = {.name = "lock", .mode = S_IFREG | S_IRUGO | S_IWUSR}, 173 .show = lock_read_file, 174 .store = lock_write_file 175 }; 176 177 /** 178 * release_slot - free up the memory used by a slot 179 * @hotplug_slot: slot to free 180 */ 181 static void release_slot(struct hotplug_slot *hotplug_slot) 182 { 183 dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); 184 185 kfree(hotplug_slot->info); 186 kfree(hotplug_slot); 187 } 188 189 static int init_slots(struct controller *ctrl) 190 { 191 struct slot *slot; 192 struct hotplug_slot *hotplug_slot; 193 struct hotplug_slot_info *info; 194 int len, dup = 1; 195 int retval = -ENOMEM; 196 197 list_for_each_entry(slot, &ctrl->slot_list, slot_list) { 198 hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL); 199 if (!hotplug_slot) 200 goto error; 201 202 info = kzalloc(sizeof(*info), GFP_KERNEL); 203 if (!info) 204 goto error_hpslot; 205 206 /* register this slot with the hotplug pci core */ 207 hotplug_slot->info = info; 208 hotplug_slot->name = slot->name; 209 hotplug_slot->private = slot; 210 hotplug_slot->release = &release_slot; 211 hotplug_slot->ops = &pciehp_hotplug_slot_ops; 212 get_power_status(hotplug_slot, &info->power_status); 213 get_attention_status(hotplug_slot, &info->attention_status); 214 get_latch_status(hotplug_slot, &info->latch_status); 215 get_adapter_status(hotplug_slot, &info->adapter_status); 216 slot->hotplug_slot = hotplug_slot; 217 218 dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " 219 "slot_device_offset=%x\n", slot->bus, slot->device, 220 slot->hp_slot, slot->number, ctrl->slot_device_offset); 221 duplicate_name: 222 retval = pci_hp_register(hotplug_slot, 223 ctrl->pci_dev->subordinate, 224 slot->device); 225 if (retval) { 226 /* 227 * If slot N already exists, we'll try to create 228 * slot N-1, N-2 ... N-M, until we overflow. 229 */ 230 if (retval == -EEXIST) { 231 len = snprintf(slot->name, SLOT_NAME_SIZE, 232 "%d-%d", slot->number, dup++); 233 if (len < SLOT_NAME_SIZE) 234 goto duplicate_name; 235 else 236 err("duplicate slot name overflow\n"); 237 } 238 err("pci_hp_register failed with error %d\n", retval); 239 goto error_info; 240 } 241 /* create additional sysfs entries */ 242 if (EMI(ctrl)) { 243 retval = sysfs_create_file(&hotplug_slot->pci_slot->kobj, 244 &hotplug_slot_attr_lock.attr); 245 if (retval) { 246 pci_hp_deregister(hotplug_slot); 247 err("cannot create additional sysfs entries\n"); 248 goto error_info; 249 } 250 } 251 } 252 253 return 0; 254 error_info: 255 kfree(info); 256 error_hpslot: 257 kfree(hotplug_slot); 258 error: 259 return retval; 260 } 261 262 static void cleanup_slots(struct controller *ctrl) 263 { 264 struct slot *slot; 265 266 list_for_each_entry(slot, &ctrl->slot_list, slot_list) { 267 if (EMI(ctrl)) 268 sysfs_remove_file(&slot->hotplug_slot->pci_slot->kobj, 269 &hotplug_slot_attr_lock.attr); 270 pci_hp_deregister(slot->hotplug_slot); 271 } 272 } 273 274 /* 275 * set_attention_status - Turns the Amber LED for a slot on, off or blink 276 */ 277 static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) 278 { 279 struct slot *slot = hotplug_slot->private; 280 281 dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); 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 dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); 297 298 return pciehp_sysfs_enable_slot(slot); 299 } 300 301 302 static int disable_slot(struct hotplug_slot *hotplug_slot) 303 { 304 struct slot *slot = hotplug_slot->private; 305 306 dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); 307 308 return pciehp_sysfs_disable_slot(slot); 309 } 310 311 static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) 312 { 313 struct slot *slot = hotplug_slot->private; 314 int retval; 315 316 dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); 317 318 retval = slot->hpc_ops->get_power_status(slot, value); 319 if (retval < 0) 320 *value = hotplug_slot->info->power_status; 321 322 return 0; 323 } 324 325 static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) 326 { 327 struct slot *slot = hotplug_slot->private; 328 int retval; 329 330 dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); 331 332 retval = slot->hpc_ops->get_attention_status(slot, value); 333 if (retval < 0) 334 *value = hotplug_slot->info->attention_status; 335 336 return 0; 337 } 338 339 static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) 340 { 341 struct slot *slot = hotplug_slot->private; 342 int retval; 343 344 dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); 345 346 retval = slot->hpc_ops->get_latch_status(slot, value); 347 if (retval < 0) 348 *value = hotplug_slot->info->latch_status; 349 350 return 0; 351 } 352 353 static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) 354 { 355 struct slot *slot = hotplug_slot->private; 356 int retval; 357 358 dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); 359 360 retval = slot->hpc_ops->get_adapter_status(slot, value); 361 if (retval < 0) 362 *value = hotplug_slot->info->adapter_status; 363 364 return 0; 365 } 366 367 static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, 368 enum pci_bus_speed *value) 369 { 370 struct slot *slot = hotplug_slot->private; 371 int retval; 372 373 dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); 374 375 retval = slot->hpc_ops->get_max_bus_speed(slot, value); 376 if (retval < 0) 377 *value = PCI_SPEED_UNKNOWN; 378 379 return 0; 380 } 381 382 static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) 383 { 384 struct slot *slot = hotplug_slot->private; 385 int retval; 386 387 dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); 388 389 retval = slot->hpc_ops->get_cur_bus_speed(slot, value); 390 if (retval < 0) 391 *value = PCI_SPEED_UNKNOWN; 392 393 return 0; 394 } 395 396 static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_id *id) 397 { 398 int rc; 399 struct controller *ctrl; 400 struct slot *t_slot; 401 u8 value; 402 struct pci_dev *pdev = dev->port; 403 404 if (pciehp_force) 405 dbg("Bypassing BIOS check for pciehp use on %s\n", 406 pci_name(pdev)); 407 else if (pciehp_get_hp_hw_control_from_firmware(pdev)) 408 goto err_out_none; 409 410 ctrl = pcie_init(dev); 411 if (!ctrl) { 412 dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME); 413 goto err_out_none; 414 } 415 set_service_data(dev, ctrl); 416 417 /* Setup the slot information structures */ 418 rc = init_slots(ctrl); 419 if (rc) { 420 if (rc == -EBUSY) 421 warn("%s: slot already registered by another " 422 "hotplug driver\n", PCIE_MODULE_NAME); 423 else 424 err("%s: slot initialization failed\n", 425 PCIE_MODULE_NAME); 426 goto err_out_release_ctlr; 427 } 428 429 t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); 430 431 t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ 432 if (value && pciehp_force) { 433 rc = pciehp_enable_slot(t_slot); 434 if (rc) /* -ENODEV: shouldn't happen, but deal with it */ 435 value = 0; 436 } 437 if ((POWER_CTRL(ctrl)) && !value) { 438 rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ 439 if (rc) 440 goto err_out_free_ctrl_slot; 441 } 442 443 return 0; 444 445 err_out_free_ctrl_slot: 446 cleanup_slots(ctrl); 447 err_out_release_ctlr: 448 ctrl->hpc_ops->release_ctlr(ctrl); 449 err_out_none: 450 return -ENODEV; 451 } 452 453 static void pciehp_remove (struct pcie_device *dev) 454 { 455 struct controller *ctrl = get_service_data(dev); 456 457 cleanup_slots(ctrl); 458 ctrl->hpc_ops->release_ctlr(ctrl); 459 } 460 461 #ifdef CONFIG_PM 462 static int pciehp_suspend (struct pcie_device *dev, pm_message_t state) 463 { 464 printk("%s ENTRY\n", __func__); 465 return 0; 466 } 467 468 static int pciehp_resume (struct pcie_device *dev) 469 { 470 printk("%s ENTRY\n", __func__); 471 if (pciehp_force) { 472 struct controller *ctrl = get_service_data(dev); 473 struct slot *t_slot; 474 u8 status; 475 476 /* reinitialize the chipset's event detection logic */ 477 pcie_enable_notification(ctrl); 478 479 t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); 480 481 /* Check if slot is occupied */ 482 t_slot->hpc_ops->get_adapter_status(t_slot, &status); 483 if (status) 484 pciehp_enable_slot(t_slot); 485 else 486 pciehp_disable_slot(t_slot); 487 } 488 return 0; 489 } 490 #endif 491 492 static struct pcie_port_service_id port_pci_ids[] = { { 493 .vendor = PCI_ANY_ID, 494 .device = PCI_ANY_ID, 495 .port_type = PCIE_ANY_PORT, 496 .service_type = PCIE_PORT_SERVICE_HP, 497 .driver_data = 0, 498 }, { /* end: all zeroes */ } 499 }; 500 static const char device_name[] = "hpdriver"; 501 502 static struct pcie_port_service_driver hpdriver_portdrv = { 503 .name = (char *)device_name, 504 .id_table = &port_pci_ids[0], 505 506 .probe = pciehp_probe, 507 .remove = pciehp_remove, 508 509 #ifdef CONFIG_PM 510 .suspend = pciehp_suspend, 511 .resume = pciehp_resume, 512 #endif /* PM */ 513 }; 514 515 static int __init pcied_init(void) 516 { 517 int retval = 0; 518 519 retval = pcie_port_service_register(&hpdriver_portdrv); 520 dbg("pcie_port_service_register = %d\n", retval); 521 info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); 522 if (retval) 523 dbg("%s: Failure to register service\n", __func__); 524 return retval; 525 } 526 527 static void __exit pcied_cleanup(void) 528 { 529 dbg("unload_pciehpd()\n"); 530 pcie_port_service_unregister(&hpdriver_portdrv); 531 info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); 532 } 533 534 module_init(pcied_init); 535 module_exit(pcied_cleanup); 536