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.17-rc4 180 lines 5.4 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 u32 reg32; 100 101 if (!hpp) 102 return; 103 104 if (hpp->revision > 1) { 105 dev_warn(&dev->dev, "PCIe settings rev %d not supported\n", 106 hpp->revision); 107 return; 108 } 109 110 /* Initialize Device Control Register */ 111 pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL, 112 ~hpp->pci_exp_devctl_and, hpp->pci_exp_devctl_or); 113 114 /* Initialize Link Control Register */ 115 if (dev->subordinate) 116 pcie_capability_clear_and_set_word(dev, PCI_EXP_LNKCTL, 117 ~hpp->pci_exp_lnkctl_and, hpp->pci_exp_lnkctl_or); 118 119 /* Find Advanced Error Reporting Enhanced Capability */ 120 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); 121 if (!pos) 122 return; 123 124 /* Initialize Uncorrectable Error Mask Register */ 125 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, &reg32); 126 reg32 = (reg32 & hpp->unc_err_mask_and) | hpp->unc_err_mask_or; 127 pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, reg32); 128 129 /* Initialize Uncorrectable Error Severity Register */ 130 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &reg32); 131 reg32 = (reg32 & hpp->unc_err_sever_and) | hpp->unc_err_sever_or; 132 pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, reg32); 133 134 /* Initialize Correctable Error Mask Register */ 135 pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &reg32); 136 reg32 = (reg32 & hpp->cor_err_mask_and) | hpp->cor_err_mask_or; 137 pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg32); 138 139 /* Initialize Advanced Error Capabilities and Control Register */ 140 pci_read_config_dword(dev, pos + PCI_ERR_CAP, &reg32); 141 reg32 = (reg32 & hpp->adv_err_cap_and) | hpp->adv_err_cap_or; 142 pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32); 143 144 /* 145 * FIXME: The following two registers are not supported yet. 146 * 147 * o Secondary Uncorrectable Error Severity Register 148 * o Secondary Uncorrectable Error Mask Register 149 */ 150} 151 152void pci_configure_slot(struct pci_dev *dev) 153{ 154 struct pci_dev *cdev; 155 struct hotplug_params hpp; 156 int ret; 157 158 if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL || 159 (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && 160 (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) 161 return; 162 163 pcie_bus_configure_settings(dev->bus); 164 165 memset(&hpp, 0, sizeof(hpp)); 166 ret = pci_get_hp_params(dev, &hpp); 167 if (ret) 168 dev_warn(&dev->dev, "no hotplug settings from platform\n"); 169 170 program_hpp_type2(dev, hpp.t2); 171 program_hpp_type1(dev, hpp.t1); 172 program_hpp_type0(dev, hpp.t0); 173 174 if (dev->subordinate) { 175 list_for_each_entry(cdev, &dev->subordinate->devices, 176 bus_list) 177 pci_configure_slot(cdev); 178 } 179} 180EXPORT_SYMBOL_GPL(pci_configure_slot);