aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>2005-11-23 21:36:59 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2006-01-09 15:13:17 -0500
commit0455986cce45d28511f59a29d6cecc17d6b65720 (patch)
tree1819f13fdaee29489090a92b683faebff6651ea7 /drivers
parent87d6c5593111844f308af7d5106b3fd259b36514 (diff)
[PATCH] shpchp: fix improper mmio mapping
Current SHPCHP driver seems not to map MMIO region properly. This patch fixes this bug. This patch also cleanup the code. Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pci/hotplug/shpchp.h3
-rw-r--r--drivers/pci/hotplug/shpchp_core.c2
-rw-r--r--drivers/pci/hotplug/shpchp_hpc.c73
3 files changed, 49 insertions, 29 deletions
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index 08ad26a0cae7..55b0cd15f348 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -98,6 +98,9 @@ struct controller {
98 enum pci_bus_speed speed; 98 enum pci_bus_speed speed;
99 u32 first_slot; /* First physical slot number */ 99 u32 first_slot; /* First physical slot number */
100 u8 slot_bus; /* Bus where the slots handled by this controller sit */ 100 u8 slot_bus; /* Bus where the slots handled by this controller sit */
101 u32 cap_offset;
102 unsigned long mmio_base;
103 unsigned long mmio_size;
101}; 104};
102 105
103struct hotplug_params { 106struct hotplug_params {
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index 63628e01dd43..d81f8a75b495 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -377,8 +377,6 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
377 goto err_out_free_ctrl; 377 goto err_out_free_ctrl;
378 } 378 }
379 379
380 ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */
381
382 pci_set_drvdata(pdev, ctrl); 380 pci_set_drvdata(pdev, ctrl);
383 381
384 ctrl->pci_bus = kmalloc (sizeof (*ctrl->pci_bus), GFP_KERNEL); 382 ctrl->pci_bus = kmalloc (sizeof (*ctrl->pci_bus), GFP_KERNEL);
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
index f5a8bf374634..d82987f075b2 100644
--- a/drivers/pci/hotplug/shpchp_hpc.c
+++ b/drivers/pci/hotplug/shpchp_hpc.c
@@ -791,7 +791,7 @@ static void hpc_release_ctlr(struct controller *ctrl)
791 } 791 }
792 if (php_ctlr->pci_dev) { 792 if (php_ctlr->pci_dev) {
793 iounmap(php_ctlr->creg); 793 iounmap(php_ctlr->creg);
794 release_mem_region(pci_resource_start(php_ctlr->pci_dev, 0), pci_resource_len(php_ctlr->pci_dev, 0)); 794 release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
795 php_ctlr->pci_dev = NULL; 795 php_ctlr->pci_dev = NULL;
796 } 796 }
797 797
@@ -1320,19 +1320,34 @@ static struct hpc_ops shpchp_hpc_ops = {
1320 .check_cmd_status = hpc_check_cmd_status, 1320 .check_cmd_status = hpc_check_cmd_status,
1321}; 1321};
1322 1322
1323inline static int shpc_indirect_creg_read(struct controller *ctrl, int index,
1324 u32 *value)
1325{
1326 int rc;
1327 u32 cap_offset = ctrl->cap_offset;
1328 struct pci_dev *pdev = ctrl->pci_dev;
1329
1330 rc = pci_write_config_byte(pdev, cap_offset + DWORD_SELECT, index);
1331 if (rc)
1332 return rc;
1333 return pci_read_config_dword(pdev, cap_offset + DWORD_DATA, value);
1334}
1335
1323int shpc_init(struct controller * ctrl, struct pci_dev * pdev) 1336int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
1324{ 1337{
1325 struct php_ctlr_state_s *php_ctlr, *p; 1338 struct php_ctlr_state_s *php_ctlr, *p;
1326 void *instance_id = ctrl; 1339 void *instance_id = ctrl;
1327 int rc; 1340 int rc, num_slots = 0;
1328 u8 hp_slot; 1341 u8 hp_slot;
1329 static int first = 1; 1342 static int first = 1;
1330 u32 shpc_cap_offset, shpc_base_offset; 1343 u32 shpc_base_offset;
1331 u32 tempdword, slot_reg; 1344 u32 tempdword, slot_reg;
1332 u8 i; 1345 u8 i;
1333 1346
1334 DBG_ENTER_ROUTINE 1347 DBG_ENTER_ROUTINE
1335 1348
1349 ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */
1350
1336 spin_lock_init(&list_lock); 1351 spin_lock_init(&list_lock);
1337 php_ctlr = (struct php_ctlr_state_s *) kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL); 1352 php_ctlr = (struct php_ctlr_state_s *) kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL);
1338 1353
@@ -1347,41 +1362,45 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
1347 1362
1348 if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device == 1363 if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device ==
1349 PCI_DEVICE_ID_AMD_GOLAM_7450)) { 1364 PCI_DEVICE_ID_AMD_GOLAM_7450)) {
1350 shpc_base_offset = 0; /* amd shpc driver doesn't use this; assume 0 */ 1365 /* amd shpc driver doesn't use Base Offset; assume 0 */
1366 ctrl->mmio_base = pci_resource_start(pdev, 0);
1367 ctrl->mmio_size = pci_resource_len(pdev, 0);
1351 } else { 1368 } else {
1352 if ((shpc_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC)) == 0) { 1369 ctrl->cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC);
1353 err("%s : shpc_cap_offset == 0\n", __FUNCTION__); 1370 if (!ctrl->cap_offset) {
1371 err("%s : cap_offset == 0\n", __FUNCTION__);
1354 goto abort_free_ctlr; 1372 goto abort_free_ctlr;
1355 } 1373 }
1356 dbg("%s: shpc_cap_offset = %x\n", __FUNCTION__, shpc_cap_offset); 1374 dbg("%s: cap_offset = %x\n", __FUNCTION__, ctrl->cap_offset);
1357 1375
1358 rc = pci_write_config_byte(pdev, (u8)shpc_cap_offset + DWORD_SELECT , BASE_OFFSET); 1376 rc = shpc_indirect_creg_read(ctrl, 0, &shpc_base_offset);
1359 if (rc) { 1377 if (rc) {
1360 err("%s : pci_word_config_byte failed\n", __FUNCTION__); 1378 err("%s: cannot read base_offset\n", __FUNCTION__);
1361 goto abort_free_ctlr; 1379 goto abort_free_ctlr;
1362 } 1380 }
1363 1381
1364 rc = pci_read_config_dword(pdev, (u8)shpc_cap_offset + DWORD_DATA, &shpc_base_offset); 1382 rc = shpc_indirect_creg_read(ctrl, 3, &tempdword);
1365 if (rc) { 1383 if (rc) {
1366 err("%s : pci_read_config_dword failed\n", __FUNCTION__); 1384 err("%s: cannot read slot config\n", __FUNCTION__);
1367 goto abort_free_ctlr; 1385 goto abort_free_ctlr;
1368 } 1386 }
1387 num_slots = tempdword & SLOT_NUM;
1388 dbg("%s: num_slots (indirect) %x\n", __FUNCTION__, num_slots);
1369 1389
1370 for (i = 0; i <= 14; i++) { 1390 for (i = 0; i < 9 + num_slots; i++) {
1371 rc = pci_write_config_byte(pdev, (u8)shpc_cap_offset + DWORD_SELECT , i); 1391 rc = shpc_indirect_creg_read(ctrl, i, &tempdword);
1372 if (rc) {
1373 err("%s : pci_word_config_byte failed\n", __FUNCTION__);
1374 goto abort_free_ctlr;
1375 }
1376
1377 rc = pci_read_config_dword(pdev, (u8)shpc_cap_offset + DWORD_DATA, &tempdword);
1378 if (rc) { 1392 if (rc) {
1379 err("%s : pci_read_config_dword failed\n", __FUNCTION__); 1393 err("%s: cannot read creg (index = %d)\n",
1394 __FUNCTION__, i);
1380 goto abort_free_ctlr; 1395 goto abort_free_ctlr;
1381 } 1396 }
1382 dbg("%s: offset %d: value %x\n", __FUNCTION__,i, 1397 dbg("%s: offset %d: value %x\n", __FUNCTION__,i,
1383 tempdword); 1398 tempdword);
1384 } 1399 }
1400
1401 ctrl->mmio_base =
1402 pci_resource_start(pdev, 0) + shpc_base_offset;
1403 ctrl->mmio_size = 0x24 + 0x4 * num_slots;
1385 } 1404 }
1386 1405
1387 if (first) { 1406 if (first) {
@@ -1395,16 +1414,16 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
1395 if (pci_enable_device(pdev)) 1414 if (pci_enable_device(pdev))
1396 goto abort_free_ctlr; 1415 goto abort_free_ctlr;
1397 1416
1398 if (!request_mem_region(pci_resource_start(pdev, 0) + shpc_base_offset, pci_resource_len(pdev, 0), MY_NAME)) { 1417 if (!request_mem_region(ctrl->mmio_base, ctrl->mmio_size, MY_NAME)) {
1399 err("%s: cannot reserve MMIO region\n", __FUNCTION__); 1418 err("%s: cannot reserve MMIO region\n", __FUNCTION__);
1400 goto abort_free_ctlr; 1419 goto abort_free_ctlr;
1401 } 1420 }
1402 1421
1403 php_ctlr->creg = ioremap(pci_resource_start(pdev, 0) + shpc_base_offset, pci_resource_len(pdev, 0)); 1422 php_ctlr->creg = ioremap(ctrl->mmio_base, ctrl->mmio_size);
1404 if (!php_ctlr->creg) { 1423 if (!php_ctlr->creg) {
1405 err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__, pci_resource_len(pdev, 0), 1424 err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__,
1406 pci_resource_start(pdev, 0) + shpc_base_offset); 1425 ctrl->mmio_size, ctrl->mmio_base);
1407 release_mem_region(pci_resource_start(pdev, 0) + shpc_base_offset, pci_resource_len(pdev, 0)); 1426 release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
1408 goto abort_free_ctlr; 1427 goto abort_free_ctlr;
1409 } 1428 }
1410 dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg); 1429 dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg);