Merge branch 'pci/hotplug'

- Drop shpchp module init/exit logging (Ilpo Järvinen)

- Replace shpchp dbg() with ctrl_dbg() and remove unused dbg(), err(),
  info(), warn() wrappers (Ilpo Järvinen)

- Drop 'shpchp_debug' module parameter in favor of standard dynamic
  debugging (Ilpo Järvinen)

- Drop unused .get_power(), .set_power() function pointers (Guilherme
  Giacomo Simoes)

- Drop superfluous pci_hotplug_slot_list (Lukas Wunner)

- Drop superfluous try_module_get() calls (Lukas Wunner)

- Drop superfluous NULL pointer checks (Lukas Wunner)

- Pass struct hotplug_slot pointers directly to avoid backpointer
  dereferencing in has_*_file() (Lukas Wunner)

- Inline pci_hp_{create,remove}_module_link() to reduce exported symbols
  (Lukas Wunner)

- Disable hotplug interrupts in portdrv only when pciehp is not enabled to
  prevent issuing two hotplug commands too close together (Feng Tang)

- Skip pciehp 'device replaced' check if the device has been removed to
  address a common deadlock when resuming after a device was removed during
  system sleep (Lukas Wunner)

- Don't enable pciehp hotplug interupt when resuming in poll mode (Ilpo
  Järvinen)

* pci/hotplug:
  PCI: pciehp: Don't enable HPIE when resuming in poll mode
  PCI: pciehp: Avoid unnecessary device replacement check
  PCI/portdrv: Only disable pciehp interrupts early when needed
  PCI: hotplug: Inline pci_hp_{create,remove}_module_link()
  PCI: hotplug: Avoid backpointer dereferencing in has_*_file()
  PCI: hotplug: Drop superfluous NULL pointer checks in has_*_file()
  PCI: hotplug: Drop superfluous try_module_get() calls
  PCI: hotplug: Drop superfluous pci_hotplug_slot_list
  PCI: cpcihp: Remove unused .get_power() and .set_power()
  PCI: shpchp: Remove 'shpchp_debug' module parameter
  PCI: shpchp: Remove unused logging wrappers
  PCI: shpchp: Change dbg() -> ctrl_dbg()
  PCI: shpchp: Remove logging from module init/exit functions
This commit is contained in:
Bjorn Helgaas 2025-03-27 13:14:44 -05:00
commit 655ea930fe
12 changed files with 58 additions and 204 deletions

View File

@ -44,8 +44,6 @@ struct cpci_hp_controller_ops {
int (*enable_irq)(void);
int (*disable_irq)(void);
int (*check_irq)(void *dev_id);
u8 (*get_power)(struct slot *slot);
int (*set_power)(struct slot *slot, int value);
};
struct cpci_hp_controller {

View File

@ -71,13 +71,10 @@ static int
enable_slot(struct hotplug_slot *hotplug_slot)
{
struct slot *slot = to_slot(hotplug_slot);
int retval = 0;
dbg("%s - physical_slot = %s", __func__, slot_name(slot));
if (controller->ops->set_power)
retval = controller->ops->set_power(slot, 1);
return retval;
return 0;
}
static int
@ -109,12 +106,6 @@ disable_slot(struct hotplug_slot *hotplug_slot)
}
cpci_led_on(slot);
if (controller->ops->set_power) {
retval = controller->ops->set_power(slot, 0);
if (retval)
goto disable_error;
}
slot->adapter_status = 0;
if (slot->extracting) {
@ -129,11 +120,7 @@ disable_slot(struct hotplug_slot *hotplug_slot)
static u8
cpci_get_power_status(struct slot *slot)
{
u8 power = 1;
if (controller->ops->get_power)
power = controller->ops->get_power(slot);
return power;
return 1;
}
static int

View File

@ -14,18 +14,16 @@
* Scott Murray <scottm@somanetworks.com>
*/
#include <linux/module.h> /* try_module_get & module_put */
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/list.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/pagemap.h>
#include <linux/init.h>
#include <linux/mount.h>
#include <linux/namei.h>
#include <linux/mutex.h>
#include <linux/pci.h>
#include <linux/pci_hotplug.h>
#include <linux/uaccess.h>
@ -42,20 +40,14 @@
/* local variables */
static bool debug;
static LIST_HEAD(pci_hotplug_slot_list);
static DEFINE_MUTEX(pci_hp_mutex);
/* Weee, fun with macros... */
#define GET_STATUS(name, type) \
static int get_##name(struct hotplug_slot *slot, type *value) \
{ \
const struct hotplug_slot_ops *ops = slot->ops; \
int retval = 0; \
if (!try_module_get(slot->owner)) \
return -ENODEV; \
if (ops->get_##name) \
retval = ops->get_##name(slot, value); \
module_put(slot->owner); \
return retval; \
}
@ -88,10 +80,6 @@ static ssize_t power_write_file(struct pci_slot *pci_slot, const char *buf,
power = (u8)(lpower & 0xff);
dbg("power = %d\n", power);
if (!try_module_get(slot->owner)) {
retval = -ENODEV;
goto exit;
}
switch (power) {
case 0:
if (slot->ops->disable_slot)
@ -107,9 +95,7 @@ static ssize_t power_write_file(struct pci_slot *pci_slot, const char *buf,
err("Illegal value specified for power\n");
retval = -EINVAL;
}
module_put(slot->owner);
exit:
if (retval)
return retval;
return count;
@ -146,15 +132,9 @@ static ssize_t attention_write_file(struct pci_slot *pci_slot, const char *buf,
attention = (u8)(lattention & 0xff);
dbg(" - attention = %d\n", attention);
if (!try_module_get(slot->owner)) {
retval = -ENODEV;
goto exit;
}
if (ops->set_attention_status)
retval = ops->set_attention_status(slot, attention);
module_put(slot->owner);
exit:
if (retval)
return retval;
return count;
@ -212,15 +192,9 @@ static ssize_t test_write_file(struct pci_slot *pci_slot, const char *buf,
test = (u32)(ltest & 0xffffffff);
dbg("test = %d\n", test);
if (!try_module_get(slot->owner)) {
retval = -ENODEV;
goto exit;
}
if (slot->ops->hardware_test)
retval = slot->ops->hardware_test(slot, test);
module_put(slot->owner);
exit:
if (retval)
return retval;
return count;
@ -231,12 +205,8 @@ static struct pci_slot_attribute hotplug_slot_attr_test = {
.store = test_write_file
};
static bool has_power_file(struct pci_slot *pci_slot)
static bool has_power_file(struct hotplug_slot *slot)
{
struct hotplug_slot *slot = pci_slot->hotplug;
if ((!slot) || (!slot->ops))
return false;
if ((slot->ops->enable_slot) ||
(slot->ops->disable_slot) ||
(slot->ops->get_power_status))
@ -244,87 +214,79 @@ static bool has_power_file(struct pci_slot *pci_slot)
return false;
}
static bool has_attention_file(struct pci_slot *pci_slot)
static bool has_attention_file(struct hotplug_slot *slot)
{
struct hotplug_slot *slot = pci_slot->hotplug;
if ((!slot) || (!slot->ops))
return false;
if ((slot->ops->set_attention_status) ||
(slot->ops->get_attention_status))
return true;
return false;
}
static bool has_latch_file(struct pci_slot *pci_slot)
static bool has_latch_file(struct hotplug_slot *slot)
{
struct hotplug_slot *slot = pci_slot->hotplug;
if ((!slot) || (!slot->ops))
return false;
if (slot->ops->get_latch_status)
return true;
return false;
}
static bool has_adapter_file(struct pci_slot *pci_slot)
static bool has_adapter_file(struct hotplug_slot *slot)
{
struct hotplug_slot *slot = pci_slot->hotplug;
if ((!slot) || (!slot->ops))
return false;
if (slot->ops->get_adapter_status)
return true;
return false;
}
static bool has_test_file(struct pci_slot *pci_slot)
static bool has_test_file(struct hotplug_slot *slot)
{
struct hotplug_slot *slot = pci_slot->hotplug;
if ((!slot) || (!slot->ops))
return false;
if (slot->ops->hardware_test)
return true;
return false;
}
static int fs_add_slot(struct pci_slot *pci_slot)
static int fs_add_slot(struct hotplug_slot *slot, struct pci_slot *pci_slot)
{
struct kobject *kobj;
int retval = 0;
/* Create symbolic link to the hotplug driver module */
pci_hp_create_module_link(pci_slot);
kobj = kset_find_obj(module_kset, slot->mod_name);
if (kobj) {
retval = sysfs_create_link(&pci_slot->kobj, kobj, "module");
if (retval)
dev_err(&pci_slot->bus->dev,
"Error creating sysfs link (%d)\n", retval);
kobject_put(kobj);
}
if (has_power_file(pci_slot)) {
if (has_power_file(slot)) {
retval = sysfs_create_file(&pci_slot->kobj,
&hotplug_slot_attr_power.attr);
if (retval)
goto exit_power;
}
if (has_attention_file(pci_slot)) {
if (has_attention_file(slot)) {
retval = sysfs_create_file(&pci_slot->kobj,
&hotplug_slot_attr_attention.attr);
if (retval)
goto exit_attention;
}
if (has_latch_file(pci_slot)) {
if (has_latch_file(slot)) {
retval = sysfs_create_file(&pci_slot->kobj,
&hotplug_slot_attr_latch.attr);
if (retval)
goto exit_latch;
}
if (has_adapter_file(pci_slot)) {
if (has_adapter_file(slot)) {
retval = sysfs_create_file(&pci_slot->kobj,
&hotplug_slot_attr_presence.attr);
if (retval)
goto exit_adapter;
}
if (has_test_file(pci_slot)) {
if (has_test_file(slot)) {
retval = sysfs_create_file(&pci_slot->kobj,
&hotplug_slot_attr_test.attr);
if (retval)
@ -334,56 +296,45 @@ static int fs_add_slot(struct pci_slot *pci_slot)
goto exit;
exit_test:
if (has_adapter_file(pci_slot))
if (has_adapter_file(slot))
sysfs_remove_file(&pci_slot->kobj,
&hotplug_slot_attr_presence.attr);
exit_adapter:
if (has_latch_file(pci_slot))
if (has_latch_file(slot))
sysfs_remove_file(&pci_slot->kobj, &hotplug_slot_attr_latch.attr);
exit_latch:
if (has_attention_file(pci_slot))
if (has_attention_file(slot))
sysfs_remove_file(&pci_slot->kobj,
&hotplug_slot_attr_attention.attr);
exit_attention:
if (has_power_file(pci_slot))
if (has_power_file(slot))
sysfs_remove_file(&pci_slot->kobj, &hotplug_slot_attr_power.attr);
exit_power:
pci_hp_remove_module_link(pci_slot);
sysfs_remove_link(&pci_slot->kobj, "module");
exit:
return retval;
}
static void fs_remove_slot(struct pci_slot *pci_slot)
static void fs_remove_slot(struct hotplug_slot *slot, struct pci_slot *pci_slot)
{
if (has_power_file(pci_slot))
if (has_power_file(slot))
sysfs_remove_file(&pci_slot->kobj, &hotplug_slot_attr_power.attr);
if (has_attention_file(pci_slot))
if (has_attention_file(slot))
sysfs_remove_file(&pci_slot->kobj,
&hotplug_slot_attr_attention.attr);
if (has_latch_file(pci_slot))
if (has_latch_file(slot))
sysfs_remove_file(&pci_slot->kobj, &hotplug_slot_attr_latch.attr);
if (has_adapter_file(pci_slot))
if (has_adapter_file(slot))
sysfs_remove_file(&pci_slot->kobj,
&hotplug_slot_attr_presence.attr);
if (has_test_file(pci_slot))
if (has_test_file(slot))
sysfs_remove_file(&pci_slot->kobj, &hotplug_slot_attr_test.attr);
pci_hp_remove_module_link(pci_slot);
}
static struct hotplug_slot *get_slot_from_name(const char *name)
{
struct hotplug_slot *slot;
list_for_each_entry(slot, &pci_hotplug_slot_list, slot_list) {
if (strcmp(hotplug_slot_name(slot), name) == 0)
return slot;
}
return NULL;
sysfs_remove_link(&pci_slot->kobj, "module");
}
/**
@ -476,18 +427,19 @@ EXPORT_SYMBOL_GPL(__pci_hp_initialize);
*/
int pci_hp_add(struct hotplug_slot *slot)
{
struct pci_slot *pci_slot = slot->pci_slot;
struct pci_slot *pci_slot;
int result;
result = fs_add_slot(pci_slot);
if (WARN_ON(!slot))
return -EINVAL;
pci_slot = slot->pci_slot;
result = fs_add_slot(slot, pci_slot);
if (result)
return result;
kobject_uevent(&pci_slot->kobj, KOBJ_ADD);
mutex_lock(&pci_hp_mutex);
list_add(&slot->slot_list, &pci_hotplug_slot_list);
mutex_unlock(&pci_hp_mutex);
dbg("Added slot %s to the list\n", hotplug_slot_name(slot));
return 0;
}
EXPORT_SYMBOL_GPL(pci_hp_add);
@ -514,22 +466,10 @@ EXPORT_SYMBOL_GPL(pci_hp_deregister);
*/
void pci_hp_del(struct hotplug_slot *slot)
{
struct hotplug_slot *temp;
if (WARN_ON(!slot))
return;
mutex_lock(&pci_hp_mutex);
temp = get_slot_from_name(hotplug_slot_name(slot));
if (WARN_ON(temp != slot)) {
mutex_unlock(&pci_hp_mutex);
return;
}
list_del(&slot->slot_list);
mutex_unlock(&pci_hp_mutex);
dbg("Removed slot %s from the list\n", hotplug_slot_name(slot));
fs_remove_slot(slot->pci_slot);
fs_remove_slot(slot, slot->pci_slot);
}
EXPORT_SYMBOL_GPL(pci_hp_del);

View File

@ -286,9 +286,12 @@ static int pciehp_suspend(struct pcie_device *dev)
static bool pciehp_device_replaced(struct controller *ctrl)
{
struct pci_dev *pdev __free(pci_dev_put);
struct pci_dev *pdev __free(pci_dev_put) = NULL;
u32 reg;
if (pci_dev_is_disconnected(ctrl->pcie->port))
return false;
pdev = pci_get_slot(ctrl->pcie->port->subordinate, PCI_DEVFN(0, 0));
if (!pdev)
return true;

View File

@ -843,7 +843,9 @@ void pcie_enable_interrupt(struct controller *ctrl)
{
u16 mask;
mask = PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_DLLSCE;
mask = PCI_EXP_SLTCTL_DLLSCE;
if (!pciehp_poll_mode)
mask |= PCI_EXP_SLTCTL_HPIE;
pcie_write_cmd(ctrl, mask, mask);
}

View File

@ -33,24 +33,8 @@ extern bool shpchp_poll_mode;
extern int shpchp_poll_time;
extern bool shpchp_debug;
#define dbg(format, arg...) \
do { \
if (shpchp_debug) \
printk(KERN_DEBUG "%s: " format, MY_NAME, ## arg); \
} while (0)
#define err(format, arg...) \
printk(KERN_ERR "%s: " format, MY_NAME, ## arg)
#define info(format, arg...) \
printk(KERN_INFO "%s: " format, MY_NAME, ## arg)
#define warn(format, arg...) \
printk(KERN_WARNING "%s: " format, MY_NAME, ## arg)
#define ctrl_dbg(ctrl, format, arg...) \
do { \
if (shpchp_debug) \
pci_printk(KERN_DEBUG, ctrl->pci_dev, \
format, ## arg); \
} while (0)
pci_dbg(ctrl->pci_dev, format, ## arg)
#define ctrl_err(ctrl, format, arg...) \
pci_err(ctrl->pci_dev, format, ## arg)
#define ctrl_info(ctrl, format, arg...) \

View File

@ -22,7 +22,6 @@
#include "shpchp.h"
/* Global variables */
bool shpchp_debug;
bool shpchp_poll_mode;
int shpchp_poll_time;
@ -33,10 +32,8 @@ int shpchp_poll_time;
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
module_param(shpchp_debug, bool, 0644);
module_param(shpchp_poll_mode, bool, 0644);
module_param(shpchp_poll_time, int, 0644);
MODULE_PARM_DESC(shpchp_debug, "Debugging mode enabled or not");
MODULE_PARM_DESC(shpchp_poll_mode, "Using polling mechanism for hot-plug events or not");
MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds");
@ -324,20 +321,12 @@ static struct pci_driver shpc_driver = {
static int __init shpcd_init(void)
{
int retval;
retval = pci_register_driver(&shpc_driver);
dbg("%s: pci_register_driver = %d\n", __func__, retval);
info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
return retval;
return pci_register_driver(&shpc_driver);
}
static void __exit shpcd_cleanup(void)
{
dbg("unload_shpchpd()\n");
pci_unregister_driver(&shpc_driver);
info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
}
module_init(shpcd_init);

View File

@ -675,7 +675,7 @@ static int shpc_get_cur_bus_speed(struct controller *ctrl)
out:
bus->cur_bus_speed = bus_speed;
dbg("Current bus speed = %d\n", bus_speed);
ctrl_dbg(ctrl, "Current bus speed = %d\n", bus_speed);
return retval;
}

View File

@ -228,10 +228,12 @@ static int get_port_device_capability(struct pci_dev *dev)
/*
* Disable hot-plug interrupts in case they have been enabled
* by the BIOS and the hot-plug service driver is not loaded.
* by the BIOS and the hot-plug service driver won't be loaded
* to handle them.
*/
pcie_capability_clear_word(dev, PCI_EXP_SLTCTL,
PCI_EXP_SLTCTL_CCIE | PCI_EXP_SLTCTL_HPIE);
if (!IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE))
pcie_capability_clear_word(dev, PCI_EXP_SLTCTL,
PCI_EXP_SLTCTL_CCIE | PCI_EXP_SLTCTL_HPIE);
}
#ifdef CONFIG_PCIEAER

View File

@ -7,7 +7,6 @@
#include <linux/kobject.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/err.h>
#include "pci.h"
@ -325,49 +324,6 @@ void pci_destroy_slot(struct pci_slot *slot)
}
EXPORT_SYMBOL_GPL(pci_destroy_slot);
#if defined(CONFIG_HOTPLUG_PCI) || defined(CONFIG_HOTPLUG_PCI_MODULE)
#include <linux/pci_hotplug.h>
/**
* pci_hp_create_module_link - create symbolic link to hotplug driver module
* @pci_slot: struct pci_slot
*
* Helper function for pci_hotplug_core.c to create symbolic link to
* the hotplug driver module.
*/
void pci_hp_create_module_link(struct pci_slot *pci_slot)
{
struct hotplug_slot *slot = pci_slot->hotplug;
struct kobject *kobj = NULL;
int ret;
if (!slot || !slot->ops)
return;
kobj = kset_find_obj(module_kset, slot->mod_name);
if (!kobj)
return;
ret = sysfs_create_link(&pci_slot->kobj, kobj, "module");
if (ret)
dev_err(&pci_slot->bus->dev, "Error creating sysfs link (%d)\n",
ret);
kobject_put(kobj);
}
EXPORT_SYMBOL_GPL(pci_hp_create_module_link);
/**
* pci_hp_remove_module_link - remove symbolic link to the hotplug driver
* module.
* @pci_slot: struct pci_slot
*
* Helper function for pci_hotplug_core.c to remove symbolic link to
* the hotplug driver module.
*/
void pci_hp_remove_module_link(struct pci_slot *pci_slot)
{
sysfs_remove_link(&pci_slot->kobj, "module");
}
EXPORT_SYMBOL_GPL(pci_hp_remove_module_link);
#endif
static int pci_slot_init(void)
{
struct kset *pci_bus_kset;

View File

@ -2449,11 +2449,6 @@ static inline resource_size_t pci_iov_resource_size(struct pci_dev *dev, int res
static inline void pci_vf_drivers_autoprobe(struct pci_dev *dev, bool probe) { }
#endif
#if defined(CONFIG_HOTPLUG_PCI) || defined(CONFIG_HOTPLUG_PCI_MODULE)
void pci_hp_create_module_link(struct pci_slot *pci_slot);
void pci_hp_remove_module_link(struct pci_slot *pci_slot);
#endif
/**
* pci_pcie_cap - get the saved PCIe capability offset
* @dev: PCI device

View File

@ -50,7 +50,6 @@ struct hotplug_slot_ops {
/**
* struct hotplug_slot - used to register a physical slot with the hotplug pci core
* @ops: pointer to the &struct hotplug_slot_ops to be used for this slot
* @slot_list: internal list used to track hotplug PCI slots
* @pci_slot: represents a physical slot
* @owner: The module owner of this structure
* @mod_name: The module name (KBUILD_MODNAME) of this structure
@ -59,7 +58,6 @@ struct hotplug_slot {
const struct hotplug_slot_ops *ops;
/* Variables below this are for use only by the hotplug pci core. */
struct list_head slot_list;
struct pci_slot *pci_slot;
struct module *owner;
const char *mod_name;