diff options
| author | Asai Thambi S P <asamymuthupa@micron.com> | 2014-05-20 13:48:56 -0400 |
|---|---|---|
| committer | Jens Axboe <axboe@fb.com> | 2014-05-20 13:51:30 -0400 |
| commit | 9b204fbf0987748ec6cc4a3cde0064ecf42accd0 (patch) | |
| tree | 58c669aefeaef7ac581617e712ca6ecc768f5e20 /drivers/block/mtip32xx | |
| parent | 0c29e93eae8a7f703e463c7b38ebc85d8718cae2 (diff) | |
mtip32xx: move error handling to service thread
Move error handling to service thread, and use mtip_set_timeout()
to set timeouts for HDIO_DRIVE_TASK and HDIO_DRIVE_CMD IOCTL commands.
Signed-off-by: Selvan Mani <smani@micron.com>
Signed-off-by: Asai Thambi S P <asamymuthupa@micron.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'drivers/block/mtip32xx')
| -rw-r--r-- | drivers/block/mtip32xx/mtip32xx.c | 71 | ||||
| -rw-r--r-- | drivers/block/mtip32xx/mtip32xx.h | 8 |
2 files changed, 53 insertions, 26 deletions
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index 4efc676aa5f4..ae331ab4a451 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c | |||
| @@ -620,7 +620,6 @@ static void mtip_handle_tfe(struct driver_data *dd) | |||
| 620 | 620 | ||
| 621 | port = dd->port; | 621 | port = dd->port; |
| 622 | 622 | ||
| 623 | /* Stop the timer to prevent command timeouts. */ | ||
| 624 | set_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags); | 623 | set_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags); |
| 625 | 624 | ||
| 626 | if (test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags) && | 625 | if (test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags) && |
| @@ -855,8 +854,6 @@ static inline void mtip_process_legacy(struct driver_data *dd, u32 port_stat) | |||
| 855 | */ | 854 | */ |
| 856 | static inline void mtip_process_errors(struct driver_data *dd, u32 port_stat) | 855 | static inline void mtip_process_errors(struct driver_data *dd, u32 port_stat) |
| 857 | { | 856 | { |
| 858 | if (likely(port_stat & (PORT_IRQ_TF_ERR | PORT_IRQ_IF_ERR))) | ||
| 859 | mtip_handle_tfe(dd); | ||
| 860 | 857 | ||
| 861 | if (unlikely(port_stat & PORT_IRQ_CONNECT)) { | 858 | if (unlikely(port_stat & PORT_IRQ_CONNECT)) { |
| 862 | dev_warn(&dd->pdev->dev, | 859 | dev_warn(&dd->pdev->dev, |
| @@ -874,6 +871,12 @@ static inline void mtip_process_errors(struct driver_data *dd, u32 port_stat) | |||
| 874 | dev_warn(&dd->pdev->dev, | 871 | dev_warn(&dd->pdev->dev, |
| 875 | "Port stat errors %x unhandled\n", | 872 | "Port stat errors %x unhandled\n", |
| 876 | (port_stat & ~PORT_IRQ_HANDLED)); | 873 | (port_stat & ~PORT_IRQ_HANDLED)); |
| 874 | if (mtip_check_surprise_removal(dd->pdev)) | ||
| 875 | return; | ||
| 876 | } | ||
| 877 | if (likely(port_stat & (PORT_IRQ_TF_ERR | PORT_IRQ_IF_ERR))) { | ||
| 878 | set_bit(MTIP_PF_EH_ACTIVE_BIT, &dd->port->flags); | ||
| 879 | wake_up_interruptible(&dd->port->svc_wait); | ||
| 877 | } | 880 | } |
| 878 | } | 881 | } |
| 879 | 882 | ||
| @@ -1040,8 +1043,13 @@ static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout) | |||
| 1040 | msleep(20); | 1043 | msleep(20); |
| 1041 | continue; /* svc thd is actively issuing commands */ | 1044 | continue; /* svc thd is actively issuing commands */ |
| 1042 | } | 1045 | } |
| 1046 | |||
| 1047 | msleep(100); | ||
| 1048 | if (mtip_check_surprise_removal(port->dd->pdev)) | ||
| 1049 | goto err_fault; | ||
| 1043 | if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &port->dd->dd_flag)) | 1050 | if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &port->dd->dd_flag)) |
| 1044 | goto err_fault; | 1051 | goto err_fault; |
| 1052 | |||
| 1045 | /* | 1053 | /* |
| 1046 | * Ignore s_active bit 0 of array element 0. | 1054 | * Ignore s_active bit 0 of array element 0. |
| 1047 | * This bit will always be set | 1055 | * This bit will always be set |
| @@ -1052,8 +1060,6 @@ static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout) | |||
| 1052 | 1060 | ||
| 1053 | if (!active) | 1061 | if (!active) |
| 1054 | break; | 1062 | break; |
| 1055 | |||
| 1056 | msleep(20); | ||
| 1057 | } while (time_before(jiffies, to)); | 1063 | } while (time_before(jiffies, to)); |
| 1058 | 1064 | ||
| 1059 | blk_mq_start_stopped_hw_queues(port->dd->queue, true); | 1065 | blk_mq_start_stopped_hw_queues(port->dd->queue, true); |
| @@ -1113,7 +1119,8 @@ static int mtip_exec_internal_command(struct mtip_port *port, | |||
| 1113 | if (atomic == GFP_KERNEL) { | 1119 | if (atomic == GFP_KERNEL) { |
| 1114 | if (fis->command != ATA_CMD_STANDBYNOW1) { | 1120 | if (fis->command != ATA_CMD_STANDBYNOW1) { |
| 1115 | /* wait for io to complete if non atomic */ | 1121 | /* wait for io to complete if non atomic */ |
| 1116 | if (mtip_quiesce_io(port, 5000) < 0) { | 1122 | if (mtip_quiesce_io(port, |
| 1123 | MTIP_QUIESCE_IO_TIMEOUT_MS) < 0) { | ||
| 1117 | dev_warn(&dd->pdev->dev, | 1124 | dev_warn(&dd->pdev->dev, |
| 1118 | "Failed to quiesce IO\n"); | 1125 | "Failed to quiesce IO\n"); |
| 1119 | mtip_put_int_command(dd, int_cmd); | 1126 | mtip_put_int_command(dd, int_cmd); |
| @@ -1161,9 +1168,9 @@ static int mtip_exec_internal_command(struct mtip_port *port, | |||
| 1161 | 1168 | ||
| 1162 | if (atomic == GFP_KERNEL) { | 1169 | if (atomic == GFP_KERNEL) { |
| 1163 | /* Wait for the command to complete or timeout. */ | 1170 | /* Wait for the command to complete or timeout. */ |
| 1164 | if (wait_for_completion_interruptible_timeout( | 1171 | if ((rv = wait_for_completion_interruptible_timeout( |
| 1165 | &wait, | 1172 | &wait, |
| 1166 | msecs_to_jiffies(timeout)) <= 0) { | 1173 | msecs_to_jiffies(timeout))) <= 0) { |
| 1167 | if (rv == -ERESTARTSYS) { /* interrupted */ | 1174 | if (rv == -ERESTARTSYS) { /* interrupted */ |
| 1168 | dev_err(&dd->pdev->dev, | 1175 | dev_err(&dd->pdev->dev, |
| 1169 | "Internal command [%02X] was interrupted after %lu ms\n", | 1176 | "Internal command [%02X] was interrupted after %lu ms\n", |
| @@ -1299,7 +1306,7 @@ static void mtip_set_timeout(struct driver_data *dd, | |||
| 1299 | *timeout = 15000; /* 15 seconds */ | 1306 | *timeout = 15000; /* 15 seconds */ |
| 1300 | break; | 1307 | break; |
| 1301 | default: | 1308 | default: |
| 1302 | *timeout = MTIP_IOCTL_COMMAND_TIMEOUT_MS; | 1309 | *timeout = MTIP_IOCTL_CMD_TIMEOUT_MS; |
| 1303 | break; | 1310 | break; |
| 1304 | } | 1311 | } |
| 1305 | } | 1312 | } |
| @@ -1351,7 +1358,7 @@ static int mtip_get_identify(struct mtip_port *port, void __user *user_buffer) | |||
| 1351 | sizeof(u16) * ATA_ID_WORDS, | 1358 | sizeof(u16) * ATA_ID_WORDS, |
| 1352 | 0, | 1359 | 0, |
| 1353 | GFP_KERNEL, | 1360 | GFP_KERNEL, |
| 1354 | MTIP_INTERNAL_COMMAND_TIMEOUT_MS) | 1361 | MTIP_INT_CMD_TIMEOUT_MS) |
| 1355 | < 0) { | 1362 | < 0) { |
| 1356 | rv = -1; | 1363 | rv = -1; |
| 1357 | goto out; | 1364 | goto out; |
| @@ -1483,7 +1490,7 @@ static int mtip_read_log_page(struct mtip_port *port, u8 page, u16 *buffer, | |||
| 1483 | sectors * ATA_SECT_SIZE, | 1490 | sectors * ATA_SECT_SIZE, |
| 1484 | 0, | 1491 | 0, |
| 1485 | GFP_ATOMIC, | 1492 | GFP_ATOMIC, |
| 1486 | MTIP_INTERNAL_COMMAND_TIMEOUT_MS); | 1493 | MTIP_INT_CMD_TIMEOUT_MS); |
| 1487 | } | 1494 | } |
| 1488 | 1495 | ||
| 1489 | /* | 1496 | /* |
| @@ -1776,6 +1783,7 @@ static int exec_drive_task(struct mtip_port *port, u8 *command) | |||
| 1776 | { | 1783 | { |
| 1777 | struct host_to_dev_fis fis; | 1784 | struct host_to_dev_fis fis; |
| 1778 | struct host_to_dev_fis *reply = (port->rxfis + RX_FIS_D2H_REG); | 1785 | struct host_to_dev_fis *reply = (port->rxfis + RX_FIS_D2H_REG); |
| 1786 | unsigned int to; | ||
| 1779 | 1787 | ||
| 1780 | /* Build the FIS. */ | 1788 | /* Build the FIS. */ |
| 1781 | memset(&fis, 0, sizeof(struct host_to_dev_fis)); | 1789 | memset(&fis, 0, sizeof(struct host_to_dev_fis)); |
| @@ -1789,6 +1797,8 @@ static int exec_drive_task(struct mtip_port *port, u8 *command) | |||
| 1789 | fis.cyl_hi = command[5]; | 1797 | fis.cyl_hi = command[5]; |
| 1790 | fis.device = command[6] & ~0x10; /* Clear the dev bit*/ | 1798 | fis.device = command[6] & ~0x10; /* Clear the dev bit*/ |
| 1791 | 1799 | ||
| 1800 | mtip_set_timeout(port->dd, &fis, &to, 0); | ||
| 1801 | |||
| 1792 | dbg_printk(MTIP_DRV_NAME " %s: User Command: cmd %x, feat %x, nsect %x, sect %x, lcyl %x, hcyl %x, sel %x\n", | 1802 | dbg_printk(MTIP_DRV_NAME " %s: User Command: cmd %x, feat %x, nsect %x, sect %x, lcyl %x, hcyl %x, sel %x\n", |
| 1793 | __func__, | 1803 | __func__, |
| 1794 | command[0], | 1804 | command[0], |
| @@ -1807,7 +1817,7 @@ static int exec_drive_task(struct mtip_port *port, u8 *command) | |||
| 1807 | 0, | 1817 | 0, |
| 1808 | 0, | 1818 | 0, |
| 1809 | GFP_KERNEL, | 1819 | GFP_KERNEL, |
| 1810 | MTIP_IOCTL_COMMAND_TIMEOUT_MS) < 0) { | 1820 | to) < 0) { |
| 1811 | return -1; | 1821 | return -1; |
| 1812 | } | 1822 | } |
| 1813 | 1823 | ||
| @@ -1847,6 +1857,7 @@ static int exec_drive_command(struct mtip_port *port, u8 *command, | |||
| 1847 | u8 *buf = NULL; | 1857 | u8 *buf = NULL; |
| 1848 | dma_addr_t dma_addr = 0; | 1858 | dma_addr_t dma_addr = 0; |
| 1849 | int rv = 0, xfer_sz = command[3]; | 1859 | int rv = 0, xfer_sz = command[3]; |
| 1860 | unsigned int to; | ||
| 1850 | 1861 | ||
| 1851 | if (xfer_sz) { | 1862 | if (xfer_sz) { |
| 1852 | if (!user_buffer) | 1863 | if (!user_buffer) |
| @@ -1878,6 +1889,8 @@ static int exec_drive_command(struct mtip_port *port, u8 *command, | |||
| 1878 | fis.cyl_hi = 0xC2; | 1889 | fis.cyl_hi = 0xC2; |
| 1879 | } | 1890 | } |
| 1880 | 1891 | ||
| 1892 | mtip_set_timeout(port->dd, &fis, &to, 0); | ||
| 1893 | |||
| 1881 | if (xfer_sz) | 1894 | if (xfer_sz) |
| 1882 | reply = (port->rxfis + RX_FIS_PIO_SETUP); | 1895 | reply = (port->rxfis + RX_FIS_PIO_SETUP); |
| 1883 | else | 1896 | else |
| @@ -1900,7 +1913,7 @@ static int exec_drive_command(struct mtip_port *port, u8 *command, | |||
| 1900 | (xfer_sz ? ATA_SECT_SIZE * xfer_sz : 0), | 1913 | (xfer_sz ? ATA_SECT_SIZE * xfer_sz : 0), |
| 1901 | 0, | 1914 | 0, |
| 1902 | GFP_KERNEL, | 1915 | GFP_KERNEL, |
| 1903 | MTIP_IOCTL_COMMAND_TIMEOUT_MS) | 1916 | to) |
| 1904 | < 0) { | 1917 | < 0) { |
| 1905 | rv = -EFAULT; | 1918 | rv = -EFAULT; |
| 1906 | goto exit_drive_command; | 1919 | goto exit_drive_command; |
| @@ -2956,6 +2969,11 @@ static int mtip_service_thread(void *data) | |||
| 2956 | int ret; | 2969 | int ret; |
| 2957 | 2970 | ||
| 2958 | while (1) { | 2971 | while (1) { |
| 2972 | if (kthread_should_stop() || | ||
| 2973 | test_bit(MTIP_PF_SVC_THD_STOP_BIT, &port->flags)) | ||
| 2974 | goto st_out; | ||
| 2975 | clear_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags); | ||
| 2976 | |||
| 2959 | /* | 2977 | /* |
| 2960 | * the condition is to check neither an internal command is | 2978 | * the condition is to check neither an internal command is |
| 2961 | * is in progress nor error handling is active | 2979 | * is in progress nor error handling is active |
| @@ -2963,11 +2981,12 @@ static int mtip_service_thread(void *data) | |||
| 2963 | wait_event_interruptible(port->svc_wait, (port->flags) && | 2981 | wait_event_interruptible(port->svc_wait, (port->flags) && |
| 2964 | !(port->flags & MTIP_PF_PAUSE_IO)); | 2982 | !(port->flags & MTIP_PF_PAUSE_IO)); |
| 2965 | 2983 | ||
| 2966 | if (kthread_should_stop()) | ||
| 2967 | goto st_out; | ||
| 2968 | |||
| 2969 | set_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags); | 2984 | set_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags); |
| 2970 | 2985 | ||
| 2986 | if (kthread_should_stop() || | ||
| 2987 | test_bit(MTIP_PF_SVC_THD_STOP_BIT, &port->flags)) | ||
| 2988 | goto st_out; | ||
| 2989 | |||
| 2971 | /* If I am an orphan, start self cleanup */ | 2990 | /* If I am an orphan, start self cleanup */ |
| 2972 | if (test_bit(MTIP_PF_SR_CLEANUP_BIT, &port->flags)) | 2991 | if (test_bit(MTIP_PF_SR_CLEANUP_BIT, &port->flags)) |
| 2973 | break; | 2992 | break; |
| @@ -2976,6 +2995,16 @@ static int mtip_service_thread(void *data) | |||
| 2976 | &dd->dd_flag))) | 2995 | &dd->dd_flag))) |
| 2977 | goto st_out; | 2996 | goto st_out; |
| 2978 | 2997 | ||
| 2998 | restart_eh: | ||
| 2999 | /* Demux bits: start with error handling */ | ||
| 3000 | if (test_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags)) { | ||
| 3001 | mtip_handle_tfe(dd); | ||
| 3002 | clear_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags); | ||
| 3003 | } | ||
| 3004 | |||
| 3005 | if (test_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags)) | ||
| 3006 | goto restart_eh; | ||
| 3007 | |||
| 2979 | if (test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags)) { | 3008 | if (test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags)) { |
| 2980 | slot = 1; | 3009 | slot = 1; |
| 2981 | /* used to restrict the loop to one iteration */ | 3010 | /* used to restrict the loop to one iteration */ |
| @@ -3005,16 +3034,14 @@ static int mtip_service_thread(void *data) | |||
| 3005 | } | 3034 | } |
| 3006 | 3035 | ||
| 3007 | clear_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags); | 3036 | clear_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags); |
| 3008 | } else if (test_bit(MTIP_PF_REBUILD_BIT, &port->flags)) { | 3037 | } |
| 3038 | |||
| 3039 | if (test_bit(MTIP_PF_REBUILD_BIT, &port->flags)) { | ||
| 3009 | if (mtip_ftl_rebuild_poll(dd) < 0) | 3040 | if (mtip_ftl_rebuild_poll(dd) < 0) |
| 3010 | set_bit(MTIP_DDF_REBUILD_FAILED_BIT, | 3041 | set_bit(MTIP_DDF_REBUILD_FAILED_BIT, |
| 3011 | &dd->dd_flag); | 3042 | &dd->dd_flag); |
| 3012 | clear_bit(MTIP_PF_REBUILD_BIT, &port->flags); | 3043 | clear_bit(MTIP_PF_REBUILD_BIT, &port->flags); |
| 3013 | } | 3044 | } |
| 3014 | clear_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags); | ||
| 3015 | |||
| 3016 | if (test_bit(MTIP_PF_SVC_THD_STOP_BIT, &port->flags)) | ||
| 3017 | goto st_out; | ||
| 3018 | } | 3045 | } |
| 3019 | 3046 | ||
| 3020 | /* wait for pci remove to exit */ | 3047 | /* wait for pci remove to exit */ |
| @@ -4499,8 +4526,6 @@ static void mtip_pci_remove(struct pci_dev *pdev) | |||
| 4499 | 4526 | ||
| 4500 | pcim_iounmap_regions(pdev, 1 << MTIP_ABAR); | 4527 | pcim_iounmap_regions(pdev, 1 << MTIP_ABAR); |
| 4501 | pci_set_drvdata(pdev, NULL); | 4528 | pci_set_drvdata(pdev, NULL); |
| 4502 | pci_dev_put(pdev); | ||
| 4503 | |||
| 4504 | } | 4529 | } |
| 4505 | 4530 | ||
| 4506 | /* | 4531 | /* |
diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h index 982a88fe1ab2..4b9b554234bc 100644 --- a/drivers/block/mtip32xx/mtip32xx.h +++ b/drivers/block/mtip32xx/mtip32xx.h | |||
| @@ -40,9 +40,11 @@ | |||
| 40 | #define MTIP_MAX_RETRIES 2 | 40 | #define MTIP_MAX_RETRIES 2 |
| 41 | 41 | ||
| 42 | /* Various timeout values in ms */ | 42 | /* Various timeout values in ms */ |
| 43 | #define MTIP_NCQ_COMMAND_TIMEOUT_MS 5000 | 43 | #define MTIP_NCQ_CMD_TIMEOUT_MS 15000 |
| 44 | #define MTIP_IOCTL_COMMAND_TIMEOUT_MS 5000 | 44 | #define MTIP_IOCTL_CMD_TIMEOUT_MS 5000 |
| 45 | #define MTIP_INTERNAL_COMMAND_TIMEOUT_MS 5000 | 45 | #define MTIP_INT_CMD_TIMEOUT_MS 5000 |
| 46 | #define MTIP_QUIESCE_IO_TIMEOUT_MS (MTIP_NCQ_CMD_TIMEOUT_MS * \ | ||
| 47 | (MTIP_MAX_RETRIES + 1)) | ||
| 46 | 48 | ||
| 47 | /* check for timeouts every 500ms */ | 49 | /* check for timeouts every 500ms */ |
| 48 | #define MTIP_TIMEOUT_CHECK_PERIOD 500 | 50 | #define MTIP_TIMEOUT_CHECK_PERIOD 500 |
