Skip to content

Commit

Permalink
device property: Get rid of struct fwnode_handle type field
Browse files Browse the repository at this point in the history
Instead of relying on the struct fwnode_handle type field, define
fwnode_operations structs for all separate types of fwnodes. To find out
the type, compare to the ops field to relevant ops structs.

This change has two benefits:

1. it avoids adding the type field to each and every instance of struct
fwnode_handle, thus saving memory and

2. makes the ops field the single factor that defines both the types of
the fwnode as well as defines the implementation of its operations,
decreasing the possibility of bugs when developing code dealing with
fwnode internals.

Suggested-by: Rob Herring <robh@kernel.org>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
  • Loading branch information
Sakari Ailus authored and Rafael J. Wysocki committed Jul 21, 2017
1 parent b81b729 commit db3e50f
Show file tree
Hide file tree
Showing 10 changed files with 60 additions and 52 deletions.
47 changes: 28 additions & 19 deletions drivers/acpi/property.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ static bool acpi_nondev_subnode_extract(const union acpi_object *desc,
return false;

dn->name = link->package.elements[0].string.pointer;
dn->fwnode.type = FWNODE_ACPI_DATA;
dn->fwnode.ops = &acpi_fwnode_ops;
dn->fwnode.ops = &acpi_data_fwnode_ops;
dn->parent = parent;
INIT_LIST_HEAD(&dn->data.subnodes);

Expand Down Expand Up @@ -469,10 +468,10 @@ EXPORT_SYMBOL_GPL(acpi_dev_get_property);

static struct acpi_device_data *acpi_device_data_of_node(struct fwnode_handle *fwnode)
{
if (fwnode->type == FWNODE_ACPI) {
if (is_acpi_device_node(fwnode)) {
struct acpi_device *adev = to_acpi_device_node(fwnode);
return &adev->data;
} else if (fwnode->type == FWNODE_ACPI_DATA) {
} else if (is_acpi_data_node(fwnode)) {
struct acpi_data_node *dn = to_acpi_data_node(fwnode);
return &dn->data;
}
Expand Down Expand Up @@ -903,7 +902,7 @@ struct fwnode_handle *acpi_get_next_subnode(struct fwnode_handle *fwnode,
struct acpi_device *adev = to_acpi_device_node(fwnode);
struct list_head *head, *next;

if (!child || child->type == FWNODE_ACPI) {
if (!child || is_acpi_device_node(child)) {
if (adev)
head = &adev->children;
else
Expand All @@ -927,7 +926,7 @@ struct fwnode_handle *acpi_get_next_subnode(struct fwnode_handle *fwnode,
}

nondev:
if (!child || child->type == FWNODE_ACPI_DATA) {
if (!child || is_acpi_data_node(child)) {
struct acpi_data_node *data = to_acpi_data_node(fwnode);
struct acpi_data_node *dn;

Expand Down Expand Up @@ -1223,16 +1222,26 @@ static int acpi_fwnode_graph_parse_endpoint(struct fwnode_handle *fwnode,
return 0;
}

const struct fwnode_operations acpi_fwnode_ops = {
.device_is_available = acpi_fwnode_device_is_available,
.property_present = acpi_fwnode_property_present,
.property_read_int_array = acpi_fwnode_property_read_int_array,
.property_read_string_array = acpi_fwnode_property_read_string_array,
.get_parent = acpi_node_get_parent,
.get_next_child_node = acpi_get_next_subnode,
.get_named_child_node = acpi_fwnode_get_named_child_node,
.graph_get_next_endpoint = acpi_fwnode_graph_get_next_endpoint,
.graph_get_remote_endpoint = acpi_fwnode_graph_get_remote_endpoint,
.graph_get_port_parent = acpi_node_get_parent,
.graph_parse_endpoint = acpi_fwnode_graph_parse_endpoint,
};
#define DECLARE_ACPI_FWNODE_OPS(ops) \
const struct fwnode_operations ops = { \
.device_is_available = acpi_fwnode_device_is_available, \
.property_present = acpi_fwnode_property_present, \
.property_read_int_array = \
acpi_fwnode_property_read_int_array, \
.property_read_string_array = \
acpi_fwnode_property_read_string_array, \
.get_parent = acpi_node_get_parent, \
.get_next_child_node = acpi_get_next_subnode, \
.get_named_child_node = acpi_fwnode_get_named_child_node, \
.graph_get_next_endpoint = \
acpi_fwnode_graph_get_next_endpoint, \
.graph_get_remote_endpoint = \
acpi_fwnode_graph_get_remote_endpoint, \
.graph_get_port_parent = acpi_node_get_parent, \
.graph_parse_endpoint = acpi_fwnode_graph_parse_endpoint, \
}; \
EXPORT_SYMBOL_GPL(ops)

DECLARE_ACPI_FWNODE_OPS(acpi_device_fwnode_ops);
DECLARE_ACPI_FWNODE_OPS(acpi_data_fwnode_ops);
const struct fwnode_operations acpi_static_fwnode_ops;
3 changes: 1 addition & 2 deletions drivers/acpi/scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -1467,8 +1467,7 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
device->device_type = type;
device->handle = handle;
device->parent = acpi_bus_get_parent(handle);
device->fwnode.type = FWNODE_ACPI;
device->fwnode.ops = &acpi_fwnode_ops;
device->fwnode.ops = &acpi_device_fwnode_ops;
acpi_set_device_status(device, sta);
acpi_device_get_busid(device);
acpi_set_pnp_ids(handle, &device->pnp, type);
Expand Down
5 changes: 3 additions & 2 deletions drivers/base/property.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ struct property_set {
const struct property_entry *properties;
};

static const struct fwnode_operations pset_fwnode_ops;

static inline bool is_pset_node(struct fwnode_handle *fwnode)
{
return !IS_ERR_OR_NULL(fwnode) && fwnode->type == FWNODE_PDATA;
return !IS_ERR_OR_NULL(fwnode) && fwnode->ops == &pset_fwnode_ops;
}

static inline struct property_set *to_pset_node(struct fwnode_handle *fwnode)
Expand Down Expand Up @@ -900,7 +902,6 @@ int device_add_properties(struct device *dev,
if (IS_ERR(p))
return PTR_ERR(p);

p->fwnode.type = FWNODE_PDATA;
p->fwnode.ops = &pset_fwnode_ops;
set_secondary_fwnode(dev, &p->fwnode);
return 0;
Expand Down
1 change: 1 addition & 0 deletions drivers/of/property.c
Original file line number Diff line number Diff line change
Expand Up @@ -952,3 +952,4 @@ const struct fwnode_operations of_fwnode_ops = {
.graph_get_port_parent = of_fwnode_graph_get_port_parent,
.graph_parse_endpoint = of_fwnode_graph_parse_endpoint,
};
EXPORT_SYMBOL_GPL(of_fwnode_ops);
20 changes: 16 additions & 4 deletions include/acpi/acpi_bus.h
Original file line number Diff line number Diff line change
Expand Up @@ -395,15 +395,21 @@ struct acpi_data_node {
struct completion kobj_done;
};

extern const struct fwnode_operations acpi_device_fwnode_ops;
extern const struct fwnode_operations acpi_data_fwnode_ops;
extern const struct fwnode_operations acpi_static_fwnode_ops;

static inline bool is_acpi_node(struct fwnode_handle *fwnode)
{
return !IS_ERR_OR_NULL(fwnode) && (fwnode->type == FWNODE_ACPI
|| fwnode->type == FWNODE_ACPI_DATA);
return !IS_ERR_OR_NULL(fwnode) &&
(fwnode->ops == &acpi_device_fwnode_ops
|| fwnode->ops == &acpi_data_fwnode_ops);
}

static inline bool is_acpi_device_node(struct fwnode_handle *fwnode)
{
return !IS_ERR_OR_NULL(fwnode) && fwnode->type == FWNODE_ACPI;
return !IS_ERR_OR_NULL(fwnode) &&
fwnode->ops == &acpi_device_fwnode_ops;
}

static inline struct acpi_device *to_acpi_device_node(struct fwnode_handle *fwnode)
Expand All @@ -414,7 +420,7 @@ static inline struct acpi_device *to_acpi_device_node(struct fwnode_handle *fwno

static inline bool is_acpi_data_node(struct fwnode_handle *fwnode)
{
return !IS_ERR_OR_NULL(fwnode) && fwnode->type == FWNODE_ACPI_DATA;
return !IS_ERR_OR_NULL(fwnode) && fwnode->ops == &acpi_data_fwnode_ops;
}

static inline struct acpi_data_node *to_acpi_data_node(struct fwnode_handle *fwnode)
Expand All @@ -423,6 +429,12 @@ static inline struct acpi_data_node *to_acpi_data_node(struct fwnode_handle *fwn
container_of(fwnode, struct acpi_data_node, fwnode) : NULL;
}

static inline bool is_acpi_static_node(struct fwnode_handle *fwnode)
{
return !IS_ERR_OR_NULL(fwnode) &&
fwnode->ops == &acpi_static_fwnode_ops;
}

static inline bool acpi_data_node_match(struct fwnode_handle *fwnode,
const char *name)
{
Expand Down
8 changes: 2 additions & 6 deletions include/linux/acpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,6 @@ static inline acpi_handle acpi_device_handle(struct acpi_device *adev)
acpi_fwnode_handle(adev) : NULL)
#define ACPI_HANDLE(dev) acpi_device_handle(ACPI_COMPANION(dev))


extern const struct fwnode_operations acpi_fwnode_ops;

static inline struct fwnode_handle *acpi_alloc_fwnode_static(void)
{
struct fwnode_handle *fwnode;
Expand All @@ -68,15 +65,14 @@ static inline struct fwnode_handle *acpi_alloc_fwnode_static(void)
if (!fwnode)
return NULL;

fwnode->type = FWNODE_ACPI_STATIC;
fwnode->ops = &acpi_fwnode_ops;
fwnode->ops = &acpi_static_fwnode_ops;

return fwnode;
}

static inline void acpi_free_fwnode_static(struct fwnode_handle *fwnode)
{
if (WARN_ON(!fwnode || fwnode->type != FWNODE_ACPI_STATIC))
if (WARN_ON(!is_acpi_static_node(fwnode)))
return;

kfree(fwnode);
Expand Down
11 changes: 0 additions & 11 deletions include/linux/fwnode.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,9 @@

#include <linux/types.h>

enum fwnode_type {
FWNODE_INVALID = 0,
FWNODE_OF,
FWNODE_ACPI,
FWNODE_ACPI_DATA,
FWNODE_ACPI_STATIC,
FWNODE_PDATA,
FWNODE_IRQCHIP
};

struct fwnode_operations;

struct fwnode_handle {
enum fwnode_type type;
struct fwnode_handle *secondary;
const struct fwnode_operations *ops;
};
Expand Down
4 changes: 3 additions & 1 deletion include/linux/irqdomain.h
Original file line number Diff line number Diff line change
Expand Up @@ -265,9 +265,11 @@ static inline struct fwnode_handle *of_node_to_fwnode(struct device_node *node)
return node ? &node->fwnode : NULL;
}

extern const struct fwnode_operations irqchip_fwnode_ops;

static inline bool is_fwnode_irqchip(struct fwnode_handle *fwnode)
{
return fwnode && fwnode->type == FWNODE_IRQCHIP;
return fwnode && fwnode->ops == &irqchip_fwnode_ops;
}

extern void irq_domain_update_bus_token(struct irq_domain *domain,
Expand Down
3 changes: 1 addition & 2 deletions include/linux/of.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ extern const struct fwnode_operations of_fwnode_ops;
static inline void of_node_init(struct device_node *node)
{
kobject_init(&node->kobj, &of_node_ktype);
node->fwnode.type = FWNODE_OF;
node->fwnode.ops = &of_fwnode_ops;
}

Expand Down Expand Up @@ -152,7 +151,7 @@ void of_core_init(void);

static inline bool is_of_node(const struct fwnode_handle *fwnode)
{
return !IS_ERR_OR_NULL(fwnode) && fwnode->type == FWNODE_OF;
return !IS_ERR_OR_NULL(fwnode) && fwnode->ops == &of_fwnode_ops;
}

#define to_of_node(__fwnode) \
Expand Down
10 changes: 5 additions & 5 deletions kernel/irq/irqdomain.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ static inline void debugfs_add_domain_dir(struct irq_domain *d) { }
static inline void debugfs_remove_domain_dir(struct irq_domain *d) { }
#endif

const struct fwnode_operations irqchip_fwnode_ops;

/**
* irq_domain_alloc_fwnode - Allocate a fwnode_handle suitable for
* identifying an irq domain
Expand Down Expand Up @@ -86,7 +88,7 @@ struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int type, int id,
fwid->type = type;
fwid->name = n;
fwid->data = data;
fwid->fwnode.type = FWNODE_IRQCHIP;
fwid->fwnode.ops = &irqchip_fwnode_ops;
return &fwid->fwnode;
}
EXPORT_SYMBOL_GPL(__irq_domain_alloc_fwnode);
Expand Down Expand Up @@ -193,10 +195,8 @@ struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
}

if (!domain->name) {
if (fwnode) {
pr_err("Invalid fwnode type (%d) for irqdomain\n",
fwnode->type);
}
if (fwnode)
pr_err("Invalid fwnode type for irqdomain\n");
domain->name = kasprintf(GFP_KERNEL, "unknown-%d",
atomic_inc_return(&unknown_domains));
if (!domain->name) {
Expand Down

0 comments on commit db3e50f

Please sign in to comment.