MLK-16558: ASoC: fsl_hifi4: add reference counter for hifi4 device
authorWeiguang Kong <weiguang.kong@nxp.com>
Fri, 29 Sep 2017 06:24:59 +0000 (14:24 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 20:38:45 +0000 (15:38 -0500)
When abnormal situation occurs and the current process terminates
abnormally, the hifi4 driver can't get the HIFI4_CODEC_CLOSE CMD
from user space to release the multi-codec resource, so the current
resource can't be used again.

Have found that the fsl_hifi4_close() function can be called
implicitly when process terminates abnormally, so add a reference
counter in fsl_hifi4_open() and fsl_hifi4_close() to check this
abnormal situation, when the number is same for opening and closing
hifi4 device, the multi-codec should be reinitialized again and
the hifi4 driver should send ICM_EXT_MSG_ADDR CMD to hifi4 framework
to initialize the multi-codec resources too.

Signed-off-by: Weiguang Kong <weiguang.kong@nxp.com>
sound/soc/fsl/fsl_hifi4.c
sound/soc/fsl/fsl_hifi4.h

index f24ce33..def93c2 100644 (file)
@@ -1467,6 +1467,24 @@ static long fsl_hifi4_compat_ioctl(struct file *file, unsigned int cmd,
 }
 #endif
 
+void resource_release(struct fsl_hifi4 *hifi4_priv)
+{
+       int i;
+
+       hifi4_priv->available_resource = MULTI_CODEC_NUM;
+       for (i = 0; i < MULTI_CODEC_NUM; i++) {
+               hifi4_priv->process_info[i].data_buf_virt =
+                               hifi4_priv->data_buf_virt +
+                               i * hifi4_priv->data_buf_size / MULTI_CODEC_NUM;
+               hifi4_priv->process_info[i].data_buf_phys =
+                               hifi4_priv->data_buf_phys +
+                               i * hifi4_priv->data_buf_size / MULTI_CODEC_NUM;
+
+               hifi4_priv->process_info[i].status = 0;
+       }
+       send_dpu_ext_msg_addr(hifi4_priv);
+}
+
 static int fsl_hifi4_open(struct inode *inode, struct file *file)
 {
        struct fsl_hifi4 *hifi4_priv;
@@ -1506,6 +1524,10 @@ static int fsl_hifi4_open(struct inode *inode, struct file *file)
                        return ret;
                dev_info(dev, "hifi driver registered\n");
        }
+
+       /* increase reference counter when opening device */
+       atomic_long_inc(&hifi4_priv->refcnt);
+
        mutex_unlock(&hifi4_priv->hifi4_mutex);
 
        return ret;
@@ -1524,6 +1546,14 @@ static int fsl_hifi4_close(struct inode *inode, struct file *file)
        hifi4_engine = file->private_data;
        devm_kfree(dev, hifi4_engine);
 
+       /* decrease reference counter when closing device */
+       atomic_long_dec(&hifi4_priv->refcnt);
+       /* If device is free, reinitialize the resource of
+        * hifi4 driver and framework
+        */
+       if (atomic_long_read(&hifi4_priv->refcnt) <= 0)
+               resource_release(hifi4_priv);
+
        mutex_unlock(&hifi4_priv->hifi4_mutex);
 
        return 0;
@@ -2099,6 +2129,10 @@ static int fsl_hifi4_probe(struct platform_device *pdev)
                hifi4_priv->process_info[i].status = 0;
        }
 
+       /* initialize the reference counter for hifi4_priv
+        * structure
+        */
+       atomic_long_set(&hifi4_priv->refcnt, 0);
        mutex_init(&hifi4_priv->hifi4_mutex);
 
        return 0;
index 00b84ea..fa70580 100644 (file)
@@ -194,6 +194,7 @@ struct fsl_hifi4 {
        sc_ipc_t                        mu_ipcHandle;
        unsigned int                    hifi_mu_id;
        int                             hifi_mu_init;
+       atomic_long_t                   refcnt;
        unsigned long                   paddr;
        unsigned long                   dram0;
        unsigned long                   dram1;
@@ -304,6 +305,7 @@ static void hifi4_load_firmware(const struct firmware *fw, void *context);
 u32 icm_intr_send(struct fsl_hifi4 *hifi4_priv, u32 msg);
 u32 icm_intr_extended_send(struct fsl_hifi4 *hifi4_priv, u32 msg,
                                        struct hifi4_ext_msg *ext_msg);
+int send_dpu_ext_msg_addr(struct fsl_hifi4 *hifi4_priv);
 long icm_ack_wait(struct fsl_hifi4 *hifi4_priv, u32 msg);
 
 unsigned int xtlib_split_pi_library_size(