1 /* 2 * PCI Express Hot Plug Controller Driver 3 * 4 * Copyright (C) 1995,2001 Compaq Computer Corporation 5 * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) 6 * Copyright (C) 2001 IBM Corp. 7 * Copyright (C) 2003-2004 Intel Corporation 8 * 9 * All rights reserved. 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or (at 14 * your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, but 17 * WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 19 * NON INFRINGEMENT. See the GNU General Public License for more 20 * details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, write to the Free Software 24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 25 * 26 * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com> 27 * 28 */ 29 30 #include <linux/module.h> 31 #include <linux/kernel.h> 32 #include <linux/types.h> 33 #include <linux/pci.h> 34 #include "../pci.h" 35 #include "pciehp.h" 36 37 static void program_hpp_type0(struct pci_dev *dev, struct hpp_type0 *hpp) 38 { 39 u16 pci_cmd, pci_bctl; 40 41 if (hpp->revision > 1) { 42 warn("Rev.%d type0 record not supported\n", hpp->revision); 43 return; 44 } 45 46 pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp->cache_line_size); 47 pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp->latency_timer); 48 pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); 49 if (hpp->enable_serr) 50 pci_cmd |= PCI_COMMAND_SERR; 51 else 52 pci_cmd &= ~PCI_COMMAND_SERR; 53 if (hpp->enable_perr) 54 pci_cmd |= PCI_COMMAND_PARITY; 55 else 56 pci_cmd &= ~PCI_COMMAND_PARITY; 57 pci_write_config_word(dev, PCI_COMMAND, pci_cmd); 58 59 /* Program bridge control value */ 60 if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { 61 pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 62 hpp->latency_timer); 63 pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl); 64 if (hpp->enable_serr) 65 pci_bctl |= PCI_BRIDGE_CTL_SERR; 66 else 67 pci_bctl &= ~PCI_BRIDGE_CTL_SERR; 68 if (hpp->enable_perr) 69 pci_bctl |= PCI_BRIDGE_CTL_PARITY; 70 else 71 pci_bctl &= ~PCI_BRIDGE_CTL_PARITY; 72 pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl); 73 } 74 } 75 76 static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp) 77 { 78 int pos; 79 u16 reg16; 80 u32 reg32; 81 82 if (hpp->revision > 1) { 83 warn("Rev.%d type2 record not supported\n", hpp->revision); 84 return; 85 } 86 87 /* Find PCI Express capability */ 88 pos = pci_find_capability(dev, PCI_CAP_ID_EXP); 89 if (!pos) 90 return; 91 92 /* Initialize Device Control Register */ 93 pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, ®16); 94 reg16 = (reg16 & hpp->pci_exp_devctl_and) | hpp->pci_exp_devctl_or; 95 pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, reg16); 96 97 /* Initialize Link Control Register */ 98 if (dev->subordinate) { 99 pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, ®16); 100 reg16 = (reg16 & hpp->pci_exp_lnkctl_and) 101 | hpp->pci_exp_lnkctl_or; 102 pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, reg16); 103 } 104 105 /* Find Advanced Error Reporting Enhanced Capability */ 106 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); 107 if (!pos) 108 return; 109 110 /* Initialize Uncorrectable Error Mask Register */ 111 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, ®32); 112 reg32 = (reg32 & hpp->unc_err_mask_and) | hpp->unc_err_mask_or; 113 pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, reg32); 114 115 /* Initialize Uncorrectable Error Severity Register */ 116 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, ®32); 117 reg32 = (reg32 & hpp->unc_err_sever_and) | hpp->unc_err_sever_or; 118 pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, reg32); 119 120 /* Initialize Correctable Error Mask Register */ 121 pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, ®32); 122 reg32 = (reg32 & hpp->cor_err_mask_and) | hpp->cor_err_mask_or; 123 pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg32); 124 125 /* Initialize Advanced Error Capabilities and Control Register */ 126 pci_read_config_dword(dev, pos + PCI_ERR_CAP, ®32); 127 reg32 = (reg32 & hpp->adv_err_cap_and) | hpp->adv_err_cap_or; 128 pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32); 129 130 /* 131 * FIXME: The following two registers are not supported yet. 132 * 133 * o Secondary Uncorrectable Error Severity Register 134 * o Secondary Uncorrectable Error Mask Register 135 */ 136 } 137 138 static void program_fw_provided_values(struct pci_dev *dev) 139 { 140 struct pci_dev *cdev; 141 struct hotplug_params hpp; 142 143 /* Program hpp values for this device */ 144 if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL || 145 (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && 146 (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) 147 return; 148 149 if (pciehp_get_hp_params_from_firmware(dev, &hpp)) { 150 warn("Could not get hotplug parameters\n"); 151 return; 152 } 153 154 if (hpp.t2) 155 program_hpp_type2(dev, hpp.t2); 156 if (hpp.t0) 157 program_hpp_type0(dev, hpp.t0); 158 159 /* Program child devices */ 160 if (dev->subordinate) { 161 list_for_each_entry(cdev, &dev->subordinate->devices, 162 bus_list) 163 program_fw_provided_values(cdev); 164 } 165 } 166 167 static int __ref pciehp_add_bridge(struct pci_dev *dev) 168 { 169 struct pci_bus *parent = dev->bus; 170 int pass, busnr, start = parent->secondary; 171 int end = parent->subordinate; 172 173 for (busnr = start; busnr <= end; busnr++) { 174 if (!pci_find_bus(pci_domain_nr(parent), busnr)) 175 break; 176 } 177 if (busnr-- > end) { 178 err("No bus number available for hot-added bridge %s\n", 179 pci_name(dev)); 180 return -1; 181 } 182 for (pass = 0; pass < 2; pass++) 183 busnr = pci_scan_bridge(parent, dev, busnr, pass); 184 if (!dev->subordinate) 185 return -1; 186 pci_bus_size_bridges(dev->subordinate); 187 pci_bus_assign_resources(parent); 188 pci_enable_bridges(parent); 189 pci_bus_add_devices(parent); 190 return 0; 191 } 192 193 int pciehp_configure_device(struct slot *p_slot) 194 { 195 struct pci_dev *dev; 196 struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate; 197 int num, fn; 198 struct controller *ctrl = p_slot->ctrl; 199 200 dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0)); 201 if (dev) { 202 ctrl_err(ctrl, "Device %s already exists " 203 "at %04x:%02x:%02x, cannot hot-add\n", pci_name(dev), 204 pci_domain_nr(parent), p_slot->bus, p_slot->device); 205 pci_dev_put(dev); 206 return -EINVAL; 207 } 208 209 num = pci_scan_slot(parent, PCI_DEVFN(p_slot->device, 0)); 210 if (num == 0) { 211 ctrl_err(ctrl, "No new device found\n"); 212 return -ENODEV; 213 } 214 215 for (fn = 0; fn < 8; fn++) { 216 dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn)); 217 if (!dev) 218 continue; 219 if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { 220 ctrl_err(ctrl, "Cannot hot-add display device %s\n", 221 pci_name(dev)); 222 pci_dev_put(dev); 223 continue; 224 } 225 if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || 226 (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { 227 pciehp_add_bridge(dev); 228 } 229 program_fw_provided_values(dev); 230 pci_dev_put(dev); 231 } 232 233 pci_bus_assign_resources(parent); 234 pci_bus_add_devices(parent); 235 return 0; 236 } 237 238 int pciehp_unconfigure_device(struct slot *p_slot) 239 { 240 int ret, rc = 0; 241 int j; 242 u8 bctl = 0; 243 u8 presence = 0; 244 struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate; 245 u16 command; 246 struct controller *ctrl = p_slot->ctrl; 247 248 ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:%02x\n", 249 __func__, pci_domain_nr(parent), p_slot->bus, p_slot->device); 250 ret = p_slot->hpc_ops->get_adapter_status(p_slot, &presence); 251 if (ret) 252 presence = 0; 253 254 for (j = 0; j < 8; j++) { 255 struct pci_dev* temp = pci_get_slot(parent, 256 (p_slot->device << 3) | j); 257 if (!temp) 258 continue; 259 if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) { 260 ctrl_err(ctrl, "Cannot remove display device %s\n", 261 pci_name(temp)); 262 pci_dev_put(temp); 263 continue; 264 } 265 if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) { 266 pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl); 267 if (bctl & PCI_BRIDGE_CTL_VGA) { 268 ctrl_err(ctrl, 269 "Cannot remove display device %s\n", 270 pci_name(temp)); 271 pci_dev_put(temp); 272 continue; 273 } 274 } 275 pci_remove_bus_device(temp); 276 /* 277 * Ensure that no new Requests will be generated from 278 * the device. 279 */ 280 if (presence) { 281 pci_read_config_word(temp, PCI_COMMAND, &command); 282 command &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_SERR); 283 command |= PCI_COMMAND_INTX_DISABLE; 284 pci_write_config_word(temp, PCI_COMMAND, command); 285 } 286 pci_dev_put(temp); 287 } 288 /* 289 * Some PCI Express root ports require fixup after hot-plug operation. 290 */ 291 if (pcie_mch_quirk) 292 pci_fixup_device(pci_fixup_final, p_slot->ctrl->pci_dev); 293 294 return rc; 295 } 296