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 | 
