summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/hpsa.c179
-rw-r--r--drivers/scsi/hpsa_cmd.h19
2 files changed, 184 insertions, 14 deletions
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 092d06d..442fef9 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -2027,6 +2027,14 @@ static void hpsa_debug_map_buff(struct ctlr_info *h, int rc,
le16_to_cpu(map_buff->row_cnt));
dev_info(&h->pdev->dev, "layout_map_count = %u\n",
le16_to_cpu(map_buff->layout_map_count));
+ dev_info(&h->pdev->dev, "flags = %u\n",
+ le16_to_cpu(map_buff->flags));
+ if (map_buff->flags & RAID_MAP_FLAG_ENCRYPT_ON)
+ dev_info(&h->pdev->dev, "encrypytion = ON\n");
+ else
+ dev_info(&h->pdev->dev, "encrypytion = OFF\n");
+ dev_info(&h->pdev->dev, "dekindex = %u\n",
+ le16_to_cpu(map_buff->dekindex));
map_cnt = le16_to_cpu(map_buff->layout_map_count);
for (map = 0; map < map_cnt; map++) {
@@ -2967,6 +2975,128 @@ static int hpsa_scsi_ioaccel_direct_map(struct ctlr_info *h,
cmd->cmnd, cmd->cmd_len, dev->scsi3addr);
}
+/*
+ * Set encryption parameters for the ioaccel2 request
+ */
+static void set_encrypt_ioaccel2(struct ctlr_info *h,
+ struct CommandList *c, struct io_accel2_cmd *cp)
+{
+ struct scsi_cmnd *cmd = c->scsi_cmd;
+ struct hpsa_scsi_dev_t *dev = cmd->device->hostdata;
+ struct raid_map_data *map = &dev->raid_map;
+ u64 first_block;
+
+ BUG_ON(!(dev->offload_config && dev->offload_enabled));
+
+ /* Are we doing encryption on this device */
+ if (!(map->flags & RAID_MAP_FLAG_ENCRYPT_ON))
+ return;
+ /* Set the data encryption key index. */
+ cp->dekindex = map->dekindex;
+
+ /* Set the encryption enable flag, encoded into direction field. */
+ cp->direction |= IOACCEL2_DIRECTION_ENCRYPT_MASK;
+
+ /* Set encryption tweak values based on logical block address
+ * If block size is 512, tweak value is LBA.
+ * For other block sizes, tweak is (LBA * block size)/ 512)
+ */
+ switch (cmd->cmnd[0]) {
+ /* Required? 6-byte cdbs eliminated by fixup_ioaccel_cdb */
+ case WRITE_6:
+ case READ_6:
+ if (map->volume_blk_size == 512) {
+ cp->tweak_lower =
+ (((u32) cmd->cmnd[2]) << 8) |
+ cmd->cmnd[3];
+ cp->tweak_upper = 0;
+ } else {
+ first_block =
+ (((u64) cmd->cmnd[2]) << 8) |
+ cmd->cmnd[3];
+ first_block = (first_block * map->volume_blk_size)/512;
+ cp->tweak_lower = (u32)first_block;
+ cp->tweak_upper = (u32)(first_block >> 32);
+ }
+ break;
+ case WRITE_10:
+ case READ_10:
+ if (map->volume_blk_size == 512) {
+ cp->tweak_lower =
+ (((u32) cmd->cmnd[2]) << 24) |
+ (((u32) cmd->cmnd[3]) << 16) |
+ (((u32) cmd->cmnd[4]) << 8) |
+ cmd->cmnd[5];
+ cp->tweak_upper = 0;
+ } else {
+ first_block =
+ (((u64) cmd->cmnd[2]) << 24) |
+ (((u64) cmd->cmnd[3]) << 16) |
+ (((u64) cmd->cmnd[4]) << 8) |
+ cmd->cmnd[5];
+ first_block = (first_block * map->volume_blk_size)/512;
+ cp->tweak_lower = (u32)first_block;
+ cp->tweak_upper = (u32)(first_block >> 32);
+ }
+ break;
+ /* Required? 12-byte cdbs eliminated by fixup_ioaccel_cdb */
+ case WRITE_12:
+ case READ_12:
+ if (map->volume_blk_size == 512) {
+ cp->tweak_lower =
+ (((u32) cmd->cmnd[2]) << 24) |
+ (((u32) cmd->cmnd[3]) << 16) |
+ (((u32) cmd->cmnd[4]) << 8) |
+ cmd->cmnd[5];
+ cp->tweak_upper = 0;
+ } else {
+ first_block =
+ (((u64) cmd->cmnd[2]) << 24) |
+ (((u64) cmd->cmnd[3]) << 16) |
+ (((u64) cmd->cmnd[4]) << 8) |
+ cmd->cmnd[5];
+ first_block = (first_block * map->volume_blk_size)/512;
+ cp->tweak_lower = (u32)first_block;
+ cp->tweak_upper = (u32)(first_block >> 32);
+ }
+ break;
+ case WRITE_16:
+ case READ_16:
+ if (map->volume_blk_size == 512) {
+ cp->tweak_lower =
+ (((u32) cmd->cmnd[6]) << 24) |
+ (((u32) cmd->cmnd[7]) << 16) |
+ (((u32) cmd->cmnd[8]) << 8) |
+ cmd->cmnd[9];
+ cp->tweak_upper =
+ (((u32) cmd->cmnd[2]) << 24) |
+ (((u32) cmd->cmnd[3]) << 16) |
+ (((u32) cmd->cmnd[4]) << 8) |
+ cmd->cmnd[5];
+ } else {
+ first_block =
+ (((u64) cmd->cmnd[2]) << 56) |
+ (((u64) cmd->cmnd[3]) << 48) |
+ (((u64) cmd->cmnd[4]) << 40) |
+ (((u64) cmd->cmnd[5]) << 32) |
+ (((u64) cmd->cmnd[6]) << 24) |
+ (((u64) cmd->cmnd[7]) << 16) |
+ (((u64) cmd->cmnd[8]) << 8) |
+ cmd->cmnd[9];
+ first_block = (first_block * map->volume_blk_size)/512;
+ cp->tweak_lower = (u32)first_block;
+ cp->tweak_upper = (u32)(first_block >> 32);
+ }
+ break;
+ default:
+ dev_err(&h->pdev->dev,
+ "ERROR: %s: IOACCEL request CDB size not supported for encryption\n",
+ __func__);
+ BUG();
+ break;
+ }
+}
+
static int hpsa_scsi_ioaccel2_queue_command(struct ctlr_info *h,
struct CommandList *c, u32 ioaccel_handle, u8 *cdb, int cdb_len,
u8 *scsi3addr)
@@ -3016,13 +3146,16 @@ static int hpsa_scsi_ioaccel2_queue_command(struct ctlr_info *h,
switch (cmd->sc_data_direction) {
case DMA_TO_DEVICE:
- cp->direction = IOACCEL2_DIR_DATA_OUT;
+ cp->direction &= ~IOACCEL2_DIRECTION_MASK;
+ cp->direction |= IOACCEL2_DIR_DATA_OUT;
break;
case DMA_FROM_DEVICE:
- cp->direction = IOACCEL2_DIR_DATA_IN;
+ cp->direction &= ~IOACCEL2_DIRECTION_MASK;
+ cp->direction |= IOACCEL2_DIR_DATA_IN;
break;
case DMA_NONE:
- cp->direction = IOACCEL2_DIR_NO_DATA;
+ cp->direction &= ~IOACCEL2_DIRECTION_MASK;
+ cp->direction |= IOACCEL2_DIR_NO_DATA;
break;
default:
dev_err(&h->pdev->dev, "unknown data direction: %d\n",
@@ -3031,10 +3164,15 @@ static int hpsa_scsi_ioaccel2_queue_command(struct ctlr_info *h,
break;
}
} else {
- cp->direction = IOACCEL2_DIR_NO_DATA;
+ cp->direction &= ~IOACCEL2_DIRECTION_MASK;
+ cp->direction |= IOACCEL2_DIR_NO_DATA;
}
+
+ /* Set encryption parameters, if necessary */
+ set_encrypt_ioaccel2(h, c, cp);
+
cp->scsi_nexus = ioaccel_handle;
- cp->Tag.lower = (c->cmdindex << DIRECT_LOOKUP_SHIFT) |
+ cp->Tag = (c->cmdindex << DIRECT_LOOKUP_SHIFT) |
DIRECT_LOOKUP_BIT;
memcpy(cp->cdb, cdb, sizeof(cp->cdb));
memset(cp->cciss_lun, 0, sizeof(cp->cciss_lun));
@@ -3792,8 +3930,9 @@ static void hpsa_get_tag(struct ctlr_info *h,
if (c->cmd_type == CMD_IOACCEL2) {
struct io_accel2_cmd *cm2 = (struct io_accel2_cmd *)
&h->ioaccel2_cmd_pool[c->cmdindex];
- *tagupper = cm2->Tag.upper;
- *taglower = cm2->Tag.lower;
+ /* upper tag not used in ioaccel2 mode */
+ memset(tagupper, 0, sizeof(*tagupper));
+ *taglower = cm2->Tag;
return;
}
*tagupper = c->Header.Tag.upper;
@@ -3841,8 +3980,8 @@ static int hpsa_send_abort(struct ctlr_info *h, unsigned char *scsi3addr,
break;
}
cmd_special_free(h, c);
- dev_dbg(&h->pdev->dev, "%s: Tag:0x%08x:%08x: Finished.\n", __func__,
- abort->Header.Tag.upper, abort->Header.Tag.lower);
+ dev_dbg(&h->pdev->dev, "%s: Tag:0x%08x:%08x: Finished.\n",
+ __func__, tagupper, taglower);
return rc;
}
@@ -6971,6 +7110,28 @@ static void __exit hpsa_cleanup(void)
static void __attribute__((unused)) verify_offsets(void)
{
#define VERIFY_OFFSET(member, offset) \
+ BUILD_BUG_ON(offsetof(struct raid_map_data, member) != offset)
+
+ VERIFY_OFFSET(structure_size, 0);
+ VERIFY_OFFSET(volume_blk_size, 4);
+ VERIFY_OFFSET(volume_blk_cnt, 8);
+ VERIFY_OFFSET(phys_blk_shift, 16);
+ VERIFY_OFFSET(parity_rotation_shift, 17);
+ VERIFY_OFFSET(strip_size, 18);
+ VERIFY_OFFSET(disk_starting_blk, 20);
+ VERIFY_OFFSET(disk_blk_cnt, 28);
+ VERIFY_OFFSET(data_disks_per_row, 36);
+ VERIFY_OFFSET(metadata_disks_per_row, 38);
+ VERIFY_OFFSET(row_cnt, 40);
+ VERIFY_OFFSET(layout_map_count, 42);
+ VERIFY_OFFSET(flags, 44);
+ VERIFY_OFFSET(dekindex, 46);
+ /* VERIFY_OFFSET(reserved, 48 */
+ VERIFY_OFFSET(data, 64);
+
+#undef VERIFY_OFFSET
+
+#define VERIFY_OFFSET(member, offset) \
BUILD_BUG_ON(offsetof(struct io_accel2_cmd, member) != offset)
VERIFY_OFFSET(IU_type, 0);
diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h
index 7768092..eaa7fda 100644
--- a/drivers/scsi/hpsa_cmd.h
+++ b/drivers/scsi/hpsa_cmd.h
@@ -209,7 +209,10 @@ struct raid_map_data {
u16 row_cnt; /* rows in each layout map */
u16 layout_map_count; /* layout maps (1 map per mirror/parity
* group) */
- u8 reserved[20];
+ u16 flags; /* Bit 0 set if encryption enabled */
+#define RAID_MAP_FLAG_ENCRYPT_ON 0x01
+ u16 dekindex; /* Data encryption key index. */
+ u8 reserved[16];
struct raid_map_disk_data data[RAID_MAP_MAX_ENTRIES];
};
@@ -502,11 +505,17 @@ struct io_accel2_scsi_response {
*/
struct io_accel2_cmd {
u8 IU_type; /* IU Type */
- u8 direction; /* Transfer direction, 2 bits */
+ u8 direction; /* direction, memtype, and encryption */
+#define IOACCEL2_DIRECTION_MASK 0x03 /* bits 0,1: direction */
+#define IOACCEL2_DIRECTION_MEMTYPE_MASK 0x04 /* bit 2: memtype source/dest */
+ /* 0b=PCIe, 1b=DDR */
+#define IOACCEL2_DIRECTION_ENCRYPT_MASK 0x08 /* bit 3: encryption flag */
+ /* 0=off, 1=on */
u8 reply_queue; /* Reply Queue ID */
u8 reserved1; /* Reserved */
u32 scsi_nexus; /* Device Handle */
- struct vals32 Tag; /* cciss tag */
+ u32 Tag; /* cciss tag, lower 4 bytes only */
+ u32 tweak_lower; /* Encryption tweak, lower 4 bytes */
u8 cdb[16]; /* SCSI Command Descriptor Block */
u8 cciss_lun[8]; /* 8 byte SCSI address */
u32 data_len; /* Total bytes to transfer */
@@ -514,10 +523,10 @@ struct io_accel2_cmd {
#define IOACCEL2_PRIORITY_MASK 0x78
#define IOACCEL2_ATTR_MASK 0x07
u8 sg_count; /* Number of sg elements */
- u8 reserved3[2]; /* Reserved */
+ u16 dekindex; /* Data encryption key index */
u64 err_ptr; /* Error Pointer */
u32 err_len; /* Error Length*/
- u8 reserved4[4]; /* Reserved */
+ u32 tweak_upper; /* Encryption tweak, upper 4 bytes */
struct ioaccel2_sg_element sg[IOACCEL2_MAXSGENTRIES];
struct io_accel2_scsi_response error_data;
u8 pad[IOACCEL2_PAD];