diff options
Diffstat (limited to 'drivers/pci/hotplug/pciehp_hpc.c')
-rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 314 |
1 files changed, 202 insertions, 112 deletions
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 06d025b8b13f..6eba9b2cfb90 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
@@ -636,15 +636,57 @@ static int hpc_power_on_slot(struct slot * slot) | |||
636 | return retval; | 636 | return retval; |
637 | } | 637 | } |
638 | 638 | ||
639 | static inline int pcie_mask_bad_dllp(struct controller *ctrl) | ||
640 | { | ||
641 | struct pci_dev *dev = ctrl->pci_dev; | ||
642 | int pos; | ||
643 | u32 reg; | ||
644 | |||
645 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | ||
646 | if (!pos) | ||
647 | return 0; | ||
648 | pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, ®); | ||
649 | if (reg & PCI_ERR_COR_BAD_DLLP) | ||
650 | return 0; | ||
651 | reg |= PCI_ERR_COR_BAD_DLLP; | ||
652 | pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg); | ||
653 | return 1; | ||
654 | } | ||
655 | |||
656 | static inline void pcie_unmask_bad_dllp(struct controller *ctrl) | ||
657 | { | ||
658 | struct pci_dev *dev = ctrl->pci_dev; | ||
659 | u32 reg; | ||
660 | int pos; | ||
661 | |||
662 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | ||
663 | if (!pos) | ||
664 | return; | ||
665 | pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, ®); | ||
666 | if (!(reg & PCI_ERR_COR_BAD_DLLP)) | ||
667 | return; | ||
668 | reg &= ~PCI_ERR_COR_BAD_DLLP; | ||
669 | pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg); | ||
670 | } | ||
671 | |||
639 | static int hpc_power_off_slot(struct slot * slot) | 672 | static int hpc_power_off_slot(struct slot * slot) |
640 | { | 673 | { |
641 | struct controller *ctrl = slot->ctrl; | 674 | struct controller *ctrl = slot->ctrl; |
642 | u16 slot_cmd; | 675 | u16 slot_cmd; |
643 | u16 cmd_mask; | 676 | u16 cmd_mask; |
644 | int retval = 0; | 677 | int retval = 0; |
678 | int changed; | ||
645 | 679 | ||
646 | dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot); | 680 | dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot); |
647 | 681 | ||
682 | /* | ||
683 | * Set Bad DLLP Mask bit in Correctable Error Mask | ||
684 | * Register. This is the workaround against Bad DLLP error | ||
685 | * that sometimes happens during turning power off the slot | ||
686 | * which conforms to PCI Express 1.0a spec. | ||
687 | */ | ||
688 | changed = pcie_mask_bad_dllp(ctrl); | ||
689 | |||
648 | slot_cmd = POWER_OFF; | 690 | slot_cmd = POWER_OFF; |
649 | cmd_mask = PWR_CTRL; | 691 | cmd_mask = PWR_CTRL; |
650 | /* | 692 | /* |
@@ -674,6 +716,16 @@ static int hpc_power_off_slot(struct slot * slot) | |||
674 | dbg("%s: SLOTCTRL %x write cmd %x\n", | 716 | dbg("%s: SLOTCTRL %x write cmd %x\n", |
675 | __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd); | 717 | __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd); |
676 | 718 | ||
719 | /* | ||
720 | * After turning power off, we must wait for at least 1 second | ||
721 | * before taking any action that relies on power having been | ||
722 | * removed from the slot/adapter. | ||
723 | */ | ||
724 | msleep(1000); | ||
725 | |||
726 | if (changed) | ||
727 | pcie_unmask_bad_dllp(ctrl); | ||
728 | |||
677 | return retval; | 729 | return retval; |
678 | } | 730 | } |
679 | 731 | ||
@@ -1067,13 +1119,143 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev) | |||
1067 | } | 1119 | } |
1068 | #endif | 1120 | #endif |
1069 | 1121 | ||
1070 | int pcie_init(struct controller * ctrl, struct pcie_device *dev) | 1122 | static int pcie_init_hardware_part1(struct controller *ctrl, |
1123 | struct pcie_device *dev) | ||
1124 | { | ||
1125 | int rc; | ||
1126 | u16 temp_word; | ||
1127 | u32 slot_cap; | ||
1128 | u16 slot_status; | ||
1129 | |||
1130 | rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap); | ||
1131 | if (rc) { | ||
1132 | err("%s: Cannot read SLOTCAP register\n", __FUNCTION__); | ||
1133 | return -1; | ||
1134 | } | ||
1135 | |||
1136 | /* Mask Hot-plug Interrupt Enable */ | ||
1137 | rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); | ||
1138 | if (rc) { | ||
1139 | err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); | ||
1140 | return -1; | ||
1141 | } | ||
1142 | |||
1143 | dbg("%s: SLOTCTRL %x value read %x\n", | ||
1144 | __FUNCTION__, ctrl->cap_base + SLOTCTRL, temp_word); | ||
1145 | temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | | ||
1146 | 0x00; | ||
1147 | |||
1148 | rc = pciehp_writew(ctrl, SLOTCTRL, temp_word); | ||
1149 | if (rc) { | ||
1150 | err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__); | ||
1151 | return -1; | ||
1152 | } | ||
1153 | |||
1154 | rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); | ||
1155 | if (rc) { | ||
1156 | err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__); | ||
1157 | return -1; | ||
1158 | } | ||
1159 | |||
1160 | temp_word = 0x1F; /* Clear all events */ | ||
1161 | rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word); | ||
1162 | if (rc) { | ||
1163 | err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__); | ||
1164 | return -1; | ||
1165 | } | ||
1166 | return 0; | ||
1167 | } | ||
1168 | |||
1169 | int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev) | ||
1071 | { | 1170 | { |
1072 | int rc; | 1171 | int rc; |
1073 | u16 temp_word; | 1172 | u16 temp_word; |
1074 | u16 cap_reg; | ||
1075 | u16 intr_enable = 0; | 1173 | u16 intr_enable = 0; |
1076 | u32 slot_cap; | 1174 | u32 slot_cap; |
1175 | u16 slot_status; | ||
1176 | |||
1177 | rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); | ||
1178 | if (rc) { | ||
1179 | err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); | ||
1180 | goto abort; | ||
1181 | } | ||
1182 | |||
1183 | intr_enable = intr_enable | PRSN_DETECT_ENABLE; | ||
1184 | |||
1185 | rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap); | ||
1186 | if (rc) { | ||
1187 | err("%s: Cannot read SLOTCAP register\n", __FUNCTION__); | ||
1188 | goto abort; | ||
1189 | } | ||
1190 | |||
1191 | if (ATTN_BUTTN(slot_cap)) | ||
1192 | intr_enable = intr_enable | ATTN_BUTTN_ENABLE; | ||
1193 | |||
1194 | if (POWER_CTRL(slot_cap)) | ||
1195 | intr_enable = intr_enable | PWR_FAULT_DETECT_ENABLE; | ||
1196 | |||
1197 | if (MRL_SENS(slot_cap)) | ||
1198 | intr_enable = intr_enable | MRL_DETECT_ENABLE; | ||
1199 | |||
1200 | temp_word = (temp_word & ~intr_enable) | intr_enable; | ||
1201 | |||
1202 | if (pciehp_poll_mode) { | ||
1203 | temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x0; | ||
1204 | } else { | ||
1205 | temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE; | ||
1206 | } | ||
1207 | |||
1208 | /* | ||
1209 | * Unmask Hot-plug Interrupt Enable for the interrupt | ||
1210 | * notification mechanism case. | ||
1211 | */ | ||
1212 | rc = pciehp_writew(ctrl, SLOTCTRL, temp_word); | ||
1213 | if (rc) { | ||
1214 | err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__); | ||
1215 | goto abort; | ||
1216 | } | ||
1217 | rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); | ||
1218 | if (rc) { | ||
1219 | err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__); | ||
1220 | goto abort_disable_intr; | ||
1221 | } | ||
1222 | |||
1223 | temp_word = 0x1F; /* Clear all events */ | ||
1224 | rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word); | ||
1225 | if (rc) { | ||
1226 | err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__); | ||
1227 | goto abort_disable_intr; | ||
1228 | } | ||
1229 | |||
1230 | if (pciehp_force) { | ||
1231 | dbg("Bypassing BIOS check for pciehp use on %s\n", | ||
1232 | pci_name(ctrl->pci_dev)); | ||
1233 | } else { | ||
1234 | rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev); | ||
1235 | if (rc) | ||
1236 | goto abort_disable_intr; | ||
1237 | } | ||
1238 | |||
1239 | return 0; | ||
1240 | |||
1241 | /* We end up here for the many possible ways to fail this API. */ | ||
1242 | abort_disable_intr: | ||
1243 | rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); | ||
1244 | if (!rc) { | ||
1245 | temp_word &= ~(intr_enable | HP_INTR_ENABLE); | ||
1246 | rc = pciehp_writew(ctrl, SLOTCTRL, temp_word); | ||
1247 | } | ||
1248 | if (rc) | ||
1249 | err("%s : disabling interrupts failed\n", __FUNCTION__); | ||
1250 | abort: | ||
1251 | return -1; | ||
1252 | } | ||
1253 | |||
1254 | int pcie_init(struct controller *ctrl, struct pcie_device *dev) | ||
1255 | { | ||
1256 | int rc; | ||
1257 | u16 cap_reg; | ||
1258 | u32 slot_cap; | ||
1077 | int cap_base; | 1259 | int cap_base; |
1078 | u16 slot_status, slot_ctrl; | 1260 | u16 slot_status, slot_ctrl; |
1079 | struct pci_dev *pdev; | 1261 | struct pci_dev *pdev; |
@@ -1084,9 +1266,10 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) | |||
1084 | dbg("%s: hotplug controller vendor id 0x%x device id 0x%x\n", | 1266 | dbg("%s: hotplug controller vendor id 0x%x device id 0x%x\n", |
1085 | __FUNCTION__, pdev->vendor, pdev->device); | 1267 | __FUNCTION__, pdev->vendor, pdev->device); |
1086 | 1268 | ||
1087 | if ((cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP)) == 0) { | 1269 | cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP); |
1270 | if (cap_base == 0) { | ||
1088 | dbg("%s: Can't find PCI_CAP_ID_EXP (0x10)\n", __FUNCTION__); | 1271 | dbg("%s: Can't find PCI_CAP_ID_EXP (0x10)\n", __FUNCTION__); |
1089 | goto abort_free_ctlr; | 1272 | goto abort; |
1090 | } | 1273 | } |
1091 | 1274 | ||
1092 | ctrl->cap_base = cap_base; | 1275 | ctrl->cap_base = cap_base; |
@@ -1096,7 +1279,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) | |||
1096 | rc = pciehp_readw(ctrl, CAPREG, &cap_reg); | 1279 | rc = pciehp_readw(ctrl, CAPREG, &cap_reg); |
1097 | if (rc) { | 1280 | if (rc) { |
1098 | err("%s: Cannot read CAPREG register\n", __FUNCTION__); | 1281 | err("%s: Cannot read CAPREG register\n", __FUNCTION__); |
1099 | goto abort_free_ctlr; | 1282 | goto abort; |
1100 | } | 1283 | } |
1101 | dbg("%s: CAPREG offset %x cap_reg %x\n", | 1284 | dbg("%s: CAPREG offset %x cap_reg %x\n", |
1102 | __FUNCTION__, ctrl->cap_base + CAPREG, cap_reg); | 1285 | __FUNCTION__, ctrl->cap_base + CAPREG, cap_reg); |
@@ -1106,26 +1289,26 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) | |||
1106 | && ((cap_reg & DEV_PORT_TYPE) != 0x0060))) { | 1289 | && ((cap_reg & DEV_PORT_TYPE) != 0x0060))) { |
1107 | dbg("%s : This is not a root port or the port is not " | 1290 | dbg("%s : This is not a root port or the port is not " |
1108 | "connected to a slot\n", __FUNCTION__); | 1291 | "connected to a slot\n", __FUNCTION__); |
1109 | goto abort_free_ctlr; | 1292 | goto abort; |
1110 | } | 1293 | } |
1111 | 1294 | ||
1112 | rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap); | 1295 | rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap); |
1113 | if (rc) { | 1296 | if (rc) { |
1114 | err("%s: Cannot read SLOTCAP register\n", __FUNCTION__); | 1297 | err("%s: Cannot read SLOTCAP register\n", __FUNCTION__); |
1115 | goto abort_free_ctlr; | 1298 | goto abort; |
1116 | } | 1299 | } |
1117 | dbg("%s: SLOTCAP offset %x slot_cap %x\n", | 1300 | dbg("%s: SLOTCAP offset %x slot_cap %x\n", |
1118 | __FUNCTION__, ctrl->cap_base + SLOTCAP, slot_cap); | 1301 | __FUNCTION__, ctrl->cap_base + SLOTCAP, slot_cap); |
1119 | 1302 | ||
1120 | if (!(slot_cap & HP_CAP)) { | 1303 | if (!(slot_cap & HP_CAP)) { |
1121 | dbg("%s : This slot is not hot-plug capable\n", __FUNCTION__); | 1304 | dbg("%s : This slot is not hot-plug capable\n", __FUNCTION__); |
1122 | goto abort_free_ctlr; | 1305 | goto abort; |
1123 | } | 1306 | } |
1124 | /* For debugging purpose */ | 1307 | /* For debugging purpose */ |
1125 | rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); | 1308 | rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); |
1126 | if (rc) { | 1309 | if (rc) { |
1127 | err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__); | 1310 | err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__); |
1128 | goto abort_free_ctlr; | 1311 | goto abort; |
1129 | } | 1312 | } |
1130 | dbg("%s: SLOTSTATUS offset %x slot_status %x\n", | 1313 | dbg("%s: SLOTSTATUS offset %x slot_status %x\n", |
1131 | __FUNCTION__, ctrl->cap_base + SLOTSTATUS, slot_status); | 1314 | __FUNCTION__, ctrl->cap_base + SLOTSTATUS, slot_status); |
@@ -1133,7 +1316,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) | |||
1133 | rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); | 1316 | rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); |
1134 | if (rc) { | 1317 | if (rc) { |
1135 | err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); | 1318 | err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); |
1136 | goto abort_free_ctlr; | 1319 | goto abort; |
1137 | } | 1320 | } |
1138 | dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n", | 1321 | dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n", |
1139 | __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl); | 1322 | __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl); |
@@ -1161,36 +1344,9 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) | |||
1161 | ctrl->first_slot = slot_cap >> 19; | 1344 | ctrl->first_slot = slot_cap >> 19; |
1162 | ctrl->ctrlcap = slot_cap & 0x0000007f; | 1345 | ctrl->ctrlcap = slot_cap & 0x0000007f; |
1163 | 1346 | ||
1164 | /* Mask Hot-plug Interrupt Enable */ | 1347 | rc = pcie_init_hardware_part1(ctrl, dev); |
1165 | rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); | 1348 | if (rc) |
1166 | if (rc) { | 1349 | goto abort; |
1167 | err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); | ||
1168 | goto abort_free_ctlr; | ||
1169 | } | ||
1170 | |||
1171 | dbg("%s: SLOTCTRL %x value read %x\n", | ||
1172 | __FUNCTION__, ctrl->cap_base + SLOTCTRL, temp_word); | ||
1173 | temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | | ||
1174 | 0x00; | ||
1175 | |||
1176 | rc = pciehp_writew(ctrl, SLOTCTRL, temp_word); | ||
1177 | if (rc) { | ||
1178 | err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__); | ||
1179 | goto abort_free_ctlr; | ||
1180 | } | ||
1181 | |||
1182 | rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); | ||
1183 | if (rc) { | ||
1184 | err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__); | ||
1185 | goto abort_free_ctlr; | ||
1186 | } | ||
1187 | |||
1188 | temp_word = 0x1F; /* Clear all events */ | ||
1189 | rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word); | ||
1190 | if (rc) { | ||
1191 | err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__); | ||
1192 | goto abort_free_ctlr; | ||
1193 | } | ||
1194 | 1350 | ||
1195 | if (pciehp_poll_mode) { | 1351 | if (pciehp_poll_mode) { |
1196 | /* Install interrupt polling timer. Start with 10 sec delay */ | 1352 | /* Install interrupt polling timer. Start with 10 sec delay */ |
@@ -1206,7 +1362,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) | |||
1206 | if (rc) { | 1362 | if (rc) { |
1207 | err("Can't get irq %d for the hotplug controller\n", | 1363 | err("Can't get irq %d for the hotplug controller\n", |
1208 | ctrl->pci_dev->irq); | 1364 | ctrl->pci_dev->irq); |
1209 | goto abort_free_ctlr; | 1365 | goto abort; |
1210 | } | 1366 | } |
1211 | } | 1367 | } |
1212 | dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number, | 1368 | dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number, |
@@ -1224,82 +1380,16 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) | |||
1224 | } | 1380 | } |
1225 | } | 1381 | } |
1226 | 1382 | ||
1227 | rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); | 1383 | rc = pcie_init_hardware_part2(ctrl, dev); |
1228 | if (rc) { | 1384 | if (rc == 0) { |
1229 | err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); | 1385 | ctrl->hpc_ops = &pciehp_hpc_ops; |
1230 | goto abort_free_irq; | 1386 | return 0; |
1231 | } | 1387 | } |
1232 | |||
1233 | intr_enable = intr_enable | PRSN_DETECT_ENABLE; | ||
1234 | |||
1235 | if (ATTN_BUTTN(slot_cap)) | ||
1236 | intr_enable = intr_enable | ATTN_BUTTN_ENABLE; | ||
1237 | |||
1238 | if (POWER_CTRL(slot_cap)) | ||
1239 | intr_enable = intr_enable | PWR_FAULT_DETECT_ENABLE; | ||
1240 | |||
1241 | if (MRL_SENS(slot_cap)) | ||
1242 | intr_enable = intr_enable | MRL_DETECT_ENABLE; | ||
1243 | |||
1244 | temp_word = (temp_word & ~intr_enable) | intr_enable; | ||
1245 | |||
1246 | if (pciehp_poll_mode) { | ||
1247 | temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x0; | ||
1248 | } else { | ||
1249 | temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE; | ||
1250 | } | ||
1251 | |||
1252 | /* | ||
1253 | * Unmask Hot-plug Interrupt Enable for the interrupt | ||
1254 | * notification mechanism case. | ||
1255 | */ | ||
1256 | rc = pciehp_writew(ctrl, SLOTCTRL, temp_word); | ||
1257 | if (rc) { | ||
1258 | err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__); | ||
1259 | goto abort_free_irq; | ||
1260 | } | ||
1261 | rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); | ||
1262 | if (rc) { | ||
1263 | err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__); | ||
1264 | goto abort_disable_intr; | ||
1265 | } | ||
1266 | |||
1267 | temp_word = 0x1F; /* Clear all events */ | ||
1268 | rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word); | ||
1269 | if (rc) { | ||
1270 | err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__); | ||
1271 | goto abort_disable_intr; | ||
1272 | } | ||
1273 | |||
1274 | if (pciehp_force) { | ||
1275 | dbg("Bypassing BIOS check for pciehp use on %s\n", | ||
1276 | pci_name(ctrl->pci_dev)); | ||
1277 | } else { | ||
1278 | rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev); | ||
1279 | if (rc) | ||
1280 | goto abort_disable_intr; | ||
1281 | } | ||
1282 | |||
1283 | ctrl->hpc_ops = &pciehp_hpc_ops; | ||
1284 | |||
1285 | return 0; | ||
1286 | |||
1287 | /* We end up here for the many possible ways to fail this API. */ | ||
1288 | abort_disable_intr: | ||
1289 | rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); | ||
1290 | if (!rc) { | ||
1291 | temp_word &= ~(intr_enable | HP_INTR_ENABLE); | ||
1292 | rc = pciehp_writew(ctrl, SLOTCTRL, temp_word); | ||
1293 | } | ||
1294 | if (rc) | ||
1295 | err("%s : disabling interrupts failed\n", __FUNCTION__); | ||
1296 | |||
1297 | abort_free_irq: | 1388 | abort_free_irq: |
1298 | if (pciehp_poll_mode) | 1389 | if (pciehp_poll_mode) |
1299 | del_timer_sync(&ctrl->poll_timer); | 1390 | del_timer_sync(&ctrl->poll_timer); |
1300 | else | 1391 | else |
1301 | free_irq(ctrl->pci_dev->irq, ctrl); | 1392 | free_irq(ctrl->pci_dev->irq, ctrl); |
1302 | 1393 | abort: | |
1303 | abort_free_ctlr: | ||
1304 | return -1; | 1394 | return -1; |
1305 | } | 1395 | } |