diff options
Diffstat (limited to 'drivers/pci/hotplug/shpchp_hpc.c')
-rw-r--r-- | drivers/pci/hotplug/shpchp_hpc.c | 138 |
1 files changed, 91 insertions, 47 deletions
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 9987a6fd65b8..b4226ff3a854 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c | |||
@@ -275,6 +275,25 @@ static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds) | |||
275 | return; | 275 | return; |
276 | } | 276 | } |
277 | 277 | ||
278 | static inline int shpc_wait_cmd(struct controller *ctrl) | ||
279 | { | ||
280 | int retval = 0; | ||
281 | unsigned int timeout_msec = shpchp_poll_mode ? 2000 : 1000; | ||
282 | unsigned long timeout = msecs_to_jiffies(timeout_msec); | ||
283 | int rc = wait_event_interruptible_timeout(ctrl->queue, | ||
284 | !ctrl->cmd_busy, timeout); | ||
285 | if (!rc) { | ||
286 | retval = -EIO; | ||
287 | err("Command not completed in %d msec\n", timeout_msec); | ||
288 | } else if (rc < 0) { | ||
289 | retval = -EINTR; | ||
290 | info("Command was interrupted by a signal\n"); | ||
291 | } | ||
292 | ctrl->cmd_busy = 0; | ||
293 | |||
294 | return retval; | ||
295 | } | ||
296 | |||
278 | static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) | 297 | static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) |
279 | { | 298 | { |
280 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; | 299 | struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; |
@@ -314,8 +333,14 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) | |||
314 | /* To make sure the Controller Busy bit is 0 before we send out the | 333 | /* To make sure the Controller Busy bit is 0 before we send out the |
315 | * command. | 334 | * command. |
316 | */ | 335 | */ |
336 | slot->ctrl->cmd_busy = 1; | ||
317 | writew(temp_word, php_ctlr->creg + CMD); | 337 | writew(temp_word, php_ctlr->creg + CMD); |
318 | 338 | ||
339 | /* | ||
340 | * Wait for command completion. | ||
341 | */ | ||
342 | retval = shpc_wait_cmd(slot->ctrl); | ||
343 | |||
319 | DBG_LEAVE_ROUTINE | 344 | DBG_LEAVE_ROUTINE |
320 | return retval; | 345 | return retval; |
321 | } | 346 | } |
@@ -604,7 +629,7 @@ static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode) | |||
604 | sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG); | 629 | sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG); |
605 | 630 | ||
606 | if (pi == 2) { | 631 | if (pi == 2) { |
607 | *mode = (sec_bus_status & 0x0100) >> 7; | 632 | *mode = (sec_bus_status & 0x0100) >> 8; |
608 | } else { | 633 | } else { |
609 | retval = -1; | 634 | retval = -1; |
610 | } | 635 | } |
@@ -791,7 +816,7 @@ static void hpc_release_ctlr(struct controller *ctrl) | |||
791 | } | 816 | } |
792 | if (php_ctlr->pci_dev) { | 817 | if (php_ctlr->pci_dev) { |
793 | iounmap(php_ctlr->creg); | 818 | iounmap(php_ctlr->creg); |
794 | release_mem_region(pci_resource_start(php_ctlr->pci_dev, 0), pci_resource_len(php_ctlr->pci_dev, 0)); | 819 | release_mem_region(ctrl->mmio_base, ctrl->mmio_size); |
795 | php_ctlr->pci_dev = NULL; | 820 | php_ctlr->pci_dev = NULL; |
796 | } | 821 | } |
797 | 822 | ||
@@ -1058,12 +1083,13 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) | |||
1058 | if (intr_loc & 0x0001) { | 1083 | if (intr_loc & 0x0001) { |
1059 | /* | 1084 | /* |
1060 | * Command Complete Interrupt Pending | 1085 | * Command Complete Interrupt Pending |
1061 | * RO only - clear by writing 0 to the Command Completion | 1086 | * RO only - clear by writing 1 to the Command Completion |
1062 | * Detect bit in Controller SERR-INT register | 1087 | * Detect bit in Controller SERR-INT register |
1063 | */ | 1088 | */ |
1064 | temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); | 1089 | temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); |
1065 | temp_dword &= 0xfffeffff; | 1090 | temp_dword &= 0xfffdffff; |
1066 | writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); | 1091 | writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); |
1092 | ctrl->cmd_busy = 0; | ||
1067 | wake_up_interruptible(&ctrl->queue); | 1093 | wake_up_interruptible(&ctrl->queue); |
1068 | } | 1094 | } |
1069 | 1095 | ||
@@ -1121,7 +1147,6 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) | |||
1121 | int retval = 0; | 1147 | int retval = 0; |
1122 | u8 pi; | 1148 | u8 pi; |
1123 | u32 slot_avail1, slot_avail2; | 1149 | u32 slot_avail1, slot_avail2; |
1124 | int slot_num; | ||
1125 | 1150 | ||
1126 | DBG_ENTER_ROUTINE | 1151 | DBG_ENTER_ROUTINE |
1127 | 1152 | ||
@@ -1140,39 +1165,39 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) | |||
1140 | slot_avail2 = readl(php_ctlr->creg + SLOT_AVAIL2); | 1165 | slot_avail2 = readl(php_ctlr->creg + SLOT_AVAIL2); |
1141 | 1166 | ||
1142 | if (pi == 2) { | 1167 | if (pi == 2) { |
1143 | if ((slot_num = ((slot_avail2 & SLOT_133MHZ_PCIX_533) >> 27) ) != 0 ) | 1168 | if (slot_avail2 & SLOT_133MHZ_PCIX_533) |
1144 | bus_speed = PCIX_133MHZ_533; | 1169 | bus_speed = PCIX_133MHZ_533; |
1145 | else if ((slot_num = ((slot_avail2 & SLOT_100MHZ_PCIX_533) >> 23) ) != 0 ) | 1170 | else if (slot_avail2 & SLOT_100MHZ_PCIX_533) |
1146 | bus_speed = PCIX_100MHZ_533; | 1171 | bus_speed = PCIX_100MHZ_533; |
1147 | else if ((slot_num = ((slot_avail2 & SLOT_66MHZ_PCIX_533) >> 19) ) != 0 ) | 1172 | else if (slot_avail2 & SLOT_66MHZ_PCIX_533) |
1148 | bus_speed = PCIX_66MHZ_533; | 1173 | bus_speed = PCIX_66MHZ_533; |
1149 | else if ((slot_num = ((slot_avail2 & SLOT_133MHZ_PCIX_266) >> 15) ) != 0 ) | 1174 | else if (slot_avail2 & SLOT_133MHZ_PCIX_266) |
1150 | bus_speed = PCIX_133MHZ_266; | 1175 | bus_speed = PCIX_133MHZ_266; |
1151 | else if ((slot_num = ((slot_avail2 & SLOT_100MHZ_PCIX_266) >> 11) ) != 0 ) | 1176 | else if (slot_avail2 & SLOT_100MHZ_PCIX_266) |
1152 | bus_speed = PCIX_100MHZ_266; | 1177 | bus_speed = PCIX_100MHZ_266; |
1153 | else if ((slot_num = ((slot_avail2 & SLOT_66MHZ_PCIX_266) >> 7) ) != 0 ) | 1178 | else if (slot_avail2 & SLOT_66MHZ_PCIX_266) |
1154 | bus_speed = PCIX_66MHZ_266; | 1179 | bus_speed = PCIX_66MHZ_266; |
1155 | else if ((slot_num = ((slot_avail1 & SLOT_133MHZ_PCIX) >> 23) ) != 0 ) | 1180 | else if (slot_avail1 & SLOT_133MHZ_PCIX) |
1156 | bus_speed = PCIX_133MHZ; | 1181 | bus_speed = PCIX_133MHZ; |
1157 | else if ((slot_num = ((slot_avail1 & SLOT_100MHZ_PCIX) >> 15) ) != 0 ) | 1182 | else if (slot_avail1 & SLOT_100MHZ_PCIX) |
1158 | bus_speed = PCIX_100MHZ; | 1183 | bus_speed = PCIX_100MHZ; |
1159 | else if ((slot_num = ((slot_avail1 & SLOT_66MHZ_PCIX) >> 7) ) != 0 ) | 1184 | else if (slot_avail1 & SLOT_66MHZ_PCIX) |
1160 | bus_speed = PCIX_66MHZ; | 1185 | bus_speed = PCIX_66MHZ; |
1161 | else if ((slot_num = (slot_avail2 & SLOT_66MHZ)) != 0 ) | 1186 | else if (slot_avail2 & SLOT_66MHZ) |
1162 | bus_speed = PCI_66MHZ; | 1187 | bus_speed = PCI_66MHZ; |
1163 | else if ((slot_num = (slot_avail1 & SLOT_33MHZ)) != 0 ) | 1188 | else if (slot_avail1 & SLOT_33MHZ) |
1164 | bus_speed = PCI_33MHZ; | 1189 | bus_speed = PCI_33MHZ; |
1165 | else bus_speed = PCI_SPEED_UNKNOWN; | 1190 | else bus_speed = PCI_SPEED_UNKNOWN; |
1166 | } else { | 1191 | } else { |
1167 | if ((slot_num = ((slot_avail1 & SLOT_133MHZ_PCIX) >> 23) ) != 0 ) | 1192 | if (slot_avail1 & SLOT_133MHZ_PCIX) |
1168 | bus_speed = PCIX_133MHZ; | 1193 | bus_speed = PCIX_133MHZ; |
1169 | else if ((slot_num = ((slot_avail1 & SLOT_100MHZ_PCIX) >> 15) ) != 0 ) | 1194 | else if (slot_avail1 & SLOT_100MHZ_PCIX) |
1170 | bus_speed = PCIX_100MHZ; | 1195 | bus_speed = PCIX_100MHZ; |
1171 | else if ((slot_num = ((slot_avail1 & SLOT_66MHZ_PCIX) >> 7) ) != 0 ) | 1196 | else if (slot_avail1 & SLOT_66MHZ_PCIX) |
1172 | bus_speed = PCIX_66MHZ; | 1197 | bus_speed = PCIX_66MHZ; |
1173 | else if ((slot_num = (slot_avail2 & SLOT_66MHZ)) != 0 ) | 1198 | else if (slot_avail2 & SLOT_66MHZ) |
1174 | bus_speed = PCI_66MHZ; | 1199 | bus_speed = PCI_66MHZ; |
1175 | else if ((slot_num = (slot_avail1 & SLOT_33MHZ)) != 0 ) | 1200 | else if (slot_avail1 & SLOT_33MHZ) |
1176 | bus_speed = PCI_33MHZ; | 1201 | bus_speed = PCI_33MHZ; |
1177 | else bus_speed = PCI_SPEED_UNKNOWN; | 1202 | else bus_speed = PCI_SPEED_UNKNOWN; |
1178 | } | 1203 | } |
@@ -1321,19 +1346,34 @@ static struct hpc_ops shpchp_hpc_ops = { | |||
1321 | .check_cmd_status = hpc_check_cmd_status, | 1346 | .check_cmd_status = hpc_check_cmd_status, |
1322 | }; | 1347 | }; |
1323 | 1348 | ||
1349 | inline static int shpc_indirect_creg_read(struct controller *ctrl, int index, | ||
1350 | u32 *value) | ||
1351 | { | ||
1352 | int rc; | ||
1353 | u32 cap_offset = ctrl->cap_offset; | ||
1354 | struct pci_dev *pdev = ctrl->pci_dev; | ||
1355 | |||
1356 | rc = pci_write_config_byte(pdev, cap_offset + DWORD_SELECT, index); | ||
1357 | if (rc) | ||
1358 | return rc; | ||
1359 | return pci_read_config_dword(pdev, cap_offset + DWORD_DATA, value); | ||
1360 | } | ||
1361 | |||
1324 | int shpc_init(struct controller * ctrl, struct pci_dev * pdev) | 1362 | int shpc_init(struct controller * ctrl, struct pci_dev * pdev) |
1325 | { | 1363 | { |
1326 | struct php_ctlr_state_s *php_ctlr, *p; | 1364 | struct php_ctlr_state_s *php_ctlr, *p; |
1327 | void *instance_id = ctrl; | 1365 | void *instance_id = ctrl; |
1328 | int rc; | 1366 | int rc, num_slots = 0; |
1329 | u8 hp_slot; | 1367 | u8 hp_slot; |
1330 | static int first = 1; | 1368 | static int first = 1; |
1331 | u32 shpc_cap_offset, shpc_base_offset; | 1369 | u32 shpc_base_offset; |
1332 | u32 tempdword, slot_reg; | 1370 | u32 tempdword, slot_reg; |
1333 | u8 i; | 1371 | u8 i; |
1334 | 1372 | ||
1335 | DBG_ENTER_ROUTINE | 1373 | DBG_ENTER_ROUTINE |
1336 | 1374 | ||
1375 | ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */ | ||
1376 | |||
1337 | spin_lock_init(&list_lock); | 1377 | spin_lock_init(&list_lock); |
1338 | php_ctlr = (struct php_ctlr_state_s *) kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL); | 1378 | php_ctlr = (struct php_ctlr_state_s *) kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL); |
1339 | 1379 | ||
@@ -1348,41 +1388,45 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) | |||
1348 | 1388 | ||
1349 | if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device == | 1389 | if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device == |
1350 | PCI_DEVICE_ID_AMD_GOLAM_7450)) { | 1390 | PCI_DEVICE_ID_AMD_GOLAM_7450)) { |
1351 | shpc_base_offset = 0; /* amd shpc driver doesn't use this; assume 0 */ | 1391 | /* amd shpc driver doesn't use Base Offset; assume 0 */ |
1392 | ctrl->mmio_base = pci_resource_start(pdev, 0); | ||
1393 | ctrl->mmio_size = pci_resource_len(pdev, 0); | ||
1352 | } else { | 1394 | } else { |
1353 | if ((shpc_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC)) == 0) { | 1395 | ctrl->cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC); |
1354 | err("%s : shpc_cap_offset == 0\n", __FUNCTION__); | 1396 | if (!ctrl->cap_offset) { |
1397 | err("%s : cap_offset == 0\n", __FUNCTION__); | ||
1355 | goto abort_free_ctlr; | 1398 | goto abort_free_ctlr; |
1356 | } | 1399 | } |
1357 | dbg("%s: shpc_cap_offset = %x\n", __FUNCTION__, shpc_cap_offset); | 1400 | dbg("%s: cap_offset = %x\n", __FUNCTION__, ctrl->cap_offset); |
1358 | 1401 | ||
1359 | rc = pci_write_config_byte(pdev, (u8)shpc_cap_offset + DWORD_SELECT , BASE_OFFSET); | 1402 | rc = shpc_indirect_creg_read(ctrl, 0, &shpc_base_offset); |
1360 | if (rc) { | 1403 | if (rc) { |
1361 | err("%s : pci_word_config_byte failed\n", __FUNCTION__); | 1404 | err("%s: cannot read base_offset\n", __FUNCTION__); |
1362 | goto abort_free_ctlr; | 1405 | goto abort_free_ctlr; |
1363 | } | 1406 | } |
1364 | 1407 | ||
1365 | rc = pci_read_config_dword(pdev, (u8)shpc_cap_offset + DWORD_DATA, &shpc_base_offset); | 1408 | rc = shpc_indirect_creg_read(ctrl, 3, &tempdword); |
1366 | if (rc) { | 1409 | if (rc) { |
1367 | err("%s : pci_read_config_dword failed\n", __FUNCTION__); | 1410 | err("%s: cannot read slot config\n", __FUNCTION__); |
1368 | goto abort_free_ctlr; | 1411 | goto abort_free_ctlr; |
1369 | } | 1412 | } |
1413 | num_slots = tempdword & SLOT_NUM; | ||
1414 | dbg("%s: num_slots (indirect) %x\n", __FUNCTION__, num_slots); | ||
1370 | 1415 | ||
1371 | for (i = 0; i <= 14; i++) { | 1416 | for (i = 0; i < 9 + num_slots; i++) { |
1372 | rc = pci_write_config_byte(pdev, (u8)shpc_cap_offset + DWORD_SELECT , i); | 1417 | rc = shpc_indirect_creg_read(ctrl, i, &tempdword); |
1373 | if (rc) { | ||
1374 | err("%s : pci_word_config_byte failed\n", __FUNCTION__); | ||
1375 | goto abort_free_ctlr; | ||
1376 | } | ||
1377 | |||
1378 | rc = pci_read_config_dword(pdev, (u8)shpc_cap_offset + DWORD_DATA, &tempdword); | ||
1379 | if (rc) { | 1418 | if (rc) { |
1380 | err("%s : pci_read_config_dword failed\n", __FUNCTION__); | 1419 | err("%s: cannot read creg (index = %d)\n", |
1420 | __FUNCTION__, i); | ||
1381 | goto abort_free_ctlr; | 1421 | goto abort_free_ctlr; |
1382 | } | 1422 | } |
1383 | dbg("%s: offset %d: value %x\n", __FUNCTION__,i, | 1423 | dbg("%s: offset %d: value %x\n", __FUNCTION__,i, |
1384 | tempdword); | 1424 | tempdword); |
1385 | } | 1425 | } |
1426 | |||
1427 | ctrl->mmio_base = | ||
1428 | pci_resource_start(pdev, 0) + shpc_base_offset; | ||
1429 | ctrl->mmio_size = 0x24 + 0x4 * num_slots; | ||
1386 | } | 1430 | } |
1387 | 1431 | ||
1388 | if (first) { | 1432 | if (first) { |
@@ -1396,16 +1440,16 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) | |||
1396 | if (pci_enable_device(pdev)) | 1440 | if (pci_enable_device(pdev)) |
1397 | goto abort_free_ctlr; | 1441 | goto abort_free_ctlr; |
1398 | 1442 | ||
1399 | if (!request_mem_region(pci_resource_start(pdev, 0) + shpc_base_offset, pci_resource_len(pdev, 0), MY_NAME)) { | 1443 | if (!request_mem_region(ctrl->mmio_base, ctrl->mmio_size, MY_NAME)) { |
1400 | err("%s: cannot reserve MMIO region\n", __FUNCTION__); | 1444 | err("%s: cannot reserve MMIO region\n", __FUNCTION__); |
1401 | goto abort_free_ctlr; | 1445 | goto abort_free_ctlr; |
1402 | } | 1446 | } |
1403 | 1447 | ||
1404 | php_ctlr->creg = ioremap(pci_resource_start(pdev, 0) + shpc_base_offset, pci_resource_len(pdev, 0)); | 1448 | php_ctlr->creg = ioremap(ctrl->mmio_base, ctrl->mmio_size); |
1405 | if (!php_ctlr->creg) { | 1449 | if (!php_ctlr->creg) { |
1406 | err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__, pci_resource_len(pdev, 0), | 1450 | err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__, |
1407 | pci_resource_start(pdev, 0) + shpc_base_offset); | 1451 | ctrl->mmio_size, ctrl->mmio_base); |
1408 | release_mem_region(pci_resource_start(pdev, 0) + shpc_base_offset, pci_resource_len(pdev, 0)); | 1452 | release_mem_region(ctrl->mmio_base, ctrl->mmio_size); |
1409 | goto abort_free_ctlr; | 1453 | goto abort_free_ctlr; |
1410 | } | 1454 | } |
1411 | dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg); | 1455 | dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg); |