Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755223AbcD0Aro (ORCPT ); Tue, 26 Apr 2016 20:47:44 -0400 Received: from shadbolt.e.decadent.org.uk ([88.96.1.126]:39572 "EHLO shadbolt.e.decadent.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753116AbcDZXN1 (ORCPT ); Tue, 26 Apr 2016 19:13:27 -0400 Content-Type: text/plain; charset="UTF-8" Content-Disposition: inline Content-Transfer-Encoding: 8bit MIME-Version: 1.0 From: Ben Hutchings To: linux-kernel@vger.kernel.org, stable@vger.kernel.org CC: akpm@linux-foundation.org, "Bjorn Helgaas" , "Andi Kleen" Date: Wed, 27 Apr 2016 01:02:24 +0200 Message-ID: X-Mailer: LinuxStableQueue (scripts by bwh) Subject: [PATCH 3.2 012/115] PCI: Disable IO/MEM decoding for devices with non-compliant BARs In-Reply-To: X-SA-Exim-Connect-IP: 2a02:8426:ae4:c500:9cba:69ae:962d:6167 X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2637 Lines: 78 3.2.80-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: Bjorn Helgaas commit b84106b4e2290c081cdab521fa832596cdfea246 upstream. The PCI config header (first 64 bytes of each device's config space) is defined by the PCI spec so generic software can identify the device and manage its usage of I/O, memory, and IRQ resources. Some non-spec-compliant devices put registers other than BARs where the BARs should be. When the PCI core sizes these "BARs", the reads and writes it does may have unwanted side effects, and the "BAR" may appear to describe non-sensical address space. Add a flag bit to mark non-compliant devices so we don't touch their BARs. Turn off IO/MEM decoding to prevent the devices from consuming address space, since we can't read the BARs to find out what that address space would be. Signed-off-by: Bjorn Helgaas Tested-by: Andi Kleen [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings --- drivers/pci/probe.c | 14 ++++++++++++++ include/linux/pci.h | 1 + 2 files changed, 15 insertions(+) --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -136,6 +136,9 @@ int __pci_read_base(struct pci_dev *dev, u32 l, sz, mask; u16 orig_cmd; + if (dev->non_compliant_bars) + return 0; + mask = type ? PCI_ROM_ADDRESS_MASK : ~0; if (!dev->mmio_always_on) { @@ -902,6 +905,7 @@ void set_pcie_hotplug_bridge(struct pci_ int pci_setup_device(struct pci_dev *dev) { u32 class; + u16 cmd; u8 hdr_type; struct pci_slot *slot; int pos = 0; @@ -949,6 +953,16 @@ int pci_setup_device(struct pci_dev *dev /* device class may be changed after fixup */ class = dev->class >> 8; + if (dev->non_compliant_bars) { + pci_read_config_word(dev, PCI_COMMAND, &cmd); + if (cmd & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { + dev_info(&dev->dev, "device has non-compliant BARs; disabling IO/MEM decoding\n"); + cmd &= ~PCI_COMMAND_IO; + cmd &= ~PCI_COMMAND_MEMORY; + pci_write_config_word(dev, PCI_COMMAND, cmd); + } + } + switch (dev->hdr_type) { /* header type */ case PCI_HEADER_TYPE_NORMAL: /* standard header */ if (class == PCI_CLASS_BRIDGE_PCI) --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -327,6 +327,7 @@ struct pci_dev { unsigned int is_hotplug_bridge:1; unsigned int __aer_firmware_first_valid:1; unsigned int __aer_firmware_first:1; + unsigned int non_compliant_bars:1; /* broken BARs; ignore them */ pci_dev_flags_t dev_flags; atomic_t enable_cnt; /* pci_enable_device has been called */