diff options
-rw-r--r-- | drivers/scsi/scsi_error.c | 55 | ||||
-rw-r--r-- | include/scsi/scsi_host.h | 2 |
2 files changed, 23 insertions, 34 deletions
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index af589fac814d..ad5342165079 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
@@ -50,7 +50,7 @@ | |||
50 | void scsi_eh_wakeup(struct Scsi_Host *shost) | 50 | void scsi_eh_wakeup(struct Scsi_Host *shost) |
51 | { | 51 | { |
52 | if (shost->host_busy == shost->host_failed) { | 52 | if (shost->host_busy == shost->host_failed) { |
53 | up(shost->eh_wait); | 53 | wake_up_process(shost->ehandler); |
54 | SCSI_LOG_ERROR_RECOVERY(5, | 54 | SCSI_LOG_ERROR_RECOVERY(5, |
55 | printk("Waking error handler thread\n")); | 55 | printk("Waking error handler thread\n")); |
56 | } | 56 | } |
@@ -70,7 +70,7 @@ int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag) | |||
70 | unsigned long flags; | 70 | unsigned long flags; |
71 | int ret = 0; | 71 | int ret = 0; |
72 | 72 | ||
73 | if (shost->eh_wait == NULL) | 73 | if (!shost->ehandler) |
74 | return 0; | 74 | return 0; |
75 | 75 | ||
76 | spin_lock_irqsave(shost->host_lock, flags); | 76 | spin_lock_irqsave(shost->host_lock, flags); |
@@ -1591,40 +1591,31 @@ int scsi_error_handler(void *data) | |||
1591 | { | 1591 | { |
1592 | struct Scsi_Host *shost = (struct Scsi_Host *) data; | 1592 | struct Scsi_Host *shost = (struct Scsi_Host *) data; |
1593 | int rtn; | 1593 | int rtn; |
1594 | DECLARE_MUTEX_LOCKED(sem); | ||
1595 | 1594 | ||
1596 | current->flags |= PF_NOFREEZE; | 1595 | current->flags |= PF_NOFREEZE; |
1597 | shost->eh_wait = &sem; | ||
1598 | 1596 | ||
1597 | |||
1599 | /* | 1598 | /* |
1600 | * Wake up the thread that created us. | 1599 | * Note - we always use TASK_INTERRUPTIBLE even if the module |
1600 | * was loaded as part of the kernel. The reason is that | ||
1601 | * UNINTERRUPTIBLE would cause this thread to be counted in | ||
1602 | * the load average as a running process, and an interruptible | ||
1603 | * wait doesn't. | ||
1601 | */ | 1604 | */ |
1602 | SCSI_LOG_ERROR_RECOVERY(3, printk("Wake up parent of" | 1605 | set_current_state(TASK_INTERRUPTIBLE); |
1603 | " scsi_eh_%d\n",shost->host_no)); | 1606 | while (!kthread_should_stop()) { |
1604 | 1607 | if (shost->host_failed == 0 || | |
1605 | while (1) { | 1608 | shost->host_failed != shost->host_busy) { |
1606 | /* | 1609 | SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler" |
1607 | * If we get a signal, it means we are supposed to go | 1610 | " scsi_eh_%d" |
1608 | * away and die. This typically happens if the user is | 1611 | " sleeping\n", |
1609 | * trying to unload a module. | 1612 | shost->host_no)); |
1610 | */ | 1613 | schedule(); |
1611 | SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler" | 1614 | set_current_state(TASK_INTERRUPTIBLE); |
1612 | " scsi_eh_%d" | 1615 | continue; |
1613 | " sleeping\n",shost->host_no)); | 1616 | } |
1614 | |||
1615 | /* | ||
1616 | * Note - we always use down_interruptible with the semaphore | ||
1617 | * even if the module was loaded as part of the kernel. The | ||
1618 | * reason is that down() will cause this thread to be counted | ||
1619 | * in the load average as a running process, and down | ||
1620 | * interruptible doesn't. Given that we need to allow this | ||
1621 | * thread to die if the driver was loaded as a module, using | ||
1622 | * semaphores isn't unreasonable. | ||
1623 | */ | ||
1624 | down_interruptible(&sem); | ||
1625 | if (kthread_should_stop()) | ||
1626 | break; | ||
1627 | 1617 | ||
1618 | __set_current_state(TASK_RUNNING); | ||
1628 | SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler" | 1619 | SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler" |
1629 | " scsi_eh_%d waking" | 1620 | " scsi_eh_%d waking" |
1630 | " up\n",shost->host_no)); | 1621 | " up\n",shost->host_no)); |
@@ -1651,7 +1642,7 @@ int scsi_error_handler(void *data) | |||
1651 | * which are still online. | 1642 | * which are still online. |
1652 | */ | 1643 | */ |
1653 | scsi_restart_operations(shost); | 1644 | scsi_restart_operations(shost); |
1654 | 1645 | set_current_state(TASK_INTERRUPTIBLE); | |
1655 | } | 1646 | } |
1656 | 1647 | ||
1657 | SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler scsi_eh_%d" | 1648 | SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler scsi_eh_%d" |
@@ -1660,7 +1651,7 @@ int scsi_error_handler(void *data) | |||
1660 | /* | 1651 | /* |
1661 | * Make sure that nobody tries to wake us up again. | 1652 | * Make sure that nobody tries to wake us up again. |
1662 | */ | 1653 | */ |
1663 | shost->eh_wait = NULL; | 1654 | shost->ehandler = NULL; |
1664 | return 0; | 1655 | return 0; |
1665 | } | 1656 | } |
1666 | 1657 | ||
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 540369ff815c..69313ba7505b 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h | |||
@@ -467,8 +467,6 @@ struct Scsi_Host { | |||
467 | 467 | ||
468 | struct list_head eh_cmd_q; | 468 | struct list_head eh_cmd_q; |
469 | struct task_struct * ehandler; /* Error recovery thread. */ | 469 | struct task_struct * ehandler; /* Error recovery thread. */ |
470 | struct semaphore * eh_wait; /* The error recovery thread waits | ||
471 | on this. */ | ||
472 | struct semaphore * eh_action; /* Wait for specific actions on the | 470 | struct semaphore * eh_action; /* Wait for specific actions on the |
473 | host. */ | 471 | host. */ |
474 | unsigned int eh_active:1; /* Indicates the eh thread is awake and active if | 472 | unsigned int eh_active:1; /* Indicates the eh thread is awake and active if |