diff options
Diffstat (limited to 'drivers/scsi/scsi_error.c')
-rw-r--r-- | drivers/scsi/scsi_error.c | 48 |
1 files changed, 14 insertions, 34 deletions
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 0fc8b48f052b..895c9452be4c 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/string.h> | 20 | #include <linux/string.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/kthread.h> | ||
23 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
24 | #include <linux/blkdev.h> | 25 | #include <linux/blkdev.h> |
25 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
@@ -75,7 +76,7 @@ int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag) | |||
75 | 76 | ||
76 | scmd->eh_eflags |= eh_flag; | 77 | scmd->eh_eflags |= eh_flag; |
77 | list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q); | 78 | list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q); |
78 | set_bit(SHOST_RECOVERY, &shost->shost_state); | 79 | scsi_host_set_state(shost, SHOST_RECOVERY); |
79 | shost->host_failed++; | 80 | shost->host_failed++; |
80 | scsi_eh_wakeup(shost); | 81 | scsi_eh_wakeup(shost); |
81 | spin_unlock_irqrestore(shost->host_lock, flags); | 82 | spin_unlock_irqrestore(shost->host_lock, flags); |
@@ -115,7 +116,6 @@ void scsi_add_timer(struct scsi_cmnd *scmd, int timeout, | |||
115 | 116 | ||
116 | add_timer(&scmd->eh_timeout); | 117 | add_timer(&scmd->eh_timeout); |
117 | } | 118 | } |
118 | EXPORT_SYMBOL(scsi_add_timer); | ||
119 | 119 | ||
120 | /** | 120 | /** |
121 | * scsi_delete_timer - Delete/cancel timer for a given function. | 121 | * scsi_delete_timer - Delete/cancel timer for a given function. |
@@ -143,7 +143,6 @@ int scsi_delete_timer(struct scsi_cmnd *scmd) | |||
143 | 143 | ||
144 | return rtn; | 144 | return rtn; |
145 | } | 145 | } |
146 | EXPORT_SYMBOL(scsi_delete_timer); | ||
147 | 146 | ||
148 | /** | 147 | /** |
149 | * scsi_times_out - Timeout function for normal scsi commands. | 148 | * scsi_times_out - Timeout function for normal scsi commands. |
@@ -197,7 +196,8 @@ int scsi_block_when_processing_errors(struct scsi_device *sdev) | |||
197 | { | 196 | { |
198 | int online; | 197 | int online; |
199 | 198 | ||
200 | wait_event(sdev->host->host_wait, (!test_bit(SHOST_RECOVERY, &sdev->host->shost_state))); | 199 | wait_event(sdev->host->host_wait, (sdev->host->shost_state != |
200 | SHOST_RECOVERY)); | ||
201 | 201 | ||
202 | online = scsi_device_online(sdev); | 202 | online = scsi_device_online(sdev); |
203 | 203 | ||
@@ -775,9 +775,11 @@ retry_tur: | |||
775 | __FUNCTION__, scmd, rtn)); | 775 | __FUNCTION__, scmd, rtn)); |
776 | if (rtn == SUCCESS) | 776 | if (rtn == SUCCESS) |
777 | return 0; | 777 | return 0; |
778 | else if (rtn == NEEDS_RETRY) | 778 | else if (rtn == NEEDS_RETRY) { |
779 | if (retry_cnt--) | 779 | if (retry_cnt--) |
780 | goto retry_tur; | 780 | goto retry_tur; |
781 | return 0; | ||
782 | } | ||
781 | return 1; | 783 | return 1; |
782 | } | 784 | } |
783 | 785 | ||
@@ -1458,7 +1460,7 @@ static void scsi_restart_operations(struct Scsi_Host *shost) | |||
1458 | SCSI_LOG_ERROR_RECOVERY(3, printk("%s: waking up host to restart\n", | 1460 | SCSI_LOG_ERROR_RECOVERY(3, printk("%s: waking up host to restart\n", |
1459 | __FUNCTION__)); | 1461 | __FUNCTION__)); |
1460 | 1462 | ||
1461 | clear_bit(SHOST_RECOVERY, &shost->shost_state); | 1463 | scsi_host_set_state(shost, SHOST_RUNNING); |
1462 | 1464 | ||
1463 | wake_up(&shost->host_wait); | 1465 | wake_up(&shost->host_wait); |
1464 | 1466 | ||
@@ -1582,16 +1584,8 @@ int scsi_error_handler(void *data) | |||
1582 | int rtn; | 1584 | int rtn; |
1583 | DECLARE_MUTEX_LOCKED(sem); | 1585 | DECLARE_MUTEX_LOCKED(sem); |
1584 | 1586 | ||
1585 | /* | ||
1586 | * Flush resources | ||
1587 | */ | ||
1588 | |||
1589 | daemonize("scsi_eh_%d", shost->host_no); | ||
1590 | |||
1591 | current->flags |= PF_NOFREEZE; | 1587 | current->flags |= PF_NOFREEZE; |
1592 | |||
1593 | shost->eh_wait = &sem; | 1588 | shost->eh_wait = &sem; |
1594 | shost->ehandler = current; | ||
1595 | 1589 | ||
1596 | /* | 1590 | /* |
1597 | * Wake up the thread that created us. | 1591 | * Wake up the thread that created us. |
@@ -1599,8 +1593,6 @@ int scsi_error_handler(void *data) | |||
1599 | SCSI_LOG_ERROR_RECOVERY(3, printk("Wake up parent of" | 1593 | SCSI_LOG_ERROR_RECOVERY(3, printk("Wake up parent of" |
1600 | " scsi_eh_%d\n",shost->host_no)); | 1594 | " scsi_eh_%d\n",shost->host_no)); |
1601 | 1595 | ||
1602 | complete(shost->eh_notify); | ||
1603 | |||
1604 | while (1) { | 1596 | while (1) { |
1605 | /* | 1597 | /* |
1606 | * If we get a signal, it means we are supposed to go | 1598 | * If we get a signal, it means we are supposed to go |
@@ -1621,7 +1613,7 @@ int scsi_error_handler(void *data) | |||
1621 | * semaphores isn't unreasonable. | 1613 | * semaphores isn't unreasonable. |
1622 | */ | 1614 | */ |
1623 | down_interruptible(&sem); | 1615 | down_interruptible(&sem); |
1624 | if (shost->eh_kill) | 1616 | if (kthread_should_stop()) |
1625 | break; | 1617 | break; |
1626 | 1618 | ||
1627 | SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler" | 1619 | SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler" |
@@ -1660,22 +1652,6 @@ int scsi_error_handler(void *data) | |||
1660 | * Make sure that nobody tries to wake us up again. | 1652 | * Make sure that nobody tries to wake us up again. |
1661 | */ | 1653 | */ |
1662 | shost->eh_wait = NULL; | 1654 | shost->eh_wait = NULL; |
1663 | |||
1664 | /* | ||
1665 | * Knock this down too. From this point on, the host is flying | ||
1666 | * without a pilot. If this is because the module is being unloaded, | ||
1667 | * that's fine. If the user sent a signal to this thing, we are | ||
1668 | * potentially in real danger. | ||
1669 | */ | ||
1670 | shost->eh_active = 0; | ||
1671 | shost->ehandler = NULL; | ||
1672 | |||
1673 | /* | ||
1674 | * If anyone is waiting for us to exit (i.e. someone trying to unload | ||
1675 | * a driver), then wake up that process to let them know we are on | ||
1676 | * the way out the door. | ||
1677 | */ | ||
1678 | complete_and_exit(shost->eh_notify, 0); | ||
1679 | return 0; | 1655 | return 0; |
1680 | } | 1656 | } |
1681 | 1657 | ||
@@ -1846,12 +1822,16 @@ EXPORT_SYMBOL(scsi_reset_provider); | |||
1846 | int scsi_normalize_sense(const u8 *sense_buffer, int sb_len, | 1822 | int scsi_normalize_sense(const u8 *sense_buffer, int sb_len, |
1847 | struct scsi_sense_hdr *sshdr) | 1823 | struct scsi_sense_hdr *sshdr) |
1848 | { | 1824 | { |
1849 | if (!sense_buffer || !sb_len || (sense_buffer[0] & 0x70) != 0x70) | 1825 | if (!sense_buffer || !sb_len) |
1850 | return 0; | 1826 | return 0; |
1851 | 1827 | ||
1852 | memset(sshdr, 0, sizeof(struct scsi_sense_hdr)); | 1828 | memset(sshdr, 0, sizeof(struct scsi_sense_hdr)); |
1853 | 1829 | ||
1854 | sshdr->response_code = (sense_buffer[0] & 0x7f); | 1830 | sshdr->response_code = (sense_buffer[0] & 0x7f); |
1831 | |||
1832 | if (!scsi_sense_valid(sshdr)) | ||
1833 | return 0; | ||
1834 | |||
1855 | if (sshdr->response_code >= 0x72) { | 1835 | if (sshdr->response_code >= 0x72) { |
1856 | /* | 1836 | /* |
1857 | * descriptor format | 1837 | * descriptor format |