From a4df3c033004c6ebbdc14a28c3dc6ab6d2a84e44 Mon Sep 17 00:00:00 2001 From: SPRESENSE <41312067+SPRESENSE@users.noreply.github.com> Date: Mon, 24 Oct 2022 11:55:33 +0900 Subject: [PATCH] arch: cxd56xx: Fix deadlock by using GNSS CEP file on SPI-Flash If you specify a file path on SPI-Flash in CONFIG_CXD56_GNSS_CEP_FILENAME, it causes a deadlock issue in the inter-CPU communication. To resolve it, introduce a new CONFIG_CXD56_GNSS_CEP_ON_SPIFLASH and then use pre-read buffers during checking CEP file. So this needs the large of free memory. --- arch/arm/src/cxd56xx/Kconfig | 6 ++ arch/arm/src/cxd56xx/cxd56_gnss.c | 108 ++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) diff --git a/arch/arm/src/cxd56xx/Kconfig b/arch/arm/src/cxd56xx/Kconfig index 4dac76472c..e845fc2bde 100644 --- a/arch/arm/src/cxd56xx/Kconfig +++ b/arch/arm/src/cxd56xx/Kconfig @@ -1312,6 +1312,12 @@ config CXD56_GNSS_CEP_FILENAME ---help--- Specify the path and file name of cep data. +config CXD56_GNSS_CEP_ON_SPIFLASH + bool "GNSS CEP file on SPI-Flash" + default n + ---help--- + Use a cep file on SPI-Flash. + config CXD56_GNSS_FW_RTK bool "Support carrier-phase data output for Real-Time Kinematic" default n diff --git a/arch/arm/src/cxd56xx/cxd56_gnss.c b/arch/arm/src/cxd56xx/cxd56_gnss.c index 58907d8b32..3c346f0029 100644 --- a/arch/arm/src/cxd56xx/cxd56_gnss.c +++ b/arch/arm/src/cxd56xx/cxd56_gnss.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -394,6 +395,14 @@ static struct pm_cpu_freqlock_s g_lv_lock = static struct pm_cpu_freqlock_s g_hold_lock = PM_CPUFREQLOCK_INIT(0, PM_CPUFREQLOCK_FLAG_HOLD); +#ifdef CONFIG_CXD56_GNSS_CEP_ON_SPIFLASH +/* Buffer and length for CEP data on SPI-Flash */ + +static int g_check_cep_flag = 0; +static char *g_cepdata = NULL; +static size_t g_ceplen = 0; +#endif + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -1013,6 +1022,82 @@ static int cxd56_gnss_close_cep_data(struct file *filep, * Zero (OK) on success; a negated errno value on failure. * ****************************************************************************/ +#ifdef CONFIG_CXD56_GNSS_CEP_ON_SPIFLASH +static int cxd56_gnss_check_cep_data(struct file *filep, unsigned long arg) +{ + int ret; + struct stat statbuf; + struct inode *inode; + struct cxd56_gnss_dev_s *priv; + + inode = filep->f_inode; + priv = (struct cxd56_gnss_dev_s *)inode->i_private; + + /* Set a flag for checking CEP data */ + + g_check_cep_flag = 1; + + /* Allocate a buffer and read all of CEP data to it */ + + g_cepdata = NULL; + g_ceplen = 0; + + ret = file_fstat(&priv->cepfp, &statbuf); + if (ret == 0) + { + g_ceplen = (size_t)statbuf.st_size; + } + else + { + return ret; + } + + if (g_ceplen > 0) + { + g_cepdata = (char *)kmm_malloc(g_ceplen); + } + + if (!g_cepdata) + { + gnsserr("Failed to allocate cep data\n"); + return -ENOMEM; + } + + /* Set the file position to the beginning before reading */ + + ret = file_seek(&priv->cepfp, 0, SEEK_SET); + if (ret < 0) + { + goto errout; + } + + ret = file_read(&priv->cepfp, g_cepdata, g_ceplen); + if (ret < 0) + { + goto errout; + } + + ret = fw_gd_cepcheckassistdata(); + +errout: + + /* Free an allocated buffer */ + + if (g_cepdata) + { + kmm_free(g_cepdata); + g_cepdata = NULL; + g_ceplen = 0; + } + + /* Clear a flag for checking CEP data */ + + g_check_cep_flag = 0; + + return ret; +} + +#else /* !CONFIG_CXD56_GNSS_CEP_ON_SPIFLASH */ static int cxd56_gnss_check_cep_data(struct file *filep, unsigned long arg) @@ -1020,6 +1105,8 @@ static int cxd56_gnss_check_cep_data(struct file *filep, return fw_gd_cepcheckassistdata(); } +#endif + /**************************************************************************** * Name: cxd56_gnss_get_cep_age * @@ -2136,6 +2223,27 @@ cxd56_gnss_read_cep_file(struct file *fp, int32_t offset, char *buf; int ret; +#ifdef CONFIG_CXD56_GNSS_CEP_ON_SPIFLASH + if (g_check_cep_flag) + { + /* If checking CEP data, use a pre-read buffer in advance */ + + if (offset + len > g_ceplen) + { + ret = -ENOENT; + goto _err0; + } + + buf = &g_cepdata[offset]; + + *retval = len; + + cxd56_cpu1sigsend(CXD56_CPU1_DATA_TYPE_CEP, (uint32_t)buf); + + return NULL; + } +#endif + if (fp == NULL) { ret = -ENOENT;