From owner-svn-src-stable@FreeBSD.ORG Thu Jun 27 20:35:39 2013 Return-Path: Delivered-To: svn-src-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id A9C291C9; Thu, 27 Jun 2013 20:35:39 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 99B8A1DC9; Thu, 27 Jun 2013 20:35:39 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id r5RKZdeW070608; Thu, 27 Jun 2013 20:35:39 GMT (envelope-from jhb@svn.freebsd.org) Received: (from jhb@localhost) by svn.freebsd.org (8.14.7/8.14.5/Submit) id r5RKZdgB070607; Thu, 27 Jun 2013 20:35:39 GMT (envelope-from jhb@svn.freebsd.org) Message-Id: <201306272035.r5RKZdgB070607@svn.freebsd.org> From: John Baldwin Date: Thu, 27 Jun 2013 20:35:39 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r252317 - stable/9/sys/dev/pci X-SVN-Group: stable-9 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.14 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 27 Jun 2013 20:35:39 -0000 Author: jhb Date: Thu Jun 27 20:35:39 2013 New Revision: 252317 URL: http://svnweb.freebsd.org/changeset/base/252317 Log: MFC 250418,252166: Revision 233677 broke certain machines. Specifically, if the firmware/BIOS assigned conflicting ranges to BARs then leaving the BARs alone could result in one device stealing mmio accesses intended to go to a second device. Prior to 233677 the PCI bus driver attempted to handle this case by clearing the BAR to 0 depending on BARs based at 0 not decoding (which is not guaranteed to be true). Now when a conflicting BAR is detected the following steps are taken: 1) If hw.pci.realloc_bars (a new tunable) is enabled (default is disabled), then ignore the current BAR setting from the firmware and attempt to allocate a fresh resource range for the BAR. 2) If 1) failed (or was disabled), disable decoding for the relevant BAR type (e.g. disable mem decoding for a memory BAR) and emit a warning if booting verbose. Modified: stable/9/sys/dev/pci/pci.c Directory Properties: stable/9/sys/ (props changed) stable/9/sys/dev/ (props changed) Modified: stable/9/sys/dev/pci/pci.c ============================================================================== --- stable/9/sys/dev/pci/pci.c Thu Jun 27 20:27:34 2013 (r252316) +++ stable/9/sys/dev/pci/pci.c Thu Jun 27 20:35:39 2013 (r252317) @@ -289,6 +289,12 @@ SYSCTL_INT(_hw_pci, OID_AUTO, enable_io_ enable these bits correctly. We'd like to do this all the time, but there\n\ are some peripherals that this causes problems with."); +static int pci_do_realloc_bars = 0; +TUNABLE_INT("hw.pci.realloc_bars", &pci_do_realloc_bars); +SYSCTL_INT(_hw_pci, OID_AUTO, realloc_bars, CTLFLAG_RW, + &pci_do_realloc_bars, 0, + "Attempt to allocate a new range for any BARs whose original firmware-assigned ranges fail to allocate during the initial device scan."); + static int pci_do_power_nodriver = 0; TUNABLE_INT("hw.pci.do_power_nodriver", &pci_do_power_nodriver); SYSCTL_INT(_hw_pci, OID_AUTO, do_power_nodriver, CTLFLAG_RW, @@ -2745,13 +2751,34 @@ pci_add_map(device_t bus, device_t dev, */ res = resource_list_reserve(rl, bus, dev, type, ®, start, end, count, prefetch ? RF_PREFETCHABLE : 0); + if (pci_do_realloc_bars && res == NULL && (start != 0 || end != ~0ul)) { + /* + * If the allocation fails, try to allocate a resource for + * this BAR using any available range. The firmware felt + * it was important enough to assign a resource, so don't + * disable decoding if we can help it. + */ + resource_list_delete(rl, type, reg); + resource_list_add(rl, type, reg, 0, ~0ul, count); + res = resource_list_reserve(rl, bus, dev, type, ®, 0, ~0ul, + count, prefetch ? RF_PREFETCHABLE : 0); + } if (res == NULL) { /* * If the allocation fails, delete the resource list entry - * to force pci_alloc_resource() to allocate resources - * from the parent. + * and disable decoding for this device. + * + * If the driver requests this resource in the future, + * pci_reserve_map() will try to allocate a fresh + * resource range. */ resource_list_delete(rl, type, reg); + pci_disable_io(dev, type); + if (bootverbose) + device_printf(bus, + "pci%d:%d:%d:%d bar %#x failed to allocate\n", + pci_get_domain(dev), pci_get_bus(dev), + pci_get_slot(dev), pci_get_function(dev), reg); } else { start = rman_get_start(res); pci_write_bar(dev, pm, start);