diff options
Diffstat (limited to 'drivers/scsi/hosts.c')
| -rw-r--r-- | drivers/scsi/hosts.c | 35 |
1 files changed, 33 insertions, 2 deletions
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 85503fad789a..f2a72d33132c 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c | |||
| @@ -98,6 +98,7 @@ int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state) | |||
| 98 | switch (oldstate) { | 98 | switch (oldstate) { |
| 99 | case SHOST_CREATED: | 99 | case SHOST_CREATED: |
| 100 | case SHOST_RUNNING: | 100 | case SHOST_RUNNING: |
| 101 | case SHOST_CANCEL_RECOVERY: | ||
| 101 | break; | 102 | break; |
| 102 | default: | 103 | default: |
| 103 | goto illegal; | 104 | goto illegal; |
| @@ -107,12 +108,31 @@ int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state) | |||
| 107 | case SHOST_DEL: | 108 | case SHOST_DEL: |
| 108 | switch (oldstate) { | 109 | switch (oldstate) { |
| 109 | case SHOST_CANCEL: | 110 | case SHOST_CANCEL: |
| 111 | case SHOST_DEL_RECOVERY: | ||
| 110 | break; | 112 | break; |
| 111 | default: | 113 | default: |
| 112 | goto illegal; | 114 | goto illegal; |
| 113 | } | 115 | } |
| 114 | break; | 116 | break; |
| 115 | 117 | ||
| 118 | case SHOST_CANCEL_RECOVERY: | ||
| 119 | switch (oldstate) { | ||
| 120 | case SHOST_CANCEL: | ||
| 121 | case SHOST_RECOVERY: | ||
| 122 | break; | ||
| 123 | default: | ||
| 124 | goto illegal; | ||
| 125 | } | ||
| 126 | break; | ||
| 127 | |||
| 128 | case SHOST_DEL_RECOVERY: | ||
| 129 | switch (oldstate) { | ||
| 130 | case SHOST_CANCEL_RECOVERY: | ||
| 131 | break; | ||
| 132 | default: | ||
| 133 | goto illegal; | ||
| 134 | } | ||
| 135 | break; | ||
| 116 | } | 136 | } |
| 117 | shost->shost_state = state; | 137 | shost->shost_state = state; |
| 118 | return 0; | 138 | return 0; |
| @@ -134,13 +154,24 @@ EXPORT_SYMBOL(scsi_host_set_state); | |||
| 134 | **/ | 154 | **/ |
| 135 | void scsi_remove_host(struct Scsi_Host *shost) | 155 | void scsi_remove_host(struct Scsi_Host *shost) |
| 136 | { | 156 | { |
| 157 | unsigned long flags; | ||
| 137 | down(&shost->scan_mutex); | 158 | down(&shost->scan_mutex); |
| 138 | scsi_host_set_state(shost, SHOST_CANCEL); | 159 | spin_lock_irqsave(shost->host_lock, flags); |
| 160 | if (scsi_host_set_state(shost, SHOST_CANCEL)) | ||
| 161 | if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY)) { | ||
| 162 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
| 163 | up(&shost->scan_mutex); | ||
| 164 | return; | ||
| 165 | } | ||
| 166 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
| 139 | up(&shost->scan_mutex); | 167 | up(&shost->scan_mutex); |
| 140 | scsi_forget_host(shost); | 168 | scsi_forget_host(shost); |
| 141 | scsi_proc_host_rm(shost); | 169 | scsi_proc_host_rm(shost); |
| 142 | 170 | ||
| 143 | scsi_host_set_state(shost, SHOST_DEL); | 171 | spin_lock_irqsave(shost->host_lock, flags); |
| 172 | if (scsi_host_set_state(shost, SHOST_DEL)) | ||
| 173 | BUG_ON(scsi_host_set_state(shost, SHOST_DEL_RECOVERY)); | ||
| 174 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
| 144 | 175 | ||
| 145 | transport_unregister_device(&shost->shost_gendev); | 176 | transport_unregister_device(&shost->shost_gendev); |
| 146 | class_device_unregister(&shost->shost_classdev); | 177 | class_device_unregister(&shost->shost_classdev); |
