Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 2 Dec 2017 01:10:45 +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: r326452 - head/sys/dev/bhnd/cores/pmu
Message-ID:  <201712020110.vB21Ajw5059961@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: landonf
Date: Sat Dec  2 01:10:45 2017
New Revision: 326452
URL: https://svnweb.freebsd.org/changeset/base/326452

Log:
  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

Modified:
  head/sys/dev/bhnd/cores/pmu/bhnd_pmu.c

Modified: head/sys/dev/bhnd/cores/pmu/bhnd_pmu.c
==============================================================================
--- head/sys/dev/bhnd/cores/pmu/bhnd_pmu.c	Sat Dec  2 01:07:41 2017	(r326451)
+++ head/sys/dev/bhnd/cores/pmu/bhnd_pmu.c	Sat Dec  2 01:10:45 2017	(r326452)
@@ -133,33 +133,14 @@ bhnd_pmu_attach(device_t dev, struct bhnd_resource *re
 		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 *re
 
 	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 *re
 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);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201712020110.vB21Ajw5059961>