aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/probe.c
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2014-09-23 12:03:18 -0400
committerBjorn Helgaas <bhelgaas@google.com>2014-09-23 12:03:18 -0400
commit2f419d76599e2fd1a2c2cf31730c80e952201af1 (patch)
treef1302a51b310d255480931c95d9ba42b6b8e1a14 /drivers/pci/probe.c
parentef39ab79f7401f99212e2ae8a2399d88d6c77c64 (diff)
parentbceee4a97eb58bd0e80e39eff11b506ddd9e7ad3 (diff)
Merge branch 'pci/hotplug' into next
* pci/hotplug: PCI: pciehp: Prevent NULL dereference during probe PCI: pciehp: Reduce PCIe slot_ctrl to 16 bits PCI: Configure *all* devices, not just hot-added ones PCI: Preserve MPS and MRRS when applying _HPX settings PCI: Apply _HPP settings to all hot-added PCI devices PCI: Preserve BIOS PCI_COMMAND_SERR and PCI_COMMAND_PARITY settings PCI: Apply _HPP settings to PCIe devices as well as PCI and PCI-X PCI: Remove unused pci_configure_slot() ACPI / hotplug / PCI: Remove pci_configure_slot() usage PCI: shpchp: Remove pci_configure_slot() usage PCI: pciehp: Remove pci_configure_slot() usage PCI: Add pci_configure_device() during enumeration PCI: Move pci_configure_slot() to drivers/pci/probe.c PCI: Shuffle pci-acpi.c functions to group them logically PCI: Whitespace cleanup in pci-acpi.c PCI: Move pci_get_hp_params() to drivers/pci/pci-acpi.c PCI: pciehp: Configure hot-added display devices PCI: Remove "no hotplug settings from platform" warning
Diffstat (limited to 'drivers/pci/probe.c')
-rw-r--r--drivers/pci/probe.c134
1 files changed, 134 insertions, 0 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index e02cdaa5bf0c..c99c4d65461b 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -6,6 +6,7 @@
6#include <linux/delay.h> 6#include <linux/delay.h>
7#include <linux/init.h> 7#include <linux/init.h>
8#include <linux/pci.h> 8#include <linux/pci.h>
9#include <linux/pci_hotplug.h>
9#include <linux/slab.h> 10#include <linux/slab.h>
10#include <linux/module.h> 11#include <linux/module.h>
11#include <linux/cpumask.h> 12#include <linux/cpumask.h>
@@ -1249,6 +1250,137 @@ int pci_setup_device(struct pci_dev *dev)
1249 return 0; 1250 return 0;
1250} 1251}
1251 1252
1253static struct hpp_type0 pci_default_type0 = {
1254 .revision = 1,
1255 .cache_line_size = 8,
1256 .latency_timer = 0x40,
1257 .enable_serr = 0,
1258 .enable_perr = 0,
1259};
1260
1261static void program_hpp_type0(struct pci_dev *dev, struct hpp_type0 *hpp)
1262{
1263 u16 pci_cmd, pci_bctl;
1264
1265 if (!hpp)
1266 hpp = &pci_default_type0;
1267
1268 if (hpp->revision > 1) {
1269 dev_warn(&dev->dev,
1270 "PCI settings rev %d not supported; using defaults\n",
1271 hpp->revision);
1272 hpp = &pci_default_type0;
1273 }
1274
1275 pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp->cache_line_size);
1276 pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp->latency_timer);
1277 pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
1278 if (hpp->enable_serr)
1279 pci_cmd |= PCI_COMMAND_SERR;
1280 if (hpp->enable_perr)
1281 pci_cmd |= PCI_COMMAND_PARITY;
1282 pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
1283
1284 /* Program bridge control value */
1285 if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
1286 pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,
1287 hpp->latency_timer);
1288 pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
1289 if (hpp->enable_serr)
1290 pci_bctl |= PCI_BRIDGE_CTL_SERR;
1291 if (hpp->enable_perr)
1292 pci_bctl |= PCI_BRIDGE_CTL_PARITY;
1293 pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl);
1294 }
1295}
1296
1297static void program_hpp_type1(struct pci_dev *dev, struct hpp_type1 *hpp)
1298{
1299 if (hpp)
1300 dev_warn(&dev->dev, "PCI-X settings not supported\n");
1301}
1302
1303static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
1304{
1305 int pos;
1306 u32 reg32;
1307
1308 if (!hpp)
1309 return;
1310
1311 if (hpp->revision > 1) {
1312 dev_warn(&dev->dev, "PCIe settings rev %d not supported\n",
1313 hpp->revision);
1314 return;
1315 }
1316
1317 /*
1318 * Don't allow _HPX to change MPS or MRRS settings. We manage
1319 * those to make sure they're consistent with the rest of the
1320 * platform.
1321 */
1322 hpp->pci_exp_devctl_and |= PCI_EXP_DEVCTL_PAYLOAD |
1323 PCI_EXP_DEVCTL_READRQ;
1324 hpp->pci_exp_devctl_or &= ~(PCI_EXP_DEVCTL_PAYLOAD |
1325 PCI_EXP_DEVCTL_READRQ);
1326
1327 /* Initialize Device Control Register */
1328 pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL,
1329 ~hpp->pci_exp_devctl_and, hpp->pci_exp_devctl_or);
1330
1331 /* Initialize Link Control Register */
1332 if (dev->subordinate)
1333 pcie_capability_clear_and_set_word(dev, PCI_EXP_LNKCTL,
1334 ~hpp->pci_exp_lnkctl_and, hpp->pci_exp_lnkctl_or);
1335
1336 /* Find Advanced Error Reporting Enhanced Capability */
1337 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
1338 if (!pos)
1339 return;
1340
1341 /* Initialize Uncorrectable Error Mask Register */
1342 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, &reg32);
1343 reg32 = (reg32 & hpp->unc_err_mask_and) | hpp->unc_err_mask_or;
1344 pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, reg32);
1345
1346 /* Initialize Uncorrectable Error Severity Register */
1347 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &reg32);
1348 reg32 = (reg32 & hpp->unc_err_sever_and) | hpp->unc_err_sever_or;
1349 pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, reg32);
1350
1351 /* Initialize Correctable Error Mask Register */
1352 pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &reg32);
1353 reg32 = (reg32 & hpp->cor_err_mask_and) | hpp->cor_err_mask_or;
1354 pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg32);
1355
1356 /* Initialize Advanced Error Capabilities and Control Register */
1357 pci_read_config_dword(dev, pos + PCI_ERR_CAP, &reg32);
1358 reg32 = (reg32 & hpp->adv_err_cap_and) | hpp->adv_err_cap_or;
1359 pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32);
1360
1361 /*
1362 * FIXME: The following two registers are not supported yet.
1363 *
1364 * o Secondary Uncorrectable Error Severity Register
1365 * o Secondary Uncorrectable Error Mask Register
1366 */
1367}
1368
1369static void pci_configure_device(struct pci_dev *dev)
1370{
1371 struct hotplug_params hpp;
1372 int ret;
1373
1374 memset(&hpp, 0, sizeof(hpp));
1375 ret = pci_get_hp_params(dev, &hpp);
1376 if (ret)
1377 return;
1378
1379 program_hpp_type2(dev, hpp.t2);
1380 program_hpp_type1(dev, hpp.t1);
1381 program_hpp_type0(dev, hpp.t0);
1382}
1383
1252static void pci_release_capabilities(struct pci_dev *dev) 1384static void pci_release_capabilities(struct pci_dev *dev)
1253{ 1385{
1254 pci_vpd_release(dev); 1386 pci_vpd_release(dev);
@@ -1391,6 +1523,8 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
1391{ 1523{
1392 int ret; 1524 int ret;
1393 1525
1526 pci_configure_device(dev);
1527
1394 device_initialize(&dev->dev); 1528 device_initialize(&dev->dev);
1395 dev->dev.release = pci_release_dev; 1529 dev->dev.release = pci_release_dev;
1396 1530