summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_lib.c
diff options
context:
space:
mode:
authorMartin K. Petersen <martin.petersen@oracle.com>2008-07-17 17:08:48 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-07-26 15:14:55 -0400
commit7027ad72a689797475973c6feb5f0b673382f779 (patch)
tree4f6daa1d509708fb340d09608d79557a9af57f00 /drivers/scsi/scsi_lib.c
parentdb007fc5e20c00b356e9ffe2d0e007398c65c837 (diff)
downloadlinux-7027ad72a689797475973c6feb5f0b673382f779.tar.bz2
[SCSI] Support devices with protection information
Implement support for DMA of protection information for devices that are data integrity capable. - Add support for mapping an extra scatter-gather list containing the protection information. - Allocate protection scsi_data_buffer if host is DIX (integrity DMA) capable. - Accessor function for checking whether a device has protection enabled. Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/scsi_lib.c')
-rw-r--r--drivers/scsi/scsi_lib.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index fe77ccacf319..a47c05d7829a 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -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);
@@ -1072,6 +1075,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: