[PATCH] pinctrl: intel: use FAM for communities
From: Rosen Penev
Date: Wed Mar 25 2026 - 22:40:15 EST
Use a flexible array member to combine allocations into one.
Add __counted_by for extra runtime analysis. Move counting variable
assignments to after allocation as required by __counted_by.
Signed-off-by: Rosen Penev <rosenp@xxxxxxxxx>
---
drivers/pinctrl/intel/pinctrl-baytrail.c | 43 +++++++---------------
drivers/pinctrl/intel/pinctrl-cherryview.c | 11 ++----
drivers/pinctrl/intel/pinctrl-intel.c | 15 ++------
drivers/pinctrl/intel/pinctrl-intel.h | 2 +-
drivers/pinctrl/intel/pinctrl-lynxpoint.c | 9 +----
5 files changed, 25 insertions(+), 55 deletions(-)
diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c
index b733ec31ad9d..e73419498857 100644
--- a/drivers/pinctrl/intel/pinctrl-baytrail.c
+++ b/drivers/pinctrl/intel/pinctrl-baytrail.c
@@ -1558,31 +1558,6 @@ static int byt_gpio_probe(struct intel_pinctrl *vg)
return 0;
}
-static int byt_set_soc_data(struct intel_pinctrl *vg,
- const struct intel_pinctrl_soc_data *soc)
-{
- struct platform_device *pdev = to_platform_device(vg->dev);
- int i;
-
- vg->soc = soc;
-
- vg->ncommunities = vg->soc->ncommunities;
- vg->communities = devm_kmemdup_array(vg->dev, vg->soc->communities, vg->ncommunities,
- sizeof(*vg->soc->communities), GFP_KERNEL);
- if (!vg->communities)
- return -ENOMEM;
-
- for (i = 0; i < vg->soc->ncommunities; i++) {
- struct intel_community *comm = vg->communities + i;
-
- comm->pad_regs = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(comm->pad_regs))
- return PTR_ERR(comm->pad_regs);
- }
-
- return 0;
-}
-
static const struct acpi_device_id byt_gpio_acpi_match[] = {
{ "INT33B2", (kernel_ulong_t)byt_soc_data },
{ "INT33FC", (kernel_ulong_t)byt_soc_data },
@@ -1595,19 +1570,29 @@ static int byt_pinctrl_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct intel_pinctrl *vg;
int ret;
+ int i;
soc_data = intel_pinctrl_get_soc_data(pdev);
if (IS_ERR(soc_data))
return PTR_ERR(soc_data);
- vg = devm_kzalloc(dev, sizeof(*vg), GFP_KERNEL);
+ vg = devm_kzalloc(dev, struct_size(vg, communities, soc_data->ncommunities), GFP_KERNEL);
if (!vg)
return -ENOMEM;
+ vg->ncommunities = soc_data->ncommunities;
+ memcpy(vg->communities, soc_data->communities, soc_data->ncommunities * sizeof(*vg->communities));
+
vg->dev = dev;
- ret = byt_set_soc_data(vg, soc_data);
- if (ret)
- return dev_err_probe(dev, ret, "failed to set soc data\n");
+ vg->soc = soc_data;
+
+ for (i = 0; i < vg->soc->ncommunities; i++) {
+ struct intel_community *comm = vg->communities + i;
+
+ comm->pad_regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(comm->pad_regs))
+ return PTR_ERR(comm->pad_regs);
+ }
vg->pctldesc = byt_pinctrl_desc;
vg->pctldesc.name = dev_name(dev);
diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c
index a33eca5eafc4..e9b062b44fea 100644
--- a/drivers/pinctrl/intel/pinctrl-cherryview.c
+++ b/drivers/pinctrl/intel/pinctrl-cherryview.c
@@ -1595,19 +1595,16 @@ static int chv_pinctrl_probe(struct platform_device *pdev)
if (IS_ERR(soc_data))
return PTR_ERR(soc_data);
- pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL);
+ pctrl = devm_kzalloc(dev, struct_size(pctrl, communities, soc_data->ncommunities), GFP_KERNEL);
if (!pctrl)
return -ENOMEM;
+ pctrl->ncommunities = soc_data->ncommunities;
+ memcpy(pctrl->communities, soc_data->communities, soc_data->ncommunities * sizeof(*pctrl->communities));
+
pctrl->dev = dev;
pctrl->soc = soc_data;
- pctrl->ncommunities = pctrl->soc->ncommunities;
- pctrl->communities = devm_kmemdup_array(dev, pctrl->soc->communities, pctrl->ncommunities,
- sizeof(*pctrl->soc->communities), GFP_KERNEL);
- if (!pctrl->communities)
- return -ENOMEM;
-
community = &pctrl->communities[0];
community->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(community->regs))
diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c
index 97bf5ec78db4..635e4e5ab10c 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.c
+++ b/drivers/pinctrl/intel/pinctrl-intel.c
@@ -1581,24 +1581,17 @@ int intel_pinctrl_probe(struct platform_device *pdev,
struct intel_pinctrl *pctrl;
int i, ret, irq;
- pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL);
+ pctrl = devm_kzalloc(dev, struct_size(pctrl, communities, soc_data->ncommunities), GFP_KERNEL);
if (!pctrl)
return -ENOMEM;
+ pctrl->ncommunities = soc_data->ncommunities;
+ memcpy(pctrl->communities, soc_data->communities, soc_data->ncommunities * sizeof(*pctrl->communities));
+
pctrl->dev = dev;
pctrl->soc = soc_data;
raw_spin_lock_init(&pctrl->lock);
- /*
- * Make a copy of the communities which we can use to hold pointers
- * to the registers.
- */
- pctrl->ncommunities = pctrl->soc->ncommunities;
- pctrl->communities = devm_kmemdup_array(dev, pctrl->soc->communities, pctrl->ncommunities,
- sizeof(*pctrl->soc->communities), GFP_KERNEL);
- if (!pctrl->communities)
- return -ENOMEM;
-
for (i = 0; i < pctrl->ncommunities; i++) {
struct intel_community *community = &pctrl->communities[i];
unsigned short capability_offset[6];
diff --git a/drivers/pinctrl/intel/pinctrl-intel.h b/drivers/pinctrl/intel/pinctrl-intel.h
index b5476b9de0db..c382fe8f08c2 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.h
+++ b/drivers/pinctrl/intel/pinctrl-intel.h
@@ -260,10 +260,10 @@ struct intel_pinctrl {
struct pinctrl_dev *pctldev;
struct gpio_chip chip;
const struct intel_pinctrl_soc_data *soc;
- struct intel_community *communities;
size_t ncommunities;
struct intel_pinctrl_context context;
int irq;
+ struct intel_community communities[] __counted_by(ncommunities);
};
int intel_pinctrl_probe(struct platform_device *pdev,
diff --git a/drivers/pinctrl/intel/pinctrl-lynxpoint.c b/drivers/pinctrl/intel/pinctrl-lynxpoint.c
index 299ee4f22bdc..b3cde7afded9 100644
--- a/drivers/pinctrl/intel/pinctrl-lynxpoint.c
+++ b/drivers/pinctrl/intel/pinctrl-lynxpoint.c
@@ -715,19 +715,14 @@ static int lp_gpio_probe(struct platform_device *pdev)
if (!soc)
return -ENODEV;
- lg = devm_kzalloc(dev, sizeof(*lg), GFP_KERNEL);
+ lg = devm_kzalloc(dev, struct_size(lg, communities, soc->ncommunities), GFP_KERNEL);
if (!lg)
return -ENOMEM;
+ lg->ncommunities = soc->ncommunities;
lg->dev = dev;
lg->soc = soc;
- lg->ncommunities = lg->soc->ncommunities;
- lg->communities = devm_kcalloc(dev, lg->ncommunities,
- sizeof(*lg->communities), GFP_KERNEL);
- if (!lg->communities)
- return -ENOMEM;
-
lg->pctldesc = lptlp_pinctrl_desc;
lg->pctldesc.name = dev_name(dev);
lg->pctldesc.pins = lg->soc->pins;
--
2.53.0