]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/scsi/scsi_lib.c
Auto-update from upstream
[linux-2.6-omap-h63xx.git] / drivers / scsi / scsi_lib.c
index 3e136bfe42190718739815915abf172cc6bf4133..ba93d6e66d481506dc065c5763eb53f6f91fed7e 100644 (file)
@@ -306,14 +306,16 @@ struct scsi_io_context {
        char sense[SCSI_SENSE_BUFFERSIZE];
 };
 
-static void scsi_end_async(struct request *req)
+static kmem_cache_t *scsi_io_context_cache;
+
+static void scsi_end_async(struct request *req, int uptodate)
 {
        struct scsi_io_context *sioc = req->end_io_data;
 
        if (sioc->done)
                sioc->done(sioc->data, sioc->sense, req->errors, req->data_len);
 
-       kfree(sioc);
+       kmem_cache_free(scsi_io_context_cache, sioc);
        __blk_put_request(req->q, req);
 }
 
@@ -452,13 +454,15 @@ int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd,
        int err = 0;
        int write = (data_direction == DMA_TO_DEVICE);
 
-       sioc = kzalloc(sizeof(*sioc), gfp);
+       sioc = kmem_cache_alloc(scsi_io_context_cache, gfp);
        if (!sioc)
                return DRIVER_ERROR << 24;
+       memset(sioc, 0, sizeof(*sioc));
 
        req = blk_get_request(sdev->request_queue, write, gfp);
        if (!req)
                goto free_sense;
+       req->flags |= REQ_BLOCK_PC | REQ_QUIET;
 
        if (use_sg)
                err = scsi_req_map_sg(req, buffer, use_sg, bufflen, gfp);
@@ -474,7 +478,6 @@ int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd,
        req->sense_len = 0;
        req->timeout = timeout;
        req->retries = retries;
-       req->flags |= REQ_BLOCK_PC | REQ_QUIET;
        req->end_io_data = sioc;
 
        sioc->data = privdata;
@@ -788,7 +791,7 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate,
        spin_lock_irqsave(q->queue_lock, flags);
        if (blk_rq_tagged(req))
                blk_queue_end_tag(q, req);
-       end_that_request_last(req);
+       end_that_request_last(req, uptodate);
        spin_unlock_irqrestore(q->queue_lock, flags);
 
        /*
@@ -929,9 +932,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
        int sense_valid = 0;
        int sense_deferred = 0;
 
-       if (blk_complete_barrier_rq(q, req, good_bytes >> 9))
-               return;
-
        /*
         * Free up any indirection buffers we allocated for DMA purposes. 
         * For the case of a READ, we need to copy the data out of the
@@ -1196,38 +1196,6 @@ static int scsi_init_io(struct scsi_cmnd *cmd)
        return BLKPREP_KILL;
 }
 
-static int scsi_prepare_flush_fn(request_queue_t *q, struct request *rq)
-{
-       struct scsi_device *sdev = q->queuedata;
-       struct scsi_driver *drv;
-
-       if (sdev->sdev_state == SDEV_RUNNING) {
-               drv = *(struct scsi_driver **) rq->rq_disk->private_data;
-
-               if (drv->prepare_flush)
-                       return drv->prepare_flush(q, rq);
-       }
-
-       return 0;
-}
-
-static void scsi_end_flush_fn(request_queue_t *q, struct request *rq)
-{
-       struct scsi_device *sdev = q->queuedata;
-       struct request *flush_rq = rq->end_io_data;
-       struct scsi_driver *drv;
-
-       if (flush_rq->errors) {
-               printk("scsi: barrier error, disabling flush support\n");
-               blk_queue_ordered(q, QUEUE_ORDERED_NONE);
-       }
-
-       if (sdev->sdev_state == SDEV_RUNNING) {
-               drv = *(struct scsi_driver **) rq->rq_disk->private_data;
-               drv->end_flush(q, rq);
-       }
-}
-
 static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk,
                               sector_t *error_sector)
 {
@@ -1256,6 +1224,26 @@ static void scsi_generic_done(struct scsi_cmnd *cmd)
        scsi_io_completion(cmd, cmd->bufflen, 0);
 }
 
+void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd)
+{
+       struct request *req = cmd->request;
+
+       BUG_ON(sizeof(req->cmd) > sizeof(cmd->cmnd));
+       memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd));
+       cmd->cmd_len = req->cmd_len;
+       if (!req->data_len)
+               cmd->sc_data_direction = DMA_NONE;
+       else if (rq_data_dir(req) == WRITE)
+               cmd->sc_data_direction = DMA_TO_DEVICE;
+       else
+               cmd->sc_data_direction = DMA_FROM_DEVICE;
+       
+       cmd->transfersize = req->data_len;
+       cmd->allowed = req->retries;
+       cmd->timeout_per_command = req->timeout;
+}
+EXPORT_SYMBOL_GPL(scsi_setup_blk_pc_cmnd);
+
 static int scsi_prep_fn(struct request_queue *q, struct request *req)
 {
        struct scsi_device *sdev = q->queuedata;
@@ -1391,18 +1379,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
                                goto kill;
                        }
                } else {
-                       memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd));
-                       cmd->cmd_len = req->cmd_len;
-                       if (rq_data_dir(req) == WRITE)
-                               cmd->sc_data_direction = DMA_TO_DEVICE;
-                       else if (req->data_len)
-                               cmd->sc_data_direction = DMA_FROM_DEVICE;
-                       else
-                               cmd->sc_data_direction = DMA_NONE;
-                       
-                       cmd->transfersize = req->data_len;
-                       cmd->allowed = req->retries;
-                       cmd->timeout_per_command = req->timeout;
+                       scsi_setup_blk_pc_cmnd(cmd);
                        cmd->done = scsi_generic_done;
                }
        }
@@ -1691,17 +1668,6 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev)
        blk_queue_segment_boundary(q, shost->dma_boundary);
        blk_queue_issue_flush_fn(q, scsi_issue_flush_fn);
 
-       /*
-        * ordered tags are superior to flush ordering
-        */
-       if (shost->ordered_tag)
-               blk_queue_ordered(q, QUEUE_ORDERED_TAG);
-       else if (shost->ordered_flush) {
-               blk_queue_ordered(q, QUEUE_ORDERED_FLUSH);
-               q->prepare_flush_fn = scsi_prepare_flush_fn;
-               q->end_flush_fn = scsi_end_flush_fn;
-       }
-
        if (!shost->use_clustering)
                clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
        return q;
@@ -1765,6 +1731,14 @@ int __init scsi_init_queue(void)
 {
        int i;
 
+       scsi_io_context_cache = kmem_cache_create("scsi_io_context",
+                                       sizeof(struct scsi_io_context),
+                                       0, 0, NULL, NULL);
+       if (!scsi_io_context_cache) {
+               printk(KERN_ERR "SCSI: can't init scsi io context cache\n");
+               return -ENOMEM;
+       }
+
        for (i = 0; i < SG_MEMPOOL_NR; i++) {
                struct scsi_host_sg_pool *sgp = scsi_sg_pools + i;
                int size = sgp->size * sizeof(struct scatterlist);
@@ -1792,6 +1766,8 @@ void scsi_exit_queue(void)
 {
        int i;
 
+       kmem_cache_destroy(scsi_io_context_cache);
+
        for (i = 0; i < SG_MEMPOOL_NR; i++) {
                struct scsi_host_sg_pool *sgp = scsi_sg_pools + i;
                mempool_destroy(sgp->pool);