1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * PCI HotPlug Controller Core 4 * 5 * Copyright (C) 2001-2002 Greg Kroah-Hartman (greg@kroah.com) 6 * Copyright (C) 2001-2002 IBM Corp. 7 * 8 * All rights reserved. 9 * 10 * Send feedback to <kristen.c.accardi@intel.com> 11 * 12 * Authors: 13 * Greg Kroah-Hartman <greg@kroah.com> 14 * Scott Murray <scottm@somanetworks.com> 15 */ 16 17 #include <linux/module.h> 18 #include <linux/moduleparam.h> 19 #include <linux/kernel.h> 20 #include <linux/types.h> 21 #include <linux/kobject.h> 22 #include <linux/sysfs.h> 23 #include <linux/init.h> 24 #include <linux/pci.h> 25 #include <linux/pci_hotplug.h> 26 #include "../pci.h" 27 #include "cpci_hotplug.h" 28 29 #define MY_NAME "pci_hotplug" 30 31 #define dbg(fmt, arg...) do { if (debug) printk(KERN_DEBUG "%s: %s: " fmt, MY_NAME, __func__, ## arg); } while (0) 32 #define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME, ## arg) 33 #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME, ## arg) 34 #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME, ## arg) 35 36 /* local variables */ 37 static bool debug; 38 39 /* Weee, fun with macros... */ 40 #define GET_STATUS(name, type) \ 41 static int get_##name(struct hotplug_slot *slot, type *value) \ 42 { \ 43 const struct hotplug_slot_ops *ops = slot->ops; \ 44 int retval = 0; \ 45 if (ops->get_##name) \ 46 retval = ops->get_##name(slot, value); \ 47 return retval; \ 48 } 49 50 GET_STATUS(power_status, u8) 51 GET_STATUS(attention_status, u8) 52 GET_STATUS(latch_status, u8) 53 GET_STATUS(adapter_status, u8) 54 55 static ssize_t power_read_file(struct pci_slot *pci_slot, char *buf) 56 { 57 int retval; 58 u8 value; 59 60 retval = get_power_status(pci_slot->hotplug, &value); 61 if (retval) 62 return retval; 63 64 return sysfs_emit(buf, "%d\n", value); 65 } 66 67 static ssize_t power_write_file(struct pci_slot *pci_slot, const char *buf, 68 size_t count) 69 { 70 struct hotplug_slot *slot = pci_slot->hotplug; 71 unsigned long lpower; 72 u8 power; 73 int retval = 0; 74 75 lpower = simple_strtoul(buf, NULL, 10); 76 power = (u8)(lpower & 0xff); 77 dbg("power = %d\n", power); 78 79 switch (power) { 80 case 0: 81 if (slot->ops->disable_slot) 82 retval = slot->ops->disable_slot(slot); 83 break; 84 85 case 1: 86 if (slot->ops->enable_slot) 87 retval = slot->ops->enable_slot(slot); 88 break; 89 90 default: 91 err("Illegal value specified for power\n"); 92 retval = -EINVAL; 93 } 94 95 if (retval) 96 return retval; 97 return count; 98 } 99 100 static struct pci_slot_attribute hotplug_slot_attr_power = { 101 .attr = {.name = "power", .mode = S_IFREG | S_IRUGO | S_IWUSR}, 102 .show = power_read_file, 103 .store = power_write_file 104 }; 105 106 static ssize_t attention_read_file(struct pci_slot *pci_slot, char *buf) 107 { 108 int retval; 109 u8 value; 110 111 retval = get_attention_status(pci_slot->hotplug, &value); 112 if (retval) 113 return retval; 114 115 return sysfs_emit(buf, "%d\n", value); 116 } 117 118 static ssize_t attention_write_file(struct pci_slot *pci_slot, const char *buf, 119 size_t count) 120 { 121 struct hotplug_slot *slot = pci_slot->hotplug; 122 const struct hotplug_slot_ops *ops = slot->ops; 123 unsigned long lattention; 124 u8 attention; 125 int retval = 0; 126 127 lattention = simple_strtoul(buf, NULL, 10); 128 attention = (u8)(lattention & 0xff); 129 dbg(" - attention = %d\n", attention); 130 131 if (ops->set_attention_status) 132 retval = ops->set_attention_status(slot, attention); 133 134 if (retval) 135 return retval; 136 return count; 137 } 138 139 static struct pci_slot_attribute hotplug_slot_attr_attention = { 140 .attr = {.name = "attention", .mode = S_IFREG | S_IRUGO | S_IWUSR}, 141 .show = attention_read_file, 142 .store = attention_write_file 143 }; 144 145 static ssize_t latch_read_file(struct pci_slot *pci_slot, char *buf) 146 { 147 int retval; 148 u8 value; 149 150 retval = get_latch_status(pci_slot->hotplug, &value); 151 if (retval) 152 return retval; 153 154 return sysfs_emit(buf, "%d\n", value); 155 } 156 157 static struct pci_slot_attribute hotplug_slot_attr_latch = { 158 .attr = {.name = "latch", .mode = S_IFREG | S_IRUGO}, 159 .show = latch_read_file, 160 }; 161 162 static ssize_t presence_read_file(struct pci_slot *pci_slot, char *buf) 163 { 164 int retval; 165 u8 value; 166 167 retval = get_adapter_status(pci_slot->hotplug, &value); 168 if (retval) 169 return retval; 170 171 return sysfs_emit(buf, "%d\n", value); 172 } 173 174 static struct pci_slot_attribute hotplug_slot_attr_presence = { 175 .attr = {.name = "adapter", .mode = S_IFREG | S_IRUGO}, 176 .show = presence_read_file, 177 }; 178 179 static ssize_t test_write_file(struct pci_slot *pci_slot, const char *buf, 180 size_t count) 181 { 182 struct hotplug_slot *slot = pci_slot->hotplug; 183 unsigned long ltest; 184 u32 test; 185 int retval = 0; 186 187 ltest = simple_strtoul(buf, NULL, 10); 188 test = (u32)(ltest & 0xffffffff); 189 dbg("test = %d\n", test); 190 191 if (slot->ops->hardware_test) 192 retval = slot->ops->hardware_test(slot, test); 193 194 if (retval) 195 return retval; 196 return count; 197 } 198 199 static struct pci_slot_attribute hotplug_slot_attr_test = { 200 .attr = {.name = "test", .mode = S_IFREG | S_IRUGO | S_IWUSR}, 201 .store = test_write_file 202 }; 203 204 static bool has_power_file(struct hotplug_slot *slot) 205 { 206 if ((slot->ops->enable_slot) || 207 (slot->ops->disable_slot) || 208 (slot->ops->get_power_status)) 209 return true; 210 return false; 211 } 212 213 static bool has_attention_file(struct hotplug_slot *slot) 214 { 215 if ((slot->ops->set_attention_status) || 216 (slot->ops->get_attention_status)) 217 return true; 218 return false; 219 } 220 221 static bool has_latch_file(struct hotplug_slot *slot) 222 { 223 if (slot->ops->get_latch_status) 224 return true; 225 return false; 226 } 227 228 static bool has_adapter_file(struct hotplug_slot *slot) 229 { 230 if (slot->ops->get_adapter_status) 231 return true; 232 return false; 233 } 234 235 static bool has_test_file(struct hotplug_slot *slot) 236 { 237 if (slot->ops->hardware_test) 238 return true; 239 return false; 240 } 241 242 static int fs_add_slot(struct hotplug_slot *slot, struct pci_slot *pci_slot) 243 { 244 struct kobject *kobj; 245 int retval = 0; 246 247 /* Create symbolic link to the hotplug driver module */ 248 kobj = kset_find_obj(module_kset, slot->mod_name); 249 if (kobj) { 250 retval = sysfs_create_link(&pci_slot->kobj, kobj, "module"); 251 if (retval) 252 dev_err(&pci_slot->bus->dev, 253 "Error creating sysfs link (%d)\n", retval); 254 kobject_put(kobj); 255 } 256 257 if (has_power_file(slot)) { 258 retval = sysfs_create_file(&pci_slot->kobj, 259 &hotplug_slot_attr_power.attr); 260 if (retval) 261 goto exit_power; 262 } 263 264 if (has_attention_file(slot)) { 265 retval = sysfs_create_file(&pci_slot->kobj, 266 &hotplug_slot_attr_attention.attr); 267 if (retval) 268 goto exit_attention; 269 } 270 271 if (has_latch_file(slot)) { 272 retval = sysfs_create_file(&pci_slot->kobj, 273 &hotplug_slot_attr_latch.attr); 274 if (retval) 275 goto exit_latch; 276 } 277 278 if (has_adapter_file(slot)) { 279 retval = sysfs_create_file(&pci_slot->kobj, 280 &hotplug_slot_attr_presence.attr); 281 if (retval) 282 goto exit_adapter; 283 } 284 285 if (has_test_file(slot)) { 286 retval = sysfs_create_file(&pci_slot->kobj, 287 &hotplug_slot_attr_test.attr); 288 if (retval) 289 goto exit_test; 290 } 291 292 goto exit; 293 294 exit_test: 295 if (has_adapter_file(slot)) 296 sysfs_remove_file(&pci_slot->kobj, 297 &hotplug_slot_attr_presence.attr); 298 exit_adapter: 299 if (has_latch_file(slot)) 300 sysfs_remove_file(&pci_slot->kobj, &hotplug_slot_attr_latch.attr); 301 exit_latch: 302 if (has_attention_file(slot)) 303 sysfs_remove_file(&pci_slot->kobj, 304 &hotplug_slot_attr_attention.attr); 305 exit_attention: 306 if (has_power_file(slot)) 307 sysfs_remove_file(&pci_slot->kobj, &hotplug_slot_attr_power.attr); 308 exit_power: 309 sysfs_remove_link(&pci_slot->kobj, "module"); 310 exit: 311 return retval; 312 } 313 314 static void fs_remove_slot(struct hotplug_slot *slot, struct pci_slot *pci_slot) 315 { 316 if (has_power_file(slot)) 317 sysfs_remove_file(&pci_slot->kobj, &hotplug_slot_attr_power.attr); 318 319 if (has_attention_file(slot)) 320 sysfs_remove_file(&pci_slot->kobj, 321 &hotplug_slot_attr_attention.attr); 322 323 if (has_latch_file(slot)) 324 sysfs_remove_file(&pci_slot->kobj, &hotplug_slot_attr_latch.attr); 325 326 if (has_adapter_file(slot)) 327 sysfs_remove_file(&pci_slot->kobj, 328 &hotplug_slot_attr_presence.attr); 329 330 if (has_test_file(slot)) 331 sysfs_remove_file(&pci_slot->kobj, &hotplug_slot_attr_test.attr); 332 333 sysfs_remove_link(&pci_slot->kobj, "module"); 334 } 335 336 /** 337 * __pci_hp_register - register a hotplug_slot with the PCI hotplug subsystem 338 * @slot: pointer to the &struct hotplug_slot to register 339 * @bus: bus this slot is on 340 * @devnr: device number 341 * @name: name registered with kobject core 342 * @owner: caller module owner 343 * @mod_name: caller module name 344 * 345 * Prepares a hotplug slot for in-kernel use and immediately publishes it to 346 * user space in one go. Drivers may alternatively carry out the two steps 347 * separately by invoking pci_hp_initialize() and pci_hp_add(). 348 * 349 * Returns 0 if successful, anything else for an error. 350 */ 351 int __pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, 352 int devnr, const char *name, 353 struct module *owner, const char *mod_name) 354 { 355 int result; 356 357 result = __pci_hp_initialize(slot, bus, devnr, name, owner, mod_name); 358 if (result) 359 return result; 360 361 result = pci_hp_add(slot); 362 if (result) 363 pci_hp_destroy(slot); 364 365 return result; 366 } 367 EXPORT_SYMBOL_GPL(__pci_hp_register); 368 369 /** 370 * __pci_hp_initialize - prepare hotplug slot for in-kernel use 371 * @slot: pointer to the &struct hotplug_slot to initialize 372 * @bus: bus this slot is on 373 * @devnr: slot number 374 * @name: name registered with kobject core 375 * @owner: caller module owner 376 * @mod_name: caller module name 377 * 378 * Allocate and fill in a PCI slot for use by a hotplug driver. Once this has 379 * been called, the driver may invoke hotplug_slot_name() to get the slot's 380 * unique name. The driver must be prepared to handle a ->reset_slot callback 381 * from this point on. 382 * 383 * Returns 0 on success or a negative int on error. 384 */ 385 int __pci_hp_initialize(struct hotplug_slot *slot, struct pci_bus *bus, 386 int devnr, const char *name, struct module *owner, 387 const char *mod_name) 388 { 389 struct pci_slot *pci_slot; 390 391 if (slot == NULL) 392 return -ENODEV; 393 if (slot->ops == NULL) 394 return -EINVAL; 395 396 slot->owner = owner; 397 slot->mod_name = mod_name; 398 399 /* 400 * No problems if we call this interface from both ACPI_PCI_SLOT 401 * driver and call it here again. If we've already created the 402 * pci_slot, the interface will simply bump the refcount. 403 */ 404 pci_slot = pci_create_slot(bus, devnr, name, slot); 405 if (IS_ERR(pci_slot)) 406 return PTR_ERR(pci_slot); 407 408 slot->pci_slot = pci_slot; 409 pci_slot->hotplug = slot; 410 return 0; 411 } 412 EXPORT_SYMBOL_GPL(__pci_hp_initialize); 413 414 /** 415 * pci_hp_add - publish hotplug slot to user space 416 * @slot: pointer to the &struct hotplug_slot to publish 417 * 418 * Make a hotplug slot's sysfs interface available and inform user space of its 419 * addition by sending a uevent. The hotplug driver must be prepared to handle 420 * all &struct hotplug_slot_ops callbacks from this point on. 421 * 422 * Returns 0 on success or a negative int on error. 423 */ 424 int pci_hp_add(struct hotplug_slot *slot) 425 { 426 struct pci_slot *pci_slot; 427 int result; 428 429 if (WARN_ON(!slot)) 430 return -EINVAL; 431 432 pci_slot = slot->pci_slot; 433 434 result = fs_add_slot(slot, pci_slot); 435 if (result) 436 return result; 437 438 kobject_uevent(&pci_slot->kobj, KOBJ_ADD); 439 return 0; 440 } 441 EXPORT_SYMBOL_GPL(pci_hp_add); 442 443 /** 444 * pci_hp_deregister - deregister a hotplug_slot with the PCI hotplug subsystem 445 * @slot: pointer to the &struct hotplug_slot to deregister 446 * 447 * The @slot must have been registered with the pci hotplug subsystem 448 * previously with a call to pci_hp_register(). 449 */ 450 void pci_hp_deregister(struct hotplug_slot *slot) 451 { 452 pci_hp_del(slot); 453 pci_hp_destroy(slot); 454 } 455 EXPORT_SYMBOL_GPL(pci_hp_deregister); 456 457 /** 458 * pci_hp_del - unpublish hotplug slot from user space 459 * @slot: pointer to the &struct hotplug_slot to unpublish 460 * 461 * Remove a hotplug slot's sysfs interface. 462 */ 463 void pci_hp_del(struct hotplug_slot *slot) 464 { 465 if (WARN_ON(!slot)) 466 return; 467 468 fs_remove_slot(slot, slot->pci_slot); 469 } 470 EXPORT_SYMBOL_GPL(pci_hp_del); 471 472 /** 473 * pci_hp_destroy - remove hotplug slot from in-kernel use 474 * @slot: pointer to the &struct hotplug_slot to destroy 475 * 476 * Destroy a PCI slot used by a hotplug driver. Once this has been called, 477 * the driver may no longer invoke hotplug_slot_name() to get the slot's 478 * unique name. The driver no longer needs to handle a ->reset_slot callback 479 * from this point on. 480 */ 481 void pci_hp_destroy(struct hotplug_slot *slot) 482 { 483 struct pci_slot *pci_slot = slot->pci_slot; 484 485 slot->pci_slot = NULL; 486 pci_slot->hotplug = NULL; 487 pci_destroy_slot(pci_slot); 488 } 489 EXPORT_SYMBOL_GPL(pci_hp_destroy); 490 491 static DECLARE_WAIT_QUEUE_HEAD(pci_hp_link_change_wq); 492 493 /** 494 * pci_hp_ignore_link_change - begin code section causing spurious link changes 495 * @pdev: PCI hotplug bridge 496 * 497 * Mark the beginning of a code section causing spurious link changes on the 498 * Secondary Bus of @pdev, e.g. as a side effect of a Secondary Bus Reset, 499 * D3cold transition, firmware update or FPGA reconfiguration. 500 * 501 * Hotplug drivers can thus check whether such a code section is executing 502 * concurrently, await it with pci_hp_spurious_link_change() and ignore the 503 * resulting link change events. 504 * 505 * Must be paired with pci_hp_unignore_link_change(). May be called both 506 * from the PCI core and from Endpoint drivers. May be called for bridges 507 * which are not hotplug-capable, in which case it has no effect because 508 * no hotplug driver is bound to the bridge. 509 */ 510 void pci_hp_ignore_link_change(struct pci_dev *pdev) 511 { 512 set_bit(PCI_LINK_CHANGING, &pdev->priv_flags); 513 smp_mb__after_atomic(); /* pairs with implied barrier of wait_event() */ 514 } 515 516 /** 517 * pci_hp_unignore_link_change - end code section causing spurious link changes 518 * @pdev: PCI hotplug bridge 519 * 520 * Mark the end of a code section causing spurious link changes on the 521 * Secondary Bus of @pdev. Must be paired with pci_hp_ignore_link_change(). 522 */ 523 void pci_hp_unignore_link_change(struct pci_dev *pdev) 524 { 525 set_bit(PCI_LINK_CHANGED, &pdev->priv_flags); 526 mb(); /* ensure pci_hp_spurious_link_change() sees either bit set */ 527 clear_bit(PCI_LINK_CHANGING, &pdev->priv_flags); 528 wake_up_all(&pci_hp_link_change_wq); 529 } 530 531 /** 532 * pci_hp_spurious_link_change - check for spurious link changes 533 * @pdev: PCI hotplug bridge 534 * 535 * Check whether a code section is executing concurrently which is causing 536 * spurious link changes on the Secondary Bus of @pdev. Await the end of the 537 * code section if so. 538 * 539 * May be called by hotplug drivers to check whether a link change is spurious 540 * and can be ignored. 541 * 542 * Because a genuine link change may have occurred in-between a spurious link 543 * change and the invocation of this function, hotplug drivers should perform 544 * sanity checks such as retrieving the current link state and bringing down 545 * the slot if the link is down. 546 * 547 * Return: %true if such a code section has been executing concurrently, 548 * otherwise %false. Also return %true if such a code section has not been 549 * executing concurrently, but at least once since the last invocation of this 550 * function. 551 */ 552 bool pci_hp_spurious_link_change(struct pci_dev *pdev) 553 { 554 wait_event(pci_hp_link_change_wq, 555 !test_bit(PCI_LINK_CHANGING, &pdev->priv_flags)); 556 557 return test_and_clear_bit(PCI_LINK_CHANGED, &pdev->priv_flags); 558 } 559 560 static int __init pci_hotplug_init(void) 561 { 562 int result; 563 564 result = cpci_hotplug_init(debug); 565 if (result) { 566 err("cpci_hotplug_init with error %d\n", result); 567 return result; 568 } 569 570 return result; 571 } 572 device_initcall(pci_hotplug_init); 573 574 /* 575 * not really modular, but the easiest way to keep compat with existing 576 * bootargs behaviour is to continue using module_param here. 577 */ 578 module_param(debug, bool, 0644); 579 MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); 580