From patchwork Thu Sep 20 14:16:03 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephan Schreiber X-Patchwork-Id: 1485231 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Original-To: patchwork-linux-pci@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork1.kernel.org (Postfix) with ESMTP id 9394F3FE65 for ; Thu, 20 Sep 2012 14:25:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755759Ab2ITOZA (ORCPT ); Thu, 20 Sep 2012 10:25:00 -0400 Received: from smtprelay03.ispgateway.de ([80.67.31.41]:56255 "EHLO smtprelay03.ispgateway.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755751Ab2ITOY4 (ORCPT ); Thu, 20 Sep 2012 10:24:56 -0400 X-Greylist: delayed 528 seconds by postgrey-1.27 at vger.kernel.org; Thu, 20 Sep 2012 10:24:54 EDT Received: from [80.67.16.117] (helo=webmailfront01.ispgateway.de) by smtprelay03.ispgateway.de with esmtpsa (TLSv1:AES256-SHA:256) (Exim 4.68) (envelope-from ) id 1TEhXv-0000ip-L2; Thu, 20 Sep 2012 16:16:03 +0200 Received: from g225026161.adsl.alicedsl.de (g225026161.adsl.alicedsl.de [92.225.26.161]) by webmail.df.eu (Horde Framework) with HTTP; Thu, 20 Sep 2012 16:16:03 +0200 Date: Thu, 20 Sep 2012 16:16:03 +0200 Message-ID: <20120920161603.Horde.aF7BBcL8999QWyUjk2AmsNA@webmail.df.eu> From: Stephan Schreiber To: Alan Cox Cc: linux-ia64@vger.kernel.org, linux-pci@vger.kernel.org, linux-ide@vger.kernel.org, linux-kernel@vger.kernel.org, 679545@bugs.debian.org, jrnieder@gmail.com Subject: [RFC/PATCH v2] ia64, SR870, EFI bug breaks ata_piix, uninitialized ICH4 IDE EXBAR mem resource References: <20120916183914.Horde._TGALdjz9kRQVgCy6ATxxJA@webmail.df.eu> <20120917115619.13d3a3cb@pyramind.ukuu.org.uk> In-Reply-To: <20120917115619.13d3a3cb@pyramind.ukuu.org.uk> User-Agent: Internet Messaging Program (IMP) H4 (5.0.19) MIME-Version: 1.0 Content-Disposition: inline X-Df-Sender: aW5mb0Bmcy1kcml2ZXIub3Jn Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org description of the symptoms which you have already read on the initial RFC/PATCH======> Kernel 3.2.23 with Debian patches (Debian Wheezy, testing) Debian bug#679545 (http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=679545) Machine: Dell PowerEdge 3250 (equivalent with Intel SR870BH2) Processor: 2x Itanium Madison 1.5GHz 6M Memory: 4GB Intel ICH4 (82801DB), IDE host adapter. The ata_piix module fails to initialize. A snippet from dmesg: [ 0.000000] Initializing cgroup subsys cpuset [ 0.000000] Initializing cgroup subsys cpu [ 0.000000] Linux version 3.2.0-3-mckinley (Debian 3.2.23-1) (debian-kernel@lists.debian.org) (gcc version 4.6.3 (Debian 4.6.3-8) ) #1 SMP Mon Jul 23 09:01:02 UTC 2012 ... [ 0.065516] pci 0000:00:1f.1: [8086:24cb] type 0 class 0x000101 [ 0.065530] pci 0000:00:1f.1: reg 10: [io 0x0000-0x0007] [ 0.065541] pci 0000:00:1f.1: reg 14: [io 0x0000-0x0003] [ 0.065552] pci 0000:00:1f.1: reg 18: [io 0x0000-0x0007] [ 0.065563] pci 0000:00:1f.1: reg 1c: [io 0x0000-0x0003] [ 0.065574] pci 0000:00:1f.1: reg 20: [io 0x1000-0x100f] [ 0.065585] pci 0000:00:1f.1: reg 24: [mem 0x00000000-0x000003ff] ... [ 1.640965] libata version 3.00 loaded. [ 1.641656] ata_piix 0000:00:1f.1: version 2.13 [ 1.641671] ata_piix 0000:00:1f.1: device not available (can't reserve [mem 0x00000000-0x000003ff]) [ 1.641747] ata_piix: probe of 0000:00:1f.1 failed with error -22 ... lspci -vvxxx reports: 00:1f.1 IDE interface: Intel Corporation 82801DB (ICH4) IDE Controller (rev 02) (prog-if 8a [Master SecP PriP]) Subsystem: Intel Corporation Device 3404 Control: I/O+ Mem- BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx- Status: Cap- 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- SERR- My only disagreement here would be putting it in the ia64 paths. If > someone does the same for x86-32 (and this is EFI so it'll presumbly > smell the same on all platforms) then we'll want the same. > > Better I think to generically catch the 0/0 case. > > Alan Here is a new patch. It extends some existing code in pci_setup_device() which maintains some hard-coded io regions on ide controllers in legacy mode. The idea is hiding an uninitialized EXBAR just as on the initial patch. The patch is defensive; it does nothing if - the controller isn't in legacy mode, - BAR5 (EXBAR) isn't a memory resource, or - BAR5 is already initialized. The patch is generic because it works on both x86-32 and ia64 and also for other ICH4 variants than my rare 82801DB_11 ICH4. Even the added 'if' statement of this patch is also executed on IDE controllers of other vendors than Intel or on other Intel ICHs, I believe that it won't break anything. Stephan { struct pci_dev *pci_dev; pci_dev = to_pci_dev(dev); pci_release_capabilities(pci_dev); Signed-off-by: Stephan Schreiber --- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html --- linux-3.2.23/drivers/pci/probe.c.orig 2012-07-12 05:32:21.000000000 +0200 +++ linux-3.2.23/drivers/pci/probe.c 2012-09-19 20:52:24.000000000 +0200 @@ -898,146 +898,158 @@ int pci_setup_device(struct pci_dev *dev { u32 class; u8 hdr_type; struct pci_slot *slot; int pos = 0; if (pci_read_config_byte(dev, PCI_HEADER_TYPE, &hdr_type)) return -EIO; dev->sysdata = dev->bus->sysdata; dev->dev.parent = dev->bus->bridge; dev->dev.bus = &pci_bus_type; dev->hdr_type = hdr_type & 0x7f; dev->multifunction = !!(hdr_type & 0x80); dev->error_state = pci_channel_io_normal; set_pcie_port_type(dev); list_for_each_entry(slot, &dev->bus->slots, list) if (PCI_SLOT(dev->devfn) == slot->number) dev->slot = slot; /* Assume 32-bit PCI; let 64-bit PCI cards (which are far rarer) set this higher, assuming the system even supports it. */ dev->dma_mask = 0xffffffff; dev_set_name(&dev->dev, "%04x:%02x:%02x.%d", pci_domain_nr(dev->bus), dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); pci_read_config_dword(dev, PCI_CLASS_REVISION, &class); dev->revision = class & 0xff; class >>= 8; /* upper 3 bytes */ dev->class = class; class >>= 8; dev_printk(KERN_DEBUG, &dev->dev, "[%04x:%04x] type %d class %#08x\n", dev->vendor, dev->device, dev->hdr_type, class); /* need to have dev->class ready */ dev->cfg_size = pci_cfg_space_size(dev); /* "Unknown power state" */ dev->current_state = PCI_UNKNOWN; /* Early fixups, before probing the BARs */ pci_fixup_device(pci_fixup_early, dev); /* device class may be changed after fixup */ class = dev->class >> 8; switch (dev->hdr_type) { /* header type */ case PCI_HEADER_TYPE_NORMAL: /* standard header */ if (class == PCI_CLASS_BRIDGE_PCI) goto bad; pci_read_irq(dev); pci_read_bases(dev, 6, PCI_ROM_ADDRESS); pci_read_config_word(dev, PCI_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor); pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &dev->subsystem_device); /* * Do the ugly legacy mode stuff here rather than broken chip * quirk code. Legacy mode ATA controllers have fixed * addresses. These are not always echoed in BAR0-3, and * BAR0-3 in a few cases contain junk! + * BAR5 is a memory resource on Intel ICH4 which isn't + * functional at all. Some BIOS or EFI don't initialize + * it and would break ata_piix. If the controller is in + * legacy mode and BAR5 is an uninitialized memory + * resource, hide it. */ if (class == PCI_CLASS_STORAGE_IDE) { u8 progif; pci_read_config_byte(dev, PCI_CLASS_PROG, &progif); if ((progif & 1) == 0) { dev->resource[0].start = 0x1F0; dev->resource[0].end = 0x1F7; dev->resource[0].flags = LEGACY_IO_RESOURCE; dev->resource[1].start = 0x3F6; dev->resource[1].end = 0x3F6; dev->resource[1].flags = LEGACY_IO_RESOURCE; } if ((progif & 4) == 0) { dev->resource[2].start = 0x170; dev->resource[2].end = 0x177; dev->resource[2].flags = LEGACY_IO_RESOURCE; dev->resource[3].start = 0x376; dev->resource[3].end = 0x376; dev->resource[3].flags = LEGACY_IO_RESOURCE; } + if ((progif & 5) == 0 + && (dev->resource[5].flags & IORESOURCE_MEM) + && dev->resource[5].start == 0 + && dev->resource[5].end != 0) { + dev->resource[5].flags = 0; + dev->resource[5].end = 0; + } } break; case PCI_HEADER_TYPE_BRIDGE: /* bridge header */ if (class != PCI_CLASS_BRIDGE_PCI) goto bad; /* The PCI-to-PCI bridge spec requires that subtractive decoding (i.e. transparent) bridge must have programming interface code of 0x01. */ pci_read_irq(dev); dev->transparent = ((dev->class & 0xff) == 1); pci_read_bases(dev, 2, PCI_ROM_ADDRESS1); set_pcie_hotplug_bridge(dev); pos = pci_find_capability(dev, PCI_CAP_ID_SSVID); if (pos) { pci_read_config_word(dev, pos + PCI_SSVID_VENDOR_ID, &dev->subsystem_vendor); pci_read_config_word(dev, pos + PCI_SSVID_DEVICE_ID, &dev->subsystem_device); } break; case PCI_HEADER_TYPE_CARDBUS: /* CardBus bridge header */ if (class != PCI_CLASS_BRIDGE_CARDBUS) goto bad; pci_read_irq(dev); pci_read_bases(dev, 1, 0); pci_read_config_word(dev, PCI_CB_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor); pci_read_config_word(dev, PCI_CB_SUBSYSTEM_ID, &dev->subsystem_device); break; default: /* unknown header */ dev_err(&dev->dev, "unknown header type %02x, " "ignoring device\n", dev->hdr_type); return -EIO; bad: dev_err(&dev->dev, "ignoring class %02x (doesn't match header " "type %02x)\n", class, dev->hdr_type); dev->class = PCI_CLASS_NOT_DEFINED; } /* We found a fine healthy device, go go go... */ return 0; } static void pci_release_capabilities(struct pci_dev *dev) { pci_vpd_release(dev); pci_iov_release(dev); } /** * pci_release_dev - free a pci device structure when all users of it are finished. * @dev: device that's been disconnected * * Will be called only by the device core when all users of this pci device are * done. */ static void pci_release_dev(struct device *dev)