coresight: disable device before unregister

coresight_claim_device will fail when unregister device
which has been enabled. device should be the init state when
it is unregistered.

Signed-off-by: liaoao <liaoao@xiaomi.com>
This commit is contained in:
liaoao 2024-01-10 18:12:10 +08:00 committed by Xiang Xiao
parent 8a57dafdcf
commit 6f770fb4b1
5 changed files with 93 additions and 0 deletions

View File

@ -791,6 +791,36 @@ void coresight_unregister(FAR struct coresight_dev_s *csdev)
}
}
if (csdev->refcnt > 0)
{
switch (csdev->type)
{
case CORESIGHT_DEV_TYPE_SINK:
if (csdev->ops->sink_ops->disable != NULL)
{
csdev->ops->sink_ops->disable(csdev);
}
break;
case CORESIGHT_DEV_TYPE_SOURCE:
if (csdev->ops->source_ops->disable != NULL)
{
csdev->ops->source_ops->disable(csdev);
}
break;
/* Link devices may have multiple inport or outport, it can
* not be distinguished here which one of them has been enabled.
* so disable inport/outports in its own unregister function.
*/
default:
break;
}
coresight_disable_clk(csdev);
}
list_delete(&csdev->node);
leave_critical_section(flags);

View File

@ -25,6 +25,7 @@
#include <errno.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include <nuttx/irq.h>
#include <nuttx/coresight/coresight_funnel.h>
@ -223,6 +224,7 @@ funnel_register(FAR const struct coresight_desc_s *desc)
return NULL;
}
fundev->port_num = desc->inport_num;
csdev = &fundev->csdev;
csdev->ops = &g_funnel_ops;
ret = coresight_register(csdev, desc);
@ -249,6 +251,24 @@ funnel_register(FAR const struct coresight_desc_s *desc)
void funnel_unregister(FAR struct coresight_funnel_dev_s *fundev)
{
irqstate_t flags;
flags = enter_critical_section();
if (fundev->csdev.refcnt > 0)
{
int i;
for (i = 0; i < fundev->port_num; i++)
{
if (fundev->port_refcnt[i] > 0)
{
funnel_hw_disable(fundev, i);
}
}
}
leave_critical_section(flags);
coresight_unregister(&fundev->csdev);
kmm_free(fundev);
}

View File

@ -25,6 +25,7 @@
#include <errno.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include <nuttx/irq.h>
#include <nuttx/coresight/coresight_replicator.h>
@ -274,6 +275,24 @@ replicator_register(FAR const struct coresight_desc_s *desc)
void replicator_unregister(FAR struct coresight_replicator_dev_s *repdev)
{
irqstate_t flags;
flags = enter_critical_section();
if (repdev->csdev.refcnt > 0)
{
int i;
for (i = 0; i < repdev->csdev.outport_num; i++)
{
if (repdev->port_refcnt[i] > 0)
{
replicator_hw_disable(repdev, i);
}
}
}
leave_critical_section(flags);
coresight_unregister(&repdev->csdev);
kmm_free(repdev);
}

View File

@ -319,6 +319,11 @@ static int tmc_etf_link_enable(FAR struct coresight_dev_s *csdev,
(FAR struct coresight_tmc_dev_s *)csdev;
int ret;
if (csdev->refcnt != 1)
{
return 0;
}
ret = coresight_claim_device(tmcdev->csdev.addr);
if (ret < 0)
{
@ -345,6 +350,11 @@ static void tmc_etf_link_disable(FAR struct coresight_dev_s *csdev,
FAR struct coresight_tmc_dev_s *tmcdev =
(FAR struct coresight_tmc_dev_s *)csdev;
if (csdev->refcnt != 1)
{
return;
}
tmc_etf_hw_disable(tmcdev);
coresight_disclaim_device(tmcdev->csdev.addr);
}
@ -545,6 +555,19 @@ void tmc_etf_unregister(FAR struct coresight_tmc_dev_s * tmcdev)
snprintf(pathname, sizeof(pathname), "/dev/%s", tmcdev->csdev.name);
unregister_driver(pathname);
}
else if (tmcdev->csdev.refcnt > 0)
{
irqstate_t flags;
/* Link device should disable hw here, and sink device will disable
* hw in coresight_core.c
*/
flags = enter_critical_section();
tmc_etf_hw_disable(tmcdev);
coresight_disclaim_device(tmcdev->csdev.addr);
leave_critical_section(flags);
}
coresight_unregister(&tmcdev->csdev);
}

View File

@ -35,6 +35,7 @@ struct coresight_funnel_dev_s
{
struct coresight_dev_s csdev;
uint32_t priority; /* Port selection order. */
uint8_t port_num; /* Port numbre. */
uint8_t port_refcnt[0]; /* Port refcnt. */
};