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> /* try_module_get & module_put */ 18 #include <linux/moduleparam.h> 19 #include <linux/kernel.h> 20 #include <linux/types.h> 21 #include <linux/list.h> 22 #include <linux/kobject.h> 23 #include <linux/sysfs.h> 24 #include <linux/pagemap.h> 25 #include <linux/init.h> 26 #include <linux/mount.h> 27 #include <linux/namei.h> 28 #include <linux/mutex.h> 29 #include <linux/pci.h> 30 #include <linux/pci_hotplug.h> 31 #include <linux/uaccess.h> 32 #include "../pci.h" 33 #include "cpci_hotplug.h" 34 35 #define MY_NAME "pci_hotplug" 36 37 #define dbg(fmt, arg...) do { if (debug) printk(KERN_DEBUG "%s: %s: " fmt, MY_NAME, __func__, ## arg); } while (0) 38 #define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME, ## arg) 39 #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME, ## arg) 40 #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME, ## arg) 41 42 /* local variables */ 43 static bool debug; 44 45 static LIST_HEAD(pci_hotplug_slot_list); 46 static DEFINE_MUTEX(pci_hp_mutex); 47 48 /* Weee, fun with macros... */ 49 #define GET_STATUS(name, type) \ 50 static int get_##name(struct hotplug_slot *slot, type *value) \ 51 { \ 52 struct hotplug_slot_ops *ops = slot->ops; \ 53 int retval = 0; \ 54 if (!try_module_get(ops->owner)) \ 55 return -ENODEV; \ 56 if (ops->get_##name) \ 57 retval = ops->get_##name(slot, value); \ 58 else \ 59 *value = slot->info->name; \ 60 module_put(ops->owner); \ 61 return retval; \ 62 } 63 64 GET_STATUS(power_status, u8) 65 GET_STATUS(attention_status, u8) 66 GET_STATUS(latch_status, u8) 67 GET_STATUS(adapter_status, u8) 68 69 static ssize_t power_read_file(struct pci_slot *pci_slot, char *buf) 70 { 71 int retval; 72 u8 value; 73 74 retval = get_power_status(pci_slot->hotplug, &value); 75 if (retval) 76 return retval; 77 78 return sprintf(buf, "%d\n", value); 79 } 80 81 static ssize_t power_write_file(struct pci_slot *pci_slot, const char *buf, 82 size_t count) 83 { 84 struct hotplug_slot *slot = pci_slot->hotplug; 85 unsigned long lpower; 86 u8 power; 87 int retval = 0; 88 89 lpower = simple_strtoul(buf, NULL, 10); 90 power = (u8)(lpower & 0xff); 91 dbg("power = %d\n", power); 92 93 if (!try_module_get(slot->ops->owner)) { 94 retval = -ENODEV; 95 goto exit; 96 } 97 switch (power) { 98 case 0: 99 if (slot->ops->disable_slot) 100 retval = slot->ops->disable_slot(slot); 101 break; 102 103 case 1: 104 if (slot->ops->enable_slot) 105 retval = slot->ops->enable_slot(slot); 106 break; 107 108 default: 109 err("Illegal value specified for power\n"); 110 retval = -EINVAL; 111 } 112 module_put(slot->ops->owner); 113 114 exit: 115 if (retval) 116 return retval; 117 return count; 118 } 119 120 static struct pci_slot_attribute hotplug_slot_attr_power = { 121 .attr = {.name = "power", .mode = S_IFREG | S_IRUGO | S_IWUSR}, 122 .show = power_read_file, 123 .store = power_write_file 124 }; 125 126 static ssize_t attention_read_file(struct pci_slot *pci_slot, char *buf) 127 { 128 int retval; 129 u8 value; 130 131 retval = get_attention_status(pci_slot->hotplug, &value); 132 if (retval) 133 return retval; 134 135 return sprintf(buf, "%d\n", value); 136 } 137 138 static ssize_t attention_write_file(struct pci_slot *pci_slot, const char *buf, 139 size_t count) 140 { 141 struct hotplug_slot_ops *ops = pci_slot->hotplug->ops; 142 unsigned long lattention; 143 u8 attention; 144 int retval = 0; 145 146 lattention = simple_strtoul(buf, NULL, 10); 147 attention = (u8)(lattention & 0xff); 148 dbg(" - attention = %d\n", attention); 149 150 if (!try_module_get(ops->owner)) { 151 retval = -ENODEV; 152 goto exit; 153 } 154 if (ops->set_attention_status) 155 retval = ops->set_attention_status(pci_slot->hotplug, attention); 156 module_put(ops->owner); 157 158 exit: 159 if (retval) 160 return retval; 161 return count; 162 } 163 164 static struct pci_slot_attribute hotplug_slot_attr_attention = { 165 .attr = {.name = "attention", .mode = S_IFREG | S_IRUGO | S_IWUSR}, 166 .show = attention_read_file, 167 .store = attention_write_file 168 }; 169 170 static ssize_t latch_read_file(struct pci_slot *pci_slot, char *buf) 171 { 172 int retval; 173 u8 value; 174 175 retval = get_latch_status(pci_slot->hotplug, &value); 176 if (retval) 177 return retval; 178 179 return sprintf(buf, "%d\n", value); 180 } 181 182 static struct pci_slot_attribute hotplug_slot_attr_latch = { 183 .attr = {.name = "latch", .mode = S_IFREG | S_IRUGO}, 184 .show = latch_read_file, 185 }; 186 187 static ssize_t presence_read_file(struct pci_slot *pci_slot, char *buf) 188 { 189 int retval; 190 u8 value; 191 192 retval = get_adapter_status(pci_slot->hotplug, &value); 193 if (retval) 194 return retval; 195 196 return sprintf(buf, "%d\n", value); 197 } 198 199 static struct pci_slot_attribute hotplug_slot_attr_presence = { 200 .attr = {.name = "adapter", .mode = S_IFREG | S_IRUGO}, 201 .show = presence_read_file, 202 }; 203 204 static ssize_t test_write_file(struct pci_slot *pci_slot, const char *buf, 205 size_t count) 206 { 207 struct hotplug_slot *slot = pci_slot->hotplug; 208 unsigned long ltest; 209 u32 test; 210 int retval = 0; 211 212 ltest = simple_strtoul(buf, NULL, 10); 213 test = (u32)(ltest & 0xffffffff); 214 dbg("test = %d\n", test); 215 216 if (!try_module_get(slot->ops->owner)) { 217 retval = -ENODEV; 218 goto exit; 219 } 220 if (slot->ops->hardware_test) 221 retval = slot->ops->hardware_test(slot, test); 222 module_put(slot->ops->owner); 223 224 exit: 225 if (retval) 226 return retval; 227 return count; 228 } 229 230 static struct pci_slot_attribute hotplug_slot_attr_test = { 231 .attr = {.name = "test", .mode = S_IFREG | S_IRUGO | S_IWUSR}, 232 .store = test_write_file 233 }; 234 235 static bool has_power_file(struct pci_slot *pci_slot) 236 { 237 struct hotplug_slot *slot = pci_slot->hotplug; 238 239 if ((!slot) || (!slot->ops)) 240 return false; 241 if ((slot->ops->enable_slot) || 242 (slot->ops->disable_slot) || 243 (slot->ops->get_power_status)) 244 return true; 245 return false; 246 } 247 248 static bool has_attention_file(struct pci_slot *pci_slot) 249 { 250 struct hotplug_slot *slot = pci_slot->hotplug; 251 252 if ((!slot) || (!slot->ops)) 253 return false; 254 if ((slot->ops->set_attention_status) || 255 (slot->ops->get_attention_status)) 256 return true; 257 return false; 258 } 259 260 static bool has_latch_file(struct pci_slot *pci_slot) 261 { 262 struct hotplug_slot *slot = pci_slot->hotplug; 263 264 if ((!slot) || (!slot->ops)) 265 return false; 266 if (slot->ops->get_latch_status) 267 return true; 268 return false; 269 } 270 271 static bool has_adapter_file(struct pci_slot *pci_slot) 272 { 273 struct hotplug_slot *slot = pci_slot->hotplug; 274 275 if ((!slot) || (!slot->ops)) 276 return false; 277 if (slot->ops->get_adapter_status) 278 return true; 279 return false; 280 } 281 282 static bool has_test_file(struct pci_slot *pci_slot) 283 { 284 struct hotplug_slot *slot = pci_slot->hotplug; 285 286 if ((!slot) || (!slot->ops)) 287 return false; 288 if (slot->ops->hardware_test) 289 return true; 290 return false; 291 } 292 293 static int fs_add_slot(struct pci_slot *pci_slot) 294 { 295 int retval = 0; 296 297 /* Create symbolic link to the hotplug driver module */ 298 pci_hp_create_module_link(pci_slot); 299 300 if (has_power_file(pci_slot)) { 301 retval = sysfs_create_file(&pci_slot->kobj, 302 &hotplug_slot_attr_power.attr); 303 if (retval) 304 goto exit_power; 305 } 306 307 if (has_attention_file(pci_slot)) { 308 retval = sysfs_create_file(&pci_slot->kobj, 309 &hotplug_slot_attr_attention.attr); 310 if (retval) 311 goto exit_attention; 312 } 313 314 if (has_latch_file(pci_slot)) { 315 retval = sysfs_create_file(&pci_slot->kobj, 316 &hotplug_slot_attr_latch.attr); 317 if (retval) 318 goto exit_latch; 319 } 320 321 if (has_adapter_file(pci_slot)) { 322 retval = sysfs_create_file(&pci_slot->kobj, 323 &hotplug_slot_attr_presence.attr); 324 if (retval) 325 goto exit_adapter; 326 } 327 328 if (has_test_file(pci_slot)) { 329 retval = sysfs_create_file(&pci_slot->kobj, 330 &hotplug_slot_attr_test.attr); 331 if (retval) 332 goto exit_test; 333 } 334 335 goto exit; 336 337 exit_test: 338 if (has_adapter_file(pci_slot)) 339 sysfs_remove_file(&pci_slot->kobj, 340 &hotplug_slot_attr_presence.attr); 341 exit_adapter: 342 if (has_latch_file(pci_slot)) 343 sysfs_remove_file(&pci_slot->kobj, &hotplug_slot_attr_latch.attr); 344 exit_latch: 345 if (has_attention_file(pci_slot)) 346 sysfs_remove_file(&pci_slot->kobj, 347 &hotplug_slot_attr_attention.attr); 348 exit_attention: 349 if (has_power_file(pci_slot)) 350 sysfs_remove_file(&pci_slot->kobj, &hotplug_slot_attr_power.attr); 351 exit_power: 352 pci_hp_remove_module_link(pci_slot); 353 exit: 354 return retval; 355 } 356 357 static void fs_remove_slot(struct pci_slot *pci_slot) 358 { 359 if (has_power_file(pci_slot)) 360 sysfs_remove_file(&pci_slot->kobj, &hotplug_slot_attr_power.attr); 361 362 if (has_attention_file(pci_slot)) 363 sysfs_remove_file(&pci_slot->kobj, 364 &hotplug_slot_attr_attention.attr); 365 366 if (has_latch_file(pci_slot)) 367 sysfs_remove_file(&pci_slot->kobj, &hotplug_slot_attr_latch.attr); 368 369 if (has_adapter_file(pci_slot)) 370 sysfs_remove_file(&pci_slot->kobj, 371 &hotplug_slot_attr_presence.attr); 372 373 if (has_test_file(pci_slot)) 374 sysfs_remove_file(&pci_slot->kobj, &hotplug_slot_attr_test.attr); 375 376 pci_hp_remove_module_link(pci_slot); 377 } 378 379 static struct hotplug_slot *get_slot_from_name(const char *name) 380 { 381 struct hotplug_slot *slot; 382 383 list_for_each_entry(slot, &pci_hotplug_slot_list, slot_list) { 384 if (strcmp(hotplug_slot_name(slot), name) == 0) 385 return slot; 386 } 387 return NULL; 388 } 389 390 /** 391 * __pci_hp_register - register a hotplug_slot with the PCI hotplug subsystem 392 * @bus: bus this slot is on 393 * @slot: pointer to the &struct hotplug_slot to register 394 * @devnr: device number 395 * @name: name registered with kobject core 396 * @owner: caller module owner 397 * @mod_name: caller module name 398 * 399 * Prepares a hotplug slot for in-kernel use and immediately publishes it to 400 * user space in one go. Drivers may alternatively carry out the two steps 401 * separately by invoking pci_hp_initialize() and pci_hp_add(). 402 * 403 * Returns 0 if successful, anything else for an error. 404 */ 405 int __pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, 406 int devnr, const char *name, 407 struct module *owner, const char *mod_name) 408 { 409 int result; 410 411 result = __pci_hp_initialize(slot, bus, devnr, name, owner, mod_name); 412 if (result) 413 return result; 414 415 result = pci_hp_add(slot); 416 if (result) 417 pci_hp_destroy(slot); 418 419 return result; 420 } 421 EXPORT_SYMBOL_GPL(__pci_hp_register); 422 423 /** 424 * __pci_hp_initialize - prepare hotplug slot for in-kernel use 425 * @slot: pointer to the &struct hotplug_slot to initialize 426 * @bus: bus this slot is on 427 * @devnr: slot number 428 * @name: name registered with kobject core 429 * @owner: caller module owner 430 * @mod_name: caller module name 431 * 432 * Allocate and fill in a PCI slot for use by a hotplug driver. Once this has 433 * been called, the driver may invoke hotplug_slot_name() to get the slot's 434 * unique name. The driver must be prepared to handle a ->reset_slot callback 435 * from this point on. 436 * 437 * Returns 0 on success or a negative int on error. 438 */ 439 int __pci_hp_initialize(struct hotplug_slot *slot, struct pci_bus *bus, 440 int devnr, const char *name, struct module *owner, 441 const char *mod_name) 442 { 443 struct pci_slot *pci_slot; 444 445 if (slot == NULL) 446 return -ENODEV; 447 if ((slot->info == NULL) || (slot->ops == NULL)) 448 return -EINVAL; 449 450 slot->ops->owner = owner; 451 slot->ops->mod_name = mod_name; 452 453 /* 454 * No problems if we call this interface from both ACPI_PCI_SLOT 455 * driver and call it here again. If we've already created the 456 * pci_slot, the interface will simply bump the refcount. 457 */ 458 pci_slot = pci_create_slot(bus, devnr, name, slot); 459 if (IS_ERR(pci_slot)) 460 return PTR_ERR(pci_slot); 461 462 slot->pci_slot = pci_slot; 463 pci_slot->hotplug = slot; 464 return 0; 465 } 466 EXPORT_SYMBOL_GPL(__pci_hp_initialize); 467 468 /** 469 * pci_hp_add - publish hotplug slot to user space 470 * @slot: pointer to the &struct hotplug_slot to publish 471 * 472 * Make a hotplug slot's sysfs interface available and inform user space of its 473 * addition by sending a uevent. The hotplug driver must be prepared to handle 474 * all &struct hotplug_slot_ops callbacks from this point on. 475 * 476 * Returns 0 on success or a negative int on error. 477 */ 478 int pci_hp_add(struct hotplug_slot *slot) 479 { 480 struct pci_slot *pci_slot = slot->pci_slot; 481 int result; 482 483 result = fs_add_slot(pci_slot); 484 if (result) 485 return result; 486 487 kobject_uevent(&pci_slot->kobj, KOBJ_ADD); 488 mutex_lock(&pci_hp_mutex); 489 list_add(&slot->slot_list, &pci_hotplug_slot_list); 490 mutex_unlock(&pci_hp_mutex); 491 dbg("Added slot %s to the list\n", hotplug_slot_name(slot)); 492 return 0; 493 } 494 EXPORT_SYMBOL_GPL(pci_hp_add); 495 496 /** 497 * pci_hp_deregister - deregister a hotplug_slot with the PCI hotplug subsystem 498 * @slot: pointer to the &struct hotplug_slot to deregister 499 * 500 * The @slot must have been registered with the pci hotplug subsystem 501 * previously with a call to pci_hp_register(). 502 * 503 * Returns 0 if successful, anything else for an error. 504 */ 505 void pci_hp_deregister(struct hotplug_slot *slot) 506 { 507 pci_hp_del(slot); 508 pci_hp_destroy(slot); 509 } 510 EXPORT_SYMBOL_GPL(pci_hp_deregister); 511 512 /** 513 * pci_hp_del - unpublish hotplug slot from user space 514 * @slot: pointer to the &struct hotplug_slot to unpublish 515 * 516 * Remove a hotplug slot's sysfs interface. 517 * 518 * Returns 0 on success or a negative int on error. 519 */ 520 void pci_hp_del(struct hotplug_slot *slot) 521 { 522 struct hotplug_slot *temp; 523 524 if (WARN_ON(!slot)) 525 return; 526 527 mutex_lock(&pci_hp_mutex); 528 temp = get_slot_from_name(hotplug_slot_name(slot)); 529 if (WARN_ON(temp != slot)) { 530 mutex_unlock(&pci_hp_mutex); 531 return; 532 } 533 534 list_del(&slot->slot_list); 535 mutex_unlock(&pci_hp_mutex); 536 dbg("Removed slot %s from the list\n", hotplug_slot_name(slot)); 537 fs_remove_slot(slot->pci_slot); 538 } 539 EXPORT_SYMBOL_GPL(pci_hp_del); 540 541 /** 542 * pci_hp_destroy - remove hotplug slot from in-kernel use 543 * @slot: pointer to the &struct hotplug_slot to destroy 544 * 545 * Destroy a PCI slot used by a hotplug driver. Once this has been called, 546 * the driver may no longer invoke hotplug_slot_name() to get the slot's 547 * unique name. The driver no longer needs to handle a ->reset_slot callback 548 * from this point on. 549 * 550 * Returns 0 on success or a negative int on error. 551 */ 552 void pci_hp_destroy(struct hotplug_slot *slot) 553 { 554 struct pci_slot *pci_slot = slot->pci_slot; 555 556 slot->pci_slot = NULL; 557 pci_slot->hotplug = NULL; 558 pci_destroy_slot(pci_slot); 559 } 560 EXPORT_SYMBOL_GPL(pci_hp_destroy); 561 562 /** 563 * pci_hp_change_slot_info - changes the slot's information structure in the core 564 * @slot: pointer to the slot whose info has changed 565 * @info: pointer to the info copy into the slot's info structure 566 * 567 * @slot must have been registered with the pci 568 * hotplug subsystem previously with a call to pci_hp_register(). 569 * 570 * Returns 0 if successful, anything else for an error. 571 */ 572 int pci_hp_change_slot_info(struct hotplug_slot *slot, 573 struct hotplug_slot_info *info) 574 { 575 if (!slot || !info) 576 return -ENODEV; 577 578 memcpy(slot->info, info, sizeof(struct hotplug_slot_info)); 579 580 return 0; 581 } 582 EXPORT_SYMBOL_GPL(pci_hp_change_slot_info); 583 584 static int __init pci_hotplug_init(void) 585 { 586 int result; 587 588 result = cpci_hotplug_init(debug); 589 if (result) { 590 err("cpci_hotplug_init with error %d\n", result); 591 return result; 592 } 593 594 return result; 595 } 596 device_initcall(pci_hotplug_init); 597 598 /* 599 * not really modular, but the easiest way to keep compat with existing 600 * bootargs behaviour is to continue using module_param here. 601 */ 602 module_param(debug, bool, 0644); 603 MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); 604