diff options
Diffstat (limited to 'drivers/pci/hotplug/shpchp_hpc.c')
-rw-r--r-- | drivers/pci/hotplug/shpchp_hpc.c | 82 |
1 files changed, 54 insertions, 28 deletions
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 4d8aee119134..83a5226ba9ed 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c | |||
@@ -302,21 +302,51 @@ static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int sec) | |||
302 | add_timer(&php_ctlr->int_poll_timer); | 302 | add_timer(&php_ctlr->int_poll_timer); |
303 | } | 303 | } |
304 | 304 | ||
305 | static inline int is_ctrl_busy(struct controller *ctrl) | ||
306 | { | ||
307 | u16 cmd_status = shpc_readw(ctrl, CMD_STATUS); | ||
308 | return cmd_status & 0x1; | ||
309 | } | ||
310 | |||
311 | /* | ||
312 | * Returns 1 if SHPC finishes executing a command within 1 sec, | ||
313 | * otherwise returns 0. | ||
314 | */ | ||
315 | static inline int shpc_poll_ctrl_busy(struct controller *ctrl) | ||
316 | { | ||
317 | int i; | ||
318 | |||
319 | if (!is_ctrl_busy(ctrl)) | ||
320 | return 1; | ||
321 | |||
322 | /* Check every 0.1 sec for a total of 1 sec */ | ||
323 | for (i = 0; i < 10; i++) { | ||
324 | msleep(100); | ||
325 | if (!is_ctrl_busy(ctrl)) | ||
326 | return 1; | ||
327 | } | ||
328 | |||
329 | return 0; | ||
330 | } | ||
331 | |||
305 | static inline int shpc_wait_cmd(struct controller *ctrl) | 332 | static inline int shpc_wait_cmd(struct controller *ctrl) |
306 | { | 333 | { |
307 | int retval = 0; | 334 | int retval = 0; |
308 | unsigned int timeout_msec = shpchp_poll_mode ? 2000 : 1000; | 335 | unsigned long timeout = msecs_to_jiffies(1000); |
309 | unsigned long timeout = msecs_to_jiffies(timeout_msec); | 336 | int rc; |
310 | int rc = wait_event_interruptible_timeout(ctrl->queue, | 337 | |
311 | !ctrl->cmd_busy, timeout); | 338 | if (shpchp_poll_mode) |
312 | if (!rc) { | 339 | rc = shpc_poll_ctrl_busy(ctrl); |
340 | else | ||
341 | rc = wait_event_interruptible_timeout(ctrl->queue, | ||
342 | !is_ctrl_busy(ctrl), timeout); | ||
343 | if (!rc && is_ctrl_busy(ctrl)) { | ||
313 | retval = -EIO; | 344 | retval = -EIO; |
314 | err("Command not completed in %d msec\n", timeout_msec); | 345 | err("Command not completed in 1000 msec\n"); |
315 | } else if (rc < 0) { | 346 | } else if (rc < 0) { |
316 | retval = -EINTR; | 347 | retval = -EINTR; |
317 | info("Command was interrupted by a signal\n"); | 348 | info("Command was interrupted by a signal\n"); |
318 | } | 349 | } |
319 | ctrl->cmd_busy = 0; | ||
320 | 350 | ||
321 | return retval; | 351 | return retval; |
322 | } | 352 | } |
@@ -327,26 +357,15 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) | |||
327 | u16 cmd_status; | 357 | u16 cmd_status; |
328 | int retval = 0; | 358 | int retval = 0; |
329 | u16 temp_word; | 359 | u16 temp_word; |
330 | int i; | ||
331 | 360 | ||
332 | DBG_ENTER_ROUTINE | 361 | DBG_ENTER_ROUTINE |
333 | 362 | ||
334 | mutex_lock(&slot->ctrl->cmd_lock); | 363 | mutex_lock(&slot->ctrl->cmd_lock); |
335 | 364 | ||
336 | for (i = 0; i < 10; i++) { | 365 | if (!shpc_poll_ctrl_busy(ctrl)) { |
337 | cmd_status = shpc_readw(ctrl, CMD_STATUS); | ||
338 | |||
339 | if (!(cmd_status & 0x1)) | ||
340 | break; | ||
341 | /* Check every 0.1 sec for a total of 1 sec*/ | ||
342 | msleep(100); | ||
343 | } | ||
344 | |||
345 | cmd_status = shpc_readw(ctrl, CMD_STATUS); | ||
346 | |||
347 | if (cmd_status & 0x1) { | ||
348 | /* After 1 sec and and the controller is still busy */ | 366 | /* After 1 sec and and the controller is still busy */ |
349 | err("%s : Controller is still busy after 1 sec.\n", __FUNCTION__); | 367 | err("%s : Controller is still busy after 1 sec.\n", |
368 | __FUNCTION__); | ||
350 | retval = -EBUSY; | 369 | retval = -EBUSY; |
351 | goto out; | 370 | goto out; |
352 | } | 371 | } |
@@ -358,7 +377,6 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) | |||
358 | /* To make sure the Controller Busy bit is 0 before we send out the | 377 | /* To make sure the Controller Busy bit is 0 before we send out the |
359 | * command. | 378 | * command. |
360 | */ | 379 | */ |
361 | slot->ctrl->cmd_busy = 1; | ||
362 | shpc_writew(ctrl, CMD, temp_word); | 380 | shpc_writew(ctrl, CMD, temp_word); |
363 | 381 | ||
364 | /* | 382 | /* |
@@ -908,7 +926,6 @@ static irqreturn_t shpc_isr(int irq, void *dev_id) | |||
908 | serr_int &= ~SERR_INTR_RSVDZ_MASK; | 926 | serr_int &= ~SERR_INTR_RSVDZ_MASK; |
909 | shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); | 927 | shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); |
910 | 928 | ||
911 | ctrl->cmd_busy = 0; | ||
912 | wake_up_interruptible(&ctrl->queue); | 929 | wake_up_interruptible(&ctrl->queue); |
913 | } | 930 | } |
914 | 931 | ||
@@ -1101,7 +1118,7 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) | |||
1101 | { | 1118 | { |
1102 | struct php_ctlr_state_s *php_ctlr, *p; | 1119 | struct php_ctlr_state_s *php_ctlr, *p; |
1103 | void *instance_id = ctrl; | 1120 | void *instance_id = ctrl; |
1104 | int rc, num_slots = 0; | 1121 | int rc = -1, num_slots = 0; |
1105 | u8 hp_slot; | 1122 | u8 hp_slot; |
1106 | u32 shpc_base_offset; | 1123 | u32 shpc_base_offset; |
1107 | u32 tempdword, slot_reg, slot_config; | 1124 | u32 tempdword, slot_reg, slot_config; |
@@ -1167,11 +1184,15 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) | |||
1167 | info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, | 1184 | info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, |
1168 | pdev->subsystem_device); | 1185 | pdev->subsystem_device); |
1169 | 1186 | ||
1170 | if (pci_enable_device(pdev)) | 1187 | rc = pci_enable_device(pdev); |
1188 | if (rc) { | ||
1189 | err("%s: pci_enable_device failed\n", __FUNCTION__); | ||
1171 | goto abort_free_ctlr; | 1190 | goto abort_free_ctlr; |
1191 | } | ||
1172 | 1192 | ||
1173 | if (!request_mem_region(ctrl->mmio_base, ctrl->mmio_size, MY_NAME)) { | 1193 | if (!request_mem_region(ctrl->mmio_base, ctrl->mmio_size, MY_NAME)) { |
1174 | err("%s: cannot reserve MMIO region\n", __FUNCTION__); | 1194 | err("%s: cannot reserve MMIO region\n", __FUNCTION__); |
1195 | rc = -1; | ||
1175 | goto abort_free_ctlr; | 1196 | goto abort_free_ctlr; |
1176 | } | 1197 | } |
1177 | 1198 | ||
@@ -1180,6 +1201,7 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) | |||
1180 | err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__, | 1201 | err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__, |
1181 | ctrl->mmio_size, ctrl->mmio_base); | 1202 | ctrl->mmio_size, ctrl->mmio_base); |
1182 | release_mem_region(ctrl->mmio_base, ctrl->mmio_size); | 1203 | release_mem_region(ctrl->mmio_base, ctrl->mmio_size); |
1204 | rc = -1; | ||
1183 | goto abort_free_ctlr; | 1205 | goto abort_free_ctlr; |
1184 | } | 1206 | } |
1185 | dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg); | 1207 | dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg); |
@@ -1282,8 +1304,10 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) | |||
1282 | */ | 1304 | */ |
1283 | if (atomic_add_return(1, &shpchp_num_controllers) == 1) { | 1305 | if (atomic_add_return(1, &shpchp_num_controllers) == 1) { |
1284 | shpchp_wq = create_singlethread_workqueue("shpchpd"); | 1306 | shpchp_wq = create_singlethread_workqueue("shpchpd"); |
1285 | if (!shpchp_wq) | 1307 | if (!shpchp_wq) { |
1286 | return -ENOMEM; | 1308 | rc = -ENOMEM; |
1309 | goto abort_free_ctlr; | ||
1310 | } | ||
1287 | } | 1311 | } |
1288 | 1312 | ||
1289 | /* | 1313 | /* |
@@ -1313,8 +1337,10 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) | |||
1313 | 1337 | ||
1314 | /* We end up here for the many possible ways to fail this API. */ | 1338 | /* We end up here for the many possible ways to fail this API. */ |
1315 | abort_free_ctlr: | 1339 | abort_free_ctlr: |
1340 | if (php_ctlr->creg) | ||
1341 | iounmap(php_ctlr->creg); | ||
1316 | kfree(php_ctlr); | 1342 | kfree(php_ctlr); |
1317 | abort: | 1343 | abort: |
1318 | DBG_LEAVE_ROUTINE | 1344 | DBG_LEAVE_ROUTINE |
1319 | return -1; | 1345 | return rc; |
1320 | } | 1346 | } |