PCI hotplug diet
cover PCI hotplug diet
Here's PCI hotplug material I've prepared for v4.20:
Patches [1/9] to [8/9] reduce the code by 488 lines. There should be no loss of functionality and no new features, just less and simpler code.
Patch [9/9] collects TODOs for hotplug drivers to spur contributions.
I've assumed that my patch "PCI: pciehp: Differentiate between surprise and safe removal" (submitted July 31) gets merged before this series:
https://patchwork.ozlabs.org/patch/951386/
If that patch is not accepted or other pciehp-related patches are merged before this series, I'll have to rebase patch [4/9] ("PCI: pciehp: Unify controller and slot structs"). No big deal, just a heads-up.
Thanks,
Lukas
Lukas Wunner (9):
PCI: Simplify disconnected marking
PCI: pciehp: Drop unnecessary includes
PCI: pciehp: Drop hotplug_slot_ops wrappers
PCI: pciehp: Unify controller and slot structs
PCI: pciehp: Reshuffle controller struct for clarity
PCI: hotplug: Constify hotplug_slot_ops
PCI: hotplug: Drop hotplug_slot_info
PCI: hotplug: Embed hotplug_slot
PCI: hotplug: Document TODOs
arch/powerpc/include/asm/pnv-pci.h | 2 +- drivers/pci/hotplug/TODO | 74 +++++++ drivers/pci/hotplug/acpiphp.h | 10 +- drivers/pci/hotplug/acpiphp_core.c | 36 +--- drivers/pci/hotplug/acpiphp_ibm.c | 2 +- drivers/pci/hotplug/cpci_hotplug.h | 11 +- drivers/pci/hotplug/cpci_hotplug_core.c | 105 +++------- drivers/pci/hotplug/cpci_hotplug_pci.c | 6 +- drivers/pci/hotplug/cpqphp.h | 9 +- drivers/pci/hotplug/cpqphp_core.c | 59 ++---- drivers/pci/hotplug/cpqphp_ctrl.c | 31 +-- drivers/pci/hotplug/ibmphp.h | 9 +- drivers/pci/hotplug/ibmphp_core.c | 121 ++++------- drivers/pci/hotplug/ibmphp_ebda.c | 70 +------ drivers/pci/hotplug/pci_hotplug_core.c | 53 ++--- drivers/pci/hotplug/pciehp.h | 138 ++++++------- drivers/pci/hotplug/pciehp_core.c | 127 +++--------- drivers/pci/hotplug/pciehp_ctrl.c | 255 +++++++++++------------- drivers/pci/hotplug/pciehp_hpc.c | 127 ++++-------- drivers/pci/hotplug/pciehp_pci.c | 24 +-- drivers/pci/hotplug/pnv_php.c | 35 ++-- drivers/pci/hotplug/rpaphp.h | 10 +- drivers/pci/hotplug/rpaphp_core.c | 20 +- drivers/pci/hotplug/rpaphp_pci.c | 11 +- drivers/pci/hotplug/rpaphp_slot.c | 22 +- drivers/pci/hotplug/s390_pci_hpc.c | 44 ++-- drivers/pci/hotplug/sgi_hotplug.c | 63 +++--- drivers/pci/hotplug/shpchp.h | 8 +- drivers/pci/hotplug/shpchp_core.c | 48 ++--- drivers/pci/hotplug/shpchp_ctrl.c | 21 +- drivers/pci/pci.c | 4 +- drivers/pci/pcie/err.c | 8 +- drivers/pci/slot.c | 2 +- drivers/platform/x86/asus-wmi.c | 39 +--- drivers/platform/x86/eeepc-laptop.c | 43 ++-- include/linux/pci_hotplug.h | 43 +--- 36 files changed, 638 insertions(+), 1052 deletions(-) create mode 100644 drivers/pci/hotplug/TODO
Signature · 1 line
2.18.0
PATCH 1/9 PCI: Simplify disconnected marking
Commit 89ee9f768003 ("PCI: Add device disconnected state") iterates over the devices on a parent bus, marks each as disconnected, then marks each device's children as disconnected using pci_walk_bus().
The same can be achieved more succinctly by calling pci_walk_bus() on the parent bus. Moreover, this does not need to wait until acquiring pci_lock_rescan_remove(), so move it out of that critical section.
The critical section in err.c contains a pci_dev_get() / pci_dev_put() pair which was apparently copy-pasted from pciehp_pci.c. In the latter it serves the purpose of holding the struct pci_dev in place until the Command register is updated. err.c doesn't do anything like that, hence the pair is unnecessary. Remove it.
--- drivers/pci/hotplug/pciehp_pci.c | 9 +++------ drivers/pci/pcie/err.c | 8 ++------ 2 files changed, 5 insertions(+), 12 deletions(-)
drivers/pci/hotplug/pciehp_pci.c +3 -6
@@ -91,6 +91,9 @@ void pciehp_unconfigure_device(struct slot *p_slot, bool presence)ctrl_dbg (ctrl,"%s: domain:bus:dev = %04x:%02x:00\n" , __func__,pci_domain_nr (parent), parent->number); +if (!presence) +pci_walk_bus (parent, pci_dev_set_disconnected,NULL ); +pci_lock_rescan_remove ();/*
@@ -102,12 +105,6 @@ void pciehp_unconfigure_device(struct slot *p_slot, bool presence)list_for_each_entry_safe_reverse (dev, temp, &parent->devices, bus_list) {pci_dev_get (dev); -if (!presence) { -pci_dev_set_disconnected (dev,NULL ); -if (pci_has_subordinate (dev)) -pci_walk_bus (dev->subordinate, - pci_dev_set_disconnected,NULL ); - }pci_stop_and_remove_bus_device (dev);/* * Ensure that no new Requests will be generated from
drivers/pci/pcie/err.c +2 -6
@@ -292,17 +292,13 @@ void pcie_do_fatal_recovery(struct pci_dev *dev, u32 service) udev = dev->bus->self; parent = udev->subordinate; +pci_walk_bus (parent, pci_dev_set_disconnected,NULL ); +pci_lock_rescan_remove ();pci_dev_get (dev);list_for_each_entry_safe_reverse (pdev, temp, &parent->devices, bus_list) { -pci_dev_get (pdev); -pci_dev_set_disconnected (pdev,NULL ); -if (pci_has_subordinate (pdev)) -pci_walk_bus (pdev->subordinate, - pci_dev_set_disconnected,NULL );pci_stop_and_remove_bus_device (pdev); -pci_dev_put (pdev); } result =reset_link (udev, service);
Signature · 1 line
2.18.0
Re: [PATCH 1/9] PCI: Simplify disconnected marking
drivers/pci/hotplug/pciehp_pci.c void pciehp_unconfigure_device(struct slot *p_slot, bool presence) · line 110
Quoted 7 lines · Lukas Wunner
pci_dev_get(dev);drivers/pci/hotplug/pciehp_pci.c +0
-6-if (!presence) { -pci_dev_set_disconnected (dev,NULL ); -if (pci_has_subordinate (dev)) -pci_walk_bus (dev->subordinate, - pci_dev_set_disconnected,NULL ); - }
Thanks, I never liked this.
PATCH 2/9 PCI: pciehp: Drop unnecessary includes
In reply to Lukas WunnerDrop the following includes from pciehp source files which no longer use any of the included symbols:
* <linux/sched/signal.h> in pciehp.h
<linux/signal.h> in pciehp_hpc.c
Added by commit de25968cc87c ("fix more missing includes") to accommodate for a call to signal_pending().
The call was removed by commit 262303fe329a ("pciehp: fix wait command completion").
* <linux/interrupt.h> in pciehp_core.c
Added by historic commit f308a2dfbe63 ("PCI: add PCI Express Port Bus Driver subsystem") to accommodate for a call to free_irq():
https://git.kernel.org/tglx/history/c/f308a2dfbe63
The call was removed by commit 407f452b05f9 ("pciehp: remove unnecessary free_irq").
* <linux/time.h> in pciehp_core.c and pciehp_hpc.c Added by commit 34d03419f03b ("PCIEHP: Add Electro Mechanical Interlock (EMI) support to the PCIE hotplug driver."), which was reverted by commit bd3d99c17039 ("PCI: Remove untested Electromechanical Interlock (EMI) support in pciehp.").
* <linux/module.h> in pciehp_ctrl.c, pciehp_hpc.c and pciehp_pci.c Added by historic commit c16b4b14d980 ("PCI Hotplug: Add SHPC and PCI Express hot-plug drivers"):
https://git.kernel.org/tglx/history/c/c16b4b14d980
Module-related symbols were neither used back then in those files, nor are they used today.
* <linux/slab.h> in pciehp_ctrl.c
Added by commit 5a0e3ad6af86 ("include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h") to accommodate for calls to kmalloc().
The calls were removed by commit 0e94916e6091 ("PCI: pciehp: Handle events synchronously").
* "../pci.h" in pciehp_ctrl.c
Added by historic commit 67f4660b72f2 ("PCI: ASPM patch for") to accommodate for usage of the global variable pcie_mch_quirk:
https://git.kernel.org/tglx/history/c/67f4660b72f2
The global variable was removed by commit 0ba379ec0fb1 ("PCI: Simplify hotplug mch quirk").
--- drivers/pci/hotplug/pciehp.h | 1 - drivers/pci/hotplug/pciehp_core.c | 2 -- drivers/pci/hotplug/pciehp_ctrl.c | 3 --- drivers/pci/hotplug/pciehp_hpc.c | 3 --- drivers/pci/hotplug/pciehp_pci.c | 1 - 5 files changed, 10 deletions(-)
drivers/pci/hotplug/pciehp.h +0 -1
@@ -19,7 +19,6 @@#include <linux/pci.h> #include <linux/pci_hotplug.h> #include <linux/delay.h> -#include <linux/sched/signal.h> /* signal_pending() */ #include <linux/mutex.h> #include <linux/rwsem.h> #include <linux/workqueue.h>
drivers/pci/hotplug/pciehp_core.c +0 -2
@@ -23,8 +23,6 @@#include <linux/types.h> #include <linux/pci.h> #include "pciehp.h" -#include <linux/interrupt.h> -#include <linux/time.h> #include "../pci.h"
drivers/pci/hotplug/pciehp_ctrl.c +0 -3
@@ -13,13 +13,10 @@* */ -#include <linux/module.h> #include <linux/kernel.h> #include <linux/types.h> -#include <linux/slab.h> #include <linux/pm_runtime.h> #include <linux/pci.h> -#include "../pci.h" #include "pciehp.h" /* The following routines constitute the bulk of the
drivers/pci/hotplug/pciehp_hpc.c +0 -3
@@ -13,15 +13,12 @@*/ #include <linux/kernel.h> -#include <linux/module.h> #include <linux/types.h> -#include <linux/signal.h> #include <linux/jiffies.h> #include <linux/kthread.h> #include <linux/pci.h> #include <linux/pm_runtime.h> #include <linux/interrupt.h> -#include <linux/time.h> #include <linux/slab.h> #include "../pci.h"
drivers/pci/hotplug/pciehp_pci.c +0 -1
@@ -13,7 +13,6 @@* */ -#include <linux/module.h> #include <linux/kernel.h> #include <linux/types.h> #include <linux/pci.h>
Signature · 1 line
2.18.0
PATCH 3/9 PCI: pciehp: Drop hotplug_slot_ops wrappers
In reply to Lukas Wunnerpciehp's ->enable_slot, ->disable_slot, ->get_attention_status and ->reset_slot callbacks are currently implemented by wrapper functions that do nothing else but call down to a backend function. The backends are not called from anywhere else, so drop the wrappers and use the backends directly as callbacks, thereby shaving off a few lines of unnecessary code.
No functional change intended.
--- drivers/pci/hotplug/pciehp.h | 8 +++--- drivers/pci/hotplug/pciehp_core.c | 43 +++---------------------------- drivers/pci/hotplug/pciehp_ctrl.c | 6 +++-- drivers/pci/hotplug/pciehp_hpc.c | 8 ++++-- 4 files changed, 18 insertions(+), 47 deletions(-)
drivers/pci/hotplug/pciehp.h +4 -4
@@ -173,8 +173,6 @@ struct controller {#define NO_CMD_CMPL (ctrl) ((ctrl)->slot_cap & PCI_EXP_SLTCAP_NCCS)#define PSN (ctrl) (((ctrl)->slot_cap & PCI_EXP_SLTCAP_PSN) >> 19) -int pciehp_sysfs_enable_slot (struct slot *slot); -int pciehp_sysfs_disable_slot (struct slot *slot);void pciehp_request (struct controller *ctrl,int action);void pciehp_handle_button_press (struct slot *slot);void pciehp_handle_disable_request (struct slot *slot);
@@ -189,7 +187,6 @@ void pcie_clear_hotplug_events(struct controller *ctrl);int pciehp_power_on_slot (struct slot *slot);void pciehp_power_off_slot (struct slot *slot);void pciehp_get_power_status (struct slot *slot,u8 *status); -void pciehp_get_attention_status (struct slot *slot,u8 *status);void pciehp_set_attention_status (struct slot *slot,u8 status);void pciehp_get_latch_status (struct slot *slot,u8 *status);
@@ -201,8 +198,11 @@ void pciehp_green_led_blink(struct slot *slot);int pciehp_check_link_status (struct controller *ctrl);bool pciehp_check_link_active (struct controller *ctrl);void pciehp_release_ctrl (struct controller *ctrl); -int pciehp_reset_slot (struct slot *slot,int probe); +int pciehp_sysfs_enable_slot (struct hotplug_slot *hotplug_slot); +int pciehp_sysfs_disable_slot (struct hotplug_slot *hotplug_slot); +int pciehp_reset_slot (struct hotplug_slot *hotplug_slot,int probe); +int pciehp_get_attention_status (struct hotplug_slot *hotplug_slot,u8 *status);int pciehp_set_raw_indicator_status (struct hotplug_slot *h_slot,u8 status);int pciehp_get_raw_indicator_status (struct hotplug_slot *h_slot,u8 *status);
drivers/pci/hotplug/pciehp_core.c +4 -39
81 lines not on this page · raw message
drivers/pci/hotplug/pciehp_ctrl.c +4 -2
@@ -364,8 +364,9 @@ static int pciehp_disable_slot(struct slot *slot, bool safe_removal)return ret; } -int pciehp_sysfs_enable_slot (struct slot *p_slot) +int pciehp_sysfs_enable_slot (struct hotplug_slot *hotplug_slot) { +struct slot *p_slot = hotplug_slot->private;struct controller *ctrl = p_slot->ctrl;mutex_lock (&p_slot->lock);
@@ -402,8 +403,9 @@ int pciehp_sysfs_enable_slot(struct slot *p_slot)return -ENODEV ; } -int pciehp_sysfs_disable_slot (struct slot *p_slot) +int pciehp_sysfs_disable_slot (struct hotplug_slot *hotplug_slot) { +struct slot *p_slot = hotplug_slot->private;struct controller *ctrl = p_slot->ctrl;mutex_lock (&p_slot->lock);
drivers/pci/hotplug/pciehp_hpc.c +6 -2
@@ -326,8 +326,9 @@ int pciehp_get_raw_indicator_status(struct hotplug_slot *hotplug_slot,return 0 ; } -void pciehp_get_attention_status (struct slot *slot,u8 *status) +int pciehp_get_attention_status (struct hotplug_slot *hotplug_slot,u8 *status) { +struct slot *slot = hotplug_slot->private;struct controller *ctrl = slot->ctrl;struct pci_dev *pdev =ctrl_dev (ctrl);u16 slot_ctrl;
@@ -352,6 +353,8 @@ void pciehp_get_attention_status(struct slot *slot, u8 *status) *status =0xFF ;break ; } + +return 0 ; }void pciehp_get_power_status (struct slot *slot,u8 *status)
@@ -753,8 +756,9 @@ void pcie_clear_hotplug_events(struct controller *ctrl)* momentarily, if we see that they could interfere. Also, clear any spurious * events after. */ -int pciehp_reset_slot (struct slot *slot,int probe) +int pciehp_reset_slot (struct hotplug_slot *hotplug_slot,int probe) { +struct slot *slot = hotplug_slot->private;struct controller *ctrl = slot->ctrl;struct pci_dev *pdev =ctrl_dev (ctrl);u16 stat_mask =0 , ctrl_mask =0 ;
Signature · 1 line
2.18.0
Re: [PATCH 3/9] PCI: pciehp: Drop hotplug_slot_ops wrappers
Quoted 10 lines · Lukas Wunner
pciehp's ->enable_slot, ->disable_slot, ->get_attention_status and ->reset_slot callbacks are currently implemented by wrapper functions that do nothing else but call down to a backend function. The backends are not called from anywhere else, so drop the wrappers and use the backends directly as callbacks, thereby shaving off a few lines of unnecessary code.
No functional change intended.
Signed-off-by Lukas Wunner<[email protected]>
Great work. I was surprised by the number of steps we need to jump in order to reach to real code here. Simplification is welcome.
PATCH 4/9 PCI: pciehp: Unify controller and slot structs
In reply to Lukas Wunnerpciehp was originally introduced together with shpchp in a single commit, c16b4b14d980 ("PCI Hotplug: Add SHPC and PCI Express hot-plug drivers"):
https://git.kernel.org/tglx/history/c/c16b4b14d980
shpchp supports up to 31 slots per controller, hence uses separate slot and controller structs. pciehp has a 1:1 relationship between slot and controller and therefore never required this separation. Nevertheless, because much of the code had been copy-pasted between the two drivers, pciehp likewise uses separate structs to this very day.
The artificial separation of data structures adds unnecessary complexity and bloat to pciehp and requires constantly chasing pointers at runtime.
Simplify the driver by merging struct slot into struct controller. Merge the slot constructor pcie_init_slot() and the destructor pcie_cleanup_slot() into the controller counterparts. Rename the slot struct's "lock" member to "state_lock" and rename "work" to "button_work" for clarity.
No functional change intended.
--- drivers/pci/hotplug/pciehp.h | 69 ++++----- drivers/pci/hotplug/pciehp_core.c | 55 +++---- drivers/pci/hotplug/pciehp_ctrl.c | 250 ++++++++++++++---------------- drivers/pci/hotplug/pciehp_hpc.c | 120 +++++--------- drivers/pci/hotplug/pciehp_pci.c | 14 +- 5 files changed, 218 insertions(+), 290 deletions(-)
drivers/pci/hotplug/pciehp.h +31 -38
@@ -58,24 +58,6 @@ do { \#define SLOT_NAME_SIZE 10 -/** -* struct slot - PCIe hotplug slot -* @state: current state machine position -* @ctrl: pointer to the slot's controller structure -* @hotplug_slot: pointer to the structure registered with the PCI hotplug core -* @work: work item to turn the slot on or off after 5 seconds in response to -* an Attention Button press -* @lock: protects reads and writes of @state; -* protects scheduling, execution and cancellation of @work -*/ -struct slot { -u8 state; -struct controller *ctrl; -struct hotplug_slot *hotplug_slot; -struct delayed_work work; -struct mutex lock; -}; -/** * struct controller - PCIe hotplug controller * @ctrl_lock: serializes writes to the Slot Control register
@@ -83,7 +65,6 @@ struct slot {* @reset_lock: prevents access to the Data Link Layer Link Active bit in the * Link Status register and to the Presence Detect State bit in the Slot * Status register during a slot reset which may cause them to flap -* @slot: pointer to the controller's slot structure * @queue: wait queue to wake up on reception of a Command Completed event, * used for synchronous writes to the Slot Control register * @slot_cap: cached copy of the Slot Capabilities register
@@ -105,15 +86,23 @@ struct slot {* that has not yet been cleared by the user * @pending_events: used by the IRQ handler to save events retrieved from the * Slot Status register for later consumption by the IRQ thread +* @state: current state machine position +* @state_lock: protects reads and writes of @state; +* protects scheduling, execution and cancellation of @button_work +* @button_work: work item to turn the slot on or off after 5 seconds +* in response to an Attention Button press +* @hotplug_slot: pointer to the structure registered with the PCI hotplug core * @request_result: result of last user request submitted to the IRQ thread * @requester: wait queue to wake up on completion of user request, * used for synchronous slot enable/disable request via sysfs +* +* PCIe hotplug has a 1:1 relationship between controller and slot, hence +* unlike other drivers, the two aren't represented by separate structures. */ struct controller {struct mutex ctrl_lock;struct pcie_device *pcie;struct rw_semaphore reset_lock; -struct slot *slot;wait_queue_head_t queue;u32 slot_cap;u16 slot_ctrl;
@@ -124,6 +113,10 @@ struct controller { unsigned int notification_enabled:1;unsigned int power_fault_detected;atomic_t pending_events; +u8 state; +struct mutex state_lock; +struct delayed_work button_work; +struct hotplug_slot *hotplug_slot;int request_result;wait_queue_head_t requester; };
@@ -174,27 +167,27 @@ struct controller {#define PSN (ctrl) (((ctrl)->slot_cap & PCI_EXP_SLTCAP_PSN) >> 19)void pciehp_request (struct controller *ctrl,int action); -void pciehp_handle_button_press (struct slot *slot); -void pciehp_handle_disable_request (struct slot *slot); -void pciehp_handle_presence_or_link_change (struct slot *slot,u32 events); -int pciehp_configure_device (struct slot *p_slot); -void pciehp_unconfigure_device (struct slot *p_slot,bool presence); +void pciehp_handle_button_press (struct controller *ctrl); +void pciehp_handle_disable_request (struct controller *ctrl); +void pciehp_handle_presence_or_link_change (struct controller *ctrl,u32 events); +int pciehp_configure_device (struct controller *ctrl); +void pciehp_unconfigure_device (struct controller *ctrl,bool presence);void pciehp_queue_pushbutton_work (struct work_struct *work);struct controller *pcie_init (struct pcie_device *dev);int pcie_init_notification (struct controller *ctrl);void pcie_shutdown_notification (struct controller *ctrl);void pcie_clear_hotplug_events (struct controller *ctrl); -int pciehp_power_on_slot (struct slot *slot); -void pciehp_power_off_slot (struct slot *slot); -void pciehp_get_power_status (struct slot *slot,u8 *status); - -void pciehp_set_attention_status (struct slot *slot,u8 status); -void pciehp_get_latch_status (struct slot *slot,u8 *status); -void pciehp_get_adapter_status (struct slot *slot,u8 *status); -int pciehp_query_power_fault (struct slot *slot); -void pciehp_green_led_on (struct slot *slot); -void pciehp_green_led_off (struct slot *slot); -void pciehp_green_led_blink (struct slot *slot); +int pciehp_power_on_slot (struct controller *ctrl); +void pciehp_power_off_slot (struct controller *ctrl); +void pciehp_get_power_status (struct controller *ctrl,u8 *status); + +void pciehp_set_attention_status (struct controller *ctrl,u8 status); +void pciehp_get_latch_status (struct controller *ctrl,u8 *status); +void pciehp_get_adapter_status (struct controller *ctrl,u8 *status); +int pciehp_query_power_fault (struct controller *ctrl); +void pciehp_green_led_on (struct controller *ctrl); +void pciehp_green_led_off (struct controller *ctrl); +void pciehp_green_led_blink (struct controller *ctrl);int pciehp_check_link_status (struct controller *ctrl);bool pciehp_check_link_active (struct controller *ctrl);void pciehp_release_ctrl (struct controller *ctrl);
@@ -206,9 +199,9 @@ int pciehp_get_attention_status(struct hotplug_slot *hotplug_slot, u8 *status);int pciehp_set_raw_indicator_status (struct hotplug_slot *h_slot,u8 status);int pciehp_get_raw_indicator_status (struct hotplug_slot *h_slot,u8 *status); -static inline const char *slot_name (struct slot *slot) +static inline const char *slot_name (struct controller *ctrl) { -return hotplug_slot_name (slot->hotplug_slot); +return hotplug_slot_name (ctrl->hotplug_slot); }#endif /* _PCIEHP_H */
drivers/pci/hotplug/pciehp_core.c +25 -30
148 lines not on this page · raw message
drivers/pci/hotplug/pciehp_ctrl.c +118 -132
504 lines not on this page · raw message
drivers/pci/hotplug/pciehp_hpc.c +38 -82
291 lines not on this page · raw message
drivers/pci/hotplug/pciehp_pci.c +6 -8
@@ -21,19 +21,18 @@/** * pciehp_configure_device() - enumerate PCI devices below a hotplug bridge -* @p_slot: PCIe hotplug slot +* @ctrl: PCIe hotplug controller * * Enumerate PCI devices below a hotplug bridge and add them to the system. * Return 0 on success, %-EEXIST if the devices are already enumerated or * %-ENODEV if enumeration failed. */ -int pciehp_configure_device (struct slot *p_slot) +int pciehp_configure_device (struct controller *ctrl) {struct pci_dev *dev; -struct pci_dev *bridge = p_slot->ctrl->pcie->port; +struct pci_dev *bridge = ctrl->pcie->port;struct pci_bus *parent = bridge->subordinate;int num, ret =0 ; -struct controller *ctrl = p_slot->ctrl;pci_lock_rescan_remove ();
@@ -71,7 +70,7 @@ int pciehp_configure_device(struct slot *p_slot)/** * pciehp_unconfigure_device() - remove PCI devices below a hotplug bridge -* @p_slot: PCIe hotplug slot +* @ctrl: PCIe hotplug controller * @presence: whether the card is still present in the slot; * true for safe removal via sysfs or an Attention Button press, * false for surprise removal
@@ -80,12 +79,11 @@ int pciehp_configure_device(struct slot *p_slot)* them from the system. Safely removed devices are quiesced. Surprise * removed devices are marked as such to prevent further accesses. */ -void pciehp_unconfigure_device (struct slot *p_slot,bool presence) +void pciehp_unconfigure_device (struct controller *ctrl,bool presence) {struct pci_dev *dev, *temp; -struct pci_bus *parent = p_slot->ctrl->pcie->port->subordinate; +struct pci_bus *parent = ctrl->pcie->port->subordinate;u16 command; -struct controller *ctrl = p_slot->ctrl;ctrl_dbg (ctrl,"%s: domain:bus:dev = %04x:%02x:00\n" , __func__,pci_domain_nr (parent), parent->number);
Signature · 1 line
2.18.0
Re: [PATCH 4/9] PCI: pciehp: Unify controller and slot structs
Quoted 5 lines · Lukas Wunner
Simplify the driver by merging struct slot into struct controller. Merge the slot constructor
pcie_init_slot()and the destructorpcie_cleanup_slot()into the controller counterparts. Rename the slot struct's "lock" member to "state_lock" and rename "work" to "button_work" for clarity.
please split this into multiple pieces.
Re: [PATCH 4/9] PCI: pciehp: Unify controller and slot structs
Quoted 8 lines · Sinan Kaya
Quoted 5 lines · Lukas Wunner
Simplify the driver by merging struct slot into struct controller. Merge the slot constructor
pcie_init_slot()and the destructorpcie_cleanup_slot()into the controller counterparts. Rename the slot struct's "lock" member to "state_lock" and rename "work" to "button_work" for clarity.please split this into multiple pieces.
Hm, you mean split out the renaming of the "lock" and "work" members?
The unification of the two structs needs to happen in a single commit to avoid breaking the build for people doing a git bisect.
Thanks,
Lukas
Re: [PATCH 4/9] PCI: pciehp: Unify controller and slot structs
Quoted 8 lines · Lukas Wunner
Quoted 7 lines · Sinan Kaya
Quoted 5 lines · Lukas Wunner
Simplify the driver by merging struct slot into struct controller. Merge the slot constructor
pcie_init_slot()and the destructorpcie_cleanup_slot()into the controller counterparts. Rename the slot struct's "lock" member to "state_lock" and rename "work" to "button_work" for clarity.
Quoted 7 lines
Quoted 1 line
please split this into multiple pieces.
Hm, you mean split out the renaming of the "lock" and "work" members?
The unification of the two structs needs to happen in a single commit to avoid breaking the build for people doing a git bisect.
I was thinking of the rename.
Quoted 4 lines
Thanks,
Lukas
Re: [PATCH 4/9] PCI: pciehp: Unify controller and slot structs
Quoted 9 lines · Sinan Kaya
Quoted 8 lines · Lukas Wunner
Quoted 7 lines · Sinan Kaya
Quoted 5 lines · Lukas Wunner
Simplify the driver by merging struct slot into struct controller. Merge the slot constructor
pcie_init_slot()and the destructorpcie_cleanup_slot()into the controller counterparts. Rename the slot struct's "lock" member to "state_lock" and rename "work" to "button_work" for clarity.
Quoted 8 lines
Quoted 6 lines
Quoted 1 line
please split this into multiple pieces.
Hm, you mean split out the renaming of the "lock" and "work" members?
The unification of the two structs needs to happen in a single commit to avoid breaking the build for people doing a git bisect.
I was thinking of the rename.
Could the rename be done in a separate patch before the unification? If so, that would be nice.
Bjorn
Re: [PATCH 4/9] PCI: pciehp: Unify controller and slot structs
Quoted 9 lines · Bjorn Helgaas
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines · Lukas Wunner
Quoted 5 lines
Simplify the driver by merging struct slot into struct controller. Merge the slot constructor
pcie_init_slot()and the destructorpcie_cleanup_slot()into the controller counterparts. Rename the slot struct's "lock" member to "state_lock" and rename "work" to "button_work" for clarity.Could the rename be done in a separate patch before the unification? If so, that would be nice.
Okay, I've already reworked my internal development branch to do the unification first, then the rename, but can easily turn the order around, no problem at all.
The preceding patches 1 to 3 of this series could be merged independently, or would you prefer me to resend them? The first one is also included in Keith's error handling rework series (posted yesterday):
[1/9] PCI: Simplify disconnected marking
https://patchwork.ozlabs.org/patch/959373/ [2/9] PCI: pciehp: Drop unnecessary includes https://patchwork.ozlabs.org/patch/959376/ [3/9] [3/9] PCI: pciehp: Drop hotplug_slot_ops wrappers https://patchwork.ozlabs.org/patch/959377/
Important side note: Keith's series includes a pciehp fix which should probably go into 4.19:
[PATCHv2,15/20] PCI/pciehp: Fix powerfault detection order
https://patchwork.ozlabs.org/patch/966678/
Now, if that patch goes into, say, 4.19-rc3, the pci/hotplug branch would have to be rebased on top of 4.19-rc3 to avoid conflicts during the 4.20 merge window.
The problem with unification of the controller and slot structs in pciehp is that it's a fairly intrusive patch. Any pciehp patches that are pending now would need to be rebased on top of it. Right now the only pending pciehp patches are Keith's series posted yesterday and this patch from me (which would be 4.20 material):
PCI: pciehp: Tolerate Presence Detect hardwired to zero diffmboxseries
https://patchwork.ozlabs.org/patch/961860/
I can rebase all the patches as often as necessary, no problem. Just let me know when it is most convenient for you to merge what and I'll accommodate. I'm sorry for the somewhat complicated merging situation.
Thanks,
Lukas
Re: [PATCH 4/9] PCI: pciehp: Unify controller and slot structs
Quoted 8 lines · Lukas Wunner
Quoted 7 lines · Bjorn Helgaas
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines · Lukas Wunner
Quoted 5 lines
Simplify the driver by merging struct slot into struct controller. Merge the slot constructor
pcie_init_slot()and the destructorpcie_cleanup_slot()into the controller counterparts. Rename the slot struct's "lock" member to "state_lock" and rename "work" to "button_work" for clarity.
Quoted 6 lines
Quoted 2 lines
Could the rename be done in a separate patch before the unification? If so, that would be nice.
Okay, I've already reworked my internal development branch to do the unification first, then the rename, but can easily turn the order around, no problem at all.
I don't care which order they're in. I just wasn't sure if the unification was possible without the renaming.
Quoted 10 lines
The preceding patches 1 to 3 of this series could be merged independently, or would you prefer me to resend them? The first one is also included in Keith's error handling rework series (posted yesterday):
[1/9] PCI: Simplify disconnected marking
https://patchwork.ozlabs.org/patch/959373/ [2/9] PCI: pciehp: Drop unnecessary includes https://patchwork.ozlabs.org/patch/959376/ [3/9] [3/9] PCI: pciehp: Drop hotplug_slot_ops wrappers https://patchwork.ozlabs.org/patch/959377/
I applied patches 1-3 to pci/hotplug. If you could rebase what's left on top of that, it would be great.
Quoted 5 lines
Important side note: Keith's series includes a pciehp fix which should probably go into 4.19:
[PATCHv2,15/20] PCI/pciehp: Fix powerfault detection order
https://patchwork.ozlabs.org/patch/966678/
Thanks for the heads-up; I probably wouldn't have picked that out.
Quoted 3 lines
Now, if that patch goes into, say, 4.19-rc3, the pci/hotplug branch would have to be rebased on top of 4.19-rc3 to avoid conflicts during the 4.20 merge window.
I'll try to remember to do this. I have no problem rebasing my branches to -rc3.
Bjorn
Re: [PATCH 4/9] PCI: pciehp: Unify controller and slot structs
In reply to Lukas WunnerQuoted 29 lines · Lukas Wunner
Quoted 9 lines · Bjorn Helgaas
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines · Lukas Wunner
Quoted 5 lines
Simplify the driver by merging struct slot into struct controller. Merge the slot constructor
pcie_init_slot()and the destructorpcie_cleanup_slot()into the controller counterparts. Rename the slot struct's "lock" member to "state_lock" and rename "work" to "button_work" for clarity.Could the rename be done in a separate patch before the unification? If so, that would be nice.
Okay, I've already reworked my internal development branch to do the unification first, then the rename, but can easily turn the order around, no problem at all.
The preceding patches 1 to 3 of this series could be merged independently, or would you prefer me to resend them? The first one is also included in Keith's error handling rework series (posted yesterday):
[1/9] PCI: Simplify disconnected marking
https://patchwork.ozlabs.org/patch/959373/ [2/9] PCI: pciehp: Drop unnecessary includes https://patchwork.ozlabs.org/patch/959376/ [3/9] [3/9] PCI: pciehp: Drop hotplug_slot_ops wrappers https://patchwork.ozlabs.org/patch/959377/Important side note: Keith's series includes a pciehp fix which should probably go into 4.19:
Quoted 6 lines
[PATCHv2,15/20] PCI/pciehp: Fix powerfault detection order
https://patchwork.ozlabs.org/patch/966678/Now, if that patch goes into, say, 4.19-rc3, the pci/hotplug branch would have to be rebased on top of 4.19-rc3 to avoid conflicts during the 4.20 merge window.
OK, I rebased pci/hotplug to v4.19-rc4. Any chance you could update this series to apply on top of that?
Bjorn
Re: [PATCH 4/9] PCI: pciehp: Unify controller and slot structs
Quoted 2 lines · Bjorn Helgaas
OK, I rebased pci/hotplug to v4.19-rc4. Any chance you could update this series to apply on top of that?
Great, thanks.
I've posted a v2 of this series on Sep 8:
https://patchwork.ozlabs.org/project/linux-pci/list/?series=64701&state=*
Only a single patch of that series is affected by the rebase, patch [2/8]. I have just marked that patch as "Not Applicable" in patchwork and am including a replacement patch below. Same patch, just rebased on top of current pci/hotplug branch.
I can also post the series again if that is easier for you to handle than a replacement patch.
-- >8 --
Subject: [PATCH] PCI: pciehp: Unify controller and slot structs
pciehp was originally introduced together with shpchp in a single commit, c16b4b14d980 ("PCI Hotplug: Add SHPC and PCI Express hot-plug drivers"):
https://git.kernel.org/tglx/history/c/c16b4b14d980
shpchp supports up to 31 slots per controller, hence uses separate slot and controller structs. pciehp has a 1:1 relationship between slot and controller and therefore never required this separation. Nevertheless, because much of the code had been copy-pasted between the two drivers, pciehp likewise uses separate structs to this very day.
The artificial separation of data structures adds unnecessary complexity and bloat to pciehp and requires constantly chasing pointers at runtime.
Simplify the driver by merging struct slot into struct controller. Merge the slot constructor pcie_init_slot() and the destructor pcie_cleanup_slot() into the controller counterparts.
No functional change intended.
--- drivers/pci/hotplug/pciehp.h | 67 ++++---- drivers/pci/hotplug/pciehp_core.c | 53 +++---- drivers/pci/hotplug/pciehp_ctrl.c | 244 ++++++++++++++---------------- drivers/pci/hotplug/pciehp_hpc.c | 114 +++++--------- drivers/pci/hotplug/pciehp_pci.c | 14 +- 5 files changed, 210 insertions(+), 282 deletions(-)
drivers/pci/hotplug/pciehp.h +30 -37
@@ -58,24 +58,6 @@ do { \#define SLOT_NAME_SIZE 10 -/** -* struct slot - PCIe hotplug slot -* @state: current state machine position -* @ctrl: pointer to the slot's controller structure -* @hotplug_slot: pointer to the structure registered with the PCI hotplug core -* @work: work item to turn the slot on or off after 5 seconds in response to -* an Attention Button press -* @lock: protects reads and writes of @state; -* protects scheduling, execution and cancellation of @work -*/ -struct slot { -u8 state; -struct controller *ctrl; -struct hotplug_slot *hotplug_slot; -struct delayed_work work; -struct mutex lock; -}; -/** * struct controller - PCIe hotplug controller * @ctrl_lock: serializes writes to the Slot Control register
@@ -83,7 +65,6 @@ struct slot {* @reset_lock: prevents access to the Data Link Layer Link Active bit in the * Link Status register and to the Presence Detect State bit in the Slot * Status register during a slot reset which may cause them to flap -* @slot: pointer to the controller's slot structure * @queue: wait queue to wake up on reception of a Command Completed event, * used for synchronous writes to the Slot Control register * @slot_cap: cached copy of the Slot Capabilities register
@@ -105,15 +86,23 @@ struct slot {* that has not yet been cleared by the user * @pending_events: used by the IRQ handler to save events retrieved from the * Slot Status register for later consumption by the IRQ thread +* @state: current state machine position +* @lock: protects reads and writes of @state; +* protects scheduling, execution and cancellation of @work +* @work: work item to turn the slot on or off after 5 seconds +* in response to an Attention Button press +* @hotplug_slot: pointer to the structure registered with the PCI hotplug core * @request_result: result of last user request submitted to the IRQ thread * @requester: wait queue to wake up on completion of user request, * used for synchronous slot enable/disable request via sysfs +* +* PCIe hotplug has a 1:1 relationship between controller and slot, hence +* unlike other drivers, the two aren't represented by separate structures. */ struct controller {struct mutex ctrl_lock;struct pcie_device *pcie;struct rw_semaphore reset_lock; -struct slot *slot;wait_queue_head_t queue;u32 slot_cap;u16 slot_ctrl;
@@ -124,6 +113,10 @@ struct controller { unsigned int notification_enabled:1;unsigned int power_fault_detected;atomic_t pending_events; +u8 state; +struct mutex lock; +struct delayed_work work; +struct hotplug_slot *hotplug_slot;int request_result;wait_queue_head_t requester; };
@@ -174,26 +167,26 @@ struct controller {#define PSN (ctrl) (((ctrl)->slot_cap & PCI_EXP_SLTCAP_PSN) >> 19)void pciehp_request (struct controller *ctrl,int action); -void pciehp_handle_button_press (struct slot *slot); -void pciehp_handle_disable_request (struct slot *slot); -void pciehp_handle_presence_or_link_change (struct slot *slot,u32 events); -int pciehp_configure_device (struct slot *p_slot); -void pciehp_unconfigure_device (struct slot *p_slot,bool presence); +void pciehp_handle_button_press (struct controller *ctrl); +void pciehp_handle_disable_request (struct controller *ctrl); +void pciehp_handle_presence_or_link_change (struct controller *ctrl,u32 events); +int pciehp_configure_device (struct controller *ctrl); +void pciehp_unconfigure_device (struct controller *ctrl,bool presence);void pciehp_queue_pushbutton_work (struct work_struct *work);struct controller *pcie_init (struct pcie_device *dev);int pcie_init_notification (struct controller *ctrl);void pcie_shutdown_notification (struct controller *ctrl);void pcie_clear_hotplug_events (struct controller *ctrl); -int pciehp_power_on_slot (struct slot *slot); -void pciehp_power_off_slot (struct slot *slot); -void pciehp_get_power_status (struct slot *slot,u8 *status); - -void pciehp_set_attention_status (struct slot *slot,u8 status); -void pciehp_get_latch_status (struct slot *slot,u8 *status); -int pciehp_query_power_fault (struct slot *slot); -void pciehp_green_led_on (struct slot *slot); -void pciehp_green_led_off (struct slot *slot); -void pciehp_green_led_blink (struct slot *slot); +int pciehp_power_on_slot (struct controller *ctrl); +void pciehp_power_off_slot (struct controller *ctrl); +void pciehp_get_power_status (struct controller *ctrl,u8 *status); + +void pciehp_set_attention_status (struct controller *ctrl,u8 status); +void pciehp_get_latch_status (struct controller *ctrl,u8 *status); +int pciehp_query_power_fault (struct controller *ctrl); +void pciehp_green_led_on (struct controller *ctrl); +void pciehp_green_led_off (struct controller *ctrl); +void pciehp_green_led_blink (struct controller *ctrl);bool pciehp_card_present (struct controller *ctrl);bool pciehp_card_present_or_link_active (struct controller *ctrl);int pciehp_check_link_status (struct controller *ctrl);
@@ -207,9 +200,9 @@ int pciehp_get_attention_status(struct hotplug_slot *hotplug_slot, u8 *status);int pciehp_set_raw_indicator_status (struct hotplug_slot *h_slot,u8 status);int pciehp_get_raw_indicator_status (struct hotplug_slot *h_slot,u8 *status); -static inline const char *slot_name (struct slot *slot) +static inline const char *slot_name (struct controller *ctrl) { -return hotplug_slot_name (slot->hotplug_slot); +return hotplug_slot_name (ctrl->hotplug_slot); }#endif /* _PCIEHP_H */
drivers/pci/hotplug/pciehp_core.c +24 -29
147 lines not on this page · raw message
drivers/pci/hotplug/pciehp_ctrl.c +115 -129
496 lines not on this page · raw message
drivers/pci/hotplug/pciehp_hpc.c +35 -79
278 lines not on this page · raw message
drivers/pci/hotplug/pciehp_pci.c +6 -8
@@ -21,19 +21,18 @@/** * pciehp_configure_device() - enumerate PCI devices below a hotplug bridge -* @p_slot: PCIe hotplug slot +* @ctrl: PCIe hotplug controller * * Enumerate PCI devices below a hotplug bridge and add them to the system. * Return 0 on success, %-EEXIST if the devices are already enumerated or * %-ENODEV if enumeration failed. */ -int pciehp_configure_device (struct slot *p_slot) +int pciehp_configure_device (struct controller *ctrl) {struct pci_dev *dev; -struct pci_dev *bridge = p_slot->ctrl->pcie->port; +struct pci_dev *bridge = ctrl->pcie->port;struct pci_bus *parent = bridge->subordinate;int num, ret =0 ; -struct controller *ctrl = p_slot->ctrl;pci_lock_rescan_remove ();
@@ -71,7 +70,7 @@ int pciehp_configure_device(struct slot *p_slot)/** * pciehp_unconfigure_device() - remove PCI devices below a hotplug bridge -* @p_slot: PCIe hotplug slot +* @ctrl: PCIe hotplug controller * @presence: whether the card is still present in the slot; * true for safe removal via sysfs or an Attention Button press, * false for surprise removal
@@ -80,12 +79,11 @@ int pciehp_configure_device(struct slot *p_slot)* them from the system. Safely removed devices are quiesced. Surprise * removed devices are marked as such to prevent further accesses. */ -void pciehp_unconfigure_device (struct slot *p_slot,bool presence) +void pciehp_unconfigure_device (struct controller *ctrl,bool presence) {struct pci_dev *dev, *temp; -struct pci_bus *parent = p_slot->ctrl->pcie->port->subordinate; +struct pci_bus *parent = ctrl->pcie->port->subordinate;u16 command; -struct controller *ctrl = p_slot->ctrl;ctrl_dbg (ctrl,"%s: domain:bus:dev = %04x:%02x:00\n" , __func__,pci_domain_nr (parent), parent->number);
Signature · 1 line
2.18.0
PATCH 5/9 PCI: pciehp: Reshuffle controller struct for clarity
In reply to Lukas WunnerThe members in pciehp's controller struct are arranged in a seemingly arbitrary order and have grown to an amount that I no longer consider easily graspable by contributors.
Sort the members into 5 rubrics:
* Slot Capabilities register and quirks
* Slot Control register access
* Slot Status register event handling
* state machine
* hotplug core interface
Obviously, this is just my personal bikeshed color and if anyone has a better idea, please come forward. Any ordering will do as long as the information is presented in a manageable manner.
Change unsigned int members to bool where applicable. Some of these were declared as bitfields, which doesn't really save a whole lot of memory due to padding. It is also racy if adjacent bitfields are modified concurrently.
No functional change intended.
--- drivers/pci/hotplug/pciehp.h | 59 +++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 27 deletions(-)
drivers/pci/hotplug/pciehp.h +32 -27
@@ -60,38 +60,38 @@ do { \/** * struct controller - PCIe hotplug controller -* @ctrl_lock: serializes writes to the Slot Control register * @pcie: pointer to the controller's PCIe port service device -* @reset_lock: prevents access to the Data Link Layer Link Active bit in the -* Link Status register and to the Presence Detect State bit in the Slot -* Status register during a slot reset which may cause them to flap -* @queue: wait queue to wake up on reception of a Command Completed event, -* used for synchronous writes to the Slot Control register * @slot_cap: cached copy of the Slot Capabilities register +* @link_active_reporting: cached copy of Data Link Layer Link Active Reporting +* Capable bit in Link Capabilities register; if this bit is zero, the +* Data Link Layer Link Active bit in the Link Status register will never +* be set and the driver is thus confined to wait 1 second before assuming +* the link to a hotplugged device is up and accessing it * @slot_ctrl: cached copy of the Slot Control register -* @poll_thread: thread to poll for slot events if no IRQ is available, -* enabled with pciehp_poll_mode module parameter +* @ctrl_lock: serializes writes to the Slot Control register * @cmd_started: jiffies when the Slot Control register was last written; * the next write is allowed 1 second later, absent a Command Completed * interrupt (PCIe r4.0, sec 6.7.3.2) * @cmd_busy: flag set on Slot Control register write, cleared by IRQ handler * on reception of a Command Completed event -* @link_active_reporting: cached copy of Data Link Layer Link Active Reporting -* Capable bit in Link Capabilities register; if this bit is zero, the -* Data Link Layer Link Active bit in the Link Status register will never -* be set and the driver is thus confined to wait 1 second before assuming -* the link to a hotplugged device is up and accessing it +* @queue: wait queue to wake up on reception of a Command Completed event, +* used for synchronous writes to the Slot Control register +* @pending_events: used by the IRQ handler to save events retrieved from the +* Slot Status register for later consumption by the IRQ thread * @notification_enabled: whether the IRQ was requested successfully * @power_fault_detected: whether a power fault was detected by the hardware * that has not yet been cleared by the user -* @pending_events: used by the IRQ handler to save events retrieved from the -* Slot Status register for later consumption by the IRQ thread +* @poll_thread: thread to poll for slot events if no IRQ is available, +* enabled with pciehp_poll_mode module parameter * @state: current state machine position * @state_lock: protects reads and writes of @state; * protects scheduling, execution and cancellation of @button_work * @button_work: work item to turn the slot on or off after 5 seconds * in response to an Attention Button press * @hotplug_slot: pointer to the structure registered with the PCI hotplug core +* @reset_lock: prevents access to the Data Link Layer Link Active bit in the +* Link Status register and to the Presence Detect State bit in the Slot +* Status register during a slot reset which may cause them to flap * @request_result: result of last user request submitted to the IRQ thread * @requester: wait queue to wake up on completion of user request, * used for synchronous slot enable/disable request via sysfs
@@ -100,23 +100,28 @@ do { \* unlike other drivers, the two aren't represented by separate structures. */ struct controller { -struct mutex ctrl_lock;struct pcie_device *pcie; -struct rw_semaphore reset_lock; + +u32 slot_cap;/* capabilities and quirks */ +bool link_active_reporting; + +u16 slot_ctrl;/* control register access */ +struct mutex ctrl_lock; +unsigned long cmd_started; +bool cmd_busy;wait_queue_head_t queue; -u32 slot_cap; -u16 slot_ctrl; + +atomic_t pending_events;/* event handling */ +bool notification_enabled; +bool power_fault_detected;struct task_struct *poll_thread; -unsigned long cmd_started;/* jiffies */ -unsigned int cmd_busy:1 ; -unsigned int link_active_reporting:1 ; -unsigned int notification_enabled:1 ; -unsigned int power_fault_detected; -atomic_t pending_events; -u8 state; + +u8 state;/* state machine */ struct mutex state_lock;struct delayed_work button_work; -struct hotplug_slot *hotplug_slot; + +struct hotplug_slot *hotplug_slot;/* hotplug core interface */ +struct rw_semaphore reset_lock;int request_result;wait_queue_head_t requester; };
Signature · 1 line
2.18.0
PATCH 6/9 PCI: hotplug: Constify hotplug_slot_ops
In reply to Lukas WunnerHotplug drivers cannot declare their hotplug_slot_ops const, making them attractive targets for attackers, because upon registration of a hotplug slot, __pci_hp_initialize() writes to the "owner" and "mod_name" members in that struct.
Fix by moving these members to struct hotplug_slot and constify every driver's hotplug_slot_ops except for pciehp.
pciehp constructs its hotplug_slot_ops at runtime based on the PCIe port's capabilities, hence cannot declare them const. It can be converted to __write_rarely once that's mainlined:
http://www.openwall.com/lists/kernel-hardening/2016/11/16/3
--- drivers/pci/hotplug/acpiphp_core.c | 2 +- drivers/pci/hotplug/cpci_hotplug_core.c | 2 +- drivers/pci/hotplug/cpqphp_core.c | 2 +- drivers/pci/hotplug/ibmphp.h | 2 +- drivers/pci/hotplug/ibmphp_core.c | 2 +- drivers/pci/hotplug/pci_hotplug_core.c | 27 +++++++++++++------------ drivers/pci/hotplug/pnv_php.c | 2 +- drivers/pci/hotplug/rpaphp.h | 2 +- drivers/pci/hotplug/rpaphp_core.c | 2 +- drivers/pci/hotplug/s390_pci_hpc.c | 2 +- drivers/pci/hotplug/sgi_hotplug.c | 2 +- drivers/pci/hotplug/shpchp_core.c | 2 +- drivers/pci/pci.c | 4 ++-- drivers/pci/slot.c | 2 +- drivers/platform/x86/asus-wmi.c | 3 +-- drivers/platform/x86/eeepc-laptop.c | 3 +-- include/linux/pci_hotplug.h | 10 ++++----- 17 files changed, 35 insertions(+), 36 deletions(-)
drivers/pci/hotplug/acpiphp_core.c +1 -1
@@ -57,7 +57,7 @@ static int get_attention_status(struct hotplug_slot *slot, u8 *value);static int get_latch_status (struct hotplug_slot *slot,u8 *value);static int get_adapter_status (struct hotplug_slot *slot,u8 *value); -static struct hotplug_slot_ops acpi_hotplug_slot_ops = { +static const struct hotplug_slot_ops acpi_hotplug_slot_ops = { .enable_slot = enable_slot, .disable_slot = disable_slot, .set_attention_status = set_attention_status,
drivers/pci/hotplug/cpci_hotplug_core.c +1 -1
@@ -57,7 +57,7 @@ static int get_attention_status(struct hotplug_slot *slot, u8 *value);static int get_adapter_status (struct hotplug_slot *slot,u8 *value);static int get_latch_status (struct hotplug_slot *slot,u8 *value); -static struct hotplug_slot_ops cpci_hotplug_slot_ops = { +static const struct hotplug_slot_ops cpci_hotplug_slot_ops = { .enable_slot = enable_slot, .disable_slot = disable_slot, .set_attention_status = set_attention_status,
drivers/pci/hotplug/cpqphp_core.c +1 -1
@@ -560,7 +560,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)return 0 ; } -static struct hotplug_slot_ops cpqphp_hotplug_slot_ops = { +static const struct hotplug_slot_ops cpqphp_hotplug_slot_ops = { .set_attention_status = set_attention_status, .enable_slot = process_SI, .disable_slot = process_SS,
drivers/pci/hotplug/ibmphp.h +1 -1
@@ -740,7 +740,7 @@ int ibmphp_do_disable_slot(struct slot *slot_cur);int ibmphp_update_slot_info (struct slot *);/* This function is called from HPC, so we need it to not be be static */ int ibmphp_configure_card (struct pci_func *,u8 );int ibmphp_unconfigure_card (struct slot **,int ); -extern struct hotplug_slot_ops ibmphp_hotplug_slot_ops; +extern const struct hotplug_slot_ops ibmphp_hotplug_slot_ops;#endif //__IBMPHP_H
drivers/pci/hotplug/ibmphp_core.c +1 -1
@@ -1259,7 +1259,7 @@ int ibmphp_do_disable_slot(struct slot *slot_cur) goto exit; } -struct hotplug_slot_ops ibmphp_hotplug_slot_ops = { +const struct hotplug_slot_ops ibmphp_hotplug_slot_ops = { .set_attention_status = set_attention_status, .enable_slot = enable_slot, .disable_slot = ibmphp_disable_slot,
drivers/pci/hotplug/pci_hotplug_core.c +14 -13
@@ -49,15 +49,15 @@ static DEFINE_MUTEX(pci_hp_mutex);#define GET_STATUS (name, type) \ static int get_##name(struct hotplug_slot *slot, type *value) \ { \ - struct hotplug_slot_ops *ops = slot->ops; \ + const struct hotplug_slot_ops *ops = slot->ops; \ int retval = 0; \ - if (!try_module_get(ops->owner)) \ + if (!try_module_get(slot->owner)) \ return -ENODEV; \ if (ops->get_##name) \ retval = ops->get_##name(slot, value); \ else \ *value = slot->info->name; \ - module_put(ops->owner); \ + module_put(slot->owner); \ return retval; \ }
@@ -90,7 +90,7 @@ 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->ops->owner)) { +if (!try_module_get (slot->owner)) { retval = -ENODEV ; goto exit; }
@@ -109,7 +109,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->ops->owner); +module_put (slot->owner); exit:if (retval)
@@ -138,7 +138,8 @@ static ssize_t attention_read_file(struct pci_slot *pci_slot, char *buf)static ssize_t attention_write_file (struct pci_slot *pci_slot,const char *buf,size_t count) { -struct hotplug_slot_ops *ops = pci_slot->hotplug->ops; +struct hotplug_slot *slot = pci_slot->hotplug; +const struct hotplug_slot_ops *ops = slot->ops;unsigned long lattention;u8 attention;int retval =0 ;
@@ -147,13 +148,13 @@ 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 (ops->owner)) { +if (!try_module_get (slot->owner)) { retval = -ENODEV ; goto exit; }if (ops->set_attention_status) - retval = ops->set_attention_status (pci_slot->hotplug, attention); -module_put (ops->owner); + retval = ops->set_attention_status (slot, attention); +module_put (slot->owner); exit:if (retval)
@@ -213,13 +214,13 @@ 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->ops->owner)) { +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->ops->owner); +module_put (slot->owner); exit:if (retval)
@@ -447,8 +448,8 @@ int __pci_hp_initialize(struct hotplug_slot *slot, struct pci_bus *bus,if ((slot->info ==NULL ) || (slot->ops ==NULL ))return -EINVAL ; - slot->ops->owner = owner; - slot->ops->mod_name = mod_name; + slot->owner = owner; + slot->mod_name = mod_name;/* * No problems if we call this interface from both ACPI_PCI_SLOT
drivers/pci/hotplug/pnv_php.c +1 -1
@@ -530,7 +530,7 @@ static int pnv_php_disable_slot(struct hotplug_slot *slot)return ret; } -static struct hotplug_slot_ops php_slot_ops = { +static const struct hotplug_slot_ops php_slot_ops = { .get_power_status = pnv_php_get_power_state, .get_adapter_status = pnv_php_get_adapter_state, .set_attention_status = pnv_php_set_attention_state,
drivers/pci/hotplug/rpaphp.h +1 -1
@@ -70,7 +70,7 @@ struct slot {struct hotplug_slot *hotplug_slot; }; -extern struct hotplug_slot_ops rpaphp_hotplug_slot_ops; +extern const struct hotplug_slot_ops rpaphp_hotplug_slot_ops;extern struct list_head rpaphp_slot_head;/* function prototypes */
drivers/pci/hotplug/rpaphp_core.c +1 -1
@@ -477,7 +477,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)return 0 ; } -struct hotplug_slot_ops rpaphp_hotplug_slot_ops = { +const struct hotplug_slot_ops rpaphp_hotplug_slot_ops = { .enable_slot = enable_slot, .disable_slot = disable_slot, .set_attention_status = set_attention_status,
drivers/pci/hotplug/s390_pci_hpc.c +1 -1
@@ -130,7 +130,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)return 0 ; } -static struct hotplug_slot_ops s390_hotplug_slot_ops = { +static const struct hotplug_slot_ops s390_hotplug_slot_ops = { .enable_slot = enable_slot, .disable_slot = disable_slot, .get_power_status = get_power_status,
drivers/pci/hotplug/sgi_hotplug.c +1 -1
@@ -80,7 +80,7 @@ static int enable_slot(struct hotplug_slot *slot);static int disable_slot (struct hotplug_slot *slot);static inline int get_power_status (struct hotplug_slot *slot,u8 *value); -static struct hotplug_slot_ops sn_hotplug_slot_ops = { +static const struct hotplug_slot_ops sn_hotplug_slot_ops = { .enable_slot = enable_slot, .disable_slot = disable_slot, .get_power_status = get_power_status,
drivers/pci/hotplug/shpchp_core.c +1 -1
@@ -51,7 +51,7 @@ static int get_attention_status(struct hotplug_slot *slot, u8 *value);static int get_latch_status (struct hotplug_slot *slot,u8 *value);static int get_adapter_status (struct hotplug_slot *slot,u8 *value); -static struct hotplug_slot_ops shpchp_hotplug_slot_ops = { +static const struct hotplug_slot_ops shpchp_hotplug_slot_ops = { .set_attention_status = set_attention_status, .enable_slot = enable_slot, .disable_slot = disable_slot,
drivers/pci/pci.c +2 -2
@@ -4570,13 +4570,13 @@ static int pci_reset_hotplug_slot(struct hotplug_slot *hotplug, int probe) {int rc = -ENOTTY ; -if (!hotplug || !try_module_get (hotplug->ops->owner)) +if (!hotplug || !try_module_get (hotplug->owner))return rc;if (hotplug->ops->reset_slot) rc = hotplug->ops->reset_slot (hotplug, probe); -module_put (hotplug->ops->owner); +module_put (hotplug->owner);return rc; }
drivers/pci/slot.c +1 -1
@@ -371,7 +371,7 @@ void pci_hp_create_module_link(struct pci_slot *pci_slot)if (!slot || !slot->ops)return ; - kobj =kset_find_obj (module_kset, slot->ops->mod_name); + kobj =kset_find_obj (module_kset, slot->mod_name);if (!kobj)return ; ret =sysfs_create_link (&pci_slot->kobj, kobj,"module" );
drivers/platform/x86/asus-wmi.c +1 -2
@@ -858,8 +858,7 @@ static int asus_get_adapter_status(struct hotplug_slot *hotplug_slot,return 0 ; } -static struct hotplug_slot_ops asus_hotplug_slot_ops = { - .owner =THIS_MODULE , +static const struct hotplug_slot_ops asus_hotplug_slot_ops = { .get_adapter_status = asus_get_adapter_status, .get_power_status = asus_get_adapter_status, };
drivers/platform/x86/eeepc-laptop.c +1 -2
@@ -726,8 +726,7 @@ static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,return 0 ; } -static struct hotplug_slot_ops eeepc_hotplug_slot_ops = { - .owner =THIS_MODULE , +static const struct hotplug_slot_ops eeepc_hotplug_slot_ops = { .get_adapter_status = eeepc_get_adapter_status, .get_power_status = eeepc_get_adapter_status, };
include/linux/pci_hotplug.h +5 -5
@@ -16,8 +16,6 @@/** * struct hotplug_slot_ops -the callbacks that the hotplug pci core can use -* @owner: The module owner of this structure -* @mod_name: The module name (KBUILD_MODNAME) of this structure * @enable_slot: Called when the user wants to enable a specific pci slot * @disable_slot: Called when the user wants to disable a specific pci slot * @set_attention_status: Called to set the specific slot's attention LED to
@@ -46,8 +44,6 @@* set an LED, enable / disable power, etc.) */ struct hotplug_slot_ops { -struct module *owner; -const char *mod_name;int (*enable_slot) (struct hotplug_slot *slot);int (*disable_slot) (struct hotplug_slot *slot);int (*set_attention_status) (struct hotplug_slot *slot,u8 value);
@@ -82,15 +78,19 @@ struct hotplug_slot_info {* this slot. * @private: used by the hotplug pci controller driver to store whatever it * needs. +* @owner: The module owner of this structure +* @mod_name: The module name (KBUILD_MODNAME) of this structure */ struct hotplug_slot { -struct hotplug_slot_ops *ops; +const struct hotplug_slot_ops *ops;struct hotplug_slot_info *info;void *private;/* 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; };static inline const char *hotplug_slot_name (const struct hotplug_slot *slot)
Signature · 1 line
2.18.0
Re: [PATCH 6/9] PCI: hotplug: Constify hotplug_slot_ops
Quoted 38 lines · Lukas Wunner
Hotplug drivers cannot declare their
hotplug_slot_opsconst, making them attractive targets for attackers, because upon registration of a hotplug slot,__pci_hp_initialize()writes to the "owner" and "mod_name" members in that struct.Fix by moving these members to struct
hotplug_slotand constify every driver'shotplug_slot_opsexcept for pciehp.pciehp constructs its
hotplug_slot_opsat runtime based on the PCIe port's capabilities, hence cannot declare them const. It can be converted to__write_rarelyonce that's mainlined:
http://www.openwall.com/lists/kernel-hardening/2016/11/16/3Signed-off-by Lukas Wunner <[email protected]>Cc Rafael J. Wysocki <[email protected]>Cc Len Brown <[email protected]>Cc Scott Murray <[email protected]>Cc Benjamin Herrenschmidt <[email protected]>Cc Paul Mackerras <[email protected]>Cc Michael Ellerman <[email protected]>Cc Gavin Shan <[email protected]>Cc Sebastian Ott <[email protected]>Cc Gerald Schaefer <[email protected]>Cc Corentin Chary <[email protected]>Cc Darren Hart <[email protected]>Cc Andy Shevchenko <[email protected]>--- drivers/pci/hotplug/acpiphp_core.c | 2 +- drivers/pci/hotplug/cpci_hotplug_core.c | 2 +- drivers/pci/hotplug/cpqphp_core.c | 2 +- drivers/pci/hotplug/ibmphp.h | 2 +- drivers/pci/hotplug/ibmphp_core.c | 2 +- drivers/pci/hotplug/pci_hotplug_core.c | 27 +++++++++++++------------ drivers/pci/hotplug/pnv_php.c | 2 +- drivers/pci/hotplug/rpaphp.h | 2 +- drivers/pci/hotplug/rpaphp_core.c | 2 +- drivers/pci/hotplug/s390_pci_hpc.c | 2 +-
Quoted 8 lines
drivers/pci/hotplug/sgi_hotplug.c | 2 +- drivers/pci/hotplug/shpchp_core.c | 2 +- drivers/pci/pci.c | 4 ++-- drivers/pci/slot.c | 2 +- drivers/platform/x86/asus-wmi.c | 3 +-- drivers/platform/x86/eeepc-laptop.c | 3 +-- include/linux/pci_hotplug.h | 10 ++++----- 17 files changed, 35 insertions(+), 36 deletions(-)
Nice!
Re: [PATCH 6/9] PCI: hotplug: Constify hotplug_slot_ops
In reply to Lukas WunnerQuoted 26 lines · Lukas Wunner
Hotplug drivers cannot declare their
hotplug_slot_opsconst, making them attractive targets for attackers, because upon registration of a hotplug slot,__pci_hp_initialize()writes to the "owner" and "mod_name" members in that struct.Fix by moving these members to struct
hotplug_slotand constify every driver'shotplug_slot_opsexcept for pciehp.pciehp constructs its
hotplug_slot_opsat runtime based on the PCIe port's capabilities, hence cannot declare them const. It can be converted to__write_rarelyonce that's mainlined:
http://www.openwall.com/lists/kernel-hardening/2016/11/16/3Signed-off-by Lukas Wunner <[email protected]>Cc Rafael J. Wysocki <[email protected]>Cc Len Brown <[email protected]>Cc Scott Murray <[email protected]>Cc Benjamin Herrenschmidt <[email protected]>Cc Paul Mackerras <[email protected]>Cc Michael Ellerman <[email protected]>Cc Gavin Shan <[email protected]>Cc Sebastian Ott <[email protected]>Cc Gerald Schaefer <[email protected]>Cc Corentin Chary <[email protected]>Cc Darren Hart <[email protected]>Cc Andy Shevchenko <[email protected]>
Quoted 1 line
---
With regards to drivers/pci/hotplug/rpa*
PATCH 7/9 PCI: hotplug: Drop hotplug_slot_info
In reply to Lukas WunnerEver since the PCI hotplug core was introduced in 2002, drivers had to allocate and register a struct hotplug_slot_info for every slot:
https://git.kernel.org/tglx/history/c/a8a2069f432c
Apparently the idea was that drivers furnish the hotplug core with an up-to-date card presence status, power status, latch status and attention indicator status as well as notify the hotplug core of changes thereof. However only 4 out of 12 hotplug drivers bother to notify the hotplug core with pci_hp_change_slot_info() and the hotplug core never made any use of the information: There is just a single macro in pci_hotplug_core.c, GET_STATUS(), which uses the hotplug_slot_info if the driver lacks the corresponding callback in hotplug_slot_ops. The macro is called when the user reads the attribute via sysfs.
Now, if the callback isn't defined, the attribute isn't exposed in sysfs in the first place (see e.g. has_power_file()). There are only two situations when the hotplug_slot_info would actually be accessed:
* If the driver defines ->enable_slot or ->disable_slot but not ->get_power_status.
* If the driver defines ->set_attention_status but not ->get_attention_status.
There is no driver doing the former and just a single driver doing the latter, namely pnv_php.c. Amend it with a ->get_attention_status callback. With that, the hotplug_slot_info becomes completely unused by the PCI hotplug core. But a few drivers use it internally as a cache:
cpcihp uses it to cache the latch_status and adapter_status. cpqhp uses it to cache the adapter_status.pnv_php and rpaphp use it to cache the attention_status. shpchp uses it to cache all four values.
Amend these drivers to cache the information in their private slot struct. shpchp's slot struct already contains members to cache the power_status and adapter_status, so additional members are only needed for the other two values. In the case of cpqphp, the cached value is only accessed in a single place, so instead of caching it, read the current value from the hardware.
Caution: acpiphp, cpci, cpqhp, shpchp, asus-wmi and eeepc-laptop populate the hotplug_slot_info with initial values on probe. That code is herewith removed. There is a theoretical chance that the code has side effects without which the driver fails to function, e.g. if the ACPI method to read the adapter status needs to be executed at least once on probe. That seems unlikely to me, still maintainers should review the changes carefully for this possibility.
--- arch/powerpc/include/asm/pnv-pci.h | 2 +- drivers/pci/hotplug/acpiphp.h | 1 - drivers/pci/hotplug/acpiphp_core.c | 6 --- drivers/pci/hotplug/cpci_hotplug.h | 2 + drivers/pci/hotplug/cpci_hotplug_core.c | 72 +++++-------------------- drivers/pci/hotplug/cpqphp_core.c | 22 +------- drivers/pci/hotplug/cpqphp_ctrl.c | 31 +---------- drivers/pci/hotplug/ibmphp_core.c | 27 +--------- drivers/pci/hotplug/ibmphp_ebda.c | 33 ------------ drivers/pci/hotplug/pci_hotplug_core.c | 26 +-------- drivers/pci/hotplug/pciehp_core.c | 8 --- drivers/pci/hotplug/pnv_php.c | 24 ++++++--- drivers/pci/hotplug/rpaphp.h | 1 + drivers/pci/hotplug/rpaphp_core.c | 4 +- drivers/pci/hotplug/rpaphp_pci.c | 11 +--- drivers/pci/hotplug/rpaphp_slot.c | 9 +--- drivers/pci/hotplug/s390_pci_hpc.c | 12 ----- drivers/pci/hotplug/sgi_hotplug.c | 9 ---- drivers/pci/hotplug/shpchp.h | 2 + drivers/pci/hotplug/shpchp_core.c | 31 ++++------- drivers/pci/hotplug/shpchp_ctrl.c | 21 ++------ drivers/platform/x86/asus-wmi.c | 10 ---- drivers/platform/x86/eeepc-laptop.c | 10 ---- include/linux/pci_hotplug.h | 30 ----------- 24 files changed, 64 insertions(+), 340 deletions(-)
arch/powerpc/include/asm/pnv-pci.h +1 -1
@@ -54,7 +54,6 @@ void pnv_cxl_release_hwirq_ranges(struct cxl_irq_ranges *irqs,struct pnv_php_slot {struct hotplug_slot slot; -struct hotplug_slot_info slot_info;uint64_t id;char *name;int slot_no;
@@ -72,6 +71,7 @@ struct pnv_php_slot {struct pci_dev *pdev;struct pci_bus *bus;bool power_state_check; +u8 attention_state;void *fdt;void *dt;struct of_changeset ocs;
drivers/pci/hotplug/acpiphp.h +0 -1
@@ -35,7 +35,6 @@ struct acpiphp_slot;struct slot {struct hotplug_slot *hotplug_slot;struct acpiphp_slot *acpi_slot; -struct hotplug_slot_info info;unsigned int sun;/* ACPI _SUN (Slot User Number) value */ };
drivers/pci/hotplug/acpiphp_core.c +0 -6
@@ -270,16 +270,10 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot,if (!slot->hotplug_slot) goto error_slot; - slot->hotplug_slot->info = &slot->info; - slot->hotplug_slot->private = slot; slot->hotplug_slot->ops = &acpi_hotplug_slot_ops; slot->acpi_slot = acpiphp_slot; - slot->hotplug_slot->info->power_status =acpiphp_get_power_status (slot->acpi_slot); - slot->hotplug_slot->info->attention_status =0 ; - slot->hotplug_slot->info->latch_status =acpiphp_get_latch_status (slot->acpi_slot); - slot->hotplug_slot->info->adapter_status =acpiphp_get_adapter_status (slot->acpi_slot); acpiphp_slot->slot = slot; slot->sun = sun;
drivers/pci/hotplug/cpci_hotplug.h +2 -0
@@ -32,6 +32,8 @@ struct slot {unsigned int devfn;struct pci_bus *bus;struct pci_dev *dev; +bool latch_status; +bool adapter_status;unsigned int extracting;struct hotplug_slot *hotplug_slot;struct list_head slot_list;
drivers/pci/hotplug/cpci_hotplug_core.c +14 -58
153 lines not on this page · raw message
drivers/pci/hotplug/cpqphp_core.c +1 -21
@@ -276,7 +276,6 @@ static int ctrl_slot_cleanup(struct controller *ctrl)while (old_slot) { next_slot = old_slot->next;pci_hp_deregister (old_slot->hotplug_slot); -kfree (old_slot->hotplug_slot->info);kfree (old_slot->hotplug_slot);kfree (old_slot); old_slot = next_slot;
@@ -579,7 +578,6 @@ static int ctrl_slot_setup(struct controller *ctrl, {struct slot *slot;struct hotplug_slot *hotplug_slot; -struct hotplug_slot_info *hotplug_slot_info;struct pci_bus *bus = ctrl->pci_bus;u8 number_of_slots;u8 slot_device;
@@ -613,14 +611,6 @@ static int ctrl_slot_setup(struct controller *ctrl, } hotplug_slot = slot->hotplug_slot; - hotplug_slot->info =kzalloc (sizeof (*(hotplug_slot->info)), -GFP_KERNEL ); -if (!hotplug_slot->info) { - result = -ENOMEM ; - goto error_hpslot; - } - hotplug_slot_info = hotplug_slot->info; - slot->ctrl = ctrl; slot->bus = ctrl->bus; slot->device = slot_device;
@@ -673,14 +663,6 @@ static int ctrl_slot_setup(struct controller *ctrl,snprintf (name,SLOT_NAME_SIZE ,"%u" , slot->number); hotplug_slot->ops = &cpqphp_hotplug_slot_ops; - hotplug_slot_info->power_status =get_slot_enabled (ctrl, slot); - hotplug_slot_info->attention_status = -cpq_get_attention_status (ctrl, slot); - hotplug_slot_info->latch_status = -cpq_get_latch_status (ctrl, slot); - hotplug_slot_info->adapter_status = -get_presence_status (ctrl, slot); - dbg("registering bus %d, dev %d, number %d, ctrl->slot_device_offset %d, slot %d\n", slot->bus, slot->device, slot->number, ctrl->slot_device_offset,
@@ -691,7 +673,7 @@ static int ctrl_slot_setup(struct controller *ctrl, name);if (result) {err ("pci_hp_register failed with error %d\n" , result); - goto error_info; + goto error_hpslot; } slot->next = ctrl->slot;
@@ -703,8 +685,6 @@ static int ctrl_slot_setup(struct controller *ctrl, }return 0 ; -error_info: -kfree (hotplug_slot_info); error_hpslot:kfree (hotplug_slot); error_slot:
drivers/pci/hotplug/cpqphp_ctrl.c +2 -29
@@ -1130,9 +1130,9 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_for (slot = ctrl->slot; slot; slot = slot->next) {if (slot->device == (hp_slot + ctrl->slot_device_offset))continue ; -if (!slot->hotplug_slot || !slot->hotplug_slot->info) +if (!slot->hotplug_slot)continue ; -if (slot->hotplug_slot->info->adapter_status ==0 ) +if (get_presence_status (ctrl, slot) ==0 )continue ;/* If another adapter is running on the same segment but at a * lower speed/mode, we allow the new adapter to function at
@@ -1767,24 +1767,6 @@ void cpqhp_event_stop_thread(void) } -static int update_slot_info (struct controller *ctrl,struct slot *slot) -{ -struct hotplug_slot_info *info; -int result; - - info =kmalloc (sizeof (*info),GFP_KERNEL ); -if (!info) -return -ENOMEM ; - - info->power_status =get_slot_enabled (ctrl, slot); - info->attention_status =cpq_get_attention_status (ctrl, slot); - info->latch_status =cpq_get_latch_status (ctrl, slot); - info->adapter_status =get_presence_status (ctrl, slot); - result =pci_hp_change_slot_info (slot->hotplug_slot, info); -kfree (info); -return result; -} -static void interrupt_event_handler (struct controller *ctrl) {int loop =0 ;
@@ -1884,9 +1866,6 @@ static void interrupt_event_handler(struct controller *ctrl)/***********POWER FAULT */ else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) {dbg ("power fault\n" ); - } else { -/* refresh notification */ -update_slot_info (ctrl, p_slot); } ctrl->event_queue[loop].event_type =0 ;
@@ -2057,9 +2036,6 @@ int cpqhp_process_SI(struct controller *ctrl, struct pci_func *func)if (rc)dbg ("%s: rc = %d\n" , __func__, rc); -if (p_slot) -update_slot_info (ctrl, p_slot); -return rc; }
@@ -2125,9 +2101,6 @@ int cpqhp_process_SS(struct controller *ctrl, struct pci_func *func) rc =1 ; } -if (p_slot) -update_slot_info (ctrl, p_slot); -return rc; }
drivers/pci/hotplug/ibmphp_core.c +2 -25
@@ -582,29 +582,10 @@ static int validate(struct slot *slot_cur, int opn)****************************************************************************/ int ibmphp_update_slot_info (struct slot *slot_cur) { -struct hotplug_slot_info *info;struct pci_bus *bus = slot_cur->hotplug_slot->pci_slot->bus; -int rc;u8 bus_speed;u8 mode; - info =kmalloc (sizeof (struct hotplug_slot_info ),GFP_KERNEL ); -if (!info) -return -ENOMEM ; - - info->power_status =SLOT_PWRGD (slot_cur->status); - info->attention_status =SLOT_ATTN (slot_cur->status, - slot_cur->ext_status); - info->latch_status =SLOT_LATCH (slot_cur->status); -if (!SLOT_PRESENT (slot_cur->status)) { - info->adapter_status =0 ; -/* info->max_adapter_speed_status = MAX_ADAPTER_NONE; */ - }else { - info->adapter_status =1 ; -/* get_max_adapter_speed_1(slot_cur->hotplug_slot, -&info->max_adapter_speed_status, 0); */ - } - bus_speed = slot_cur->bus_on->current_speed; mode = slot_cur->bus_on->current_bus_mode;
@@ -630,9 +611,7 @@ int ibmphp_update_slot_info(struct slot *slot_cur) bus->cur_bus_speed = bus_speed;// To do: bus_names - rc =pci_hp_change_slot_info (slot_cur->hotplug_slot, info); -kfree (info); -return rc; +return 0 ; }
@@ -684,7 +663,6 @@ static void free_slots(void)ibmphp_unconfigure_card (&slot_cur,-1 );pci_hp_destroy (slot_cur->hotplug_slot); -kfree (slot_cur->hotplug_slot->info);kfree (slot_cur->hotplug_slot);kfree (slot_cur); }
@@ -1095,8 +1073,7 @@ static int enable_slot(struct hotplug_slot *hs) slot_cur->func =kzalloc (sizeof (struct pci_func ),GFP_KERNEL );if (!slot_cur->func) { -/* We cannot do update_slot_info here, since no memory for -* kmalloc n.e.ways, and update_slot_info allocates some */ +/* do update_slot_info here? */ rc = -ENOMEM ; goto error_power; }
drivers/pci/hotplug/ibmphp_ebda.c +0 -33
@@ -671,31 +671,6 @@ static int fillslotinfo(struct hotplug_slot *hotplug_slot) slot = hotplug_slot->private; rc =ibmphp_hpc_readslot (slot,READ_ALLSTAT ,NULL ); -if (rc) -return rc; - -// power - enabled:1 not:0 - hotplug_slot->info->power_status =SLOT_POWER (slot->status); - -// attention - off:0, on:1, blinking:2 - hotplug_slot->info->attention_status =SLOT_ATTN (slot->status, slot->ext_status); - -// latch - open:1 closed:0 - hotplug_slot->info->latch_status =SLOT_LATCH (slot->status); - -// pci board - present:1 not:0 -if (SLOT_PRESENT (slot->status)) - hotplug_slot->info->adapter_status =1 ; -else - hotplug_slot->info->adapter_status =0 ; -/* -if (slot->bus_on->supported_bus_mode -&& (slot->bus_on->supported_speed == BUS_SPEED_66)) -hotplug_slot->info->max_bus_speed_status = BUS_SPEED_66PCIX; -else -hotplug_slot->info->max_bus_speed_status = slot->bus_on->supported_speed; -*/ -return rc; }
@@ -877,12 +852,6 @@ static int __init ebda_rsrc_controller(void) goto error_no_hp_slot; } - hp_slot_ptr->info =kzalloc (sizeof (struct hotplug_slot_info ),GFP_KERNEL ); -if (!hp_slot_ptr->info) { - rc = -ENOMEM ; - goto error_no_hp_info; - } - tmp_slot =kzalloc (sizeof (*tmp_slot),GFP_KERNEL );if (!tmp_slot) { rc = -ENOMEM ;
@@ -955,8 +924,6 @@ static int __init ebda_rsrc_controller(void) error:kfree (hp_slot_ptr->private); error_no_slot: -kfree (hp_slot_ptr->info); -error_no_hp_info:kfree (hp_slot_ptr); error_no_hp_slot:free_ebda_hpc (hpc_ptr);
drivers/pci/hotplug/pci_hotplug_core.c +1 -25
@@ -55,8 +55,6 @@ static int get_##name(struct hotplug_slot *slot, type *value) \return -ENODEV ; \ if (ops->get_##name) \ retval = ops->get_##name(slot, value); \ - else \ - *value = slot->info->name; \ module_put(slot->owner); \ return retval; \ }
@@ -445,7 +443,7 @@ int __pci_hp_initialize(struct hotplug_slot *slot, struct pci_bus *bus,if (slot ==NULL )return -ENODEV ; -if ((slot->info ==NULL ) || (slot->ops ==NULL )) +if (slot->ops ==NULL )return -EINVAL ; slot->owner = owner;
@@ -560,28 +558,6 @@ void pci_hp_destroy(struct hotplug_slot *slot) }EXPORT_SYMBOL_GPL (pci_hp_destroy); -/** -* pci_hp_change_slot_info - changes the slot's information structure in the core -* @slot: pointer to the slot whose info has changed -* @info: pointer to the info copy into the slot's info structure -* -* @slot must have been registered with the pci -* hotplug subsystem previously with a call to pci_hp_register(). -* -* Returns 0 if successful, anything else for an error. -*/ -int pci_hp_change_slot_info (struct hotplug_slot *slot, -struct hotplug_slot_info *info) -{ -if (!slot || !info) -return -ENODEV ; - -memcpy (slot->info, info,sizeof (struct hotplug_slot_info )); - -return 0 ; -} -EXPORT_SYMBOL_GPL (pci_hp_change_slot_info); -static int __init pci_hotplug_init (void ) {int result;
drivers/pci/hotplug/pciehp_core.c +0 -8
@@ -52,7 +52,6 @@ static int get_adapter_status(struct hotplug_slot *slot, u8 *value);static int init_slot (struct controller *ctrl) {struct hotplug_slot *hotplug =NULL ; -struct hotplug_slot_info *info =NULL ;struct hotplug_slot_ops *ops =NULL ;char name[SLOT_NAME_SIZE ];int retval = -ENOMEM ;
@@ -61,10 +60,6 @@ static int init_slot(struct controller *ctrl)if (!hotplug) goto out; - info =kzalloc (sizeof (*info),GFP_KERNEL ); -if (!info) - goto out; -/* Setup hotplug slot ops */ ops =kzalloc (sizeof (*ops),GFP_KERNEL );if (!ops)
@@ -86,7 +81,6 @@ static int init_slot(struct controller *ctrl) }/* register this slot with the hotplug pci core */ - hotplug->info = info; hotplug->private = ctrl; hotplug->ops = ops; ctrl->hotplug_slot = hotplug;
@@ -99,7 +93,6 @@ static int init_slot(struct controller *ctrl) out:if (retval) {kfree (ops); -kfree (info);kfree (hotplug); }return retval;
@@ -111,7 +104,6 @@ static void cleanup_slot(struct controller *ctrl)pci_hp_destroy (hotplug_slot);kfree (hotplug_slot->ops); -kfree (hotplug_slot->info);kfree (hotplug_slot); }
drivers/pci/hotplug/pnv_php.c +18 -6
@@ -328,6 +328,11 @@ static int pnv_php_add_devtree(struct pnv_php_slot *php_slot)return ret; } +static inline struct pnv_php_slot *to_pnv_php_slot (struct hotplug_slot *slot) +{ + return container_of(slot, struct pnv_php_slot, slot); +} +int pnv_php_set_slot_power_state (struct hotplug_slot *slot,uint8_t state) {
@@ -378,7 +383,6 @@ static int pnv_php_get_power_state(struct hotplug_slot *slot, u8 *state) ret); }else { *state = power_state; - slot->info->power_status = power_state; }return 0 ;
@@ -397,7 +401,6 @@ static int pnv_php_get_adapter_state(struct hotplug_slot *slot, u8 *state) ret =pnv_pci_get_presence_state (php_slot->id, &presence);if (ret >=0 ) { *state = presence; - slot->info->adapter_status = presence; ret =0 ; }else {pci_warn (php_slot->pdev,"Error %d getting presence\n" , ret);
@@ -406,10 +409,20 @@ static int pnv_php_get_adapter_state(struct hotplug_slot *slot, u8 *state)return ret; } +static int pnv_php_get_attention_state (struct hotplug_slot *slot,u8 *state) +{ +struct pnv_php_slot *php_slot =to_pnv_php_slot (slot); + + *state = php_slot->attention_state; +return 0 ; +} +static int pnv_php_set_attention_state (struct hotplug_slot *slot,u8 state) { +struct pnv_php_slot *php_slot =to_pnv_php_slot (slot); +/* FIXME: Make it real once firmware supports it */ - slot->info->attention_status = state; + php_slot->attention_state = state;return 0 ; }
@@ -501,8 +514,7 @@ static int pnv_php_enable(struct pnv_php_slot *php_slot, bool rescan)static int pnv_php_enable_slot (struct hotplug_slot *slot) { -struct pnv_php_slot *php_slot =container_of (slot, - struct pnv_php_slot, slot); +struct pnv_php_slot *php_slot =to_pnv_php_slot (slot);return pnv_php_enable (php_slot, true); }
@@ -533,6 +545,7 @@ static int pnv_php_disable_slot(struct hotplug_slot *slot)static const struct hotplug_slot_ops php_slot_ops = { .get_power_status = pnv_php_get_power_state, .get_adapter_status = pnv_php_get_adapter_state, + .get_attention_status = pnv_php_get_attention_state, .set_attention_status = pnv_php_set_attention_state, .enable_slot = pnv_php_enable_slot, .disable_slot = pnv_php_disable_slot,
@@ -594,7 +607,6 @@ static struct pnv_php_slot *pnv_php_alloc_slot(struct device_node *dn) php_slot->id = id; php_slot->power_state_check = false; php_slot->slot.ops = &php_slot_ops; - php_slot->slot.info = &php_slot->slot_info; php_slot->slot.private = php_slot;INIT_LIST_HEAD (&php_slot->children);
drivers/pci/hotplug/rpaphp.h +1 -0
@@ -63,6 +63,7 @@ struct slot {u32 index;u32 type;u32 power_domain; +u8 attention_status;char *name;struct device_node *dn;struct pci_bus *bus;
drivers/pci/hotplug/rpaphp_core.c +2 -2
@@ -66,7 +66,7 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value) rc =rtas_set_indicator (DR_INDICATOR , slot->index, value);if (!rc) - hotplug_slot->info->attention_status = value; + slot->attention_status = value;return rc; }
@@ -95,7 +95,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)static int get_attention_status (struct hotplug_slot *hotplug_slot,u8 *value) {struct slot *slot = (struct slot *)hotplug_slot->private; - *value = slot->hotplug_slot->info->attention_status; + *value = slot->attention_status;return 0 ; }
drivers/pci/hotplug/rpaphp_pci.c +2 -9
@@ -54,25 +54,21 @@ int rpaphp_get_sensor_state(struct slot *slot, int *state)* rpaphp_enable_slot - record slot state, config pci device * @slot: target &slot * -* Initialize values in the slot, and the hotplug_slot info -* structures to indicate if there is a pci card plugged into -* the slot. If the slot is not empty, run the pcibios routine +* Initialize values in the slot structure to indicate if there is a pci card +* plugged into the slot. If the slot is not empty, run the pcibios routine * to get pcibios stuff correctly set up. */ int rpaphp_enable_slot (struct slot *slot) {int rc, level, state;struct pci_bus *bus; -struct hotplug_slot_info *info = slot->hotplug_slot->info; - info->adapter_status =NOT_VALID ; slot->state =EMPTY ;/* Find out if the power is turned on for the slot */ rc =rtas_get_power_level (slot->power_domain, &level);if (rc)return rc; - info->power_status = level;/* Figure out if there is an adapter in the slot */ rc =rpaphp_get_sensor_state (slot, &state);
@@ -85,13 +81,11 @@ int rpaphp_enable_slot(struct slot *slot)return -EINVAL ; } - info->adapter_status =EMPTY ; slot->bus = bus; slot->pci_devs = &bus->devices;/* if there's an adapter in the slot, go add the pci devices */ if (state ==PRESENT ) { - info->adapter_status =NOT_CONFIGURED ; slot->state =NOT_CONFIGURED ;/* non-empty slot has to have child */
@@ -105,7 +99,6 @@ int rpaphp_enable_slot(struct slot *slot)pci_hp_add_devices (bus);if (!list_empty (&bus->devices)) { - info->adapter_status =CONFIGURED ; slot->state =CONFIGURED ; }
drivers/pci/hotplug/rpaphp_slot.c +1 -8
@@ -21,7 +21,6 @@/* free up the memory used by a slot */ void dealloc_slot_struct (struct slot *slot) { -kfree (slot->hotplug_slot->info);kfree (slot->name);kfree (slot->hotplug_slot);kfree (slot);
@@ -38,13 +37,9 @@ struct slot *alloc_slot_struct(struct device_node *dn, slot->hotplug_slot =kzalloc (sizeof (struct hotplug_slot ),GFP_KERNEL );if (!slot->hotplug_slot) goto error_slot; - slot->hotplug_slot->info =kzalloc (sizeof (struct hotplug_slot_info ), -GFP_KERNEL ); -if (!slot->hotplug_slot->info) - goto error_hpslot; slot->name =kstrdup (drc_name,GFP_KERNEL );if (!slot->name) - goto error_info; + goto error_hpslot; slot->dn = dn; slot->index = drc_index; slot->power_domain = power_domain;
@@ -53,8 +48,6 @@ struct slot *alloc_slot_struct(struct device_node *dn,return (slot); -error_info: -kfree (slot->hotplug_slot->info); error_hpslot:kfree (slot->hotplug_slot); error_slot:
drivers/pci/hotplug/s390_pci_hpc.c +0 -12
@@ -140,7 +140,6 @@ static const struct hotplug_slot_ops s390_hotplug_slot_ops = {int zpci_init_slot (struct zpci_dev *zdev) {struct hotplug_slot *hotplug_slot; -struct hotplug_slot_info *info;char name[SLOT_NAME_SIZE ];struct slot *slot;int rc;
@@ -160,16 +159,8 @@ int zpci_init_slot(struct zpci_dev *zdev) slot->hotplug_slot = hotplug_slot; slot->zdev = zdev; - info =kzalloc (sizeof (*info),GFP_KERNEL ); -if (!info) - goto error_info; - hotplug_slot->info = info; - hotplug_slot->ops = &s390_hotplug_slot_ops; -get_power_status (hotplug_slot, &info->power_status); -get_adapter_status (hotplug_slot, &info->adapter_status); -snprintf (name,SLOT_NAME_SIZE ,"%08x" , zdev->fid); rc =pci_hp_register (slot->hotplug_slot, zdev->bus,ZPCI_DEVFN , name);
@@ -180,8 +171,6 @@ int zpci_init_slot(struct zpci_dev *zdev)return 0 ; error_reg: -kfree (info); -error_info:kfree (hotplug_slot); error_hp:kfree (slot);
@@ -199,7 +188,6 @@ void zpci_exit_slot(struct zpci_dev *zdev)continue ;list_del (&slot->slot_list);pci_hp_deregister (slot->hotplug_slot); -kfree (slot->hotplug_slot->info);kfree (slot->hotplug_slot);kfree (slot); }
drivers/pci/hotplug/sgi_hotplug.c +0 -9
@@ -585,7 +585,6 @@ static inline int get_power_status(struct hotplug_slot *bss_hotplug_slot,static void sn_release_slot (struct hotplug_slot *bss_hotplug_slot) { -kfree (bss_hotplug_slot->info);kfree (bss_hotplug_slot->private);kfree (bss_hotplug_slot); }
@@ -614,14 +613,6 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus) goto alloc_err; } - bss_hotplug_slot->info = -kzalloc (sizeof (struct hotplug_slot_info ), -GFP_KERNEL ); -if (!bss_hotplug_slot->info) { - rc = -ENOMEM ; - goto alloc_err; - } -if (sn_hp_slot_private_alloc (bss_hotplug_slot, pci_bus, device, name)) { rc = -ENOMEM ;
drivers/pci/hotplug/shpchp.h +2 -0
@@ -67,7 +67,9 @@ struct slot {u32 number;u8 is_a_board;u8 state; +u8 attention_save;u8 presence_save; +u8 latch_save;u8 pwr_save;struct controller *ctrl;const struct hpc_ops *hpc_ops;
drivers/pci/hotplug/shpchp_core.c +10 -21
@@ -65,7 +65,6 @@ static int init_slots(struct controller *ctrl) {struct slot *slot;struct hotplug_slot *hotplug_slot; -struct hotplug_slot_info *info;char name[SLOT_NAME_SIZE ];int retval;int i;
@@ -84,13 +83,6 @@ static int init_slots(struct controller *ctrl) } slot->hotplug_slot = hotplug_slot; - info =kzalloc (sizeof (*info),GFP_KERNEL ); -if (!info) { - retval = -ENOMEM ; - goto error_hpslot; - } - hotplug_slot->info = info; - slot->hp_slot = i; slot->ctrl = ctrl; slot->bus = ctrl->pci_dev->subordinate->number;
@@ -101,7 +93,7 @@ static int init_slots(struct controller *ctrl) slot->wq =alloc_workqueue ("shpchp-%d" ,0 ,0 , slot->number);if (!slot->wq) { retval = -ENOMEM ; - goto error_info; + goto error_hpslot; }mutex_init (&slot->lock);
@@ -124,10 +116,10 @@ static int init_slots(struct controller *ctrl) goto error_slotwq; } -get_power_status (hotplug_slot, &info->power_status); -get_attention_status (hotplug_slot, &info->attention_status); -get_latch_status (hotplug_slot, &info->latch_status); -get_adapter_status (hotplug_slot, &info->adapter_status); +get_power_status (hotplug_slot, &slot->pwr_save); +get_attention_status (hotplug_slot, &slot->attention_save); +get_latch_status (hotplug_slot, &slot->latch_save); +get_adapter_status (hotplug_slot, &slot->presence_save);list_add (&slot->slot_list, &ctrl->slot_list); }
@@ -135,8 +127,6 @@ static int init_slots(struct controller *ctrl)return 0 ; error_slotwq:destroy_workqueue (slot->wq); -error_info: -kfree (info); error_hpslot:kfree (hotplug_slot); error_slot:
@@ -154,7 +144,6 @@ void cleanup_slots(struct controller *ctrl)cancel_delayed_work (&slot->work);destroy_workqueue (slot->wq);pci_hp_deregister (slot->hotplug_slot); -kfree (slot->hotplug_slot->info);kfree (slot->hotplug_slot);kfree (slot); }
@@ -170,7 +159,7 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)ctrl_dbg (slot->ctrl,"%s: physical_slot = %s\n" , __func__,slot_name (slot)); - hotplug_slot->info->attention_status = status; + slot->attention_save = status; slot->hpc_ops->set_attention_status (slot, status);return 0 ;
@@ -206,7 +195,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) retval = slot->hpc_ops->get_power_status (slot, value);if (retval <0 ) - *value = hotplug_slot->info->power_status; + *value = slot->pwr_save;return 0 ; }
@@ -221,7 +210,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) retval = slot->hpc_ops->get_attention_status (slot, value);if (retval <0 ) - *value = hotplug_slot->info->attention_status; + *value = slot->attention_save;return 0 ; }
@@ -236,7 +225,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) retval = slot->hpc_ops->get_latch_status (slot, value);if (retval <0 ) - *value = hotplug_slot->info->latch_status; + *value = slot->latch_save;return 0 ; }
@@ -251,7 +240,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) retval = slot->hpc_ops->get_adapter_status (slot, value);if (retval <0 ) - *value = hotplug_slot->info->adapter_status; + *value = slot->presence_save;return 0 ; }
drivers/pci/hotplug/shpchp_ctrl.c +5 -16
@@ -446,23 +446,12 @@ void shpchp_queue_pushbutton_work(struct work_struct *work)mutex_unlock (&p_slot->lock); } -static int update_slot_info (struct slot *slot) +static void update_slot_info (struct slot *slot) { -struct hotplug_slot_info *info; -int result; - - info =kmalloc (sizeof (*info),GFP_KERNEL ); -if (!info) -return -ENOMEM ; - - slot->hpc_ops->get_power_status (slot, &(info->power_status)); - slot->hpc_ops->get_attention_status (slot, &(info->attention_status)); - slot->hpc_ops->get_latch_status (slot, &(info->latch_status)); - slot->hpc_ops->get_adapter_status (slot, &(info->adapter_status)); - - result =pci_hp_change_slot_info (slot->hotplug_slot, info); -kfree (info); -return result; + slot->hpc_ops->get_power_status (slot, &slot->pwr_save); + slot->hpc_ops->get_attention_status (slot, &slot->attention_save); + slot->hpc_ops->get_latch_status (slot, &slot->latch_save); + slot->hpc_ops->get_adapter_status (slot, &slot->presence_save); }/*
drivers/platform/x86/asus-wmi.c +0 -10
@@ -892,15 +892,8 @@ static int asus_setup_pci_hotplug(struct asus_wmi *asus)if (!asus->hotplug_slot) goto error_slot; - asus->hotplug_slot->info =kzalloc (sizeof (struct hotplug_slot_info ), -GFP_KERNEL ); -if (!asus->hotplug_slot->info) - goto error_info; - asus->hotplug_slot->private = asus; asus->hotplug_slot->ops = &asus_hotplug_slot_ops; -asus_get_adapter_status (asus->hotplug_slot, - &asus->hotplug_slot->info->adapter_status); ret =pci_hp_register (asus->hotplug_slot, bus,0 ,"asus-wifi" );if (ret) {
@@ -911,8 +904,6 @@ static int asus_setup_pci_hotplug(struct asus_wmi *asus)return 0 ; error_register: -kfree (asus->hotplug_slot->info); -error_info:kfree (asus->hotplug_slot); asus->hotplug_slot =NULL ; error_slot:
@@ -1045,7 +1036,6 @@ static void asus_wmi_rfkill_exit(struct asus_wmi *asus)asus_rfkill_hotplug (asus);if (asus->hotplug_slot) {pci_hp_deregister (asus->hotplug_slot); -kfree (asus->hotplug_slot->info);kfree (asus->hotplug_slot); }if (asus->hotplug_workqueue)
drivers/platform/x86/eeepc-laptop.c +0 -10
@@ -745,15 +745,8 @@ static int eeepc_setup_pci_hotplug(struct eeepc_laptop *eeepc)if (!eeepc->hotplug_slot) goto error_slot; - eeepc->hotplug_slot->info =kzalloc (sizeof (struct hotplug_slot_info ), -GFP_KERNEL ); -if (!eeepc->hotplug_slot->info) - goto error_info; - eeepc->hotplug_slot->private = eeepc; eeepc->hotplug_slot->ops = &eeepc_hotplug_slot_ops; -eeepc_get_adapter_status (eeepc->hotplug_slot, - &eeepc->hotplug_slot->info->adapter_status); ret =pci_hp_register (eeepc->hotplug_slot, bus,0 ,"eeepc-wifi" );if (ret) {
@@ -764,8 +757,6 @@ static int eeepc_setup_pci_hotplug(struct eeepc_laptop *eeepc)return 0 ; error_register: -kfree (eeepc->hotplug_slot->info); -error_info:kfree (eeepc->hotplug_slot); eeepc->hotplug_slot =NULL ; error_slot:
@@ -831,7 +822,6 @@ static void eeepc_rfkill_exit(struct eeepc_laptop *eeepc)if (eeepc->hotplug_slot) {pci_hp_deregister (eeepc->hotplug_slot); -kfree (eeepc->hotplug_slot->info);kfree (eeepc->hotplug_slot); }
include/linux/pci_hotplug.h +0 -30
@@ -23,17 +23,9 @@* @hardware_test: Called to run a specified hardware test on the specified * slot. * @get_power_status: Called to get the current power status of a slot. -* If this field is NULL, the value passed in the struct hotplug_slot_info -* will be used when this value is requested by a user. * @get_attention_status: Called to get the current attention status of a slot. -* If this field is NULL, the value passed in the struct hotplug_slot_info -* will be used when this value is requested by a user. * @get_latch_status: Called to get the current latch status of a slot. -* If this field is NULL, the value passed in the struct hotplug_slot_info -* will be used when this value is requested by a user. * @get_adapter_status: Called to get see if an adapter is present in the slot or not. -* If this field is NULL, the value passed in the struct hotplug_slot_info -* will be used when this value is requested by a user. * @reset_slot: Optional interface to allow override of a bus reset for the * slot for cases where a secondary bus reset can result in spurious * hotplug events or where a slot can be reset independent of the bus.
@@ -55,27 +47,9 @@ struct hotplug_slot_ops {int (*reset_slot) (struct hotplug_slot *slot,int probe); }; -/** -* struct hotplug_slot_info - used to notify the hotplug pci core of the state of the slot -* @power_status: if power is enabled or not (1/0) -* @attention_status: if the attention light is enabled or not (1/0) -* @latch_status: if the latch (if any) is open or closed (1/0) -* @adapter_status: if there is a pci board present in the slot or not (1/0) -* -* Used to notify the hotplug pci core of the status of a specific slot. -*/ -struct hotplug_slot_info { -u8 power_status; -u8 attention_status; -u8 latch_status; -u8 adapter_status; -}; -/** * 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 -* @info: pointer to the &struct hotplug_slot_info for the initial values for -* this slot. * @private: used by the hotplug pci controller driver to store whatever it * needs. * @owner: The module owner of this structure
@@ -83,7 +57,6 @@ struct hotplug_slot_info {*/ struct hotplug_slot {const struct hotplug_slot_ops *ops; -struct hotplug_slot_info *info;void *private;/* Variables below this are for use only by the hotplug pci core. */
@@ -110,9 +83,6 @@ void pci_hp_del(struct hotplug_slot *slot);void pci_hp_destroy (struct hotplug_slot *slot);void pci_hp_deregister (struct hotplug_slot *slot); -int __must_check pci_hp_change_slot_info (struct hotplug_slot *slot, -struct hotplug_slot_info *info); -/* use a define to avoid include chaining to get THIS_MODULE & friends */ #define pci_hp_register (slot, pbus, devnr, name) \ __pci_hp_register(slot, pbus, devnr, name, THIS_MODULE, KBUILD_MODNAME)
Signature · 1 line
2.18.0
Re: [PATCH 7/9] PCI: hotplug: Drop hotplug_slot_info
Quoted 42 lines · Lukas Wunner
Ever since the PCI hotplug core was introduced in 2002, drivers had to allocate and register a struct
hotplug_slot_infofor every slot:
https://git.kernel.org/tglx/history/c/a8a2069f432cApparently the idea was that drivers furnish the hotplug core with an up-to-date card presence status, power status, latch status and attention indicator status as well as notify the hotplug core of changes thereof. However only 4 out of 12 hotplug drivers bother to notify the hotplug core with
pci_hp_change_slot_info()and the hotplug core never made any use of the information: There is just a single macro inpci_hotplug_core.c,GET_STATUS(), which uses thehotplug_slot_infoif the driver lacks the corresponding callback inhotplug_slot_ops. The macro is called when the user reads the attribute via sysfs.Now, if the callback isn't defined, the attribute isn't exposed in sysfs in the first place (see e.g.
has_power_file()). There are only two situations when thehotplug_slot_infowould actually be accessed:* If the driver defines ->enable_slot or ->disable_slot but not ->get_power_status.
* If the driver defines ->set_attention_status but not ->get_attention_status.
There is no driver doing the former and just a single driver doing the latter, namely
pnv_php.c. Amend it with a ->get_attention_status callback. With that, thehotplug_slot_infobecomes completely unused by the PCI hotplug core. But a few drivers use it internally as a cache:cpcihp uses it to cache the
latch_statusandadapter_status. cpqhp uses it to cache theadapter_status.pnv_phpand rpaphp use it to cache theattention_status. shpchp uses it to cache all four values.Amend these drivers to cache the information in their private slot struct. shpchp's slot struct already contains members to cache the
power_statusandadapter_status, so additional members are only needed for the other two values. In the case of cpqphp, the cached value is only accessed in a single place, so instead of caching it, read the current value from the hardware.
Quoted 7 lines
Caution: acpiphp, cpci, cpqhp, shpchp, asus-wmi and eeepc-laptop populate the
hotplug_slot_infowith initial values on probe. That code is herewith removed. There is a theoretical chance that the code has side effects without which the driver fails to function, e.g. if the ACPI method to read the adapter status needs to be executed at least once on probe. That seems unlikely to me, still maintainers should review the changes carefully for this possibility.
I'm not aware of any case in which it will break anything, so
but if that happens, it may be necessary to add the execution of the control methods in question directly to the initialization part.
Re: [PATCH 7/9] PCI: hotplug: Drop hotplug_slot_info
In reply to Lukas WunnerQuoted 62 lines · Lukas Wunner
Ever since the PCI hotplug core was introduced in 2002, drivers had to allocate and register a struct
hotplug_slot_infofor every slot:
https://git.kernel.org/tglx/history/c/a8a2069f432cApparently the idea was that drivers furnish the hotplug core with an up-to-date card presence status, power status, latch status and attention indicator status as well as notify the hotplug core of changes thereof. However only 4 out of 12 hotplug drivers bother to notify the hotplug core with
pci_hp_change_slot_info()and the hotplug core never made any use of the information: There is just a single macro inpci_hotplug_core.c,GET_STATUS(), which uses thehotplug_slot_infoif the driver lacks the corresponding callback inhotplug_slot_ops. The macro is called when the user reads the attribute via sysfs.Now, if the callback isn't defined, the attribute isn't exposed in sysfs in the first place (see e.g.
has_power_file()). There are only two situations when thehotplug_slot_infowould actually be accessed:* If the driver defines ->enable_slot or ->disable_slot but not ->get_power_status.
* If the driver defines ->set_attention_status but not ->get_attention_status.
There is no driver doing the former and just a single driver doing the latter, namely
pnv_php.c. Amend it with a ->get_attention_status callback. With that, thehotplug_slot_infobecomes completely unused by the PCI hotplug core. But a few drivers use it internally as a cache:cpcihp uses it to cache the
latch_statusandadapter_status. cpqhp uses it to cache theadapter_status.pnv_phpand rpaphp use it to cache theattention_status. shpchp uses it to cache all four values.Amend these drivers to cache the information in their private slot struct. shpchp's slot struct already contains members to cache the
power_statusandadapter_status, so additional members are only needed for the other two values. In the case of cpqphp, the cached value is only accessed in a single place, so instead of caching it, read the current value from the hardware.Caution: acpiphp, cpci, cpqhp, shpchp, asus-wmi and eeepc-laptop populate the
hotplug_slot_infowith initial values on probe. That code is herewith removed. There is a theoretical chance that the code has side effects without which the driver fails to function, e.g. if the ACPI method to read the adapter status needs to be executed at least once on probe. That seems unlikely to me, still maintainers should review the changes carefully for this possibility.Signed-off-by Lukas Wunner <[email protected]>Cc Rafael J. Wysocki <[email protected]>Cc Len Brown <[email protected]>Cc Scott Murray <[email protected]>Cc Benjamin Herrenschmidt <[email protected]>Cc Paul Mackerras <[email protected]>Cc Michael Ellerman <[email protected]>Cc Gavin Shan <[email protected]>Cc Sebastian Ott <[email protected]>Cc Gerald Schaefer <[email protected]>Cc Corentin Chary <[email protected]>Cc Darren Hart <[email protected]>Cc Andy Shevchenko <[email protected]>
Quoted 1 line
---
With regards to driver/pci/hotplug/rpa*
Re: [PATCH 7/9] PCI: hotplug: Drop hotplug_slot_info
In reply to Lukas WunnerQuoted 49 lines · Lukas Wunner
Ever since the PCI hotplug core was introduced in 2002, drivers had to allocate and register a struct
hotplug_slot_infofor every slot:
https://git.kernel.org/tglx/history/c/a8a2069f432cApparently the idea was that drivers furnish the hotplug core with an up-to-date card presence status, power status, latch status and attention indicator status as well as notify the hotplug core of changes thereof. However only 4 out of 12 hotplug drivers bother to notify the hotplug core with
pci_hp_change_slot_info()and the hotplug core never made any use of the information: There is just a single macro inpci_hotplug_core.c,GET_STATUS(), which uses thehotplug_slot_infoif the driver lacks the corresponding callback inhotplug_slot_ops. The macro is called when the user reads the attribute via sysfs.Now, if the callback isn't defined, the attribute isn't exposed in sysfs in the first place (see e.g.
has_power_file()). There are only two situations when thehotplug_slot_infowould actually be accessed:* If the driver defines ->enable_slot or ->disable_slot but not ->get_power_status.
* If the driver defines ->set_attention_status but not ->get_attention_status.
There is no driver doing the former and just a single driver doing the latter, namely
pnv_php.c. Amend it with a ->get_attention_status callback. With that, thehotplug_slot_infobecomes completely unused by the PCI hotplug core. But a few drivers use it internally as a cache:cpcihp uses it to cache the
latch_statusandadapter_status. cpqhp uses it to cache theadapter_status.pnv_phpand rpaphp use it to cache theattention_status. shpchp uses it to cache all four values.Amend these drivers to cache the information in their private slot struct. shpchp's slot struct already contains members to cache the
power_statusandadapter_status, so additional members are only needed for the other two values. In the case of cpqphp, the cached value is only accessed in a single place, so instead of caching it, read the current value from the hardware.Caution: acpiphp, cpci, cpqhp, shpchp, asus-wmi and eeepc-laptop populate the
hotplug_slot_infowith initial values on probe. That code is herewith removed. There is a theoretical chance that the code has side effects without which the driver fails to function, e.g. if the ACPI method to read the adapter status needs to be executed at least once on probe. That seems unlikely to me, still maintainers should review the changes carefully for this possibility.
Quoted 13 lines
Signed-off-by Lukas Wunner <[email protected]>Cc Rafael J. Wysocki <[email protected]>Cc Len Brown <[email protected]>Cc Scott Murray <[email protected]>Cc Benjamin Herrenschmidt <[email protected]>Cc Paul Mackerras <[email protected]>Cc Michael Ellerman <[email protected]>Cc Gavin Shan <[email protected]>Cc Sebastian Ott <[email protected]>Cc Gerald Schaefer <[email protected]>Cc Corentin Chary <[email protected]>Cc Darren Hart <[email protected]>Cc Andy Shevchenko <[email protected]>
for s390_pci_hpc.c:
PATCH 8/9 PCI: hotplug: Embed hotplug_slot
In reply to Lukas WunnerWhen the PCI hotplug core and its first user, cpqphp, were introduced in February 2002 with historic commit a8a2069f432c, cpqphp allocated a slot struct for its internal use plus a hotplug_slot struct to be registered with the hotplug core and linked the two with pointers:
https://git.kernel.org/tglx/history/c/a8a2069f432c
Nowadays, the predominant pattern in the tree is to embed ("subclass") such structures in one another and cast to the containing struct with container_of(). But it wasn't until July 2002 that container_of() was introduced with historic commit ec4f214232cf:
https://git.kernel.org/tglx/history/c/ec4f214232cf
pnv_php, introduced in 2016, did the right thing and embedded struct hotplug_slot in its internal struct pnv_php_slot, but all other drivers cargo-culted cpqphp's design and linked separate structs with pointers.
Embedding structs is preferrable to linking them with pointers because it requires fewer allocations, thereby reducing overhead and simplifying error paths. Casting an embedded struct to the containing struct becomes a cheap subtraction rather than a dereference. And having fewer pointers reduces the risk of them pointing nowhere either accidentally or due to an attack.
Convert all drivers to embed struct hotplug_slot in their internal slot struct. The "private" pointer in struct hotplug_slot thereby becomes unused, so drop it.
--- drivers/pci/hotplug/acpiphp.h | 9 ++- drivers/pci/hotplug/acpiphp_core.c | 28 +++----- drivers/pci/hotplug/acpiphp_ibm.c | 2 +- drivers/pci/hotplug/cpci_hotplug.h | 9 ++- drivers/pci/hotplug/cpci_hotplug_core.c | 37 ++++------ drivers/pci/hotplug/cpci_hotplug_pci.c | 6 +- drivers/pci/hotplug/cpqphp.h | 9 ++- drivers/pci/hotplug/cpqphp_core.c | 37 ++++------ drivers/pci/hotplug/cpqphp_ctrl.c | 2 - drivers/pci/hotplug/ibmphp.h | 7 +- drivers/pci/hotplug/ibmphp_core.c | 92 +++++++++++-------------- drivers/pci/hotplug/ibmphp_ebda.c | 37 +++------- drivers/pci/hotplug/pciehp.h | 11 ++- drivers/pci/hotplug/pciehp_core.c | 37 ++++------ drivers/pci/hotplug/pciehp_ctrl.c | 4 +- drivers/pci/hotplug/pciehp_hpc.c | 8 +-- drivers/pci/hotplug/pnv_php.c | 9 ++- drivers/pci/hotplug/rpaphp.h | 7 +- drivers/pci/hotplug/rpaphp_core.c | 14 ++-- drivers/pci/hotplug/rpaphp_slot.c | 15 ++-- drivers/pci/hotplug/s390_pci_hpc.c | 30 ++++---- drivers/pci/hotplug/sgi_hotplug.c | 52 ++++++-------- drivers/pci/hotplug/shpchp.h | 6 +- drivers/pci/hotplug/shpchp_core.c | 17 ++--- drivers/platform/x86/asus-wmi.c | 26 +++---- drivers/platform/x86/eeepc-laptop.c | 30 ++++---- include/linux/pci_hotplug.h | 3 - 27 files changed, 223 insertions(+), 321 deletions(-)
drivers/pci/hotplug/acpiphp.h +7 -2
@@ -33,14 +33,19 @@ struct acpiphp_slot;* struct slot - slot information for each *physical* slot */ struct slot { -struct hotplug_slot *hotplug_slot; +struct hotplug_slot hotplug_slot;struct acpiphp_slot *acpi_slot;unsigned int sun;/* ACPI _SUN (Slot User Number) value */ };static inline const char *slot_name (struct slot *slot) { -return hotplug_slot_name (slot->hotplug_slot); +return hotplug_slot_name (&slot->hotplug_slot); +} + +static inline struct slot *to_slot (struct hotplug_slot *hotplug_slot) +{ + return container_of(hotplug_slot, struct slot, hotplug_slot); }/*
drivers/pci/hotplug/acpiphp_core.c +10 -18
@@ -118,7 +118,7 @@ EXPORT_SYMBOL_GPL(acpiphp_unregister_attention);*/ static int enable_slot (struct hotplug_slot *hotplug_slot) { -struct slot *slot = hotplug_slot->private; +struct slot *slot =to_slot (hotplug_slot);pr_debug ("%s - physical_slot = %s\n" , __func__,slot_name (slot));
@@ -135,7 +135,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)*/ static int disable_slot (struct hotplug_slot *hotplug_slot) { -struct slot *slot = hotplug_slot->private; +struct slot *slot =to_slot (hotplug_slot);pr_debug ("%s - physical_slot = %s\n" , __func__,slot_name (slot));
@@ -179,7 +179,7 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)*/ static int get_power_status (struct hotplug_slot *hotplug_slot,u8 *value) { -struct slot *slot = hotplug_slot->private; +struct slot *slot =to_slot (hotplug_slot);pr_debug ("%s - physical_slot = %s\n" , __func__,slot_name (slot));
@@ -225,7 +225,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)*/ static int get_latch_status (struct hotplug_slot *hotplug_slot,u8 *value) { -struct slot *slot = hotplug_slot->private; +struct slot *slot =to_slot (hotplug_slot);pr_debug ("%s - physical_slot = %s\n" , __func__,slot_name (slot));
@@ -245,7 +245,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)*/ static int get_adapter_status (struct hotplug_slot *hotplug_slot,u8 *value) { -struct slot *slot = hotplug_slot->private; +struct slot *slot =to_slot (hotplug_slot);pr_debug ("%s - physical_slot = %s\n" , __func__,slot_name (slot));
@@ -266,12 +266,7 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot,if (!slot) goto error; - slot->hotplug_slot =kzalloc (sizeof (*slot->hotplug_slot),GFP_KERNEL ); -if (!slot->hotplug_slot) - goto error_slot; - - slot->hotplug_slot->private = slot; - slot->hotplug_slot->ops = &acpi_hotplug_slot_ops; + slot->hotplug_slot.ops = &acpi_hotplug_slot_ops; slot->acpi_slot = acpiphp_slot;
@@ -279,20 +274,18 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot, slot->sun = sun;snprintf (name,SLOT_NAME_SIZE ,"%u" , sun); - retval =pci_hp_register (slot->hotplug_slot, acpiphp_slot->bus, + retval =pci_hp_register (&slot->hotplug_slot, acpiphp_slot->bus, acpiphp_slot->device, name);if (retval == -EBUSY ) - goto error_hpslot; + goto error_slot;if (retval) {pr_err ("pci_hp_register failed with error %d\n" , retval); - goto error_hpslot; + goto error_slot; }pr_info ("Slot [%s] registered\n" ,slot_name (slot));return 0 ; -error_hpslot: -kfree (slot->hotplug_slot); error_slot:kfree (slot); error:
@@ -306,8 +299,7 @@ void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *acpiphp_slot)pr_info ("Slot [%s] unregistered\n" ,slot_name (slot)); -pci_hp_deregister (slot->hotplug_slot); -kfree (slot->hotplug_slot); +pci_hp_deregister (&slot->hotplug_slot);kfree (slot); }
drivers/pci/hotplug/acpiphp_ibm.c +1 -1
@@ -41,7 +41,7 @@ MODULE_VERSION(DRIVER_VERSION);#define IBM_HARDWARE_ID1 "IBM37D0"#define IBM_HARDWARE_ID2 "IBM37D4" -#define hpslot_to_sun (A ) (((struct slot *)((A)->private))->sun) +#define hpslot_to_sun (A ) (to_slot(A)->sun)/* union apci_descriptor - allows access to the * various device descriptors that are embedded in the
drivers/pci/hotplug/cpci_hotplug.h +7 -2
@@ -35,7 +35,7 @@ struct slot {bool latch_status;bool adapter_status;unsigned int extracting; -struct hotplug_slot *hotplug_slot; +struct hotplug_slot hotplug_slot;struct list_head slot_list; };
@@ -60,7 +60,12 @@ struct cpci_hp_controller {static inline const char *slot_name (struct slot *slot) { -return hotplug_slot_name (slot->hotplug_slot); +return hotplug_slot_name (&slot->hotplug_slot); +} + +static inline struct slot *to_slot (struct hotplug_slot *hotplug_slot) +{ + return container_of(hotplug_slot, struct slot, hotplug_slot); }int cpci_hp_register_controller (struct cpci_hp_controller *controller);
drivers/pci/hotplug/cpci_hotplug_core.c +12 -25
@@ -70,7 +70,7 @@ static const struct hotplug_slot_ops cpci_hotplug_slot_ops = {static int enable_slot (struct hotplug_slot *hotplug_slot) { -struct slot *slot = hotplug_slot->private; +struct slot *slot =to_slot (hotplug_slot);int retval =0 ;dbg ("%s - physical_slot = %s" , __func__,slot_name (slot));
@@ -83,7 +83,7 @@ enable_slot(struct hotplug_slot *hotplug_slot)static int disable_slot (struct hotplug_slot *hotplug_slot) { -struct slot *slot = hotplug_slot->private; +struct slot *slot =to_slot (hotplug_slot);int retval =0 ;dbg ("%s - physical_slot = %s" , __func__,slot_name (slot));
@@ -139,7 +139,7 @@ cpci_get_power_status(struct slot *slot)static int get_power_status (struct hotplug_slot *hotplug_slot,u8 *value) { -struct slot *slot = hotplug_slot->private; +struct slot *slot =to_slot (hotplug_slot); *value =cpci_get_power_status (slot);return 0 ;
@@ -148,7 +148,7 @@ get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)static int get_attention_status (struct hotplug_slot *hotplug_slot,u8 *value) { -struct slot *slot = hotplug_slot->private; +struct slot *slot =to_slot (hotplug_slot); *value =cpci_get_attention_status (slot);return 0 ;
@@ -157,13 +157,13 @@ get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)static int set_attention_status (struct hotplug_slot *hotplug_slot,u8 status) { -return cpci_set_attention_status (hotplug_slot->private, status); +return cpci_set_attention_status (to_slot (hotplug_slot), status); }static int get_adapter_status (struct hotplug_slot *hotplug_slot,u8 *value) { -struct slot *slot = hotplug_slot->private; +struct slot *slot =to_slot (hotplug_slot); *value = slot->adapter_status;return 0 ;
@@ -172,7 +172,7 @@ get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)static int get_latch_status (struct hotplug_slot *hotplug_slot,u8 *value) { -struct slot *slot = hotplug_slot->private; +struct slot *slot =to_slot (hotplug_slot); *value = slot->latch_status;return 0 ;
@@ -180,7 +180,6 @@ get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)static void release_slot (struct slot *slot) { -kfree (slot->hotplug_slot);pci_dev_put (slot->dev);kfree (slot); }
@@ -191,7 +190,6 @@ int cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last) { struct slot *slot; -struct hotplug_slot *hotplug_slot;char name[SLOT_NAME_SIZE ];int status;int i;
@@ -210,28 +208,19 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last) goto error; } - hotplug_slot = -kzalloc (sizeof (struct hotplug_slot ),GFP_KERNEL ); -if (!hotplug_slot) { - status = -ENOMEM ; - goto error_slot; - } - slot->hotplug_slot = hotplug_slot; - slot->bus = bus; slot->number = i; slot->devfn =PCI_DEVFN (i,0 );snprintf (name,SLOT_NAME_SIZE ,"%02x:%02x" , bus->number, i); - hotplug_slot->private = slot; - hotplug_slot->ops = &cpci_hotplug_slot_ops; + slot->hotplug_slot.ops = &cpci_hotplug_slot_ops;dbg ("registering slot %s" , name); - status =pci_hp_register (slot->hotplug_slot, bus, i, name); + status =pci_hp_register (&slot->hotplug_slot, bus, i, name);if (status) {err ("pci_hp_register failed with error %d" , status); - goto error_hpslot; + goto error_slot; }dbg ("slot registered with name: %s" ,slot_name (slot));
@@ -242,8 +231,6 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last)up_write (&list_rwsem); }return 0 ; -error_hpslot: -kfree (hotplug_slot); error_slot:kfree (slot); error:
@@ -269,7 +256,7 @@ cpci_hp_unregister_bus(struct pci_bus *bus) slots--;dbg ("deregistering slot %s" ,slot_name (slot)); -pci_hp_deregister (slot->hotplug_slot); +pci_hp_deregister (&slot->hotplug_slot);release_slot (slot); } }
@@ -571,7 +558,7 @@ cleanup_slots(void) goto cleanup_null;list_for_each_entry_safe (slot, tmp, &slot_list, slot_list) {list_del (&slot->slot_list); -pci_hp_deregister (slot->hotplug_slot); +pci_hp_deregister (&slot->hotplug_slot);release_slot (slot); } cleanup_null:
drivers/pci/hotplug/cpci_hotplug_pci.c +2 -4
@@ -194,8 +194,7 @@ int cpci_led_on(struct slot *slot) slot->devfn, hs_cap + 2, hs_csr)) { -err ("Could not set LOO for slot %s" , -hotplug_slot_name (slot->hotplug_slot)); +err ("Could not set LOO for slot %s" ,slot_name (slot));return -ENODEV ; } }
@@ -223,8 +222,7 @@ int cpci_led_off(struct slot *slot) slot->devfn, hs_cap + 2, hs_csr)) { -err ("Could not clear LOO for slot %s" , -hotplug_slot_name (slot->hotplug_slot)); +err ("Could not clear LOO for slot %s" ,slot_name (slot));return -ENODEV ; } }
drivers/pci/hotplug/cpqphp.h +7 -2
@@ -260,7 +260,7 @@ struct slot {u8 hp_slot;struct controller *ctrl;void __iomem *p_sm_slot; -struct hotplug_slot *hotplug_slot; +struct hotplug_slot hotplug_slot; };struct pci_resource {
@@ -445,7 +445,12 @@ extern u8 cpqhp_disk_irq;static inline const char *slot_name (struct slot *slot) { -return hotplug_slot_name (slot->hotplug_slot); +return hotplug_slot_name (&slot->hotplug_slot); +} + +static inline struct slot *to_slot (struct hotplug_slot *hotplug_slot) +{ + return container_of(hotplug_slot, struct slot, hotplug_slot); }/*
drivers/pci/hotplug/cpqphp_core.c +12 -25
@@ -275,8 +275,7 @@ static int ctrl_slot_cleanup(struct controller *ctrl)while (old_slot) { next_slot = old_slot->next; -pci_hp_deregister (old_slot->hotplug_slot); -kfree (old_slot->hotplug_slot); +pci_hp_deregister (&old_slot->hotplug_slot);kfree (old_slot); old_slot = next_slot; }
@@ -418,7 +417,7 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func,static int set_attention_status (struct hotplug_slot *hotplug_slot,u8 status) {struct pci_func *slot_func; -struct slot *slot = hotplug_slot->private; +struct slot *slot =to_slot (hotplug_slot);struct controller *ctrl = slot->ctrl;u8 bus;u8 devfn;
@@ -445,7 +444,7 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)static int process_SI (struct hotplug_slot *hotplug_slot) {struct pci_func *slot_func; -struct slot *slot = hotplug_slot->private; +struct slot *slot =to_slot (hotplug_slot);struct controller *ctrl = slot->ctrl;u8 bus;u8 devfn;
@@ -477,7 +476,7 @@ static int process_SI(struct hotplug_slot *hotplug_slot)static int process_SS (struct hotplug_slot *hotplug_slot) {struct pci_func *slot_func; -struct slot *slot = hotplug_slot->private; +struct slot *slot =to_slot (hotplug_slot);struct controller *ctrl = slot->ctrl;u8 bus;u8 devfn;
@@ -504,7 +503,7 @@ static int process_SS(struct hotplug_slot *hotplug_slot)static int hardware_test (struct hotplug_slot *hotplug_slot,u32 value) { -struct slot *slot = hotplug_slot->private; +struct slot *slot =to_slot (hotplug_slot);struct controller *ctrl = slot->ctrl;dbg ("%s - physical_slot = %s\n" , __func__,slot_name (slot));
@@ -515,7 +514,7 @@ static int hardware_test(struct hotplug_slot *hotplug_slot, u32 value)static int get_power_status (struct hotplug_slot *hotplug_slot,u8 *value) { -struct slot *slot = hotplug_slot->private; +struct slot *slot =to_slot (hotplug_slot);struct controller *ctrl = slot->ctrl;dbg ("%s - physical_slot = %s\n" , __func__,slot_name (slot));
@@ -526,7 +525,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)static int get_attention_status (struct hotplug_slot *hotplug_slot,u8 *value) { -struct slot *slot = hotplug_slot->private; +struct slot *slot =to_slot (hotplug_slot);struct controller *ctrl = slot->ctrl;dbg ("%s - physical_slot = %s\n" , __func__,slot_name (slot));
@@ -537,7 +536,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)static int get_latch_status (struct hotplug_slot *hotplug_slot,u8 *value) { -struct slot *slot = hotplug_slot->private; +struct slot *slot =to_slot (hotplug_slot);struct controller *ctrl = slot->ctrl;dbg ("%s - physical_slot = %s\n" , __func__,slot_name (slot));
@@ -549,7 +548,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)static int get_adapter_status (struct hotplug_slot *hotplug_slot,u8 *value) { -struct slot *slot = hotplug_slot->private; +struct slot *slot =to_slot (hotplug_slot);struct controller *ctrl = slot->ctrl;dbg ("%s - physical_slot = %s\n" , __func__,slot_name (slot));
@@ -577,7 +576,6 @@ static int ctrl_slot_setup(struct controller *ctrl, void __iomem *smbios_table) {struct slot *slot; -struct hotplug_slot *hotplug_slot;struct pci_bus *bus = ctrl->pci_bus;u8 number_of_slots;u8 slot_device;
@@ -603,14 +601,6 @@ static int ctrl_slot_setup(struct controller *ctrl, goto error; } - slot->hotplug_slot =kzalloc (sizeof (*(slot->hotplug_slot)), -GFP_KERNEL ); -if (!slot->hotplug_slot) { - result = -ENOMEM ; - goto error_slot; - } - hotplug_slot = slot->hotplug_slot; - slot->ctrl = ctrl; slot->bus = ctrl->bus; slot->device = slot_device;
@@ -659,21 +649,20 @@ static int ctrl_slot_setup(struct controller *ctrl, ((read_slot_enable (ctrl) <<2 ) >> ctrl_slot) &0x04 ;/* register this slot with the hotplug pci core */ - hotplug_slot->private = slot;snprintf (name,SLOT_NAME_SIZE ,"%u" , slot->number); - hotplug_slot->ops = &cpqphp_hotplug_slot_ops; + slot->hotplug_slot.ops = &cpqphp_hotplug_slot_ops;dbg ("registering bus %d, dev %d, number %d, ctrl->slot_device_offset %d, slot %d\n" , slot->bus, slot->device, slot->number, ctrl->slot_device_offset, slot_number); - result =pci_hp_register (hotplug_slot, + result =pci_hp_register (&slot->hotplug_slot, ctrl->pci_dev->bus, slot->device, name);if (result) {err ("pci_hp_register failed with error %d\n" , result); - goto error_hpslot; + goto error_slot; } slot->next = ctrl->slot;
@@ -685,8 +674,6 @@ static int ctrl_slot_setup(struct controller *ctrl, }return 0 ; -error_hpslot: -kfree (hotplug_slot); error_slot:kfree (slot); error:
drivers/pci/hotplug/cpqphp_ctrl.c +0 -2
@@ -1130,8 +1130,6 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_for (slot = ctrl->slot; slot; slot = slot->next) {if (slot->device == (hp_slot + ctrl->slot_device_offset))continue ; -if (!slot->hotplug_slot) -continue ;if (get_presence_status (ctrl, slot) ==0 )continue ;/* If another adapter is running on the same segment but at a
drivers/pci/hotplug/ibmphp.h +6 -1
@@ -698,7 +698,7 @@ struct slot {u8 supported_bus_mode;u8 flag;/* this is for disable slot and polling */ u8 ctlr_index; -struct hotplug_slot *hotplug_slot; +struct hotplug_slot hotplug_slot;struct controller *ctrl;struct pci_func *func;u8 irq[4 ];
@@ -742,5 +742,10 @@ int ibmphp_configure_card(struct pci_func *, u8);int ibmphp_unconfigure_card (struct slot **,int );extern const struct hotplug_slot_ops ibmphp_hotplug_slot_ops; +static inline struct slot *to_slot (struct hotplug_slot *hotplug_slot) +{ + return container_of(hotplug_slot, struct slot, hotplug_slot); +} +#endif //__IBMPHP_H
drivers/pci/hotplug/ibmphp_core.c +39 -53
158 lines not on this page · raw message
drivers/pci/hotplug/ibmphp_ebda.c +10 -27
@@ -666,10 +666,7 @@ static int fillslotinfo(struct hotplug_slot *hotplug_slot)struct slot *slot;int rc =0 ; -if (!hotplug_slot || !hotplug_slot->private) -return -EINVAL ; - - slot = hotplug_slot->private; + slot =to_slot (hotplug_slot); rc =ibmphp_hpc_readslot (slot,READ_ALLSTAT ,NULL );return rc; }
@@ -687,7 +684,6 @@ static int __init ebda_rsrc_controller(void)u8 ctlr_id, temp, bus_index;u16 ctlr, slot, bus;u16 slot_num, bus_num, index; -struct hotplug_slot *hp_slot_ptr;struct controller *hpc_ptr;struct ebda_hpc_bus *bus_ptr;struct ebda_hpc_slot *slot_ptr;
@@ -746,7 +742,7 @@ static int __init ebda_rsrc_controller(void) bus_info_ptr1 =kzalloc (sizeof (struct bus_info ),GFP_KERNEL );if (!bus_info_ptr1) { rc = -ENOMEM ; - goto error_no_hp_slot; + goto error_no_slot; } bus_info_ptr1->slot_min = slot_ptr->slot_num; bus_info_ptr1->slot_max = slot_ptr->slot_num;
@@ -817,7 +813,7 @@ static int __init ebda_rsrc_controller(void) (hpc_ptr->u.isa_ctlr.io_end - hpc_ptr->u.isa_ctlr.io_start + 1), "ibmphp")) { rc = -ENODEV ; - goto error_no_hp_slot; + goto error_no_slot; } hpc_ptr->irq =readb (io_mem + addr +4 ); addr +=5 ;
@@ -832,7 +828,7 @@ static int __init ebda_rsrc_controller(void)break ;default : rc = -ENODEV ; - goto error_no_hp_slot; + goto error_no_slot; }//reorganize chassis' linked list
@@ -845,13 +841,6 @@ static int __init ebda_rsrc_controller(void)// register slots with hpc core as well as create linked list of ibm slot for (index =0 ; index < hpc_ptr->slot_count; index++) { - - hp_slot_ptr =kzalloc (sizeof (*hp_slot_ptr),GFP_KERNEL ); -if (!hp_slot_ptr) { - rc = -ENOMEM ; - goto error_no_hp_slot; - } - tmp_slot =kzalloc (sizeof (*tmp_slot),GFP_KERNEL );if (!tmp_slot) { rc = -ENOMEM ;
@@ -878,7 +867,6 @@ static int __init ebda_rsrc_controller(void) bus_info_ptr1 =ibmphp_find_same_bus_num (hpc_ptr->slots[index].slot_bus_num);if (!bus_info_ptr1) { -kfree (tmp_slot); rc = -ENODEV ; goto error; }
@@ -888,22 +876,19 @@ static int __init ebda_rsrc_controller(void) tmp_slot->ctlr_index = hpc_ptr->slots[index].ctl_index; tmp_slot->number = hpc_ptr->slots[index].slot_num; - tmp_slot->hotplug_slot = hp_slot_ptr; - - hp_slot_ptr->private = tmp_slot; - rc =fillslotinfo (hp_slot_ptr); + rc =fillslotinfo (&tmp_slot->hotplug_slot);if (rc) goto error; - rc =ibmphp_init_devno ((struct slot **) &hp_slot_ptr->private); + rc =ibmphp_init_devno (&tmp_slot);if (rc) goto error; - hp_slot_ptr->ops = &ibmphp_hotplug_slot_ops; + tmp_slot->hotplug_slot.ops = &ibmphp_hotplug_slot_ops;// end of registering ibm slot with hotplug core -list_add (&((struct slot *)(hp_slot_ptr->private))->ibm_slot_list, &ibmphp_slot_head); +list_add (&tmp_slot->ibm_slot_list, &ibmphp_slot_head); }print_bus_info ();
@@ -913,7 +898,7 @@ static int __init ebda_rsrc_controller(void)list_for_each_entry (tmp_slot, &ibmphp_slot_head, ibm_slot_list) {snprintf (name,SLOT_NAME_SIZE ,"%s" ,create_file_name (tmp_slot)); -pci_hp_register (tmp_slot->hotplug_slot, +pci_hp_register (&tmp_slot->hotplug_slot,pci_find_bus (0 , tmp_slot->bus), tmp_slot->device, name); }
@@ -922,10 +907,8 @@ static int __init ebda_rsrc_controller(void)return 0 ; error: -kfree (hp_slot_ptr->private); +kfree (tmp_slot); error_no_slot: -kfree (hp_slot_ptr); -error_no_hp_slot:free_ebda_hpc (hpc_ptr); error_no_hpc:iounmap (io_mem);
drivers/pci/hotplug/pciehp.h +8 -3
@@ -88,7 +88,7 @@ do { \* protects scheduling, execution and cancellation of @button_work * @button_work: work item to turn the slot on or off after 5 seconds * in response to an Attention Button press -* @hotplug_slot: pointer to the structure registered with the PCI hotplug core +* @hotplug_slot: structure registered with the PCI hotplug core * @reset_lock: prevents access to the Data Link Layer Link Active bit in the * Link Status register and to the Presence Detect State bit in the Slot * Status register during a slot reset which may cause them to flap
@@ -120,7 +120,7 @@ struct controller {struct mutex state_lock;struct delayed_work button_work; -struct hotplug_slot *hotplug_slot;/* hotplug core interface */ +struct hotplug_slot hotplug_slot;/* hotplug core interface */ struct rw_semaphore reset_lock;int request_result;wait_queue_head_t requester;
@@ -206,7 +206,12 @@ int pciehp_get_raw_indicator_status(struct hotplug_slot *h_slot, u8 *status);static inline const char *slot_name (struct controller *ctrl) { -return hotplug_slot_name (ctrl->hotplug_slot); +return hotplug_slot_name (&ctrl->hotplug_slot); +} + +static inline struct controller *to_ctrl (struct hotplug_slot *hotplug_slot) +{ + return container_of(hotplug_slot, struct controller, hotplug_slot); }#endif /* _PCIEHP_H */
drivers/pci/hotplug/pciehp_core.c +13 -24
@@ -51,19 +51,14 @@ static int get_adapter_status(struct hotplug_slot *slot, u8 *value);static int init_slot (struct controller *ctrl) { -struct hotplug_slot *hotplug =NULL ; -struct hotplug_slot_ops *ops =NULL ; +struct hotplug_slot_ops *ops;char name[SLOT_NAME_SIZE ]; -int retval = -ENOMEM ; - - hotplug =kzalloc (sizeof (*hotplug),GFP_KERNEL ); -if (!hotplug) - goto out; +int retval;/* Setup hotplug slot ops */ ops =kzalloc (sizeof (*ops),GFP_KERNEL );if (!ops) - goto out; +return -ENOMEM ; ops->enable_slot = pciehp_sysfs_enable_slot; ops->disable_slot = pciehp_sysfs_disable_slot;
@@ -81,30 +76,24 @@ static int init_slot(struct controller *ctrl) }/* register this slot with the hotplug pci core */ - hotplug->private = ctrl; - hotplug->ops = ops; - ctrl->hotplug_slot = hotplug; + ctrl->hotplug_slot.ops = ops;snprintf (name,SLOT_NAME_SIZE ,"%u" ,PSN (ctrl)); - retval =pci_hp_initialize (hotplug, + retval =pci_hp_initialize (&ctrl->hotplug_slot, ctrl->pcie->port->subordinate,0 , name); -if (retval) -ctrl_err (ctrl,"pci_hp_initialize failed: error %d\n" , retval); -out:if (retval) { +ctrl_err (ctrl,"pci_hp_initialize failed: error %d\n" , retval);kfree (ops); -kfree (hotplug); }return retval; }static void cleanup_slot (struct controller *ctrl) { -struct hotplug_slot *hotplug_slot = ctrl->hotplug_slot; +struct hotplug_slot *hotplug_slot = &ctrl->hotplug_slot;pci_hp_destroy (hotplug_slot);kfree (hotplug_slot->ops); -kfree (hotplug_slot); }/*
@@ -112,7 +101,7 @@ static void cleanup_slot(struct controller *ctrl)*/ static int set_attention_status (struct hotplug_slot *hotplug_slot,u8 status) { -struct controller *ctrl = hotplug_slot->private; +struct controller *ctrl =to_ctrl (hotplug_slot);struct pci_dev *pdev = ctrl->pcie->port;pci_config_pm_runtime_get (pdev);
@@ -123,7 +112,7 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)static int get_power_status (struct hotplug_slot *hotplug_slot,u8 *value) { -struct controller *ctrl = hotplug_slot->private; +struct controller *ctrl =to_ctrl (hotplug_slot);struct pci_dev *pdev = ctrl->pcie->port;pci_config_pm_runtime_get (pdev);
@@ -134,7 +123,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)static int get_latch_status (struct hotplug_slot *hotplug_slot,u8 *value) { -struct controller *ctrl = hotplug_slot->private; +struct controller *ctrl =to_ctrl (hotplug_slot);struct pci_dev *pdev = ctrl->pcie->port;pci_config_pm_runtime_get (pdev);
@@ -145,7 +134,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)static int get_adapter_status (struct hotplug_slot *hotplug_slot,u8 *value) { -struct controller *ctrl = hotplug_slot->private; +struct controller *ctrl =to_ctrl (hotplug_slot);struct pci_dev *pdev = ctrl->pcie->port;pci_config_pm_runtime_get (pdev);
@@ -223,7 +212,7 @@ static int pciehp_probe(struct pcie_device *dev) }/* Publish to user space */ - rc =pci_hp_add (ctrl->hotplug_slot); + rc =pci_hp_add (&ctrl->hotplug_slot);if (rc) {ctrl_err (ctrl,"Publication to user space failed (%d)\n" , rc); goto err_out_shutdown_notification;
@@ -246,7 +235,7 @@ static void pciehp_remove(struct pcie_device *dev) {struct controller *ctrl =get_service_data (dev); -pci_hp_del (ctrl->hotplug_slot); +pci_hp_del (&ctrl->hotplug_slot);pcie_shutdown_notification (ctrl);cleanup_slot (ctrl);pciehp_release_ctrl (ctrl);
drivers/pci/hotplug/pciehp_ctrl.c +2 -2
@@ -354,7 +354,7 @@ static int pciehp_disable_slot(struct controller *ctrl, bool safe_removal)int pciehp_sysfs_enable_slot (struct hotplug_slot *hotplug_slot) { -struct controller *ctrl = hotplug_slot->private; +struct controller *ctrl =to_ctrl (hotplug_slot);mutex_lock (&ctrl->state_lock);switch (ctrl->state) {
@@ -392,7 +392,7 @@ int pciehp_sysfs_enable_slot(struct hotplug_slot *hotplug_slot)int pciehp_sysfs_disable_slot (struct hotplug_slot *hotplug_slot) { -struct controller *ctrl = hotplug_slot->private; +struct controller *ctrl =to_ctrl (hotplug_slot);mutex_lock (&ctrl->state_lock);switch (ctrl->state) {
drivers/pci/hotplug/pciehp_hpc.c +4 -4
@@ -315,7 +315,7 @@ static int pciehp_link_enable(struct controller *ctrl)int pciehp_get_raw_indicator_status (struct hotplug_slot *hotplug_slot,u8 *status) { -struct controller *ctrl = hotplug_slot->private; +struct controller *ctrl =to_ctrl (hotplug_slot);struct pci_dev *pdev =ctrl_dev (ctrl);u16 slot_ctrl;
@@ -328,7 +328,7 @@ int pciehp_get_raw_indicator_status(struct hotplug_slot *hotplug_slot,int pciehp_get_attention_status (struct hotplug_slot *hotplug_slot,u8 *status) { -struct controller *ctrl = hotplug_slot->private; +struct controller *ctrl =to_ctrl (hotplug_slot);struct pci_dev *pdev =ctrl_dev (ctrl);u16 slot_ctrl;
@@ -408,7 +408,7 @@ int pciehp_query_power_fault(struct controller *ctrl)int pciehp_set_raw_indicator_status (struct hotplug_slot *hotplug_slot,u8 status) { -struct controller *ctrl = hotplug_slot->private; +struct controller *ctrl =to_ctrl (hotplug_slot);struct pci_dev *pdev =ctrl_dev (ctrl);pci_config_pm_runtime_get (pdev);
@@ -744,7 +744,7 @@ void pcie_clear_hotplug_events(struct controller *ctrl)*/ int pciehp_reset_slot (struct hotplug_slot *hotplug_slot,int probe) { -struct controller *ctrl = hotplug_slot->private; +struct controller *ctrl =to_ctrl (hotplug_slot);struct pci_dev *pdev =ctrl_dev (ctrl);u16 stat_mask =0 , ctrl_mask =0 ;int rc;
drivers/pci/hotplug/pnv_php.c +4 -5
@@ -336,7 +336,7 @@ static inline struct pnv_php_slot *to_pnv_php_slot(struct hotplug_slot *slot)int pnv_php_set_slot_power_state (struct hotplug_slot *slot,uint8_t state) { -struct pnv_php_slot *php_slot = slot->private; +struct pnv_php_slot *php_slot =to_pnv_php_slot (slot);struct opal_msg msg;int ret;
@@ -368,7 +368,7 @@ EXPORT_SYMBOL_GPL(pnv_php_set_slot_power_state);static int pnv_php_get_power_state (struct hotplug_slot *slot,u8 *state) { -struct pnv_php_slot *php_slot = slot->private; +struct pnv_php_slot *php_slot =to_pnv_php_slot (slot);uint8_t power_state =OPAL_PCI_SLOT_POWER_ON ;int ret;
@@ -390,7 +390,7 @@ static int pnv_php_get_power_state(struct hotplug_slot *slot, u8 *state)static int pnv_php_get_adapter_state (struct hotplug_slot *slot,u8 *state) { -struct pnv_php_slot *php_slot = slot->private; +struct pnv_php_slot *php_slot =to_pnv_php_slot (slot);uint8_t presence =OPAL_PCI_SLOT_EMPTY ;int ret;
@@ -521,7 +521,7 @@ static int pnv_php_enable_slot(struct hotplug_slot *slot)static int pnv_php_disable_slot (struct hotplug_slot *slot) { -struct pnv_php_slot *php_slot = slot->private; +struct pnv_php_slot *php_slot =to_pnv_php_slot (slot);int ret;if (php_slot->state !=PNV_PHP_STATE_POPULATED )
@@ -607,7 +607,6 @@ static struct pnv_php_slot *pnv_php_alloc_slot(struct device_node *dn) php_slot->id = id; php_slot->power_state_check = false; php_slot->slot.ops = &php_slot_ops; - php_slot->slot.private = php_slot;INIT_LIST_HEAD (&php_slot->children);INIT_LIST_HEAD (&php_slot->link);
drivers/pci/hotplug/rpaphp.h +6 -1
@@ -68,12 +68,17 @@ struct slot {struct device_node *dn;struct pci_bus *bus;struct list_head *pci_devs; -struct hotplug_slot *hotplug_slot; +struct hotplug_slot hotplug_slot; };extern const struct hotplug_slot_ops rpaphp_hotplug_slot_ops;extern struct list_head rpaphp_slot_head; +static inline struct slot *to_slot (struct hotplug_slot *hotplug_slot) +{ + return container_of(hotplug_slot, struct slot, hotplug_slot); +} +/* function prototypes */ /* rpaphp_pci.c */
drivers/pci/hotplug/rpaphp_core.c +7 -7
@@ -52,7 +52,7 @@ module_param_named(debug, rpaphp_debug, bool, 0644);static int set_attention_status (struct hotplug_slot *hotplug_slot,u8 value) {int rc; -struct slot *slot = (struct slot *)hotplug_slot->private; +struct slot *slot =to_slot (hotplug_slot);switch (value) {case 0 :
@@ -79,7 +79,7 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value)static int get_power_status (struct hotplug_slot *hotplug_slot,u8 *value) {int retval, level; -struct slot *slot = (struct slot *)hotplug_slot->private; +struct slot *slot =to_slot (hotplug_slot); retval =rtas_get_power_level (slot->power_domain, &level);if (!retval)
@@ -94,14 +94,14 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)*/ static int get_attention_status (struct hotplug_slot *hotplug_slot,u8 *value) { -struct slot *slot = (struct slot *)hotplug_slot->private; +struct slot *slot =to_slot (hotplug_slot); *value = slot->attention_status;return 0 ; }static int get_adapter_status (struct hotplug_slot *hotplug_slot,u8 *value) { -struct slot *slot = (struct slot *)hotplug_slot->private; +struct slot *slot =to_slot (hotplug_slot);int rc, state; rc =rpaphp_get_sensor_state (slot, &state);
@@ -409,7 +409,7 @@ static void __exit cleanup_slots(void)list_for_each_entry_safe (slot, next, &rpaphp_slot_head, rpaphp_slot_list) {list_del (&slot->rpaphp_slot_list); -pci_hp_deregister (slot->hotplug_slot); +pci_hp_deregister (&slot->hotplug_slot);dealloc_slot_struct (slot); }return ;
@@ -434,7 +434,7 @@ static void __exit rpaphp_exit(void)static int enable_slot (struct hotplug_slot *hotplug_slot) { -struct slot *slot = (struct slot *)hotplug_slot->private; +struct slot *slot =to_slot (hotplug_slot);int state;int retval;
@@ -464,7 +464,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)static int disable_slot (struct hotplug_slot *hotplug_slot) { -struct slot *slot = (struct slot *)hotplug_slot->private; +struct slot *slot =to_slot (hotplug_slot);if (slot->state ==NOT_CONFIGURED )return -EINVAL ;
drivers/pci/hotplug/rpaphp_slot.c +4 -11
@@ -22,7 +22,6 @@void dealloc_slot_struct (struct slot *slot) {kfree (slot->name); -kfree (slot->hotplug_slot);kfree (slot); }
@@ -34,22 +33,16 @@ struct slot *alloc_slot_struct(struct device_node *dn, slot =kzalloc (sizeof (struct slot ),GFP_KERNEL );if (!slot) goto error_nomem; - slot->hotplug_slot =kzalloc (sizeof (struct hotplug_slot ),GFP_KERNEL ); -if (!slot->hotplug_slot) - goto error_slot; slot->name =kstrdup (drc_name,GFP_KERNEL );if (!slot->name) - goto error_hpslot; + goto error_slot; slot->dn = dn; slot->index = drc_index; slot->power_domain = power_domain; - slot->hotplug_slot->private = slot; - slot->hotplug_slot->ops = &rpaphp_hotplug_slot_ops; + slot->hotplug_slot.ops = &rpaphp_hotplug_slot_ops;return (slot); -error_hpslot: -kfree (slot->hotplug_slot); error_slot:kfree (slot); error_nomem:
@@ -70,7 +63,7 @@ static int is_registered(struct slot *slot)int rpaphp_deregister_slot (struct slot *slot) {int retval =0 ; -struct hotplug_slot *php_slot = slot->hotplug_slot; +struct hotplug_slot *php_slot = &slot->hotplug_slot;dbg ("%s - Entry: deregistering slot=%s\n" , __func__, slot->name);
@@ -86,7 +79,7 @@ EXPORT_SYMBOL_GPL(rpaphp_deregister_slot);int rpaphp_register_slot (struct slot *slot) { -struct hotplug_slot *php_slot = slot->hotplug_slot; +struct hotplug_slot *php_slot = &slot->hotplug_slot;struct device_node *child;u32 my_index;int retval;
drivers/pci/hotplug/s390_pci_hpc.c +12 -18
@@ -32,10 +32,15 @@ static int zpci_fn_configured(enum zpci_state state)*/ struct slot {struct list_head slot_list; -struct hotplug_slot *hotplug_slot; +struct hotplug_slot hotplug_slot;struct zpci_dev *zdev; }; +static inline struct slot *to_slot (struct hotplug_slot *hotplug_slot) +{ + return container_of(hotplug_slot, struct slot, hotplug_slot); +} +static inline int slot_configure (struct slot *slot) {int ret =sclp_pci_configure (slot->zdev->fid);
@@ -60,7 +65,7 @@ static inline int slot_deconfigure(struct slot *slot)static int enable_slot (struct hotplug_slot *hotplug_slot) { -struct slot *slot = hotplug_slot->private; +struct slot *slot =to_slot (hotplug_slot);int rc;if (slot->zdev->state !=ZPCI_FN_STATE_STANDBY )
@@ -88,7 +93,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)static int disable_slot (struct hotplug_slot *hotplug_slot) { -struct slot *slot = hotplug_slot->private; +struct slot *slot =to_slot (hotplug_slot);struct pci_dev *pdev;int rc;
@@ -110,7 +115,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)static int get_power_status (struct hotplug_slot *hotplug_slot,u8 *value) { -struct slot *slot = hotplug_slot->private; +struct slot *slot =to_slot (hotplug_slot);switch (slot->zdev->state) {case ZPCI_FN_STATE_STANDBY :
@@ -139,7 +144,6 @@ static const struct hotplug_slot_ops s390_hotplug_slot_ops = {int zpci_init_slot (struct zpci_dev *zdev) { -struct hotplug_slot *hotplug_slot;char name[SLOT_NAME_SIZE ];struct slot *slot;int rc;
@@ -151,18 +155,11 @@ int zpci_init_slot(struct zpci_dev *zdev)if (!slot) goto error; - hotplug_slot =kzalloc (sizeof (*hotplug_slot),GFP_KERNEL ); -if (!hotplug_slot) - goto error_hp; - hotplug_slot->private = slot; - - slot->hotplug_slot = hotplug_slot; slot->zdev = zdev; - - hotplug_slot->ops = &s390_hotplug_slot_ops; + slot->hotplug_slot.ops = &s390_hotplug_slot_ops;snprintf (name,SLOT_NAME_SIZE ,"%08x" , zdev->fid); - rc =pci_hp_register (slot->hotplug_slot, zdev->bus, + rc =pci_hp_register (&slot->hotplug_slot, zdev->bus,ZPCI_DEVFN , name);if (rc) goto error_reg;
@@ -171,8 +168,6 @@ int zpci_init_slot(struct zpci_dev *zdev)return 0 ; error_reg: -kfree (hotplug_slot); -error_hp:kfree (slot); error:return -ENOMEM ;
@@ -187,8 +182,7 @@ void zpci_exit_slot(struct zpci_dev *zdev)if (slot->zdev != zdev)continue ;list_del (&slot->slot_list); -pci_hp_deregister (slot->hotplug_slot); -kfree (slot->hotplug_slot); +pci_hp_deregister (&slot->hotplug_slot);kfree (slot); } }
drivers/pci/hotplug/sgi_hotplug.c +22 -30
149 lines not on this page · raw message
drivers/pci/hotplug/shpchp.h +3 -3
@@ -73,7 +73,7 @@ struct slot {u8 pwr_save;struct controller *ctrl;const struct hpc_ops *hpc_ops; -struct hotplug_slot *hotplug_slot; +struct hotplug_slot hotplug_slot;struct list_head slot_list;struct delayed_work work;/* work for button event */ struct mutex lock;
@@ -171,7 +171,7 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev);static inline const char *slot_name (struct slot *slot) { -return hotplug_slot_name (slot->hotplug_slot); +return hotplug_slot_name (&slot->hotplug_slot); }struct ctrl_reg {
@@ -209,7 +209,7 @@ enum ctrl_offsets {static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot) { -return hotplug_slot->private; + return container_of(hotplug_slot, struct slot, hotplug_slot); }static inline struct slot *shpchp_find_slot (struct controller *ctrl,u8 device)
drivers/pci/hotplug/shpchp_core.c +4 -13
@@ -76,12 +76,7 @@ static int init_slots(struct controller *ctrl) goto error; } - hotplug_slot =kzalloc (sizeof (*hotplug_slot),GFP_KERNEL ); -if (!hotplug_slot) { - retval = -ENOMEM ; - goto error_slot; - } - slot->hotplug_slot = hotplug_slot; + hotplug_slot = &slot->hotplug_slot; slot->hp_slot = i; slot->ctrl = ctrl;
@@ -93,14 +88,13 @@ static int init_slots(struct controller *ctrl) slot->wq =alloc_workqueue ("shpchp-%d" ,0 ,0 , slot->number);if (!slot->wq) { retval = -ENOMEM ; - goto error_hpslot; + goto error_slot; }mutex_init (&slot->lock);INIT_DELAYED_WORK (&slot->work, shpchp_queue_pushbutton_work);/* register this slot with the hotplug pci core */ - hotplug_slot->private = slot;snprintf (name,SLOT_NAME_SIZE ,"%d" , slot->number); hotplug_slot->ops = &shpchp_hotplug_slot_ops;
@@ -108,7 +102,7 @@ static int init_slots(struct controller *ctrl)pci_domain_nr (ctrl->pci_dev->subordinate), slot->bus, slot->device, slot->hp_slot, slot->number, ctrl->slot_device_offset); - retval =pci_hp_register (slot->hotplug_slot, + retval =pci_hp_register (hotplug_slot, ctrl->pci_dev->subordinate, slot->device, name);if (retval) { ctrl_err(ctrl, "pci_hp_register failed with error %d\n",
@@ -127,8 +121,6 @@ static int init_slots(struct controller *ctrl)return 0 ; error_slotwq:destroy_workqueue (slot->wq); -error_hpslot: -kfree (hotplug_slot); error_slot:kfree (slot); error:
@@ -143,8 +135,7 @@ void cleanup_slots(struct controller *ctrl)list_del (&slot->slot_list);cancel_delayed_work (&slot->work);destroy_workqueue (slot->wq); -pci_hp_deregister (slot->hotplug_slot); -kfree (slot->hotplug_slot); +pci_hp_deregister (&slot->hotplug_slot);kfree (slot); } }
drivers/platform/x86/asus-wmi.c +9 -17
@@ -253,7 +253,7 @@ struct asus_wmi {int asus_hwmon_num_fans;int asus_hwmon_pwm; -struct hotplug_slot *hotplug_slot; +struct hotplug_slot hotplug_slot;struct mutex hotplug_lock;struct mutex wmi_lock;struct workqueue_struct *hotplug_workqueue;
@@ -743,7 +743,7 @@ static void asus_rfkill_hotplug(struct asus_wmi *asus)if (asus->wlan.rfkill)rfkill_set_sw_state (asus->wlan.rfkill, blocked); -if (asus->hotplug_slot) { +if (asus->hotplug_slot.ops) { bus =pci_find_bus (0 ,1 );if (!bus) {pr_warn ("Unable to find PCI bus 1?\n" );
@@ -848,7 +848,8 @@ static void asus_unregister_rfkill_notifier(struct asus_wmi *asus, char *node)static int asus_get_adapter_status (struct hotplug_slot *hotplug_slot,u8 *value) { -struct asus_wmi *asus = hotplug_slot->private; +struct asus_wmi *asus =container_of (hotplug_slot, + struct asus_wmi, hotplug_slot);int result =asus_wmi_get_devstate_simple (asus,ASUS_WMI_DEVID_WLAN );if (result <0 )
@@ -888,14 +889,9 @@ static int asus_setup_pci_hotplug(struct asus_wmi *asus)INIT_WORK (&asus->hotplug_work, asus_hotplug_work); - asus->hotplug_slot =kzalloc (sizeof (struct hotplug_slot ),GFP_KERNEL ); -if (!asus->hotplug_slot) - goto error_slot; + asus->hotplug_slot.ops = &asus_hotplug_slot_ops; - asus->hotplug_slot->private = asus; - asus->hotplug_slot->ops = &asus_hotplug_slot_ops; - - ret =pci_hp_register (asus->hotplug_slot, bus,0 ,"asus-wifi" ); + ret =pci_hp_register (&asus->hotplug_slot, bus,0 ,"asus-wifi" );if (ret) {pr_err ("Unable to register hotplug slot - %d\n" , ret); goto error_register;
@@ -904,9 +900,7 @@ static int asus_setup_pci_hotplug(struct asus_wmi *asus)return 0 ; error_register: -kfree (asus->hotplug_slot); - asus->hotplug_slot =NULL ; -error_slot: + asus->hotplug_slot.ops =NULL ;destroy_workqueue (asus->hotplug_workqueue); error_workqueue:return ret;
@@ -1034,10 +1028,8 @@ static void asus_wmi_rfkill_exit(struct asus_wmi *asus)* asus_unregister_rfkill_notifier() */ asus_rfkill_hotplug (asus); -if (asus->hotplug_slot) { -pci_hp_deregister (asus->hotplug_slot); -kfree (asus->hotplug_slot); - } +if (asus->hotplug_slot.ops) +pci_hp_deregister (&asus->hotplug_slot);if (asus->hotplug_workqueue)destroy_workqueue (asus->hotplug_workqueue);
drivers/platform/x86/eeepc-laptop.c +12 -18
@@ -177,7 +177,7 @@ struct eeepc_laptop {struct rfkill *wwan3g_rfkill;struct rfkill *wimax_rfkill; -struct hotplug_slot *hotplug_slot; +struct hotplug_slot hotplug_slot;struct mutex hotplug_lock;struct led_classdev tpd_led;
@@ -582,7 +582,7 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle)mutex_lock (&eeepc->hotplug_lock);pci_lock_rescan_remove (); -if (!eeepc->hotplug_slot) +if (!eeepc->hotplug_slot.ops) goto out_unlock; port =acpi_get_pci_dev (handle);
@@ -715,8 +715,11 @@ static void eeepc_unregister_rfkill_notifier(struct eeepc_laptop *eeepc,static int eeepc_get_adapter_status (struct hotplug_slot *hotplug_slot,u8 *value) { -struct eeepc_laptop *eeepc = hotplug_slot->private; -int val =get_acpi (eeepc,CM_ASL_WLAN ); +struct eeepc_laptop *eeepc; +int val; + + eeepc = container_of(hotplug_slot, struct eeepc_laptop, hotplug_slot); + val =get_acpi (eeepc,CM_ASL_WLAN );if (val ==1 || val ==0 ) *value = val;
@@ -741,14 +744,9 @@ static int eeepc_setup_pci_hotplug(struct eeepc_laptop *eeepc)return -ENODEV ; } - eeepc->hotplug_slot =kzalloc (sizeof (struct hotplug_slot ),GFP_KERNEL ); -if (!eeepc->hotplug_slot) - goto error_slot; + eeepc->hotplug_slot.ops = &eeepc_hotplug_slot_ops; - eeepc->hotplug_slot->private = eeepc; - eeepc->hotplug_slot->ops = &eeepc_hotplug_slot_ops; - - ret =pci_hp_register (eeepc->hotplug_slot, bus,0 ,"eeepc-wifi" ); + ret =pci_hp_register (&eeepc->hotplug_slot, bus,0 ,"eeepc-wifi" );if (ret) {pr_err ("Unable to register hotplug slot - %d\n" , ret); goto error_register;
@@ -757,9 +755,7 @@ static int eeepc_setup_pci_hotplug(struct eeepc_laptop *eeepc)return 0 ; error_register: -kfree (eeepc->hotplug_slot); - eeepc->hotplug_slot =NULL ; -error_slot: + eeepc->hotplug_slot.ops =NULL ;return ret; }
@@ -820,10 +816,8 @@ static void eeepc_rfkill_exit(struct eeepc_laptop *eeepc) eeepc->wlan_rfkill =NULL ; } -if (eeepc->hotplug_slot) { -pci_hp_deregister (eeepc->hotplug_slot); -kfree (eeepc->hotplug_slot); - } +if (eeepc->hotplug_slot.ops) +pci_hp_deregister (&eeepc->hotplug_slot);if (eeepc->bluetooth_rfkill) {rfkill_unregister (eeepc->bluetooth_rfkill);
include/linux/pci_hotplug.h +0 -3
@@ -50,14 +50,11 @@ 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 -* @private: used by the hotplug pci controller driver to store whatever it -* needs. * @owner: The module owner of this structure * @mod_name: The module name (KBUILD_MODNAME) of this structure */ struct hotplug_slot {const struct hotplug_slot_ops *ops; -void *private;/* Variables below this are for use only by the hotplug pci core. */ struct list_head slot_list;
Signature · 1 line
2.18.0
Re: [PATCH 8/9] PCI: hotplug: Embed hotplug_slot
Quoted 62 lines · Lukas Wunner
When the PCI hotplug core and its first user, cpqphp, were introduced in February 2002 with historic commit
a8a2069f432c, cpqphp allocated a slot struct for its internal use plus ahotplug_slotstruct to be registered with the hotplug core and linked the two with pointers:
https://git.kernel.org/tglx/history/c/a8a2069f432cNowadays, the predominant pattern in the tree is to embed ("subclass") such structures in one another and cast to the containing struct with
container_of(). But it wasn't until July 2002 thatcontainer_of()was introduced with historic commitec4f214232cf:
https://git.kernel.org/tglx/history/c/ec4f214232cf
pnv_php, introduced in 2016, did the right thing and embedded structhotplug_slotin its internal structpnv_php_slot, but all other drivers cargo-culted cpqphp's design and linked separate structs with pointers.Embedding structs is preferrable to linking them with pointers because it requires fewer allocations, thereby reducing overhead and simplifying error paths. Casting an embedded struct to the containing struct becomes a cheap subtraction rather than a dereference. And having fewer pointers reduces the risk of them pointing nowhere either accidentally or due to an attack.
Convert all drivers to embed struct
hotplug_slotin their internal slot struct. The "private" pointer in structhotplug_slotthereby becomes unused, so drop it.Signed-off-by Lukas Wunner <[email protected]>Cc Rafael J. Wysocki <[email protected]>Cc Len Brown <[email protected]>Cc Scott Murray <[email protected]>Cc Benjamin Herrenschmidt <[email protected]>Cc Paul Mackerras <[email protected]>Cc Michael Ellerman <[email protected]>Cc Gavin Shan <[email protected]>Cc Sebastian Ott <[email protected]>Cc Gerald Schaefer <[email protected]>Cc Corentin Chary <[email protected]>Cc Darren Hart <[email protected]>Cc Andy Shevchenko <[email protected]>--- drivers/pci/hotplug/acpiphp.h | 9 ++- drivers/pci/hotplug/acpiphp_core.c | 28 +++----- drivers/pci/hotplug/acpiphp_ibm.c | 2 +- drivers/pci/hotplug/cpci_hotplug.h | 9 ++- drivers/pci/hotplug/cpci_hotplug_core.c | 37 ++++------ drivers/pci/hotplug/cpci_hotplug_pci.c | 6 +- drivers/pci/hotplug/cpqphp.h | 9 ++- drivers/pci/hotplug/cpqphp_core.c | 37 ++++------ drivers/pci/hotplug/cpqphp_ctrl.c | 2 - drivers/pci/hotplug/ibmphp.h | 7 +- drivers/pci/hotplug/ibmphp_core.c | 92 +++++++++++-------------- drivers/pci/hotplug/ibmphp_ebda.c | 37 +++------- drivers/pci/hotplug/pciehp.h | 11 ++- drivers/pci/hotplug/pciehp_core.c | 37 ++++------ drivers/pci/hotplug/pciehp_ctrl.c | 4 +- drivers/pci/hotplug/pciehp_hpc.c | 8 +-- drivers/pci/hotplug/pnv_php.c | 9 ++- drivers/pci/hotplug/rpaphp.h | 7 +- drivers/pci/hotplug/rpaphp_core.c | 14 ++-- drivers/pci/hotplug/rpaphp_slot.c | 15 ++--
Quoted 8 lines
drivers/pci/hotplug/s390_pci_hpc.c | 30 ++++---- drivers/pci/hotplug/sgi_hotplug.c | 52 ++++++-------- drivers/pci/hotplug/shpchp.h | 6 +- drivers/pci/hotplug/shpchp_core.c | 17 ++--- drivers/platform/x86/asus-wmi.c | 26 +++---- drivers/platform/x86/eeepc-laptop.c | 30 ++++---- include/linux/pci_hotplug.h | 3 - 27 files changed, 223 insertions(+), 321 deletions(-)
Good cleanup.
Re: [PATCH 8/9] PCI: hotplug: Embed hotplug_slot
In reply to Lukas WunnerQuoted 27 lines · Lukas Wunner
When the PCI hotplug core and its first user, cpqphp, were introduced in February 2002 with historic commit
a8a2069f432c, cpqphp allocated a slot struct for its internal use plus ahotplug_slotstruct to be registered with the hotplug core and linked the two with pointers:
https://git.kernel.org/tglx/history/c/a8a2069f432cNowadays, the predominant pattern in the tree is to embed ("subclass") such structures in one another and cast to the containing struct with
container_of(). But it wasn't until July 2002 thatcontainer_of()was introduced with historic commitec4f214232cf:
https://git.kernel.org/tglx/history/c/ec4f214232cf
pnv_php, introduced in 2016, did the right thing and embedded structhotplug_slotin its internal structpnv_php_slot, but all other drivers cargo-culted cpqphp's design and linked separate structs with pointers.Embedding structs is preferrable to linking them with pointers because it requires fewer allocations, thereby reducing overhead and simplifying error paths. Casting an embedded struct to the containing struct becomes a cheap subtraction rather than a dereference. And having fewer pointers reduces the risk of them pointing nowhere either accidentally or due to an attack.
Convert all drivers to embed struct
hotplug_slotin their internal slot struct. The "private" pointer in structhotplug_slotthereby becomes unused, so drop it.
Quoted 12 lines
Signed-off-by Lukas Wunner <[email protected]>Cc Rafael J. Wysocki <[email protected]>Cc Len Brown <[email protected]>Cc Scott Murray <[email protected]>Cc Benjamin Herrenschmidt <[email protected]>Cc Paul Mackerras <[email protected]>Cc Michael Ellerman <[email protected]>Cc Gavin Shan <[email protected]>Cc Sebastian Ott <[email protected]>Cc Gerald Schaefer <[email protected]>Cc Corentin Chary <[email protected]>Cc Darren Hart <[email protected]
With regards to driver/pci/hotplug/rpa*
Re: [PATCH 8/9] PCI: hotplug: Embed hotplug_slot
In reply to Lukas WunnerQuoted 27 lines · Lukas Wunner
When the PCI hotplug core and its first user, cpqphp, were introduced in February 2002 with historic commit
a8a2069f432c, cpqphp allocated a slot struct for its internal use plus ahotplug_slotstruct to be registered with the hotplug core and linked the two with pointers:
https://git.kernel.org/tglx/history/c/a8a2069f432cNowadays, the predominant pattern in the tree is to embed ("subclass") such structures in one another and cast to the containing struct with
container_of(). But it wasn't until July 2002 thatcontainer_of()was introduced with historic commitec4f214232cf:
https://git.kernel.org/tglx/history/c/ec4f214232cf
pnv_php, introduced in 2016, did the right thing and embedded structhotplug_slotin its internal structpnv_php_slot, but all other drivers cargo-culted cpqphp's design and linked separate structs with pointers.Embedding structs is preferrable to linking them with pointers because it requires fewer allocations, thereby reducing overhead and simplifying error paths. Casting an embedded struct to the containing struct becomes a cheap subtraction rather than a dereference. And having fewer pointers reduces the risk of them pointing nowhere either accidentally or due to an attack.
Convert all drivers to embed struct
hotplug_slotin their internal slot struct. The "private" pointer in structhotplug_slotthereby becomes unused, so drop it.
Quoted 13 lines
Signed-off-by Lukas Wunner <[email protected]>Cc Rafael J. Wysocki <[email protected]>Cc Len Brown <[email protected]>Cc Scott Murray <[email protected]>Cc Benjamin Herrenschmidt <[email protected]>Cc Paul Mackerras <[email protected]>Cc Michael Ellerman <[email protected]>Cc Gavin Shan <[email protected]>Cc Sebastian Ott <[email protected]>Cc Gerald Schaefer <[email protected]>Cc Corentin Chary <[email protected]>Cc Darren Hart <[email protected]>Cc Andy Shevchenko <[email protected]>
for s390_pci_hpc.c:
PATCH 9/9 PCI: hotplug: Document TODOs
In reply to Lukas WunnerWhile refactoring the PCI hotplug core's API, I noticed a significant amount of technical debt in some of the hotplug drivers. Document the issues that caught my eye for starters.
I do not have hardware at my disposal that utilizes the listed drivers and I think that's a prerequisite to work on them to ensure that no regressions sneak in. But some of this hardware is so old that it may be hard to come by. Obviously, it is fine to support old hardware, but the drivers need to be maintained.
If noone steps up, perhaps we should consider sunsetting a few drivers by moving them to staging. Based on my findings, ibmphp would be the first candidate. I've found it fairly difficult to apply my API refactorings to it and have listed some obvious bugs in the driver. cpqphp is also in need of a modernization and would be a second candidate for relegation to staging.
shpchp was introduced in the same commit as pciehp but hasn't benefited from the same amount of refactoring due to the decline of conventional PCI's relevance. Yet hardware supporting it may be more prevalent than for the proprietary hotplug methods.
Per Documentation/process/2.Process.rst, "a TODO file should be present" for drivers in staging. The file introduced by the present commit may serve as a basis for this.
--- drivers/pci/hotplug/TODO | 74 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 drivers/pci/hotplug/TODO
drivers/pci/hotplug/TODO new file +74 -0
@@ -0,0 +1,74 @@ +Contributions are solicited in particular to remedy the following issues: + +cpcihp: + +* There are no implementations of the ->hardware_test, ->get_power and + ->set_power callbacks in struct cpci_hp_controller_ops. Why were they + introduced? Can they be removed from the struct? + +cpqphp: + +* The driver spawns a kthread cpqhp_event_thread() which is woken by the + hardirq handler cpqhp_ctrl_intr(). Convert this to threaded IRQ handling. + The kthread is also woken from the timer pushbutton_helper_thread(), + convert it to call irq_wake_thread(). Use pciehp as a template. + +* A large portion of cpqphp_ctrl.c and cpqphp_pci.c concerns resource + management. Doesn't this duplicate functionality in the core? + +ibmphp: + +* Implementations of hotplug_slot_ops callbacks such as get_adapter_present() + in ibmphp_core.c create a copy of the struct slot on the stack, then perform + the actual operation on that copy. Determine if this overhead is necessary, + delete it if not. The functions also perform a NULL pointer check on the + struct hotplug_slot, this seems superfluous. + +* Several functions access the pci_slot member in struct hotplug_slot even + though pci_hotplug.h declares it private. See get_max_bus_speed() for an + example. Either the pci_slot member should no longer be declared private + or ibmphp should store a pointer to its bus in struct slot. Probably the + former. + +* The functions get_max_adapter_speed() and get_bus_name() are commented out. + Can they be deleted? There are also forward declarations at the top of + ibmphp_core.c as well as pointers in ibmphp_hotplug_slot_ops, likewise + commented out. + +* ibmphp_init_devno() takes a struct slot **, it could instead take a + struct slot *. + +* The return value of pci_hp_register() is not checked. + +* iounmap(io_mem) is called in the error path of ebda_rsrc_controller() + and once more in the error path of its caller ibmphp_access_ebda(). + +* The various slot data structures are difficult to follow and need to be + simplified. A lot of functions are too large and too complex, they need + to be broken up into smaller, manageable pieces. Negative examples are + ebda_rsrc_controller() and configure_bridge(). + +* A large portion of ibmphp_res.c and ibmphp_pci.c concerns resource + management. Doesn't this duplicate functionality in the core? + +sgi_hotplug: + +* Several functions access the pci_slot member in struct hotplug_slot even + though pci_hotplug.h declares it private. See sn_hp_destroy() for an + example. Either the pci_slot member should no longer be declared private + or sgi_hotplug should store a pointer to it in struct slot. Probably the + former. + +shpchp: + +* There is only a single implementation of struct hpc_ops. Can the struct be + removed and its functions invoked directly? This has already been done in + pciehp with commit 82a9e79ef132 ("PCI: pciehp: remove hpc_ops"). Clarify + if there was a specific reason not to apply the same change to shpchp. + +* The ->get_mode1_ECC_cap callback in shpchp_hpc_ops is never invoked. + Why was it introduced? Can it be removed? + +* The hardirq handler shpc_isr() queues events on a workqueue. It can be + simplified by converting it to threaded IRQ handling. Use pciehp as a + template.
Signature · 1 line
2.18.0
Quoted 9 lines · Lukas Wunner
Here's PCI hotplug material I've prepared for v4.20:
Patches [1/9] to [8/9] reduce the code by 488 lines. There should be no loss of functionality and no new features, just less and simpler code.
Patch [9/9] collects TODOs for hotplug drivers to spur contributions.
Quoted 8 lines
I've assumed that my patch "PCI: pciehp: Differentiate between surprise and safe removal" (submitted July 31) gets merged before this series:
https://patchwork.ozlabs.org/patch/951386/If that patch is not accepted or other pciehp-related patches are merged before this series, I'll have to rebase patch [4/9] ("PCI: pciehp: Unify controller and slot structs"). No big deal, just a heads-up.
for PDx86 bits
Quoted 58 lines
Thanks,
Lukas
Lukas Wunner (9):
PCI: Simplify disconnected marking
PCI: pciehp: Drop unnecessary includes
PCI: pciehp: Drophotplug_slot_opswrappers
PCI: pciehp: Unify controller and slot structs
PCI: pciehp: Reshuffle controller struct for clarity
PCI: hotplug: Constifyhotplug_slot_ops
PCI: hotplug: Drophotplug_slot_info
PCI: hotplug: Embedhotplug_slot
PCI: hotplug: Document TODOsarch/powerpc/include/asm/pnv-pci.h | 2 +- drivers/pci/hotplug/TODO | 74 +++++++ drivers/pci/hotplug/acpiphp.h | 10 +- drivers/pci/hotplug/acpiphp_core.c | 36 +--- drivers/pci/hotplug/acpiphp_ibm.c | 2 +- drivers/pci/hotplug/cpci_hotplug.h | 11 +- drivers/pci/hotplug/cpci_hotplug_core.c | 105 +++------- drivers/pci/hotplug/cpci_hotplug_pci.c | 6 +- drivers/pci/hotplug/cpqphp.h | 9 +- drivers/pci/hotplug/cpqphp_core.c | 59 ++---- drivers/pci/hotplug/cpqphp_ctrl.c | 31 +-- drivers/pci/hotplug/ibmphp.h | 9 +- drivers/pci/hotplug/ibmphp_core.c | 121 ++++------- drivers/pci/hotplug/ibmphp_ebda.c | 70 +------ drivers/pci/hotplug/pci_hotplug_core.c | 53 ++--- drivers/pci/hotplug/pciehp.h | 138 ++++++------- drivers/pci/hotplug/pciehp_core.c | 127 +++--------- drivers/pci/hotplug/pciehp_ctrl.c | 255 +++++++++++------------- drivers/pci/hotplug/pciehp_hpc.c | 127 ++++-------- drivers/pci/hotplug/pciehp_pci.c | 24 +-- drivers/pci/hotplug/pnv_php.c | 35 ++-- drivers/pci/hotplug/rpaphp.h | 10 +- drivers/pci/hotplug/rpaphp_core.c | 20 +- drivers/pci/hotplug/rpaphp_pci.c | 11 +- drivers/pci/hotplug/rpaphp_slot.c | 22 +- drivers/pci/hotplug/s390_pci_hpc.c | 44 ++-- drivers/pci/hotplug/sgi_hotplug.c | 63 +++--- drivers/pci/hotplug/shpchp.h | 8 +- drivers/pci/hotplug/shpchp_core.c | 48 ++--- drivers/pci/hotplug/shpchp_ctrl.c | 21 +- drivers/pci/pci.c | 4 +- drivers/pci/pcie/err.c | 8 +- drivers/pci/slot.c | 2 +- drivers/platform/x86/asus-wmi.c | 39 +--- drivers/platform/x86/eeepc-laptop.c | 43 ++-- include/linux/pci_hotplug.h | 43 +--- 36 files changed, 638 insertions(+), 1052 deletions(-) create mode 100644 drivers/pci/hotplug/TODO--
2.18.0
Signature · 2 lines
With Best Regards, Andy Shevchenko