sim/sim_rptun: Support master/slave notifies opposite side when recovery
When in a multi-core structure, as the intermediate core, remote is both the master and slave;When the remote exception or restart occurs, it needs to notify the slave and reestablish the connection Signed-off-by: yintao <yintao@xiaomi.com>
This commit is contained in:
parent
a20cc9f04c
commit
4f14f8226a
@ -92,32 +92,20 @@ void host_freeheap(void *mem)
|
||||
host_uninterruptible(munmap, mem, 0);
|
||||
}
|
||||
|
||||
void *host_allocshmem(const char *name, size_t size, int master)
|
||||
void *host_allocshmem(const char *name, size_t size)
|
||||
{
|
||||
void *mem;
|
||||
int oflag;
|
||||
int ret;
|
||||
int fd;
|
||||
|
||||
oflag = O_RDWR;
|
||||
if (master)
|
||||
{
|
||||
oflag |= O_CREAT | O_TRUNC;
|
||||
}
|
||||
|
||||
oflag = O_RDWR | O_CREAT;
|
||||
fd = host_uninterruptible(shm_open, name, oflag, S_IRUSR | S_IWUSR);
|
||||
if (fd < 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!master)
|
||||
{
|
||||
/* Avoid the second slave instance open successfully */
|
||||
|
||||
host_unlinkshmem(name);
|
||||
}
|
||||
|
||||
ret = host_uninterruptible(ftruncate, fd, size);
|
||||
if (ret < 0)
|
||||
{
|
||||
|
@ -224,7 +224,7 @@ int host_waitpid(pid_t pid);
|
||||
|
||||
void *host_allocheap(size_t size, bool exec);
|
||||
void host_freeheap(void *mem);
|
||||
void *host_allocshmem(const char *name, size_t size, int master);
|
||||
void *host_allocshmem(const char *name, size_t size);
|
||||
void host_freeshmem(void *mem);
|
||||
|
||||
size_t host_mallocsize(void *mem);
|
||||
|
@ -40,6 +40,12 @@
|
||||
#define SIM_RPTUN_SHIFT 16
|
||||
#define SIM_RPTUN_WORK_DELAY 1
|
||||
|
||||
/* Status byte for master/slave to report progress */
|
||||
|
||||
#define SIM_RPTUN_STATUS_BOOT 0x01
|
||||
#define SIM_RPTUN_STATUS_OK 0x02
|
||||
#define SIM_RPTUN_STATUS_NEED_RESET 0x04
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
@ -51,6 +57,8 @@ struct sim_rptun_shmem_s
|
||||
volatile unsigned int seqm;
|
||||
volatile unsigned int cmds;
|
||||
volatile unsigned int cmdm;
|
||||
volatile unsigned int boots;
|
||||
volatile unsigned int bootm;
|
||||
struct rptun_rsc_s rsc;
|
||||
char buf[0x10000];
|
||||
};
|
||||
@ -91,24 +99,14 @@ sim_rptun_get_resource(struct rptun_dev_s *dev)
|
||||
struct sim_rptun_dev_s *priv = container_of(dev,
|
||||
struct sim_rptun_dev_s, rptun);
|
||||
|
||||
if (priv->shmem)
|
||||
{
|
||||
return &priv->shmem->rsc;
|
||||
}
|
||||
|
||||
while (priv->shmem == NULL)
|
||||
{
|
||||
priv->shmem = host_allocshmem(priv->shmemname,
|
||||
sizeof(*priv->shmem),
|
||||
priv->master);
|
||||
usleep(1000);
|
||||
|
||||
/* Master isn't ready, sleep and try again */
|
||||
}
|
||||
priv->shmem = host_allocshmem(priv->shmemname,
|
||||
sizeof(*priv->shmem));
|
||||
|
||||
if (priv->master)
|
||||
{
|
||||
struct rptun_rsc_s *rsc = &priv->shmem->rsc;
|
||||
memset(priv->shmem->buf, 0, sizeof(priv->shmem->buf));
|
||||
memset(rsc, 0, sizeof(struct rptun_rsc_s));
|
||||
|
||||
rsc->rsc_tbl_hdr.ver = 1;
|
||||
rsc->rsc_tbl_hdr.num = 1;
|
||||
@ -121,9 +119,11 @@ sim_rptun_get_resource(struct rptun_dev_s *dev)
|
||||
| 1 << VIRTIO_RPMSG_F_BUFSZ;
|
||||
rsc->rpmsg_vdev.config_len = sizeof(struct fw_rsc_config);
|
||||
rsc->rpmsg_vdev.num_of_vrings = 2;
|
||||
rsc->rpmsg_vring0.da = 0;
|
||||
rsc->rpmsg_vring0.align = 8;
|
||||
rsc->rpmsg_vring0.num = 8;
|
||||
rsc->rpmsg_vring0.notifyid = RSC_NOTIFY_ID_ANY;
|
||||
rsc->rpmsg_vring1.da = 0;
|
||||
rsc->rpmsg_vring1.align = 8;
|
||||
rsc->rpmsg_vring1.num = 8;
|
||||
rsc->rpmsg_vring1.notifyid = RSC_NOTIFY_ID_ANY;
|
||||
@ -131,16 +131,36 @@ sim_rptun_get_resource(struct rptun_dev_s *dev)
|
||||
rsc->config.h2r_buf_size = 0x800;
|
||||
|
||||
priv->shmem->base = (uintptr_t)priv->shmem;
|
||||
|
||||
/* The master notifies its slave when it starts again */
|
||||
|
||||
if (priv->shmem->boots & SIM_RPTUN_STATUS_OK)
|
||||
{
|
||||
priv->shmem->boots = SIM_RPTUN_STATUS_NEED_RESET;
|
||||
}
|
||||
|
||||
priv->shmem->bootm = SIM_RPTUN_STATUS_BOOT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The slave notifies its master when it starts again */
|
||||
|
||||
if (priv->shmem->boots & SIM_RPTUN_STATUS_OK)
|
||||
{
|
||||
priv->shmem->bootm = SIM_RPTUN_STATUS_NEED_RESET;
|
||||
}
|
||||
|
||||
priv->shmem->boots = SIM_RPTUN_STATUS_BOOT;
|
||||
|
||||
/* Wait untils master is ready */
|
||||
|
||||
while (priv->shmem->base == 0)
|
||||
while (!(priv->shmem->bootm & SIM_RPTUN_STATUS_OK))
|
||||
{
|
||||
usleep(1000);
|
||||
}
|
||||
|
||||
priv->shmem->boots = SIM_RPTUN_STATUS_OK;
|
||||
|
||||
priv->addrenv[0].va = (uintptr_t)priv->shmem;
|
||||
priv->addrenv[0].pa = priv->shmem->base;
|
||||
priv->addrenv[0].size = sizeof(*priv->shmem);
|
||||
@ -180,6 +200,14 @@ static int sim_rptun_start(struct rptun_dev_s *dev)
|
||||
priv->pid = pid;
|
||||
}
|
||||
|
||||
/* Wait until slave has started */
|
||||
|
||||
while (!(priv->shmem->boots & SIM_RPTUN_STATUS_BOOT))
|
||||
{
|
||||
usleep(1000);
|
||||
}
|
||||
|
||||
priv->shmem->bootm = SIM_RPTUN_STATUS_OK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -188,13 +216,21 @@ static int sim_rptun_stop(struct rptun_dev_s *dev)
|
||||
struct sim_rptun_dev_s *priv = container_of(dev,
|
||||
struct sim_rptun_dev_s, rptun);
|
||||
|
||||
if ((priv->master & SIM_RPTUN_BOOT) && (priv->pid > 0))
|
||||
/* Don't send SIM_RPTUN_STOP when slave recovery */
|
||||
|
||||
if (priv->shmem->boots & SIM_RPTUN_STATUS_OK)
|
||||
{
|
||||
priv->shmem->cmdm = SIM_RPTUN_STOP << SIM_RPTUN_SHIFT;
|
||||
}
|
||||
|
||||
if ((priv->master & SIM_RPTUN_BOOT) && priv->pid > 0)
|
||||
{
|
||||
host_waitpid(priv->pid);
|
||||
}
|
||||
|
||||
if (priv->shmem)
|
||||
/* Master cleans shmem when both sides are about to exit */
|
||||
|
||||
if (priv->shmem && (priv->shmem->boots & SIM_RPTUN_STATUS_OK))
|
||||
{
|
||||
host_freeshmem(priv->shmem);
|
||||
priv->shmem = NULL;
|
||||
@ -267,6 +303,22 @@ static void sim_rptun_check_cmd(struct sim_rptun_dev_s *priv)
|
||||
}
|
||||
}
|
||||
|
||||
static void sim_rptun_check_reset(struct sim_rptun_dev_s *priv)
|
||||
{
|
||||
if (priv->master &&
|
||||
(priv->shmem->bootm & SIM_RPTUN_STATUS_NEED_RESET))
|
||||
{
|
||||
priv->shmem->bootm = 0;
|
||||
rptun_boot(priv->cpuname);
|
||||
}
|
||||
else if (!priv->master &&
|
||||
(priv->shmem->boots & SIM_RPTUN_STATUS_NEED_RESET))
|
||||
{
|
||||
priv->shmem->boots = 0;
|
||||
rptun_boot(priv->cpuname);
|
||||
}
|
||||
}
|
||||
|
||||
static void sim_rptun_work(void *arg)
|
||||
{
|
||||
struct sim_rptun_dev_s *dev = arg;
|
||||
@ -277,6 +329,10 @@ static void sim_rptun_work(void *arg)
|
||||
|
||||
sim_rptun_check_cmd(dev);
|
||||
|
||||
/* Check if master/slave need to reset */
|
||||
|
||||
sim_rptun_check_reset(dev);
|
||||
|
||||
if (dev->master && dev->seq != dev->shmem->seqs)
|
||||
{
|
||||
dev->seq = dev->shmem->seqs;
|
||||
|
@ -675,7 +675,7 @@ static int sim_uartram_register(const char *devname, bool slave)
|
||||
struct uart_rambuf_s *shmem;
|
||||
|
||||
strlcpy(name, strrchr(devname, '/') + 1, NAME_MAX);
|
||||
shmem = host_allocshmem(name, sizeof(struct uart_rambuf_s) * 2, !slave);
|
||||
shmem = host_allocshmem(name, sizeof(struct uart_rambuf_s) * 2);
|
||||
DEBUGASSERT(shmem);
|
||||
|
||||
memset(shmem, 0, sizeof(struct uart_rambuf_s) * 2);
|
||||
|
@ -56,7 +56,7 @@ void host_freeheap(void *mem)
|
||||
_aligned_free(mem);
|
||||
}
|
||||
|
||||
void *host_allocshmem(const char *name, size_t size, int master)
|
||||
void *host_allocshmem(const char *name, size_t size)
|
||||
{
|
||||
HANDLE handle;
|
||||
void *mem;
|
||||
|
Loading…
x
Reference in New Issue
Block a user