On Tue, Dec 27, 2011 at 05:06:56PM +0900, Sangsu Park wrote:
/* free the ops memory */
if (rtd->ops) kfree(rtd->ops);
We shouldn't be doing a kfree() on the ops at all.
+++ b/sound/soc/soc-pcm.c @@ -641,22 +645,23 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work); rtd->pcm = pcm;
rtd->ops = soc_pcm_ops;
That *might* work if ops were changed to be a member variable, though it's racy against two things initializing simultaneously.
What I'd expect is something like:
INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work); rtd->pcm = pcm; rtd->pcm_ops = soc_pcm_ops; pcm->private_data = rtd; if (platform->driver->ops) { rtd->pcm_ops.mmap = platform->driver->ops->mmap; rtd->pcm_ops.pointer = platform->driver->ops->pointer;
and so on so we start off by taking a copy of the default ops then copy the new ops in in the same fashion.
Ideally we should also have an indirection for ioctl() though using it at all is dodgy.