From owner-svn-src-stable@freebsd.org  Sun Aug  6 08:15:22 2017
Return-Path: <owner-svn-src-stable@freebsd.org>
Delivered-To: svn-src-stable@mailman.ysv.freebsd.org
Received: from mx1.freebsd.org (mx1.freebsd.org
 [IPv6:2001:1900:2254:206a::19:1])
 by mailman.ysv.freebsd.org (Postfix) with ESMTP id 72B72DCACA1;
 Sun,  6 Aug 2017 08:15:22 +0000 (UTC) (envelope-from mav@FreeBSD.org)
Received: from repo.freebsd.org (repo.freebsd.org
 [IPv6:2610:1c1:1:6068::e6a:0])
 (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
 (Client did not present a certificate)
 by mx1.freebsd.org (Postfix) with ESMTPS id 4935B7C4F7;
 Sun,  6 Aug 2017 08:15:22 +0000 (UTC) (envelope-from mav@FreeBSD.org)
Received: from repo.freebsd.org ([127.0.1.37])
 by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v768FLZI097279;
 Sun, 6 Aug 2017 08:15:21 GMT (envelope-from mav@FreeBSD.org)
Received: (from mav@localhost)
 by repo.freebsd.org (8.15.2/8.15.2/Submit) id v768FLDn097278;
 Sun, 6 Aug 2017 08:15:21 GMT (envelope-from mav@FreeBSD.org)
Message-Id: <201708060815.v768FLDn097278@repo.freebsd.org>
X-Authentication-Warning: repo.freebsd.org: mav set sender to mav@FreeBSD.org
 using -f
From: Alexander Motin <mav@FreeBSD.org>
Date: Sun, 6 Aug 2017 08:15:21 +0000 (UTC)
To: src-committers@freebsd.org, svn-src-all@freebsd.org,
 svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject: svn commit: r322116 - stable/10/sys/dev/ichwd
X-SVN-Group: stable-10
X-SVN-Commit-Author: mav
X-SVN-Commit-Paths: stable/10/sys/dev/ichwd
X-SVN-Commit-Revision: 322116
X-SVN-Commit-Repository: base
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
X-BeenThere: svn-src-stable@freebsd.org
X-Mailman-Version: 2.1.23
Precedence: list
List-Id: SVN commit messages for all the -stable branches of the src tree
 <svn-src-stable.freebsd.org>
List-Unsubscribe: <https://lists.freebsd.org/mailman/options/svn-src-stable>, 
 <mailto:svn-src-stable-request@freebsd.org?subject=unsubscribe>
List-Archive: <http://lists.freebsd.org/pipermail/svn-src-stable/>
List-Post: <mailto:svn-src-stable@freebsd.org>
List-Help: <mailto:svn-src-stable-request@freebsd.org?subject=help>
List-Subscribe: <https://lists.freebsd.org/mailman/listinfo/svn-src-stable>,
 <mailto:svn-src-stable-request@freebsd.org?subject=subscribe>
X-List-Received-Date: Sun, 06 Aug 2017 08:15:22 -0000

Author: mav
Date: Sun Aug  6 08:15:21 2017
New Revision: 322116
URL: https://svnweb.freebsd.org/changeset/base/322116

Log:
  MFC r321720, r321856: Attach ichwd(4) only to ISA bus of the LPC bridge.
  
  Resource allocation for parent device does not look good by itself, but
  attempt to allocate them for unrelated device just does not end up good.
  On Asus X99-E WS/USB3.1 system reporting ISA bridge via both PCI and ACPI
  this reported to cause kernel panic on shutdown due to messed resources:
  https://bugs.freenas.org/issues/25237.

Modified:
  stable/10/sys/dev/ichwd/ichwd.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/ichwd/ichwd.c
==============================================================================
--- stable/10/sys/dev/ichwd/ichwd.c	Sun Aug  6 08:14:46 2017	(r322115)
+++ stable/10/sys/dev/ichwd/ichwd.c	Sun Aug  6 08:15:21 2017	(r322116)
@@ -527,23 +527,29 @@ ichwd_event(void *arg, unsigned int cmd, int *error)
 }
 
 static device_t
-ichwd_find_ich_lpc_bridge(struct ichwd_device **id_p)
+ichwd_find_ich_lpc_bridge(device_t isa, struct ichwd_device **id_p)
 {
 	struct ichwd_device *id;
-	device_t ich = NULL;
+	device_t isab, pci;
+	uint16_t devid;
 
-	/* look for an ICH LPC interface bridge */
-	for (id = ichwd_devices; id->desc != NULL; ++id)
-		if ((ich = pci_find_device(VENDORID_INTEL, id->device)) != NULL)
-			break;
-
-	if (ich == NULL)
+	/* Check whether parent ISA bridge looks familiar. */
+	isab = device_get_parent(isa);
+	pci = device_get_parent(isab);
+	if (pci == NULL || device_get_devclass(pci) != devclass_find("pci"))
 		return (NULL);
+	if (pci_get_vendor(isab) != VENDORID_INTEL)
+		return (NULL);
+	devid = pci_get_device(isab);
+	for (id = ichwd_devices; id->desc != NULL; ++id) {
+		if (devid == id->device) {
+			if (id_p != NULL)
+				*id_p = id;
+			return (isab);
+		}
+	}
 
-	if (id_p)
-		*id_p = id;
-
-	return (ich);
+	return (NULL);
 }
 
 /*
@@ -559,7 +565,7 @@ ichwd_identify(driver_t *driver, device_t parent)
 	uint32_t base_address;
 	int rc;
 
-	ich = ichwd_find_ich_lpc_bridge(&id_p);
+	ich = ichwd_find_ich_lpc_bridge(parent, &id_p);
 	if (ich == NULL)
 		return;
 
@@ -612,7 +618,7 @@ ichwd_probe(device_t dev)
 	if (isa_get_logicalid(dev) != 0)
 		return (ENXIO);
 
-	if (ichwd_find_ich_lpc_bridge(&id_p) == NULL)
+	if (ichwd_find_ich_lpc_bridge(device_get_parent(dev), &id_p) == NULL)
 		return (ENXIO);
 
 	device_set_desc_copy(dev, id_p->desc);
@@ -630,7 +636,7 @@ ichwd_attach(device_t dev)
 	sc = device_get_softc(dev);
 	sc->device = dev;
 
-	ich = ichwd_find_ich_lpc_bridge(&id_p);
+	ich = ichwd_find_ich_lpc_bridge(device_get_parent(dev), &id_p);
 	if (ich == NULL) {
 		device_printf(sc->device, "Can not find ICH device.\n");
 		goto fail;
@@ -720,7 +726,6 @@ static int
 ichwd_detach(device_t dev)
 {
 	struct ichwd_softc *sc;
-	device_t ich = NULL;
 
 	sc = device_get_softc(dev);
 
@@ -745,9 +750,8 @@ ichwd_detach(device_t dev)
 	bus_release_resource(dev, SYS_RES_IOPORT, sc->smi_rid, sc->smi_res);
 
 	/* deallocate memory resource */
-	ich = ichwd_find_ich_lpc_bridge(NULL);
-	if (sc->gcs_res && ich)
-		bus_release_resource(ich, SYS_RES_MEMORY, sc->gcs_rid,
+	if (sc->gcs_res)
+		bus_release_resource(sc->ich, SYS_RES_MEMORY, sc->gcs_rid,
 		    sc->gcs_res);
 
 	return (0);