Skip to content

Commit

Permalink
PCI: hotplug: Embed hotplug_slot
Browse files Browse the repository at this point in the history
When the PCI hotplug core and its first user, cpqphp, were introduced in
February 2002 with historic commit a8a2069, 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 ec4f214:
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.

Signed-off-by: Lukas Wunner <[email protected]>
Signed-off-by: Bjorn Helgaas <[email protected]>
Reviewed-by: Rafael J. Wysocki <[email protected]>
Acked-by: Tyrel Datwyler <[email protected]>  # drivers/pci/hotplug/rpa*
Acked-by: Sebastian Ott <[email protected]>        # drivers/pci/hotplug/s390*
Acked-by: Andy Shevchenko <[email protected]> # drivers/platform/x86
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: Oliver OHalloran <[email protected]>
Cc: Gavin Shan <[email protected]>
Cc: Gerald Schaefer <[email protected]>
Cc: Corentin Chary <[email protected]>
Cc: Darren Hart <[email protected]>
  • Loading branch information
l1k authored and bjorn-helgaas committed Sep 18, 2018
1 parent a7da216 commit 125450f
Show file tree
Hide file tree
Showing 27 changed files with 223 additions and 321 deletions.
9 changes: 7 additions & 2 deletions drivers/pci/hotplug/acpiphp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/*
Expand Down
28 changes: 10 additions & 18 deletions drivers/pci/hotplug/acpiphp_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand All @@ -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));

Expand Down Expand Up @@ -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));

Expand Down Expand Up @@ -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));

Expand All @@ -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));

Expand All @@ -266,33 +266,26 @@ 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;

acpiphp_slot->slot = 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:
Expand All @@ -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);
}

Expand Down
2 changes: 1 addition & 1 deletion drivers/pci/hotplug/acpiphp_ibm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 7 additions & 2 deletions drivers/pci/hotplug/cpci_hotplug.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ struct slot {
unsigned int latch_status:1;
unsigned int adapter_status:1;
unsigned int extracting;
struct hotplug_slot *hotplug_slot;
struct hotplug_slot hotplug_slot;
struct list_head slot_list;
};

Expand All @@ -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);
Expand Down
37 changes: 12 additions & 25 deletions drivers/pci/hotplug/cpci_hotplug_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -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));
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -172,15 +172,14 @@ 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;
}

static void release_slot(struct slot *slot)
{
kfree(slot->hotplug_slot);
pci_dev_put(slot->dev);
kfree(slot);
}
Expand All @@ -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;
Expand All @@ -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));

Expand All @@ -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:
Expand All @@ -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);
}
}
Expand Down Expand Up @@ -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:
Expand Down
6 changes: 2 additions & 4 deletions drivers/pci/hotplug/cpci_hotplug_pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -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;
}
}
Expand Down
9 changes: 7 additions & 2 deletions drivers/pci/hotplug/cpqphp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
}

/*
Expand Down
Loading

0 comments on commit 125450f

Please sign in to comment.