Date: Thu, 16 Jun 2016 19:57:24 +0000 (UTC) From: "Landon J. Fuller" <landonf@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r301971 - in head/sys/dev/bhnd: . cores/chipc Message-ID: <201606161957.u5GJvOaZ021916@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: landonf Date: Thu Jun 16 19:57:24 2016 New Revision: 301971 URL: https://svnweb.freebsd.org/changeset/base/301971 Log: bhnd(4): Fix resource allocation issues exposed by chipc PMU support. - Delete all chipc children on attachment failure. - Added missing bhnd_nexus bhnd_bus_deactivate_resource implementation. - Drop a CHIPC_UNLOCK() accidentally left behind after lifting synchronization into the chipc region refcounting API. - Fix re-allocation of chipc resources. Previously, the resource ID was reset to -1 on release, preventing later re-allocation. Approved by: re (gjb), adrian (mentor) Differential Revision: https://reviews.freebsd.org/D6849 Modified: head/sys/dev/bhnd/bhnd_nexus.c head/sys/dev/bhnd/cores/chipc/chipc.c head/sys/dev/bhnd/cores/chipc/chipc_private.h head/sys/dev/bhnd/cores/chipc/chipc_subr.c Modified: head/sys/dev/bhnd/bhnd_nexus.c ============================================================================== --- head/sys/dev/bhnd/bhnd_nexus.c Thu Jun 16 17:59:15 2016 (r301970) +++ head/sys/dev/bhnd/bhnd_nexus.c Thu Jun 16 19:57:24 2016 (r301971) @@ -106,10 +106,26 @@ bhnd_nexus_activate_resource(device_t de return (0); } +static int +bhnd_nexus_deactivate_resource(device_t dev, device_t child, + int type, int rid, struct bhnd_resource *r) +{ + int error; + + /* Always direct */ + KASSERT(r->direct, ("indirect resource delegated to bhnd_nexus\n")); + + if ((error = bus_deactivate_resource(child, type, rid, r->res))) + return (error); + + r->direct = false; + return (0); +} static device_method_t bhnd_nexus_methods[] = { /* bhnd interface */ DEVMETHOD(bhnd_bus_activate_resource, bhnd_nexus_activate_resource), + DEVMETHOD(bhnd_bus_deactivate_resource, bhnd_nexus_deactivate_resource), DEVMETHOD(bhnd_bus_is_hw_disabled, bhnd_nexus_is_hw_disabled), DEVMETHOD(bhnd_bus_get_attach_type, bhnd_nexus_get_attach_type), Modified: head/sys/dev/bhnd/cores/chipc/chipc.c ============================================================================== --- head/sys/dev/bhnd/cores/chipc/chipc.c Thu Jun 16 17:59:15 2016 (r301970) +++ head/sys/dev/bhnd/cores/chipc/chipc.c Thu Jun 16 19:57:24 2016 (r301971) @@ -282,6 +282,8 @@ chipc_attach(device_t dev) return (0); failed: + device_delete_children(sc->dev); + if (sc->core_region != NULL) { chipc_release_region(sc, sc->core_region, RF_ALLOCATED|RF_ACTIVE); @@ -878,10 +880,8 @@ chipc_alloc_resource(device_t dev, devic } /* Try to retain a region reference */ - if ((error = chipc_retain_region(sc, cr, RF_ALLOCATED))) { - CHIPC_UNLOCK(sc); + if ((error = chipc_retain_region(sc, cr, RF_ALLOCATED))) return (NULL); - } /* Make our rman reservation */ rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE, Modified: head/sys/dev/bhnd/cores/chipc/chipc_private.h ============================================================================== --- head/sys/dev/bhnd/cores/chipc/chipc_private.h Thu Jun 16 17:59:15 2016 (r301970) +++ head/sys/dev/bhnd/cores/chipc/chipc_private.h Thu Jun 16 19:57:24 2016 (r301971) @@ -84,11 +84,13 @@ struct chipc_region { bhnd_addr_t cr_addr; /**< region base address */ bhnd_addr_t cr_end; /**< region end address */ bhnd_size_t cr_count; /**< region count */ - int cr_rid; /**< rid, or -1 if no rid - * is allocated by the bus for - * this region */ + int cr_rid; /**< rid to use when performing + resource allocation, or -1 + if region has no assigned + resource ID */ struct bhnd_resource *cr_res; /**< bus resource, or NULL */ + int cr_res_rid; /**< cr_res RID, if any. */ u_int cr_refs; /**< RF_ALLOCATED refcount */ u_int cr_act_refs; /**< RF_ACTIVE refcount */ Modified: head/sys/dev/bhnd/cores/chipc/chipc_subr.c ============================================================================== --- head/sys/dev/bhnd/cores/chipc/chipc_subr.c Thu Jun 16 17:59:15 2016 (r301970) +++ head/sys/dev/bhnd/cores/chipc/chipc_subr.c Thu Jun 16 19:57:24 2016 (r301971) @@ -150,9 +150,10 @@ chipc_alloc_region(struct chipc_softc *s cr->cr_end = cr->cr_addr + cr->cr_count - 1; - /* Note that not all regions have an assigned rid, in which case - * this will return -1 */ + /* Fetch default resource ID for this region. Not all regions have an + * assigned rid, in which case this will return -1 */ cr->cr_rid = bhnd_get_port_rid(sc->dev, type, port, region); + return (cr); failed: @@ -177,7 +178,7 @@ chipc_free_region(struct chipc_softc *sc cr->cr_region_num, cr->cr_refs)); if (cr->cr_res != NULL) { - bhnd_release_resource(sc->dev, SYS_RES_MEMORY, cr->cr_rid, + bhnd_release_resource(sc->dev, SYS_RES_MEMORY, cr->cr_res_rid, cr->cr_res); } @@ -264,10 +265,16 @@ chipc_retain_region(struct chipc_softc * KASSERT(cr->cr_res == NULL, ("non-NULL resource has refcount")); + /* Fetch initial resource ID */ + if ((cr->cr_res_rid = cr->cr_rid) == -1) { + CHIPC_UNLOCK(sc); + return (EINVAL); + } + + /* Allocate resource */ cr->cr_res = bhnd_alloc_resource(sc->dev, - SYS_RES_MEMORY, &cr->cr_rid, cr->cr_addr, + SYS_RES_MEMORY, &cr->cr_res_rid, cr->cr_addr, cr->cr_end, cr->cr_count, 0); - if (cr->cr_res == NULL) { CHIPC_UNLOCK(sc); return (ENXIO); @@ -287,7 +294,7 @@ chipc_retain_region(struct chipc_softc * /* If this is the first reference, activate the resource */ if (cr->cr_act_refs == 0) { error = bhnd_activate_resource(sc->dev, SYS_RES_MEMORY, - cr->cr_rid, cr->cr_res); + cr->cr_res_rid, cr->cr_res); if (error) { /* Drop any allocation reference acquired * above */ @@ -324,6 +331,8 @@ chipc_release_region(struct chipc_softc CHIPC_LOCK(sc); error = 0; + KASSERT(cr->cr_res != NULL, ("release on NULL region resource")); + if (flags & RF_ACTIVE) { KASSERT(cr->cr_act_refs > 0, ("RF_ACTIVE over-released")); KASSERT(cr->cr_act_refs <= cr->cr_refs, @@ -332,7 +341,7 @@ chipc_release_region(struct chipc_softc /* If this is the last reference, deactivate the resource */ if (cr->cr_act_refs == 1) { error = bhnd_deactivate_resource(sc->dev, - SYS_RES_MEMORY, cr->cr_rid, cr->cr_res); + SYS_RES_MEMORY, cr->cr_res_rid, cr->cr_res); if (error) goto done; } @@ -343,16 +352,14 @@ chipc_release_region(struct chipc_softc if (flags & RF_ALLOCATED) { KASSERT(cr->cr_refs > 0, ("overrelease of refs")); - /* If this is the last reference, release the resource */ if (cr->cr_refs == 1) { - error = bhnd_release_resource(sc->dev, - SYS_RES_MEMORY, cr->cr_rid, cr->cr_res); + error = bhnd_release_resource(sc->dev, SYS_RES_MEMORY, + cr->cr_res_rid, cr->cr_res); if (error) goto done; cr->cr_res = NULL; - cr->cr_rid = -1; } /* Drop our allocation refcount */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201606161957.u5GJvOaZ021916>