mirror of
https://github.com/freebsd/freebsd-src
synced 2024-07-22 10:48:02 +00:00
bhnd_pmu(4): Do not leak our chipc provider reference or clkctl state in
failure paths of bhnd_pmu_attach() Approved by: adrian (mentor, implicit) Sponsored by: The FreeBSD Foundation
This commit is contained in:
parent
d16875a806
commit
78baa4d625
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=326452
|
@ -133,33 +133,14 @@ bhnd_pmu_attach(device_t dev, struct bhnd_resource *res)
|
|||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Allocate our own core clkctl state directly; we use this to wait on
|
||||
* PMU state transitions, avoiding a cyclic dependency between bhnd(4)'s
|
||||
* clkctl handling and registration of this device as a PMU */
|
||||
sc->clkctl = bhnd_alloc_core_clkctl(core, dev, sc->res, BHND_CLK_CTL_ST,
|
||||
BHND_PMU_MAX_TRANSITION_DLY);
|
||||
if (sc->clkctl == NULL) {
|
||||
device_printf(sc->dev, "failed to allocate clkctl for %s\n",
|
||||
device_get_nameunit(core));
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
/* Fetch chip and board info */
|
||||
sc->cid = *bhnd_get_chipid(core);
|
||||
|
||||
if ((error = bhnd_read_board_info(core, &sc->board))) {
|
||||
device_printf(sc->dev, "error fetching board info: %d\n",
|
||||
error);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Locate ChipCommon device */
|
||||
sc->chipc_dev = bhnd_retain_provider(dev, BHND_SERVICE_CHIPC);
|
||||
if (sc->chipc_dev == NULL) {
|
||||
device_printf(sc->dev, "chipcommon device not found\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Initialize query state */
|
||||
error = bhnd_pmu_query_init(&sc->query, dev, sc->cid, &bhnd_pmu_res_io,
|
||||
sc);
|
||||
|
@ -170,6 +151,26 @@ bhnd_pmu_attach(device_t dev, struct bhnd_resource *res)
|
|||
|
||||
BPMU_LOCK_INIT(sc);
|
||||
|
||||
/* Allocate our own core clkctl state directly; we use this to wait on
|
||||
* PMU state transitions, avoiding a cyclic dependency between bhnd(4)'s
|
||||
* clkctl handling and registration of this device as a PMU */
|
||||
sc->clkctl = bhnd_alloc_core_clkctl(core, dev, sc->res, BHND_CLK_CTL_ST,
|
||||
BHND_PMU_MAX_TRANSITION_DLY);
|
||||
if (sc->clkctl == NULL) {
|
||||
device_printf(sc->dev, "failed to allocate clkctl for %s\n",
|
||||
device_get_nameunit(core));
|
||||
error = ENOMEM;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* Locate ChipCommon device */
|
||||
sc->chipc_dev = bhnd_retain_provider(dev, BHND_SERVICE_CHIPC);
|
||||
if (sc->chipc_dev == NULL) {
|
||||
device_printf(sc->dev, "chipcommon device not found\n");
|
||||
error = ENXIO;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* Initialize PMU */
|
||||
if ((error = bhnd_pmu_init(sc))) {
|
||||
device_printf(sc->dev, "PMU init failed: %d\n", error);
|
||||
|
@ -204,8 +205,14 @@ bhnd_pmu_attach(device_t dev, struct bhnd_resource *res)
|
|||
failed:
|
||||
BPMU_LOCK_DESTROY(sc);
|
||||
bhnd_pmu_query_fini(&sc->query);
|
||||
bhnd_free_core_clkctl(sc->clkctl);
|
||||
bhnd_release_provider(sc->dev, sc->chipc_dev, BHND_SERVICE_CHIPC);
|
||||
|
||||
if (sc->clkctl != NULL)
|
||||
bhnd_free_core_clkctl(sc->clkctl);
|
||||
|
||||
if (sc->chipc_dev != NULL) {
|
||||
bhnd_release_provider(sc->dev, sc->chipc_dev,
|
||||
BHND_SERVICE_CHIPC);
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue