Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.5-rc3 192 lines 5.8 kB view raw
1/* 2 * Copyright (C) 1995,2001 Compaq Computer Corporation 3 * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) 4 * Copyright (C) 2001 IBM Corp. 5 * Copyright (C) 2003-2004 Intel Corporation 6 * (c) Copyright 2009 Hewlett-Packard Development Company, L.P. 7 * 8 * All rights reserved. 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or (at 13 * your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, but 16 * WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 18 * NON INFRINGEMENT. See the GNU General Public License for more 19 * details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 24 */ 25 26#include <linux/pci.h> 27#include <linux/export.h> 28#include <linux/pci_hotplug.h> 29 30static struct hpp_type0 pci_default_type0 = { 31 .revision = 1, 32 .cache_line_size = 8, 33 .latency_timer = 0x40, 34 .enable_serr = 0, 35 .enable_perr = 0, 36}; 37 38static void program_hpp_type0(struct pci_dev *dev, struct hpp_type0 *hpp) 39{ 40 u16 pci_cmd, pci_bctl; 41 42 if (!hpp) { 43 /* 44 * Perhaps we *should* use default settings for PCIe, but 45 * pciehp didn't, so we won't either. 46 */ 47 if (pci_is_pcie(dev)) 48 return; 49 dev_info(&dev->dev, "using default PCI settings\n"); 50 hpp = &pci_default_type0; 51 } 52 53 if (hpp->revision > 1) { 54 dev_warn(&dev->dev, 55 "PCI settings rev %d not supported; using defaults\n", 56 hpp->revision); 57 hpp = &pci_default_type0; 58 } 59 60 pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp->cache_line_size); 61 pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp->latency_timer); 62 pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); 63 if (hpp->enable_serr) 64 pci_cmd |= PCI_COMMAND_SERR; 65 else 66 pci_cmd &= ~PCI_COMMAND_SERR; 67 if (hpp->enable_perr) 68 pci_cmd |= PCI_COMMAND_PARITY; 69 else 70 pci_cmd &= ~PCI_COMMAND_PARITY; 71 pci_write_config_word(dev, PCI_COMMAND, pci_cmd); 72 73 /* Program bridge control value */ 74 if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { 75 pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 76 hpp->latency_timer); 77 pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl); 78 if (hpp->enable_serr) 79 pci_bctl |= PCI_BRIDGE_CTL_SERR; 80 else 81 pci_bctl &= ~PCI_BRIDGE_CTL_SERR; 82 if (hpp->enable_perr) 83 pci_bctl |= PCI_BRIDGE_CTL_PARITY; 84 else 85 pci_bctl &= ~PCI_BRIDGE_CTL_PARITY; 86 pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl); 87 } 88} 89 90static void program_hpp_type1(struct pci_dev *dev, struct hpp_type1 *hpp) 91{ 92 if (hpp) 93 dev_warn(&dev->dev, "PCI-X settings not supported\n"); 94} 95 96static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp) 97{ 98 int pos; 99 u16 reg16; 100 u32 reg32; 101 102 if (!hpp) 103 return; 104 105 /* Find PCI Express capability */ 106 pos = pci_pcie_cap(dev); 107 if (!pos) 108 return; 109 110 if (hpp->revision > 1) { 111 dev_warn(&dev->dev, "PCIe settings rev %d not supported\n", 112 hpp->revision); 113 return; 114 } 115 116 /* Initialize Device Control Register */ 117 pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &reg16); 118 reg16 = (reg16 & hpp->pci_exp_devctl_and) | hpp->pci_exp_devctl_or; 119 pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, reg16); 120 121 /* Initialize Link Control Register */ 122 if (dev->subordinate) { 123 pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &reg16); 124 reg16 = (reg16 & hpp->pci_exp_lnkctl_and) 125 | hpp->pci_exp_lnkctl_or; 126 pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, reg16); 127 } 128 129 /* Find Advanced Error Reporting Enhanced Capability */ 130 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); 131 if (!pos) 132 return; 133 134 /* Initialize Uncorrectable Error Mask Register */ 135 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, &reg32); 136 reg32 = (reg32 & hpp->unc_err_mask_and) | hpp->unc_err_mask_or; 137 pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, reg32); 138 139 /* Initialize Uncorrectable Error Severity Register */ 140 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &reg32); 141 reg32 = (reg32 & hpp->unc_err_sever_and) | hpp->unc_err_sever_or; 142 pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, reg32); 143 144 /* Initialize Correctable Error Mask Register */ 145 pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &reg32); 146 reg32 = (reg32 & hpp->cor_err_mask_and) | hpp->cor_err_mask_or; 147 pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg32); 148 149 /* Initialize Advanced Error Capabilities and Control Register */ 150 pci_read_config_dword(dev, pos + PCI_ERR_CAP, &reg32); 151 reg32 = (reg32 & hpp->adv_err_cap_and) | hpp->adv_err_cap_or; 152 pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32); 153 154 /* 155 * FIXME: The following two registers are not supported yet. 156 * 157 * o Secondary Uncorrectable Error Severity Register 158 * o Secondary Uncorrectable Error Mask Register 159 */ 160} 161 162void pci_configure_slot(struct pci_dev *dev) 163{ 164 struct pci_dev *cdev; 165 struct hotplug_params hpp; 166 int ret; 167 168 if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL || 169 (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && 170 (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) 171 return; 172 173 if (dev->bus && dev->bus->self) 174 pcie_bus_configure_settings(dev->bus, 175 dev->bus->self->pcie_mpss); 176 177 memset(&hpp, 0, sizeof(hpp)); 178 ret = pci_get_hp_params(dev, &hpp); 179 if (ret) 180 dev_warn(&dev->dev, "no hotplug settings from platform\n"); 181 182 program_hpp_type2(dev, hpp.t2); 183 program_hpp_type1(dev, hpp.t1); 184 program_hpp_type0(dev, hpp.t0); 185 186 if (dev->subordinate) { 187 list_for_each_entry(cdev, &dev->subordinate->devices, 188 bus_list) 189 pci_configure_slot(cdev); 190 } 191} 192EXPORT_SYMBOL_GPL(pci_configure_slot);