diff options
author | Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> | 2005-11-23 21:36:59 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-01-09 15:13:17 -0500 |
commit | 0455986cce45d28511f59a29d6cecc17d6b65720 (patch) | |
tree | 1819f13fdaee29489090a92b683faebff6651ea7 | |
parent | 87d6c5593111844f308af7d5106b3fd259b36514 (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>
-rw-r--r-- | drivers/pci/hotplug/shpchp.h | 3 | ||||
-rw-r--r-- | drivers/pci/hotplug/shpchp_core.c | 2 | ||||
-rw-r--r-- | drivers/pci/hotplug/shpchp_hpc.c | 73 |
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 | ||
103 | struct hotplug_params { | 106 | struct 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 | ||
1323 | inline 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 | |||
1323 | int shpc_init(struct controller * ctrl, struct pci_dev * pdev) | 1336 | int 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); |