diff options
-rw-r--r-- | drivers/scsi/scsi.c | 67 |
1 files changed, 25 insertions, 42 deletions
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index c4dd0bfc663a..586c241c941e 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c | |||
@@ -161,47 +161,20 @@ static struct scsi_host_cmd_pool scsi_cmd_dma_pool = { | |||
161 | static DEFINE_MUTEX(host_cmd_pool_mutex); | 161 | static DEFINE_MUTEX(host_cmd_pool_mutex); |
162 | 162 | ||
163 | /** | 163 | /** |
164 | * scsi_pool_alloc_command - internal function to get a fully allocated command | 164 | * scsi_host_free_command - internal function to release a command |
165 | * @pool: slab pool to allocate the command from | 165 | * @shost: host to free the command for |
166 | * @gfp_mask: mask for the allocation | ||
167 | * | ||
168 | * Returns a fully allocated command (with the allied sense buffer) or | ||
169 | * NULL on failure | ||
170 | */ | ||
171 | static struct scsi_cmnd * | ||
172 | scsi_pool_alloc_command(struct scsi_host_cmd_pool *pool, gfp_t gfp_mask) | ||
173 | { | ||
174 | struct scsi_cmnd *cmd; | ||
175 | |||
176 | cmd = kmem_cache_zalloc(pool->cmd_slab, gfp_mask | pool->gfp_mask); | ||
177 | if (!cmd) | ||
178 | return NULL; | ||
179 | |||
180 | cmd->sense_buffer = kmem_cache_alloc(pool->sense_slab, | ||
181 | gfp_mask | pool->gfp_mask); | ||
182 | if (!cmd->sense_buffer) { | ||
183 | kmem_cache_free(pool->cmd_slab, cmd); | ||
184 | return NULL; | ||
185 | } | ||
186 | |||
187 | return cmd; | ||
188 | } | ||
189 | |||
190 | /** | ||
191 | * scsi_pool_free_command - internal function to release a command | ||
192 | * @pool: slab pool to allocate the command from | ||
193 | * @cmd: command to release | 166 | * @cmd: command to release |
194 | * | 167 | * |
195 | * the command must previously have been allocated by | 168 | * the command must previously have been allocated by |
196 | * scsi_pool_alloc_command. | 169 | * scsi_host_alloc_command. |
197 | */ | 170 | */ |
198 | static void | 171 | static void |
199 | scsi_pool_free_command(struct scsi_host_cmd_pool *pool, | 172 | scsi_host_free_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd) |
200 | struct scsi_cmnd *cmd) | ||
201 | { | 173 | { |
174 | struct scsi_host_cmd_pool *pool = shost->cmd_pool; | ||
175 | |||
202 | if (cmd->prot_sdb) | 176 | if (cmd->prot_sdb) |
203 | kmem_cache_free(scsi_sdb_cache, cmd->prot_sdb); | 177 | kmem_cache_free(scsi_sdb_cache, cmd->prot_sdb); |
204 | |||
205 | kmem_cache_free(pool->sense_slab, cmd->sense_buffer); | 178 | kmem_cache_free(pool->sense_slab, cmd->sense_buffer); |
206 | kmem_cache_free(pool->cmd_slab, cmd); | 179 | kmem_cache_free(pool->cmd_slab, cmd); |
207 | } | 180 | } |
@@ -217,22 +190,32 @@ scsi_pool_free_command(struct scsi_host_cmd_pool *pool, | |||
217 | static struct scsi_cmnd * | 190 | static struct scsi_cmnd * |
218 | scsi_host_alloc_command(struct Scsi_Host *shost, gfp_t gfp_mask) | 191 | scsi_host_alloc_command(struct Scsi_Host *shost, gfp_t gfp_mask) |
219 | { | 192 | { |
193 | struct scsi_host_cmd_pool *pool = shost->cmd_pool; | ||
220 | struct scsi_cmnd *cmd; | 194 | struct scsi_cmnd *cmd; |
221 | 195 | ||
222 | cmd = scsi_pool_alloc_command(shost->cmd_pool, gfp_mask); | 196 | cmd = kmem_cache_zalloc(pool->cmd_slab, gfp_mask | pool->gfp_mask); |
223 | if (!cmd) | 197 | if (!cmd) |
224 | return NULL; | 198 | goto fail; |
199 | |||
200 | cmd->sense_buffer = kmem_cache_alloc(pool->sense_slab, | ||
201 | gfp_mask | pool->gfp_mask); | ||
202 | if (!cmd->sense_buffer) | ||
203 | goto fail_free_cmd; | ||
225 | 204 | ||
226 | if (scsi_host_get_prot(shost) >= SHOST_DIX_TYPE0_PROTECTION) { | 205 | if (scsi_host_get_prot(shost) >= SHOST_DIX_TYPE0_PROTECTION) { |
227 | cmd->prot_sdb = kmem_cache_zalloc(scsi_sdb_cache, gfp_mask); | 206 | cmd->prot_sdb = kmem_cache_zalloc(scsi_sdb_cache, gfp_mask); |
228 | 207 | if (!cmd->prot_sdb) | |
229 | if (!cmd->prot_sdb) { | 208 | goto fail_free_sense; |
230 | scsi_pool_free_command(shost->cmd_pool, cmd); | ||
231 | return NULL; | ||
232 | } | ||
233 | } | 209 | } |
234 | 210 | ||
235 | return cmd; | 211 | return cmd; |
212 | |||
213 | fail_free_sense: | ||
214 | kmem_cache_free(pool->sense_slab, cmd->sense_buffer); | ||
215 | fail_free_cmd: | ||
216 | kmem_cache_free(pool->cmd_slab, cmd); | ||
217 | fail: | ||
218 | return NULL; | ||
236 | } | 219 | } |
237 | 220 | ||
238 | /** | 221 | /** |
@@ -320,7 +303,7 @@ void __scsi_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd) | |||
320 | } | 303 | } |
321 | 304 | ||
322 | if (likely(cmd != NULL)) | 305 | if (likely(cmd != NULL)) |
323 | scsi_pool_free_command(shost->cmd_pool, cmd); | 306 | scsi_host_free_command(shost, cmd); |
324 | } | 307 | } |
325 | EXPORT_SYMBOL(__scsi_put_command); | 308 | EXPORT_SYMBOL(__scsi_put_command); |
326 | 309 | ||
@@ -456,7 +439,7 @@ void scsi_destroy_command_freelist(struct Scsi_Host *shost) | |||
456 | 439 | ||
457 | cmd = list_entry(shost->free_list.next, struct scsi_cmnd, list); | 440 | cmd = list_entry(shost->free_list.next, struct scsi_cmnd, list); |
458 | list_del_init(&cmd->list); | 441 | list_del_init(&cmd->list); |
459 | scsi_pool_free_command(shost->cmd_pool, cmd); | 442 | scsi_host_free_command(shost, cmd); |
460 | } | 443 | } |
461 | shost->cmd_pool = NULL; | 444 | shost->cmd_pool = NULL; |
462 | scsi_put_host_cmd_pool(shost->unchecked_isa_dma ? GFP_DMA : GFP_KERNEL); | 445 | scsi_put_host_cmd_pool(shost->unchecked_isa_dma ? GFP_DMA : GFP_KERNEL); |