Skip to content

Commit 1188095

Browse files
Srinivas-Kandagatla0day robot
authored and
0day robot
committed
sound: lpass-platform: Move dma channel allocation to pcmops
Move dma channel allocations to pcmops open and close functions. Reason to do this is that, lpass_platform_pcm_free() accesses snd_soc_pcm_runtime via substream->private data, However By this time runtimes are already freed as part of soc_cleanup_card_resources() sequence. This patch moves the channel allocations/deallocations to pcmops open() and close() respectively, where the code has valid snd_soc_pcm_runtime. Without this patch unloading lpass sound card module would result in below crash: Unable to handle kernel NULL pointer dereference at virtual address 00000000 pgd = ffff800038f0d000 [00000000] *pgd=0000000000000000 Internal error: Oops: 96000004 [#1] PREEMPT SMP Modules linked in: snd_soc_apq8016_sbc(-) snd_soc_lpass_apq8016 snd_soc_lpass_cpu snd_soc_lpass_platform CPU: 0 PID: 1573 Comm: rmmod Not tainted 4.7.0-rc2-next-20160609+ torvalds#59 Hardware name: Qualcomm Technologies, Inc. APQ 8016 SBC (DT) task: ffff800038cd0000 ti: ffff80003929c000 task.ti: ffff80003929c000 PC is at lpass_platform_pcm_free+0xc4/0x1c0 [snd_soc_lpass_platform] LR is at lpass_platform_pcm_free+0xb8/0x1c0 [snd_soc_lpass_platform] pc : [<ffff000000b20b64>] lr : [<ffff000000b20b58>] pstate: 60000145 sp : ffff80003929fa90 x29: ffff80003929fa90 x28: ffff000000b22438 x27: ffff000000b22450 x26: ffff000000b22468 x25: ffff000000b22488 x24: ffff000000b223f0 x23: ffff000000b22418 x22: ffff800038f428c0 x21: ffff8000392ae280 x20: 0000000000000001 x19: ffff000000b22118 x18: 0000ffffdc331600 x17: 0000ffffb78036c0 x16: ffff0000081c16e8 x15: 0000ffffb77f0588 x14: 3d4d554e51455300 x13: ffffffffffff0000 x12: 0000000000000028 x11: 0000000000000044 x10: ffff80003929f822 x9 : ffff80003929f823 x8 : 0000000000000000 x7 : 0000000000000004 x6 : ffff000008864890 x5 : 0000000000000000 x4 : 0000000000000000 x3 : 0000000000000000 x2 : ffff80003efac228 x1 : ffff000000b22118 x0 : ffff000000b22450 Process rmmod (pid: 1573, stack limit = 0xffff80003929c020) Stack: (0xffff80003929fa90 to 0xffff8000392a0000) fa80: ffff80003929fb40 ffff0000086d1f8c faa0: ffff000008ca5408 ffff800038f42200 ffff000008ca5420 000000000000000b fac0: ffff80003929fd70 0000000000000015 0000000000000120 000000000000006a fae0: ffff0000087f2000 ffff80003929c000 ffff80003929fb40 ffff8000392ae358 fb00: ffff8000392af900 0000000000000000 ffff8000392afa48 000000000000000b fb20: ffff80003929fd70 0000000000000015 ffff80003929fb80 ffff0000086cc070 fb40: ffff80003929fb70 ffff0000086d21d4 ffff800038f7fa00 ffff8000392801a0 fb60: ffff800038cf2000 0000000000000015 ffff80003929fb80 ffff0000086cc064 fb80: ffff80003929fba0 ffff0000086cc1f4 ffff800038f70600 000000000000000b fba0: ffff80003929fbc0 ffff0000086c68a8 ffff800039280000 ffff800039280540 fbc0: ffff80003929fbe0 ffff0000084a7438 ffff800039280540 ffff800039280550 fbe0: ffff80003929fc10 ffff000008355ddc ffff800039280550 ffff000008c64718 fc00: ffff800038f61d00 ffff000008ca5190 ffff80003929fc40 ffff000008355e5c fc20: ffff800039280550 ffff800039280000 ffff80003847b618 ffff800039280000 fc40: ffff80003929fc60 ffff0000084a77d8 0000000000000000 0000000000000015 fc60: ffff80003929fc70 ffff0000086c6e58 ffff80003929fc90 ffff0000086c6fbc fc80: ffff80003929fcb0 ffff800039280000 ffff80003929fcd0 ffff0000086e3e50 fca0: ffff80003847b050 ffff80003847b728 ffff800000000000 ffff000000000000 fcc0: ffff80003929fcc0 ffff80003929fcc0 ffff80003929fd00 ffff0000086e4c8c fce0: ffff80003847b618 ffff800038f61100 ffff8000399ddf90 000000000000000b fd00: ffff80003929fd20 ffff0000086f0684 ffff800038f61000 ffff0000080d51c0 fd20: ffff80003929fd30 ffff0000084af904 ffff80003929fd80 ffff0000084afcf8 fd40: ffff8000399ddf90 ffff000000b3c028 ffff8000399ddff0 ffff000008cc8000 fd60: 0000000080000000 ffff0000084ac090 ffff800038f94600 ffff800038f61000 fd80: ffff80003929fda0 ffff0000084ac0b0 ffff8000399ddf90 ffff000000b3c028 fda0: ffff80003929fdc0 ffff0000084ac234 ffff8000399ddf90 ffff000000b3c028 fdc0: ffff80003929fdf0 ffff0000084ab3d4 ffff000000b3c028 ffff000008c64000 fde0: ffff000008c64818 ffff000000000001 ffff80003929fe20 ffff0000084ac8ac fe00: ffff000000b3c028 ffff000000b3c100 fffffffffffffff5 0000000000000000 fe20: ffff80003929fe40 ffff0000084ad998 ffff000008c2d000 0000000000000015 fe40: ffff80003929fe50 ffff000000b3a460 ffff80003929fe60 ffff000008120fe4 fe60: 0000000000000000 ffff000008084e70 0000000000000000 0000000000000000 fe80: ffffffffffffffff 0000ffff954cca48 0000000000000004 5f636f735f646e73 fea0: 5f36313038717061 0000000000636273 0000000000000000 ffff000008084d64 fec0: 0000000000000000 0000000000000000 0000aaaabc814340 0000000000000800 fee0: 4fdc43dac03e2300 0000000000002002 0000ffff95548e58 0000ffffd9f89fb9 ff00: 0000000000000000 0000000000000000 000000000000006a 1999999999999999 ff20: 00000000ffffffff 0000000000000000 0000000000000005 ffffffffffffffff ff40: 0000ffff95402a94 0000ffff9554a588 0000ffff954cca40 0000aaaaaf8d22d0 ff60: 0000ffffd9f8ad70 0000aaaabc8142e0 0000000000000000 0000000000000000 ff80: 0000ffffd9f8be7c 0000000000000000 0000ffffd9f8b0e0 0000ffffd9f8b2b8 ffa0: 0000aaaabc8142e0 0000aaaabc813010 0000000000000000 0000ffffd9f8b010 ffc0: 0000aaaaaf8b5ad4 0000ffffd9f8b010 0000ffff954cca48 0000000080000000 ffe0: 0000aaaabc814340 000000000000006a 0000060000000000 00000000fffefcaf Call trace: Exception stack(0xffff80003929f8d0 to 0xffff80003929f9f0) f8c0: ffff000000b22118 00000000000001 f8e0: ffff80003929fa90 ffff000000b20b64 ffff80003929f910 ffff000008a12f40 f900: ffff000008c15b78 0000000100000001 ffff80003929f9b0 ffff0000080f66e0 f920: ffff000000b22118 0000000000000001 ffff8000392ae280 ffff800038f428c0 f940: ffff000000b22418 ffff000000b223f0 ffff000000b22488 ffff000000b22468 f960: ffff000000b22450 ffff000000b22438 ffff000000b22450 ffff000000b22118 f980: ffff80003efac228 0000000000000000 0000000000000000 0000000000000000 f9a0: ffff000008864890 0000000000000004 0000000000000000 ffff80003929f823 f9c0: ffff80003929f822 0000000000000044 0000000000000028 ffffffffffff0000 f9e0: 3d4d554e51455300 0000ffffb77f0588 [<ffff000000b20b64>] lpass_platform_pcm_free+0xc4/0x1c0 [snd_soc_lpass_platform] [<ffff0000086d1f8c>] snd_pcm_free+0x30/0xa0 [<ffff0000086d21d4>] snd_pcm_dev_free+0x10/0x18 [<ffff0000086cc064>] __snd_device_free+0x58/0xa0 [<ffff0000086cc1f4>] snd_device_free_all+0x2c/0x48 [<ffff0000086c68a8>] release_card_device+0x1c/0x74 [<ffff0000084a7438>] device_release+0x34/0x90 [<ffff000008355ddc>] kobject_release+0x44/0x84 [<ffff000008355e5c>] kobject_put+0x40/0x68 [<ffff0000084a77d8>] put_device+0x14/0x1c [<ffff0000086c6e58>] snd_card_free_when_closed+0x24/0x34 [<ffff0000086c6fbc>] snd_card_free+0x40/0x60 [<ffff0000086e3e50>] soc_cleanup_card_resources+0x80/0x94 [<ffff0000086e4c8c>] snd_soc_unregister_card+0x28/0x38 [<ffff0000086f0684>] devm_card_release+0x10/0x18 [<ffff0000084af904>] release_nodes+0x124/0x208 [<ffff0000084afcf8>] devres_release_all+0x34/0x54 [<ffff0000084ac0b0>] __device_release_driver+0x84/0xfc [<ffff0000084ac234>] driver_detach+0xbc/0xc0 [<ffff0000084ab3d4>] bus_remove_driver+0x58/0xac [<ffff0000084ac8ac>] driver_unregister+0x2c/0x4c [<ffff0000084ad998>] platform_driver_unregister+0x10/0x18 [<ffff000000b3a460>] apq8016_sbc_platform_driver_exit+0x10/0xbb0 [snd_soc_apq8016_sbc] [<ffff000008120fe4>] SyS_delete_module+0x1b8/0x1fc [<ffff000008084e70>] el0_svc_naked+0x24/0x28 Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
1 parent 3be14c8 commit 1188095

File tree

1 file changed

+76
-78
lines changed

1 file changed

+76
-78
lines changed

sound/soc/qcom/lpass-platform.c

+76-78
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,36 @@ static int lpass_platform_pcmops_open(struct snd_pcm_substream *substream)
6161
{
6262
struct snd_pcm_runtime *runtime = substream->runtime;
6363
struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
64-
int ret;
64+
struct lpass_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(soc_runtime);
65+
struct lpass_data *drvdata =
66+
snd_soc_platform_get_drvdata(soc_runtime->platform);
67+
struct lpass_variant *v = drvdata->variant;
68+
int ch = -1, reg, ret;
69+
70+
if (v->alloc_dma_channel) {
71+
ch = v->alloc_dma_channel(drvdata, substream->stream);
72+
73+
if (ch < 0)
74+
return ch;
75+
76+
drvdata->substream[ch] = substream;
77+
78+
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
79+
pcm_data->rdma_ch = ch;
80+
reg = LPAIF_RDMACTL_REG(v, ch);
81+
} else {
82+
pcm_data->wrdma_ch = ch;
83+
reg = LPAIF_WRDMACTL_REG(v, ch);
84+
}
85+
86+
ret = regmap_write(drvdata->lpaif_map, reg, 0);
87+
if (ret) {
88+
dev_err(soc_runtime->dev,
89+
"%s() error writing to dmactl reg: %d\n",
90+
__func__, ret);
91+
goto err;
92+
}
93+
}
6594

6695
snd_soc_set_runtime_hwparams(substream, &lpass_platform_pcm_hardware);
6796

@@ -72,11 +101,41 @@ static int lpass_platform_pcmops_open(struct snd_pcm_substream *substream)
72101
if (ret < 0) {
73102
dev_err(soc_runtime->dev, "%s() setting constraints failed: %d\n",
74103
__func__, ret);
75-
return -EINVAL;
104+
goto err;
76105
}
77106

78107
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
79108

109+
return 0;
110+
111+
err:
112+
if (ch >= 0 && v->free_dma_channel)
113+
v->free_dma_channel(drvdata, ch);
114+
115+
return ret;
116+
}
117+
118+
static int lpass_platform_pcmops_close(struct snd_pcm_substream *substream)
119+
{
120+
struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
121+
struct lpass_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(soc_runtime);
122+
struct lpass_data *drvdata =
123+
snd_soc_platform_get_drvdata(soc_runtime->platform);
124+
struct lpass_variant *v = drvdata->variant;
125+
int ch;
126+
127+
if (v->free_dma_channel) {
128+
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
129+
ch = pcm_data->rdma_ch;
130+
else
131+
ch = pcm_data->wrdma_ch;
132+
133+
if (ch >= 0)
134+
v->free_dma_channel(drvdata, ch);
135+
136+
drvdata->substream[ch] = NULL;
137+
}
138+
80139
return 0;
81140
}
82141

@@ -374,6 +433,7 @@ static int lpass_platform_pcmops_mmap(struct snd_pcm_substream *substream,
374433

375434
static struct snd_pcm_ops lpass_platform_pcm_ops = {
376435
.open = lpass_platform_pcmops_open,
436+
.close = lpass_platform_pcmops_close,
377437
.ioctl = snd_pcm_lib_ioctl,
378438
.hw_params = lpass_platform_pcmops_hw_params,
379439
.hw_free = lpass_platform_pcmops_hw_free,
@@ -471,12 +531,9 @@ static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime)
471531
struct snd_pcm *pcm = soc_runtime->pcm;
472532
struct snd_pcm_substream *psubstream, *csubstream;
473533
struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai;
474-
struct lpass_data *drvdata =
475-
snd_soc_platform_get_drvdata(soc_runtime->platform);
476-
struct lpass_variant *v = drvdata->variant;
477-
int ret = -EINVAL;
478534
struct lpass_pcm_data *data;
479535
size_t size = lpass_platform_pcm_hardware.buffer_bytes_max;
536+
int ret = -EINVAL;
480537

481538
data = devm_kzalloc(soc_runtime->dev, sizeof(*data), GFP_KERNEL);
482539
if (!data)
@@ -487,100 +544,41 @@ static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime)
487544

488545
psubstream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
489546
if (psubstream) {
490-
if (v->alloc_dma_channel)
491-
data->rdma_ch = v->alloc_dma_channel(drvdata,
492-
SNDRV_PCM_STREAM_PLAYBACK);
493-
494-
if (data->rdma_ch < 0)
495-
return data->rdma_ch;
496-
497-
drvdata->substream[data->rdma_ch] = psubstream;
498-
499547
ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
500-
soc_runtime->platform->dev,
501-
size, &psubstream->dma_buffer);
502-
if (ret)
503-
goto playback_alloc_err;
504-
505-
ret = regmap_write(drvdata->lpaif_map,
506-
LPAIF_RDMACTL_REG(v, data->rdma_ch), 0);
548+
soc_runtime->platform->dev,
549+
size, &psubstream->dma_buffer);
507550
if (ret) {
508-
dev_err(soc_runtime->dev,
509-
"%s() error writing to rdmactl reg: %d\n",
510-
__func__, ret);
511-
goto capture_alloc_err;
551+
dev_err(soc_runtime->platform->dev,
552+
"can't alloc playback dma buffer (%d)\n", ret);
553+
return ret;
512554
}
513555
}
514556

515557
csubstream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
516558
if (csubstream) {
517-
if (v->alloc_dma_channel)
518-
data->wrdma_ch = v->alloc_dma_channel(drvdata,
519-
SNDRV_PCM_STREAM_CAPTURE);
520-
521-
if (data->wrdma_ch < 0) {
522-
ret = data->wrdma_ch;
523-
goto capture_alloc_err;
524-
}
525-
526-
drvdata->substream[data->wrdma_ch] = csubstream;
527-
528559
ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
529-
soc_runtime->platform->dev,
530-
size, &csubstream->dma_buffer);
531-
if (ret)
532-
goto capture_alloc_err;
533-
534-
ret = regmap_write(drvdata->lpaif_map,
535-
LPAIF_WRDMACTL_REG(v, data->wrdma_ch), 0);
560+
soc_runtime->platform->dev,
561+
size, &csubstream->dma_buffer);
536562
if (ret) {
537-
dev_err(soc_runtime->dev,
538-
"%s() error writing to wrdmactl reg: %d\n",
539-
__func__, ret);
540-
goto capture_reg_err;
563+
dev_err(soc_runtime->platform->dev,
564+
"can't alloc capture dma buffer (%d)\n", ret);
565+
if (psubstream)
566+
snd_dma_free_pages(&psubstream->dma_buffer);
567+
return ret;
541568
}
542569
}
543570

544571
return 0;
545-
546-
capture_reg_err:
547-
if (csubstream)
548-
snd_dma_free_pages(&csubstream->dma_buffer);
549-
550-
capture_alloc_err:
551-
if (psubstream)
552-
snd_dma_free_pages(&psubstream->dma_buffer);
553-
554-
playback_alloc_err:
555-
dev_err(soc_runtime->dev, "Cannot allocate buffer(s)\n");
556-
557-
return ret;
558572
}
559573

560574
static void lpass_platform_pcm_free(struct snd_pcm *pcm)
561575
{
562-
struct snd_soc_pcm_runtime *rt;
563-
struct lpass_data *drvdata;
564-
struct lpass_pcm_data *data;
565-
struct lpass_variant *v;
566576
struct snd_pcm_substream *substream;
567-
int ch, i;
577+
int i;
568578

569579
for (i = 0; i < ARRAY_SIZE(pcm->streams); i++) {
570580
substream = pcm->streams[i].substream;
571581
if (substream) {
572-
rt = substream->private_data;
573-
data = snd_soc_pcm_get_drvdata(rt);
574-
drvdata = snd_soc_platform_get_drvdata(rt->platform);
575-
576-
ch = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
577-
? data->rdma_ch
578-
: data->wrdma_ch;
579-
v = drvdata->variant;
580-
drvdata->substream[ch] = NULL;
581-
if (v->free_dma_channel)
582-
v->free_dma_channel(drvdata, ch);
583-
584582
snd_dma_free_pages(&substream->dma_buffer);
585583
substream->dma_buffer.area = NULL;
586584
substream->dma_buffer.addr = 0;

0 commit comments

Comments
 (0)