diff options
Diffstat (limited to 'drivers/scsi/hosts.c')
| -rw-r--r-- | drivers/scsi/hosts.c | 37 |
1 files changed, 34 insertions, 3 deletions
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 85503fad789a..02fe371b0ab8 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,17 +154,29 @@ 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); |
| 147 | device_del(&shost->shost_gendev); | 178 | device_del(&shost->shost_gendev); |
| 179 | scsi_proc_hostdir_rm(shost->hostt); | ||
| 148 | } | 180 | } |
| 149 | EXPORT_SYMBOL(scsi_remove_host); | 181 | EXPORT_SYMBOL(scsi_remove_host); |
| 150 | 182 | ||
| @@ -231,7 +263,6 @@ static void scsi_host_dev_release(struct device *dev) | |||
| 231 | if (shost->work_q) | 263 | if (shost->work_q) |
| 232 | destroy_workqueue(shost->work_q); | 264 | destroy_workqueue(shost->work_q); |
| 233 | 265 | ||
| 234 | scsi_proc_hostdir_rm(shost->hostt); | ||
| 235 | scsi_destroy_command_freelist(shost); | 266 | scsi_destroy_command_freelist(shost); |
| 236 | kfree(shost->shost_data); | 267 | kfree(shost->shost_data); |
| 237 | 268 | ||
