From patchwork Sun Oct 11 22:16:44 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yinghai Lu X-Patchwork-Id: 53033 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n9BMMK3h020081 for ; Sun, 11 Oct 2009 22:22:20 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751266AbZJKWR6 (ORCPT ); Sun, 11 Oct 2009 18:17:58 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1751267AbZJKWR6 (ORCPT ); Sun, 11 Oct 2009 18:17:58 -0400 Received: from hera.kernel.org ([140.211.167.34]:33417 "EHLO hera.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751266AbZJKWR5 (ORCPT ); Sun, 11 Oct 2009 18:17:57 -0400 Received: from [192.168.101.9] (adsl-76-193-117-243.dsl.pltn13.sbcglobal.net [76.193.117.243]) (authenticated bits=0) by hera.kernel.org (8.14.2/8.13.8) with ESMTP id n9BMGvCe000407 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Sun, 11 Oct 2009 22:17:10 GMT Message-ID: <4AD2594C.70003@kernel.org> Date: Sun, 11 Oct 2009 15:16:44 -0700 From: Yinghai Lu User-Agent: Thunderbird 2.0.0.23 (X11/20090817) MIME-Version: 1.0 To: Jesse Barnes CC: Brad Spengler , "linux-kernel@vger.kernel.org" , "linux-pci@vger.kernel.org" , Ingo Molnar , "H. Peter Anvin" , Matthew Wilcox Subject: [RFC PATCH] ia64/pci: add ext pci config detection for SAL 3.2 less References: <20091011074531.GA12357@grsecurity.net> <4AD1AE0D.1030007@kernel.org> <4AD24766.7050205@kernel.org> In-Reply-To: <4AD24766.7050205@kernel.org> X-Virus-Scanned: ClamAV 0.93.3/9881/Sat Oct 10 09:21:35 2009 on hera.kernel.org X-Virus-Status: Clean Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index bf79155..12c6b70 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -44,7 +44,57 @@ #define PCI_SAL_EXT_ADDRESS(seg, bus, devfn, reg) \ (((u64) seg << 28) | (bus << 20) | (devfn << 12) | (reg)) -int raw_pci_read(unsigned int seg, unsigned int bus, unsigned int devfn, +struct pci_raw_ops { + int (*read)(unsigned int domain, unsigned int bus, unsigned int devfn, + int reg, int len, u32 *val); + int (*write)(unsigned int domain, unsigned int bus, unsigned int devfn, + int reg, int len, u32 val); +}; + +static int sal_pci_read(unsigned int seg, unsigned int bus, unsigned int devfn, + int reg, int len, u32 *value) +{ + u64 addr, data = 0; + int mode, result; + + if (!value || !seg || (bus > 255) || (devfn > 255) || (reg > 255)) + return -EINVAL; + + addr = PCI_SAL_ADDRESS(seg, bus, devfn, reg); + mode = 0; + + result = ia64_sal_pci_config_read(addr, mode, len, &data); + if (result != 0) + return -EINVAL; + + *value = (u32) data; + return 0; +} + +static int sal_pci_write(unsigned int seg, unsigned int bus, unsigned int devfn, + int reg, int len, u32 value) +{ + u64 addr; + int mode, result; + + if (!seg || (bus > 255) || (devfn > 255) || (reg > 255)) + return -EINVAL; + + addr = PCI_SAL_ADDRESS(seg, bus, devfn, reg); + mode = 0; + + result = ia64_sal_pci_config_write(addr, mode, len, value); + if (result != 0) + return -EINVAL; + return 0; +} + +static struct pci_raw_ops sal_pci_conf = { + .read = sal_pci_read, + .write = sal_pci_write, +}; + +static int sal_pci_ext_read(unsigned int seg, unsigned int bus, unsigned int devfn, int reg, int len, u32 *value) { u64 addr, data = 0; @@ -53,13 +103,9 @@ int raw_pci_read(unsigned int seg, unsigned int bus, unsigned int devfn, if (!value || (seg > 65535) || (bus > 255) || (devfn > 255) || (reg > 4095)) return -EINVAL; - if ((seg | reg) <= 255) { - addr = PCI_SAL_ADDRESS(seg, bus, devfn, reg); - mode = 0; - } else { - addr = PCI_SAL_EXT_ADDRESS(seg, bus, devfn, reg); - mode = 1; - } + addr = PCI_SAL_EXT_ADDRESS(seg, bus, devfn, reg); + mode = 1; + result = ia64_sal_pci_config_read(addr, mode, len, &data); if (result != 0) return -EINVAL; @@ -68,7 +114,7 @@ int raw_pci_read(unsigned int seg, unsigned int bus, unsigned int devfn, return 0; } -int raw_pci_write(unsigned int seg, unsigned int bus, unsigned int devfn, +static int sal_pci_ext_write(unsigned int seg, unsigned int bus, unsigned int devfn, int reg, int len, u32 value) { u64 addr; @@ -77,19 +123,51 @@ int raw_pci_write(unsigned int seg, unsigned int bus, unsigned int devfn, if ((seg > 65535) || (bus > 255) || (devfn > 255) || (reg > 4095)) return -EINVAL; - if ((seg | reg) <= 255) { - addr = PCI_SAL_ADDRESS(seg, bus, devfn, reg); - mode = 0; - } else { - addr = PCI_SAL_EXT_ADDRESS(seg, bus, devfn, reg); - mode = 1; - } + addr = PCI_SAL_EXT_ADDRESS(seg, bus, devfn, reg); + mode = 1; + result = ia64_sal_pci_config_write(addr, mode, len, value); if (result != 0) return -EINVAL; return 0; } +static struct pci_raw_ops sal_pci_ext_conf = { + .read = sal_pci_ext_read, + .write = sal_pci_ext_write, +}; + +static struct pci_raw_ops *raw_pci_ops = sal_pci_ops; +static struct pci_raw_ops *raw_pci_ext_opsi = NULL; + +static __init int pci_arch_init(void) +{ + if (sal_revision >= SAL_VERSION_CODE(3,2)) + raw_pci_ext_ops = sal_pci_ext_ops; +} + +arch_initcall(pci_arch_init); + +int raw_pci_read(unsigned int seg, unsigned int bus, unsigned int devfn, + int reg, int len, u32 *value) +{ + if (seg == 0 && reg < 256 && raw_pci_ops) + return raw_pci_ops->read(seg, bus, devfn, reg, len, val); + if (raw_pci_ext_ops) + return raw_pci_ext_ops->read(seg, bus, devfn, reg, len, val); + return -EINVAL; +} + +int raw_pci_write(unsigned int seg, unsigned int bus, unsigned int devfn, + int reg, int len, u32 value) +{ + if (seg == 0 && reg < 256 && raw_pci_ops) + return raw_pci_ops->write(seg, bus, devfn, reg, len, val); + if (raw_pci_ext_ops) + return raw_pci_ext_ops->write(seg, bus, devfn, reg, len, val); + return -EINVAL; +} + static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) {