diff options
author | Asai Thambi S P <asamymuthupa@micron.com> | 2013-04-03 10:23:07 -0400 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2013-04-03 15:54:01 -0400 |
commit | d0d096b1d8b97172cee953f1a00b7d4379d398da (patch) | |
tree | 9e47917fa7477960c5c239f88188ab45732bfbfe | |
parent | c678ef5286ddb5cf70384ad5af286b0afc9b73e1 (diff) |
mtip32xx: recovery from command timeout
To recover from command timeouts, reset the device. In addition
to that improved timeout handling of PIO commands.
Signed-off-by: Sam Bradshaw <sbradshaw@micron.com>
Signed-off-by: Asai Thambi S P <asamymuthupa@micron.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r-- | drivers/block/mtip32xx/mtip32xx.c | 177 |
1 files changed, 87 insertions, 90 deletions
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index 92250af84e7d..30f233634650 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c | |||
@@ -243,40 +243,31 @@ static inline void release_slot(struct mtip_port *port, int tag) | |||
243 | /* | 243 | /* |
244 | * Reset the HBA (without sleeping) | 244 | * Reset the HBA (without sleeping) |
245 | * | 245 | * |
246 | * Just like hba_reset, except does not call sleep, so can be | ||
247 | * run from interrupt/tasklet context. | ||
248 | * | ||
249 | * @dd Pointer to the driver data structure. | 246 | * @dd Pointer to the driver data structure. |
250 | * | 247 | * |
251 | * return value | 248 | * return value |
252 | * 0 The reset was successful. | 249 | * 0 The reset was successful. |
253 | * -1 The HBA Reset bit did not clear. | 250 | * -1 The HBA Reset bit did not clear. |
254 | */ | 251 | */ |
255 | static int hba_reset_nosleep(struct driver_data *dd) | 252 | static int mtip_hba_reset(struct driver_data *dd) |
256 | { | 253 | { |
257 | unsigned long timeout; | 254 | unsigned long timeout; |
258 | 255 | ||
259 | /* Chip quirk: quiesce any chip function */ | ||
260 | mdelay(10); | ||
261 | |||
262 | /* Set the reset bit */ | 256 | /* Set the reset bit */ |
263 | writel(HOST_RESET, dd->mmio + HOST_CTL); | 257 | writel(HOST_RESET, dd->mmio + HOST_CTL); |
264 | 258 | ||
265 | /* Flush */ | 259 | /* Flush */ |
266 | readl(dd->mmio + HOST_CTL); | 260 | readl(dd->mmio + HOST_CTL); |
267 | 261 | ||
268 | /* | 262 | /* Spin for up to 2 seconds, waiting for reset acknowledgement */ |
269 | * Wait 10ms then spin for up to 1 second | 263 | timeout = jiffies + msecs_to_jiffies(2000); |
270 | * waiting for reset acknowledgement | 264 | do { |
271 | */ | 265 | mdelay(10); |
272 | timeout = jiffies + msecs_to_jiffies(1000); | 266 | if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag)) |
273 | mdelay(10); | 267 | return -1; |
274 | while ((readl(dd->mmio + HOST_CTL) & HOST_RESET) | ||
275 | && time_before(jiffies, timeout)) | ||
276 | mdelay(1); | ||
277 | 268 | ||
278 | if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag)) | 269 | } while ((readl(dd->mmio + HOST_CTL) & HOST_RESET) |
279 | return -1; | 270 | && time_before(jiffies, timeout)); |
280 | 271 | ||
281 | if (readl(dd->mmio + HOST_CTL) & HOST_RESET) | 272 | if (readl(dd->mmio + HOST_CTL) & HOST_RESET) |
282 | return -1; | 273 | return -1; |
@@ -481,7 +472,7 @@ static void mtip_restart_port(struct mtip_port *port) | |||
481 | dev_warn(&port->dd->pdev->dev, | 472 | dev_warn(&port->dd->pdev->dev, |
482 | "PxCMD.CR not clear, escalating reset\n"); | 473 | "PxCMD.CR not clear, escalating reset\n"); |
483 | 474 | ||
484 | if (hba_reset_nosleep(port->dd)) | 475 | if (mtip_hba_reset(port->dd)) |
485 | dev_err(&port->dd->pdev->dev, | 476 | dev_err(&port->dd->pdev->dev, |
486 | "HBA reset escalation failed.\n"); | 477 | "HBA reset escalation failed.\n"); |
487 | 478 | ||
@@ -527,6 +518,26 @@ static void mtip_restart_port(struct mtip_port *port) | |||
527 | 518 | ||
528 | } | 519 | } |
529 | 520 | ||
521 | static int mtip_device_reset(struct driver_data *dd) | ||
522 | { | ||
523 | int rv = 0; | ||
524 | |||
525 | if (mtip_check_surprise_removal(dd->pdev)) | ||
526 | return 0; | ||
527 | |||
528 | if (mtip_hba_reset(dd) < 0) | ||
529 | rv = -EFAULT; | ||
530 | |||
531 | mdelay(1); | ||
532 | mtip_init_port(dd->port); | ||
533 | mtip_start_port(dd->port); | ||
534 | |||
535 | /* Enable interrupts on the HBA. */ | ||
536 | writel(readl(dd->mmio + HOST_CTL) | HOST_IRQ_EN, | ||
537 | dd->mmio + HOST_CTL); | ||
538 | return rv; | ||
539 | } | ||
540 | |||
530 | /* | 541 | /* |
531 | * Helper function for tag logging | 542 | * Helper function for tag logging |
532 | */ | 543 | */ |
@@ -632,7 +643,7 @@ static void mtip_timeout_function(unsigned long int data) | |||
632 | if (cmdto_cnt) { | 643 | if (cmdto_cnt) { |
633 | print_tags(port->dd, "timed out", tagaccum, cmdto_cnt); | 644 | print_tags(port->dd, "timed out", tagaccum, cmdto_cnt); |
634 | if (!test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) { | 645 | if (!test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) { |
635 | mtip_restart_port(port); | 646 | mtip_device_reset(port->dd); |
636 | wake_up_interruptible(&port->svc_wait); | 647 | wake_up_interruptible(&port->svc_wait); |
637 | } | 648 | } |
638 | clear_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags); | 649 | clear_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags); |
@@ -1283,11 +1294,11 @@ static int mtip_exec_internal_command(struct mtip_port *port, | |||
1283 | int rv = 0, ready2go = 1; | 1294 | int rv = 0, ready2go = 1; |
1284 | struct mtip_cmd *int_cmd = &port->commands[MTIP_TAG_INTERNAL]; | 1295 | struct mtip_cmd *int_cmd = &port->commands[MTIP_TAG_INTERNAL]; |
1285 | unsigned long to; | 1296 | unsigned long to; |
1297 | struct driver_data *dd = port->dd; | ||
1286 | 1298 | ||
1287 | /* Make sure the buffer is 8 byte aligned. This is asic specific. */ | 1299 | /* Make sure the buffer is 8 byte aligned. This is asic specific. */ |
1288 | if (buffer & 0x00000007) { | 1300 | if (buffer & 0x00000007) { |
1289 | dev_err(&port->dd->pdev->dev, | 1301 | dev_err(&dd->pdev->dev, "SG buffer is not 8 byte aligned\n"); |
1290 | "SG buffer is not 8 byte aligned\n"); | ||
1291 | return -EFAULT; | 1302 | return -EFAULT; |
1292 | } | 1303 | } |
1293 | 1304 | ||
@@ -1300,23 +1311,21 @@ static int mtip_exec_internal_command(struct mtip_port *port, | |||
1300 | mdelay(100); | 1311 | mdelay(100); |
1301 | } while (time_before(jiffies, to)); | 1312 | } while (time_before(jiffies, to)); |
1302 | if (!ready2go) { | 1313 | if (!ready2go) { |
1303 | dev_warn(&port->dd->pdev->dev, | 1314 | dev_warn(&dd->pdev->dev, |
1304 | "Internal cmd active. new cmd [%02X]\n", fis->command); | 1315 | "Internal cmd active. new cmd [%02X]\n", fis->command); |
1305 | return -EBUSY; | 1316 | return -EBUSY; |
1306 | } | 1317 | } |
1307 | set_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags); | 1318 | set_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags); |
1308 | port->ic_pause_timer = 0; | 1319 | port->ic_pause_timer = 0; |
1309 | 1320 | ||
1310 | if (fis->command == ATA_CMD_SEC_ERASE_UNIT) | 1321 | clear_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags); |
1311 | clear_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags); | 1322 | clear_bit(MTIP_PF_DM_ACTIVE_BIT, &port->flags); |
1312 | else if (fis->command == ATA_CMD_DOWNLOAD_MICRO) | ||
1313 | clear_bit(MTIP_PF_DM_ACTIVE_BIT, &port->flags); | ||
1314 | 1323 | ||
1315 | if (atomic == GFP_KERNEL) { | 1324 | if (atomic == GFP_KERNEL) { |
1316 | if (fis->command != ATA_CMD_STANDBYNOW1) { | 1325 | if (fis->command != ATA_CMD_STANDBYNOW1) { |
1317 | /* wait for io to complete if non atomic */ | 1326 | /* wait for io to complete if non atomic */ |
1318 | if (mtip_quiesce_io(port, 5000) < 0) { | 1327 | if (mtip_quiesce_io(port, 5000) < 0) { |
1319 | dev_warn(&port->dd->pdev->dev, | 1328 | dev_warn(&dd->pdev->dev, |
1320 | "Failed to quiesce IO\n"); | 1329 | "Failed to quiesce IO\n"); |
1321 | release_slot(port, MTIP_TAG_INTERNAL); | 1330 | release_slot(port, MTIP_TAG_INTERNAL); |
1322 | clear_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags); | 1331 | clear_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags); |
@@ -1361,58 +1370,84 @@ static int mtip_exec_internal_command(struct mtip_port *port, | |||
1361 | /* Issue the command to the hardware */ | 1370 | /* Issue the command to the hardware */ |
1362 | mtip_issue_non_ncq_command(port, MTIP_TAG_INTERNAL); | 1371 | mtip_issue_non_ncq_command(port, MTIP_TAG_INTERNAL); |
1363 | 1372 | ||
1364 | /* Poll if atomic, wait_for_completion otherwise */ | ||
1365 | if (atomic == GFP_KERNEL) { | 1373 | if (atomic == GFP_KERNEL) { |
1366 | /* Wait for the command to complete or timeout. */ | 1374 | /* Wait for the command to complete or timeout. */ |
1367 | if (wait_for_completion_timeout( | 1375 | if (wait_for_completion_interruptible_timeout( |
1368 | &wait, | 1376 | &wait, |
1369 | msecs_to_jiffies(timeout)) == 0) { | 1377 | msecs_to_jiffies(timeout)) <= 0) { |
1370 | dev_err(&port->dd->pdev->dev, | 1378 | if (rv == -ERESTARTSYS) { /* interrupted */ |
1371 | "Internal command did not complete [%d] " | 1379 | dev_err(&dd->pdev->dev, |
1372 | "within timeout of %lu ms\n", | 1380 | "Internal command [%02X] was interrupted after %lu ms\n", |
1373 | atomic, timeout); | 1381 | fis->command, timeout); |
1374 | if (mtip_check_surprise_removal(port->dd->pdev) || | 1382 | rv = -EINTR; |
1383 | goto exec_ic_exit; | ||
1384 | } else if (rv == 0) /* timeout */ | ||
1385 | dev_err(&dd->pdev->dev, | ||
1386 | "Internal command did not complete [%02X] within timeout of %lu ms\n", | ||
1387 | fis->command, timeout); | ||
1388 | else | ||
1389 | dev_err(&dd->pdev->dev, | ||
1390 | "Internal command [%02X] wait returned code [%d] after %lu ms - unhandled\n", | ||
1391 | fis->command, rv, timeout); | ||
1392 | |||
1393 | if (mtip_check_surprise_removal(dd->pdev) || | ||
1375 | test_bit(MTIP_DDF_REMOVE_PENDING_BIT, | 1394 | test_bit(MTIP_DDF_REMOVE_PENDING_BIT, |
1376 | &port->dd->dd_flag)) { | 1395 | &dd->dd_flag)) { |
1396 | dev_err(&dd->pdev->dev, | ||
1397 | "Internal command [%02X] wait returned due to SR\n", | ||
1398 | fis->command); | ||
1377 | rv = -ENXIO; | 1399 | rv = -ENXIO; |
1378 | goto exec_ic_exit; | 1400 | goto exec_ic_exit; |
1379 | } | 1401 | } |
1402 | mtip_device_reset(dd); /* recover from timeout issue */ | ||
1380 | rv = -EAGAIN; | 1403 | rv = -EAGAIN; |
1404 | goto exec_ic_exit; | ||
1381 | } | 1405 | } |
1382 | } else { | 1406 | } else { |
1407 | u32 hba_stat, port_stat; | ||
1408 | |||
1383 | /* Spin for <timeout> checking if command still outstanding */ | 1409 | /* Spin for <timeout> checking if command still outstanding */ |
1384 | timeout = jiffies + msecs_to_jiffies(timeout); | 1410 | timeout = jiffies + msecs_to_jiffies(timeout); |
1385 | while ((readl(port->cmd_issue[MTIP_TAG_INTERNAL]) | 1411 | while ((readl(port->cmd_issue[MTIP_TAG_INTERNAL]) |
1386 | & (1 << MTIP_TAG_INTERNAL)) | 1412 | & (1 << MTIP_TAG_INTERNAL)) |
1387 | && time_before(jiffies, timeout)) { | 1413 | && time_before(jiffies, timeout)) { |
1388 | if (mtip_check_surprise_removal(port->dd->pdev)) { | 1414 | if (mtip_check_surprise_removal(dd->pdev)) { |
1389 | rv = -ENXIO; | 1415 | rv = -ENXIO; |
1390 | goto exec_ic_exit; | 1416 | goto exec_ic_exit; |
1391 | } | 1417 | } |
1392 | if ((fis->command != ATA_CMD_STANDBYNOW1) && | 1418 | if ((fis->command != ATA_CMD_STANDBYNOW1) && |
1393 | test_bit(MTIP_DDF_REMOVE_PENDING_BIT, | 1419 | test_bit(MTIP_DDF_REMOVE_PENDING_BIT, |
1394 | &port->dd->dd_flag)) { | 1420 | &dd->dd_flag)) { |
1395 | rv = -ENXIO; | 1421 | rv = -ENXIO; |
1396 | goto exec_ic_exit; | 1422 | goto exec_ic_exit; |
1397 | } | 1423 | } |
1398 | if (readl(port->mmio + PORT_IRQ_STAT) & PORT_IRQ_ERR) { | 1424 | port_stat = readl(port->mmio + PORT_IRQ_STAT); |
1399 | atomic_inc(&int_cmd->active); /* error */ | 1425 | if (!port_stat) |
1400 | break; | 1426 | continue; |
1427 | |||
1428 | if (port_stat & PORT_IRQ_ERR) { | ||
1429 | dev_err(&dd->pdev->dev, | ||
1430 | "Internal command [%02X] failed\n", | ||
1431 | fis->command); | ||
1432 | mtip_device_reset(dd); | ||
1433 | rv = -EIO; | ||
1434 | goto exec_ic_exit; | ||
1435 | } else { | ||
1436 | writel(port_stat, port->mmio + PORT_IRQ_STAT); | ||
1437 | hba_stat = readl(dd->mmio + HOST_IRQ_STAT); | ||
1438 | if (hba_stat) | ||
1439 | writel(hba_stat, | ||
1440 | dd->mmio + HOST_IRQ_STAT); | ||
1401 | } | 1441 | } |
1442 | break; | ||
1402 | } | 1443 | } |
1403 | } | 1444 | } |
1404 | 1445 | ||
1405 | if (atomic_read(&int_cmd->active) > 1) { | ||
1406 | dev_err(&port->dd->pdev->dev, | ||
1407 | "Internal command [%02X] failed\n", fis->command); | ||
1408 | rv = -EIO; | ||
1409 | } | ||
1410 | if (readl(port->cmd_issue[MTIP_TAG_INTERNAL]) | 1446 | if (readl(port->cmd_issue[MTIP_TAG_INTERNAL]) |
1411 | & (1 << MTIP_TAG_INTERNAL)) { | 1447 | & (1 << MTIP_TAG_INTERNAL)) { |
1412 | rv = -ENXIO; | 1448 | rv = -ENXIO; |
1413 | if (!test_bit(MTIP_DDF_REMOVE_PENDING_BIT, | 1449 | if (!test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag)) { |
1414 | &port->dd->dd_flag)) { | 1450 | mtip_device_reset(dd); |
1415 | mtip_restart_port(port); | ||
1416 | rv = -EAGAIN; | 1451 | rv = -EAGAIN; |
1417 | } | 1452 | } |
1418 | } | 1453 | } |
@@ -1724,7 +1759,8 @@ static int mtip_get_smart_attr(struct mtip_port *port, unsigned int id, | |||
1724 | * -EINVAL Invalid parameters passed in, trim not supported | 1759 | * -EINVAL Invalid parameters passed in, trim not supported |
1725 | * -EIO Error submitting trim request to hw | 1760 | * -EIO Error submitting trim request to hw |
1726 | */ | 1761 | */ |
1727 | static int mtip_send_trim(struct driver_data *dd, unsigned int lba, unsigned int len) | 1762 | static int mtip_send_trim(struct driver_data *dd, unsigned int lba, |
1763 | unsigned int len) | ||
1728 | { | 1764 | { |
1729 | int i, rv = 0; | 1765 | int i, rv = 0; |
1730 | u64 tlba, tlen, sect_left; | 1766 | u64 tlba, tlen, sect_left; |
@@ -1811,45 +1847,6 @@ static bool mtip_hw_get_capacity(struct driver_data *dd, sector_t *sectors) | |||
1811 | } | 1847 | } |
1812 | 1848 | ||
1813 | /* | 1849 | /* |
1814 | * Reset the HBA. | ||
1815 | * | ||
1816 | * Resets the HBA by setting the HBA Reset bit in the Global | ||
1817 | * HBA Control register. After setting the HBA Reset bit the | ||
1818 | * function waits for 1 second before reading the HBA Reset | ||
1819 | * bit to make sure it has cleared. If HBA Reset is not clear | ||
1820 | * an error is returned. Cannot be used in non-blockable | ||
1821 | * context. | ||
1822 | * | ||
1823 | * @dd Pointer to the driver data structure. | ||
1824 | * | ||
1825 | * return value | ||
1826 | * 0 The reset was successful. | ||
1827 | * -1 The HBA Reset bit did not clear. | ||
1828 | */ | ||
1829 | static int mtip_hba_reset(struct driver_data *dd) | ||
1830 | { | ||
1831 | mtip_deinit_port(dd->port); | ||
1832 | |||
1833 | /* Set the reset bit */ | ||
1834 | writel(HOST_RESET, dd->mmio + HOST_CTL); | ||
1835 | |||
1836 | /* Flush */ | ||
1837 | readl(dd->mmio + HOST_CTL); | ||
1838 | |||
1839 | /* Wait for reset to clear */ | ||
1840 | ssleep(1); | ||
1841 | |||
1842 | /* Check the bit has cleared */ | ||
1843 | if (readl(dd->mmio + HOST_CTL) & HOST_RESET) { | ||
1844 | dev_err(&dd->pdev->dev, | ||
1845 | "Reset bit did not clear.\n"); | ||
1846 | return -1; | ||
1847 | } | ||
1848 | |||
1849 | return 0; | ||
1850 | } | ||
1851 | |||
1852 | /* | ||
1853 | * Display the identify command data. | 1850 | * Display the identify command data. |
1854 | * | 1851 | * |
1855 | * @port Pointer to the port data structure. | 1852 | * @port Pointer to the port data structure. |