[SCSI] implement scsi_data_buffer
[firefly-linux-kernel-4.4.55.git] / drivers / scsi / scsi_lib.c
index 3b5121c4c08110f6e3b2d601d6b94809fef7a87d..d5e77e9b3a9cfb8e0ca6af380ef71a41aa38aa0e 100644 (file)
@@ -440,7 +440,7 @@ EXPORT_SYMBOL_GPL(scsi_execute_async);
 static void scsi_init_cmd_errh(struct scsi_cmnd *cmd)
 {
        cmd->serial_number = 0;
-       cmd->resid = 0;
+       scsi_set_resid(cmd, 0);
        memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
        if (cmd->cmd_len == 0)
                cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
@@ -634,7 +634,7 @@ void scsi_run_host_queues(struct Scsi_Host *shost)
  *             of upper level post-processing and scsi_io_completion).
  *
  * Arguments:   cmd     - command that is complete.
- *              uptodate - 1 if I/O indicates success, <= 0 for I/O error.
+ *              error    - 0 if I/O indicates success, < 0 for I/O error.
  *              bytes    - number of bytes of completed I/O
  *             requeue  - indicates whether we should requeue leftovers.
  *
@@ -649,26 +649,25 @@ void scsi_run_host_queues(struct Scsi_Host *shost)
  *             at some point during this call.
  * Notes:      If cmd was requeued, upon return it will be a stale pointer.
  */
-static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate,
+static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int error,
                                          int bytes, int requeue)
 {
        struct request_queue *q = cmd->device->request_queue;
        struct request *req = cmd->request;
-       unsigned long flags;
 
        /*
         * If there are blocks left over at the end, set up the command
         * to queue the remainder of them.
         */
-       if (end_that_request_chunk(req, uptodate, bytes)) {
+       if (blk_end_request(req, error, bytes)) {
                int leftover = (req->hard_nr_sectors << 9);
 
                if (blk_pc_request(req))
                        leftover = req->data_len;
 
                /* kill remainder if no retrys */
-               if (!uptodate && blk_noretry_request(req))
-                       end_that_request_chunk(req, 0, leftover);
+               if (error && blk_noretry_request(req))
+                       blk_end_request(req, error, leftover);
                else {
                        if (requeue) {
                                /*
@@ -683,14 +682,6 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate,
                }
        }
 
-       add_disk_randomness(req->rq_disk);
-
-       spin_lock_irqsave(q->queue_lock, flags);
-       if (blk_rq_tagged(req))
-               blk_queue_end_tag(q, req);
-       end_that_request_last(req, uptodate);
-       spin_unlock_irqrestore(q->queue_lock, flags);
-
        /*
         * This will goose the queue request function at the end, so we don't
         * need to worry about launching another command.
@@ -755,29 +746,27 @@ static struct scatterlist *scsi_sg_alloc(unsigned int nents, gfp_t gfp_mask)
        return mempool_alloc(sgp->pool, gfp_mask);
 }
 
-int scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_mask)
+static int scsi_alloc_sgtable(struct scsi_data_buffer *sdb, int nents,
+                             gfp_t gfp_mask)
 {
        int ret;
 
-       BUG_ON(!cmd->use_sg);
+       BUG_ON(!nents);
 
-       ret = __sg_alloc_table(&cmd->sg_table, cmd->use_sg, gfp_mask, scsi_sg_alloc);
+       ret = __sg_alloc_table(&sdb->table, nents, SCSI_MAX_SG_SEGMENTS,
+                              gfp_mask, scsi_sg_alloc);
        if (unlikely(ret))
-               __sg_free_table(&cmd->sg_table, scsi_sg_free);
+               __sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS,
+                               scsi_sg_free);
 
-       cmd->request_buffer = cmd->sg_table.sgl;
        return ret;
 }
 
-EXPORT_SYMBOL(scsi_alloc_sgtable);
-
-void scsi_free_sgtable(struct scsi_cmnd *cmd)
+static void scsi_free_sgtable(struct scsi_data_buffer *sdb)
 {
-       __sg_free_table(&cmd->sg_table, scsi_sg_free);
+       __sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS, scsi_sg_free);
 }
 
-EXPORT_SYMBOL(scsi_free_sgtable);
-
 /*
  * Function:    scsi_release_buffers()
  *
@@ -795,18 +784,14 @@ EXPORT_SYMBOL(scsi_free_sgtable);
  *             the scatter-gather table, and potentially any bounce
  *             buffers.
  */
-static void scsi_release_buffers(struct scsi_cmnd *cmd)
+void scsi_release_buffers(struct scsi_cmnd *cmd)
 {
-       if (cmd->use_sg)
-               scsi_free_sgtable(cmd);
+       if (cmd->sdb.table.nents)
+               scsi_free_sgtable(&cmd->sdb);
 
-       /*
-        * Zero these out.  They now point to freed memory, and it is
-        * dangerous to hang onto the pointers.
-        */
-       cmd->request_buffer = NULL;
-       cmd->request_bufflen = 0;
+       memset(&cmd->sdb, 0, sizeof(cmd->sdb));
 }
+EXPORT_SYMBOL(scsi_release_buffers);
 
 /*
  * Function:    scsi_io_completion()
@@ -839,7 +824,7 @@ static void scsi_release_buffers(struct scsi_cmnd *cmd)
 void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
 {
        int result = cmd->result;
-       int this_count = cmd->request_bufflen;
+       int this_count = scsi_bufflen(cmd);
        struct request_queue *q = cmd->device->request_queue;
        struct request *req = cmd->request;
        int clear_errors = 1;
@@ -847,8 +832,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
        int sense_valid = 0;
        int sense_deferred = 0;
 
-       scsi_release_buffers(cmd);
-
        if (result) {
                sense_valid = scsi_command_normalize_sense(cmd, &sshdr);
                if (sense_valid)
@@ -871,9 +854,11 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
                                req->sense_len = len;
                        }
                }
-               req->data_len = cmd->resid;
+               req->data_len = scsi_get_resid(cmd);
        }
 
+       scsi_release_buffers(cmd);
+
        /*
         * Next deal with any sectors which we were able to correctly
         * handle.
@@ -881,7 +866,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
        SCSI_LOG_HLCOMPLETE(1, printk("%ld sectors total, "
                                      "%d bytes done.\n",
                                      req->nr_sectors, good_bytes));
-       SCSI_LOG_HLCOMPLETE(1, printk("use_sg is %d\n", cmd->use_sg));
 
        if (clear_errors)
                req->errors = 0;
@@ -890,7 +874,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
         * are leftovers and there is some kind of error
         * (result != 0), retry the rest.
         */
-       if (scsi_end_request(cmd, 1, good_bytes, result == 0) == NULL)
+       if (scsi_end_request(cmd, 0, good_bytes, result == 0) == NULL)
                return;
 
        /* good_bytes = 0, or (inclusive) there were leftovers and
@@ -904,7 +888,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
                                 * and quietly refuse further access.
                                 */
                                cmd->device->changed = 1;
-                               scsi_end_request(cmd, 0, this_count, 1);
+                               scsi_end_request(cmd, -EIO, this_count, 1);
                                return;
                        } else {
                                /* Must have been a power glitch, or a
@@ -936,7 +920,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
                                scsi_requeue_command(q, cmd);
                                return;
                        } else {
-                               scsi_end_request(cmd, 0, this_count, 1);
+                               scsi_end_request(cmd, -EIO, this_count, 1);
                                return;
                        }
                        break;
@@ -964,7 +948,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
                                                         "Device not ready",
                                                         &sshdr);
 
-                       scsi_end_request(cmd, 0, this_count, 1);
+                       scsi_end_request(cmd, -EIO, this_count, 1);
                        return;
                case VOLUME_OVERFLOW:
                        if (!(req->cmd_flags & REQ_QUIET)) {
@@ -974,7 +958,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
                                scsi_print_sense("", cmd);
                        }
                        /* See SSC3rXX or current. */
-                       scsi_end_request(cmd, 0, this_count, 1);
+                       scsi_end_request(cmd, -EIO, this_count, 1);
                        return;
                default:
                        break;
@@ -995,7 +979,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
                                scsi_print_sense("", cmd);
                }
        }
-       scsi_end_request(cmd, 0, this_count, !result);
+       scsi_end_request(cmd, -EIO, this_count, !result);
 }
 
 /*
@@ -1008,41 +992,37 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
  * Returns:     0 on success
  *             BLKPREP_DEFER if the failure is retryable
  */
-static int scsi_init_io(struct scsi_cmnd *cmd)
+int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask)
 {
        struct request     *req = cmd->request;
        int                count;
-
-       /*
-        * We used to not use scatter-gather for single segment request,
-        * but now we do (it makes highmem I/O easier to support without
-        * kmapping pages)
-        */
-       cmd->use_sg = req->nr_phys_segments;
+       struct scsi_data_buffer *sdb = &cmd->sdb;
 
        /*
         * If sg table allocation fails, requeue request later.
         */
-       if (unlikely(scsi_alloc_sgtable(cmd, GFP_ATOMIC))) {
+       if (unlikely(scsi_alloc_sgtable(sdb, req->nr_phys_segments,
+                                       gfp_mask))) {
                scsi_unprep_request(req);
                return BLKPREP_DEFER;
        }
 
        req->buffer = NULL;
        if (blk_pc_request(req))
-               cmd->request_bufflen = req->data_len;
+               sdb->length = req->data_len;
        else
-               cmd->request_bufflen = req->nr_sectors << 9;
+               sdb->length = req->nr_sectors << 9;
 
        /* 
         * Next, walk the list, and fill in the addresses and sizes of
         * each segment.
         */
-       count = blk_rq_map_sg(req->q, req, cmd->request_buffer);
-       BUG_ON(count > cmd->use_sg);
-       cmd->use_sg = count;
+       count = blk_rq_map_sg(req->q, req, sdb->table.sgl);
+       BUG_ON(count > sdb->table.nents);
+       sdb->table.nents = count;
        return BLKPREP_OK;
 }
+EXPORT_SYMBOL(scsi_init_io);
 
 static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev,
                struct request *req)
@@ -1088,16 +1068,14 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
 
                BUG_ON(!req->nr_phys_segments);
 
-               ret = scsi_init_io(cmd);
+               ret = scsi_init_io(cmd, GFP_ATOMIC);
                if (unlikely(ret))
                        return ret;
        } else {
                BUG_ON(req->data_len);
                BUG_ON(req->data);
 
-               cmd->request_bufflen = 0;
-               cmd->request_buffer = NULL;
-               cmd->use_sg = 0;
+               memset(&cmd->sdb, 0, sizeof(cmd->sdb));
                req->buffer = NULL;
        }
 
@@ -1139,7 +1117,7 @@ int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req)
        if (unlikely(!cmd))
                return BLKPREP_DEFER;
 
-       return scsi_init_io(cmd);
+       return scsi_init_io(cmd, GFP_ATOMIC);
 }
 EXPORT_SYMBOL(scsi_setup_fs_cmnd);