diff options
Diffstat (limited to 'drivers/scsi')
| -rw-r--r-- | drivers/scsi/hosts.c | 4 | ||||
| -rw-r--r-- | drivers/scsi/scsi.c | 43 | ||||
| -rw-r--r-- | drivers/scsi/scsi_lib.c | 33 |
3 files changed, 54 insertions, 26 deletions
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 2ffdc9e0532d..38c3a291efac 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c | |||
| @@ -263,6 +263,10 @@ static void scsi_host_dev_release(struct device *dev) | |||
| 263 | kthread_stop(shost->ehandler); | 263 | kthread_stop(shost->ehandler); |
| 264 | if (shost->work_q) | 264 | if (shost->work_q) |
| 265 | destroy_workqueue(shost->work_q); | 265 | destroy_workqueue(shost->work_q); |
| 266 | if (shost->uspace_req_q) { | ||
| 267 | kfree(shost->uspace_req_q->queuedata); | ||
| 268 | scsi_free_queue(shost->uspace_req_q); | ||
| 269 | } | ||
| 266 | 270 | ||
| 267 | scsi_destroy_command_freelist(shost); | 271 | scsi_destroy_command_freelist(shost); |
| 268 | if (shost->bqt) | 272 | if (shost->bqt) |
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 780d6dc92b42..fafc00deaade 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c | |||
| @@ -156,8 +156,7 @@ static struct scsi_host_cmd_pool scsi_cmd_dma_pool = { | |||
| 156 | 156 | ||
| 157 | static DEFINE_MUTEX(host_cmd_pool_mutex); | 157 | static DEFINE_MUTEX(host_cmd_pool_mutex); |
| 158 | 158 | ||
| 159 | static struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, | 159 | struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask) |
| 160 | gfp_t gfp_mask) | ||
| 161 | { | 160 | { |
| 162 | struct scsi_cmnd *cmd; | 161 | struct scsi_cmnd *cmd; |
| 163 | 162 | ||
| @@ -178,6 +177,7 @@ static struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, | |||
| 178 | 177 | ||
| 179 | return cmd; | 178 | return cmd; |
| 180 | } | 179 | } |
| 180 | EXPORT_SYMBOL_GPL(__scsi_get_command); | ||
| 181 | 181 | ||
| 182 | /* | 182 | /* |
| 183 | * Function: scsi_get_command() | 183 | * Function: scsi_get_command() |
| @@ -214,9 +214,29 @@ struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, gfp_t gfp_mask) | |||
| 214 | put_device(&dev->sdev_gendev); | 214 | put_device(&dev->sdev_gendev); |
| 215 | 215 | ||
| 216 | return cmd; | 216 | return cmd; |
| 217 | } | 217 | } |
| 218 | EXPORT_SYMBOL(scsi_get_command); | 218 | EXPORT_SYMBOL(scsi_get_command); |
| 219 | 219 | ||
| 220 | void __scsi_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd, | ||
| 221 | struct device *dev) | ||
| 222 | { | ||
| 223 | unsigned long flags; | ||
| 224 | |||
| 225 | /* changing locks here, don't need to restore the irq state */ | ||
| 226 | spin_lock_irqsave(&shost->free_list_lock, flags); | ||
| 227 | if (unlikely(list_empty(&shost->free_list))) { | ||
| 228 | list_add(&cmd->list, &shost->free_list); | ||
| 229 | cmd = NULL; | ||
| 230 | } | ||
| 231 | spin_unlock_irqrestore(&shost->free_list_lock, flags); | ||
| 232 | |||
| 233 | if (likely(cmd != NULL)) | ||
| 234 | kmem_cache_free(shost->cmd_pool->slab, cmd); | ||
| 235 | |||
| 236 | put_device(dev); | ||
| 237 | } | ||
| 238 | EXPORT_SYMBOL(__scsi_put_command); | ||
| 239 | |||
| 220 | /* | 240 | /* |
| 221 | * Function: scsi_put_command() | 241 | * Function: scsi_put_command() |
| 222 | * | 242 | * |
| @@ -231,26 +251,15 @@ EXPORT_SYMBOL(scsi_get_command); | |||
| 231 | void scsi_put_command(struct scsi_cmnd *cmd) | 251 | void scsi_put_command(struct scsi_cmnd *cmd) |
| 232 | { | 252 | { |
| 233 | struct scsi_device *sdev = cmd->device; | 253 | struct scsi_device *sdev = cmd->device; |
| 234 | struct Scsi_Host *shost = sdev->host; | ||
| 235 | unsigned long flags; | 254 | unsigned long flags; |
| 236 | 255 | ||
| 237 | /* serious error if the command hasn't come from a device list */ | 256 | /* serious error if the command hasn't come from a device list */ |
| 238 | spin_lock_irqsave(&cmd->device->list_lock, flags); | 257 | spin_lock_irqsave(&cmd->device->list_lock, flags); |
| 239 | BUG_ON(list_empty(&cmd->list)); | 258 | BUG_ON(list_empty(&cmd->list)); |
| 240 | list_del_init(&cmd->list); | 259 | list_del_init(&cmd->list); |
| 241 | spin_unlock(&cmd->device->list_lock); | 260 | spin_unlock_irqrestore(&cmd->device->list_lock, flags); |
| 242 | /* changing locks here, don't need to restore the irq state */ | ||
| 243 | spin_lock(&shost->free_list_lock); | ||
| 244 | if (unlikely(list_empty(&shost->free_list))) { | ||
| 245 | list_add(&cmd->list, &shost->free_list); | ||
| 246 | cmd = NULL; | ||
| 247 | } | ||
| 248 | spin_unlock_irqrestore(&shost->free_list_lock, flags); | ||
| 249 | 261 | ||
| 250 | if (likely(cmd != NULL)) | 262 | __scsi_put_command(cmd->device->host, cmd, &sdev->sdev_gendev); |
| 251 | kmem_cache_free(shost->cmd_pool->slab, cmd); | ||
| 252 | |||
| 253 | put_device(&sdev->sdev_gendev); | ||
| 254 | } | 263 | } |
| 255 | EXPORT_SYMBOL(scsi_put_command); | 264 | EXPORT_SYMBOL(scsi_put_command); |
| 256 | 265 | ||
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 2f12f9f12fcb..fb616c69151f 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
| @@ -704,7 +704,7 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate, | |||
| 704 | return NULL; | 704 | return NULL; |
| 705 | } | 705 | } |
| 706 | 706 | ||
| 707 | static struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_mask) | 707 | struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_mask) |
| 708 | { | 708 | { |
| 709 | struct scsi_host_sg_pool *sgp; | 709 | struct scsi_host_sg_pool *sgp; |
| 710 | struct scatterlist *sgl; | 710 | struct scatterlist *sgl; |
| @@ -745,7 +745,9 @@ static struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_m | |||
| 745 | return sgl; | 745 | return sgl; |
| 746 | } | 746 | } |
| 747 | 747 | ||
| 748 | static void scsi_free_sgtable(struct scatterlist *sgl, int index) | 748 | EXPORT_SYMBOL(scsi_alloc_sgtable); |
| 749 | |||
| 750 | void scsi_free_sgtable(struct scatterlist *sgl, int index) | ||
| 749 | { | 751 | { |
| 750 | struct scsi_host_sg_pool *sgp; | 752 | struct scsi_host_sg_pool *sgp; |
| 751 | 753 | ||
| @@ -755,6 +757,8 @@ static void scsi_free_sgtable(struct scatterlist *sgl, int index) | |||
| 755 | mempool_free(sgl, sgp->pool); | 757 | mempool_free(sgl, sgp->pool); |
| 756 | } | 758 | } |
| 757 | 759 | ||
| 760 | EXPORT_SYMBOL(scsi_free_sgtable); | ||
| 761 | |||
| 758 | /* | 762 | /* |
| 759 | * Function: scsi_release_buffers() | 763 | * Function: scsi_release_buffers() |
| 760 | * | 764 | * |
| @@ -1567,29 +1571,40 @@ u64 scsi_calculate_bounce_limit(struct Scsi_Host *shost) | |||
| 1567 | } | 1571 | } |
| 1568 | EXPORT_SYMBOL(scsi_calculate_bounce_limit); | 1572 | EXPORT_SYMBOL(scsi_calculate_bounce_limit); |
| 1569 | 1573 | ||
| 1570 | struct request_queue *scsi_alloc_queue(struct scsi_device *sdev) | 1574 | struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost, |
| 1575 | request_fn_proc *request_fn) | ||
| 1571 | { | 1576 | { |
| 1572 | struct Scsi_Host *shost = sdev->host; | ||
| 1573 | struct request_queue *q; | 1577 | struct request_queue *q; |
| 1574 | 1578 | ||
| 1575 | q = blk_init_queue(scsi_request_fn, NULL); | 1579 | q = blk_init_queue(request_fn, NULL); |
| 1576 | if (!q) | 1580 | if (!q) |
| 1577 | return NULL; | 1581 | return NULL; |
| 1578 | 1582 | ||
| 1579 | blk_queue_prep_rq(q, scsi_prep_fn); | ||
| 1580 | |||
| 1581 | blk_queue_max_hw_segments(q, shost->sg_tablesize); | 1583 | blk_queue_max_hw_segments(q, shost->sg_tablesize); |
| 1582 | blk_queue_max_phys_segments(q, SCSI_MAX_PHYS_SEGMENTS); | 1584 | blk_queue_max_phys_segments(q, SCSI_MAX_PHYS_SEGMENTS); |
| 1583 | blk_queue_max_sectors(q, shost->max_sectors); | 1585 | blk_queue_max_sectors(q, shost->max_sectors); |
| 1584 | blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost)); | 1586 | blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost)); |
| 1585 | blk_queue_segment_boundary(q, shost->dma_boundary); | 1587 | blk_queue_segment_boundary(q, shost->dma_boundary); |
| 1586 | blk_queue_issue_flush_fn(q, scsi_issue_flush_fn); | ||
| 1587 | blk_queue_softirq_done(q, scsi_softirq_done); | ||
| 1588 | 1588 | ||
| 1589 | if (!shost->use_clustering) | 1589 | if (!shost->use_clustering) |
| 1590 | clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); | 1590 | clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); |
| 1591 | return q; | 1591 | return q; |
| 1592 | } | 1592 | } |
| 1593 | EXPORT_SYMBOL(__scsi_alloc_queue); | ||
| 1594 | |||
| 1595 | struct request_queue *scsi_alloc_queue(struct scsi_device *sdev) | ||
| 1596 | { | ||
| 1597 | struct request_queue *q; | ||
| 1598 | |||
| 1599 | q = __scsi_alloc_queue(sdev->host, scsi_request_fn); | ||
| 1600 | if (!q) | ||
| 1601 | return NULL; | ||
| 1602 | |||
| 1603 | blk_queue_prep_rq(q, scsi_prep_fn); | ||
| 1604 | blk_queue_issue_flush_fn(q, scsi_issue_flush_fn); | ||
| 1605 | blk_queue_softirq_done(q, scsi_softirq_done); | ||
| 1606 | return q; | ||
| 1607 | } | ||
| 1593 | 1608 | ||
| 1594 | void scsi_free_queue(struct request_queue *q) | 1609 | void scsi_free_queue(struct request_queue *q) |
| 1595 | { | 1610 | { |
