Skip to content

Commit 75b9113

Browse files
davejiangvinodkoul
authored andcommitted
dmaengine: idxd: fix engine conf_dev lifetime
Remove devm_* allocation and fix engine->conf_dev 'struct device' lifetime. Address issues flagged by CONFIG_DEBUG_KOBJECT_RELEASE. Add release functions in order to free the allocated memory at the engine conf_dev destruction time. Reported-by: Jason Gunthorpe <[email protected]> Fixes: bfe1d56 ("dmaengine: idxd: Init and probe for Intel data accelerators") Signed-off-by: Dave Jiang <[email protected]> Link: https://lore.kernel.org/r/161852986460.2203940.16603218225412118431.stgit@djiang5-desk3.ch.intel.com Signed-off-by: Vinod Koul <[email protected]>
1 parent 7c5dd23 commit 75b9113

File tree

4 files changed

+86
-51
lines changed

4 files changed

+86
-51
lines changed

drivers/dma/idxd/device.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -786,7 +786,7 @@ static int idxd_engines_setup(struct idxd_device *idxd)
786786
}
787787

788788
for (i = 0; i < idxd->max_engines; i++) {
789-
eng = &idxd->engines[i];
789+
eng = idxd->engines[i];
790790
group = eng->group;
791791

792792
if (!group)

drivers/dma/idxd/idxd.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ struct idxd_device {
195195
struct completion *cmd_done;
196196
struct idxd_group *groups;
197197
struct idxd_wq **wqs;
198-
struct idxd_engine *engines;
198+
struct idxd_engine **engines;
199199

200200
struct iommu_sva *sva;
201201
unsigned int pasid;
@@ -259,6 +259,7 @@ extern bool support_enqcmd;
259259
extern struct device_type dsa_device_type;
260260
extern struct device_type iax_device_type;
261261
extern struct device_type idxd_wq_device_type;
262+
extern struct device_type idxd_engine_device_type;
262263

263264
static inline bool is_dsa_dev(struct device *dev)
264265
{

drivers/dma/idxd/init.c

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,46 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
196196
return rc;
197197
}
198198

199+
static int idxd_setup_engines(struct idxd_device *idxd)
200+
{
201+
struct idxd_engine *engine;
202+
struct device *dev = &idxd->pdev->dev;
203+
int i, rc;
204+
205+
idxd->engines = kcalloc_node(idxd->max_engines, sizeof(struct idxd_engine *),
206+
GFP_KERNEL, dev_to_node(dev));
207+
if (!idxd->engines)
208+
return -ENOMEM;
209+
210+
for (i = 0; i < idxd->max_engines; i++) {
211+
engine = kzalloc_node(sizeof(*engine), GFP_KERNEL, dev_to_node(dev));
212+
if (!engine) {
213+
rc = -ENOMEM;
214+
goto err;
215+
}
216+
217+
engine->id = i;
218+
engine->idxd = idxd;
219+
device_initialize(&engine->conf_dev);
220+
engine->conf_dev.parent = &idxd->conf_dev;
221+
engine->conf_dev.type = &idxd_engine_device_type;
222+
rc = dev_set_name(&engine->conf_dev, "engine%d.%d", idxd->id, engine->id);
223+
if (rc < 0) {
224+
put_device(&engine->conf_dev);
225+
goto err;
226+
}
227+
228+
idxd->engines[i] = engine;
229+
}
230+
231+
return 0;
232+
233+
err:
234+
while (--i >= 0)
235+
put_device(&idxd->engines[i]->conf_dev);
236+
return rc;
237+
}
238+
199239
static int idxd_setup_internals(struct idxd_device *idxd)
200240
{
201241
struct device *dev = &idxd->pdev->dev;
@@ -207,6 +247,10 @@ static int idxd_setup_internals(struct idxd_device *idxd)
207247
if (rc < 0)
208248
return rc;
209249

250+
rc = idxd_setup_engines(idxd);
251+
if (rc < 0)
252+
goto err_engine;
253+
210254
idxd->groups = devm_kcalloc(dev, idxd->max_groups,
211255
sizeof(struct idxd_group), GFP_KERNEL);
212256
if (!idxd->groups) {
@@ -221,19 +265,6 @@ static int idxd_setup_internals(struct idxd_device *idxd)
221265
idxd->groups[i].tc_b = -1;
222266
}
223267

224-
idxd->engines = devm_kcalloc(dev, idxd->max_engines,
225-
sizeof(struct idxd_engine), GFP_KERNEL);
226-
if (!idxd->engines) {
227-
rc = -ENOMEM;
228-
goto err;
229-
}
230-
231-
232-
for (i = 0; i < idxd->max_engines; i++) {
233-
idxd->engines[i].idxd = idxd;
234-
idxd->engines[i].id = i;
235-
}
236-
237268
idxd->wq = create_workqueue(dev_name(dev));
238269
if (!idxd->wq) {
239270
rc = -ENOMEM;
@@ -243,6 +274,9 @@ static int idxd_setup_internals(struct idxd_device *idxd)
243274
return 0;
244275

245276
err:
277+
for (i = 0; i < idxd->max_engines; i++)
278+
put_device(&idxd->engines[i]->conf_dev);
279+
err_engine:
246280
for (i = 0; i < idxd->max_wqs; i++)
247281
put_device(&idxd->wqs[i]->conf_dev);
248282
return rc;

drivers/dma/idxd/sysfs.c

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,6 @@ static struct device_type idxd_group_device_type = {
2626
.release = idxd_conf_sub_device_release,
2727
};
2828

29-
static struct device_type idxd_engine_device_type = {
30-
.name = "engine",
31-
.release = idxd_conf_sub_device_release,
32-
};
33-
3429
static int idxd_config_bus_match(struct device *dev,
3530
struct device_driver *drv)
3631
{
@@ -464,6 +459,19 @@ static const struct attribute_group *idxd_engine_attribute_groups[] = {
464459
NULL,
465460
};
466461

462+
static void idxd_conf_engine_release(struct device *dev)
463+
{
464+
struct idxd_engine *engine = container_of(dev, struct idxd_engine, conf_dev);
465+
466+
kfree(engine);
467+
}
468+
469+
struct device_type idxd_engine_device_type = {
470+
.name = "engine",
471+
.release = idxd_conf_engine_release,
472+
.groups = idxd_engine_attribute_groups,
473+
};
474+
467475
/* Group attributes */
468476

469477
static void idxd_set_free_tokens(struct idxd_device *idxd)
@@ -626,7 +634,7 @@ static ssize_t group_engines_show(struct device *dev,
626634
struct idxd_device *idxd = group->idxd;
627635

628636
for (i = 0; i < idxd->max_engines; i++) {
629-
struct idxd_engine *engine = &idxd->engines[i];
637+
struct idxd_engine *engine = idxd->engines[i];
630638

631639
if (!engine->group)
632640
continue;
@@ -1634,37 +1642,27 @@ struct device_type iax_device_type = {
16341642
.groups = idxd_attribute_groups,
16351643
};
16361644

1637-
static int idxd_setup_engine_sysfs(struct idxd_device *idxd)
1645+
static int idxd_register_engine_devices(struct idxd_device *idxd)
16381646
{
1639-
struct device *dev = &idxd->pdev->dev;
1640-
int i, rc;
1647+
int i, j, rc;
16411648

16421649
for (i = 0; i < idxd->max_engines; i++) {
1643-
struct idxd_engine *engine = &idxd->engines[i];
1644-
1645-
engine->conf_dev.parent = &idxd->conf_dev;
1646-
dev_set_name(&engine->conf_dev, "engine%d.%d",
1647-
idxd->id, engine->id);
1648-
engine->conf_dev.bus = idxd_get_bus_type(idxd);
1649-
engine->conf_dev.groups = idxd_engine_attribute_groups;
1650-
engine->conf_dev.type = &idxd_engine_device_type;
1651-
dev_dbg(dev, "Engine device register: %s\n",
1652-
dev_name(&engine->conf_dev));
1653-
rc = device_register(&engine->conf_dev);
1654-
if (rc < 0) {
1655-
put_device(&engine->conf_dev);
1650+
struct idxd_engine *engine = idxd->engines[i];
1651+
1652+
rc = device_add(&engine->conf_dev);
1653+
if (rc < 0)
16561654
goto cleanup;
1657-
}
16581655
}
16591656

16601657
return 0;
16611658

16621659
cleanup:
1663-
while (i--) {
1664-
struct idxd_engine *engine = &idxd->engines[i];
1660+
j = i - 1;
1661+
for (; i < idxd->max_engines; i++)
1662+
put_device(&idxd->engines[i]->conf_dev);
16651663

1666-
device_unregister(&engine->conf_dev);
1667-
}
1664+
while (j--)
1665+
device_unregister(&idxd->engines[j]->conf_dev);
16681666
return rc;
16691667
}
16701668

@@ -1741,23 +1739,25 @@ int idxd_register_devices(struct idxd_device *idxd)
17411739
goto err_wq;
17421740
}
17431741

1744-
rc = idxd_setup_group_sysfs(idxd);
1742+
rc = idxd_register_engine_devices(idxd);
17451743
if (rc < 0) {
1746-
/* unregister conf dev */
1747-
dev_dbg(dev, "Group sysfs registering failed: %d\n", rc);
1748-
goto err;
1744+
dev_dbg(dev, "Engine devices registering failed: %d\n", rc);
1745+
goto err_engine;
17491746
}
17501747

1751-
rc = idxd_setup_engine_sysfs(idxd);
1748+
rc = idxd_setup_group_sysfs(idxd);
17521749
if (rc < 0) {
17531750
/* unregister conf dev */
1754-
dev_dbg(dev, "Engine sysfs registering failed: %d\n", rc);
1755-
goto err;
1751+
dev_dbg(dev, "Group sysfs registering failed: %d\n", rc);
1752+
goto err_group;
17561753
}
17571754

17581755
return 0;
17591756

1760-
err:
1757+
err_group:
1758+
for (i = 0; i < idxd->max_engines; i++)
1759+
device_unregister(&idxd->engines[i]->conf_dev);
1760+
err_engine:
17611761
for (i = 0; i < idxd->max_wqs; i++)
17621762
device_unregister(&idxd->wqs[i]->conf_dev);
17631763
err_wq:
@@ -1776,7 +1776,7 @@ void idxd_unregister_devices(struct idxd_device *idxd)
17761776
}
17771777

17781778
for (i = 0; i < idxd->max_engines; i++) {
1779-
struct idxd_engine *engine = &idxd->engines[i];
1779+
struct idxd_engine *engine = idxd->engines[i];
17801780

17811781
device_unregister(&engine->conf_dev);
17821782
}

0 commit comments

Comments
 (0)