Skip to content

Commit 7c5dd23

Browse files
davejiangvinodkoul
authored andcommitted
dmaengine: idxd: fix wq conf_dev 'struct device' lifetime
Remove devm_* allocation and fix wq->conf_dev 'struct device' lifetime. Address issues flagged by CONFIG_DEBUG_KOBJECT_RELEASE. Add release functions in order to free the allocated memory for the wq context at device 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/161852985907.2203940.6840120734115043753.stgit@djiang5-desk3.ch.intel.com Signed-off-by: Vinod Koul <[email protected]>
1 parent 47c16ac commit 7c5dd23

File tree

5 files changed

+146
-91
lines changed

5 files changed

+146
-91
lines changed

drivers/dma/idxd/device.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ void idxd_device_wqs_clear_state(struct idxd_device *idxd)
520520
lockdep_assert_held(&idxd->dev_lock);
521521

522522
for (i = 0; i < idxd->max_wqs; i++) {
523-
struct idxd_wq *wq = &idxd->wqs[i];
523+
struct idxd_wq *wq = idxd->wqs[i];
524524

525525
if (wq->state == IDXD_WQ_ENABLED) {
526526
idxd_wq_disable_cleanup(wq);
@@ -738,7 +738,7 @@ static int idxd_wqs_config_write(struct idxd_device *idxd)
738738
int i, rc;
739739

740740
for (i = 0; i < idxd->max_wqs; i++) {
741-
struct idxd_wq *wq = &idxd->wqs[i];
741+
struct idxd_wq *wq = idxd->wqs[i];
742742

743743
rc = idxd_wq_config_write(wq);
744744
if (rc < 0)
@@ -816,7 +816,7 @@ static int idxd_wqs_setup(struct idxd_device *idxd)
816816
}
817817

818818
for (i = 0; i < idxd->max_wqs; i++) {
819-
wq = &idxd->wqs[i];
819+
wq = idxd->wqs[i];
820820
group = wq->group;
821821

822822
if (!wq->group)

drivers/dma/idxd/idxd.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ struct idxd_device {
194194
spinlock_t dev_lock; /* spinlock for device */
195195
struct completion *cmd_done;
196196
struct idxd_group *groups;
197-
struct idxd_wq *wqs;
197+
struct idxd_wq **wqs;
198198
struct idxd_engine *engines;
199199

200200
struct iommu_sva *sva;
@@ -258,6 +258,7 @@ extern struct bus_type iax_bus_type;
258258
extern bool support_enqcmd;
259259
extern struct device_type dsa_device_type;
260260
extern struct device_type iax_device_type;
261+
extern struct device_type idxd_wq_device_type;
261262

262263
static inline bool is_dsa_dev(struct device *dev)
263264
{
@@ -274,6 +275,23 @@ static inline bool is_idxd_dev(struct device *dev)
274275
return is_dsa_dev(dev) || is_iax_dev(dev);
275276
}
276277

278+
static inline bool is_idxd_wq_dev(struct device *dev)
279+
{
280+
return dev->type == &idxd_wq_device_type;
281+
}
282+
283+
static inline bool is_idxd_wq_dmaengine(struct idxd_wq *wq)
284+
{
285+
if (wq->type == IDXD_WQT_KERNEL && strcmp(wq->name, "dmaengine") == 0)
286+
return true;
287+
return false;
288+
}
289+
290+
static inline bool is_idxd_wq_cdev(struct idxd_wq *wq)
291+
{
292+
return wq->type == IDXD_WQT_USER;
293+
}
294+
277295
static inline bool wq_dedicated(struct idxd_wq *wq)
278296
{
279297
return test_bit(WQ_FLAG_DEDICATED, &wq->flags);

drivers/dma/idxd/init.c

Lines changed: 77 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -145,16 +145,74 @@ static int idxd_setup_interrupts(struct idxd_device *idxd)
145145
return rc;
146146
}
147147

148+
static int idxd_setup_wqs(struct idxd_device *idxd)
149+
{
150+
struct device *dev = &idxd->pdev->dev;
151+
struct idxd_wq *wq;
152+
int i, rc;
153+
154+
idxd->wqs = kcalloc_node(idxd->max_wqs, sizeof(struct idxd_wq *),
155+
GFP_KERNEL, dev_to_node(dev));
156+
if (!idxd->wqs)
157+
return -ENOMEM;
158+
159+
for (i = 0; i < idxd->max_wqs; i++) {
160+
wq = kzalloc_node(sizeof(*wq), GFP_KERNEL, dev_to_node(dev));
161+
if (!wq) {
162+
rc = -ENOMEM;
163+
goto err;
164+
}
165+
166+
wq->id = i;
167+
wq->idxd = idxd;
168+
device_initialize(&wq->conf_dev);
169+
wq->conf_dev.parent = &idxd->conf_dev;
170+
wq->conf_dev.bus = idxd_get_bus_type(idxd);
171+
wq->conf_dev.type = &idxd_wq_device_type;
172+
rc = dev_set_name(&wq->conf_dev, "wq%d.%d", idxd->id, wq->id);
173+
if (rc < 0) {
174+
put_device(&wq->conf_dev);
175+
goto err;
176+
}
177+
178+
mutex_init(&wq->wq_lock);
179+
wq->idxd_cdev.minor = -1;
180+
wq->max_xfer_bytes = idxd->max_xfer_bytes;
181+
wq->max_batch_size = idxd->max_batch_size;
182+
wq->wqcfg = kzalloc_node(idxd->wqcfg_size, GFP_KERNEL, dev_to_node(dev));
183+
if (!wq->wqcfg) {
184+
put_device(&wq->conf_dev);
185+
rc = -ENOMEM;
186+
goto err;
187+
}
188+
idxd->wqs[i] = wq;
189+
}
190+
191+
return 0;
192+
193+
err:
194+
while (--i >= 0)
195+
put_device(&idxd->wqs[i]->conf_dev);
196+
return rc;
197+
}
198+
148199
static int idxd_setup_internals(struct idxd_device *idxd)
149200
{
150201
struct device *dev = &idxd->pdev->dev;
151-
int i;
202+
int i, rc;
152203

153204
init_waitqueue_head(&idxd->cmd_waitq);
205+
206+
rc = idxd_setup_wqs(idxd);
207+
if (rc < 0)
208+
return rc;
209+
154210
idxd->groups = devm_kcalloc(dev, idxd->max_groups,
155211
sizeof(struct idxd_group), GFP_KERNEL);
156-
if (!idxd->groups)
157-
return -ENOMEM;
212+
if (!idxd->groups) {
213+
rc = -ENOMEM;
214+
goto err;
215+
}
158216

159217
for (i = 0; i < idxd->max_groups; i++) {
160218
idxd->groups[i].idxd = idxd;
@@ -163,40 +221,31 @@ static int idxd_setup_internals(struct idxd_device *idxd)
163221
idxd->groups[i].tc_b = -1;
164222
}
165223

166-
idxd->wqs = devm_kcalloc(dev, idxd->max_wqs, sizeof(struct idxd_wq),
167-
GFP_KERNEL);
168-
if (!idxd->wqs)
169-
return -ENOMEM;
170-
171224
idxd->engines = devm_kcalloc(dev, idxd->max_engines,
172225
sizeof(struct idxd_engine), GFP_KERNEL);
173-
if (!idxd->engines)
174-
return -ENOMEM;
175-
176-
for (i = 0; i < idxd->max_wqs; i++) {
177-
struct idxd_wq *wq = &idxd->wqs[i];
178-
179-
wq->id = i;
180-
wq->idxd = idxd;
181-
mutex_init(&wq->wq_lock);
182-
wq->idxd_cdev.minor = -1;
183-
wq->max_xfer_bytes = idxd->max_xfer_bytes;
184-
wq->max_batch_size = idxd->max_batch_size;
185-
wq->wqcfg = devm_kzalloc(dev, idxd->wqcfg_size, GFP_KERNEL);
186-
if (!wq->wqcfg)
187-
return -ENOMEM;
226+
if (!idxd->engines) {
227+
rc = -ENOMEM;
228+
goto err;
188229
}
189230

231+
190232
for (i = 0; i < idxd->max_engines; i++) {
191233
idxd->engines[i].idxd = idxd;
192234
idxd->engines[i].id = i;
193235
}
194236

195237
idxd->wq = create_workqueue(dev_name(dev));
196-
if (!idxd->wq)
197-
return -ENOMEM;
238+
if (!idxd->wq) {
239+
rc = -ENOMEM;
240+
goto err;
241+
}
198242

199243
return 0;
244+
245+
err:
246+
for (i = 0; i < idxd->max_wqs; i++)
247+
put_device(&idxd->wqs[i]->conf_dev);
248+
return rc;
200249
}
201250

202251
static void idxd_read_table_offsets(struct idxd_device *idxd)
@@ -371,11 +420,11 @@ static int idxd_probe(struct idxd_device *idxd)
371420

372421
rc = idxd_setup_internals(idxd);
373422
if (rc)
374-
goto err_setup;
423+
goto err;
375424

376425
rc = idxd_setup_interrupts(idxd);
377426
if (rc)
378-
goto err_setup;
427+
goto err;
379428

380429
dev_dbg(dev, "IDXD interrupt setup complete.\n");
381430

@@ -384,7 +433,7 @@ static int idxd_probe(struct idxd_device *idxd)
384433
dev_dbg(dev, "IDXD device %d probed successfully\n", idxd->id);
385434
return 0;
386435

387-
err_setup:
436+
err:
388437
if (device_pasid_enabled(idxd))
389438
idxd_disable_system_pasid(idxd);
390439
return rc;

drivers/dma/idxd/irq.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ static void idxd_device_reinit(struct work_struct *work)
4545
goto out;
4646

4747
for (i = 0; i < idxd->max_wqs; i++) {
48-
struct idxd_wq *wq = &idxd->wqs[i];
48+
struct idxd_wq *wq = idxd->wqs[i];
4949

5050
if (wq->state == IDXD_WQ_ENABLED) {
5151
rc = idxd_wq_enable(wq);
@@ -130,15 +130,15 @@ static int process_misc_interrupts(struct idxd_device *idxd, u32 cause)
130130

131131
if (idxd->sw_err.valid && idxd->sw_err.wq_idx_valid) {
132132
int id = idxd->sw_err.wq_idx;
133-
struct idxd_wq *wq = &idxd->wqs[id];
133+
struct idxd_wq *wq = idxd->wqs[id];
134134

135135
if (wq->type == IDXD_WQT_USER)
136136
wake_up_interruptible(&wq->idxd_cdev.err_queue);
137137
} else {
138138
int i;
139139

140140
for (i = 0; i < idxd->max_wqs; i++) {
141-
struct idxd_wq *wq = &idxd->wqs[i];
141+
struct idxd_wq *wq = idxd->wqs[i];
142142

143143
if (wq->type == IDXD_WQT_USER)
144144
wake_up_interruptible(&wq->idxd_cdev.err_queue);

0 commit comments

Comments
 (0)