arch: cxd56xx: Fix multiple open and close ADC driver
ADC driver does not support multiple open and close. It causes the memory corruption by multiple free. This commit fixes this problem by introducing the reference counter.
This commit is contained in:
parent
98871e58af
commit
f0cae6cdf3
@ -35,6 +35,7 @@
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/semaphore.h>
|
||||
#include <arch/chip/scu.h>
|
||||
#include <arch/chip/adc.h>
|
||||
|
||||
@ -172,6 +173,8 @@ struct cxd56adc_dev_s
|
||||
struct scufifo_wm_s *wm; /* water mark */
|
||||
struct math_filter_s *filter; /* math filter */
|
||||
struct scuev_notify_s * notify; /* notify */
|
||||
sem_t exclsem; /* exclusive semaphore */
|
||||
int crefs; /* reference count */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
@ -218,6 +221,7 @@ static struct cxd56adc_dev_s g_lpadc0priv =
|
||||
.wm = NULL,
|
||||
.filter = NULL,
|
||||
.notify = NULL,
|
||||
.crefs = 0,
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -233,6 +237,7 @@ static struct cxd56adc_dev_s g_lpadc1priv =
|
||||
.wm = NULL,
|
||||
.filter = NULL,
|
||||
.notify = NULL,
|
||||
.crefs = 0,
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -248,6 +253,7 @@ static struct cxd56adc_dev_s g_lpadc2priv =
|
||||
.wm = NULL,
|
||||
.filter = NULL,
|
||||
.notify = NULL,
|
||||
.crefs = 0,
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -263,6 +269,7 @@ static struct cxd56adc_dev_s g_lpadc3priv =
|
||||
.wm = NULL,
|
||||
.filter = NULL,
|
||||
.notify = NULL,
|
||||
.crefs = 0,
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -278,6 +285,7 @@ static struct cxd56adc_dev_s g_hpadc0priv =
|
||||
.wm = NULL,
|
||||
.filter = NULL,
|
||||
.notify = NULL,
|
||||
.crefs = 0,
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -293,6 +301,7 @@ static struct cxd56adc_dev_s g_hpadc1priv =
|
||||
.wm = NULL,
|
||||
.filter = NULL,
|
||||
.notify = NULL,
|
||||
.crefs = 0,
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -703,9 +712,23 @@ static int cxd56_adc_open(FAR struct file *filep)
|
||||
int type;
|
||||
|
||||
DEBUGASSERT(priv != NULL);
|
||||
DEBUGASSERT(priv->seq == NULL);
|
||||
DEBUGASSERT(priv->ch < CH_MAX);
|
||||
|
||||
/* Increment reference counter */
|
||||
|
||||
nxsem_wait_uninterruptible(&priv->exclsem);
|
||||
|
||||
priv->crefs++;
|
||||
DEBUGASSERT(priv->crefs > 0);
|
||||
|
||||
if (priv->crefs > 1)
|
||||
{
|
||||
nxsem_post(&priv->exclsem);
|
||||
return OK;
|
||||
}
|
||||
|
||||
DEBUGASSERT(priv->seq == NULL);
|
||||
|
||||
type = SCU_BUS_LPADC0 + priv->ch;
|
||||
|
||||
/* Open sequencer */
|
||||
@ -713,6 +736,7 @@ static int cxd56_adc_open(FAR struct file *filep)
|
||||
priv->seq = seq_open(SEQ_TYPE_NORMAL, type);
|
||||
if (!priv->seq)
|
||||
{
|
||||
nxsem_post(&priv->exclsem);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
@ -725,11 +749,14 @@ static int cxd56_adc_open(FAR struct file *filep)
|
||||
ret = set_ofstgain(priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
nxsem_post(&priv->exclsem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ainfo("open ch%d freq%d scufifo%d\n", priv->ch, priv->freq, priv->fsize);
|
||||
|
||||
nxsem_post(&priv->exclsem);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
@ -750,6 +777,19 @@ static int cxd56_adc_close(FAR struct file *filep)
|
||||
DEBUGASSERT(priv->seq != NULL);
|
||||
DEBUGASSERT(priv->ch < CH_MAX);
|
||||
|
||||
/* Decrement reference counter */
|
||||
|
||||
nxsem_wait_uninterruptible(&priv->exclsem);
|
||||
|
||||
DEBUGASSERT(priv->crefs > 0);
|
||||
priv->crefs--;
|
||||
|
||||
if (priv->crefs > 0)
|
||||
{
|
||||
nxsem_post(&priv->exclsem);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Close sequencer */
|
||||
|
||||
seq_close(priv->seq);
|
||||
@ -773,6 +813,8 @@ static int cxd56_adc_close(FAR struct file *filep)
|
||||
priv->notify = NULL;
|
||||
}
|
||||
|
||||
nxsem_post(&priv->exclsem);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
@ -1058,6 +1100,7 @@ int cxd56_adcinitialize(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
nxsem_init(&g_lpadc0priv.exclsem, 0, 1);
|
||||
#endif
|
||||
#if defined (CONFIG_CXD56_LPADC1) || defined (CONFIG_CXD56_LPADC0_1) || defined (CONFIG_CXD56_LPADC_ALL)
|
||||
ret = register_driver("/dev/lpadc1", &g_adcops, 0666, &g_lpadc1priv);
|
||||
@ -1067,6 +1110,7 @@ int cxd56_adcinitialize(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
nxsem_init(&g_lpadc1priv.exclsem, 0, 1);
|
||||
#endif
|
||||
#if defined (CONFIG_CXD56_LPADC2) || defined (CONFIG_CXD56_LPADC_ALL)
|
||||
ret = register_driver("/dev/lpadc2", &g_adcops, 0666, &g_lpadc2priv);
|
||||
@ -1076,6 +1120,7 @@ int cxd56_adcinitialize(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
nxsem_init(&g_lpadc2priv.exclsem, 0, 1);
|
||||
#endif
|
||||
#if defined (CONFIG_CXD56_LPADC3) || defined (CONFIG_CXD56_LPADC_ALL)
|
||||
ret = register_driver("/dev/lpadc3", &g_adcops, 0666, &g_lpadc3priv);
|
||||
@ -1085,6 +1130,7 @@ int cxd56_adcinitialize(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
nxsem_init(&g_lpadc3priv.exclsem, 0, 1);
|
||||
#endif
|
||||
#ifdef CONFIG_CXD56_HPADC0
|
||||
ret = register_driver("/dev/hpadc0", &g_adcops, 0666, &g_hpadc0priv);
|
||||
@ -1094,6 +1140,7 @@ int cxd56_adcinitialize(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
nxsem_init(&g_hpadc0priv.exclsem, 0, 1);
|
||||
#endif
|
||||
#ifdef CONFIG_CXD56_HPADC1
|
||||
ret = register_driver("/dev/hpadc1", &g_adcops, 0666, &g_hpadc1priv);
|
||||
@ -1103,6 +1150,7 @@ int cxd56_adcinitialize(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
nxsem_init(&g_hpadc1priv.exclsem, 0, 1);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
|
Loading…
Reference in New Issue
Block a user