diff options
| author | Zhi-Jun Robin Fu <Zhijun.Fu@Sun.COM> | 2010-04-22 15:10:46 +0800 |
|---|---|---|
| committer | Zhi-Jun Robin Fu <Zhijun.Fu@Sun.COM> | 2010-04-22 15:10:46 +0800 |
| commit | 8d7fafffed373567f52062b634e61fd50858b8d9 (patch) | |
| tree | cb77823b1668cdc1d8277f0e4ffa5858f2a721fc | |
| parent | c6698ca1e2450f37cc5ee4cdded3e5472088ba41 (diff) | |
| download | illumos-joyent-8d7fafffed373567f52062b634e61fd50858b8d9.tar.gz | |
6910668 the code for 6831378 should do better error handling
| -rw-r--r-- | usr/src/cmd/pcitool/pcitool.c | 13 | ||||
| -rw-r--r-- | usr/src/uts/i86pc/Makefile.files | 4 | ||||
| -rw-r--r-- | usr/src/uts/i86pc/io/pci/pci_tools.c | 18 | ||||
| -rw-r--r-- | usr/src/uts/i86pc/os/pci_cfgacc_x86.c | 117 | ||||
| -rw-r--r-- | usr/src/uts/i86pc/os/pci_cfgspace.c | 16 | ||||
| -rw-r--r-- | usr/src/uts/i86pc/os/pci_mech1_amd.c | 185 | ||||
| -rw-r--r-- | usr/src/uts/i86pc/sys/pci_cfgspace_impl.h | 17 | ||||
| -rw-r--r-- | usr/src/uts/sun4u/io/pciex/pci_cfgacc_4u.c | 33 | ||||
| -rw-r--r-- | usr/src/uts/sun4v/io/pciex/pci_cfgacc_4v.c | 35 |
9 files changed, 338 insertions, 100 deletions
diff --git a/usr/src/cmd/pcitool/pcitool.c b/usr/src/cmd/pcitool/pcitool.c index 4f575eae08..951980ef4a 100644 --- a/usr/src/cmd/pcitool/pcitool.c +++ b/usr/src/cmd/pcitool/pcitool.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. */ /* This file is the main module for the pcitool. */ @@ -476,7 +475,7 @@ supports_ari(int fd, uint8_t bus_no) cfg_prg.func_no = func_no; cfg_prg.barnum = 0; cfg_prg.user_version = PCITOOL_VERSION; - cfg_prg.offset = PCI_CONF_COMM; + cfg_prg.offset = 0; cfg_prg.acc_attr = PCITOOL_ACC_ATTR_SIZE_4 + PCITOOL_ACC_ATTR_ENDN_LTL; if (ioctl(fd, PCITOOL_DEVICE_GET_REG, &cfg_prg) != SUCCESS) { @@ -484,7 +483,15 @@ supports_ari(int fd, uint8_t bus_no) } data = (uint32_t)cfg_prg.data; + if (data == (uint32_t)(-1)) + return (FAILURE); + cfg_prg.offset = PCI_CONF_COMM; + if (ioctl(fd, PCITOOL_DEVICE_GET_REG, &cfg_prg) != SUCCESS) { + return (FAILURE); + } + + data = (uint32_t)cfg_prg.data; if (!((data >> 16) & PCI_STAT_CAP)) return (FAILURE); diff --git a/usr/src/uts/i86pc/Makefile.files b/usr/src/uts/i86pc/Makefile.files index eeaaa379ab..8156574ad1 100644 --- a/usr/src/uts/i86pc/Makefile.files +++ b/usr/src/uts/i86pc/Makefile.files @@ -20,8 +20,7 @@ # # -# Copyright 2010 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. # # This Makefile defines file modules in the directory uts/i86pc # and its children. These are the source files which are i86pc @@ -101,6 +100,7 @@ CORE_OBJS += \ pci_cfgacc_x86.o \ pci_cfgspace.o \ pci_mech1.o \ + pci_mech1_amd.o \ pci_mech2.o \ pci_neptune.o \ pci_orion.o \ diff --git a/usr/src/uts/i86pc/io/pci/pci_tools.c b/usr/src/uts/i86pc/io/pci/pci_tools.c index 2dea113932..1100e63d0b 100644 --- a/usr/src/uts/i86pc/io/pci/pci_tools.c +++ b/usr/src/uts/i86pc/io/pci/pci_tools.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <sys/types.h> @@ -557,7 +556,20 @@ pcitool_cfg_access(pcitool_reg_t *prg, boolean_t write_flag, pci_cfgacc_acc(&req); } else { pci_cfgacc_acc(&req); - local_data = VAL64(&req); + switch (size) { + case 1: + local_data = VAL8(&req); + break; + case 2: + local_data = VAL16(&req); + break; + case 4: + local_data = VAL32(&req); + break; + case 8: + local_data = VAL64(&req); + break; + } if (big_endian) { prg->data = pcitool_swap_endian(local_data, size); diff --git a/usr/src/uts/i86pc/os/pci_cfgacc_x86.c b/usr/src/uts/i86pc/os/pci_cfgacc_x86.c index 184e41d6ed..f643354245 100644 --- a/usr/src/uts/i86pc/os/pci_cfgacc_x86.c +++ b/usr/src/uts/i86pc/os/pci_cfgacc_x86.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <sys/systm.h> @@ -32,6 +31,7 @@ #include <sys/sysmacros.h> #include <sys/x86_archext.h> #include <sys/pci.h> +#include <sys/cmn_err.h> #include <vm/hat_i86.h> #include <vm/seg_kmem.h> #include <vm/kboot_mmu.h> @@ -73,22 +73,20 @@ pci_cfgacc_map(paddr_t phys_addr) * Note: no need to unmap first, clear_boot_mappings() will * do that for us. */ - if (pci_cfgacc_virt_base < (caddr_t)kernelbase) { - if ((pci_cfgacc_virt_base = vmem_alloc(heap_arena, - MMU_PAGESIZE, VM_NOSLEEP)) == NULL) - return (NULL); - } + if (pci_cfgacc_virt_base < (caddr_t)kernelbase) + pci_cfgacc_virt_base = vmem_alloc(heap_arena, + MMU_PAGESIZE, VM_SLEEP); + hat_devload(kas.a_hat, pci_cfgacc_virt_base, MMU_PAGESIZE, pfn, PROT_READ | PROT_WRITE | HAT_STRICTORDER, HAT_LOAD_LOCK); } else { paddr_t pa_base = P2ALIGN(phys_addr, MMU_PAGESIZE); - if (pci_cfgacc_virt_base == NULL) { - if ((pci_cfgacc_virt_base = (caddr_t) - alloc_vaddr(MMU_PAGESIZE, MMU_PAGESIZE)) == NULL) - return (NULL); - } + if (pci_cfgacc_virt_base == NULL) + pci_cfgacc_virt_base = + (caddr_t)alloc_vaddr(MMU_PAGESIZE, MMU_PAGESIZE); + kbm_map((uintptr_t)pci_cfgacc_virt_base, pa_base, 0, 0); } @@ -106,18 +104,14 @@ pci_cfgacc_unmap() static void pci_cfgacc_io(pci_cfgacc_req_t *req) { - uint8_t bus, dev, func, ioacc_offset; - - if (req->offset > 0xff) { - if (!req->write) - VAL64(req) = (uint64_t)-1; - return; - } + uint8_t bus, dev, func; + uint16_t ioacc_offset; /* 4K config access with IO ECS */ bus = PCI_BDF_BUS(req->bdf); dev = PCI_BDF_DEV(req->bdf); func = PCI_BDF_FUNC(req->bdf); ioacc_offset = req->offset; + switch (req->size) { case 1: if (req->write) @@ -143,26 +137,33 @@ pci_cfgacc_io(pci_cfgacc_req_t *req) VAL32(req) = (*pci_getl_func)(bus, dev, func, ioacc_offset); break; - default: - return; + case 8: + if (req->write) { + (*pci_putl_func)(bus, dev, func, + ioacc_offset, VAL64(req) & 0xffffffff); + (*pci_putl_func)(bus, dev, func, + ioacc_offset + 4, VAL64(req) >> 32); + } else { + VAL64(req) = (*pci_getl_func)(bus, dev, func, + ioacc_offset); + VAL64(req) |= (uint64_t)(*pci_getl_func)(bus, dev, func, + ioacc_offset + 4) << 32; + } + break; } } -static int +static void pci_cfgacc_mmio(pci_cfgacc_req_t *req) { caddr_t vaddr; paddr_t paddr; - int rval = DDI_SUCCESS; paddr = (paddr_t)req->bdf << 12; paddr += mcfg_mem_base + req->offset; mutex_enter(&pcicfg_mmio_mutex); - if ((vaddr = pci_cfgacc_map(paddr)) == NULL) { - mutex_exit(&pcicfg_mmio_mutex); - return (DDI_FAILURE); - } + vaddr = pci_cfgacc_map(paddr); switch (req->size) { case 1: @@ -189,56 +190,56 @@ pci_cfgacc_mmio(pci_cfgacc_req_t *req) else VAL64(req) = *((uint64_t *)vaddr); break; - default: - rval = DDI_FAILURE; } pci_cfgacc_unmap(); mutex_exit(&pcicfg_mmio_mutex); - - return (rval); } static boolean_t -pci_cfgacc_valid(pci_cfgacc_req_t *req) +pci_cfgacc_valid(pci_cfgacc_req_t *req, uint16_t maxoffset) { - return (IS_P2ALIGNED(req->offset, req->size) && - (req->offset < PCIE_CFG_SPACE_SIZE)); + int sz = req->size; + + if (IS_P2ALIGNED(req->offset, sz) && + (req->offset < maxoffset) && + ((sz & 0xf) && ISP2(sz))) + return (B_TRUE); + + cmn_err(CE_WARN, "illegal PCI request: offset = %x, size = %d", + req->offset, sz); + return (B_FALSE); } void -pci_cfgacc_acc(pci_cfgacc_req_t *req) +pci_cfgacc_check_io(pci_cfgacc_req_t *req) { uint8_t bus; - if (!req->write) - VAL64(req) = 0; - - if (!pci_cfgacc_valid(req)) { - if (!req->write) - VAL64(req) = (uint64_t)-1; - return; - } - bus = PCI_BDF_BUS(req->bdf); - if (pci_cfgacc_force_io || (mcfg_mem_base == NULL) || - (bus < mcfg_bus_start) || (bus > mcfg_bus_end)) - goto ioacc; - if (req->ioacc) - goto ioacc; + if (pci_cfgacc_force_io || (mcfg_mem_base == NULL) || + (bus < mcfg_bus_start) || (bus > mcfg_bus_end) || + pci_cfgacc_find_workaround(req->bdf)) + req->ioacc = B_TRUE; +} - /* check if workaround is needed */ - if (pci_cfgacc_find_workaround(req->bdf)) - goto ioacc; +void +pci_cfgacc_acc(pci_cfgacc_req_t *req) +{ + extern uint_t pci_iocfg_max_offset; - if (pci_cfgacc_mmio(req) != DDI_SUCCESS) - goto ioacc; + if (!req->write) + VAL64(req) = (uint64_t)-1; - return; + pci_cfgacc_check_io(req); -ioacc: - pci_cfgacc_io(req); - req->ioacc = B_TRUE; + if (req->ioacc) { + if (pci_cfgacc_valid(req, pci_iocfg_max_offset)) + pci_cfgacc_io(req); + } else { + if (pci_cfgacc_valid(req, PCIE_CFG_SPACE_SIZE)) + pci_cfgacc_mmio(req); + } } typedef struct cfgacc_bus_range { diff --git a/usr/src/uts/i86pc/os/pci_cfgspace.c b/usr/src/uts/i86pc/os/pci_cfgspace.c index cf93bfeff0..abfec8854b 100644 --- a/usr/src/uts/i86pc/os/pci_cfgspace.c +++ b/usr/src/uts/i86pc/os/pci_cfgspace.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -64,6 +63,11 @@ uint8_t mcfg_bus_start = 0; uint8_t mcfg_bus_end = 0xff; /* + * Maximum offset in config space when not using MMIO + */ +uint_t pci_iocfg_max_offset = 0xff; + +/* * These function pointers lead to the actual implementation routines * for configuration space access. Normally they lead to either the * pci_mech1_* or pci_mech2_* routines, but they can also lead to @@ -173,6 +177,14 @@ pci_check(void) pci_putb_func = pci_orion_putb; pci_putw_func = pci_orion_putw; pci_putl_func = pci_orion_putl; + } else if (pci_check_amd_ioecs()) { + pci_getb_func = pci_mech1_amd_getb; + pci_getw_func = pci_mech1_amd_getw; + pci_getl_func = pci_mech1_amd_getl; + pci_putb_func = pci_mech1_amd_putb; + pci_putw_func = pci_mech1_amd_putw; + pci_putl_func = pci_mech1_amd_putl; + pci_iocfg_max_offset = 0xfff; } else { pci_getb_func = pci_mech1_getb; pci_getw_func = pci_mech1_getw; diff --git a/usr/src/uts/i86pc/os/pci_mech1_amd.c b/usr/src/uts/i86pc/os/pci_mech1_amd.c new file mode 100644 index 0000000000..d45408731b --- /dev/null +++ b/usr/src/uts/i86pc/os/pci_mech1_amd.c @@ -0,0 +1,185 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2010 Advanced Micro Devices, Inc. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + */ + +/* + * PCI Mechanism 1 low-level routines with ECS support for AMD family >= 0x10 + */ + +#include <sys/controlregs.h> +#include <sys/cpuvar.h> +#include <sys/types.h> +#include <sys/pci.h> +#include <sys/pci_impl.h> +#include <sys/sunddi.h> +#include <sys/pci_cfgspace_impl.h> +#include <sys/x86_archext.h> + +boolean_t +pci_check_amd_ioecs(void) +{ + struct cpuid_regs cp; + int family; + + if ((x86_feature & X86_CPUID) == 0) + return (B_FALSE); + + /* + * Get the CPU vendor string from CPUID. + * This PCI mechanism only applies to AMD CPUs. + */ + cp.cp_eax = 0; + (void) __cpuid_insn(&cp); + + if ((cp.cp_ebx != 0x68747541) || /* Auth */ + (cp.cp_edx != 0x69746e65) || /* enti */ + (cp.cp_ecx != 0x444d4163)) /* cAMD */ + return (B_FALSE); + + /* + * Get the CPU family from CPUID. + * This PCI mechanism is only available on family 0x10 or higher. + */ + cp.cp_eax = 1; + (void) __cpuid_insn(&cp); + family = ((cp.cp_eax >> 8) & 0xf) + ((cp.cp_eax >> 20) & 0xff); + + if (family < 0x10) + return (B_FALSE); + + /* + * Set the EnableCf8ExtCfg bit in the Northbridge Configuration Register + * to enable accessing PCI ECS using in/out instructions. + */ + wrmsr(MSR_AMD_NB_CFG, rdmsr(MSR_AMD_NB_CFG) | AMD_GH_NB_CFG_EN_ECS); + return (B_TRUE); +} + +/* + * Macro to setup PCI Extended Configuration Space (ECS) address to give to + * "in/out" instructions + */ +#define PCI_CADDR1_ECS(b, d, f, r) \ + (PCI_CADDR1((b), (d), (f), (r)) | ((((r) >> 8) & 0xf) << 24)) + +/* + * Per PCI 2.1 section 3.7.4.1 and PCI-PCI Bridge Architecture 1.0 section + * 5.3.1.2: dev=31 func=7 reg=0 means a special cycle. We don't want to + * trigger that by accident, so we pretend that dev 31, func 7 doesn't + * exist. If we ever want special cycle support, we'll add explicit + * special cycle support. + */ + +uint8_t +pci_mech1_amd_getb(int bus, int device, int function, int reg) +{ + uint8_t val; + + if (device == PCI_MECH1_SPEC_CYCLE_DEV && + function == PCI_MECH1_SPEC_CYCLE_FUNC) { + return (0xff); + } + + mutex_enter(&pcicfg_mutex); + outl(PCI_CONFADD, PCI_CADDR1_ECS(bus, device, function, reg)); + val = inb(PCI_CONFDATA | (reg & 0x3)); + mutex_exit(&pcicfg_mutex); + return (val); +} + +uint16_t +pci_mech1_amd_getw(int bus, int device, int function, int reg) +{ + uint16_t val; + + if (device == PCI_MECH1_SPEC_CYCLE_DEV && + function == PCI_MECH1_SPEC_CYCLE_FUNC) { + return (0xffff); + } + + mutex_enter(&pcicfg_mutex); + outl(PCI_CONFADD, PCI_CADDR1_ECS(bus, device, function, reg)); + val = inw(PCI_CONFDATA | (reg & 0x2)); + mutex_exit(&pcicfg_mutex); + return (val); +} + +uint32_t +pci_mech1_amd_getl(int bus, int device, int function, int reg) +{ + uint32_t val; + + if (device == PCI_MECH1_SPEC_CYCLE_DEV && + function == PCI_MECH1_SPEC_CYCLE_FUNC) { + return (0xffffffffu); + } + + mutex_enter(&pcicfg_mutex); + outl(PCI_CONFADD, PCI_CADDR1_ECS(bus, device, function, reg)); + val = inl(PCI_CONFDATA); + mutex_exit(&pcicfg_mutex); + return (val); +} + +void +pci_mech1_amd_putb(int bus, int device, int function, int reg, uint8_t val) +{ + if (device == PCI_MECH1_SPEC_CYCLE_DEV && + function == PCI_MECH1_SPEC_CYCLE_FUNC) { + return; + } + + mutex_enter(&pcicfg_mutex); + outl(PCI_CONFADD, PCI_CADDR1_ECS(bus, device, function, reg)); + outb(PCI_CONFDATA | (reg & 0x3), val); + mutex_exit(&pcicfg_mutex); +} + +void +pci_mech1_amd_putw(int bus, int device, int function, int reg, uint16_t val) +{ + if (device == PCI_MECH1_SPEC_CYCLE_DEV && + function == PCI_MECH1_SPEC_CYCLE_FUNC) { + return; + } + + mutex_enter(&pcicfg_mutex); + outl(PCI_CONFADD, PCI_CADDR1_ECS(bus, device, function, reg)); + outw(PCI_CONFDATA | (reg & 0x2), val); + mutex_exit(&pcicfg_mutex); +} + +void +pci_mech1_amd_putl(int bus, int device, int function, int reg, uint32_t val) +{ + if (device == PCI_MECH1_SPEC_CYCLE_DEV && + function == PCI_MECH1_SPEC_CYCLE_FUNC) { + return; + } + + mutex_enter(&pcicfg_mutex); + outl(PCI_CONFADD, PCI_CADDR1_ECS(bus, device, function, reg)); + outl(PCI_CONFDATA, val); + mutex_exit(&pcicfg_mutex); +} diff --git a/usr/src/uts/i86pc/sys/pci_cfgspace_impl.h b/usr/src/uts/i86pc/sys/pci_cfgspace_impl.h index 76cc353f1c..3eaf621efd 100644 --- a/usr/src/uts/i86pc/sys/pci_cfgspace_impl.h +++ b/usr/src/uts/i86pc/sys/pci_cfgspace_impl.h @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _SYS_PCI_CFGSPACE_IMPL_H @@ -47,6 +46,20 @@ extern void pci_mech1_putw(int bus, int dev, int func, int reg, uint16_t val); extern void pci_mech1_putl(int bus, int dev, int func, int reg, uint32_t val); /* + * AMD family >= 0x10 Mechanism 1 routines with ECS support + */ +extern boolean_t pci_check_amd_ioecs(void); +extern uint8_t pci_mech1_amd_getb(int bus, int dev, int func, int reg); +extern uint16_t pci_mech1_amd_getw(int bus, int dev, int func, int reg); +extern uint32_t pci_mech1_amd_getl(int bus, int dev, int func, int reg); +extern void pci_mech1_amd_putb(int bus, int dev, int func, int reg, + uint8_t val); +extern void pci_mech1_amd_putw(int bus, int dev, int func, int reg, + uint16_t val); +extern void pci_mech1_amd_putl(int bus, int dev, int func, int reg, + uint32_t val); + +/* * Generic Mechanism 2 routines */ extern uint8_t pci_mech2_getb(int bus, int dev, int func, int reg); diff --git a/usr/src/uts/sun4u/io/pciex/pci_cfgacc_4u.c b/usr/src/uts/sun4u/io/pciex/pci_cfgacc_4u.c index 65296bec24..9d12a74ce6 100644 --- a/usr/src/uts/sun4u/io/pciex/pci_cfgacc_4u.c +++ b/usr/src/uts/sun4u/io/pciex/pci_cfgacc_4u.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <sys/sunddi.h> @@ -43,11 +42,16 @@ static boolean_t pci_cfgacc_valid(pci_cfgacc_req_t *req) { - /* do not support 64 bit pci config space access */ - return (IS_P2ALIGNED(req->offset, req->size) && + int sz = req->size; + + if (IS_P2ALIGNED(req->offset, sz) && (req->offset < PCIE_CFG_SPACE_SIZE) && - ((req->size == 1) || (req->size == 2) || - (req->size == 4) || (req->size == 8))); + ((sz & 0xf) && ISP2(sz))) + return (B_TRUE); + + cmn_err(CE_WARN, "illegal PCI request: offset = %x, size = %d", + req->offset, sz); + return (B_FALSE); } /* @@ -60,8 +64,8 @@ pci_cfgacc_get(dev_info_t *dip, uint16_t bdf, uint16_t offset, uint8_t size) uint64_t base_addr; uint64_t val; - if ((bus_p = PCIE_DIP2DOWNBUS(dip)) == NULL) - return ((uint64_t)-1); + bus_p = PCIE_DIP2DOWNBUS(dip); + ASSERT(bus_p != NULL); base_addr = bus_p->bus_cfgacc_base; base_addr += RC_BDF_TO_CFGADDR(bdf, offset); @@ -93,8 +97,8 @@ pci_cfgacc_set(dev_info_t *dip, uint16_t bdf, uint16_t offset, uint8_t size, pcie_bus_t *bus_p; uint64_t base_addr; - if ((bus_p = PCIE_DIP2DOWNBUS(dip)) == NULL) - return; + bus_p = PCIE_DIP2DOWNBUS(dip); + ASSERT(bus_p != NULL); base_addr = bus_p->bus_cfgacc_base; base_addr += RC_BDF_TO_CFGADDR(bdf, offset); @@ -122,12 +126,11 @@ pci_cfgacc_set(dev_info_t *dip, uint16_t bdf, uint16_t offset, uint8_t size, void pci_cfgacc_acc(pci_cfgacc_req_t *req) { - /* is request valid? */ - if (!pci_cfgacc_valid(req)) { - if (!req->write) - VAL64(req) = (uint64_t)-1; + if (!req->write) + VAL64(req) = (uint64_t)-1; + + if (!pci_cfgacc_valid(req)) return; - } if (req->write) { pci_cfgacc_set(req->rcdip, req->bdf, req->offset, diff --git a/usr/src/uts/sun4v/io/pciex/pci_cfgacc_4v.c b/usr/src/uts/sun4v/io/pciex/pci_cfgacc_4v.c index 653de54b4c..9818ac0ce6 100644 --- a/usr/src/uts/sun4v/io/pciex/pci_cfgacc_4v.c +++ b/usr/src/uts/sun4v/io/pciex/pci_cfgacc_4v.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -48,11 +47,16 @@ static boolean_t pci_cfgacc_valid(pci_cfgacc_req_t *req) { - /* do not support 64 bit pci config space access */ - return (IS_P2ALIGNED(req->offset, req->size) && + int sz = req->size; + + if (IS_P2ALIGNED(req->offset, sz) && (req->offset < PCIE_CFG_SPACE_SIZE) && - ((req->size == 1) || (req->size == 2) || - (req->size == 4) || (req->size == 8))); + ((sz & 0xf) && ISP2(sz))) + return (B_TRUE); + + cmn_err(CE_WARN, "illegal PCI request: offset = %x, size = %d", + req->offset, sz); + return (B_FALSE); } /* @@ -66,8 +70,8 @@ pci_cfgacc_get(dev_info_t *dip, uint16_t bdf, uint16_t offset, uint8_t size) uint64_t devaddr; uint64_t data = 0; - if ((bus_p = PCIE_DIP2DOWNBUS(dip)) == NULL) - return ((uint64_t)-1); + bus_p = PCIE_DIP2DOWNBUS(dip); + ASSERT(bus_p != NULL); devhdl = bus_p->bus_cfgacc_base; devaddr = ((uint64_t)bdf) << RC_RA_BDF_SHIFT; @@ -87,8 +91,8 @@ pci_cfgacc_set(dev_info_t *dip, uint16_t bdf, uint16_t offset, uint8_t size, uint64_t devaddr; pci_cfg_data_t wdata = { 0 }; - if ((bus_p = PCIE_DIP2DOWNBUS(dip)) == NULL) - return; + bus_p = PCIE_DIP2DOWNBUS(dip); + ASSERT(bus_p != NULL); devhdl = bus_p->bus_cfgacc_base; devaddr = ((uint64_t)bdf) << RC_RA_BDF_SHIFT; @@ -100,12 +104,11 @@ pci_cfgacc_set(dev_info_t *dip, uint16_t bdf, uint16_t offset, uint8_t size, void pci_cfgacc_acc(pci_cfgacc_req_t *req) { - /* is request valid? */ - if (!pci_cfgacc_valid(req)) { - if (!req->write) - VAL64(req) = (uint64_t)-1; + if (!req->write) + VAL64(req) = (uint64_t)-1; + + if (!pci_cfgacc_valid(req)) return; - } if (req->write) { pci_cfgacc_set(req->rcdip, req->bdf, req->offset, @@ -123,6 +126,8 @@ pci_cfgacc_acc(pci_cfgacc_req_t *req) case 4: VAL32(req) = (uint32_t)VAL64(req); break; + case 8: + /* fall through, no special handling needed */ default: break; } |
