mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 03:27:44 -04:00
[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 <[email protected]> Signed-off-by: James Bottomley <[email protected]>
This commit is contained in:
parent
db007fc5e2
commit
7027ad72a6
5 changed files with 84 additions and 3 deletions
|
|
@ -197,10 +197,42 @@ static void
|
|||
scsi_pool_free_command(struct scsi_host_cmd_pool *pool,
|
||||
struct scsi_cmnd *cmd)
|
||||
{
|
||||
if (cmd->prot_sdb)
|
||||
kmem_cache_free(scsi_sdb_cache, cmd->prot_sdb);
|
||||
|
||||
kmem_cache_free(pool->sense_slab, cmd->sense_buffer);
|
||||
kmem_cache_free(pool->cmd_slab, cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* scsi_host_alloc_command - internal function to allocate command
|
||||
* @shost: SCSI host whose pool to allocate from
|
||||
* @gfp_mask: mask for the allocation
|
||||
*
|
||||
* Returns a fully allocated command with sense buffer and protection
|
||||
* data buffer (where applicable) or NULL on failure
|
||||
*/
|
||||
static struct scsi_cmnd *
|
||||
scsi_host_alloc_command(struct Scsi_Host *shost, gfp_t gfp_mask)
|
||||
{
|
||||
struct scsi_cmnd *cmd;
|
||||
|
||||
cmd = scsi_pool_alloc_command(shost->cmd_pool, gfp_mask);
|
||||
if (!cmd)
|
||||
return NULL;
|
||||
|
||||
if (scsi_host_get_prot(shost) >= SHOST_DIX_TYPE0_PROTECTION) {
|
||||
cmd->prot_sdb = kmem_cache_zalloc(scsi_sdb_cache, gfp_mask);
|
||||
|
||||
if (!cmd->prot_sdb) {
|
||||
scsi_pool_free_command(shost->cmd_pool, cmd);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
/**
|
||||
* __scsi_get_command - Allocate a struct scsi_cmnd
|
||||
* @shost: host to transmit command
|
||||
|
|
@ -214,7 +246,7 @@ struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask)
|
|||
struct scsi_cmnd *cmd;
|
||||
unsigned char *buf;
|
||||
|
||||
cmd = scsi_pool_alloc_command(shost->cmd_pool, gfp_mask);
|
||||
cmd = scsi_host_alloc_command(shost, gfp_mask);
|
||||
|
||||
if (unlikely(!cmd)) {
|
||||
unsigned long flags;
|
||||
|
|
@ -457,7 +489,7 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost)
|
|||
/*
|
||||
* Get one backup command for this host.
|
||||
*/
|
||||
cmd = scsi_pool_alloc_command(shost->cmd_pool, gfp_mask);
|
||||
cmd = scsi_host_alloc_command(shost, gfp_mask);
|
||||
if (!cmd) {
|
||||
scsi_put_host_cmd_pool(gfp_mask);
|
||||
shost->cmd_pool = NULL;
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ extern void scsi_exit_queue(void);
|
|||
struct request_queue;
|
||||
struct request;
|
||||
extern int scsi_prep_fn(struct request_queue *, struct request *);
|
||||
extern struct kmem_cache *scsi_sdb_cache;
|
||||
|
||||
/* scsi_proc.c */
|
||||
#ifdef CONFIG_SCSI_PROC_FS
|
||||
|
|
|
|||
Loading…
Reference in a new issue