Merge current mainline tree into linux-omap tree
[pandora-kernel.git] / drivers / scsi / scsi_lib.c
index 88d1b5f..62307bd 100644 (file)
@@ -65,7 +65,7 @@ static struct scsi_host_sg_pool scsi_sg_pools[] = {
 };
 #undef SP
 
-static struct kmem_cache *scsi_sdb_cache;
+struct kmem_cache *scsi_sdb_cache;
 
 static void scsi_run_queue(struct request_queue *q);
 
@@ -787,6 +787,9 @@ void scsi_release_buffers(struct scsi_cmnd *cmd)
                kmem_cache_free(scsi_sdb_cache, bidi_sdb);
                cmd->request->next_rq->special = NULL;
        }
+
+       if (scsi_prot_sg_count(cmd))
+               scsi_free_sgtable(cmd->prot_sdb);
 }
 EXPORT_SYMBOL(scsi_release_buffers);
 
@@ -849,7 +852,7 @@ static void scsi_end_bidi_request(struct scsi_cmnd *cmd)
 void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
 {
        int result = cmd->result;
-       int this_count = scsi_bufflen(cmd);
+       int this_count;
        struct request_queue *q = cmd->device->request_queue;
        struct request *req = cmd->request;
        int error = 0;
@@ -905,6 +908,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
         */
        if (scsi_end_request(cmd, error, good_bytes, result == 0) == NULL)
                return;
+       this_count = blk_rq_bytes(req);
 
        /* good_bytes = 0, or (inclusive) there were leftovers and
         * result = 0, so scsi_end_request couldn't retry.
@@ -947,9 +951,14 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
                                 * 6-byte command.
                                 */
                                scsi_requeue_command(q, cmd);
-                               return;
-                       } else {
+                       } else if (sshdr.asc == 0x10) /* DIX */
+                               scsi_end_request(cmd, -EIO, this_count, 0);
+                       else
                                scsi_end_request(cmd, -EIO, this_count, 1);
+                       return;
+               case ABORTED_COMMAND:
+                       if (sshdr.asc == 0x10) { /* DIF */
+                               scsi_end_request(cmd, -EIO, this_count, 0);
                                return;
                        }
                        break;
@@ -1072,6 +1081,26 @@ int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask)
                        goto err_exit;
        }
 
+       if (blk_integrity_rq(cmd->request)) {
+               struct scsi_data_buffer *prot_sdb = cmd->prot_sdb;
+               int ivecs, count;
+
+               BUG_ON(prot_sdb == NULL);
+               ivecs = blk_rq_count_integrity_sg(cmd->request);
+
+               if (scsi_alloc_sgtable(prot_sdb, ivecs, gfp_mask)) {
+                       error = BLKPREP_DEFER;
+                       goto err_exit;
+               }
+
+               count = blk_rq_map_integrity_sg(cmd->request,
+                                               prot_sdb->table.sgl);
+               BUG_ON(unlikely(count > ivecs));
+
+               cmd->prot_sdb = prot_sdb;
+               cmd->prot_sdb->table.nents = count;
+       }
+
        return BLKPREP_OK ;
 
 err_exit:
@@ -1367,7 +1396,7 @@ static void scsi_kill_request(struct request *req, struct request_queue *q)
 
        if (unlikely(cmd == NULL)) {
                printk(KERN_CRIT "impossible request in %s.\n",
-                                __FUNCTION__);
+                                __func__);
                BUG();
        }
 
@@ -1491,12 +1520,27 @@ static void scsi_request_fn(struct request_queue *q)
                        printk(KERN_CRIT "impossible request in %s.\n"
                                         "please mail a stack trace to "
                                         "linux-scsi@vger.kernel.org\n",
-                                        __FUNCTION__);
+                                        __func__);
                        blk_dump_rq_flags(req, "foo");
                        BUG();
                }
                spin_lock(shost->host_lock);
 
+               /*
+                * We hit this when the driver is using a host wide
+                * tag map. For device level tag maps the queue_depth check
+                * in the device ready fn would prevent us from trying
+                * to allocate a tag. Since the map is a shared host resource
+                * we add the dev to the starved list so it eventually gets
+                * a run when a tag is freed.
+                */
+               if (blk_queue_tagged(q) && !blk_rq_tagged(req)) {
+                       if (list_empty(&sdev->starved_entry))
+                               list_add_tail(&sdev->starved_entry,
+                                             &shost->starved_list);
+                       goto not_ready;
+               }
+
                if (!scsi_host_queue_ready(q, shost, sdev))
                        goto not_ready;
                if (scsi_target(sdev)->single_lun) {
@@ -2486,7 +2530,7 @@ void *scsi_kmap_atomic_sg(struct scatterlist *sgl, int sg_count,
        if (unlikely(i == sg_count)) {
                printk(KERN_ERR "%s: Bytes in sg: %zu, requested offset %zu, "
                        "elements %d\n",
-                      __FUNCTION__, sg_len, *offset, sg_count);
+                      __func__, sg_len, *offset, sg_count);
                WARN_ON(1);
                return NULL;
        }