All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/48] hpsa driver updates
@ 2015-01-23 22:41 Don Brace
  2015-01-23 22:41 ` [PATCH v2 01/48] hpsa: correct endian sparse warnings Don Brace
                   ` (47 more replies)
  0 siblings, 48 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:41 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

This patch set is based on Linus's tree.

The changes are:
 - correct sparse warnings
 - correct memory leaks
 - correct kdump issues
 - correct queue depth updates
 - cleanup function return values
 - cleanup and enhance messages
 - cleanup and enhance error handling
 - minor code refactoring
 - performance enhancements.
 - removal of command queueing in driver
 - elimination of race conditions around aborts
 - change to internal driver workqueues

---

Don Brace (12):
      hpsa: correct endian sparse warnings
      hpsa: change how SA controllers are reset
      hpsa: correct change_queue_depth
      hpsa: do not queue commands internally in driver
      hpsa: use workqueue to resubmit failed ioaccel commands
      hpsa: honor queue depth of physical devices
      hpsa: count passthru cmds with atomics, not a spin locked int
      hpsa: slightly optimize SA5_performant_completed
      hpsa: return failed from device reset/abort handlers
      hpsa: add in gen9 controller model names
      hpsa: add in P840ar controller model name
      hpsa: Use local workqueues instead of system workqueues

Fabian Frederick (1):
      hpsa: Fix -Wunused-but-set-variable warning

Robert Elliott (16):
      hpsa: adjust RAID-1, RAID-1ADM, and RAID-6 names
      hpsa: rename free_irqs to hpsa_free_irqs
      hpsa: notice all request_irq errors
      hpsa: remove 0x from queue depth print which is in decimal
      hpsa: propagate hard_reset failures in reset_devices mode
      hpsa: propagate return value from board ID lookup
      hpsa: downgrade the Waiting for no-op print to dev_info
      hpsa: report failure to ioremap config table
      hpsa: rename hpsa_request_irq to hpsa_request_irqs
      hpsa: pass error from pci_set_consistent_dma_mask from hpsa_message
      hpsa: report allocation failures while allocating SG chain blocks
      hpsa: fix memory leak in hpsa_alloc_cmd_pool
      hpsa: avoid unneccesary calls to resource freeing functions
      hpsa: optimize cmd_alloc function by remembering last allocation
      hpsa: shorten the wait for the CISS doorbell mode change ack
      hpsa: detect and report failures changing controller transport modes

Stephen Cameron (13):
      hpsa: trivial message and comment clean ups
      hpsa: reserve some commands for use by driver
      hpsa: get rid of cmd_special_alloc and cmd_special_free
      hpsa: do not request device rescan on every ioaccel path error
      hpsa: factor out hpsa_ciss_submit function
      hpsa: do not check for msi(x) in interrupt_pending
      hpsa: remove incorrect BUG_ONs checking for raid offload enable
      hpsa: do not ack controller events on controllers that do not support it
      hpsa: guard against overflowing raid map array
      hpsa: check for ctlr lockup after command allocation in main io path
      hpsa: do not use a void pointer for scsi_cmd field of struct CommandList
      hpsa: print CDBs instead of kernel virtual addresses for uncommon errors
      hpsa: do not use function pointers in fast path command submission

Tomas Henzl (2):
      hpsa: fix memory leak in kdump hard reset
      hpsa: turn off interrupts when kdump starts

Webb Scales (4):
      hpsa: refactor hpsa_find_board_params() to encapsulate legacy test
      hpsa: fix race between abort handler and main i/o path
      hpsa: move SG descriptor set-up out of hpsa_scatter_gather()
      hpsa: refactor duplicated scan completion code into a new routine


 drivers/scsi/hpsa.c     | 1858 ++++++++++++++++++++++++-----------------------
 drivers/scsi/hpsa.h     |   61 +-
 drivers/scsi/hpsa_cmd.h |  334 ++++++--
 3 files changed, 1203 insertions(+), 1050 deletions(-)

--
Signature

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [PATCH v2 01/48] hpsa: correct endian sparse warnings
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
@ 2015-01-23 22:41 ` Don Brace
  2015-01-23 22:41 ` [PATCH v2 02/48] hpsa: fix memory leak in kdump hard reset Don Brace
                   ` (46 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:41 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

Correct endiness issues reported by sparse. SA controllers are
little endian. This patch ensures endiness correctness.

Signed-off-by: Don Brace <don.brace@pmcs.com>
Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Reviewed-by: Webb Scales <webbnh@hp.com>
---
 drivers/scsi/hpsa.c     |  275 +++++++++++++++++++----------------------------
 drivers/scsi/hpsa_cmd.h |  172 +++++++++++++++--------------
 2 files changed, 198 insertions(+), 249 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 6bb4611..2b9baea 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -50,6 +50,7 @@
 #include <linux/jiffies.h>
 #include <linux/percpu-defs.h>
 #include <linux/percpu.h>
+#include <asm/unaligned.h>
 #include <asm/div64.h>
 #include "hpsa_cmd.h"
 #include "hpsa.h"
@@ -229,7 +230,7 @@ static void check_ioctl_unit_attention(struct ctlr_info *h,
 	struct CommandList *c);
 /* performant mode helper functions */
 static void calc_bucket_map(int *bucket, int num_buckets,
-	int nsgs, int min_blocks, int *bucket_map);
+	int nsgs, int min_blocks, u32 *bucket_map);
 static void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h);
 static inline u32 next_command(struct ctlr_info *h, u8 q);
 static int hpsa_find_cfg_addrs(struct pci_dev *pdev, void __iomem *vaddr,
@@ -919,7 +920,7 @@ static int hpsa_scsi_add_entry(struct ctlr_info *h, int hostno,
 
 	/* If this device a non-zero lun of a multi-lun device
 	 * byte 4 of the 8-byte LUN addr will contain the logical
-	 * unit no, zero otherise.
+	 * unit no, zero otherwise.
 	 */
 	if (device->scsi3addr[4] == 0) {
 		/* This is not a non-zero lun of a multi-lun device */
@@ -1504,7 +1505,7 @@ static int hpsa_map_sg_chain_block(struct ctlr_info *h,
 	chain_block = h->cmd_sg_list[c->cmdindex];
 	chain_sg->Ext = cpu_to_le32(HPSA_SG_CHAIN);
 	chain_len = sizeof(*chain_sg) *
-		(c->Header.SGTotal - h->max_cmd_sg_entries);
+		(le16_to_cpu(c->Header.SGTotal) - h->max_cmd_sg_entries);
 	chain_sg->Len = cpu_to_le32(chain_len);
 	temp64 = pci_map_single(h->pdev, chain_block, chain_len,
 				PCI_DMA_TODEVICE);
@@ -1693,7 +1694,7 @@ static void complete_scsi_command(struct CommandList *cp)
 
 	scsi_dma_unmap(cmd); /* undo the DMA mappings */
 	if ((cp->cmd_type == CMD_SCSI) &&
-		(cp->Header.SGTotal > h->max_cmd_sg_entries))
+		(le16_to_cpu(cp->Header.SGTotal) > h->max_cmd_sg_entries))
 		hpsa_unmap_sg_chain_block(h, cp);
 
 	cmd->result = (DID_OK << 16); 		/* host byte */
@@ -1726,8 +1727,10 @@ static void complete_scsi_command(struct CommandList *cp)
 	 */
 	if (cp->cmd_type == CMD_IOACCEL1) {
 		struct io_accel1_cmd *c = &h->ioaccel_cmd_pool[cp->cmdindex];
-		cp->Header.SGList = cp->Header.SGTotal = scsi_sg_count(cmd);
-		cp->Request.CDBLen = c->io_flags & IOACCEL1_IOFLAGS_CDBLEN_MASK;
+		cp->Header.SGList = scsi_sg_count(cmd);
+		cp->Header.SGTotal = cpu_to_le16(cp->Header.SGList);
+		cp->Request.CDBLen = le16_to_cpu(c->io_flags) &
+			IOACCEL1_IOFLAGS_CDBLEN_MASK;
 		cp->Header.tag = c->tag;
 		memcpy(cp->Header.LUN.LunAddrBytes, c->CISS_LUN, 8);
 		memcpy(cp->Request.CDB, c->CDB, cp->Request.CDBLen);
@@ -2191,15 +2194,13 @@ 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",
+	dev_info(&h->pdev->dev, "flags = 0x%x\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, "encrypytion = %s\n",
+			le16_to_cpu(map_buff->flags) &
+			RAID_MAP_FLAG_ENCRYPT_ON ?  "ON" : "OFF");
 	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++) {
 		dev_info(&h->pdev->dev, "Map%u:\n", map);
@@ -2741,8 +2742,8 @@ static int hpsa_get_pdisk_of_ioaccel2(struct ctlr_info *h,
 	struct scsi_cmnd *scmd;	/* scsi command within request being aborted */
 	struct hpsa_scsi_dev_t *d; /* device of request being aborted */
 	struct io_accel2_cmd *c2a; /* ioaccel2 command to abort */
-	u32 it_nexus;		/* 4 byte device handle for the ioaccel2 cmd */
-	u32 scsi_nexus;		/* 4 byte device handle for the ioaccel2 cmd */
+	__le32 it_nexus;	/* 4 byte device handle for the ioaccel2 cmd */
+	__le32 scsi_nexus;	/* 4 byte device handle for the ioaccel2 cmd */
 
 	if (ioaccel2_cmd_to_abort->cmd_type != CMD_IOACCEL2)
 		return 0; /* no match */
@@ -2761,8 +2762,8 @@ static int hpsa_get_pdisk_of_ioaccel2(struct ctlr_info *h,
 		return 0; /* no match */
 
 	it_nexus = cpu_to_le32(d->ioaccel_handle);
-	scsi_nexus = cpu_to_le32(c2a->scsi_nexus);
-	find = c2a->scsi_nexus;
+	scsi_nexus = c2a->scsi_nexus;
+	find = le32_to_cpu(c2a->scsi_nexus);
 
 	if (h->raid_offload_debug > 0)
 		dev_info(&h->pdev->dev,
@@ -3284,11 +3285,11 @@ static int hpsa_scsi_ioaccel1_queue_command(struct ctlr_info *h,
 
 	c->Header.SGList = use_sg;
 	/* Fill out the command structure to submit */
-	cp->dev_handle = ioaccel_handle & 0xFFFF;
-	cp->transfer_len = total_len;
-	cp->io_flags = IOACCEL1_IOFLAGS_IO_REQ |
-			(cdb_len & IOACCEL1_IOFLAGS_CDBLEN_MASK);
-	cp->control = control;
+	cp->dev_handle = cpu_to_le16(ioaccel_handle & 0xFFFF);
+	cp->transfer_len = cpu_to_le32(total_len);
+	cp->io_flags = cpu_to_le16(IOACCEL1_IOFLAGS_IO_REQ |
+			(cdb_len & IOACCEL1_IOFLAGS_CDBLEN_MASK));
+	cp->control = cpu_to_le32(control);
 	memcpy(cp->CDB, cdb, cdb_len);
 	memcpy(cp->CISS_LUN, scsi3addr, 8);
 	/* Tag was already set at init time. */
@@ -3324,7 +3325,7 @@ static void set_encrypt_ioaccel2(struct ctlr_info *h,
 	BUG_ON(!(dev->offload_config && dev->offload_enabled));
 
 	/* Are we doing encryption on this device */
-	if (!(map->flags & RAID_MAP_FLAG_ENCRYPT_ON))
+	if (!(le16_to_cpu(map->flags) & RAID_MAP_FLAG_ENCRYPT_ON))
 		return;
 	/* Set the data encryption key index. */
 	cp->dekindex = map->dekindex;
@@ -3340,96 +3341,33 @@ static void set_encrypt_ioaccel2(struct ctlr_info *h,
 	/* 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);
-		}
+		first_block = get_unaligned_be16(&cmd->cmnd[2]);
 		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);
-		}
+		first_block = get_unaligned_be32(&cmd->cmnd[2]);
 		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);
-		}
+		first_block = get_unaligned_be64(&cmd->cmnd[2]);
 		break;
 	default:
 		dev_err(&h->pdev->dev,
-			"ERROR: %s: IOACCEL request CDB size not supported for encryption\n",
-			__func__);
+			"ERROR: %s: size (0x%x) not supported for encryption\n",
+			__func__, cmd->cmnd[0]);
 		BUG();
 		break;
 	}
+
+	if (le32_to_cpu(map->volume_blk_size) != 512)
+		first_block = first_block *
+				le32_to_cpu(map->volume_blk_size)/512;
+
+	cp->tweak_lower = cpu_to_le32(first_block);
+	cp->tweak_upper = cpu_to_le32(first_block >> 32);
 }
 
 static int hpsa_scsi_ioaccel2_queue_command(struct ctlr_info *h,
@@ -3506,9 +3444,9 @@ static int hpsa_scsi_ioaccel2_queue_command(struct ctlr_info *h,
 	/* Set encryption parameters, if necessary */
 	set_encrypt_ioaccel2(h, c, cp);
 
-	cp->scsi_nexus = ioaccel_handle;
-	cp->Tag = (c->cmdindex << DIRECT_LOOKUP_SHIFT) |
-				DIRECT_LOOKUP_BIT;
+	cp->scsi_nexus = cpu_to_le32(ioaccel_handle);
+	cp->Tag = cpu_to_le32(c->cmdindex << DIRECT_LOOKUP_SHIFT |
+				DIRECT_LOOKUP_BIT);
 	memcpy(cp->cdb, cdb, sizeof(cp->cdb));
 
 	/* fill in sg elements */
@@ -3543,21 +3481,22 @@ static void raid_map_helper(struct raid_map_data *map,
 {
 	if (offload_to_mirror == 0)  {
 		/* use physical disk in the first mirrored group. */
-		*map_index %= map->data_disks_per_row;
+		*map_index %= le16_to_cpu(map->data_disks_per_row);
 		return;
 	}
 	do {
 		/* determine mirror group that *map_index indicates */
-		*current_group = *map_index / map->data_disks_per_row;
+		*current_group = *map_index /
+			le16_to_cpu(map->data_disks_per_row);
 		if (offload_to_mirror == *current_group)
 			continue;
-		if (*current_group < (map->layout_map_count - 1)) {
+		if (*current_group < le16_to_cpu(map->layout_map_count) - 1) {
 			/* select map index from next group */
-			*map_index += map->data_disks_per_row;
+			*map_index += le16_to_cpu(map->data_disks_per_row);
 			(*current_group)++;
 		} else {
 			/* select map index from first group */
-			*map_index %= map->data_disks_per_row;
+			*map_index %= le16_to_cpu(map->data_disks_per_row);
 			*current_group = 0;
 		}
 	} while (offload_to_mirror != *current_group);
@@ -3595,6 +3534,7 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h,
 	u32 disk_block_cnt;
 	u8 cdb[16];
 	u8 cdb_len;
+	u16 strip_size;
 #if BITS_PER_LONG == 32
 	u64 tmpdiv;
 #endif
@@ -3668,11 +3608,14 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h,
 		return IO_ACCEL_INELIGIBLE;
 
 	/* check for invalid block or wraparound */
-	if (last_block >= map->volume_blk_cnt || last_block < first_block)
+	if (last_block >= le64_to_cpu(map->volume_blk_cnt) ||
+		last_block < first_block)
 		return IO_ACCEL_INELIGIBLE;
 
 	/* calculate stripe information for the request */
-	blocks_per_row = map->data_disks_per_row * map->strip_size;
+	blocks_per_row = le16_to_cpu(map->data_disks_per_row) *
+				le16_to_cpu(map->strip_size);
+	strip_size = le16_to_cpu(map->strip_size);
 #if BITS_PER_LONG == 32
 	tmpdiv = first_block;
 	(void) do_div(tmpdiv, blocks_per_row);
@@ -3683,18 +3626,18 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h,
 	first_row_offset = (u32) (first_block - (first_row * blocks_per_row));
 	last_row_offset = (u32) (last_block - (last_row * blocks_per_row));
 	tmpdiv = first_row_offset;
-	(void) do_div(tmpdiv,  map->strip_size);
+	(void) do_div(tmpdiv, strip_size);
 	first_column = tmpdiv;
 	tmpdiv = last_row_offset;
-	(void) do_div(tmpdiv, map->strip_size);
+	(void) do_div(tmpdiv, strip_size);
 	last_column = tmpdiv;
 #else
 	first_row = first_block / blocks_per_row;
 	last_row = last_block / blocks_per_row;
 	first_row_offset = (u32) (first_block - (first_row * blocks_per_row));
 	last_row_offset = (u32) (last_block - (last_row * blocks_per_row));
-	first_column = first_row_offset / map->strip_size;
-	last_column = last_row_offset / map->strip_size;
+	first_column = first_row_offset / strip_size;
+	last_column = last_row_offset / strip_size;
 #endif
 
 	/* if this isn't a single row/column then give to the controller */
@@ -3702,10 +3645,10 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h,
 		return IO_ACCEL_INELIGIBLE;
 
 	/* proceeding with driver mapping */
-	total_disks_per_row = map->data_disks_per_row +
-				map->metadata_disks_per_row;
+	total_disks_per_row = le16_to_cpu(map->data_disks_per_row) +
+				le16_to_cpu(map->metadata_disks_per_row);
 	map_row = ((u32)(first_row >> map->parity_rotation_shift)) %
-				map->row_cnt;
+				le16_to_cpu(map->row_cnt);
 	map_index = (map_row * total_disks_per_row) + first_column;
 
 	switch (dev->raid_level) {
@@ -3716,23 +3659,24 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h,
 		 * (2-drive R1 and R10 with even # of drives.)
 		 * Appropriate for SSDs, not optimal for HDDs
 		 */
-		BUG_ON(map->layout_map_count != 2);
+		BUG_ON(le16_to_cpu(map->layout_map_count) != 2);
 		if (dev->offload_to_mirror)
-			map_index += map->data_disks_per_row;
+			map_index += le16_to_cpu(map->data_disks_per_row);
 		dev->offload_to_mirror = !dev->offload_to_mirror;
 		break;
 	case HPSA_RAID_ADM:
 		/* Handles N-way mirrors  (R1-ADM)
 		 * and R10 with # of drives divisible by 3.)
 		 */
-		BUG_ON(map->layout_map_count != 3);
+		BUG_ON(le16_to_cpu(map->layout_map_count) != 3);
 
 		offload_to_mirror = dev->offload_to_mirror;
 		raid_map_helper(map, offload_to_mirror,
 				&map_index, &current_group);
 		/* set mirror group to use next time */
 		offload_to_mirror =
-			(offload_to_mirror >= map->layout_map_count - 1)
+			(offload_to_mirror >=
+			le16_to_cpu(map->layout_map_count) - 1)
 			? 0 : offload_to_mirror + 1;
 		dev->offload_to_mirror = offload_to_mirror;
 		/* Avoid direct use of dev->offload_to_mirror within this
@@ -3742,14 +3686,16 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h,
 		break;
 	case HPSA_RAID_5:
 	case HPSA_RAID_6:
-		if (map->layout_map_count <= 1)
+		if (le16_to_cpu(map->layout_map_count) <= 1)
 			break;
 
 		/* Verify first and last block are in same RAID group */
 		r5or6_blocks_per_row =
-			map->strip_size * map->data_disks_per_row;
+			le16_to_cpu(map->strip_size) *
+			le16_to_cpu(map->data_disks_per_row);
 		BUG_ON(r5or6_blocks_per_row == 0);
-		stripesize = r5or6_blocks_per_row * map->layout_map_count;
+		stripesize = r5or6_blocks_per_row *
+			le16_to_cpu(map->layout_map_count);
 #if BITS_PER_LONG == 32
 		tmpdiv = first_block;
 		first_group = do_div(tmpdiv, stripesize);
@@ -3812,19 +3758,19 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h,
 						r5or6_blocks_per_row);
 
 		first_column = r5or6_first_column =
-			r5or6_first_row_offset / map->strip_size;
+			r5or6_first_row_offset / le16_to_cpu(map->strip_size);
 		r5or6_last_column =
-			r5or6_last_row_offset / map->strip_size;
+			r5or6_last_row_offset / le16_to_cpu(map->strip_size);
 #endif
 		if (r5or6_first_column != r5or6_last_column)
 			return IO_ACCEL_INELIGIBLE;
 
 		/* Request is eligible */
 		map_row = ((u32)(first_row >> map->parity_rotation_shift)) %
-			map->row_cnt;
+			le16_to_cpu(map->row_cnt);
 
 		map_index = (first_group *
-			(map->row_cnt * total_disks_per_row)) +
+			(le16_to_cpu(map->row_cnt) * total_disks_per_row)) +
 			(map_row * total_disks_per_row) + first_column;
 		break;
 	default:
@@ -3832,8 +3778,10 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h,
 	}
 
 	disk_handle = dd[map_index].ioaccel_handle;
-	disk_block = map->disk_starting_blk + (first_row * map->strip_size) +
-			(first_row_offset - (first_column * map->strip_size));
+	disk_block = le64_to_cpu(map->disk_starting_blk) +
+			first_row * le16_to_cpu(map->strip_size) +
+			(first_row_offset - first_column *
+			le16_to_cpu(map->strip_size));
 	disk_block_cnt = block_cnt;
 
 	/* handle differing logical/physical block sizes */
@@ -4227,13 +4175,15 @@ static void swizzle_abort_tag(u8 *tag)
 }
 
 static void hpsa_get_tag(struct ctlr_info *h,
-	struct CommandList *c, u32 *taglower, u32 *tagupper)
+	struct CommandList *c, __le32 *taglower, __le32 *tagupper)
 {
+	u64 tag;
 	if (c->cmd_type == CMD_IOACCEL1) {
 		struct io_accel1_cmd *cm1 = (struct io_accel1_cmd *)
 			&h->ioaccel_cmd_pool[c->cmdindex];
-		*tagupper = (u32) (cm1->tag >> 32);
-		*taglower = (u32) (cm1->tag & 0x0ffffffffULL);
+		tag = le64_to_cpu(cm1->tag);
+		*tagupper = cpu_to_le32(tag >> 32);
+		*taglower = cpu_to_le32(tag);
 		return;
 	}
 	if (c->cmd_type == CMD_IOACCEL2) {
@@ -4244,8 +4194,9 @@ static void hpsa_get_tag(struct ctlr_info *h,
 		*taglower = cm2->Tag;
 		return;
 	}
-	*tagupper = (u32) (c->Header.tag >> 32);
-	*taglower = (u32) (c->Header.tag & 0x0ffffffffULL);
+	tag = le64_to_cpu(c->Header.tag);
+	*tagupper = cpu_to_le32(tag >> 32);
+	*taglower = cpu_to_le32(tag);
 }
 
 static int hpsa_send_abort(struct ctlr_info *h, unsigned char *scsi3addr,
@@ -4254,7 +4205,7 @@ static int hpsa_send_abort(struct ctlr_info *h, unsigned char *scsi3addr,
 	int rc = IO_OK;
 	struct CommandList *c;
 	struct ErrorInfo *ei;
-	u32 tagupper, taglower;
+	__le32 tagupper, taglower;
 
 	c = cmd_special_alloc(h);
 	if (c == NULL) {	/* trouble... */
@@ -4479,7 +4430,7 @@ static int hpsa_eh_abort_handler(struct scsi_cmnd *sc)
 	struct scsi_cmnd *as;	/* ptr to scsi cmd inside aborted command. */
 	char msg[256];		/* For debug messaging. */
 	int ml = 0;
-	u32 tagupper, taglower;
+	__le32 tagupper, taglower;
 
 	/* Find the controller of the command to be aborted */
 	h = sdev_to_hba(sc->device);
@@ -4884,7 +4835,7 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp)
 	}
 	memcpy(&c->Header.LUN, &iocommand.LUN_info, sizeof(c->Header.LUN));
 	/* use the kernel address the cmd block for tag */
-	c->Header.tag = c->busaddr;
+	c->Header.tag = cpu_to_le64(c->busaddr);
 
 	/* Fill in Request block */
 	memcpy(&c->Request, &iocommand.Request,
@@ -4940,7 +4891,6 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp)
 	u64 temp64;
 	BYTE sg_used = 0;
 	int status = 0;
-	int i;
 	u32 left;
 	u32 sz;
 	BYTE __user *data_ptr;
@@ -5014,7 +4964,7 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp)
 	c->Header.SGList = (u8) sg_used;
 	c->Header.SGTotal = cpu_to_le16(sg_used);
 	memcpy(&c->Header.LUN, &ioc->LUN_info, sizeof(c->Header.LUN));
-	c->Header.tag = c->busaddr;
+	c->Header.tag = cpu_to_le64(c->busaddr);
 	memcpy(&c->Request, &ioc->Request, sizeof(c->Request));
 	if (ioc->buf_size > 0) {
 		int i;
@@ -5047,6 +4997,8 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp)
 		goto cleanup0;
 	}
 	if ((ioc->Request.Type.Direction & XFER_READ) && ioc->buf_size > 0) {
+		int i;
+
 		/* Copy the data out of the buffer we created */
 		BYTE __user *ptr = ioc->buf;
 		for (i = 0; i < sg_used; i++) {
@@ -5062,6 +5014,8 @@ cleanup0:
 	cmd_special_free(h, c);
 cleanup1:
 	if (buff) {
+		int i;
+
 		for (i = 0; i < sg_used; i++)
 			kfree(buff[i]);
 		kfree(buff);
@@ -5173,7 +5127,6 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
 {
 	int pci_dir = XFER_NONE;
 	struct CommandList *a; /* for commands to be aborted */
-	u32 tupper, tlower;
 
 	c->cmd_type = CMD_IOCTL_PEND;
 	c->Header.ReplyQueue = 0;
@@ -5184,7 +5137,7 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
 		c->Header.SGList = 0;
 		c->Header.SGTotal = cpu_to_le16(0);
 	}
-	c->Header.tag = c->busaddr;
+	c->Header.tag = cpu_to_le64(c->busaddr);
 	memcpy(c->Header.LUN.LunAddrBytes, scsi3addr, 8);
 
 	if (cmd_type == TYPE_CMD) {
@@ -5281,10 +5234,9 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
 			break;
 		case  HPSA_ABORT_MSG:
 			a = buff;       /* point to command to be aborted */
-			dev_dbg(&h->pdev->dev, "Abort Tag:0x%016llx using request Tag:0x%016llx",
+			dev_dbg(&h->pdev->dev,
+				"Abort Tag:0x%016llx request Tag:0x%016llx",
 				a->Header.tag, c->Header.tag);
-			tlower = (u32) (a->Header.tag >> 32);
-			tupper = (u32) (a->Header.tag & 0x0ffffffffULL);
 			c->Request.CDBLen = 16;
 			c->Request.type_attr_dir =
 					TYPE_ATTR_DIR(cmd_type,
@@ -5295,14 +5247,8 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
 			c->Request.CDB[2] = 0x00; /* reserved */
 			c->Request.CDB[3] = 0x00; /* reserved */
 			/* Tag to abort goes in CDB[4]-CDB[11] */
-			c->Request.CDB[4] = tlower & 0xFF;
-			c->Request.CDB[5] = (tlower >> 8) & 0xFF;
-			c->Request.CDB[6] = (tlower >> 16) & 0xFF;
-			c->Request.CDB[7] = (tlower >> 24) & 0xFF;
-			c->Request.CDB[8] = tupper & 0xFF;
-			c->Request.CDB[9] = (tupper >> 8) & 0xFF;
-			c->Request.CDB[10] = (tupper >> 16) & 0xFF;
-			c->Request.CDB[11] = (tupper >> 24) & 0xFF;
+			memcpy(&c->Request.CDB[4], &a->Header.tag,
+				sizeof(a->Header.tag));
 			c->Request.CDB[12] = 0x00; /* reserved */
 			c->Request.CDB[13] = 0x00; /* reserved */
 			c->Request.CDB[14] = 0x00; /* reserved */
@@ -5633,7 +5579,8 @@ static int hpsa_message(struct pci_dev *pdev, unsigned char opcode,
 	static const size_t cmd_sz = sizeof(*cmd) +
 					sizeof(cmd->ErrorDescriptor);
 	dma_addr_t paddr64;
-	uint32_t paddr32, tag;
+	__le32 paddr32;
+	u32 tag;
 	void __iomem *vaddr;
 	int i, err;
 
@@ -5661,12 +5608,12 @@ static int hpsa_message(struct pci_dev *pdev, unsigned char opcode,
 	 * although there's no guarantee, we assume that the address is at
 	 * least 4-byte aligned (most likely, it's page-aligned).
 	 */
-	paddr32 = paddr64;
+	paddr32 = cpu_to_le32(paddr64);
 
 	cmd->CommandHeader.ReplyQueue = 0;
 	cmd->CommandHeader.SGList = 0;
 	cmd->CommandHeader.SGTotal = cpu_to_le16(0);
-	cmd->CommandHeader.tag = paddr32;
+	cmd->CommandHeader.tag = cpu_to_le64(paddr64);
 	memset(&cmd->CommandHeader.LUN.LunAddrBytes, 0, 8);
 
 	cmd->Request.CDBLen = 16;
@@ -5677,14 +5624,14 @@ static int hpsa_message(struct pci_dev *pdev, unsigned char opcode,
 	cmd->Request.CDB[1] = type;
 	memset(&cmd->Request.CDB[2], 0, 14); /* rest of the CDB is reserved */
 	cmd->ErrorDescriptor.Addr =
-			cpu_to_le64((paddr32 + sizeof(*cmd)));
+			cpu_to_le64((le32_to_cpu(paddr32) + sizeof(*cmd)));
 	cmd->ErrorDescriptor.Len = cpu_to_le32(sizeof(struct ErrorInfo));
 
-	writel(paddr32, vaddr + SA5_REQUEST_PORT_OFFSET);
+	writel(le32_to_cpu(paddr32), vaddr + SA5_REQUEST_PORT_OFFSET);
 
 	for (i = 0; i < HPSA_MSG_SEND_RETRY_LIMIT; i++) {
 		tag = readl(vaddr + SA5_REPLY_PORT_OFFSET);
-		if ((tag & ~HPSA_SIMPLE_ERROR_BITS) == paddr32)
+		if ((tag & ~HPSA_SIMPLE_ERROR_BITS) == paddr64)
 			break;
 		msleep(HPSA_MSG_SEND_RETRY_INTERVAL_MSECS);
 	}
@@ -5718,8 +5665,6 @@ static int hpsa_message(struct pci_dev *pdev, unsigned char opcode,
 static int hpsa_controller_hard_reset(struct pci_dev *pdev,
 	void __iomem *vaddr, u32 use_doorbell)
 {
-	u16 pmcsr;
-	int pos;
 
 	if (use_doorbell) {
 		/* For everything after the P600, the PCI power state method
@@ -5744,6 +5689,8 @@ static int hpsa_controller_hard_reset(struct pci_dev *pdev,
 		 * the controller, place the interface device in D3 then to D0,
 		 * this causes a secondary PCI reset which will reset the
 		 * controller." */
+		int pos;
+		u16 pmcsr;
 
 		pos = pci_find_capability(pdev, PCI_CAP_ID_PM);
 		if (pos == 0) {
@@ -5754,16 +5701,17 @@ static int hpsa_controller_hard_reset(struct pci_dev *pdev,
 		}
 		dev_info(&pdev->dev, "using PCI PM to reset controller\n");
 		/* enter the D3hot power management state */
-		pci_read_config_word(pdev, pos + PCI_PM_CTRL, &pmcsr);
+		pci_read_config_word(pdev, pos + PCI_PM_CTRL,
+					(__force u16 *)&pmcsr);
 		pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
-		pmcsr |= PCI_D3hot;
+		pmcsr |= (__force u16) PCI_D3hot;
 		pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr);
 
 		msleep(500);
 
 		/* enter the D0 power management state */
 		pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
-		pmcsr |= PCI_D0;
+		pmcsr |= (__force u16) PCI_D0;
 		pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr);
 
 		/*
@@ -7172,7 +7120,7 @@ static struct pci_driver hpsa_pci_driver = {
  * bits of the command address.
  */
 static void  calc_bucket_map(int bucket[], int num_buckets,
-	int nsgs, int min_blocks, int *bucket_map)
+	int nsgs, int min_blocks, u32 *bucket_map)
 {
 	int i, j, b, size;
 
@@ -7328,7 +7276,8 @@ static void hpsa_enter_performant_mode(struct ctlr_info *h, u32 trans_support)
 					(i * sizeof(struct ErrorInfo)));
 			cp->err_info_len = sizeof(struct ErrorInfo);
 			cp->sgl_offset = IOACCEL1_SGLOFFSET;
-			cp->host_context_flags = IOACCEL1_HCFLAGS_CISS_FORMAT;
+			cp->host_context_flags =
+				cpu_to_le16(IOACCEL1_HCFLAGS_CISS_FORMAT);
 			cp->timeout_sec = 0;
 			cp->ReplyQueue = 0;
 			cp->tag =
diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h
index cb988c4..9bae50c 100644
--- a/drivers/scsi/hpsa_cmd.h
+++ b/drivers/scsi/hpsa_cmd.h
@@ -206,27 +206,27 @@ struct raid_map_disk_data {
 };
 
 struct raid_map_data {
-	u32   structure_size;		/* Size of entire structure in bytes */
-	u32   volume_blk_size;		/* bytes / block in the volume */
-	u64   volume_blk_cnt;		/* logical blocks on the volume */
+	__le32   structure_size;	/* Size of entire structure in bytes */
+	__le32   volume_blk_size;	/* bytes / block in the volume */
+	__le64   volume_blk_cnt;	/* logical blocks on the volume */
 	u8    phys_blk_shift;		/* Shift factor to convert between
 					 * units of logical blocks and physical
 					 * disk blocks */
 	u8    parity_rotation_shift;	/* Shift factor to convert between units
 					 * of logical stripes and physical
 					 * stripes */
-	u16   strip_size;		/* blocks used on each disk / stripe */
-	u64   disk_starting_blk;	/* First disk block used in volume */
-	u64   disk_blk_cnt;		/* disk blocks used by volume / disk */
-	u16   data_disks_per_row;	/* data disk entries / row in the map */
-	u16   metadata_disks_per_row;	/* mirror/parity disk entries / row
+	__le16   strip_size;		/* blocks used on each disk / stripe */
+	__le64   disk_starting_blk;	/* First disk block used in volume */
+	__le64   disk_blk_cnt;		/* disk blocks used by volume / disk */
+	__le16   data_disks_per_row;	/* data disk entries / row in the map */
+	__le16   metadata_disks_per_row;/* mirror/parity disk entries / row
 					 * in the map */
-	u16   row_cnt;			/* rows in each layout map */
-	u16   layout_map_count;		/* layout maps (1 map per mirror/parity
+	__le16   row_cnt;		/* rows in each layout map */
+	__le16   layout_map_count;	/* layout maps (1 map per mirror/parity
 					 * group) */
-	u16   flags;			/* Bit 0 set if encryption enabled */
+	__le16   flags;			/* Bit 0 set if encryption enabled */
 #define RAID_MAP_FLAG_ENCRYPT_ON  0x01
-	u16   dekindex;			/* Data encryption key index. */
+	__le16   dekindex;		/* Data encryption key index. */
 	u8    reserved[16];
 	struct raid_map_disk_data data[RAID_MAP_MAX_ENTRIES];
 };
@@ -313,8 +313,8 @@ union LUNAddr {
 struct CommandListHeader {
 	u8              ReplyQueue;
 	u8              SGList;
-	u16             SGTotal;
-	u64		tag;
+	__le16          SGTotal;
+	__le64		tag;
 	union LUNAddr     LUN;
 };
 
@@ -338,14 +338,14 @@ struct RequestBlock {
 };
 
 struct ErrDescriptor {
-	u64 Addr;
-	u32  Len;
+	__le64 Addr;
+	__le32 Len;
 };
 
 struct SGDescriptor {
-	u64 Addr;
-	u32  Len;
-	u32  Ext;
+	__le64 Addr;
+	__le32 Len;
+	__le32 Ext;
 };
 
 union MoreErrInfo {
@@ -420,7 +420,7 @@ struct CommandList {
  */
 #define IOACCEL1_COMMANDLIST_ALIGNMENT 128
 struct io_accel1_cmd {
-	u16 dev_handle;			/* 0x00 - 0x01 */
+	__le16 dev_handle;		/* 0x00 - 0x01 */
 	u8  reserved1;			/* 0x02 */
 	u8  function;			/* 0x03 */
 	u8  reserved2[8];		/* 0x04 - 0x0B */
@@ -430,20 +430,20 @@ struct io_accel1_cmd {
 	u8  reserved4;			/* 0x13 */
 	u8  sgl_offset;			/* 0x14 */
 	u8  reserved5[7];		/* 0x15 - 0x1B */
-	u32 transfer_len;		/* 0x1C - 0x1F */
+	__le32 transfer_len;		/* 0x1C - 0x1F */
 	u8  reserved6[4];		/* 0x20 - 0x23 */
-	u16 io_flags;			/* 0x24 - 0x25 */
+	__le16 io_flags;		/* 0x24 - 0x25 */
 	u8  reserved7[14];		/* 0x26 - 0x33 */
 	u8  LUN[8];			/* 0x34 - 0x3B */
-	u32 control;			/* 0x3C - 0x3F */
+	__le32 control;			/* 0x3C - 0x3F */
 	u8  CDB[16];			/* 0x40 - 0x4F */
 	u8  reserved8[16];		/* 0x50 - 0x5F */
-	u16 host_context_flags;		/* 0x60 - 0x61 */
-	u16 timeout_sec;		/* 0x62 - 0x63 */
+	__le16 host_context_flags;	/* 0x60 - 0x61 */
+	__le16 timeout_sec;		/* 0x62 - 0x63 */
 	u8  ReplyQueue;			/* 0x64 */
 	u8  reserved9[3];		/* 0x65 - 0x67 */
-	u64 tag;			/* 0x68 - 0x6F */
-	u64 host_addr;			/* 0x70 - 0x77 */
+	__le64 tag;			/* 0x68 - 0x6F */
+	__le64 host_addr;		/* 0x70 - 0x77 */
 	u8  CISS_LUN[8];		/* 0x78 - 0x7F */
 	struct SGDescriptor SG[IOACCEL1_MAXSGENTRIES];
 } __aligned(IOACCEL1_COMMANDLIST_ALIGNMENT);
@@ -470,8 +470,8 @@ struct io_accel1_cmd {
 #define IOACCEL1_BUSADDR_CMDTYPE        0x00000060
 
 struct ioaccel2_sg_element {
-	u64 address;
-	u32 length;
+	__le64 address;
+	__le32 length;
 	u8 reserved[3];
 	u8 chain_indicator;
 #define IOACCEL2_CHAIN 0x80
@@ -526,20 +526,20 @@ struct io_accel2_cmd {
 					     /*     0=off, 1=on */
 	u8  reply_queue;		/* Reply Queue ID */
 	u8  reserved1;			/* Reserved */
-	u32 scsi_nexus;			/* Device Handle */
-	u32 Tag;			/* cciss tag, lower 4 bytes only */
-	u32 tweak_lower;		/* Encryption tweak, lower 4 bytes */
+	__le32 scsi_nexus;		/* Device Handle */
+	__le32 Tag;			/* cciss tag, lower 4 bytes only */
+	__le32 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 */
+	__le32 data_len;		/* Total bytes to transfer */
 	u8  cmd_priority_task_attr;	/* priority and task attrs */
 #define IOACCEL2_PRIORITY_MASK 0x78
 #define IOACCEL2_ATTR_MASK 0x07
 	u8  sg_count;			/* Number of sg elements */
-	u16 dekindex;			/* Data encryption key index */
-	u64 err_ptr;			/* Error Pointer */
-	u32 err_len;			/* Error Length*/
-	u32 tweak_upper;		/* Encryption tweak, upper 4 bytes */
+	__le16 dekindex;		/* Data encryption key index */
+	__le64 err_ptr;			/* Error Pointer */
+	__le32 err_len;			/* Error Length*/
+	__le32 tweak_upper;		/* Encryption tweak, upper 4 bytes */
 	struct ioaccel2_sg_element sg[IOACCEL2_MAXSGENTRIES];
 	struct io_accel2_scsi_response error_data;
 } __aligned(IOACCEL2_COMMANDLIST_ALIGNMENT);
@@ -563,18 +563,18 @@ struct hpsa_tmf_struct {
 	u8 reserved1;		/* byte 3 Reserved */
 	u32 it_nexus;		/* SCSI I-T Nexus */
 	u8 lun_id[8];		/* LUN ID for TMF request */
-	u64 tag;		/* cciss tag associated w/ request */
-	u64 abort_tag;		/* cciss tag of SCSI cmd or task to abort */
-	u64 error_ptr;		/* Error Pointer */
-	u32 error_len;		/* Error Length */
+	__le64 tag;		/* cciss tag associated w/ request */
+	__le64 abort_tag;	/* cciss tag of SCSI cmd or TMF to abort */
+	__le64 error_ptr;		/* Error Pointer */
+	__le32 error_len;		/* Error Length */
 };
 
 /* Configuration Table Structure */
 struct HostWrite {
-	u32 TransportRequest;
-	u32 command_pool_addr_hi;
-	u32 CoalIntDelay;
-	u32 CoalIntCount;
+	__le32		TransportRequest;
+	__le32		command_pool_addr_hi;
+	__le32		CoalIntDelay;
+	__le32		CoalIntCount;
 };
 
 #define SIMPLE_MODE     0x02
@@ -585,54 +585,54 @@ struct HostWrite {
 #define DRIVER_SUPPORT_UA_ENABLE        0x00000001
 
 struct CfgTable {
-	u8            Signature[4];
-	u32		SpecValence;
-	u32           TransportSupport;
-	u32           TransportActive;
-	struct 		HostWrite HostWrite;
-	u32           CmdsOutMax;
-	u32           BusTypes;
-	u32           TransMethodOffset;
-	u8            ServerName[16];
-	u32           HeartBeat;
-	u32           driver_support;
-#define			ENABLE_SCSI_PREFETCH 0x100
-#define			ENABLE_UNIT_ATTN 0x01
-	u32	 	MaxScatterGatherElements;
-	u32		MaxLogicalUnits;
-	u32		MaxPhysicalDevices;
-	u32		MaxPhysicalDrivesPerLogicalUnit;
-	u32		MaxPerformantModeCommands;
-	u32		MaxBlockFetch;
-	u32		PowerConservationSupport;
-	u32		PowerConservationEnable;
-	u32		TMFSupportFlags;
+	u8		Signature[4];
+	__le32		SpecValence;
+	__le32		TransportSupport;
+	__le32		TransportActive;
+	struct HostWrite HostWrite;
+	__le32		CmdsOutMax;
+	__le32		BusTypes;
+	__le32		TransMethodOffset;
+	u8		ServerName[16];
+	__le32		HeartBeat;
+	__le32		driver_support;
+#define			ENABLE_SCSI_PREFETCH		0x100
+#define			ENABLE_UNIT_ATTN		0x01
+	__le32		MaxScatterGatherElements;
+	__le32		MaxLogicalUnits;
+	__le32		MaxPhysicalDevices;
+	__le32		MaxPhysicalDrivesPerLogicalUnit;
+	__le32		MaxPerformantModeCommands;
+	__le32		MaxBlockFetch;
+	__le32		PowerConservationSupport;
+	__le32		PowerConservationEnable;
+	__le32		TMFSupportFlags;
 	u8		TMFTagMask[8];
 	u8		reserved[0x78 - 0x70];
-	u32		misc_fw_support; /* offset 0x78 */
-#define			MISC_FW_DOORBELL_RESET (0x02)
-#define			MISC_FW_DOORBELL_RESET2 (0x010)
-#define			MISC_FW_RAID_OFFLOAD_BASIC (0x020)
-#define			MISC_FW_EVENT_NOTIFY (0x080)
+	__le32		misc_fw_support;		/* offset 0x78 */
+#define			MISC_FW_DOORBELL_RESET		0x02
+#define			MISC_FW_DOORBELL_RESET2		0x010
+#define			MISC_FW_RAID_OFFLOAD_BASIC	0x020
+#define			MISC_FW_EVENT_NOTIFY		0x080
 	u8		driver_version[32];
-	u32             max_cached_write_size;
-	u8              driver_scratchpad[16];
-	u32             max_error_info_length;
-	u32		io_accel_max_embedded_sg_count;
-	u32		io_accel_request_size_offset;
-	u32		event_notify;
-#define HPSA_EVENT_NOTIFY_ACCEL_IO_PATH_STATE_CHANGE (1 << 30)
-#define HPSA_EVENT_NOTIFY_ACCEL_IO_PATH_CONFIG_CHANGE (1 << 31)
-	u32		clear_event_notify;
+	__le32		max_cached_write_size;
+	u8		driver_scratchpad[16];
+	__le32		max_error_info_length;
+	__le32		io_accel_max_embedded_sg_count;
+	__le32		io_accel_request_size_offset;
+	__le32		event_notify;
+#define		HPSA_EVENT_NOTIFY_ACCEL_IO_PATH_STATE_CHANGE (1 << 30)
+#define		HPSA_EVENT_NOTIFY_ACCEL_IO_PATH_CONFIG_CHANGE (1 << 31)
+	__le32		clear_event_notify;
 };
 
 #define NUM_BLOCKFETCH_ENTRIES 8
 struct TransTable_struct {
-	u32            BlockFetch[NUM_BLOCKFETCH_ENTRIES];
-	u32            RepQSize;
-	u32            RepQCount;
-	u32            RepQCtrAddrLow32;
-	u32            RepQCtrAddrHigh32;
+	__le32		BlockFetch[NUM_BLOCKFETCH_ENTRIES];
+	__le32		RepQSize;
+	__le32		RepQCount;
+	__le32		RepQCtrAddrLow32;
+	__le32		RepQCtrAddrHigh32;
 #define MAX_REPLY_QUEUES 64
 	struct vals32  RepQAddr[MAX_REPLY_QUEUES];
 };


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 02/48] hpsa: fix memory leak in kdump hard reset
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
  2015-01-23 22:41 ` [PATCH v2 01/48] hpsa: correct endian sparse warnings Don Brace
@ 2015-01-23 22:41 ` Don Brace
  2015-01-23 22:41 ` [PATCH v2 03/48] hpsa: turn off interrupts when kdump starts Don Brace
                   ` (45 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:41 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Tomas Henzl <thenzl@redhat.com>

There is a potential memory leak in hpsa_kdump_hard_reset_controller.


Reviewed-by: Don Brace <don.brace@pmcs.com>
Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Tomas Henzl <thenzl@redhat.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 2b9baea..d97f455 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -5840,7 +5840,7 @@ static int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
 	}
 	rc = write_driver_ver_to_cfgtable(cfgtable);
 	if (rc)
-		goto unmap_vaddr;
+		goto unmap_cfgtable;
 
 	/* If reset via doorbell register is supported, use that.
 	 * There are two such methods.  Favor the newest method.


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 03/48] hpsa: turn off interrupts when kdump starts
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
  2015-01-23 22:41 ` [PATCH v2 01/48] hpsa: correct endian sparse warnings Don Brace
  2015-01-23 22:41 ` [PATCH v2 02/48] hpsa: fix memory leak in kdump hard reset Don Brace
@ 2015-01-23 22:41 ` Don Brace
  2015-01-23 22:41 ` [PATCH v2 04/48] hpsa: change how SA controllers are reset Don Brace
                   ` (44 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:41 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Tomas Henzl <thenzl@redhat.com>

Sometimes when the card is restarted it may cause -
"irq 16: nobody cared (try booting with the "irqpoll" option)"
that is likely caused so, that the card, after the hard reset
finishes, pulls on the irq. Disabling the ints before or after
the hpsa_kdump_hard_reset_controller fixes it.

At this point we can't know in which state the card is,
so using SA5_INTR_OFF + SA5_REPLY_INTR_MASK_OFFSET defines directly,
instead of the function the drivers provides, seems to be apropriate.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |    9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index d97f455..9edacff 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -6370,6 +6370,7 @@ static void hpsa_hba_inquiry(struct ctlr_info *h)
 static int hpsa_init_reset_devices(struct pci_dev *pdev)
 {
 	int rc, i;
+	void __iomem *vaddr;
 
 	if (!reset_devices)
 		return 0;
@@ -6393,6 +6394,14 @@ static int hpsa_init_reset_devices(struct pci_dev *pdev)
 
 	pci_set_master(pdev);
 
+	vaddr = pci_ioremap_bar(pdev, 0);
+	if (vaddr == NULL) {
+		rc = -ENOMEM;
+		goto out_disable;
+	}
+	writel(SA5_INTR_OFF, vaddr + SA5_REPLY_INTR_MASK_OFFSET);
+	iounmap(vaddr);
+
 	/* Reset the controller with a PCI power-cycle or via doorbell */
 	rc = hpsa_kdump_hard_reset_controller(pdev);
 


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 04/48] hpsa: change how SA controllers are reset
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (2 preceding siblings ...)
  2015-01-23 22:41 ` [PATCH v2 03/48] hpsa: turn off interrupts when kdump starts Don Brace
@ 2015-01-23 22:41 ` Don Brace
  2015-01-23 22:41 ` [PATCH v2 05/48] hpsa: correct change_queue_depth Don Brace
                   ` (43 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:41 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

Change how SA controllers are reset by changing PCI power levels.
The hpsa driver was finding the PCI_PM_CTRL_STATE_MASK offset
then reading/writing a bitmask to change the power state. There
are kernel functions that do the same operations. Better to use
the kernel functions.

Signed-off-by: Don Brace <don.brace@pmcs.com>
Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Reviewed-by: Webb Scales <webbnh@hp.com>
---
 drivers/scsi/hpsa.c |   28 ++++++++++------------------
 1 file changed, 10 insertions(+), 18 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 9edacff..371d0a8 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -5689,30 +5689,22 @@ static int hpsa_controller_hard_reset(struct pci_dev *pdev,
 		 * the controller, place the interface device in D3 then to D0,
 		 * this causes a secondary PCI reset which will reset the
 		 * controller." */
-		int pos;
-		u16 pmcsr;
-
-		pos = pci_find_capability(pdev, PCI_CAP_ID_PM);
-		if (pos == 0) {
-			dev_err(&pdev->dev,
-				"hpsa_reset_controller: "
-				"PCI PM not supported\n");
-			return -ENODEV;
-		}
+
+		int rc = 0;
+
 		dev_info(&pdev->dev, "using PCI PM to reset controller\n");
+
 		/* enter the D3hot power management state */
-		pci_read_config_word(pdev, pos + PCI_PM_CTRL,
-					(__force u16 *)&pmcsr);
-		pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
-		pmcsr |= (__force u16) PCI_D3hot;
-		pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr);
+		rc = pci_set_power_state(pdev, PCI_D3hot);
+		if (rc)
+			return rc;
 
 		msleep(500);
 
 		/* enter the D0 power management state */
-		pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
-		pmcsr |= (__force u16) PCI_D0;
-		pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr);
+		rc = pci_set_power_state(pdev, PCI_D0);
+		if (rc)
+			return rc;
 
 		/*
 		 * The P600 requires a small delay when changing states.


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 05/48] hpsa: correct change_queue_depth
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (3 preceding siblings ...)
  2015-01-23 22:41 ` [PATCH v2 04/48] hpsa: change how SA controllers are reset Don Brace
@ 2015-01-23 22:41 ` Don Brace
  2015-01-23 22:41 ` [PATCH v2 06/48] hpsa: adjust RAID-1, RAID-1ADM, and RAID-6 names Don Brace
                   ` (42 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:41 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

We change drive queue depths to match drive reported queue depths.
The name of the SML function was changed from scsi_adjust_queue_depth
changed to scsi_change_queue_depth.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |   16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 371d0a8..7dfe829 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -217,6 +217,7 @@ static int hpsa_scsi_queue_command(struct Scsi_Host *h, struct scsi_cmnd *cmd);
 static void hpsa_scan_start(struct Scsi_Host *);
 static int hpsa_scan_finished(struct Scsi_Host *sh,
 	unsigned long elapsed_time);
+static int hpsa_change_queue_depth(struct scsi_device *sdev, int qdepth);
 
 static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd);
 static int hpsa_eh_abort_handler(struct scsi_cmnd *scsicmd);
@@ -672,7 +673,7 @@ static struct scsi_host_template hpsa_driver_template = {
 	.queuecommand		= hpsa_scsi_queue_command,
 	.scan_start		= hpsa_scan_start,
 	.scan_finished		= hpsa_scan_finished,
-	.change_queue_depth	= scsi_change_queue_depth,
+	.change_queue_depth	= hpsa_change_queue_depth,
 	.this_id		= -1,
 	.use_clustering		= ENABLE_CLUSTERING,
 	.eh_abort_handler	= hpsa_eh_abort_handler,
@@ -4007,6 +4008,19 @@ static void hpsa_scan_start(struct Scsi_Host *sh)
 	spin_unlock_irqrestore(&h->scan_lock, flags);
 }
 
+static int hpsa_change_queue_depth(struct scsi_device *sdev, int qdepth)
+{
+	struct ctlr_info *h = sdev_to_hba(sdev);
+
+	if (qdepth < 1)
+		qdepth = 1;
+	else
+		if (qdepth > h->nr_cmds)
+			qdepth = h->nr_cmds;
+	scsi_change_queue_depth(sdev, qdepth);
+	return sdev->queue_depth;
+}
+
 static int hpsa_scan_finished(struct Scsi_Host *sh,
 	unsigned long elapsed_time)
 {


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 06/48] hpsa: adjust RAID-1, RAID-1ADM, and RAID-6 names
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (4 preceding siblings ...)
  2015-01-23 22:41 ` [PATCH v2 05/48] hpsa: correct change_queue_depth Don Brace
@ 2015-01-23 22:41 ` Don Brace
  2015-01-23 22:41 ` [PATCH v2 07/48] hpsa: rename free_irqs to hpsa_free_irqs Don Brace
                   ` (41 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:41 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Robert Elliott <elliott@hp.com>

HP now uses RAID-6 rather than RAID-ADG (Advanced Data Guarding)
as the marketing name for our implementation of RAID-6.

The driver considers RAID-1 and RAID-1+0 to be the same level, and
considers RAID-1ADM and RAID-1+0ADM to be the same level.  Parenthesis
can be used to reflect the optional +0 portion of both those RAID levels.

Rename: RAID-ADG to RAID-6
	RAID-1(1+0) to RAID-1(+0)
	RAID-1(ADM) to RAID-1(+0)ADM

Also, add another const after the pointer type as suggested
by checkpatch.pl so the array is:
	static const char * const raid_label[]

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Robert Elliott <elliott@hp.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 7dfe829..4252b63 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -507,8 +507,8 @@ static inline int is_logical_dev_addr_mode(unsigned char scsi3addr[])
 	return (scsi3addr[3] & 0xC0) == 0x40;
 }
 
-static const char *raid_label[] = { "0", "4", "1(1+0)", "5", "5+1", "ADG",
-	"1(ADM)", "UNKNOWN"
+static const char * const raid_label[] = { "0", "4", "1(+0)", "5", "5+1", "6",
+	"1(+0)ADM", "UNKNOWN"
 };
 #define HPSA_RAID_0	0
 #define HPSA_RAID_4	1


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 07/48] hpsa: rename free_irqs to hpsa_free_irqs
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (5 preceding siblings ...)
  2015-01-23 22:41 ` [PATCH v2 06/48] hpsa: adjust RAID-1, RAID-1ADM, and RAID-6 names Don Brace
@ 2015-01-23 22:41 ` Don Brace
  2015-01-23 22:41 ` [PATCH v2 08/48] hpsa: Fix -Wunused-but-set-variable warning Don Brace
                   ` (40 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:41 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Robert Elliott <elliott@hp.com>

Change the function names to have hpsa prefix.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Robert Elliott <elliott@hp.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |   43 ++++++++++++++++++++++---------------------
 1 file changed, 22 insertions(+), 21 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 4252b63..dc81d88 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -6491,6 +6491,25 @@ static void hpsa_irq_affinity_hints(struct ctlr_info *h)
 	}
 }
 
+/* clear affinity hints and free MSI-X, MSI, or legacy INTx vectors */
+static void hpsa_free_irqs(struct ctlr_info *h)
+{
+	int i;
+
+	if (!h->msix_vector || h->intr_mode != PERF_MODE_INT) {
+		/* Single reply queue, only one irq to free */
+		i = h->intr_mode;
+		irq_set_affinity_hint(h->intr[i], NULL);
+		free_irq(h->intr[i], &h->q[i]);
+		return;
+	}
+
+	for (i = 0; i < h->msix_vector; i++) {
+		irq_set_affinity_hint(h->intr[i], NULL);
+		free_irq(h->intr[i], &h->q[i]);
+	}
+}
+
 static int hpsa_request_irq(struct ctlr_info *h,
 	irqreturn_t (*msixhandler)(int, void *),
 	irqreturn_t (*intxhandler)(int, void *))
@@ -6555,27 +6574,9 @@ static int hpsa_kdump_soft_reset(struct ctlr_info *h)
 	return 0;
 }
 
-static void free_irqs(struct ctlr_info *h)
-{
-	int i;
-
-	if (!h->msix_vector || h->intr_mode != PERF_MODE_INT) {
-		/* Single reply queue, only one irq to free */
-		i = h->intr_mode;
-		irq_set_affinity_hint(h->intr[i], NULL);
-		free_irq(h->intr[i], &h->q[i]);
-		return;
-	}
-
-	for (i = 0; i < h->msix_vector; i++) {
-		irq_set_affinity_hint(h->intr[i], NULL);
-		free_irq(h->intr[i], &h->q[i]);
-	}
-}
-
 static void hpsa_free_irqs_and_disable_msix(struct ctlr_info *h)
 {
-	free_irqs(h);
+	hpsa_free_irqs(h);
 #ifdef CONFIG_PCI_MSI
 	if (h->msix_vector) {
 		if (h->pdev->msix_enabled)
@@ -6937,7 +6938,7 @@ reinit_after_soft_reset:
 		spin_lock_irqsave(&h->lock, flags);
 		h->access.set_intr_mask(h, HPSA_INTR_OFF);
 		spin_unlock_irqrestore(&h->lock, flags);
-		free_irqs(h);
+		hpsa_free_irqs(h);
 		rc = hpsa_request_irq(h, hpsa_msix_discard_completions,
 					hpsa_intx_discard_completions);
 		if (rc) {
@@ -6997,7 +6998,7 @@ reinit_after_soft_reset:
 clean4:
 	hpsa_free_sg_chain_blocks(h);
 	hpsa_free_cmd_pool(h);
-	free_irqs(h);
+	hpsa_free_irqs(h);
 clean2:
 clean1:
 	if (h->lockup_detected)


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 08/48] hpsa: Fix -Wunused-but-set-variable warning
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (6 preceding siblings ...)
  2015-01-23 22:41 ` [PATCH v2 07/48] hpsa: rename free_irqs to hpsa_free_irqs Don Brace
@ 2015-01-23 22:41 ` Don Brace
  2015-01-23 22:41 ` [PATCH v2 09/48] hpsa: notice all request_irq errors Don Brace
                   ` (39 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:41 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Fabian Frederick <fabf@skynet.be>

Remove unused variable in hpsa_free_cmd_pool.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Fabian Frederick <fabf@skynet.be>
Acked-by: Don Brace <don.brace@pmcs.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index dc81d88..11d21ef 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -6482,11 +6482,11 @@ static void hpsa_free_cmd_pool(struct ctlr_info *h)
 
 static void hpsa_irq_affinity_hints(struct ctlr_info *h)
 {
-	int i, cpu, rc;
+	int i, cpu;
 
 	cpu = cpumask_first(cpu_online_mask);
 	for (i = 0; i < h->msix_vector; i++) {
-		rc = irq_set_affinity_hint(h->intr[i], get_cpu_mask(cpu));
+		irq_set_affinity_hint(h->intr[i], get_cpu_mask(cpu));
 		cpu = cpumask_next(cpu, cpu_online_mask);
 	}
 }


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 09/48] hpsa: notice all request_irq errors
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (7 preceding siblings ...)
  2015-01-23 22:41 ` [PATCH v2 08/48] hpsa: Fix -Wunused-but-set-variable warning Don Brace
@ 2015-01-23 22:41 ` Don Brace
  2015-01-23 22:41 ` [PATCH v2 10/48] hpsa: remove 0x from queue depth print which is in decimal Don Brace
                   ` (38 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:41 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Robert Elliott <elliott@hp.com>

In MSI and MSI-X mode, where hpsa asks for more than one interrupt,
hpsa_request_irqs forgets if the first request_irq call failed
if later ones succeed.

It needs to exit the loop on any failure rather than continue,
freeing all irqs that were requested until that point.

Also, it needs to clear out the q numbers up to MAX_REPLY_QUEUES.
The same is true for the general hpsa_free_irqs function.

Tested with error injection of -ENOSYS on the 4th call:
[    9.277691]  injecting error in inj_request_irq: 1 4
[    9.277780] hpsa 0000:02:00.0: failed to get irq 35 for hpsa1
[   10.711623] scsi host1: Error handler scsi_eh_1 exiting
[   10.739170] hpsa: probe of 0000:02:00.0 failed with error -38

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Robert Elliott <elliott@hp.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |   19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 11d21ef..97bb718 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -6508,6 +6508,8 @@ static void hpsa_free_irqs(struct ctlr_info *h)
 		irq_set_affinity_hint(h->intr[i], NULL);
 		free_irq(h->intr[i], &h->q[i]);
 	}
+	for (; i < MAX_REPLY_QUEUES; i++)
+		h->q[i] = 0;
 }
 
 static int hpsa_request_irq(struct ctlr_info *h,
@@ -6525,10 +6527,25 @@ static int hpsa_request_irq(struct ctlr_info *h,
 
 	if (h->intr_mode == PERF_MODE_INT && h->msix_vector > 0) {
 		/* If performant mode and MSI-X, use multiple reply queues */
-		for (i = 0; i < h->msix_vector; i++)
+		for (i = 0; i < h->msix_vector; i++) {
 			rc = request_irq(h->intr[i], msixhandler,
 					0, h->devname,
 					&h->q[i]);
+			if (rc) {
+				int j;
+
+				dev_err(&h->pdev->dev,
+					"failed to get irq %d for %s\n",
+				       h->intr[i], h->devname);
+				for (j = 0; j < i; j++) {
+					free_irq(h->intr[j], &h->q[j]);
+					h->q[j] = 0;
+				}
+				for (; j < MAX_REPLY_QUEUES; j++)
+					h->q[j] = 0;
+				return rc;
+			}
+		}
 		hpsa_irq_affinity_hints(h);
 	} else {
 		/* Use single reply pool */


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 10/48] hpsa: remove 0x from queue depth print which is in decimal
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (8 preceding siblings ...)
  2015-01-23 22:41 ` [PATCH v2 09/48] hpsa: notice all request_irq errors Don Brace
@ 2015-01-23 22:41 ` Don Brace
  2015-01-23 22:42 ` [PATCH v2 11/48] hpsa: propagate hard_reset failures in reset_devices mode Don Brace
                   ` (37 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:41 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Robert Elliott <elliott@hp.com>

The queue depth printed at startup is in decimal, so
shouldn't have a 0x prefix.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Robert Elliott <elliott@hp.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 97bb718..fbeef5b 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -5931,7 +5931,7 @@ static void print_cfg_table(struct device *dev, struct CfgTable __iomem *tb)
 	       readl(&(tb->HostWrite.CoalIntDelay)));
 	dev_info(dev, "   Coalesce Interrupt Count = 0x%x\n",
 	       readl(&(tb->HostWrite.CoalIntCount)));
-	dev_info(dev, "   Max outstanding commands = 0x%d\n",
+	dev_info(dev, "   Max outstanding commands = %d\n",
 	       readl(&(tb->CmdsOutMax)));
 	dev_info(dev, "   Bus Types = 0x%x\n", readl(&(tb->BusTypes)));
 	for (i = 0; i < 16; i++)


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 11/48] hpsa: propagate hard_reset failures in reset_devices mode
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (9 preceding siblings ...)
  2015-01-23 22:41 ` [PATCH v2 10/48] hpsa: remove 0x from queue depth print which is in decimal Don Brace
@ 2015-01-23 22:42 ` Don Brace
  2015-01-23 22:42 ` [PATCH v2 12/48] hpsa: propagate return value from board ID lookup Don Brace
                   ` (36 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:42 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Robert Elliott <elliott@hp.com>

Return the real reason for kdump_hard_reset failure rather
than change them all to -ENODEV.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Robert Elliott <elliott@hp.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |    5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index fbeef5b..92ac76a 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -6416,11 +6416,8 @@ static int hpsa_init_reset_devices(struct pci_dev *pdev)
 	 * "performant mode".  Or, it might be 640x, which can't reset
 	 * due to concerns about shared bbwc between 6402/6404 pair.
 	 */
-	if (rc) {
-		if (rc != -ENOTSUPP) /* just try to do the kdump anyhow. */
-			rc = -ENODEV;
+	if (rc)
 		goto out_disable;
-	}
 
 	/* Now try to get the controller to respond to a no-op */
 	dev_warn(&pdev->dev, "Waiting for controller to respond to no-op\n");


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 12/48] hpsa: propagate return value from board ID lookup
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (10 preceding siblings ...)
  2015-01-23 22:42 ` [PATCH v2 11/48] hpsa: propagate hard_reset failures in reset_devices mode Don Brace
@ 2015-01-23 22:42 ` Don Brace
  2015-01-23 22:42 ` [PATCH v2 13/48] hpsa: downgrade the Waiting for no-op print to dev_info Don Brace
                   ` (35 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:42 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Robert Elliott <elliott@hp.com>

If the board ID lookup function fails, return the return
code rather than return -ENODEV.

The only board ID failure reason right now is -ENODEV,
so this just provides more informative prints in kdump
and adapts to future changes.

Tested with error injection while booting with
	reset_devices
on the kernel command line:
[   62.804324]  injecting error in inj_hpsa_lookup_board_id: 1 11
[   62.804423] hpsa 0000:04:00.0: Board ID not found

(the pci probe layer does not print an additional
message if -ENODEV is the reason)

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Robert Elliott <elliott@hp.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |   10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 92ac76a..85b3d73 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -5812,8 +5812,12 @@ static int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
 	 */
 
 	rc = hpsa_lookup_board_id(pdev, &board_id);
-	if (rc < 0 || !ctlr_is_resettable(board_id)) {
-		dev_warn(&pdev->dev, "Not resetting device.\n");
+	if (rc < 0) {
+		dev_warn(&pdev->dev, "Board ID not found\n");
+		return rc;
+	}
+	if (!ctlr_is_resettable(board_id)) {
+		dev_warn(&pdev->dev, "Controller not resettable\n");
 		return -ENODEV;
 	}
 
@@ -6295,7 +6299,7 @@ static int hpsa_pci_init(struct ctlr_info *h)
 
 	prod_index = hpsa_lookup_board_id(h->pdev, &h->board_id);
 	if (prod_index < 0)
-		return -ENODEV;
+		return prod_index;
 	h->product_name = products[prod_index].product_name;
 	h->access = *(products[prod_index].access);
 


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 13/48] hpsa: downgrade the Waiting for no-op print to dev_info
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (11 preceding siblings ...)
  2015-01-23 22:42 ` [PATCH v2 12/48] hpsa: propagate return value from board ID lookup Don Brace
@ 2015-01-23 22:42 ` Don Brace
  2015-01-23 22:42 ` [PATCH v2 14/48] hpsa: refactor hpsa_find_board_params() to encapsulate legacy test Don Brace
                   ` (34 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:42 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Robert Elliott <elliott@hp.com>

There is nothing worrisome about the "Waiting for controller to
respond to no-op" print, so use dev_info rather than dev_warn.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Robert Elliott <elliott@hp.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 85b3d73..ec2503a 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -6424,7 +6424,7 @@ static int hpsa_init_reset_devices(struct pci_dev *pdev)
 		goto out_disable;
 
 	/* Now try to get the controller to respond to a no-op */
-	dev_warn(&pdev->dev, "Waiting for controller to respond to no-op\n");
+	dev_info(&pdev->dev, "Waiting for controller to respond to no-op\n");
 	for (i = 0; i < HPSA_POST_RESET_NOOP_RETRIES; i++) {
 		if (hpsa_noop(pdev) == 0)
 			break;


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 14/48] hpsa: refactor hpsa_find_board_params() to encapsulate legacy test
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (12 preceding siblings ...)
  2015-01-23 22:42 ` [PATCH v2 13/48] hpsa: downgrade the Waiting for no-op print to dev_info Don Brace
@ 2015-01-23 22:42 ` Don Brace
  2015-01-23 22:42 ` [PATCH v2 15/48] hpsa: trivial message and comment clean ups Don Brace
                   ` (33 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:42 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Webb Scales <webbnh@hp.com>

Encapsulate the conditional predicate which tests for legacy controllers
in a separate function and rework the code comments.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Webb Scales <webbnh@hp.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |   30 +++++++++++++++++++++---------
 1 file changed, 21 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index ec2503a..08d96a9 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -3107,7 +3107,8 @@ out:
 	kfree(logdev_list);
 }
 
-/* hpsa_scatter_gather takes a struct scsi_cmnd, (cmd), and does the pci
+/*
+ * hpsa_scatter_gather takes a struct scsi_cmnd, (cmd), and does the pci
  * dma mapping  and fills in the scatter gather entries of the
  * hpsa command, cp.
  */
@@ -3165,7 +3166,7 @@ static int hpsa_scatter_gather(struct ctlr_info *h,
 sglist_finished:
 
 	cp->Header.SGList = (u8) use_sg;   /* no. SGs contig in this cmd */
-	cp->Header.SGTotal = cpu_to_le16(use_sg); /* total sgs in this cmd list */
+	cp->Header.SGTotal = cpu_to_le16(use_sg); /* total sgs in cmd list */
 	return 0;
 }
 
@@ -6162,6 +6163,15 @@ static void hpsa_get_max_perf_mode_cmds(struct ctlr_info *h)
 	}
 }
 
+/* If the controller reports that the total max sg entries is greater than 512,
+ * then we know that chained SG blocks work.  (Original smart arrays did not
+ * support chained SG blocks and would return zero for max sg entries.)
+ */
+static int hpsa_supports_chained_sg_blocks(struct ctlr_info *h)
+{
+	return h->maxsgentries > 512;
+}
+
 /* Interrogate the hardware for some limits:
  * max commands, max SG elements without chaining, and with chaining,
  * SG chain block size, etc.
@@ -6172,18 +6182,20 @@ static void hpsa_find_board_params(struct ctlr_info *h)
 	h->nr_cmds = h->max_commands - 4; /* Allow room for some ioctls */
 	h->maxsgentries = readl(&(h->cfgtable->MaxScatterGatherElements));
 	h->fw_support = readl(&(h->cfgtable->misc_fw_support));
-	/*
-	 * Limit in-command s/g elements to 32 save dma'able memory.
-	 * Howvever spec says if 0, use 31
-	 */
-	h->max_cmd_sg_entries = 31;
-	if (h->maxsgentries > 512) {
+	if (hpsa_supports_chained_sg_blocks(h)) {
+		/* Limit in-command s/g elements to 32 save dma'able memory. */
 		h->max_cmd_sg_entries = 32;
 		h->chainsize = h->maxsgentries - h->max_cmd_sg_entries;
 		h->maxsgentries--; /* save one for chain pointer */
 	} else {
-		h->chainsize = 0;
+		/*
+		 * Original smart arrays supported at most 31 s/g entries
+		 * embedded inline in the command (trying to use more
+		 * would lock up the controller)
+		 */
+		h->max_cmd_sg_entries = 31;
 		h->maxsgentries = 31; /* default to traditional values */
+		h->chainsize = 0;
 	}
 
 	/* Find out what task management functions are supported and cache */


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 15/48] hpsa: trivial message and comment clean ups
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (13 preceding siblings ...)
  2015-01-23 22:42 ` [PATCH v2 14/48] hpsa: refactor hpsa_find_board_params() to encapsulate legacy test Don Brace
@ 2015-01-23 22:42 ` Don Brace
  2015-01-23 22:42 ` [PATCH v2 16/48] hpsa: report failure to ioremap config table Don Brace
                   ` (32 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:42 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Stephen Cameron <stephenmcameron@gmail.com>

Cleanup comments to be more specific. Make messages more
informational.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Robert Elliott <elliott@hp.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |   21 ++++++++++-----------
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 08d96a9..5973018 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -5863,8 +5863,8 @@ static int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
 	} else {
 		use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET;
 		if (use_doorbell) {
-			dev_warn(&pdev->dev, "Soft reset not supported. "
-				"Firmware update is required.\n");
+			dev_warn(&pdev->dev,
+				"Soft reset not supported. Firmware update is required.\n");
 			rc = -ENOTSUPP; /* try soft reset */
 			goto unmap_cfgtable;
 		}
@@ -5884,8 +5884,7 @@ static int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
 	rc = hpsa_wait_for_board_state(pdev, vaddr, BOARD_READY);
 	if (rc) {
 		dev_warn(&pdev->dev,
-			"failed waiting for board to become ready "
-			"after hard reset\n");
+			"Failed waiting for board to become ready after hard reset\n");
 		goto unmap_cfgtable;
 	}
 
@@ -5984,7 +5983,7 @@ static int find_PCI_BAR_index(struct pci_dev *pdev, unsigned long pci_bar_addr)
 }
 
 /* If MSI/MSI-X is supported by the kernel we will try to enable it on
- * controllers that are capable. If not, we use IO-APIC mode.
+ * controllers that are capable. If not, we use legacy INTx mode.
  */
 
 static void hpsa_interrupt_mode(struct ctlr_info *h)
@@ -6003,7 +6002,7 @@ static void hpsa_interrupt_mode(struct ctlr_info *h)
 	    (h->board_id == 0x40820E11) || (h->board_id == 0x40830E11))
 		goto default_int_mode;
 	if (pci_find_capability(h->pdev, PCI_CAP_ID_MSIX)) {
-		dev_info(&h->pdev->dev, "MSIX\n");
+		dev_info(&h->pdev->dev, "MSI-X capable controller\n");
 		h->msix_vector = MAX_REPLY_QUEUES;
 		if (h->msix_vector > num_online_cpus())
 			h->msix_vector = num_online_cpus();
@@ -6024,7 +6023,7 @@ static void hpsa_interrupt_mode(struct ctlr_info *h)
 	}
 single_msi_mode:
 	if (pci_find_capability(h->pdev, PCI_CAP_ID_MSI)) {
-		dev_info(&h->pdev->dev, "MSI\n");
+		dev_info(&h->pdev->dev, "MSI capable controller\n");
 		if (!pci_enable_msi(h->pdev))
 			h->msi_vector = 1;
 		else
@@ -6209,7 +6208,7 @@ static void hpsa_find_board_params(struct ctlr_info *h)
 static inline bool hpsa_CISS_signature_present(struct ctlr_info *h)
 {
 	if (!check_signature(h->cfgtable->Signature, "CISS", 4)) {
-		dev_warn(&h->pdev->dev, "not a valid CISS config table\n");
+		dev_err(&h->pdev->dev, "not a valid CISS config table\n");
 		return false;
 	}
 	return true;
@@ -6301,7 +6300,7 @@ static int hpsa_enter_simple_mode(struct ctlr_info *h)
 	h->transMethod = CFGTBL_Trans_Simple;
 	return 0;
 error:
-	dev_warn(&h->pdev->dev, "unable to get board into simple mode\n");
+	dev_err(&h->pdev->dev, "failed to enter simple mode\n");
 	return -ENODEV;
 }
 
@@ -7282,8 +7281,8 @@ static void hpsa_enter_performant_mode(struct ctlr_info *h, u32 trans_support)
 	hpsa_wait_for_mode_change_ack(h);
 	register_value = readl(&(h->cfgtable->TransportActive));
 	if (!(register_value & CFGTBL_Trans_Performant)) {
-		dev_warn(&h->pdev->dev, "unable to get board into"
-					" performant mode\n");
+		dev_err(&h->pdev->dev,
+			"performant mode problem - transport not active\n");
 		return;
 	}
 	/* Change the access methods to the performant access methods */


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 16/48] hpsa: report failure to ioremap config table
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (14 preceding siblings ...)
  2015-01-23 22:42 ` [PATCH v2 15/48] hpsa: trivial message and comment clean ups Don Brace
@ 2015-01-23 22:42 ` Don Brace
  2015-01-23 22:42 ` [PATCH v2 17/48] hpsa: rename hpsa_request_irq to hpsa_request_irqs Don Brace
                   ` (31 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:42 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Robert Elliott <elliott@hp.com>

Enhance error reporting.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Robert Elliott <elliott@hp.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 5973018..354e7f8 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -6130,8 +6130,10 @@ static int hpsa_find_cfgtables(struct ctlr_info *h)
 		return rc;
 	h->cfgtable = remap_pci_mem(pci_resource_start(h->pdev,
 		       cfg_base_addr_index) + cfg_offset, sizeof(*h->cfgtable));
-	if (!h->cfgtable)
+	if (!h->cfgtable) {
+		dev_err(&h->pdev->dev, "Failed mapping cfgtable\n");
 		return -ENOMEM;
+	}
 	rc = write_driver_ver_to_cfgtable(h->cfgtable);
 	if (rc)
 		return rc;


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 17/48] hpsa: rename hpsa_request_irq to hpsa_request_irqs
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (15 preceding siblings ...)
  2015-01-23 22:42 ` [PATCH v2 16/48] hpsa: report failure to ioremap config table Don Brace
@ 2015-01-23 22:42 ` Don Brace
  2015-01-23 22:42 ` [PATCH v2 18/48] hpsa: pass error from pci_set_consistent_dma_mask from hpsa_message Don Brace
                   ` (30 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:42 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Robert Elliott <elliott@hp.com>

Make the function name more descriptive. We use more than
one interrupt.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Robert Elliott <elliott@hp.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |   11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 354e7f8..f29f569 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -6526,7 +6526,8 @@ static void hpsa_free_irqs(struct ctlr_info *h)
 		h->q[i] = 0;
 }
 
-static int hpsa_request_irq(struct ctlr_info *h,
+/* returns 0 on success; cleans up and returns -Enn on error */
+static int hpsa_request_irqs(struct ctlr_info *h,
 	irqreturn_t (*msixhandler)(int, void *),
 	irqreturn_t (*intxhandler)(int, void *))
 {
@@ -6934,7 +6935,7 @@ reinit_after_soft_reset:
 	/* make sure the board interrupts are off */
 	h->access.set_intr_mask(h, HPSA_INTR_OFF);
 
-	if (hpsa_request_irq(h, do_hpsa_intr_msi, do_hpsa_intr_intx))
+	if (hpsa_request_irqs(h, do_hpsa_intr_msi, do_hpsa_intr_intx))
 		goto clean2;
 	dev_info(&pdev->dev, "%s: <0x%x> at IRQ %d%s using DAC\n",
 	       h->devname, pdev->device,
@@ -6970,11 +6971,11 @@ reinit_after_soft_reset:
 		h->access.set_intr_mask(h, HPSA_INTR_OFF);
 		spin_unlock_irqrestore(&h->lock, flags);
 		hpsa_free_irqs(h);
-		rc = hpsa_request_irq(h, hpsa_msix_discard_completions,
+		rc = hpsa_request_irqs(h, hpsa_msix_discard_completions,
 					hpsa_intx_discard_completions);
 		if (rc) {
-			dev_warn(&h->pdev->dev, "Failed to request_irq after "
-				"soft reset.\n");
+			dev_warn(&h->pdev->dev,
+				"Failed to request_irq after soft reset.\n");
 			goto clean4;
 		}
 


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 18/48] hpsa: pass error from pci_set_consistent_dma_mask from hpsa_message
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (16 preceding siblings ...)
  2015-01-23 22:42 ` [PATCH v2 17/48] hpsa: rename hpsa_request_irq to hpsa_request_irqs Don Brace
@ 2015-01-23 22:42 ` Don Brace
  2015-01-23 22:42 ` [PATCH v2 19/48] hpsa: report allocation failures while allocating SG chain blocks Don Brace
                   ` (29 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:42 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Robert Elliott <elliott@hp.com>

Return the actual error code instead of a generic error code.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Robert Elliott <elliott@hp.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index f29f569..64d17d1 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -5610,7 +5610,7 @@ static int hpsa_message(struct pci_dev *pdev, unsigned char opcode,
 	err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
 	if (err) {
 		iounmap(vaddr);
-		return -ENOMEM;
+		return err;
 	}
 
 	cmd = pci_alloc_consistent(pdev, cmd_sz, &paddr64);


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 19/48] hpsa: report allocation failures while allocating SG chain blocks
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (17 preceding siblings ...)
  2015-01-23 22:42 ` [PATCH v2 18/48] hpsa: pass error from pci_set_consistent_dma_mask from hpsa_message Don Brace
@ 2015-01-23 22:42 ` Don Brace
  2015-01-23 22:42 ` [PATCH v2 20/48] hpsa: fix memory leak in hpsa_alloc_cmd_pool Don Brace
                   ` (28 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:42 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Robert Elliott <elliott@hp.com>

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Robert Elliott <elliott@hp.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |    8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 64d17d1..dc328ce 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -1480,13 +1480,17 @@ static int hpsa_allocate_sg_chain_blocks(struct ctlr_info *h)
 
 	h->cmd_sg_list = kzalloc(sizeof(*h->cmd_sg_list) * h->nr_cmds,
 				GFP_KERNEL);
-	if (!h->cmd_sg_list)
+	if (!h->cmd_sg_list) {
+		dev_err(&h->pdev->dev, "Failed to allocate SG list\n");
 		return -ENOMEM;
+	}
 	for (i = 0; i < h->nr_cmds; i++) {
 		h->cmd_sg_list[i] = kmalloc(sizeof(*h->cmd_sg_list[i]) *
 						h->chainsize, GFP_KERNEL);
-		if (!h->cmd_sg_list[i])
+		if (!h->cmd_sg_list[i]) {
+			dev_err(&h->pdev->dev, "Failed to allocate cmd SG\n");
 			goto clean;
+		}
 	}
 	return 0;
 


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 20/48] hpsa: fix memory leak in hpsa_alloc_cmd_pool
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (18 preceding siblings ...)
  2015-01-23 22:42 ` [PATCH v2 19/48] hpsa: report allocation failures while allocating SG chain blocks Don Brace
@ 2015-01-23 22:42 ` Don Brace
  2015-01-23 22:42 ` [PATCH v2 21/48] hpsa: avoid unneccesary calls to resource freeing functions Don Brace
                   ` (27 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:42 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Robert Elliott <elliott@hp.com>

Partial allocation failure wasn't handled correctly

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Robert Elliott <elliott@hp.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |    6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index dc328ce..a66a50e 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -211,6 +211,7 @@ static struct CommandList *cmd_special_alloc(struct ctlr_info *h);
 static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
 	void *buff, size_t size, u16 page_code, unsigned char *scsi3addr,
 	int cmd_type);
+static void hpsa_free_cmd_pool(struct ctlr_info *h);
 #define VPD_PAGE (1 << 8)
 
 static int hpsa_scsi_queue_command(struct Scsi_Host *h, struct scsi_cmnd *cmd);
@@ -6471,9 +6472,12 @@ static int hpsa_allocate_cmd_pool(struct ctlr_info *h)
 	    || (h->cmd_pool == NULL)
 	    || (h->errinfo_pool == NULL)) {
 		dev_err(&h->pdev->dev, "out of memory in %s", __func__);
-		return -ENOMEM;
+		goto clean_up;
 	}
 	return 0;
+clean_up:
+	hpsa_free_cmd_pool(h);
+	return -ENOMEM;
 }
 
 static void hpsa_free_cmd_pool(struct ctlr_info *h)


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 21/48] hpsa: avoid unneccesary calls to resource freeing functions
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (19 preceding siblings ...)
  2015-01-23 22:42 ` [PATCH v2 20/48] hpsa: fix memory leak in hpsa_alloc_cmd_pool Don Brace
@ 2015-01-23 22:42 ` Don Brace
  2015-01-23 22:42 ` [PATCH v2 22/48] hpsa: reserve some commands for use by driver Don Brace
                   ` (26 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:42 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Robert Elliott <elliott@hp.com>

If hpsa_allocate_cmd_pool failed, we were calling two functions unnecessarily:

  hpsa_free_sg_chain_blocks(h);
  hpsa_free_cmd_pool(h);

This didn't cause any problem, as those functions can tolerate being called
when what they free hasn't been allocated (relevant pointers would be NULL)
but it is potentially confusing.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Robert Elliott <elliott@hp.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index a66a50e..bee24b2 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -6948,8 +6948,9 @@ reinit_after_soft_reset:
 	dev_info(&pdev->dev, "%s: <0x%x> at IRQ %d%s using DAC\n",
 	       h->devname, pdev->device,
 	       h->intr[h->intr_mode], dac ? "" : " not");
-	if (hpsa_allocate_cmd_pool(h))
-		goto clean4;
+	rc = hpsa_allocate_cmd_pool(h);
+	if (rc)
+		goto clean2_and_free_irqs;
 	if (hpsa_allocate_sg_chain_blocks(h))
 		goto clean4;
 	init_waitqueue_head(&h->scan_wait_queue);
@@ -7038,6 +7039,7 @@ reinit_after_soft_reset:
 clean4:
 	hpsa_free_sg_chain_blocks(h);
 	hpsa_free_cmd_pool(h);
+clean2_and_free_irqs:
 	hpsa_free_irqs(h);
 clean2:
 clean1:


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 22/48] hpsa: reserve some commands for use by driver
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (20 preceding siblings ...)
  2015-01-23 22:42 ` [PATCH v2 21/48] hpsa: avoid unneccesary calls to resource freeing functions Don Brace
@ 2015-01-23 22:42 ` Don Brace
  2015-01-23 22:43 ` [PATCH v2 23/48] hpsa: get rid of cmd_special_alloc and cmd_special_free Don Brace
                   ` (25 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:42 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Stephen Cameron <stephenmcameron@gmail.com>

We need to reserve some commands for device rescans,
aborts, and the pass through ioctls, etc. so we cannot
give them all to the scsi mid layer.

This is in preparation for removing cmd_special_alloc and
cmd_special_free so that we can stop queuing commands internally
in the driver so that we can remove the locks thta protect the
queue that we will no longer have.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |    7 +++++--
 drivers/scsi/hpsa.h |    2 ++
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index bee24b2..99c32a0 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -4064,11 +4064,14 @@ static int hpsa_register_scsi(struct ctlr_info *h)
 	sh->max_cmd_len = MAX_COMMAND_SIZE;
 	sh->max_lun = HPSA_MAX_LUN;
 	sh->max_id = HPSA_MAX_LUN;
-	sh->can_queue = h->nr_cmds;
+	sh->can_queue = h->nr_cmds -
+			HPSA_CMDS_RESERVED_FOR_ABORTS -
+			HPSA_CMDS_RESERVED_FOR_DRIVER -
+			HPSA_MAX_CONCURRENT_PASSTHRUS;
 	if (h->hba_mode_enabled)
 		sh->cmd_per_lun = 7;
 	else
-		sh->cmd_per_lun = h->nr_cmds;
+		sh->cmd_per_lun = sh->can_queue;
 	sh->sg_tablesize = h->maxsgentries;
 	h->scsi_host = sh;
 	sh->hostdata[0] = (unsigned long) h;
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index 8e06d9e..5ee6c6a 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -115,6 +115,8 @@ struct ctlr_info {
 	void __iomem *vaddr;
 	unsigned long paddr;
 	int 	nr_cmds; /* Number of commands allowed on this controller */
+#define HPSA_CMDS_RESERVED_FOR_ABORTS 2
+#define HPSA_CMDS_RESERVED_FOR_DRIVER 1
 	struct CfgTable __iomem *cfgtable;
 	int	interrupts_enabled;
 	int 	max_commands;


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 23/48] hpsa: get rid of cmd_special_alloc and cmd_special_free
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (21 preceding siblings ...)
  2015-01-23 22:42 ` [PATCH v2 22/48] hpsa: reserve some commands for use by driver Don Brace
@ 2015-01-23 22:43 ` Don Brace
  2015-01-23 22:43 ` [PATCH v2 24/48] hpsa: do not queue commands internally in driver Don Brace
                   ` (24 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:43 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Stephen Cameron <stephenmcameron@gmail.com>

We have commands reserved for internal use.

This is laying the groundwork for removing the internal
queue of commands from the driver so that the locks that
protect that queue may be removed.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |  106 ++++++++++++++-------------------------------------
 drivers/scsi/hpsa.h |    2 -
 2 files changed, 31 insertions(+), 77 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 99c32a0..26e3e5b 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -205,9 +205,7 @@ static int hpsa_compat_ioctl(struct scsi_device *dev, int cmd,
 #endif
 
 static void cmd_free(struct ctlr_info *h, struct CommandList *c);
-static void cmd_special_free(struct ctlr_info *h, struct CommandList *c);
 static struct CommandList *cmd_alloc(struct ctlr_info *h);
-static struct CommandList *cmd_special_alloc(struct ctlr_info *h);
 static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
 	void *buff, size_t size, u16 page_code, unsigned char *scsi3addr,
 	int cmd_type);
@@ -2057,10 +2055,10 @@ static int hpsa_scsi_do_inquiry(struct ctlr_info *h, unsigned char *scsi3addr,
 	struct CommandList *c;
 	struct ErrorInfo *ei;
 
-	c = cmd_special_alloc(h);
+	c = cmd_alloc(h);
 
 	if (c == NULL) {			/* trouble... */
-		dev_warn(&h->pdev->dev, "cmd_special_alloc returned NULL!\n");
+		dev_warn(&h->pdev->dev, "cmd_alloc returned NULL!\n");
 		return -ENOMEM;
 	}
 
@@ -2076,7 +2074,7 @@ static int hpsa_scsi_do_inquiry(struct ctlr_info *h, unsigned char *scsi3addr,
 		rc = -1;
 	}
 out:
-	cmd_special_free(h, c);
+	cmd_free(h, c);
 	return rc;
 }
 
@@ -2088,10 +2086,9 @@ static int hpsa_bmic_ctrl_mode_sense(struct ctlr_info *h,
 	struct CommandList *c;
 	struct ErrorInfo *ei;
 
-	c = cmd_special_alloc(h);
-
+	c = cmd_alloc(h);
 	if (c == NULL) {			/* trouble... */
-		dev_warn(&h->pdev->dev, "cmd_special_alloc returned NULL!\n");
+		dev_warn(&h->pdev->dev, "cmd_alloc returned NULL!\n");
 		return -ENOMEM;
 	}
 
@@ -2107,7 +2104,7 @@ static int hpsa_bmic_ctrl_mode_sense(struct ctlr_info *h,
 		rc = -1;
 	}
 out:
-	cmd_special_free(h, c);
+	cmd_free(h, c);
 	return rc;
 	}
 
@@ -2118,10 +2115,10 @@ static int hpsa_send_reset(struct ctlr_info *h, unsigned char *scsi3addr,
 	struct CommandList *c;
 	struct ErrorInfo *ei;
 
-	c = cmd_special_alloc(h);
+	c = cmd_alloc(h);
 
 	if (c == NULL) {			/* trouble... */
-		dev_warn(&h->pdev->dev, "cmd_special_alloc returned NULL!\n");
+		dev_warn(&h->pdev->dev, "cmd_alloc returned NULL!\n");
 		return -ENOMEM;
 	}
 
@@ -2137,7 +2134,7 @@ static int hpsa_send_reset(struct ctlr_info *h, unsigned char *scsi3addr,
 		hpsa_scsi_interpret_error(h, c);
 		rc = -1;
 	}
-	cmd_special_free(h, c);
+	cmd_free(h, c);
 	return rc;
 }
 
@@ -2245,26 +2242,26 @@ static int hpsa_get_raid_map(struct ctlr_info *h,
 	struct CommandList *c;
 	struct ErrorInfo *ei;
 
-	c = cmd_special_alloc(h);
+	c = cmd_alloc(h);
 	if (c == NULL) {
-		dev_warn(&h->pdev->dev, "cmd_special_alloc returned NULL!\n");
+		dev_warn(&h->pdev->dev, "cmd_alloc returned NULL!\n");
 		return -ENOMEM;
 	}
 	if (fill_cmd(c, HPSA_GET_RAID_MAP, h, &this_device->raid_map,
 			sizeof(this_device->raid_map), 0,
 			scsi3addr, TYPE_CMD)) {
 		dev_warn(&h->pdev->dev, "Out of memory in hpsa_get_raid_map()\n");
-		cmd_special_free(h, c);
+		cmd_free(h, c);
 		return -ENOMEM;
 	}
 	hpsa_scsi_do_simple_cmd_with_retry(h, c, PCI_DMA_FROMDEVICE);
 	ei = c->err_info;
 	if (ei->CommandStatus != 0 && ei->CommandStatus != CMD_DATA_UNDERRUN) {
 		hpsa_scsi_interpret_error(h, c);
-		cmd_special_free(h, c);
+		cmd_free(h, c);
 		return -1;
 	}
-	cmd_special_free(h, c);
+	cmd_free(h, c);
 
 	/* @todo in the future, dynamically allocate RAID map memory */
 	if (le32_to_cpu(this_device->raid_map.structure_size) >
@@ -2384,9 +2381,9 @@ static int hpsa_scsi_do_report_luns(struct ctlr_info *h, int logical,
 	unsigned char scsi3addr[8];
 	struct ErrorInfo *ei;
 
-	c = cmd_special_alloc(h);
+	c = cmd_alloc(h);
 	if (c == NULL) {			/* trouble... */
-		dev_err(&h->pdev->dev, "cmd_special_alloc returned NULL!\n");
+		dev_err(&h->pdev->dev, "cmd_alloc returned NULL!\n");
 		return -1;
 	}
 	/* address the controller */
@@ -2414,7 +2411,7 @@ static int hpsa_scsi_do_report_luns(struct ctlr_info *h, int logical,
 		}
 	}
 out:
-	cmd_special_free(h, c);
+	cmd_free(h, c);
 	return rc;
 }
 
@@ -4102,7 +4099,7 @@ static int wait_for_device_to_become_ready(struct ctlr_info *h,
 	int waittime = 1; /* seconds */
 	struct CommandList *c;
 
-	c = cmd_special_alloc(h);
+	c = cmd_alloc(h);
 	if (!c) {
 		dev_warn(&h->pdev->dev, "out of memory in "
 			"wait_for_device_to_become_ready.\n");
@@ -4148,7 +4145,7 @@ static int wait_for_device_to_become_ready(struct ctlr_info *h,
 	else
 		dev_warn(&h->pdev->dev, "device is ready.\n");
 
-	cmd_special_free(h, c);
+	cmd_free(h, c);
 	return rc;
 }
 
@@ -4230,9 +4227,9 @@ static int hpsa_send_abort(struct ctlr_info *h, unsigned char *scsi3addr,
 	struct ErrorInfo *ei;
 	__le32 tagupper, taglower;
 
-	c = cmd_special_alloc(h);
+	c = cmd_alloc(h);
 	if (c == NULL) {	/* trouble... */
-		dev_warn(&h->pdev->dev, "cmd_special_alloc returned NULL!\n");
+		dev_warn(&h->pdev->dev, "cmd_alloc returned NULL!\n");
 		return -ENOMEM;
 	}
 
@@ -4261,7 +4258,7 @@ static int hpsa_send_abort(struct ctlr_info *h, unsigned char *scsi3addr,
 		rc = -1;
 		break;
 	}
-	cmd_special_free(h, c);
+	cmd_free(h, c);
 	dev_dbg(&h->pdev->dev, "%s: Tag:0x%08x:%08x: Finished.\n",
 		__func__, tagupper, taglower);
 	return rc;
@@ -4610,40 +4607,6 @@ static struct CommandList *cmd_alloc(struct ctlr_info *h)
 	return c;
 }
 
-/* For operations that can wait for kmalloc to possibly sleep,
- * this routine can be called. Lock need not be held to call
- * cmd_special_alloc. cmd_special_free() is the complement.
- */
-static struct CommandList *cmd_special_alloc(struct ctlr_info *h)
-{
-	struct CommandList *c;
-	dma_addr_t cmd_dma_handle, err_dma_handle;
-
-	c = pci_zalloc_consistent(h->pdev, sizeof(*c), &cmd_dma_handle);
-	if (c == NULL)
-		return NULL;
-
-	c->cmd_type = CMD_SCSI;
-	c->cmdindex = -1;
-
-	c->err_info = pci_zalloc_consistent(h->pdev, sizeof(*c->err_info),
-					    &err_dma_handle);
-
-	if (c->err_info == NULL) {
-		pci_free_consistent(h->pdev,
-			sizeof(*c), c, cmd_dma_handle);
-		return NULL;
-	}
-
-	INIT_LIST_HEAD(&c->list);
-	c->busaddr = (u32) cmd_dma_handle;
-	c->ErrDesc.Addr = cpu_to_le64(err_dma_handle);
-	c->ErrDesc.Len = cpu_to_le32(sizeof(*c->err_info));
-
-	c->h = h;
-	return c;
-}
-
 static void cmd_free(struct ctlr_info *h, struct CommandList *c)
 {
 	int i;
@@ -4653,15 +4616,6 @@ static void cmd_free(struct ctlr_info *h, struct CommandList *c)
 		  h->cmd_pool_bits + (i / BITS_PER_LONG));
 }
 
-static void cmd_special_free(struct ctlr_info *h, struct CommandList *c)
-{
-	pci_free_consistent(h->pdev, sizeof(*c->err_info),
-			    c->err_info,
-			    (dma_addr_t) le64_to_cpu(c->ErrDesc.Addr));
-	pci_free_consistent(h->pdev, sizeof(*c),
-			    c, (dma_addr_t) (c->busaddr & DIRECT_LOOKUP_MASK));
-}
-
 #ifdef CONFIG_COMPAT
 
 static int hpsa_ioctl32_passthru(struct scsi_device *dev, int cmd,
@@ -4840,7 +4794,7 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp)
 			memset(buff, 0, iocommand.buf_size);
 		}
 	}
-	c = cmd_special_alloc(h);
+	c = cmd_alloc(h);
 	if (c == NULL) {
 		rc = -ENOMEM;
 		goto out_kfree;
@@ -4899,7 +4853,7 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp)
 		}
 	}
 out:
-	cmd_special_free(h, c);
+	cmd_free(h, c);
 out_kfree:
 	kfree(buff);
 	return rc;
@@ -4977,7 +4931,7 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp)
 		data_ptr += sz;
 		sg_used++;
 	}
-	c = cmd_special_alloc(h);
+	c = cmd_alloc(h);
 	if (c == NULL) {
 		status = -ENOMEM;
 		goto cleanup1;
@@ -5034,7 +4988,7 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp)
 	}
 	status = 0;
 cleanup0:
-	cmd_special_free(h, c);
+	cmd_free(h, c);
 cleanup1:
 	if (buff) {
 		int i;
@@ -6188,7 +6142,7 @@ static int hpsa_supports_chained_sg_blocks(struct ctlr_info *h)
 static void hpsa_find_board_params(struct ctlr_info *h)
 {
 	hpsa_get_max_perf_mode_cmds(h);
-	h->nr_cmds = h->max_commands - 4; /* Allow room for some ioctls */
+	h->nr_cmds = h->max_commands;
 	h->maxsgentries = readl(&(h->cfgtable->MaxScatterGatherElements));
 	h->fw_support = readl(&(h->cfgtable->misc_fw_support));
 	if (hpsa_supports_chained_sg_blocks(h)) {
@@ -7064,9 +7018,9 @@ static void hpsa_flush_cache(struct ctlr_info *h)
 	if (!flush_buf)
 		return;
 
-	c = cmd_special_alloc(h);
+	c = cmd_alloc(h);
 	if (!c) {
-		dev_warn(&h->pdev->dev, "cmd_special_alloc returned NULL!\n");
+		dev_warn(&h->pdev->dev, "cmd_alloc returned NULL!\n");
 		goto out_of_memory;
 	}
 	if (fill_cmd(c, HPSA_CACHE_FLUSH, h, flush_buf, 4, 0,
@@ -7078,7 +7032,7 @@ static void hpsa_flush_cache(struct ctlr_info *h)
 out:
 		dev_warn(&h->pdev->dev,
 			"error flushing cache on controller\n");
-	cmd_special_free(h, c);
+	cmd_free(h, c);
 out_of_memory:
 	kfree(flush_buf);
 }
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index 5ee6c6a..06c9e43 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -170,7 +170,7 @@ struct ctlr_info {
 	unsigned long transMethod;
 
 	/* cap concurrent passthrus at some reasonable maximum */
-#define HPSA_MAX_CONCURRENT_PASSTHRUS (20)
+#define HPSA_MAX_CONCURRENT_PASSTHRUS (10)
 	spinlock_t passthru_count_lock; /* protects passthru_count */
 	int passthru_count;
 


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 24/48] hpsa: do not queue commands internally in driver
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (22 preceding siblings ...)
  2015-01-23 22:43 ` [PATCH v2 23/48] hpsa: get rid of cmd_special_alloc and cmd_special_free Don Brace
@ 2015-01-23 22:43 ` Don Brace
  2015-01-23 22:43 ` [PATCH v2 25/48] hpsa: do not request device rescan on every ioaccel path error Don Brace
                   ` (23 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:43 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

By not doing maintaining a list of queued commands, we can eliminate some spin
locking in the main i/o path and gain significant improvement in IOPS.  Remove
the queuing code and the code that calls it; remove now-unused interrupt code;
remove DIRECT_LOOKUP_BIT.

Now that the passthru commands share the same command pool as
the main i/o path, and the total size of the pool is less than
or equal to the number of commands that will fit in the hardware
fifo, there is no need to check to see if we are exceeding the
hardware fifo's depth.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Reviewed-by: Robert Elliott <elliott@hp.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c     |  306 +++++------------------------------------------
 drivers/scsi/hpsa.h     |   17 ---
 drivers/scsi/hpsa_cmd.h |   10 --
 3 files changed, 38 insertions(+), 295 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 26e3e5b..70f07af 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -196,8 +196,6 @@ static int number_of_controllers;
 static irqreturn_t do_hpsa_intr_intx(int irq, void *dev_id);
 static irqreturn_t do_hpsa_intr_msi(int irq, void *dev_id);
 static int hpsa_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
-static void lock_and_start_io(struct ctlr_info *h);
-static void start_io(struct ctlr_info *h, unsigned long *flags);
 
 #ifdef CONFIG_COMPAT
 static int hpsa_compat_ioctl(struct scsi_device *dev, int cmd,
@@ -689,13 +687,6 @@ static struct scsi_host_template hpsa_driver_template = {
 	.no_write_same = 1,
 };
 
-
-/* Enqueuing and dequeuing functions for cmdlists. */
-static inline void addQ(struct list_head *list, struct CommandList *c)
-{
-	list_add_tail(&c->list, list);
-}
-
 static inline u32 next_command(struct ctlr_info *h, u8 q)
 {
 	u32 a;
@@ -829,8 +820,6 @@ static void dial_up_lockup_detection_on_fw_flash_complete(struct ctlr_info *h,
 static void enqueue_cmd_and_start_io(struct ctlr_info *h,
 	struct CommandList *c)
 {
-	unsigned long flags;
-
 	switch (c->cmd_type) {
 	case CMD_IOACCEL1:
 		set_ioaccel1_performant_mode(h, c);
@@ -842,18 +831,8 @@ static void enqueue_cmd_and_start_io(struct ctlr_info *h,
 		set_performant_mode(h, c);
 	}
 	dial_down_lockup_detection_during_fw_flash(h, c);
-	spin_lock_irqsave(&h->lock, flags);
-	addQ(&h->reqQ, c);
-	h->Qdepth++;
-	start_io(h, &flags);
-	spin_unlock_irqrestore(&h->lock, flags);
-}
-
-static inline void removeQ(struct CommandList *c)
-{
-	if (WARN_ON(list_empty(&c->list)))
-		return;
-	list_del_init(&c->list);
+	atomic_inc(&h->commands_outstanding);
+	h->access.submit_command(h, c);
 }
 
 static inline int is_hba_lunid(unsigned char scsi3addr[])
@@ -3449,8 +3428,7 @@ static int hpsa_scsi_ioaccel2_queue_command(struct ctlr_info *h,
 	set_encrypt_ioaccel2(h, c, cp);
 
 	cp->scsi_nexus = cpu_to_le32(ioaccel_handle);
-	cp->Tag = cpu_to_le32(c->cmdindex << DIRECT_LOOKUP_SHIFT |
-				DIRECT_LOOKUP_BIT);
+	cp->Tag = cpu_to_le32(c->cmdindex << DIRECT_LOOKUP_SHIFT);
 	memcpy(cp->cdb, cdb, sizeof(cp->cdb));
 
 	/* fill in sg elements */
@@ -3831,10 +3809,7 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h,
 						dev->scsi3addr);
 }
 
-/*
- * Running in struct Scsi_Host->host_lock less mode using LLD internal
- * struct ctlr_info *h->lock w/ spin_lock_irqsave() protection.
- */
+/* Running in struct Scsi_Host->host_lock less mode */
 static int hpsa_scsi_queue_command(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
 {
 	struct ctlr_info *h;
@@ -3898,8 +3873,7 @@ static int hpsa_scsi_queue_command(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
 
 	c->Header.ReplyQueue = 0;  /* unused in simple mode */
 	memcpy(&c->Header.LUN.LunAddrBytes[0], &scsi3addr[0], 8);
-	c->Header.tag = cpu_to_le64((c->cmdindex << DIRECT_LOOKUP_SHIFT) |
-					DIRECT_LOOKUP_BIT);
+	c->Header.tag = cpu_to_le64((c->cmdindex << DIRECT_LOOKUP_SHIFT));
 
 	/* Fill in the request block... */
 
@@ -4264,56 +4238,6 @@ static int hpsa_send_abort(struct ctlr_info *h, unsigned char *scsi3addr,
 	return rc;
 }
 
-/*
- * hpsa_find_cmd_in_queue
- *
- * Used to determine whether a command (find) is still present
- * in queue_head.   Optionally excludes the last element of queue_head.
- *
- * This is used to avoid unnecessary aborts.  Commands in h->reqQ have
- * not yet been submitted, and so can be aborted by the driver without
- * sending an abort to the hardware.
- *
- * Returns pointer to command if found in queue, NULL otherwise.
- */
-static struct CommandList *hpsa_find_cmd_in_queue(struct ctlr_info *h,
-			struct scsi_cmnd *find, struct list_head *queue_head)
-{
-	unsigned long flags;
-	struct CommandList *c = NULL;	/* ptr into cmpQ */
-
-	if (!find)
-		return NULL;
-	spin_lock_irqsave(&h->lock, flags);
-	list_for_each_entry(c, queue_head, list) {
-		if (c->scsi_cmd == NULL) /* e.g.: passthru ioctl */
-			continue;
-		if (c->scsi_cmd == find) {
-			spin_unlock_irqrestore(&h->lock, flags);
-			return c;
-		}
-	}
-	spin_unlock_irqrestore(&h->lock, flags);
-	return NULL;
-}
-
-static struct CommandList *hpsa_find_cmd_in_queue_by_tag(struct ctlr_info *h,
-					u8 *tag, struct list_head *queue_head)
-{
-	unsigned long flags;
-	struct CommandList *c;
-
-	spin_lock_irqsave(&h->lock, flags);
-	list_for_each_entry(c, queue_head, list) {
-		if (memcmp(&c->Header.tag, tag, 8) != 0)
-			continue;
-		spin_unlock_irqrestore(&h->lock, flags);
-		return c;
-	}
-	spin_unlock_irqrestore(&h->lock, flags);
-	return NULL;
-}
-
 /* ioaccel2 path firmware cannot handle abort task requests.
  * Change abort requests to physical target reset, and send to the
  * address of the physical disk used for the ioaccel 2 command.
@@ -4400,10 +4324,6 @@ static int hpsa_send_reset_as_abort_ioaccel2(struct ctlr_info *h,
 static int hpsa_send_abort_both_ways(struct ctlr_info *h,
 	unsigned char *scsi3addr, struct CommandList *abort)
 {
-	u8 swizzled_tag[8];
-	struct CommandList *c;
-	int rc = 0, rc2 = 0;
-
 	/* ioccelerator mode 2 commands should be aborted via the
 	 * accelerated path, since RAID path is unaware of these commands,
 	 * but underlying firmware can't handle abort TMF.
@@ -4412,27 +4332,8 @@ static int hpsa_send_abort_both_ways(struct ctlr_info *h,
 	if (abort->cmd_type == CMD_IOACCEL2)
 		return hpsa_send_reset_as_abort_ioaccel2(h, scsi3addr, abort);
 
-	/* we do not expect to find the swizzled tag in our queue, but
-	 * check anyway just to be sure the assumptions which make this
-	 * the case haven't become wrong.
-	 */
-	memcpy(swizzled_tag, &abort->Request.CDB[4], 8);
-	swizzle_abort_tag(swizzled_tag);
-	c = hpsa_find_cmd_in_queue_by_tag(h, swizzled_tag, &h->cmpQ);
-	if (c != NULL) {
-		dev_warn(&h->pdev->dev, "Unexpectedly found byte-swapped tag in completion queue.\n");
-		return hpsa_send_abort(h, scsi3addr, abort, 0);
-	}
-	rc = hpsa_send_abort(h, scsi3addr, abort, 0);
-
-	/* if the command is still in our queue, we can't conclude that it was
-	 * aborted (it might have just completed normally) but in any case
-	 * we don't need to try to abort it another way.
-	 */
-	c = hpsa_find_cmd_in_queue(h, abort->scsi_cmd, &h->cmpQ);
-	if (c)
-		rc2 = hpsa_send_abort(h, scsi3addr, abort, 1);
-	return rc && rc2;
+	return hpsa_send_abort(h, scsi3addr, abort, 0) &&
+			hpsa_send_abort(h, scsi3addr, abort, 1);
 }
 
 /* Send an abort for the specified command.
@@ -4446,7 +4347,6 @@ static int hpsa_eh_abort_handler(struct scsi_cmnd *sc)
 	struct ctlr_info *h;
 	struct hpsa_scsi_dev_t *dev;
 	struct CommandList *abort; /* pointer to command to be aborted */
-	struct CommandList *found;
 	struct scsi_cmnd *as;	/* ptr to scsi cmd inside aborted command. */
 	char msg[256];		/* For debug messaging. */
 	int ml = 0;
@@ -4492,28 +4392,6 @@ static int hpsa_eh_abort_handler(struct scsi_cmnd *sc)
 	dev_dbg(&h->pdev->dev, "%s\n", msg);
 	dev_warn(&h->pdev->dev, "Abort request on C%d:B%d:T%d:L%d\n",
 		h->scsi_host->host_no, dev->bus, dev->target, dev->lun);
-
-	/* Search reqQ to See if command is queued but not submitted,
-	 * if so, complete the command with aborted status and remove
-	 * it from the reqQ.
-	 */
-	found = hpsa_find_cmd_in_queue(h, sc, &h->reqQ);
-	if (found) {
-		found->err_info->CommandStatus = CMD_ABORTED;
-		finish_cmd(found);
-		dev_info(&h->pdev->dev, "%s Request SUCCEEDED (driver queue).\n",
-				msg);
-		return SUCCESS;
-	}
-
-	/* not in reqQ, if also not in cmpQ, must have already completed */
-	found = hpsa_find_cmd_in_queue(h, sc, &h->cmpQ);
-	if (!found)  {
-		dev_dbg(&h->pdev->dev, "%s Request SUCCEEDED (not known to driver).\n",
-				msg);
-		return SUCCESS;
-	}
-
 	/*
 	 * Command is in flight, or possibly already completed
 	 * by the firmware (but not to the scsi mid layer) but we can't
@@ -4536,10 +4414,12 @@ static int hpsa_eh_abort_handler(struct scsi_cmnd *sc)
 	 */
 #define ABORT_COMPLETE_WAIT_SECS 30
 	for (i = 0; i < ABORT_COMPLETE_WAIT_SECS * 10; i++) {
-		found = hpsa_find_cmd_in_queue(h, sc, &h->cmpQ);
-		if (!found)
+		if (test_bit(abort->cmdindex & (BITS_PER_LONG - 1),
+				h->cmd_pool_bits +
+				(abort->cmdindex / BITS_PER_LONG)))
+			msleep(100);
+		else
 			return SUCCESS;
-		msleep(100);
 	}
 	dev_warn(&h->pdev->dev, "%s FAILED. Aborted command has not completed after %d seconds.\n",
 		msg, ABORT_COMPLETE_WAIT_SECS);
@@ -4588,8 +4468,8 @@ static struct CommandList *cmd_alloc(struct ctlr_info *h)
 
 	c = h->cmd_pool + i;
 	memset(c, 0, sizeof(*c));
-	cmd_dma_handle = h->cmd_pool_dhandle
-	    + i * sizeof(*c);
+	c->Header.tag = cpu_to_le64((u64) i << DIRECT_LOOKUP_SHIFT);
+	cmd_dma_handle = h->cmd_pool_dhandle + i * sizeof(*c);
 	c->err_info = h->errinfo_pool + i;
 	memset(c->err_info, 0, sizeof(*c->err_info));
 	err_dma_handle = h->errinfo_pool_dhandle
@@ -4597,7 +4477,6 @@ static struct CommandList *cmd_alloc(struct ctlr_info *h)
 
 	c->cmdindex = i;
 
-	INIT_LIST_HEAD(&c->list);
 	c->busaddr = (u32) cmd_dma_handle;
 	temp64.val = (u64) err_dma_handle;
 	c->ErrDesc.Addr = cpu_to_le64(err_dma_handle);
@@ -4811,8 +4690,6 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp)
 		c->Header.SGTotal = cpu_to_le16(0);
 	}
 	memcpy(&c->Header.LUN, &iocommand.LUN_info, sizeof(c->Header.LUN));
-	/* use the kernel address the cmd block for tag */
-	c->Header.tag = cpu_to_le64(c->busaddr);
 
 	/* Fill in Request block */
 	memcpy(&c->Request, &iocommand.Request,
@@ -4941,7 +4818,6 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp)
 	c->Header.SGList = (u8) sg_used;
 	c->Header.SGTotal = cpu_to_le16(sg_used);
 	memcpy(&c->Header.LUN, &ioc->LUN_info, sizeof(c->Header.LUN));
-	c->Header.tag = cpu_to_le64(c->busaddr);
 	memcpy(&c->Request, &ioc->Request, sizeof(c->Request));
 	if (ioc->buf_size > 0) {
 		int i;
@@ -5114,7 +4990,6 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
 		c->Header.SGList = 0;
 		c->Header.SGTotal = cpu_to_le16(0);
 	}
-	c->Header.tag = cpu_to_le64(c->busaddr);
 	memcpy(c->Header.LUN.LunAddrBytes, scsi3addr, 8);
 
 	if (cmd_type == TYPE_CMD) {
@@ -5272,47 +5147,6 @@ static void __iomem *remap_pci_mem(ulong base, ulong size)
 	return page_remapped ? (page_remapped + page_offs) : NULL;
 }
 
-/* Takes cmds off the submission queue and sends them to the hardware,
- * then puts them on the queue of cmds waiting for completion.
- * Assumes h->lock is held
- */
-static void start_io(struct ctlr_info *h, unsigned long *flags)
-{
-	struct CommandList *c;
-
-	while (!list_empty(&h->reqQ)) {
-		c = list_entry(h->reqQ.next, struct CommandList, list);
-		/* can't do anything if fifo is full */
-		if ((h->access.fifo_full(h))) {
-			h->fifo_recently_full = 1;
-			dev_warn(&h->pdev->dev, "fifo full\n");
-			break;
-		}
-		h->fifo_recently_full = 0;
-
-		/* Get the first entry from the Request Q */
-		removeQ(c);
-		h->Qdepth--;
-
-		/* Put job onto the completed Q */
-		addQ(&h->cmpQ, c);
-		atomic_inc(&h->commands_outstanding);
-		spin_unlock_irqrestore(&h->lock, *flags);
-		/* Tell the controller execute command */
-		h->access.submit_command(h, c);
-		spin_lock_irqsave(&h->lock, *flags);
-	}
-}
-
-static void lock_and_start_io(struct ctlr_info *h)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&h->lock, flags);
-	start_io(h, &flags);
-	spin_unlock_irqrestore(&h->lock, flags);
-}
-
 static inline unsigned long get_next_completion(struct ctlr_info *h, u8 q)
 {
 	return h->access.command_completed(h, q);
@@ -5341,53 +5175,12 @@ static inline int bad_tag(struct ctlr_info *h, u32 tag_index,
 
 static inline void finish_cmd(struct CommandList *c)
 {
-	unsigned long flags;
-	int io_may_be_stalled = 0;
-	struct ctlr_info *h = c->h;
-	int count;
-
-	spin_lock_irqsave(&h->lock, flags);
-	removeQ(c);
-
-	/*
-	 * Check for possibly stalled i/o.
-	 *
-	 * If a fifo_full condition is encountered, requests will back up
-	 * in h->reqQ.  This queue is only emptied out by start_io which is
-	 * only called when a new i/o request comes in.  If no i/o's are
-	 * forthcoming, the i/o's in h->reqQ can get stuck.  So we call
-	 * start_io from here if we detect such a danger.
-	 *
-	 * Normally, we shouldn't hit this case, but pounding on the
-	 * CCISS_PASSTHRU ioctl can provoke it.  Only call start_io if
-	 * commands_outstanding is low.  We want to avoid calling
-	 * start_io from in here as much as possible, and esp. don't
-	 * want to get in a cycle where we call start_io every time
-	 * through here.
-	 */
-	count = atomic_read(&h->commands_outstanding);
-	spin_unlock_irqrestore(&h->lock, flags);
-	if (unlikely(h->fifo_recently_full) && count < 5)
-		io_may_be_stalled = 1;
-
 	dial_up_lockup_detection_on_fw_flash_complete(c->h, c);
 	if (likely(c->cmd_type == CMD_IOACCEL1 || c->cmd_type == CMD_SCSI
 			|| c->cmd_type == CMD_IOACCEL2))
 		complete_scsi_command(c);
 	else if (c->cmd_type == CMD_IOCTL_PEND)
 		complete(c->waiting);
-	if (unlikely(io_may_be_stalled))
-		lock_and_start_io(h);
-}
-
-static inline u32 hpsa_tag_contains_index(u32 tag)
-{
-	return tag & DIRECT_LOOKUP_BIT;
-}
-
-static inline u32 hpsa_tag_to_index(u32 tag)
-{
-	return tag >> DIRECT_LOOKUP_SHIFT;
 }
 
 
@@ -5407,34 +5200,13 @@ static inline void process_indexed_cmd(struct ctlr_info *h,
 	u32 tag_index;
 	struct CommandList *c;
 
-	tag_index = hpsa_tag_to_index(raw_tag);
+	tag_index = raw_tag >> DIRECT_LOOKUP_SHIFT;
 	if (!bad_tag(h, tag_index, raw_tag)) {
 		c = h->cmd_pool + tag_index;
 		finish_cmd(c);
 	}
 }
 
-/* process completion of a non-indexed command */
-static inline void process_nonindexed_cmd(struct ctlr_info *h,
-	u32 raw_tag)
-{
-	u32 tag;
-	struct CommandList *c = NULL;
-	unsigned long flags;
-
-	tag = hpsa_tag_discard_error_bits(h, raw_tag);
-	spin_lock_irqsave(&h->lock, flags);
-	list_for_each_entry(c, &h->cmpQ, list) {
-		if ((c->busaddr & 0xFFFFFFE0) == (tag & 0xFFFFFFE0)) {
-			spin_unlock_irqrestore(&h->lock, flags);
-			finish_cmd(c);
-			return;
-		}
-	}
-	spin_unlock_irqrestore(&h->lock, flags);
-	bad_tag(h, h->nr_cmds + 1, raw_tag);
-}
-
 /* Some controllers, like p400, will give us one interrupt
  * after a soft reset, even if we turned interrupts off.
  * Only need to check for this in the hpsa_xxx_discard_completions
@@ -5512,10 +5284,7 @@ static irqreturn_t do_hpsa_intr_intx(int irq, void *queue)
 	while (interrupt_pending(h)) {
 		raw_tag = get_next_completion(h, q);
 		while (raw_tag != FIFO_EMPTY) {
-			if (likely(hpsa_tag_contains_index(raw_tag)))
-				process_indexed_cmd(h, raw_tag);
-			else
-				process_nonindexed_cmd(h, raw_tag);
+			process_indexed_cmd(h, raw_tag);
 			raw_tag = next_command(h, q);
 		}
 	}
@@ -5531,10 +5300,7 @@ static irqreturn_t do_hpsa_intr_msi(int irq, void *queue)
 	h->last_intr_timestamp = get_jiffies_64();
 	raw_tag = get_next_completion(h, q);
 	while (raw_tag != FIFO_EMPTY) {
-		if (likely(hpsa_tag_contains_index(raw_tag)))
-			process_indexed_cmd(h, raw_tag);
-		else
-			process_nonindexed_cmd(h, raw_tag);
+		process_indexed_cmd(h, raw_tag);
 		raw_tag = next_command(h, q);
 	}
 	return IRQ_HANDLED;
@@ -6619,14 +6385,16 @@ static void hpsa_undo_allocations_after_kdump_soft_reset(struct ctlr_info *h)
 }
 
 /* Called when controller lockup detected. */
-static void fail_all_cmds_on_list(struct ctlr_info *h, struct list_head *list)
+static void fail_all_outstanding_cmds(struct ctlr_info *h)
 {
+	int i;
 	struct CommandList *c = NULL;
 
-	assert_spin_locked(&h->lock);
-	/* Mark all outstanding commands as failed and complete them. */
-	while (!list_empty(list)) {
-		c = list_entry(list->next, struct CommandList, list);
+	for (i = 0; i < h->nr_cmds; i++) {
+		if (!test_bit(i & (BITS_PER_LONG - 1),
+				h->cmd_pool_bits + (i / BITS_PER_LONG)))
+			continue;
+		c = h->cmd_pool + i;
 		c->err_info->CommandStatus = CMD_HARDWARE_ERR;
 		finish_cmd(c);
 	}
@@ -6666,8 +6434,7 @@ static void controller_lockup_detected(struct ctlr_info *h)
 			lockup_detected);
 	pci_disable_device(h->pdev);
 	spin_lock_irqsave(&h->lock, flags);
-	fail_all_cmds_on_list(h, &h->cmpQ);
-	fail_all_cmds_on_list(h, &h->reqQ);
+	fail_all_outstanding_cmds(h);
 	spin_unlock_irqrestore(&h->lock, flags);
 }
 
@@ -6859,8 +6626,6 @@ reinit_after_soft_reset:
 
 	h->pdev = pdev;
 	h->intr_mode = hpsa_simple_mode ? SIMPLE_MODE_INT : PERF_MODE_INT;
-	INIT_LIST_HEAD(&h->cmpQ);
-	INIT_LIST_HEAD(&h->reqQ);
 	INIT_LIST_HEAD(&h->offline_device_list);
 	spin_lock_init(&h->lock);
 	spin_lock_init(&h->offline_device_lock);
@@ -7296,8 +7061,7 @@ static void hpsa_enter_performant_mode(struct ctlr_info *h, u32 trans_support)
 			cp->timeout_sec = 0;
 			cp->ReplyQueue = 0;
 			cp->tag =
-				cpu_to_le64((i << DIRECT_LOOKUP_SHIFT) |
-						DIRECT_LOOKUP_BIT);
+				cpu_to_le64((i << DIRECT_LOOKUP_SHIFT));
 			cp->host_addr =
 				cpu_to_le64(h->ioaccel_cmd_pool_dhandle +
 					(i * sizeof(struct io_accel1_cmd)));
@@ -7472,19 +7236,19 @@ static int is_accelerated_cmd(struct CommandList *c)
 static void hpsa_drain_accel_commands(struct ctlr_info *h)
 {
 	struct CommandList *c = NULL;
-	unsigned long flags;
-	int accel_cmds_out;
+	int i, accel_cmds_out;
 
-	do { /* wait for all outstanding commands to drain out */
+	do { /* wait for all outstanding ioaccel commands to drain out */
 		accel_cmds_out = 0;
-		spin_lock_irqsave(&h->lock, flags);
-		list_for_each_entry(c, &h->cmpQ, list)
-			accel_cmds_out += is_accelerated_cmd(c);
-		list_for_each_entry(c, &h->reqQ, list)
+		for (i = 0; i < h->nr_cmds; i++) {
+			if (!test_bit(i & (BITS_PER_LONG - 1),
+					h->cmd_pool_bits + (i / BITS_PER_LONG)))
+				continue;
+			c = h->cmd_pool + i;
 			accel_cmds_out += is_accelerated_cmd(c);
-		spin_unlock_irqrestore(&h->lock, flags);
+		}
 		if (accel_cmds_out <= 0)
-			break;
+				break;
 		msleep(100);
 	} while (1);
 }
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index 06c9e43..e7d7eaa 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -32,7 +32,6 @@ struct access_method {
 	void (*submit_command)(struct ctlr_info *h,
 		struct CommandList *c);
 	void (*set_intr_mask)(struct ctlr_info *h, unsigned long val);
-	unsigned long (*fifo_full)(struct ctlr_info *h);
 	bool (*intr_pending)(struct ctlr_info *h);
 	unsigned long (*command_completed)(struct ctlr_info *h, u8 q);
 };
@@ -133,8 +132,6 @@ struct ctlr_info {
 	char hba_mode_enabled;
 
 	/* queue and queue Info */
-	struct list_head reqQ;
-	struct list_head cmpQ;
 	unsigned int Qdepth;
 	unsigned int maxSG;
 	spinlock_t lock;
@@ -197,7 +194,6 @@ struct ctlr_info {
 	u32 __percpu *lockup_detected;
 	struct delayed_work monitor_ctlr_work;
 	int remove_in_progress;
-	u32 fifo_recently_full;
 	/* Address of h->q[x] is passed to intr handler to know which queue */
 	u8 q[MAX_REPLY_QUEUES];
 	u32 TMFSupportFlags; /* cache what task mgmt funcs are supported. */
@@ -428,14 +424,6 @@ static unsigned long SA5_performant_completed(struct ctlr_info *h, u8 q)
 }
 
 /*
- *  Returns true if fifo is full.
- *
- */
-static unsigned long SA5_fifo_full(struct ctlr_info *h)
-{
-	return atomic_read(&h->commands_outstanding) >= h->max_commands;
-}
-/*
  *   returns value read from hardware.
  *     returns FIFO_EMPTY if there is nothing to read
  */
@@ -527,7 +515,6 @@ static unsigned long SA5_ioaccel_mode1_completed(struct ctlr_info *h, u8 q)
 static struct access_method SA5_access = {
 	SA5_submit_command,
 	SA5_intr_mask,
-	SA5_fifo_full,
 	SA5_intr_pending,
 	SA5_completed,
 };
@@ -535,7 +522,6 @@ static struct access_method SA5_access = {
 static struct access_method SA5_ioaccel_mode1_access = {
 	SA5_submit_command,
 	SA5_performant_intr_mask,
-	SA5_fifo_full,
 	SA5_ioaccel_mode1_intr_pending,
 	SA5_ioaccel_mode1_completed,
 };
@@ -543,7 +529,6 @@ static struct access_method SA5_ioaccel_mode1_access = {
 static struct access_method SA5_ioaccel_mode2_access = {
 	SA5_submit_command_ioaccel2,
 	SA5_performant_intr_mask,
-	SA5_fifo_full,
 	SA5_performant_intr_pending,
 	SA5_performant_completed,
 };
@@ -551,7 +536,6 @@ static struct access_method SA5_ioaccel_mode2_access = {
 static struct access_method SA5_performant_access = {
 	SA5_submit_command,
 	SA5_performant_intr_mask,
-	SA5_fifo_full,
 	SA5_performant_intr_pending,
 	SA5_performant_completed,
 };
@@ -559,7 +543,6 @@ static struct access_method SA5_performant_access = {
 static struct access_method SA5_performant_access_no_read = {
 	SA5_submit_command_no_read,
 	SA5_performant_intr_mask,
-	SA5_fifo_full,
 	SA5_performant_intr_pending,
 	SA5_performant_completed,
 };
diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h
index 9bae50c..d78e666 100644
--- a/drivers/scsi/hpsa_cmd.h
+++ b/drivers/scsi/hpsa_cmd.h
@@ -375,22 +375,19 @@ struct ErrorInfo {
 #define CMD_IOACCEL1	0x04
 #define CMD_IOACCEL2	0x05
 
-#define DIRECT_LOOKUP_SHIFT 5
-#define DIRECT_LOOKUP_BIT 0x10
+#define DIRECT_LOOKUP_SHIFT 4
 #define DIRECT_LOOKUP_MASK (~((1 << DIRECT_LOOKUP_SHIFT) - 1))
 
 #define HPSA_ERROR_BIT          0x02
 struct ctlr_info; /* defined in hpsa.h */
-/* The size of this structure needs to be divisible by 32
- * on all architectures because low 5 bits of the addresses
+/* The size of this structure needs to be divisible by 128
+ * on all architectures.  The low 4 bits of the addresses
  * are used as follows:
  *
  * bit 0: to device, used to indicate "performant mode" command
  *        from device, indidcates error status.
  * bit 1-3: to device, indicates block fetch table entry for
  *          reducing DMA in fetching commands from host memory.
- * bit 4: used to indicate whether tag is "direct lookup" (index),
- *        or a bus address.
  */
 
 #define COMMANDLIST_ALIGNMENT 128
@@ -405,7 +402,6 @@ struct CommandList {
 	struct ctlr_info	   *h;
 	int			   cmd_type;
 	long			   cmdindex;
-	struct list_head list;
 	struct completion *waiting;
 	void   *scsi_cmd;
 } __aligned(COMMANDLIST_ALIGNMENT);


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 25/48] hpsa: do not request device rescan on every ioaccel path error
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (23 preceding siblings ...)
  2015-01-23 22:43 ` [PATCH v2 24/48] hpsa: do not queue commands internally in driver Don Brace
@ 2015-01-23 22:43 ` Don Brace
  2015-01-23 22:43 ` [PATCH v2 26/48] hpsa: factor out hpsa_ciss_submit function Don Brace
                   ` (22 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:43 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Stephen Cameron <stephenmcameron@gmail.com>

The original reasoning behind doing this was faulty.  An error
of some sort would be encountered, accelerated i/o would be
disabled for that logical drive, the command would be kicked
back out to the SCSI midlayer for a retry, and since i/o accelerator
mode was disabled, it would get retried down the RAID path.
However, something needs to turn ioaccellerator mode back on,
and this rescan request was what did that.  However, it was racy,
and extremely bad for performance to rescan all devices, so,
don't do that.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |   14 ++------------
 drivers/scsi/hpsa.h |    1 -
 2 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 70f07af..94a82e3 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -1637,21 +1637,19 @@ static void process_ioaccel2_completion(struct ctlr_info *h,
 		c2->error_data.serv_response ==
 			IOACCEL2_SERV_RESPONSE_FAILURE) {
 		dev->offload_enabled = 0;
-		h->drv_req_rescan = 1;	/* schedule controller for a rescan */
 		cmd->result = DID_SOFT_ERROR << 16;
 		cmd_free(h, c);
 		cmd->scsi_done(cmd);
 		return;
 	}
 	raid_retry = handle_ioaccel_mode2_error(h, c, cmd, c2);
-	/* If error found, disable Smart Path, schedule a rescan,
-	 * and force a retry on the standard path.
+	/* If error found, disable Smart Path,
+	 * force a retry on the standard path.
 	 */
 	if (raid_retry) {
 		dev_warn(&h->pdev->dev, "%s: Retrying on standard path.\n",
 			"HP SSD Smart Path");
 		dev->offload_enabled = 0; /* Disable Smart Path */
-		h->drv_req_rescan = 1;	  /* schedule controller rescan */
 		cmd->result = DID_SOFT_ERROR << 16;
 	}
 	cmd_free(h, c);
@@ -6478,9 +6476,6 @@ static void hpsa_ack_ctlr_events(struct ctlr_info *h)
 	int i;
 	char *event_type;
 
-	/* Clear the driver-requested rescan flag */
-	h->drv_req_rescan = 0;
-
 	/* Ask the controller to clear the events we're handling. */
 	if ((h->transMethod & (CFGTBL_Trans_io_accel1
 			| CFGTBL_Trans_io_accel2)) &&
@@ -6526,9 +6521,6 @@ static void hpsa_ack_ctlr_events(struct ctlr_info *h)
  */
 static int hpsa_ctlr_needs_rescan(struct ctlr_info *h)
 {
-	if (h->drv_req_rescan)
-		return 1;
-
 	if (!(h->fw_support & MISC_FW_EVENT_NOTIFY))
 		return 0;
 
@@ -6574,7 +6566,6 @@ static void hpsa_monitor_ctlr_worker(struct work_struct *work)
 
 	if (hpsa_ctlr_needs_rescan(h) || hpsa_offline_devices_ready(h)) {
 		scsi_host_get(h->scsi_host);
-		h->drv_req_rescan = 0;
 		hpsa_ack_ctlr_events(h);
 		hpsa_scan_start(h->scsi_host);
 		scsi_host_put(h->scsi_host);
@@ -6743,7 +6734,6 @@ reinit_after_soft_reset:
 		/* Enable Accelerated IO path at driver layer */
 		h->acciopath_status = 1;
 
-	h->drv_req_rescan = 0;
 
 	/* Turn the interrupts on so we can service requests */
 	h->access.set_intr_mask(h, HPSA_INTR_ON);
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index e7d7eaa..06a3e81 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -235,7 +235,6 @@ struct ctlr_info {
 	spinlock_t offline_device_lock;
 	struct list_head offline_device_list;
 	int	acciopath_status;
-	int	drv_req_rescan;	/* flag for driver to request rescan event */
 	int	raid_offload_debug;
 };
 


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 26/48] hpsa: factor out hpsa_ciss_submit function
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (24 preceding siblings ...)
  2015-01-23 22:43 ` [PATCH v2 25/48] hpsa: do not request device rescan on every ioaccel path error Don Brace
@ 2015-01-23 22:43 ` Don Brace
  2015-01-23 22:43 ` [PATCH v2 27/48] hpsa: use workqueue to resubmit failed ioaccel commands Don Brace
                   ` (21 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:43 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Stephen Cameron <stephenmcameron@gmail.com>

Factor out the bottom part of the queuecommand function
which is the part that builds commands for submitting down
the "normal' RAID stack path of a Smart Array.

Need to factor this out to improve how commands that
were initially sent down one of the "ioaccellerated"
paths but which have some sort of error condition are
retried down the "normal" path.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |  126 +++++++++++++++++++++++++++------------------------
 1 file changed, 67 insertions(+), 59 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 94a82e3..cc3128f 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -2034,7 +2034,7 @@ static int hpsa_scsi_do_inquiry(struct ctlr_info *h, unsigned char *scsi3addr,
 
 	c = cmd_alloc(h);
 
-	if (c == NULL) {			/* trouble... */
+	if (c == NULL) {
 		dev_warn(&h->pdev->dev, "cmd_alloc returned NULL!\n");
 		return -ENOMEM;
 	}
@@ -3807,68 +3807,14 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h,
 						dev->scsi3addr);
 }
 
-/* Running in struct Scsi_Host->host_lock less mode */
-static int hpsa_scsi_queue_command(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
+/* Submit commands down the "normal" RAID stack path */
+static int hpsa_ciss_submit(struct ctlr_info *h,
+	struct CommandList *c, struct scsi_cmnd *cmd,
+	unsigned char scsi3addr[])
 {
-	struct ctlr_info *h;
-	struct hpsa_scsi_dev_t *dev;
-	unsigned char scsi3addr[8];
-	struct CommandList *c;
-	int rc = 0;
-
-	/* Get the ptr to our adapter structure out of cmd->host. */
-	h = sdev_to_hba(cmd->device);
-	dev = cmd->device->hostdata;
-	if (!dev) {
-		cmd->result = DID_NO_CONNECT << 16;
-		cmd->scsi_done(cmd);
-		return 0;
-	}
-	memcpy(scsi3addr, dev->scsi3addr, sizeof(scsi3addr));
-
-	if (unlikely(lockup_detected(h))) {
-		cmd->result = DID_ERROR << 16;
-		cmd->scsi_done(cmd);
-		return 0;
-	}
-	c = cmd_alloc(h);
-	if (c == NULL) {			/* trouble... */
-		dev_err(&h->pdev->dev, "cmd_alloc returned NULL!\n");
-		return SCSI_MLQUEUE_HOST_BUSY;
-	}
-
-	/* Fill in the command list header */
-	/* save c in case we have to abort it  */
 	cmd->host_scribble = (unsigned char *) c;
-
 	c->cmd_type = CMD_SCSI;
 	c->scsi_cmd = cmd;
-
-	/* Call alternate submit routine for I/O accelerated commands.
-	 * Retries always go down the normal I/O path.
-	 */
-	if (likely(cmd->retries == 0 &&
-		cmd->request->cmd_type == REQ_TYPE_FS &&
-		h->acciopath_status)) {
-		if (dev->offload_enabled) {
-			rc = hpsa_scsi_ioaccel_raid_map(h, c);
-			if (rc == 0)
-				return 0; /* Sent on ioaccel path */
-			if (rc < 0) {   /* scsi_dma_map failed. */
-				cmd_free(h, c);
-				return SCSI_MLQUEUE_HOST_BUSY;
-			}
-		} else if (dev->ioaccel_handle) {
-			rc = hpsa_scsi_ioaccel_direct_map(h, c);
-			if (rc == 0)
-				return 0; /* Sent on direct map path */
-			if (rc < 0) {   /* scsi_dma_map failed. */
-				cmd_free(h, c);
-				return SCSI_MLQUEUE_HOST_BUSY;
-			}
-		}
-	}
-
 	c->Header.ReplyQueue = 0;  /* unused in simple mode */
 	memcpy(&c->Header.LUN.LunAddrBytes[0], &scsi3addr[0], 8);
 	c->Header.tag = cpu_to_le64((c->cmdindex << DIRECT_LOOKUP_SHIFT));
@@ -3927,6 +3873,68 @@ static int hpsa_scsi_queue_command(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
 	return 0;
 }
 
+/* Running in struct Scsi_Host->host_lock less mode */
+static int hpsa_scsi_queue_command(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
+{
+	struct ctlr_info *h;
+	struct hpsa_scsi_dev_t *dev;
+	unsigned char scsi3addr[8];
+	struct CommandList *c;
+	int rc = 0;
+
+	/* Get the ptr to our adapter structure out of cmd->host. */
+	h = sdev_to_hba(cmd->device);
+	dev = cmd->device->hostdata;
+	if (!dev) {
+		cmd->result = DID_NO_CONNECT << 16;
+		cmd->scsi_done(cmd);
+		return 0;
+	}
+	memcpy(scsi3addr, dev->scsi3addr, sizeof(scsi3addr));
+
+	if (unlikely(lockup_detected(h))) {
+		cmd->result = DID_ERROR << 16;
+		cmd->scsi_done(cmd);
+		return 0;
+	}
+	c = cmd_alloc(h);
+	if (c == NULL) {			/* trouble... */
+		dev_err(&h->pdev->dev, "cmd_alloc returned NULL!\n");
+		return SCSI_MLQUEUE_HOST_BUSY;
+	}
+
+	/* Call alternate submit routine for I/O accelerated commands.
+	 * Retries always go down the normal I/O path.
+	 */
+	if (likely(cmd->retries == 0 &&
+		cmd->request->cmd_type == REQ_TYPE_FS &&
+		h->acciopath_status)) {
+
+		cmd->host_scribble = (unsigned char *) c;
+		c->cmd_type = CMD_SCSI;
+		c->scsi_cmd = cmd;
+
+		if (dev->offload_enabled) {
+			rc = hpsa_scsi_ioaccel_raid_map(h, c);
+			if (rc == 0)
+				return 0; /* Sent on ioaccel path */
+			if (rc < 0) {   /* scsi_dma_map failed. */
+				cmd_free(h, c);
+				return SCSI_MLQUEUE_HOST_BUSY;
+			}
+		} else if (dev->ioaccel_handle) {
+			rc = hpsa_scsi_ioaccel_direct_map(h, c);
+			if (rc == 0)
+				return 0; /* Sent on direct map path */
+			if (rc < 0) {   /* scsi_dma_map failed. */
+				cmd_free(h, c);
+				return SCSI_MLQUEUE_HOST_BUSY;
+			}
+		}
+	}
+	return hpsa_ciss_submit(h, c, cmd, scsi3addr);
+}
+
 static int do_not_scan_if_controller_locked_up(struct ctlr_info *h)
 {
 	unsigned long flags;


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 27/48] hpsa: use workqueue to resubmit failed ioaccel commands
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (25 preceding siblings ...)
  2015-01-23 22:43 ` [PATCH v2 26/48] hpsa: factor out hpsa_ciss_submit function Don Brace
@ 2015-01-23 22:43 ` Don Brace
  2015-01-23 22:43 ` [PATCH v2 28/48] hpsa: honor queue depth of physical devices Don Brace
                   ` (20 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:43 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

Instead of kicking the commands all the way back to the mid
layer, use a work queue.  This enables having a mechanism for
the driver to be able to resubmit the commands down the "normal"
raid path without turning off the ioaccel feature entirely
whenever an error is encountered on the ioaccel path, and
prevent excessive rescanning of devices.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c     |   72 ++++++++++++++++++++++++++++++++++-------------
 drivers/scsi/hpsa.h     |    1 +
 drivers/scsi/hpsa_cmd.h |    1 +
 3 files changed, 54 insertions(+), 20 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index cc3128f..dcacb29 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -248,6 +248,7 @@ static void hpsa_flush_cache(struct ctlr_info *h);
 static int hpsa_scsi_ioaccel_queue_command(struct ctlr_info *h,
 	struct CommandList *c, u32 ioaccel_handle, u8 *cdb, int cdb_len,
 	u8 *scsi3addr);
+static void hpsa_command_resubmit_worker(struct work_struct *work);
 
 static inline struct ctlr_info *sdev_to_hba(struct scsi_device *sdev)
 {
@@ -1619,7 +1620,6 @@ static void process_ioaccel2_completion(struct ctlr_info *h,
 		struct hpsa_scsi_dev_t *dev)
 {
 	struct io_accel2_cmd *c2 = &h->ioaccel2_cmd_pool[c->cmdindex];
-	int raid_retry = 0;
 
 	/* check for good status */
 	if (likely(c2->error_data.serv_response == 0 &&
@@ -1636,24 +1636,22 @@ static void process_ioaccel2_completion(struct ctlr_info *h,
 	if (is_logical_dev_addr_mode(dev->scsi3addr) &&
 		c2->error_data.serv_response ==
 			IOACCEL2_SERV_RESPONSE_FAILURE) {
-		dev->offload_enabled = 0;
-		cmd->result = DID_SOFT_ERROR << 16;
-		cmd_free(h, c);
-		cmd->scsi_done(cmd);
-		return;
-	}
-	raid_retry = handle_ioaccel_mode2_error(h, c, cmd, c2);
-	/* If error found, disable Smart Path,
-	 * force a retry on the standard path.
-	 */
-	if (raid_retry) {
-		dev_warn(&h->pdev->dev, "%s: Retrying on standard path.\n",
-			"HP SSD Smart Path");
-		dev->offload_enabled = 0; /* Disable Smart Path */
-		cmd->result = DID_SOFT_ERROR << 16;
+		if (c2->error_data.status ==
+			IOACCEL2_STATUS_SR_IOACCEL_DISABLED)
+			dev->offload_enabled = 0;
+		goto retry_cmd;
 	}
+
+	if (handle_ioaccel_mode2_error(h, c, cmd, c2))
+		goto retry_cmd;
+
 	cmd_free(h, c);
 	cmd->scsi_done(cmd);
+	return;
+
+retry_cmd:
+	INIT_WORK(&c->work, hpsa_command_resubmit_worker);
+	queue_work_on(raw_smp_processor_id(), h->resubmit_wq, &c->work);
 }
 
 static void complete_scsi_command(struct CommandList *cp)
@@ -1723,9 +1721,9 @@ static void complete_scsi_command(struct CommandList *cp)
 		if (is_logical_dev_addr_mode(dev->scsi3addr)) {
 			if (ei->CommandStatus == CMD_IOACCEL_DISABLED)
 				dev->offload_enabled = 0;
-			cmd->result = DID_SOFT_ERROR << 16;
-			cmd_free(h, cp);
-			cmd->scsi_done(cmd);
+			INIT_WORK(&cp->work, hpsa_command_resubmit_worker);
+			queue_work_on(raw_smp_processor_id(),
+					h->resubmit_wq, &cp->work);
 			return;
 		}
 	}
@@ -3873,6 +3871,31 @@ static int hpsa_ciss_submit(struct ctlr_info *h,
 	return 0;
 }
 
+static void hpsa_command_resubmit_worker(struct work_struct *work)
+{
+	struct scsi_cmnd *cmd;
+	struct hpsa_scsi_dev_t *dev;
+	struct CommandList *c =
+			container_of(work, struct CommandList, work);
+
+	cmd = c->scsi_cmd;
+	dev = cmd->device->hostdata;
+	if (!dev) {
+		cmd->result = DID_NO_CONNECT << 16;
+		cmd->scsi_done(cmd);
+		return;
+	}
+	if (hpsa_ciss_submit(c->h, c, cmd, dev->scsi3addr)) {
+		/*
+		 * If we get here, it means dma mapping failed. Try
+		 * again via scsi mid layer, which will then get
+		 * SCSI_MLQUEUE_HOST_BUSY.
+		 */
+		cmd->result = DID_IMM_RETRY << 16;
+		cmd->scsi_done(cmd);
+	}
+}
+
 /* Running in struct Scsi_Host->host_lock less mode */
 static int hpsa_scsi_queue_command(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
 {
@@ -6396,6 +6419,7 @@ static void fail_all_outstanding_cmds(struct ctlr_info *h)
 	int i;
 	struct CommandList *c = NULL;
 
+	flush_workqueue(h->resubmit_wq); /* ensure all cmds are fully built */
 	for (i = 0; i < h->nr_cmds; i++) {
 		if (!test_bit(i & (BITS_PER_LONG - 1),
 				h->cmd_pool_bits + (i / BITS_PER_LONG)))
@@ -6631,6 +6655,12 @@ reinit_after_soft_reset:
 	spin_lock_init(&h->scan_lock);
 	spin_lock_init(&h->passthru_count_lock);
 
+	h->resubmit_wq = alloc_workqueue("hpsa", WQ_MEM_RECLAIM, 0);
+	if (!h->resubmit_wq) {
+		dev_err(&h->pdev->dev, "Failed to allocate work queue\n");
+		rc = -ENOMEM;
+		goto clean1;
+	}
 	/* Allocate and clear per-cpu variable lockup_detected */
 	h->lockup_detected = alloc_percpu(u32);
 	if (!h->lockup_detected) {
@@ -6763,6 +6793,8 @@ clean2_and_free_irqs:
 	hpsa_free_irqs(h);
 clean2:
 clean1:
+	if (h->resubmit_wq)
+		destroy_workqueue(h->resubmit_wq);
 	if (h->lockup_detected)
 		free_percpu(h->lockup_detected);
 	kfree(h);
@@ -6838,9 +6870,9 @@ static void hpsa_remove_one(struct pci_dev *pdev)
 	h->remove_in_progress = 1;
 	cancel_delayed_work(&h->monitor_ctlr_work);
 	spin_unlock_irqrestore(&h->lock, flags);
-
 	hpsa_unregister_scsi(h);	/* unhook from SCSI subsystem */
 	hpsa_shutdown(pdev);
+	destroy_workqueue(h->resubmit_wq);
 	iounmap(h->vaddr);
 	iounmap(h->transtable);
 	iounmap(h->cfgtable);
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index 06a3e81..a0f4268 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -236,6 +236,7 @@ struct ctlr_info {
 	struct list_head offline_device_list;
 	int	acciopath_status;
 	int	raid_offload_debug;
+	struct workqueue_struct *resubmit_wq;
 };
 
 struct offline_device_entry {
diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h
index d78e666..3f2f0af 100644
--- a/drivers/scsi/hpsa_cmd.h
+++ b/drivers/scsi/hpsa_cmd.h
@@ -404,6 +404,7 @@ struct CommandList {
 	long			   cmdindex;
 	struct completion *waiting;
 	void   *scsi_cmd;
+	struct work_struct work;
 } __aligned(COMMANDLIST_ALIGNMENT);
 
 /* Max S/G elements in I/O accelerator command */


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 28/48] hpsa: honor queue depth of physical devices
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (26 preceding siblings ...)
  2015-01-23 22:43 ` [PATCH v2 27/48] hpsa: use workqueue to resubmit failed ioaccel commands Don Brace
@ 2015-01-23 22:43 ` Don Brace
  2015-01-23 22:43 ` [PATCH v2 29/48] hpsa: fix race between abort handler and main i/o path Don Brace
                   ` (19 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:43 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

When using the ioaccel submission methods, requests destined for RAID volumes
are sometimes diverted to physical devices.  The OS has no or limited
knowledge of these physical devices, so it is up to the driver to avoid
pushing the device too hard.  It is better to honor the physical device queue
limit rather than making the device spew zillions of TASK SET FULL responses.

This is so that hpsa based devices support /sys/block/sdNN/device/queue_type
of simple, which lets the SCSI midlayer automatically adjust the queue_depth
based on TASK SET FULL and GOOD status.

Adjust the queue depth for a new device after it is created based on the
maximum queue depths of the physical devices that constitute the
device. This drops the maximum queue depth from .can_queue of 1024 to
something like 174 for single-drive RAID-0, 348 for two-drive RAID-1, etc.
It also adjusts for the ratio of data to parity drives.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Webb Scales <webbnh@hp.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c     |  318 +++++++++++++++++++++++++++++++++++++----------
 drivers/scsi/hpsa.h     |   14 ++
 drivers/scsi/hpsa_cmd.h |  148 ++++++++++++++++++++++
 3 files changed, 412 insertions(+), 68 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index dcacb29..60f5734 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -247,7 +247,7 @@ static void hpsa_drain_accel_commands(struct ctlr_info *h);
 static void hpsa_flush_cache(struct ctlr_info *h);
 static int hpsa_scsi_ioaccel_queue_command(struct ctlr_info *h,
 	struct CommandList *c, u32 ioaccel_handle, u8 *cdb, int cdb_len,
-	u8 *scsi3addr);
+	u8 *scsi3addr, struct hpsa_scsi_dev_t *phys_disk);
 static void hpsa_command_resubmit_worker(struct work_struct *work);
 
 static inline struct ctlr_info *sdev_to_hba(struct scsi_device *sdev)
@@ -965,12 +965,24 @@ static void hpsa_scsi_update_entry(struct ctlr_info *h, int hostno,
 	/* Raid level changed. */
 	h->dev[entry]->raid_level = new_entry->raid_level;
 
-	/* Raid offload parameters changed. */
+	/* Raid offload parameters changed.  Careful about the ordering. */
+	if (new_entry->offload_config && new_entry->offload_enabled) {
+		/*
+		 * if drive is newly offload_enabled, we want to copy the
+		 * raid map data first.  If previously offload_enabled and
+		 * offload_config were set, raid map data had better be
+		 * the same as it was before.  if raid map data is changed
+		 * then it had better be the case that
+		 * h->dev[entry]->offload_enabled is currently 0.
+		 */
+		h->dev[entry]->raid_map = new_entry->raid_map;
+		h->dev[entry]->ioaccel_handle = new_entry->ioaccel_handle;
+		wmb(); /* ensure raid map updated prior to ->offload_enabled */
+	}
 	h->dev[entry]->offload_config = new_entry->offload_config;
-	h->dev[entry]->offload_enabled = new_entry->offload_enabled;
-	h->dev[entry]->ioaccel_handle = new_entry->ioaccel_handle;
 	h->dev[entry]->offload_to_mirror = new_entry->offload_to_mirror;
-	h->dev[entry]->raid_map = new_entry->raid_map;
+	h->dev[entry]->offload_enabled = new_entry->offload_enabled;
+	h->dev[entry]->queue_depth = new_entry->queue_depth;
 
 	dev_info(&h->pdev->dev, "%s device c%db%dt%dl%d updated.\n",
 		scsi_device_type(new_entry->devtype), hostno, new_entry->bus,
@@ -1096,6 +1108,8 @@ static inline int device_updated(struct hpsa_scsi_dev_t *dev1,
 		return 1;
 	if (dev1->offload_enabled != dev2->offload_enabled)
 		return 1;
+	if (dev1->queue_depth != dev2->queue_depth)
+		return 1;
 	return 0;
 }
 
@@ -1241,6 +1255,85 @@ static void hpsa_show_volume_status(struct ctlr_info *h,
 	}
 }
 
+/*
+ * Figure the list of physical drive pointers for a logical drive with
+ * raid offload configured.
+ */
+static void hpsa_figure_phys_disk_ptrs(struct ctlr_info *h,
+				struct hpsa_scsi_dev_t *dev[], int ndevices,
+				struct hpsa_scsi_dev_t *logical_drive)
+{
+	struct raid_map_data *map = &logical_drive->raid_map;
+	struct raid_map_disk_data *dd = &map->data[0];
+	int i, j;
+	int total_disks_per_row = le16_to_cpu(map->data_disks_per_row) +
+				le16_to_cpu(map->metadata_disks_per_row);
+	int nraid_map_entries = le16_to_cpu(map->row_cnt) *
+				le16_to_cpu(map->layout_map_count) *
+				total_disks_per_row;
+	int nphys_disk = le16_to_cpu(map->layout_map_count) *
+				total_disks_per_row;
+	int qdepth;
+
+	if (nraid_map_entries > RAID_MAP_MAX_ENTRIES)
+		nraid_map_entries = RAID_MAP_MAX_ENTRIES;
+
+	qdepth = 0;
+	for (i = 0; i < nraid_map_entries; i++) {
+		logical_drive->phys_disk[i] = NULL;
+		if (!logical_drive->offload_config)
+			continue;
+		for (j = 0; j < ndevices; j++) {
+			if (dev[j]->devtype != TYPE_DISK)
+				continue;
+			if (is_logical_dev_addr_mode(dev[j]->scsi3addr))
+				continue;
+			if (dev[j]->ioaccel_handle != dd[i].ioaccel_handle)
+				continue;
+
+			logical_drive->phys_disk[i] = dev[j];
+			if (i < nphys_disk)
+				qdepth = min(h->nr_cmds, qdepth +
+				    logical_drive->phys_disk[i]->queue_depth);
+			break;
+		}
+
+		/*
+		 * This can happen if a physical drive is removed and
+		 * the logical drive is degraded.  In that case, the RAID
+		 * map data will refer to a physical disk which isn't actually
+		 * present.  And in that case offload_enabled should already
+		 * be 0, but we'll turn it off here just in case
+		 */
+		if (!logical_drive->phys_disk[i]) {
+			logical_drive->offload_enabled = 0;
+			logical_drive->queue_depth = h->nr_cmds;
+		}
+	}
+	if (nraid_map_entries)
+		/*
+		 * This is correct for reads, too high for full stripe writes,
+		 * way too high for partial stripe writes
+		 */
+		logical_drive->queue_depth = qdepth;
+	else
+		logical_drive->queue_depth = h->nr_cmds;
+}
+
+static void hpsa_update_log_drive_phys_drive_ptrs(struct ctlr_info *h,
+				struct hpsa_scsi_dev_t *dev[], int ndevices)
+{
+	int i;
+
+	for (i = 0; i < ndevices; i++) {
+		if (dev[i]->devtype != TYPE_DISK)
+			continue;
+		if (!is_logical_dev_addr_mode(dev[i]->scsi3addr))
+			continue;
+		hpsa_figure_phys_disk_ptrs(h, dev, ndevices, dev[i]);
+	}
+}
+
 static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,
 	struct hpsa_scsi_dev_t *sd[], int nsds)
 {
@@ -1425,8 +1518,12 @@ static int hpsa_slave_alloc(struct scsi_device *sdev)
 	spin_lock_irqsave(&h->devlock, flags);
 	sd = lookup_hpsa_scsi_dev(h, sdev_channel(sdev),
 		sdev_id(sdev), sdev->lun);
-	if (sd != NULL)
+	if (sd != NULL) {
 		sdev->hostdata = sd;
+		if (sd->queue_depth)
+			scsi_change_queue_depth(sdev, sd->queue_depth);
+		atomic_set(&sd->ioaccel_cmds_out, 0);
+	}
 	spin_unlock_irqrestore(&h->devlock, flags);
 	return 0;
 }
@@ -1679,6 +1776,9 @@ static void complete_scsi_command(struct CommandList *cp)
 	cmd->result = (DID_OK << 16); 		/* host byte */
 	cmd->result |= (COMMAND_COMPLETE << 8);	/* msg byte */
 
+	if (cp->cmd_type == CMD_IOACCEL2 || cp->cmd_type == CMD_IOACCEL1)
+		atomic_dec(&cp->phys_disk->ioaccel_cmds_out);
+
 	if (cp->cmd_type == CMD_IOACCEL2)
 		return process_ioaccel2_completion(h, cp, cmd, dev);
 
@@ -1686,6 +1786,8 @@ static void complete_scsi_command(struct CommandList *cp)
 
 	scsi_set_resid(cmd, ei->ResidualCnt);
 	if (ei->CommandStatus == 0) {
+		if (cp->cmd_type == CMD_IOACCEL1)
+			atomic_dec(&cp->phys_disk->ioaccel_cmds_out);
 		cmd_free(h, cp);
 		cmd->scsi_done(cmd);
 		return;
@@ -2248,6 +2350,34 @@ static int hpsa_get_raid_map(struct ctlr_info *h,
 	return rc;
 }
 
+static int hpsa_bmic_id_physical_device(struct ctlr_info *h,
+		unsigned char scsi3addr[], u16 bmic_device_index,
+		struct bmic_identify_physical_device *buf, size_t bufsize)
+{
+	int rc = IO_OK;
+	struct CommandList *c;
+	struct ErrorInfo *ei;
+
+	c = cmd_alloc(h);
+	rc = fill_cmd(c, BMIC_IDENTIFY_PHYSICAL_DEVICE, h, buf, bufsize,
+		0, RAID_CTLR_LUNID, TYPE_CMD);
+	if (rc)
+		goto out;
+
+	c->Request.CDB[2] = bmic_device_index & 0xff;
+	c->Request.CDB[9] = (bmic_device_index >> 8) & 0xff;
+
+	hpsa_scsi_do_simple_cmd_with_retry(h, c, PCI_DMA_FROMDEVICE);
+	ei = c->err_info;
+	if (ei->CommandStatus != 0 && ei->CommandStatus != CMD_DATA_UNDERRUN) {
+		hpsa_scsi_interpret_error(h, c);
+		rc = -1;
+	}
+out:
+	cmd_free(h, c);
+	return rc;
+}
+
 static int hpsa_vpd_page_supported(struct ctlr_info *h,
 	unsigned char scsi3addr[], u8 page)
 {
@@ -2348,7 +2478,7 @@ static int hpsa_get_device_id(struct ctlr_info *h, unsigned char *scsi3addr,
 }
 
 static int hpsa_scsi_do_report_luns(struct ctlr_info *h, int logical,
-		struct ReportLUNdata *buf, int bufsize,
+		void *buf, int bufsize,
 		int extended_response)
 {
 	int rc = IO_OK;
@@ -2377,11 +2507,13 @@ static int hpsa_scsi_do_report_luns(struct ctlr_info *h, int logical,
 		hpsa_scsi_interpret_error(h, c);
 		rc = -1;
 	} else {
-		if (buf->extended_response_flag != extended_response) {
+		struct ReportLUNdata *rld = buf;
+
+		if (rld->extended_response_flag != extended_response) {
 			dev_err(&h->pdev->dev,
 				"report luns requested format %u, got %u\n",
 				extended_response,
-				buf->extended_response_flag);
+				rld->extended_response_flag);
 			rc = -1;
 		}
 	}
@@ -2391,10 +2523,10 @@ out:
 }
 
 static inline int hpsa_scsi_do_report_phys_luns(struct ctlr_info *h,
-		struct ReportLUNdata *buf,
-		int bufsize, int extended_response)
+		struct ReportExtendedLUNdata *buf, int bufsize)
 {
-	return hpsa_scsi_do_report_luns(h, 0, buf, bufsize, extended_response);
+	return hpsa_scsi_do_report_luns(h, 0, buf, bufsize,
+						HPSA_REPORT_PHYS_EXTENDED);
 }
 
 static inline int hpsa_scsi_do_report_log_luns(struct ctlr_info *h,
@@ -2569,6 +2701,7 @@ static int hpsa_update_device_info(struct ctlr_info *h,
 		this_device->offload_config = 0;
 		this_device->offload_enabled = 0;
 		this_device->volume_offline = 0;
+		this_device->queue_depth = h->nr_cmds;
 	}
 
 	if (is_OBDR_device) {
@@ -2711,7 +2844,6 @@ static int hpsa_get_pdisk_of_ioaccel2(struct ctlr_info *h,
 {
 	struct ReportExtendedLUNdata *physicals = NULL;
 	int responsesize = 24;	/* size of physical extended response */
-	int extended = 2;	/* flag forces reporting 'other dev info'. */
 	int reportsize = sizeof(*physicals) + HPSA_MAX_PHYS_LUN * responsesize;
 	u32 nphysicals = 0;	/* number of reported physical devs */
 	int found = 0;		/* found match (1) or not (0) */
@@ -2758,8 +2890,7 @@ static int hpsa_get_pdisk_of_ioaccel2(struct ctlr_info *h,
 	physicals = kzalloc(reportsize, GFP_KERNEL);
 	if (physicals == NULL)
 		return 0;
-	if (hpsa_scsi_do_report_phys_luns(h, (struct ReportLUNdata *) physicals,
-		reportsize, extended)) {
+	if (hpsa_scsi_do_report_phys_luns(h, physicals, reportsize)) {
 		dev_err(&h->pdev->dev,
 			"Can't lookup %s device handle: report physical LUNs failed.\n",
 			"HP SSD Smart Path");
@@ -2800,34 +2931,20 @@ static int hpsa_get_pdisk_of_ioaccel2(struct ctlr_info *h,
  * Returns 0 on success, -1 otherwise.
  */
 static int hpsa_gather_lun_info(struct ctlr_info *h,
-	int reportphyslunsize, int reportloglunsize,
-	struct ReportLUNdata *physdev, u32 *nphysicals, int *physical_mode,
+	struct ReportExtendedLUNdata *physdev, u32 *nphysicals,
 	struct ReportLUNdata *logdev, u32 *nlogicals)
 {
-	int physical_entry_size = 8;
-
-	*physical_mode = 0;
-
-	/* For I/O accelerator mode we need to read physical device handles */
-	if (h->transMethod & CFGTBL_Trans_io_accel1 ||
-		h->transMethod & CFGTBL_Trans_io_accel2) {
-		*physical_mode = HPSA_REPORT_PHYS_EXTENDED;
-		physical_entry_size = 24;
-	}
-	if (hpsa_scsi_do_report_phys_luns(h, physdev, reportphyslunsize,
-							*physical_mode)) {
+	if (hpsa_scsi_do_report_phys_luns(h, physdev, sizeof(*physdev))) {
 		dev_err(&h->pdev->dev, "report physical LUNs failed.\n");
 		return -1;
 	}
-	*nphysicals = be32_to_cpu(*((__be32 *)physdev->LUNListLength)) /
-							physical_entry_size;
+	*nphysicals = be32_to_cpu(*((__be32 *)physdev->LUNListLength)) / 24;
 	if (*nphysicals > HPSA_MAX_PHYS_LUN) {
-		dev_warn(&h->pdev->dev, "maximum physical LUNs (%d) exceeded."
-			"  %d LUNs ignored.\n", HPSA_MAX_PHYS_LUN,
-			*nphysicals - HPSA_MAX_PHYS_LUN);
+		dev_warn(&h->pdev->dev, "maximum physical LUNs (%d) exceeded. %d LUNs ignored.\n",
+			HPSA_MAX_PHYS_LUN, *nphysicals - HPSA_MAX_PHYS_LUN);
 		*nphysicals = HPSA_MAX_PHYS_LUN;
 	}
-	if (hpsa_scsi_do_report_log_luns(h, logdev, reportloglunsize)) {
+	if (hpsa_scsi_do_report_log_luns(h, logdev, sizeof(*logdev))) {
 		dev_err(&h->pdev->dev, "report logical LUNs failed.\n");
 		return -1;
 	}
@@ -2900,6 +3017,33 @@ static int hpsa_hba_mode_enabled(struct ctlr_info *h)
 	return hba_mode_enabled;
 }
 
+/* get physical drive ioaccel handle and queue depth */
+static void hpsa_get_ioaccel_drive_info(struct ctlr_info *h,
+		struct hpsa_scsi_dev_t *dev,
+		u8 *lunaddrbytes,
+		struct bmic_identify_physical_device *id_phys)
+{
+	int rc;
+	struct ext_report_lun_entry *rle =
+		(struct ext_report_lun_entry *) lunaddrbytes;
+
+	dev->ioaccel_handle = rle->ioaccel_handle;
+	memset(id_phys, 0, sizeof(*id_phys));
+	rc = hpsa_bmic_id_physical_device(h, lunaddrbytes,
+			GET_BMIC_DRIVE_NUMBER(lunaddrbytes), id_phys,
+			sizeof(*id_phys));
+	if (!rc)
+		/* Reserve space for FW operations */
+#define DRIVE_CMDS_RESERVED_FOR_FW 2
+#define DRIVE_QUEUE_DEPTH 7
+		dev->queue_depth =
+			le16_to_cpu(id_phys->current_queue_depth_limit) -
+				DRIVE_CMDS_RESERVED_FOR_FW;
+	else
+		dev->queue_depth = DRIVE_QUEUE_DEPTH; /* conservative */
+	atomic_set(&dev->ioaccel_cmds_out, 0);
+}
+
 static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
 {
 	/* the idea here is we could get notified
@@ -2914,9 +3058,9 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
 	 */
 	struct ReportExtendedLUNdata *physdev_list = NULL;
 	struct ReportLUNdata *logdev_list = NULL;
+	struct bmic_identify_physical_device *id_phys = NULL;
 	u32 nphysicals = 0;
 	u32 nlogicals = 0;
-	int physical_mode = 0;
 	u32 ndev_allocated = 0;
 	struct hpsa_scsi_dev_t **currentsd, *this_device, *tmpdevice;
 	int ncurrent = 0;
@@ -2929,8 +3073,10 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
 	physdev_list = kzalloc(sizeof(*physdev_list), GFP_KERNEL);
 	logdev_list = kzalloc(sizeof(*logdev_list), GFP_KERNEL);
 	tmpdevice = kzalloc(sizeof(*tmpdevice), GFP_KERNEL);
+	id_phys = kzalloc(sizeof(*id_phys), GFP_KERNEL);
 
-	if (!currentsd || !physdev_list || !logdev_list || !tmpdevice) {
+	if (!currentsd || !physdev_list || !logdev_list ||
+		!tmpdevice || !id_phys) {
 		dev_err(&h->pdev->dev, "out of memory\n");
 		goto out;
 	}
@@ -2947,10 +3093,8 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
 
 	h->hba_mode_enabled = rescan_hba_mode;
 
-	if (hpsa_gather_lun_info(h,
-			sizeof(*physdev_list), sizeof(*logdev_list),
-			(struct ReportLUNdata *) physdev_list, &nphysicals,
-			&physical_mode, logdev_list, &nlogicals))
+	if (hpsa_gather_lun_info(h, physdev_list, &nphysicals,
+			logdev_list, &nlogicals))
 		goto out;
 
 	/* We might see up to the maximum number of logical and physical disks
@@ -3047,10 +3191,11 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
 				ncurrent++;
 				break;
 			}
-			if (physical_mode == HPSA_REPORT_PHYS_EXTENDED) {
-				memcpy(&this_device->ioaccel_handle,
-					&lunaddrbytes[20],
-					sizeof(this_device->ioaccel_handle));
+			if (h->transMethod & CFGTBL_Trans_io_accel1 ||
+				h->transMethod & CFGTBL_Trans_io_accel2) {
+				hpsa_get_ioaccel_drive_info(h, this_device,
+							lunaddrbytes, id_phys);
+				atomic_set(&this_device->ioaccel_cmds_out, 0);
 				ncurrent++;
 			}
 			break;
@@ -3074,6 +3219,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
 		if (ncurrent >= HPSA_MAX_DEVICES)
 			break;
 	}
+	hpsa_update_log_drive_phys_drive_ptrs(h, currentsd, ncurrent);
 	adjust_hpsa_scsi_table(h, hostno, currentsd, ncurrent);
 out:
 	kfree(tmpdevice);
@@ -3082,6 +3228,7 @@ out:
 	kfree(currentsd);
 	kfree(physdev_list);
 	kfree(logdev_list);
+	kfree(id_phys);
 }
 
 /*
@@ -3197,7 +3344,7 @@ static int fixup_ioaccel_cdb(u8 *cdb, int *cdb_len)
 
 static int hpsa_scsi_ioaccel1_queue_command(struct ctlr_info *h,
 	struct CommandList *c, u32 ioaccel_handle, u8 *cdb, int cdb_len,
-	u8 *scsi3addr)
+	u8 *scsi3addr, struct hpsa_scsi_dev_t *phys_disk)
 {
 	struct scsi_cmnd *cmd = c->scsi_cmd;
 	struct io_accel1_cmd *cp = &h->ioaccel_cmd_pool[c->cmdindex];
@@ -3210,13 +3357,17 @@ static int hpsa_scsi_ioaccel1_queue_command(struct ctlr_info *h,
 	u32 control = IOACCEL1_CONTROL_SIMPLEQUEUE;
 
 	/* TODO: implement chaining support */
-	if (scsi_sg_count(cmd) > h->ioaccel_maxsg)
+	if (scsi_sg_count(cmd) > h->ioaccel_maxsg) {
+		atomic_dec(&phys_disk->ioaccel_cmds_out);
 		return IO_ACCEL_INELIGIBLE;
+	}
 
 	BUG_ON(cmd->cmd_len > IOACCEL1_IOFLAGS_CDBLEN_MAX);
 
-	if (fixup_ioaccel_cdb(cdb, &cdb_len))
+	if (fixup_ioaccel_cdb(cdb, &cdb_len)) {
+		atomic_dec(&phys_disk->ioaccel_cmds_out);
 		return IO_ACCEL_INELIGIBLE;
+	}
 
 	c->cmd_type = CMD_IOACCEL1;
 
@@ -3226,8 +3377,10 @@ static int hpsa_scsi_ioaccel1_queue_command(struct ctlr_info *h,
 	BUG_ON(c->busaddr & 0x0000007F);
 
 	use_sg = scsi_dma_map(cmd);
-	if (use_sg < 0)
+	if (use_sg < 0) {
+		atomic_dec(&phys_disk->ioaccel_cmds_out);
 		return use_sg;
+	}
 
 	if (use_sg) {
 		curr_sg = cp->SG;
@@ -3286,8 +3439,10 @@ static int hpsa_scsi_ioaccel_direct_map(struct ctlr_info *h,
 	struct scsi_cmnd *cmd = c->scsi_cmd;
 	struct hpsa_scsi_dev_t *dev = cmd->device->hostdata;
 
+	c->phys_disk = dev;
+
 	return hpsa_scsi_ioaccel_queue_command(h, c, dev->ioaccel_handle,
-		cmd->cmnd, cmd->cmd_len, dev->scsi3addr);
+		cmd->cmnd, cmd->cmd_len, dev->scsi3addr, dev);
 }
 
 /*
@@ -3351,7 +3506,7 @@ static void set_encrypt_ioaccel2(struct ctlr_info *h,
 
 static int hpsa_scsi_ioaccel2_queue_command(struct ctlr_info *h,
 	struct CommandList *c, u32 ioaccel_handle, u8 *cdb, int cdb_len,
-	u8 *scsi3addr)
+	u8 *scsi3addr, struct hpsa_scsi_dev_t *phys_disk)
 {
 	struct scsi_cmnd *cmd = c->scsi_cmd;
 	struct io_accel2_cmd *cp = &h->ioaccel2_cmd_pool[c->cmdindex];
@@ -3362,11 +3517,16 @@ static int hpsa_scsi_ioaccel2_queue_command(struct ctlr_info *h,
 	u32 len;
 	u32 total_len = 0;
 
-	if (scsi_sg_count(cmd) > h->ioaccel_maxsg)
+	if (scsi_sg_count(cmd) > h->ioaccel_maxsg) {
+		atomic_dec(&phys_disk->ioaccel_cmds_out);
 		return IO_ACCEL_INELIGIBLE;
+	}
 
-	if (fixup_ioaccel_cdb(cdb, &cdb_len))
+	if (fixup_ioaccel_cdb(cdb, &cdb_len)) {
+		atomic_dec(&phys_disk->ioaccel_cmds_out);
 		return IO_ACCEL_INELIGIBLE;
+	}
+
 	c->cmd_type = CMD_IOACCEL2;
 	/* Adjust the DMA address to point to the accelerated command buffer */
 	c->busaddr = (u32) h->ioaccel2_cmd_pool_dhandle +
@@ -3377,8 +3537,10 @@ static int hpsa_scsi_ioaccel2_queue_command(struct ctlr_info *h,
 	cp->IU_type = IOACCEL2_IU_TYPE;
 
 	use_sg = scsi_dma_map(cmd);
-	if (use_sg < 0)
+	if (use_sg < 0) {
+		atomic_dec(&phys_disk->ioaccel_cmds_out);
 		return use_sg;
+	}
 
 	if (use_sg) {
 		BUG_ON(use_sg > IOACCEL2_MAXSGENTRIES);
@@ -3444,14 +3606,22 @@ static int hpsa_scsi_ioaccel2_queue_command(struct ctlr_info *h,
  */
 static int hpsa_scsi_ioaccel_queue_command(struct ctlr_info *h,
 	struct CommandList *c, u32 ioaccel_handle, u8 *cdb, int cdb_len,
-	u8 *scsi3addr)
+	u8 *scsi3addr, struct hpsa_scsi_dev_t *phys_disk)
 {
+	/* Try to honor the device's queue depth */
+	if (atomic_inc_return(&phys_disk->ioaccel_cmds_out) >
+					phys_disk->queue_depth) {
+		atomic_dec(&phys_disk->ioaccel_cmds_out);
+		return IO_ACCEL_INELIGIBLE;
+	}
 	if (h->transMethod & CFGTBL_Trans_io_accel1)
 		return hpsa_scsi_ioaccel1_queue_command(h, c, ioaccel_handle,
-						cdb, cdb_len, scsi3addr);
+						cdb, cdb_len, scsi3addr,
+						phys_disk);
 	else
 		return hpsa_scsi_ioaccel2_queue_command(h, c, ioaccel_handle,
-						cdb, cdb_len, scsi3addr);
+						cdb, cdb_len, scsi3addr,
+						phys_disk);
 }
 
 static void raid_map_helper(struct raid_map_data *map,
@@ -3755,6 +3925,8 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h,
 		return IO_ACCEL_INELIGIBLE;
 	}
 
+	c->phys_disk = dev->phys_disk[map_index];
+
 	disk_handle = dd[map_index].ioaccel_handle;
 	disk_block = le64_to_cpu(map->disk_starting_blk) +
 			first_row * le16_to_cpu(map->strip_size) +
@@ -3802,7 +3974,8 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h,
 		cdb_len = 10;
 	}
 	return hpsa_scsi_ioaccel_queue_command(h, c, disk_handle, cdb, cdb_len,
-						dev->scsi3addr);
+						dev->scsi3addr,
+						dev->phys_disk[map_index]);
 }
 
 /* Submit commands down the "normal" RAID stack path */
@@ -4016,15 +4189,17 @@ static void hpsa_scan_start(struct Scsi_Host *sh)
 
 static int hpsa_change_queue_depth(struct scsi_device *sdev, int qdepth)
 {
-	struct ctlr_info *h = sdev_to_hba(sdev);
+	struct hpsa_scsi_dev_t *logical_drive = sdev->hostdata;
+
+	if (!logical_drive)
+		return -ENODEV;
 
 	if (qdepth < 1)
 		qdepth = 1;
-	else
-		if (qdepth > h->nr_cmds)
-			qdepth = h->nr_cmds;
-	scsi_change_queue_depth(sdev, qdepth);
-	return sdev->queue_depth;
+	else if (qdepth > logical_drive->queue_depth)
+		qdepth = logical_drive->queue_depth;
+
+	return scsi_change_queue_depth(sdev, qdepth);
 }
 
 static int hpsa_scan_finished(struct Scsi_Host *sh,
@@ -4068,10 +4243,7 @@ static int hpsa_register_scsi(struct ctlr_info *h)
 			HPSA_CMDS_RESERVED_FOR_ABORTS -
 			HPSA_CMDS_RESERVED_FOR_DRIVER -
 			HPSA_MAX_CONCURRENT_PASSTHRUS;
-	if (h->hba_mode_enabled)
-		sh->cmd_per_lun = 7;
-	else
-		sh->cmd_per_lun = sh->can_queue;
+	sh->cmd_per_lun = sh->can_queue;
 	sh->sg_tablesize = h->maxsgentries;
 	h->scsi_host = sh;
 	sh->hostdata[0] = (unsigned long) h;
@@ -5090,6 +5262,16 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
 			c->Request.CDB[7] = (size >> 16) & 0xFF;
 			c->Request.CDB[8] = (size >> 8) & 0xFF;
 			break;
+		case BMIC_IDENTIFY_PHYSICAL_DEVICE:
+			c->Request.CDBLen = 10;
+			c->Request.type_attr_dir =
+				TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_READ);
+			c->Request.Timeout = 0;
+			c->Request.CDB[0] = BMIC_READ;
+			c->Request.CDB[6] = BMIC_IDENTIFY_PHYSICAL_DEVICE;
+			c->Request.CDB[7] = (size >> 16) & 0xFF;
+			c->Request.CDB[8] = (size >> 8) & 0XFF;
+			break;
 		default:
 			dev_warn(&h->pdev->dev, "unknown command 0x%c\n", cmd);
 			BUG();
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index a0f4268..d0fb854 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -46,6 +46,11 @@ struct hpsa_scsi_dev_t {
 	unsigned char model[16];        /* bytes 16-31 of inquiry data */
 	unsigned char raid_level;	/* from inquiry page 0xC1 */
 	unsigned char volume_offline;	/* discovered via TUR or VPD */
+	u16 queue_depth;		/* max queue_depth for this device */
+	atomic_t ioaccel_cmds_out;	/* Only used for physical devices
+					 * counts commands sent to physical
+					 * device via "ioaccel" path.
+					 */
 	u32 ioaccel_handle;
 	int offload_config;		/* I/O accel RAID offload configured */
 	int offload_enabled;		/* I/O accel RAID offload enabled */
@@ -54,6 +59,15 @@ struct hpsa_scsi_dev_t {
 					 */
 	struct raid_map_data raid_map;	/* I/O accelerator RAID map */
 
+	/*
+	 * Pointers from logical drive map indices to the phys drives that
+	 * make those logical drives.  Note, multiple logical drives may
+	 * share physical drives.  You can have for instance 5 physical
+	 * drives with 3 logical drives each using those same 5 physical
+	 * disks. We need these pointers for counting i/o's out to physical
+	 * devices in order to honor physical device queue depth limits.
+	 */
+	struct hpsa_scsi_dev_t *phys_disk[RAID_MAP_MAX_ENTRIES];
 };
 
 struct reply_queue_buffer {
diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h
index 3f2f0af..4726dbb 100644
--- a/drivers/scsi/hpsa_cmd.h
+++ b/drivers/scsi/hpsa_cmd.h
@@ -240,6 +240,10 @@ struct ReportLUNdata {
 
 struct ext_report_lun_entry {
 	u8 lunid[8];
+#define GET_BMIC_BUS(lunid) ((lunid)[7] & 0x3F)
+#define GET_BMIC_LEVEL_TWO_TARGET(lunid) ((lunid)[6])
+#define GET_BMIC_DRIVE_NUMBER(lunid) (((GET_BMIC_BUS((lunid)) - 1) << 8) + \
+			GET_BMIC_LEVEL_TWO_TARGET((lunid)))
 	u8 wwid[8];
 	u8 device_type;
 	u8 device_flags;
@@ -268,6 +272,7 @@ struct SenseSubsystem_info {
 #define HPSA_CACHE_FLUSH 0x01	/* C2 was already being used by HPSA */
 #define BMIC_FLASH_FIRMWARE 0xF7
 #define BMIC_SENSE_CONTROLLER_PARAMETERS 0x64
+#define BMIC_IDENTIFY_PHYSICAL_DEVICE 0x15
 
 /* Command List Structure */
 union SCSI3Addr {
@@ -405,6 +410,17 @@ struct CommandList {
 	struct completion *waiting;
 	void   *scsi_cmd;
 	struct work_struct work;
+
+	/*
+	 * For commands using either of the two "ioaccel" paths to
+	 * bypass the RAID stack and go directly to the physical disk
+	 * phys_disk is a pointer to the hpsa_scsi_dev_t to which the
+	 * i/o is destined.  We need to store that here because the command
+	 * may potentially encounter TASK SET FULL and need to be resubmitted
+	 * For "normal" i/o's not using the "ioaccel" paths, phys_disk is
+	 * not used.
+	 */
+	struct hpsa_scsi_dev_t *phys_disk;
 } __aligned(COMMANDLIST_ALIGNMENT);
 
 /* Max S/G elements in I/O accelerator command */
@@ -641,5 +657,137 @@ struct hpsa_pci_info {
 	u32		board_id;
 };
 
+struct bmic_identify_physical_device {
+	u8    scsi_bus;          /* SCSI Bus number on controller */
+	u8    scsi_id;           /* SCSI ID on this bus */
+	__le16 block_size;	     /* sector size in bytes */
+	__le32 total_blocks;	     /* number for sectors on drive */
+	__le32 reserved_blocks;   /* controller reserved (RIS) */
+	u8    model[40];         /* Physical Drive Model */
+	u8    serial_number[40]; /* Drive Serial Number */
+	u8    firmware_revision[8]; /* drive firmware revision */
+	u8    scsi_inquiry_bits; /* inquiry byte 7 bits */
+	u8    compaq_drive_stamp; /* 0 means drive not stamped */
+	u8    last_failure_reason;
+#define BMIC_LAST_FAILURE_TOO_SMALL_IN_LOAD_CONFIG		0x01
+#define BMIC_LAST_FAILURE_ERROR_ERASING_RIS			0x02
+#define BMIC_LAST_FAILURE_ERROR_SAVING_RIS			0x03
+#define BMIC_LAST_FAILURE_FAIL_DRIVE_COMMAND			0x04
+#define BMIC_LAST_FAILURE_MARK_BAD_FAILED			0x05
+#define BMIC_LAST_FAILURE_MARK_BAD_FAILED_IN_FINISH_REMAP	0x06
+#define BMIC_LAST_FAILURE_TIMEOUT				0x07
+#define BMIC_LAST_FAILURE_AUTOSENSE_FAILED			0x08
+#define BMIC_LAST_FAILURE_MEDIUM_ERROR_1			0x09
+#define BMIC_LAST_FAILURE_MEDIUM_ERROR_2			0x0a
+#define BMIC_LAST_FAILURE_NOT_READY_BAD_SENSE			0x0b
+#define BMIC_LAST_FAILURE_NOT_READY				0x0c
+#define BMIC_LAST_FAILURE_HARDWARE_ERROR			0x0d
+#define BMIC_LAST_FAILURE_ABORTED_COMMAND			0x0e
+#define BMIC_LAST_FAILURE_WRITE_PROTECTED			0x0f
+#define BMIC_LAST_FAILURE_SPIN_UP_FAILURE_IN_RECOVER		0x10
+#define BMIC_LAST_FAILURE_REBUILD_WRITE_ERROR			0x11
+#define BMIC_LAST_FAILURE_TOO_SMALL_IN_HOT_PLUG			0x12
+#define BMIC_LAST_FAILURE_BUS_RESET_RECOVERY_ABORTED		0x13
+#define BMIC_LAST_FAILURE_REMOVED_IN_HOT_PLUG			0x14
+#define BMIC_LAST_FAILURE_INIT_REQUEST_SENSE_FAILED		0x15
+#define BMIC_LAST_FAILURE_INIT_START_UNIT_FAILED		0x16
+#define BMIC_LAST_FAILURE_INQUIRY_FAILED			0x17
+#define BMIC_LAST_FAILURE_NON_DISK_DEVICE			0x18
+#define BMIC_LAST_FAILURE_READ_CAPACITY_FAILED			0x19
+#define BMIC_LAST_FAILURE_INVALID_BLOCK_SIZE			0x1a
+#define BMIC_LAST_FAILURE_HOT_PLUG_REQUEST_SENSE_FAILED		0x1b
+#define BMIC_LAST_FAILURE_HOT_PLUG_START_UNIT_FAILED		0x1c
+#define BMIC_LAST_FAILURE_WRITE_ERROR_AFTER_REMAP		0x1d
+#define BMIC_LAST_FAILURE_INIT_RESET_RECOVERY_ABORTED		0x1e
+#define BMIC_LAST_FAILURE_DEFERRED_WRITE_ERROR			0x1f
+#define BMIC_LAST_FAILURE_MISSING_IN_SAVE_RIS			0x20
+#define BMIC_LAST_FAILURE_WRONG_REPLACE				0x21
+#define BMIC_LAST_FAILURE_GDP_VPD_INQUIRY_FAILED		0x22
+#define BMIC_LAST_FAILURE_GDP_MODE_SENSE_FAILED			0x23
+#define BMIC_LAST_FAILURE_DRIVE_NOT_IN_48BIT_MODE		0x24
+#define BMIC_LAST_FAILURE_DRIVE_TYPE_MIX_IN_HOT_PLUG		0x25
+#define BMIC_LAST_FAILURE_DRIVE_TYPE_MIX_IN_LOAD_CFG		0x26
+#define BMIC_LAST_FAILURE_PROTOCOL_ADAPTER_FAILED		0x27
+#define BMIC_LAST_FAILURE_FAULTY_ID_BAY_EMPTY			0x28
+#define BMIC_LAST_FAILURE_FAULTY_ID_BAY_OCCUPIED		0x29
+#define BMIC_LAST_FAILURE_FAULTY_ID_INVALID_BAY			0x2a
+#define BMIC_LAST_FAILURE_WRITE_RETRIES_FAILED			0x2b
+
+#define BMIC_LAST_FAILURE_SMART_ERROR_REPORTED			0x37
+#define BMIC_LAST_FAILURE_PHY_RESET_FAILED			0x38
+#define BMIC_LAST_FAILURE_ONLY_ONE_CTLR_CAN_SEE_DRIVE		0x40
+#define BMIC_LAST_FAILURE_KC_VOLUME_FAILED			0x41
+#define BMIC_LAST_FAILURE_UNEXPECTED_REPLACEMENT		0x42
+#define BMIC_LAST_FAILURE_OFFLINE_ERASE				0x80
+#define BMIC_LAST_FAILURE_OFFLINE_TOO_SMALL			0x81
+#define BMIC_LAST_FAILURE_OFFLINE_DRIVE_TYPE_MIX		0x82
+#define BMIC_LAST_FAILURE_OFFLINE_ERASE_COMPLETE		0x83
+
+	u8     flags;
+	u8     more_flags;
+	u8     scsi_lun;          /* SCSI LUN for phys drive */
+	u8     yet_more_flags;
+	u8     even_more_flags;
+	__le32 spi_speed_rules;/* SPI Speed data:Ultra disable diagnose */
+	u8     phys_connector[2];         /* connector number on controller */
+	u8     phys_box_on_bus;  /* phys enclosure this drive resides */
+	u8     phys_bay_in_box;  /* phys drv bay this drive resides */
+	__le32 rpm;              /* Drive rotational speed in rpm */
+	u8     device_type;       /* type of drive */
+	u8     sata_version;     /* only valid when drive_type is SATA */
+	__le64 big_total_block_count;
+	__le64 ris_starting_lba;
+	__le32 ris_size;
+	u8     wwid[20];
+	u8     controller_phy_map[32];
+	__le16 phy_count;
+	u8     phy_connected_dev_type[256];
+	u8     phy_to_drive_bay_num[256];
+	__le16 phy_to_attached_dev_index[256];
+	u8     box_index;
+	u8     reserved;
+	__le16 extra_physical_drive_flags;
+#define BMIC_PHYS_DRIVE_SUPPORTS_GAS_GAUGE(idphydrv) \
+	(idphydrv->extra_physical_drive_flags & (1 << 10))
+	u8     negotiated_link_rate[256];
+	u8     phy_to_phy_map[256];
+	u8     redundant_path_present_map;
+	u8     redundant_path_failure_map;
+	u8     active_path_number;
+	__le16 alternate_paths_phys_connector[8];
+	u8     alternate_paths_phys_box_on_port[8];
+	u8     multi_lun_device_lun_count;
+	u8     minimum_good_fw_revision[8];
+	u8     unique_inquiry_bytes[20];
+	u8     current_temperature_degreesC;
+	u8     temperature_threshold_degreesC;
+	u8     max_temperature_degreesC;
+	u8     logical_blocks_per_phys_block_exp; /* phyblocksize = 512*2^exp */
+	__le16 current_queue_depth_limit;
+	u8     switch_name[10];
+	__le16 switch_port;
+	u8     alternate_paths_switch_name[40];
+	u8     alternate_paths_switch_port[8];
+	__le16 power_on_hours; /* valid only if gas gauge supported */
+	__le16 percent_endurance_used; /* valid only if gas gauge supported. */
+#define BMIC_PHYS_DRIVE_SSD_WEAROUT(idphydrv) \
+	((idphydrv->percent_endurance_used & 0x80) || \
+	 (idphydrv->percent_endurance_used > 10000))
+	u8     drive_authentication;
+#define BMIC_PHYS_DRIVE_AUTHENTICATED(idphydrv) \
+	(idphydrv->drive_authentication == 0x80)
+	u8     smart_carrier_authentication;
+#define BMIC_SMART_CARRIER_AUTHENTICATION_SUPPORTED(idphydrv) \
+	(idphydrv->smart_carrier_authentication != 0x0)
+#define BMIC_SMART_CARRIER_AUTHENTICATED(idphydrv) \
+	(idphydrv->smart_carrier_authentication == 0x01)
+	u8     smart_carrier_app_fw_version;
+	u8     smart_carrier_bootloader_fw_version;
+	u8     encryption_key_name[64];
+	__le32 misc_drive_flags;
+	__le16 dek_index;
+	u8     padding[112];
+};
+
 #pragma pack()
 #endif /* HPSA_CMD_H */


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 29/48] hpsa: fix race between abort handler and main i/o path
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (27 preceding siblings ...)
  2015-01-23 22:43 ` [PATCH v2 28/48] hpsa: honor queue depth of physical devices Don Brace
@ 2015-01-23 22:43 ` Don Brace
  2015-01-23 22:43 ` [PATCH v2 30/48] hpsa: optimize cmd_alloc function by remembering last allocation Don Brace
                   ` (18 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:43 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Webb Scales <webbnh@hp.com>

This means changing the allocator to reference count commands.
The reference count is now the authoritative indicator of whether a
command is allocated or not.  The h->cmd_pool_bits bitmap is now
only a heuristic hint to speed up the allocation process, it is no
longer the authoritative record of allocated commands.

Since we changed the command allocator to use reference counting
as the authoritative indicator of whether a command is allocated,
fail_all_outstanding_cmds needs to use the reference count not
h->cmd_pool_bits for this purpose.

Fix hpsa_drain_accel_commands to use the reference count as the
authoritative indicator of whether a command is allocated instead of
the h->cmd_pool_bits bitmap.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c     |  109 +++++++++++++++++++++++++++--------------------
 drivers/scsi/hpsa.h     |    2 +
 drivers/scsi/hpsa_cmd.h |    1 
 3 files changed, 65 insertions(+), 47 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 60f5734..c95a20c 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -4552,6 +4552,7 @@ static int hpsa_eh_abort_handler(struct scsi_cmnd *sc)
 	char msg[256];		/* For debug messaging. */
 	int ml = 0;
 	__le32 tagupper, taglower;
+	int refcount;
 
 	/* Find the controller of the command to be aborted */
 	h = sdev_to_hba(sc->device);
@@ -4580,9 +4581,13 @@ static int hpsa_eh_abort_handler(struct scsi_cmnd *sc)
 	/* Get SCSI command to be aborted */
 	abort = (struct CommandList *) sc->host_scribble;
 	if (abort == NULL) {
-		dev_err(&h->pdev->dev, "%s FAILED, Command to abort is NULL.\n",
-				msg);
-		return FAILED;
+		/* This can happen if the command already completed. */
+		return SUCCESS;
+	}
+	refcount = atomic_inc_return(&abort->refcount);
+	if (refcount == 1) { /* Command is done already. */
+		cmd_free(h, abort);
+		return SUCCESS;
 	}
 	hpsa_get_tag(h, abort, &taglower, &tagupper);
 	ml += sprintf(msg+ml, "Tag:0x%08x:%08x ", tagupper, taglower);
@@ -4604,6 +4609,7 @@ static int hpsa_eh_abort_handler(struct scsi_cmnd *sc)
 		dev_warn(&h->pdev->dev, "FAILED abort on device C%d:B%d:T%d:L%d\n",
 			h->scsi_host->host_no,
 			dev->bus, dev->target, dev->lun);
+		cmd_free(h, abort);
 		return FAILED;
 	}
 	dev_info(&h->pdev->dev, "%s REQUEST SUCCEEDED.\n", msg);
@@ -4615,32 +4621,35 @@ static int hpsa_eh_abort_handler(struct scsi_cmnd *sc)
 	 */
 #define ABORT_COMPLETE_WAIT_SECS 30
 	for (i = 0; i < ABORT_COMPLETE_WAIT_SECS * 10; i++) {
-		if (test_bit(abort->cmdindex & (BITS_PER_LONG - 1),
-				h->cmd_pool_bits +
-				(abort->cmdindex / BITS_PER_LONG)))
-			msleep(100);
-		else
+		refcount = atomic_read(&abort->refcount);
+		if (refcount < 2) {
+			cmd_free(h, abort);
 			return SUCCESS;
+		} else {
+			msleep(100);
+		}
 	}
 	dev_warn(&h->pdev->dev, "%s FAILED. Aborted command has not completed after %d seconds.\n",
 		msg, ABORT_COMPLETE_WAIT_SECS);
+	cmd_free(h, abort);
 	return FAILED;
 }
 
-
 /*
  * For operations that cannot sleep, a command block is allocated at init,
  * and managed by cmd_alloc() and cmd_free() using a simple bitmap to track
  * which ones are free or in use.  Lock must be held when calling this.
  * cmd_free() is the complement.
  */
+
 static struct CommandList *cmd_alloc(struct ctlr_info *h)
 {
 	struct CommandList *c;
 	int i;
 	union u64bit temp64;
 	dma_addr_t cmd_dma_handle, err_dma_handle;
-	int loopcount;
+	int refcount;
+	unsigned long offset = 0;
 
 	/* There is some *extremely* small but non-zero chance that that
 	 * multiple threads could get in here, and one thread could
@@ -4653,23 +4662,27 @@ static struct CommandList *cmd_alloc(struct ctlr_info *h)
 	 * infrequently as to be indistinguishable from never.
 	 */
 
-	loopcount = 0;
-	do {
-		i = find_first_zero_bit(h->cmd_pool_bits, h->nr_cmds);
-		if (i == h->nr_cmds)
-			i = 0;
-		loopcount++;
-	} while (test_and_set_bit(i & (BITS_PER_LONG - 1),
-		  h->cmd_pool_bits + (i / BITS_PER_LONG)) != 0 &&
-		loopcount < 10);
-
-	/* Thread got starved?  We do not expect this to ever happen. */
-	if (loopcount >= 10)
-		return NULL;
-
-	c = h->cmd_pool + i;
-	memset(c, 0, sizeof(*c));
-	c->Header.tag = cpu_to_le64((u64) i << DIRECT_LOOKUP_SHIFT);
+	for (;;) {
+		i = find_next_zero_bit(h->cmd_pool_bits, h->nr_cmds, offset);
+		if (unlikely(i == h->nr_cmds)) {
+			offset = 0;
+			continue;
+		}
+		c = h->cmd_pool + i;
+		refcount = atomic_inc_return(&c->refcount);
+		if (unlikely(refcount > 1)) {
+			cmd_free(h, c); /* already in use */
+			offset = (i + 1) % h->nr_cmds;
+			continue;
+		}
+		set_bit(i & (BITS_PER_LONG - 1),
+			h->cmd_pool_bits + (i / BITS_PER_LONG));
+		break; /* it's ours now. */
+	}
+
+	/* Zero out all of commandlist except the last field, refcount */
+	memset(c, 0, offsetof(struct CommandList, refcount));
+	c->Header.tag = cpu_to_le64((u64) (i << DIRECT_LOOKUP_SHIFT));
 	cmd_dma_handle = h->cmd_pool_dhandle + i * sizeof(*c);
 	c->err_info = h->errinfo_pool + i;
 	memset(c->err_info, 0, sizeof(*c->err_info));
@@ -4680,8 +4693,8 @@ static struct CommandList *cmd_alloc(struct ctlr_info *h)
 
 	c->busaddr = (u32) cmd_dma_handle;
 	temp64.val = (u64) err_dma_handle;
-	c->ErrDesc.Addr = cpu_to_le64(err_dma_handle);
-	c->ErrDesc.Len = cpu_to_le32(sizeof(*c->err_info));
+	c->ErrDesc.Addr = cpu_to_le64((u64) err_dma_handle);
+	c->ErrDesc.Len = cpu_to_le32((u32) sizeof(*c->err_info));
 
 	c->h = h;
 	return c;
@@ -4689,11 +4702,13 @@ static struct CommandList *cmd_alloc(struct ctlr_info *h)
 
 static void cmd_free(struct ctlr_info *h, struct CommandList *c)
 {
-	int i;
+	if (atomic_dec_and_test(&c->refcount)) {
+		int i;
 
-	i = c - h->cmd_pool;
-	clear_bit(i & (BITS_PER_LONG - 1),
-		  h->cmd_pool_bits + (i / BITS_PER_LONG));
+		i = c - h->cmd_pool;
+		clear_bit(i & (BITS_PER_LONG - 1),
+			  h->cmd_pool_bits + (i / BITS_PER_LONG));
+	}
 }
 
 #ifdef CONFIG_COMPAT
@@ -6598,17 +6613,18 @@ static void hpsa_undo_allocations_after_kdump_soft_reset(struct ctlr_info *h)
 /* Called when controller lockup detected. */
 static void fail_all_outstanding_cmds(struct ctlr_info *h)
 {
-	int i;
-	struct CommandList *c = NULL;
+	int i, refcount;
+	struct CommandList *c;
 
 	flush_workqueue(h->resubmit_wq); /* ensure all cmds are fully built */
 	for (i = 0; i < h->nr_cmds; i++) {
-		if (!test_bit(i & (BITS_PER_LONG - 1),
-				h->cmd_pool_bits + (i / BITS_PER_LONG)))
-			continue;
 		c = h->cmd_pool + i;
-		c->err_info->CommandStatus = CMD_HARDWARE_ERR;
-		finish_cmd(c);
+		refcount = atomic_inc_return(&c->refcount);
+		if (refcount > 1) {
+			c->err_info->CommandStatus = CMD_HARDWARE_ERR;
+			finish_cmd(c);
+		}
+		cmd_free(h, c);
 	}
 }
 
@@ -6645,9 +6661,7 @@ static void controller_lockup_detected(struct ctlr_info *h)
 	dev_warn(&h->pdev->dev, "Controller lockup detected: 0x%08x\n",
 			lockup_detected);
 	pci_disable_device(h->pdev);
-	spin_lock_irqsave(&h->lock, flags);
 	fail_all_outstanding_cmds(h);
-	spin_unlock_irqrestore(&h->lock, flags);
 }
 
 static void detect_controller_lockup(struct ctlr_info *h)
@@ -7449,18 +7463,19 @@ static void hpsa_drain_accel_commands(struct ctlr_info *h)
 {
 	struct CommandList *c = NULL;
 	int i, accel_cmds_out;
+	int refcount;
 
 	do { /* wait for all outstanding ioaccel commands to drain out */
 		accel_cmds_out = 0;
 		for (i = 0; i < h->nr_cmds; i++) {
-			if (!test_bit(i & (BITS_PER_LONG - 1),
-					h->cmd_pool_bits + (i / BITS_PER_LONG)))
-				continue;
 			c = h->cmd_pool + i;
-			accel_cmds_out += is_accelerated_cmd(c);
+			refcount = atomic_inc_return(&c->refcount);
+			if (refcount > 1) /* Command is allocated */
+				accel_cmds_out += is_accelerated_cmd(c);
+			cmd_free(h, c);
 		}
 		if (accel_cmds_out <= 0)
-				break;
+			break;
 		msleep(100);
 	} while (1);
 }
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index d0fb854..679e4d2 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -309,6 +309,8 @@ struct offline_device_entry {
  */
 #define SA5_DOORBELL	0x20
 #define SA5_REQUEST_PORT_OFFSET	0x40
+#define SA5_REQUEST_PORT64_LO_OFFSET 0xC0
+#define SA5_REQUEST_PORT64_HI_OFFSET 0xC4
 #define SA5_REPLY_INTR_MASK_OFFSET	0x34
 #define SA5_REPLY_PORT_OFFSET		0x44
 #define SA5_INTR_STATUS		0x30
diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h
index 4726dbb..071b64c 100644
--- a/drivers/scsi/hpsa_cmd.h
+++ b/drivers/scsi/hpsa_cmd.h
@@ -421,6 +421,7 @@ struct CommandList {
 	 * not used.
 	 */
 	struct hpsa_scsi_dev_t *phys_disk;
+	atomic_t refcount; /* Must be last to avoid memset in cmd_alloc */
 } __aligned(COMMANDLIST_ALIGNMENT);
 
 /* Max S/G elements in I/O accelerator command */


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 30/48] hpsa: optimize cmd_alloc function by remembering last allocation
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (28 preceding siblings ...)
  2015-01-23 22:43 ` [PATCH v2 29/48] hpsa: fix race between abort handler and main i/o path Don Brace
@ 2015-01-23 22:43 ` Don Brace
  2015-01-23 22:43 ` [PATCH v2 31/48] hpsa: count passthru cmds with atomics, not a spin locked int Don Brace
                   ` (17 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:43 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Robert Elliott <elliott@hp.com>

Empirically, this improves performance slightly (~2% max IOPS) by
allowing cmd_alloc to remember where it left off searching for
free commands between calls instead of always starting its search
at command 0.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Robert Elliott <elliott@hp.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |    7 +++++--
 drivers/scsi/hpsa.h |    1 +
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index c95a20c..72abcf3 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -4649,9 +4649,10 @@ static struct CommandList *cmd_alloc(struct ctlr_info *h)
 	union u64bit temp64;
 	dma_addr_t cmd_dma_handle, err_dma_handle;
 	int refcount;
-	unsigned long offset = 0;
+	unsigned long offset;
 
-	/* There is some *extremely* small but non-zero chance that that
+	/*
+	 * There is some *extremely* small but non-zero chance that that
 	 * multiple threads could get in here, and one thread could
 	 * be scanning through the list of bits looking for a free
 	 * one, but the free ones are always behind him, and other
@@ -4662,6 +4663,7 @@ static struct CommandList *cmd_alloc(struct ctlr_info *h)
 	 * infrequently as to be indistinguishable from never.
 	 */
 
+	offset = h->last_allocation; /* benignly racy */
 	for (;;) {
 		i = find_next_zero_bit(h->cmd_pool_bits, h->nr_cmds, offset);
 		if (unlikely(i == h->nr_cmds)) {
@@ -4679,6 +4681,7 @@ static struct CommandList *cmd_alloc(struct ctlr_info *h)
 			h->cmd_pool_bits + (i / BITS_PER_LONG));
 		break; /* it's ours now. */
 	}
+	h->last_allocation = i; /* benignly racy */
 
 	/* Zero out all of commandlist except the last field, refcount */
 	memset(c, 0, offsetof(struct CommandList, refcount));
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index 679e4d2..981479a 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -133,6 +133,7 @@ struct ctlr_info {
 	struct CfgTable __iomem *cfgtable;
 	int	interrupts_enabled;
 	int 	max_commands;
+	int last_allocation;
 	atomic_t commands_outstanding;
 #	define PERF_MODE_INT	0
 #	define DOORBELL_INT	1


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 31/48] hpsa: count passthru cmds with atomics, not a spin locked int
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (29 preceding siblings ...)
  2015-01-23 22:43 ` [PATCH v2 30/48] hpsa: optimize cmd_alloc function by remembering last allocation Don Brace
@ 2015-01-23 22:43 ` Don Brace
  2015-01-23 22:43 ` [PATCH v2 32/48] hpsa: slightly optimize SA5_performant_completed Don Brace
                   ` (16 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:43 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

Performance enhancement. Remove spin_locks from the driver.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |   39 +++++----------------------------------
 drivers/scsi/hpsa.h |    3 +--
 2 files changed, 6 insertions(+), 36 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 72abcf3..bae3759 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -5105,35 +5105,6 @@ static void check_ioctl_unit_attention(struct ctlr_info *h,
 		(void) check_for_unit_attention(h, c);
 }
 
-static int increment_passthru_count(struct ctlr_info *h)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&h->passthru_count_lock, flags);
-	if (h->passthru_count >= HPSA_MAX_CONCURRENT_PASSTHRUS) {
-		spin_unlock_irqrestore(&h->passthru_count_lock, flags);
-		return -1;
-	}
-	h->passthru_count++;
-	spin_unlock_irqrestore(&h->passthru_count_lock, flags);
-	return 0;
-}
-
-static void decrement_passthru_count(struct ctlr_info *h)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&h->passthru_count_lock, flags);
-	if (h->passthru_count <= 0) {
-		spin_unlock_irqrestore(&h->passthru_count_lock, flags);
-		/* not expecting to get here. */
-		dev_warn(&h->pdev->dev, "Bug detected, passthru_count seems to be incorrect.\n");
-		return;
-	}
-	h->passthru_count--;
-	spin_unlock_irqrestore(&h->passthru_count_lock, flags);
-}
-
 /*
  * ioctl
  */
@@ -5156,16 +5127,16 @@ static int hpsa_ioctl(struct scsi_device *dev, int cmd, void __user *arg)
 	case CCISS_GETDRIVVER:
 		return hpsa_getdrivver_ioctl(h, argp);
 	case CCISS_PASSTHRU:
-		if (increment_passthru_count(h))
+		if (atomic_dec_if_positive(&h->passthru_cmds_avail) < 0)
 			return -EAGAIN;
 		rc = hpsa_passthru_ioctl(h, argp);
-		decrement_passthru_count(h);
+		atomic_inc(&h->passthru_cmds_avail);
 		return rc;
 	case CCISS_BIG_PASSTHRU:
-		if (increment_passthru_count(h))
+		if (atomic_dec_if_positive(&h->passthru_cmds_avail) < 0)
 			return -EAGAIN;
 		rc = hpsa_big_passthru_ioctl(h, argp);
-		decrement_passthru_count(h);
+		atomic_inc(&h->passthru_cmds_avail);
 		return rc;
 	default:
 		return -ENOTTY;
@@ -6852,7 +6823,7 @@ reinit_after_soft_reset:
 	spin_lock_init(&h->lock);
 	spin_lock_init(&h->offline_device_lock);
 	spin_lock_init(&h->scan_lock);
-	spin_lock_init(&h->passthru_count_lock);
+	atomic_set(&h->passthru_cmds_avail, HPSA_MAX_CONCURRENT_PASSTHRUS);
 
 	h->resubmit_wq = alloc_workqueue("hpsa", WQ_MEM_RECLAIM, 0);
 	if (!h->resubmit_wq) {
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index 981479a..1856445 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -183,8 +183,7 @@ struct ctlr_info {
 
 	/* cap concurrent passthrus at some reasonable maximum */
 #define HPSA_MAX_CONCURRENT_PASSTHRUS (10)
-	spinlock_t passthru_count_lock; /* protects passthru_count */
-	int passthru_count;
+	atomic_t passthru_cmds_avail;
 
 	/*
 	 * Performant mode completion buffers


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 32/48] hpsa: slightly optimize SA5_performant_completed
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (30 preceding siblings ...)
  2015-01-23 22:43 ` [PATCH v2 31/48] hpsa: count passthru cmds with atomics, not a spin locked int Don Brace
@ 2015-01-23 22:43 ` Don Brace
  2015-01-23 22:43 ` [PATCH v2 33/48] hpsa: do not check for msi(x) in interrupt_pending Don Brace
                   ` (15 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:43 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.h |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index 1856445..aa6cb0b 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -412,19 +412,19 @@ static unsigned long SA5_performant_completed(struct ctlr_info *h, u8 q)
 	unsigned long register_value = FIFO_EMPTY;
 
 	/* msi auto clears the interrupt pending bit. */
-	if (!(h->msi_vector || h->msix_vector)) {
+	if (unlikely(!(h->msi_vector || h->msix_vector))) {
 		/* flush the controller write of the reply queue by reading
 		 * outbound doorbell status register.
 		 */
-		register_value = readl(h->vaddr + SA5_OUTDB_STATUS);
+		(void) readl(h->vaddr + SA5_OUTDB_STATUS);
 		writel(SA5_OUTDB_CLEAR_PERF_BIT, h->vaddr + SA5_OUTDB_CLEAR);
 		/* Do a read in order to flush the write to the controller
 		 * (as per spec.)
 		 */
-		register_value = readl(h->vaddr + SA5_OUTDB_STATUS);
+		(void) readl(h->vaddr + SA5_OUTDB_STATUS);
 	}
 
-	if ((rq->head[rq->current_entry] & 1) == rq->wraparound) {
+	if ((((u32) rq->head[rq->current_entry]) & 1) == rq->wraparound) {
 		register_value = rq->head[rq->current_entry];
 		rq->current_entry++;
 		atomic_dec(&h->commands_outstanding);


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 33/48] hpsa: do not check for msi(x) in interrupt_pending
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (31 preceding siblings ...)
  2015-01-23 22:43 ` [PATCH v2 32/48] hpsa: slightly optimize SA5_performant_completed Don Brace
@ 2015-01-23 22:43 ` Don Brace
  2015-01-23 22:44 ` [PATCH v2 34/48] hpsa: remove incorrect BUG_ONs checking for raid offload enable Don Brace
                   ` (14 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:43 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Stephen Cameron <stephenmcameron@gmail.com>

No need to check whether interrupt pending for MSI(X) and
conversely, no need to check whether MSI(X) interrupts are
being used when checking if interrupts are pending.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.h |    3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index aa6cb0b..239ecea 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -479,9 +479,6 @@ static bool SA5_performant_intr_pending(struct ctlr_info *h)
 	if (!register_value)
 		return false;
 
-	if (h->msi_vector || h->msix_vector)
-		return true;
-
 	/* Read outbound doorbell to flush */
 	register_value = readl(h->vaddr + SA5_OUTDB_STATUS);
 	return register_value & SA5_OUTDB_STATUS_PERF_BIT;


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 34/48] hpsa: remove incorrect BUG_ONs checking for raid offload enable
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (32 preceding siblings ...)
  2015-01-23 22:43 ` [PATCH v2 33/48] hpsa: do not check for msi(x) in interrupt_pending Don Brace
@ 2015-01-23 22:44 ` Don Brace
  2015-01-23 22:44 ` [PATCH v2 35/48] hpsa: do not ack controller events on controllers that do not support it Don Brace
                   ` (13 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:44 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Stephen Cameron <stephenmcameron@gmail.com>

In set_encrypt_ioaccel2() and in hpsa_scsi_ioaccel_raid_map
there were BUG_ONs that looked like this:

	BUG_ON(!(dev->offload_config && dev->offload_enabled));

But, In hpsa_ack_ctlr_events() we have this,

	/* Stop sending new RAID offload reqs via the IO accelerator */
	scsi_block_requests(h->scsi_host);
	for (i = 0; i < h->ndevices; i++)
		h->dev[i]->offload_enabled = 0;
	hpsa_drain_accel_commands(h);

So, we set offload_enabled = 0 for all drives, then do this
drain_accel_commands, so that means accel commands could still
be in flight, ie. perhaps having just been submitted into
hpsa_scsi_ioaccel_raid_map concurrent with ->offload_enabled
having just been set to zero.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |    4 ----
 1 file changed, 4 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index bae3759..5abd49d 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -3456,8 +3456,6 @@ static void set_encrypt_ioaccel2(struct ctlr_info *h,
 	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 (!(le16_to_cpu(map->flags) & RAID_MAP_FLAG_ENCRYPT_ON))
 		return;
@@ -3688,8 +3686,6 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h,
 #endif
 	int offload_to_mirror;
 
-	BUG_ON(!(dev->offload_config && dev->offload_enabled));
-
 	/* check for valid opcode, get LBA and block count */
 	switch (cmd->cmnd[0]) {
 	case WRITE_6:


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 35/48] hpsa: do not ack controller events on controllers that do not support it
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (33 preceding siblings ...)
  2015-01-23 22:44 ` [PATCH v2 34/48] hpsa: remove incorrect BUG_ONs checking for raid offload enable Don Brace
@ 2015-01-23 22:44 ` Don Brace
  2015-01-23 22:44 ` [PATCH v2 36/48] hpsa: guard against overflowing raid map array Don Brace
                   ` (12 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:44 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Stephen Cameron <stephenmcameron@gmail.com>

Acking controller events on controllers that do not support
it can cause such controllers to lock up.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Joe Handzik <joseph.t.handzik@hp.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 5abd49d..afd192d 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -6674,6 +6674,9 @@ static void hpsa_ack_ctlr_events(struct ctlr_info *h)
 	int i;
 	char *event_type;
 
+	if (!(h->fw_support & MISC_FW_EVENT_NOTIFY))
+		return;
+
 	/* Ask the controller to clear the events we're handling. */
 	if ((h->transMethod & (CFGTBL_Trans_io_accel1
 			| CFGTBL_Trans_io_accel2)) &&


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 36/48] hpsa: guard against overflowing raid map array
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (34 preceding siblings ...)
  2015-01-23 22:44 ` [PATCH v2 35/48] hpsa: do not ack controller events on controllers that do not support it Don Brace
@ 2015-01-23 22:44 ` Don Brace
  2015-01-23 22:44 ` [PATCH v2 37/48] hpsa: check for ctlr lockup after command allocation in main io path Don Brace
                   ` (11 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:44 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Stephen Cameron <stephenmcameron@gmail.com>

In the code that translates logical drive LBAs to physical
drive LBAs if we overflow the raid map disk data array we
will get the wrong answers.  We do not expect that to happen,
but best to be on the safe side and guard against it anyway.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index afd192d..03fae8a 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -3921,6 +3921,9 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h,
 		return IO_ACCEL_INELIGIBLE;
 	}
 
+	if (unlikely(map_index >= RAID_MAP_MAX_ENTRIES))
+		return IO_ACCEL_INELIGIBLE;
+
 	c->phys_disk = dev->phys_disk[map_index];
 
 	disk_handle = dd[map_index].ioaccel_handle;


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 37/48] hpsa: check for ctlr lockup after command allocation in main io path
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (35 preceding siblings ...)
  2015-01-23 22:44 ` [PATCH v2 36/48] hpsa: guard against overflowing raid map array Don Brace
@ 2015-01-23 22:44 ` Don Brace
  2015-01-23 22:44 ` [PATCH v2 38/48] hpsa: return failed from device reset/abort handlers Don Brace
                   ` (10 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:44 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Stephen Cameron <stephenmcameron@gmail.com>

Command allocation is the thing that takes the longest in the main i/o
path, so check for controller lockup immediately after this to prevent
submitting commands to locked up controller as much as possible.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |    9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 03fae8a..834ac78 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -4097,8 +4097,15 @@ static int hpsa_scsi_queue_command(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
 		dev_err(&h->pdev->dev, "cmd_alloc returned NULL!\n");
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
+	if (unlikely(lockup_detected(h))) {
+		cmd->result = DID_ERROR << 16;
+		cmd_free(h, c);
+		cmd->scsi_done(cmd);
+		return 0;
+	}
 
-	/* Call alternate submit routine for I/O accelerated commands.
+	/*
+	 * Call alternate submit routine for I/O accelerated commands.
 	 * Retries always go down the normal I/O path.
 	 */
 	if (likely(cmd->retries == 0 &&


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 38/48] hpsa: return failed from device reset/abort handlers
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (36 preceding siblings ...)
  2015-01-23 22:44 ` [PATCH v2 37/48] hpsa: check for ctlr lockup after command allocation in main io path Don Brace
@ 2015-01-23 22:44 ` Don Brace
  2015-01-23 22:44 ` [PATCH v2 39/48] hpsa: do not use a void pointer for scsi_cmd field of struct CommandList Don Brace
                   ` (9 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:44 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

Returning failed from the device reset handler will get the device
kicked offline, which is fine if the controller is locked up anyhow.

Cannot abort a command from a failed controller.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Reviewed-by: Justin Lindley <justin.lindley@pmcs.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |    7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 834ac78..a02ea7f 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -4343,6 +4343,10 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd)
 	h = sdev_to_hba(scsicmd->device);
 	if (h == NULL) /* paranoia */
 		return FAILED;
+
+	if (lockup_detected(h))
+		return FAILED;
+
 	dev = scsicmd->device->hostdata;
 	if (!dev) {
 		dev_err(&h->pdev->dev, "hpsa_eh_device_reset_handler: "
@@ -4566,6 +4570,9 @@ static int hpsa_eh_abort_handler(struct scsi_cmnd *sc)
 			"ABORT REQUEST FAILED, Controller lookup failed.\n"))
 		return FAILED;
 
+	if (lockup_detected(h))
+		return FAILED;
+
 	/* Check that controller supports some kind of task abort */
 	if (!(HPSATMF_PHYS_TASK_ABORT & h->TMFSupportFlags) &&
 		!(HPSATMF_LOG_TASK_ABORT & h->TMFSupportFlags))


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 39/48] hpsa: do not use a void pointer for scsi_cmd field of struct CommandList
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (37 preceding siblings ...)
  2015-01-23 22:44 ` [PATCH v2 38/48] hpsa: return failed from device reset/abort handlers Don Brace
@ 2015-01-23 22:44 ` Don Brace
  2015-01-23 22:44 ` [PATCH v2 40/48] hpsa: print CDBs instead of kernel virtual addresses for uncommon errors Don Brace
                   ` (8 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:44 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Stephen Cameron <stephenmcameron@gmail.com>

There's no reason for it to be a void *, it should be a struct scsi_cmnd *

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c     |    6 +++---
 drivers/scsi/hpsa_cmd.h |    2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index a02ea7f..8f2569c 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -1764,7 +1764,7 @@ static void complete_scsi_command(struct CommandList *cp)
 	unsigned long sense_data_size;
 
 	ei = cp->err_info;
-	cmd = (struct scsi_cmnd *) cp->scsi_cmd;
+	cmd = cp->scsi_cmd;
 	h = cp->h;
 	dev = cmd->device->hostdata;
 
@@ -4466,7 +4466,7 @@ static int hpsa_send_reset_as_abort_ioaccel2(struct ctlr_info *h,
 	unsigned char *psa = &phys_scsi3addr[0];
 
 	/* Get a pointer to the hpsa logical device. */
-	scmd = (struct scsi_cmnd *) abort->scsi_cmd;
+	scmd = abort->scsi_cmd;
 	dev = (struct hpsa_scsi_dev_t *)(scmd->device->hostdata);
 	if (dev == NULL) {
 		dev_warn(&h->pdev->dev,
@@ -4604,7 +4604,7 @@ static int hpsa_eh_abort_handler(struct scsi_cmnd *sc)
 	}
 	hpsa_get_tag(h, abort, &taglower, &tagupper);
 	ml += sprintf(msg+ml, "Tag:0x%08x:%08x ", tagupper, taglower);
-	as  = (struct scsi_cmnd *) abort->scsi_cmd;
+	as  = abort->scsi_cmd;
 	if (as != NULL)
 		ml += sprintf(msg+ml, "Command:0x%x SN:0x%lx ",
 			as->cmnd[0], as->serial_number);
diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h
index 071b64c..3a621c7 100644
--- a/drivers/scsi/hpsa_cmd.h
+++ b/drivers/scsi/hpsa_cmd.h
@@ -408,7 +408,7 @@ struct CommandList {
 	int			   cmd_type;
 	long			   cmdindex;
 	struct completion *waiting;
-	void   *scsi_cmd;
+	struct scsi_cmnd *scsi_cmd;
 	struct work_struct work;
 
 	/*


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 40/48] hpsa: print CDBs instead of kernel virtual addresses for uncommon errors
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (38 preceding siblings ...)
  2015-01-23 22:44 ` [PATCH v2 39/48] hpsa: do not use a void pointer for scsi_cmd field of struct CommandList Don Brace
@ 2015-01-23 22:44 ` Don Brace
  2015-01-23 22:44 ` [PATCH v2 41/48] hpsa: do not use function pointers in fast path command submission Don Brace
                   ` (7 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:44 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Stephen Cameron <stephenmcameron@gmail.com>

Printing the address of the command pointer is of little value, change
to print the CDB.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |   29 ++++++++++++++++-------------
 1 file changed, 16 insertions(+), 13 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 8f2569c..18bcba9 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -1882,9 +1882,8 @@ static void complete_scsi_command(struct CommandList *cp)
 	case CMD_DATA_UNDERRUN: /* let mid layer handle it. */
 		break;
 	case CMD_DATA_OVERRUN:
-		dev_warn(&h->pdev->dev, "cp %p has"
-			" completed with data overrun "
-			"reported\n", cp);
+		dev_warn(&h->pdev->dev,
+			"CDB %16phN data overrun\n", cp->Request.CDB);
 		break;
 	case CMD_INVALID: {
 		/* print_bytes(cp, sizeof(*cp), 1, 0);
@@ -1900,34 +1899,38 @@ static void complete_scsi_command(struct CommandList *cp)
 		break;
 	case CMD_PROTOCOL_ERR:
 		cmd->result = DID_ERROR << 16;
-		dev_warn(&h->pdev->dev, "cp %p has "
-			"protocol error\n", cp);
+		dev_warn(&h->pdev->dev, "CDB %16phN : protocol error\n",
+				cp->Request.CDB);
 		break;
 	case CMD_HARDWARE_ERR:
 		cmd->result = DID_ERROR << 16;
-		dev_warn(&h->pdev->dev, "cp %p had  hardware error\n", cp);
+		dev_warn(&h->pdev->dev, "CDB %16phN : hardware error\n",
+			cp->Request.CDB);
 		break;
 	case CMD_CONNECTION_LOST:
 		cmd->result = DID_ERROR << 16;
-		dev_warn(&h->pdev->dev, "cp %p had connection lost\n", cp);
+		dev_warn(&h->pdev->dev, "CDB %16phN : connection lost\n",
+			cp->Request.CDB);
 		break;
 	case CMD_ABORTED:
 		cmd->result = DID_ABORT << 16;
-		dev_warn(&h->pdev->dev, "cp %p was aborted with status 0x%x\n",
-				cp, ei->ScsiStatus);
+		dev_warn(&h->pdev->dev, "CDB %16phN was aborted with status 0x%x\n",
+				cp->Request.CDB, ei->ScsiStatus);
 		break;
 	case CMD_ABORT_FAILED:
 		cmd->result = DID_ERROR << 16;
-		dev_warn(&h->pdev->dev, "cp %p reports abort failed\n", cp);
+		dev_warn(&h->pdev->dev, "CDB %16phN : abort failed\n",
+			cp->Request.CDB);
 		break;
 	case CMD_UNSOLICITED_ABORT:
 		cmd->result = DID_SOFT_ERROR << 16; /* retry the command */
-		dev_warn(&h->pdev->dev, "cp %p aborted due to an unsolicited "
-			"abort\n", cp);
+		dev_warn(&h->pdev->dev, "CDB %16phN : unsolicited abort\n",
+			cp->Request.CDB);
 		break;
 	case CMD_TIMEOUT:
 		cmd->result = DID_TIME_OUT << 16;
-		dev_warn(&h->pdev->dev, "cp %p timedout\n", cp);
+		dev_warn(&h->pdev->dev, "CDB %16phN timed out\n",
+			cp->Request.CDB);
 		break;
 	case CMD_UNABORTABLE:
 		cmd->result = DID_ERROR << 16;


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 41/48] hpsa: do not use function pointers in fast path command submission
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (39 preceding siblings ...)
  2015-01-23 22:44 ` [PATCH v2 40/48] hpsa: print CDBs instead of kernel virtual addresses for uncommon errors Don Brace
@ 2015-01-23 22:44 ` Don Brace
  2015-01-23 22:44 ` [PATCH v2 42/48] hpsa: move SG descriptor set-up out of hpsa_scatter_gather() Don Brace
                   ` (6 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:44 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Stephen Cameron <stephenmcameron@gmail.com>

Performance tweak, avoid unnecessary function calls.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |    8 +++++---
 drivers/scsi/hpsa.h |    5 +----
 2 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 18bcba9..a23277d 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -821,19 +821,21 @@ static void dial_up_lockup_detection_on_fw_flash_complete(struct ctlr_info *h,
 static void enqueue_cmd_and_start_io(struct ctlr_info *h,
 	struct CommandList *c)
 {
+	dial_down_lockup_detection_during_fw_flash(h, c);
+	atomic_inc(&h->commands_outstanding);
 	switch (c->cmd_type) {
 	case CMD_IOACCEL1:
 		set_ioaccel1_performant_mode(h, c);
+		writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET);
 		break;
 	case CMD_IOACCEL2:
 		set_ioaccel2_performant_mode(h, c);
+		writel(c->busaddr, h->vaddr + IOACCEL2_INBOUND_POSTQ_32);
 		break;
 	default:
 		set_performant_mode(h, c);
+		h->access.submit_command(h, c);
 	}
-	dial_down_lockup_detection_during_fw_flash(h, c);
-	atomic_inc(&h->commands_outstanding);
-	h->access.submit_command(h, c);
 }
 
 static inline int is_hba_lunid(unsigned char scsi3addr[])
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index 239ecea..62c50c3 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -367,10 +367,7 @@ static void SA5_submit_command_no_read(struct ctlr_info *h,
 static void SA5_submit_command_ioaccel2(struct ctlr_info *h,
 	struct CommandList *c)
 {
-	if (c->cmd_type == CMD_IOACCEL2)
-		writel(c->busaddr, h->vaddr + IOACCEL2_INBOUND_POSTQ_32);
-	else
-		writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET);
+	writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET);
 }
 
 /*


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 42/48] hpsa: move SG descriptor set-up out of hpsa_scatter_gather()
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (40 preceding siblings ...)
  2015-01-23 22:44 ` [PATCH v2 41/48] hpsa: do not use function pointers in fast path command submission Don Brace
@ 2015-01-23 22:44 ` Don Brace
  2015-01-23 22:44 ` [PATCH v2 43/48] hpsa: refactor duplicated scan completion code into a new routine Don Brace
                   ` (5 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:44 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Webb Scales <webbnh@hp.com>

Move the code which sets up the SG descriptor out of hpsa_scatter_gather()
and into a subroutine where it can be reused (in the next patch).  The Ext
field is now assigned unconditionally: this makes the refactor much simpler,
but more importantly it removes a conditional operation from inside the
loop.  The case for which the conditional formerly tested is now executed
(unconditionally) after the loop is exited.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Webb Scales <webbnh@hp.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |   21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index a23277d..7915dc4 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -3236,6 +3236,17 @@ out:
 	kfree(id_phys);
 }
 
+static void hpsa_set_sg_descriptor(struct SGDescriptor *desc,
+				   struct scatterlist *sg)
+{
+	u64 addr64 = (u64) sg_dma_address(sg);
+	unsigned int len = sg_dma_len(sg);
+
+	desc->Addr = cpu_to_le64(addr64);
+	desc->Len = cpu_to_le32(len);
+	desc->Ext = 0;
+}
+
 /*
  * hpsa_scatter_gather takes a struct scsi_cmnd, (cmd), and does the pci
  * dma mapping  and fills in the scatter gather entries of the
@@ -3245,9 +3256,7 @@ static int hpsa_scatter_gather(struct ctlr_info *h,
 		struct CommandList *cp,
 		struct scsi_cmnd *cmd)
 {
-	unsigned int len;
 	struct scatterlist *sg;
-	u64 addr64;
 	int use_sg, i, sg_index, chained;
 	struct SGDescriptor *curr_sg;
 
@@ -3270,13 +3279,11 @@ static int hpsa_scatter_gather(struct ctlr_info *h,
 			curr_sg = h->cmd_sg_list[cp->cmdindex];
 			sg_index = 0;
 		}
-		addr64 = (u64) sg_dma_address(sg);
-		len  = sg_dma_len(sg);
-		curr_sg->Addr = cpu_to_le64(addr64);
-		curr_sg->Len = cpu_to_le32(len);
-		curr_sg->Ext = cpu_to_le32(0);
+		hpsa_set_sg_descriptor(curr_sg, sg);
 		curr_sg++;
 	}
+
+	/* Back the pointer up to the last entry and mark it as "last". */
 	(--curr_sg)->Ext = cpu_to_le32(HPSA_SG_LAST);
 
 	if (use_sg + chained > h->maxSG)


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 43/48] hpsa: refactor duplicated scan completion code into a new routine
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (41 preceding siblings ...)
  2015-01-23 22:44 ` [PATCH v2 42/48] hpsa: move SG descriptor set-up out of hpsa_scatter_gather() Don Brace
@ 2015-01-23 22:44 ` Don Brace
  2015-01-23 22:44 ` [PATCH v2 44/48] hpsa: shorten the wait for the CISS doorbell mode change ack Don Brace
                   ` (4 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:44 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Webb Scales <webbnh@hp.com>

Hoist the conditional out of do_not_scan_if_controller_locked_up() and
place it in the caller (this improves the code structure, making it
more consistent with other uses and enabling tail-call optimization);
rename the function to hpsa_scan_complete(), and use it at the end of
hpsa_scan_start() as well.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Webb Scales <webbnh@hp.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |   40 ++++++++++++++++------------------------
 1 file changed, 16 insertions(+), 24 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 7915dc4..a92653a 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -4149,25 +4149,14 @@ static int hpsa_scsi_queue_command(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
 	return hpsa_ciss_submit(h, c, cmd, scsi3addr);
 }
 
-static int do_not_scan_if_controller_locked_up(struct ctlr_info *h)
+static void hpsa_scan_complete(struct ctlr_info *h)
 {
 	unsigned long flags;
 
-	/*
-	 * Don't let rescans be initiated on a controller known
-	 * to be locked up.  If the controller locks up *during*
-	 * a rescan, that thread is probably hosed, but at least
-	 * we can prevent new rescan threads from piling up on a
-	 * locked up controller.
-	 */
-	if (unlikely(lockup_detected(h))) {
-		spin_lock_irqsave(&h->scan_lock, flags);
-		h->scan_finished = 1;
-		wake_up_all(&h->scan_wait_queue);
-		spin_unlock_irqrestore(&h->scan_lock, flags);
-		return 1;
-	}
-	return 0;
+	spin_lock_irqsave(&h->scan_lock, flags);
+	h->scan_finished = 1;
+	wake_up_all(&h->scan_wait_queue);
+	spin_unlock_irqrestore(&h->scan_lock, flags);
 }
 
 static void hpsa_scan_start(struct Scsi_Host *sh)
@@ -4175,8 +4164,14 @@ static void hpsa_scan_start(struct Scsi_Host *sh)
 	struct ctlr_info *h = shost_to_hba(sh);
 	unsigned long flags;
 
-	if (do_not_scan_if_controller_locked_up(h))
-		return;
+	/*
+	 * Don't let rescans be initiated on a controller known to be locked
+	 * up.  If the controller locks up *during* a rescan, that thread is
+	 * probably hosed, but at least we can prevent new rescan threads from
+	 * piling up on a locked up controller.
+	 */
+	if (unlikely(lockup_detected(h)))
+		return hpsa_scan_complete(h);
 
 	/* wait until any scan already in progress is finished. */
 	while (1) {
@@ -4194,15 +4189,12 @@ static void hpsa_scan_start(struct Scsi_Host *sh)
 	h->scan_finished = 0; /* mark scan as in progress */
 	spin_unlock_irqrestore(&h->scan_lock, flags);
 
-	if (do_not_scan_if_controller_locked_up(h))
-		return;
+	if (unlikely(lockup_detected(h)))
+		return hpsa_scan_complete(h);
 
 	hpsa_update_scsi_devices(h, h->scsi_host->host_no);
 
-	spin_lock_irqsave(&h->scan_lock, flags);
-	h->scan_finished = 1; /* mark scan as finished. */
-	wake_up_all(&h->scan_wait_queue);
-	spin_unlock_irqrestore(&h->scan_lock, flags);
+	hpsa_scan_complete(h);
 }
 
 static int hpsa_change_queue_depth(struct scsi_device *sdev, int qdepth)


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 44/48] hpsa: shorten the wait for the CISS doorbell mode change ack
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (42 preceding siblings ...)
  2015-01-23 22:44 ` [PATCH v2 43/48] hpsa: refactor duplicated scan completion code into a new routine Don Brace
@ 2015-01-23 22:44 ` Don Brace
  2015-01-23 22:45 ` [PATCH v2 45/48] hpsa: detect and report failures changing controller transport modes Don Brace
                   ` (3 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:44 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Robert Elliott <elliott@hp.com>

Shorten the wait for the CISS configuration table doorbell mode
change acknowledgment from 300-600 s to 20 s, which is the value
specified in the CISS specification that should be honored by
all controllers.

Wait using interruptible msleep() rather than uninterruptible
usleep_range(), which triggers rt_sched timeout errors if the
wait is long.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Robert Elliott <elliott@hp.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |   15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index a92653a..89744a1 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -60,8 +60,11 @@
 #define DRIVER_NAME "HP HPSA Driver (v " HPSA_DRIVER_VERSION ")"
 #define HPSA "hpsa"
 
-/* How long to wait (in milliseconds) for board to go into simple mode */
-#define MAX_CONFIG_WAIT 30000
+/* How long to wait for CISS doorbell communication */
+#define CLEAR_EVENT_WAIT_INTERVAL 20	/* ms for each msleep() call */
+#define MODE_CHANGE_WAIT_INTERVAL 10	/* ms for each msleep() call */
+#define MAX_CLEAR_EVENT_WAIT 30000	/* times 20 ms = 600 s */
+#define MAX_MODE_CHANGE_WAIT 2000	/* times 10 ms = 20 s */
 #define MAX_IOCTL_CONFIG_WAIT 1000
 
 /*define how many times we will try a command because of bus resets */
@@ -6194,14 +6197,14 @@ static void hpsa_wait_for_clear_event_notify_ack(struct ctlr_info *h)
 	u32 doorbell_value;
 	unsigned long flags;
 	/* wait until the clear_event_notify bit 6 is cleared by controller. */
-	for (i = 0; i < MAX_CONFIG_WAIT; i++) {
+	for (i = 0; i < MAX_CLEAR_EVENT_WAIT; i++) {
 		spin_lock_irqsave(&h->lock, flags);
 		doorbell_value = readl(h->vaddr + SA5_DOORBELL);
 		spin_unlock_irqrestore(&h->lock, flags);
 		if (!(doorbell_value & DOORBELL_CLEAR_EVENTS))
 			break;
 		/* delay and try again */
-		msleep(20);
+		msleep(CLEAR_EVENT_WAIT_INTERVAL);
 	}
 }
 
@@ -6215,14 +6218,14 @@ static void hpsa_wait_for_mode_change_ack(struct ctlr_info *h)
 	 * (e.g.: hot replace a failed 144GB drive in a RAID 5 set right
 	 * as we enter this code.)
 	 */
-	for (i = 0; i < MAX_CONFIG_WAIT; i++) {
+	for (i = 0; i < MAX_MODE_CHANGE_WAIT; i++) {
 		spin_lock_irqsave(&h->lock, flags);
 		doorbell_value = readl(h->vaddr + SA5_DOORBELL);
 		spin_unlock_irqrestore(&h->lock, flags);
 		if (!(doorbell_value & CFGTBL_ChangeReq))
 			break;
 		/* delay and try again */
-		usleep_range(10000, 20000);
+		msleep(MODE_CHANGE_WAIT_INTERVAL);
 	}
 }
 


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 45/48] hpsa: detect and report failures changing controller transport modes
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (43 preceding siblings ...)
  2015-01-23 22:44 ` [PATCH v2 44/48] hpsa: shorten the wait for the CISS doorbell mode change ack Don Brace
@ 2015-01-23 22:45 ` Don Brace
  2015-01-23 22:45 ` [PATCH v2 46/48] hpsa: add in gen9 controller model names Don Brace
                   ` (2 subsequent siblings)
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:45 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

From: Robert Elliott <elliott@hp.com>

Detect failues when attempting to change controller to use simple
or performant transport modes (mode change ack) rather than just
proceeding ahead after timeouts.

Return values are added to:
	hpsa_put_ctlr_into_performant_mode
	hpsa_wait_for_mode_change_ack
and all their callers check/propagate the result.

More consistency in printing errors and whether
dev_err is used.

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Robert Elliott <elliott@hp.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |   40 +++++++++++++++++++++++++++++-----------
 1 file changed, 29 insertions(+), 11 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 89744a1..c1f4a95 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -243,7 +243,7 @@ static int hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id);
 static int hpsa_wait_for_board_state(struct pci_dev *pdev, void __iomem *vaddr,
 				     int wait_for_ready);
 static inline void finish_cmd(struct CommandList *c);
-static void hpsa_wait_for_mode_change_ack(struct ctlr_info *h);
+static int hpsa_wait_for_mode_change_ack(struct ctlr_info *h);
 #define BOARD_NOT_READY 0
 #define BOARD_READY 1
 static void hpsa_drain_accel_commands(struct ctlr_info *h);
@@ -6191,7 +6191,7 @@ static inline void hpsa_p600_dma_prefetch_quirk(struct ctlr_info *h)
 	writel(dma_prefetch, h->vaddr + I2O_DMA1_CFG);
 }
 
-static void hpsa_wait_for_clear_event_notify_ack(struct ctlr_info *h)
+static int hpsa_wait_for_clear_event_notify_ack(struct ctlr_info *h)
 {
 	int i;
 	u32 doorbell_value;
@@ -6202,13 +6202,16 @@ static void hpsa_wait_for_clear_event_notify_ack(struct ctlr_info *h)
 		doorbell_value = readl(h->vaddr + SA5_DOORBELL);
 		spin_unlock_irqrestore(&h->lock, flags);
 		if (!(doorbell_value & DOORBELL_CLEAR_EVENTS))
-			break;
+			goto done;
 		/* delay and try again */
 		msleep(CLEAR_EVENT_WAIT_INTERVAL);
 	}
+	return -ENODEV;
+done:
+	return 0;
 }
 
-static void hpsa_wait_for_mode_change_ack(struct ctlr_info *h)
+static int hpsa_wait_for_mode_change_ack(struct ctlr_info *h)
 {
 	int i;
 	u32 doorbell_value;
@@ -6223,12 +6226,16 @@ static void hpsa_wait_for_mode_change_ack(struct ctlr_info *h)
 		doorbell_value = readl(h->vaddr + SA5_DOORBELL);
 		spin_unlock_irqrestore(&h->lock, flags);
 		if (!(doorbell_value & CFGTBL_ChangeReq))
-			break;
+			goto done;
 		/* delay and try again */
 		msleep(MODE_CHANGE_WAIT_INTERVAL);
 	}
+	return -ENODEV;
+done:
+	return 0;
 }
 
+/* return -ENODEV or other reason on error, 0 on success */
 static int hpsa_enter_simple_mode(struct ctlr_info *h)
 {
 	u32 trans_support;
@@ -6243,7 +6250,8 @@ static int hpsa_enter_simple_mode(struct ctlr_info *h)
 	writel(CFGTBL_Trans_Simple, &(h->cfgtable->HostWrite.TransportRequest));
 	writel(0, &h->cfgtable->HostWrite.command_pool_addr_hi);
 	writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
-	hpsa_wait_for_mode_change_ack(h);
+	if (hpsa_wait_for_mode_change_ack(h))
+		goto error;
 	print_cfg_table(&h->pdev->dev, h->cfgtable);
 	if (!(readl(&(h->cfgtable->TransportActive)) & CFGTBL_Trans_Simple))
 		goto error;
@@ -7144,7 +7152,8 @@ static void  calc_bucket_map(int bucket[], int num_buckets,
 	}
 }
 
-static void hpsa_enter_performant_mode(struct ctlr_info *h, u32 trans_support)
+/* return -ENODEV or other reason on error, 0 on success */
+static int hpsa_enter_performant_mode(struct ctlr_info *h, u32 trans_support)
 {
 	int i;
 	unsigned long register_value;
@@ -7236,12 +7245,16 @@ static void hpsa_enter_performant_mode(struct ctlr_info *h, u32 trans_support)
 		}
 	}
 	writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
-	hpsa_wait_for_mode_change_ack(h);
+	if (hpsa_wait_for_mode_change_ack(h)) {
+		dev_err(&h->pdev->dev,
+			"performant mode problem - doorbell timeout\n");
+		return -ENODEV;
+	}
 	register_value = readl(&(h->cfgtable->TransportActive));
 	if (!(register_value & CFGTBL_Trans_Performant)) {
 		dev_err(&h->pdev->dev,
 			"performant mode problem - transport not active\n");
-		return;
+		return -ENODEV;
 	}
 	/* Change the access methods to the performant access methods */
 	h->access = access;
@@ -7249,7 +7262,7 @@ static void hpsa_enter_performant_mode(struct ctlr_info *h, u32 trans_support)
 
 	if (!((trans_support & CFGTBL_Trans_io_accel1) ||
 		(trans_support & CFGTBL_Trans_io_accel2)))
-		return;
+		return 0;
 
 	if (trans_support & CFGTBL_Trans_io_accel1) {
 		/* Set up I/O accelerator mode */
@@ -7313,7 +7326,12 @@ static void hpsa_enter_performant_mode(struct ctlr_info *h, u32 trans_support)
 			writel(bft2[i], &h->ioaccel2_bft2_regs[i]);
 	}
 	writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
-	hpsa_wait_for_mode_change_ack(h);
+	if (hpsa_wait_for_mode_change_ack(h)) {
+		dev_err(&h->pdev->dev,
+			"performant mode problem - enabling ioaccel mode\n");
+		return -ENODEV;
+	}
+	return 0;
 }
 
 static int hpsa_alloc_ioaccel_cmd_and_bft(struct ctlr_info *h)


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 46/48] hpsa: add in gen9 controller model names
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (44 preceding siblings ...)
  2015-01-23 22:45 ` [PATCH v2 45/48] hpsa: detect and report failures changing controller transport modes Don Brace
@ 2015-01-23 22:45 ` Don Brace
  2015-01-23 22:45 ` [PATCH v2 47/48] hpsa: add in P840ar controller model name Don Brace
  2015-01-23 22:45 ` [PATCH v2 48/48] hpsa: Use local workqueues instead of system workqueues Don Brace
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:45 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

Add in gen9 controller model names

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |   26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index c1f4a95..6568da5 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -168,24 +168,24 @@ static struct board_type products[] = {
 	{0x1926103C, "Smart Array P731m", &SA5_access},
 	{0x1928103C, "Smart Array P230i", &SA5_access},
 	{0x1929103C, "Smart Array P530", &SA5_access},
-	{0x21BD103C, "Smart Array", &SA5_access},
-	{0x21BE103C, "Smart Array", &SA5_access},
-	{0x21BF103C, "Smart Array", &SA5_access},
-	{0x21C0103C, "Smart Array", &SA5_access},
+	{0x21BD103C, "Smart Array P244br", &SA5_access},
+	{0x21BE103C, "Smart Array P741m", &SA5_access},
+	{0x21BF103C, "Smart HBA H240ar", &SA5_access},
+	{0x21C0103C, "Smart Array P440ar", &SA5_access},
 	{0x21C1103C, "Smart Array", &SA5_access},
-	{0x21C2103C, "Smart Array", &SA5_access},
-	{0x21C3103C, "Smart Array", &SA5_access},
+	{0x21C2103C, "Smart Array P440", &SA5_access},
+	{0x21C3103C, "Smart Array P441", &SA5_access},
 	{0x21C4103C, "Smart Array", &SA5_access},
-	{0x21C5103C, "Smart Array", &SA5_access},
-	{0x21C6103C, "Smart Array", &SA5_access},
-	{0x21C7103C, "Smart Array", &SA5_access},
-	{0x21C8103C, "Smart Array", &SA5_access},
+	{0x21C5103C, "Smart Array P841", &SA5_access},
+	{0x21C6103C, "Smart HBA H244br", &SA5_access},
+	{0x21C7103C, "Smart HBA H240", &SA5_access},
+	{0x21C8103C, "Smart HBA H241", &SA5_access},
 	{0x21C9103C, "Smart Array", &SA5_access},
-	{0x21CA103C, "Smart Array", &SA5_access},
-	{0x21CB103C, "Smart Array", &SA5_access},
+	{0x21CA103C, "Smart Array P246br", &SA5_access},
+	{0x21CB103C, "Smart Array P840", &SA5_access},
 	{0x21CC103C, "Smart Array", &SA5_access},
 	{0x21CD103C, "Smart Array", &SA5_access},
-	{0x21CE103C, "Smart Array", &SA5_access},
+	{0x21CE103C, "Smart HBA", &SA5_access},
 	{0x00761590, "HP Storage P1224 Array Controller", &SA5_access},
 	{0x00871590, "HP Storage P1224e Array Controller", &SA5_access},
 	{0x007D1590, "HP Storage P1228 Array Controller", &SA5_access},


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 47/48] hpsa: add in P840ar controller model name
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (45 preceding siblings ...)
  2015-01-23 22:45 ` [PATCH v2 46/48] hpsa: add in gen9 controller model names Don Brace
@ 2015-01-23 22:45 ` Don Brace
  2015-01-23 22:45 ` [PATCH v2 48/48] hpsa: Use local workqueues instead of system workqueues Don Brace
  47 siblings, 0 replies; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:45 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

Add in P840ar model name for gen9

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 6568da5..15ef65c 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -172,7 +172,7 @@ static struct board_type products[] = {
 	{0x21BE103C, "Smart Array P741m", &SA5_access},
 	{0x21BF103C, "Smart HBA H240ar", &SA5_access},
 	{0x21C0103C, "Smart Array P440ar", &SA5_access},
-	{0x21C1103C, "Smart Array", &SA5_access},
+	{0x21C1103C, "Smart Array P840ar", &SA5_access},
 	{0x21C2103C, "Smart Array P440", &SA5_access},
 	{0x21C3103C, "Smart Array P441", &SA5_access},
 	{0x21C4103C, "Smart Array", &SA5_access},


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 48/48] hpsa: Use local workqueues instead of system workqueues
  2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
                   ` (46 preceding siblings ...)
  2015-01-23 22:45 ` [PATCH v2 47/48] hpsa: add in P840ar controller model name Don Brace
@ 2015-01-23 22:45 ` Don Brace
  2015-01-27 16:55   ` Tomas Henzl
  47 siblings, 1 reply; 51+ messages in thread
From: Don Brace @ 2015-01-23 22:45 UTC (permalink / raw)
  To: scott.teel, Kevin.Barnett, james.bottomley, hch, Justin.Lindley, brace
  Cc: linux-scsi

Suggested-by: Tomas Henzl <thenzl@redhat.com>
Reviewed-by: Webb Scales <webbnh@hp.com>
Reviewed-by: Kevin Barnett <Kevin.Barnett@pmcs.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
---
 drivers/scsi/hpsa.c |   68 +++++++++++++++++++++++++++++++++++++++++----------
 drivers/scsi/hpsa.h |    2 ++
 2 files changed, 56 insertions(+), 14 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 15ef65c..95d581c 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -6787,14 +6787,14 @@ static int hpsa_offline_devices_ready(struct ctlr_info *h)
 	return 0;
 }
 
-
-static void hpsa_monitor_ctlr_worker(struct work_struct *work)
+static void hpsa_rescan_ctlr_worker(struct work_struct *work)
 {
 	unsigned long flags;
 	struct ctlr_info *h = container_of(to_delayed_work(work),
-					struct ctlr_info, monitor_ctlr_work);
-	detect_controller_lockup(h);
-	if (lockup_detected(h))
+					struct ctlr_info, rescan_ctlr_work);
+
+
+	if (h->remove_in_progress)
 		return;
 
 	if (hpsa_ctlr_needs_rescan(h) || hpsa_offline_devices_ready(h)) {
@@ -6803,17 +6803,44 @@ static void hpsa_monitor_ctlr_worker(struct work_struct *work)
 		hpsa_scan_start(h->scsi_host);
 		scsi_host_put(h->scsi_host);
 	}
-
 	spin_lock_irqsave(&h->lock, flags);
-	if (h->remove_in_progress) {
-		spin_unlock_irqrestore(&h->lock, flags);
+	if (!h->remove_in_progress)
+		queue_delayed_work(h->rescan_ctlr_wq, &h->rescan_ctlr_work,
+				h->heartbeat_sample_interval);
+	spin_unlock_irqrestore(&h->lock, flags);
+}
+
+static void hpsa_monitor_ctlr_worker(struct work_struct *work)
+{
+	unsigned long flags;
+	struct ctlr_info *h = container_of(to_delayed_work(work),
+					struct ctlr_info, monitor_ctlr_work);
+
+	detect_controller_lockup(h);
+	if (lockup_detected(h))
 		return;
-	}
-	schedule_delayed_work(&h->monitor_ctlr_work,
+
+	spin_lock_irqsave(&h->lock, flags);
+	if (!h->remove_in_progress)
+		schedule_delayed_work(&h->monitor_ctlr_work,
 				h->heartbeat_sample_interval);
 	spin_unlock_irqrestore(&h->lock, flags);
 }
 
+static struct workqueue_struct *hpsa_create_controller_wq(struct ctlr_info *h,
+						char *name)
+{
+	struct workqueue_struct *wq = NULL;
+	char wq_name[20];
+
+	snprintf(wq_name, sizeof(wq_name), "%s_%d_hpsa", name, h->ctlr);
+	wq = alloc_ordered_workqueue(wq_name, 0);
+	if (!wq)
+		dev_err(&h->pdev->dev, "failed to create %s workqueue\n", name);
+
+	return wq;
+}
+
 static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	int dac, rc;
@@ -6856,12 +6883,18 @@ reinit_after_soft_reset:
 	spin_lock_init(&h->scan_lock);
 	atomic_set(&h->passthru_cmds_avail, HPSA_MAX_CONCURRENT_PASSTHRUS);
 
-	h->resubmit_wq = alloc_workqueue("hpsa", WQ_MEM_RECLAIM, 0);
+	h->rescan_ctlr_wq = hpsa_create_controller_wq(h, "rescan");
+	if (!h->rescan_ctlr_wq) {
+		rc = -ENOMEM;
+		goto clean1;
+	}
+
+	h->resubmit_wq = hpsa_create_controller_wq(h, "resubmit");
 	if (!h->resubmit_wq) {
-		dev_err(&h->pdev->dev, "Failed to allocate work queue\n");
 		rc = -ENOMEM;
 		goto clean1;
 	}
+
 	/* Allocate and clear per-cpu variable lockup_detected */
 	h->lockup_detected = alloc_percpu(u32);
 	if (!h->lockup_detected) {
@@ -6985,6 +7018,9 @@ reinit_after_soft_reset:
 	INIT_DELAYED_WORK(&h->monitor_ctlr_work, hpsa_monitor_ctlr_worker);
 	schedule_delayed_work(&h->monitor_ctlr_work,
 				h->heartbeat_sample_interval);
+	INIT_DELAYED_WORK(&h->rescan_ctlr_work, hpsa_rescan_ctlr_worker);
+	queue_delayed_work(h->rescan_ctlr_wq, &h->rescan_ctlr_work,
+				h->heartbeat_sample_interval);
 	return 0;
 
 clean4:
@@ -6996,6 +7032,8 @@ clean2:
 clean1:
 	if (h->resubmit_wq)
 		destroy_workqueue(h->resubmit_wq);
+	if (h->rescan_ctlr_wq)
+		destroy_workqueue(h->rescan_ctlr_wq);
 	if (h->lockup_detected)
 		free_percpu(h->lockup_detected);
 	kfree(h);
@@ -7069,11 +7107,13 @@ static void hpsa_remove_one(struct pci_dev *pdev)
 	/* Get rid of any controller monitoring work items */
 	spin_lock_irqsave(&h->lock, flags);
 	h->remove_in_progress = 1;
-	cancel_delayed_work(&h->monitor_ctlr_work);
 	spin_unlock_irqrestore(&h->lock, flags);
+	cancel_delayed_work_sync(&h->monitor_ctlr_work);
+	cancel_delayed_work_sync(&h->rescan_ctlr_work);
+	destroy_workqueue(h->rescan_ctlr_wq);
+	destroy_workqueue(h->resubmit_wq);
 	hpsa_unregister_scsi(h);	/* unhook from SCSI subsystem */
 	hpsa_shutdown(pdev);
-	destroy_workqueue(h->resubmit_wq);
 	iounmap(h->vaddr);
 	iounmap(h->transtable);
 	iounmap(h->cfgtable);
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index 62c50c3..6577130 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -207,6 +207,7 @@ struct ctlr_info {
 	atomic_t firmware_flash_in_progress;
 	u32 __percpu *lockup_detected;
 	struct delayed_work monitor_ctlr_work;
+	struct delayed_work rescan_ctlr_work;
 	int remove_in_progress;
 	/* Address of h->q[x] is passed to intr handler to know which queue */
 	u8 q[MAX_REPLY_QUEUES];
@@ -251,6 +252,7 @@ struct ctlr_info {
 	int	acciopath_status;
 	int	raid_offload_debug;
 	struct workqueue_struct *resubmit_wq;
+	struct workqueue_struct *rescan_ctlr_wq;
 };
 
 struct offline_device_entry {


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* Re: [PATCH v2 48/48] hpsa: Use local workqueues instead of system workqueues
  2015-01-23 22:45 ` [PATCH v2 48/48] hpsa: Use local workqueues instead of system workqueues Don Brace
@ 2015-01-27 16:55   ` Tomas Henzl
  2015-01-27 17:13     ` Tomas Henzl
  0 siblings, 1 reply; 51+ messages in thread
From: Tomas Henzl @ 2015-01-27 16:55 UTC (permalink / raw)
  To: Don Brace, scott.teel, Kevin.Barnett, james.bottomley, hch,
	Justin.Lindley
  Cc: linux-scsi

On 01/23/2015 11:45 PM, Don Brace wrote:
> Suggested-by: Tomas Henzl <thenzl@redhat.com>

Yes i have suggested something but it was something different
I wanted to move to his own workqueue the hpsa_monitor_ctlr_worker
and exactly that is what you have left out in this patch.

I'm going to post a patch on top of this series, please review.

Tomas

> Reviewed-by: Webb Scales <webbnh@hp.com>
> Reviewed-by: Kevin Barnett <Kevin.Barnett@pmcs.com>
> Signed-off-by: Don Brace <don.brace@pmcs.com>
> ---
>  drivers/scsi/hpsa.c |   68 +++++++++++++++++++++++++++++++++++++++++----------
>  drivers/scsi/hpsa.h |    2 ++
>  2 files changed, 56 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
> index 15ef65c..95d581c 100644
> --- a/drivers/scsi/hpsa.c
> +++ b/drivers/scsi/hpsa.c
> @@ -6787,14 +6787,14 @@ static int hpsa_offline_devices_ready(struct ctlr_info *h)
>  	return 0;
>  }
>  
> -
> -static void hpsa_monitor_ctlr_worker(struct work_struct *work)
> +static void hpsa_rescan_ctlr_worker(struct work_struct *work)
>  {
>  	unsigned long flags;
>  	struct ctlr_info *h = container_of(to_delayed_work(work),
> -					struct ctlr_info, monitor_ctlr_work);
> -	detect_controller_lockup(h);
> -	if (lockup_detected(h))
> +					struct ctlr_info, rescan_ctlr_work);
> +
> +
> +	if (h->remove_in_progress)
>  		return;
>  
>  	if (hpsa_ctlr_needs_rescan(h) || hpsa_offline_devices_ready(h)) {
> @@ -6803,17 +6803,44 @@ static void hpsa_monitor_ctlr_worker(struct work_struct *work)
>  		hpsa_scan_start(h->scsi_host);
>  		scsi_host_put(h->scsi_host);
>  	}
> -
>  	spin_lock_irqsave(&h->lock, flags);
> -	if (h->remove_in_progress) {
> -		spin_unlock_irqrestore(&h->lock, flags);
> +	if (!h->remove_in_progress)
> +		queue_delayed_work(h->rescan_ctlr_wq, &h->rescan_ctlr_work,
> +				h->heartbeat_sample_interval);
> +	spin_unlock_irqrestore(&h->lock, flags);
> +}
> +
> +static void hpsa_monitor_ctlr_worker(struct work_struct *work)
> +{
> +	unsigned long flags;
> +	struct ctlr_info *h = container_of(to_delayed_work(work),
> +					struct ctlr_info, monitor_ctlr_work);
> +
> +	detect_controller_lockup(h);
> +	if (lockup_detected(h))
>  		return;
> -	}
> -	schedule_delayed_work(&h->monitor_ctlr_work,
> +
> +	spin_lock_irqsave(&h->lock, flags);
> +	if (!h->remove_in_progress)
> +		schedule_delayed_work(&h->monitor_ctlr_work,
>  				h->heartbeat_sample_interval);
>  	spin_unlock_irqrestore(&h->lock, flags);
>  }
>  
> +static struct workqueue_struct *hpsa_create_controller_wq(struct ctlr_info *h,
> +						char *name)
> +{
> +	struct workqueue_struct *wq = NULL;
> +	char wq_name[20];
> +
> +	snprintf(wq_name, sizeof(wq_name), "%s_%d_hpsa", name, h->ctlr);
> +	wq = alloc_ordered_workqueue(wq_name, 0);
> +	if (!wq)
> +		dev_err(&h->pdev->dev, "failed to create %s workqueue\n", name);
> +
> +	return wq;
> +}
> +
>  static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
>  {
>  	int dac, rc;
> @@ -6856,12 +6883,18 @@ reinit_after_soft_reset:
>  	spin_lock_init(&h->scan_lock);
>  	atomic_set(&h->passthru_cmds_avail, HPSA_MAX_CONCURRENT_PASSTHRUS);
>  
> -	h->resubmit_wq = alloc_workqueue("hpsa", WQ_MEM_RECLAIM, 0);
> +	h->rescan_ctlr_wq = hpsa_create_controller_wq(h, "rescan");
> +	if (!h->rescan_ctlr_wq) {
> +		rc = -ENOMEM;
> +		goto clean1;
> +	}
> +
> +	h->resubmit_wq = hpsa_create_controller_wq(h, "resubmit");
>  	if (!h->resubmit_wq) {
> -		dev_err(&h->pdev->dev, "Failed to allocate work queue\n");
>  		rc = -ENOMEM;
>  		goto clean1;
>  	}
> +
>  	/* Allocate and clear per-cpu variable lockup_detected */
>  	h->lockup_detected = alloc_percpu(u32);
>  	if (!h->lockup_detected) {
> @@ -6985,6 +7018,9 @@ reinit_after_soft_reset:
>  	INIT_DELAYED_WORK(&h->monitor_ctlr_work, hpsa_monitor_ctlr_worker);
>  	schedule_delayed_work(&h->monitor_ctlr_work,
>  				h->heartbeat_sample_interval);
> +	INIT_DELAYED_WORK(&h->rescan_ctlr_work, hpsa_rescan_ctlr_worker);
> +	queue_delayed_work(h->rescan_ctlr_wq, &h->rescan_ctlr_work,
> +				h->heartbeat_sample_interval);
>  	return 0;
>  
>  clean4:
> @@ -6996,6 +7032,8 @@ clean2:
>  clean1:
>  	if (h->resubmit_wq)
>  		destroy_workqueue(h->resubmit_wq);
> +	if (h->rescan_ctlr_wq)
> +		destroy_workqueue(h->rescan_ctlr_wq);
>  	if (h->lockup_detected)
>  		free_percpu(h->lockup_detected);
>  	kfree(h);
> @@ -7069,11 +7107,13 @@ static void hpsa_remove_one(struct pci_dev *pdev)
>  	/* Get rid of any controller monitoring work items */
>  	spin_lock_irqsave(&h->lock, flags);
>  	h->remove_in_progress = 1;
> -	cancel_delayed_work(&h->monitor_ctlr_work);
>  	spin_unlock_irqrestore(&h->lock, flags);
> +	cancel_delayed_work_sync(&h->monitor_ctlr_work);
> +	cancel_delayed_work_sync(&h->rescan_ctlr_work);
> +	destroy_workqueue(h->rescan_ctlr_wq);
> +	destroy_workqueue(h->resubmit_wq);
>  	hpsa_unregister_scsi(h);	/* unhook from SCSI subsystem */
>  	hpsa_shutdown(pdev);
> -	destroy_workqueue(h->resubmit_wq);
>  	iounmap(h->vaddr);
>  	iounmap(h->transtable);
>  	iounmap(h->cfgtable);
> diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
> index 62c50c3..6577130 100644
> --- a/drivers/scsi/hpsa.h
> +++ b/drivers/scsi/hpsa.h
> @@ -207,6 +207,7 @@ struct ctlr_info {
>  	atomic_t firmware_flash_in_progress;
>  	u32 __percpu *lockup_detected;
>  	struct delayed_work monitor_ctlr_work;
> +	struct delayed_work rescan_ctlr_work;
>  	int remove_in_progress;
>  	/* Address of h->q[x] is passed to intr handler to know which queue */
>  	u8 q[MAX_REPLY_QUEUES];
> @@ -251,6 +252,7 @@ struct ctlr_info {
>  	int	acciopath_status;
>  	int	raid_offload_debug;
>  	struct workqueue_struct *resubmit_wq;
> +	struct workqueue_struct *rescan_ctlr_wq;
>  };
>  
>  struct offline_device_entry {
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2 48/48] hpsa: Use local workqueues instead of system workqueues
  2015-01-27 16:55   ` Tomas Henzl
@ 2015-01-27 17:13     ` Tomas Henzl
  0 siblings, 0 replies; 51+ messages in thread
From: Tomas Henzl @ 2015-01-27 17:13 UTC (permalink / raw)
  To: Don Brace, scott.teel, Kevin.Barnett, james.bottomley, hch,
	Justin.Lindley
  Cc: linux-scsi

On 01/27/2015 05:55 PM, Tomas Henzl wrote:
> On 01/23/2015 11:45 PM, Don Brace wrote:
>> Suggested-by: Tomas Henzl <thenzl@redhat.com>
> Yes i have suggested something but it was something different
> I wanted to move to his own workqueue the hpsa_monitor_ctlr_worker
> and exactly that is what you have left out in this patch.
>
> I'm going to post a patch on top of this series, please review.
>
> Tomas

I see it now, you have in this patch split the former hpsa_monitor_ctlr_worker
into two worker functions functions now run independently in two different
workqueues. In this case my already posted patch is not needed.
Tomas

>
>> Reviewed-by: Webb Scales <webbnh@hp.com>
>> Reviewed-by: Kevin Barnett <Kevin.Barnett@pmcs.com>
>> Signed-off-by: Don Brace <don.brace@pmcs.com>
>> ---
>>  drivers/scsi/hpsa.c |   68 +++++++++++++++++++++++++++++++++++++++++----------
>>  drivers/scsi/hpsa.h |    2 ++
>>  2 files changed, 56 insertions(+), 14 deletions(-)
>>
>> diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
>> index 15ef65c..95d581c 100644
>> --- a/drivers/scsi/hpsa.c
>> +++ b/drivers/scsi/hpsa.c
>> @@ -6787,14 +6787,14 @@ static int hpsa_offline_devices_ready(struct ctlr_info *h)
>>  	return 0;
>>  }
>>  
>> -
>> -static void hpsa_monitor_ctlr_worker(struct work_struct *work)
>> +static void hpsa_rescan_ctlr_worker(struct work_struct *work)
>>  {
>>  	unsigned long flags;
>>  	struct ctlr_info *h = container_of(to_delayed_work(work),
>> -					struct ctlr_info, monitor_ctlr_work);
>> -	detect_controller_lockup(h);
>> -	if (lockup_detected(h))
>> +					struct ctlr_info, rescan_ctlr_work);
>> +
>> +
>> +	if (h->remove_in_progress)
>>  		return;
>>  
>>  	if (hpsa_ctlr_needs_rescan(h) || hpsa_offline_devices_ready(h)) {
>> @@ -6803,17 +6803,44 @@ static void hpsa_monitor_ctlr_worker(struct work_struct *work)
>>  		hpsa_scan_start(h->scsi_host);
>>  		scsi_host_put(h->scsi_host);
>>  	}
>> -
>>  	spin_lock_irqsave(&h->lock, flags);
>> -	if (h->remove_in_progress) {
>> -		spin_unlock_irqrestore(&h->lock, flags);
>> +	if (!h->remove_in_progress)
>> +		queue_delayed_work(h->rescan_ctlr_wq, &h->rescan_ctlr_work,
>> +				h->heartbeat_sample_interval);
>> +	spin_unlock_irqrestore(&h->lock, flags);
>> +}
>> +
>> +static void hpsa_monitor_ctlr_worker(struct work_struct *work)
>> +{
>> +	unsigned long flags;
>> +	struct ctlr_info *h = container_of(to_delayed_work(work),
>> +					struct ctlr_info, monitor_ctlr_work);
>> +
>> +	detect_controller_lockup(h);
>> +	if (lockup_detected(h))
>>  		return;
>> -	}
>> -	schedule_delayed_work(&h->monitor_ctlr_work,
>> +
>> +	spin_lock_irqsave(&h->lock, flags);
>> +	if (!h->remove_in_progress)
>> +		schedule_delayed_work(&h->monitor_ctlr_work,
>>  				h->heartbeat_sample_interval);
>>  	spin_unlock_irqrestore(&h->lock, flags);
>>  }
>>  
>> +static struct workqueue_struct *hpsa_create_controller_wq(struct ctlr_info *h,
>> +						char *name)
>> +{
>> +	struct workqueue_struct *wq = NULL;
>> +	char wq_name[20];
>> +
>> +	snprintf(wq_name, sizeof(wq_name), "%s_%d_hpsa", name, h->ctlr);
>> +	wq = alloc_ordered_workqueue(wq_name, 0);
>> +	if (!wq)
>> +		dev_err(&h->pdev->dev, "failed to create %s workqueue\n", name);
>> +
>> +	return wq;
>> +}
>> +
>>  static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
>>  {
>>  	int dac, rc;
>> @@ -6856,12 +6883,18 @@ reinit_after_soft_reset:
>>  	spin_lock_init(&h->scan_lock);
>>  	atomic_set(&h->passthru_cmds_avail, HPSA_MAX_CONCURRENT_PASSTHRUS);
>>  
>> -	h->resubmit_wq = alloc_workqueue("hpsa", WQ_MEM_RECLAIM, 0);
>> +	h->rescan_ctlr_wq = hpsa_create_controller_wq(h, "rescan");
>> +	if (!h->rescan_ctlr_wq) {
>> +		rc = -ENOMEM;
>> +		goto clean1;
>> +	}
>> +
>> +	h->resubmit_wq = hpsa_create_controller_wq(h, "resubmit");
>>  	if (!h->resubmit_wq) {
>> -		dev_err(&h->pdev->dev, "Failed to allocate work queue\n");
>>  		rc = -ENOMEM;
>>  		goto clean1;
>>  	}
>> +
>>  	/* Allocate and clear per-cpu variable lockup_detected */
>>  	h->lockup_detected = alloc_percpu(u32);
>>  	if (!h->lockup_detected) {
>> @@ -6985,6 +7018,9 @@ reinit_after_soft_reset:
>>  	INIT_DELAYED_WORK(&h->monitor_ctlr_work, hpsa_monitor_ctlr_worker);
>>  	schedule_delayed_work(&h->monitor_ctlr_work,
>>  				h->heartbeat_sample_interval);
>> +	INIT_DELAYED_WORK(&h->rescan_ctlr_work, hpsa_rescan_ctlr_worker);
>> +	queue_delayed_work(h->rescan_ctlr_wq, &h->rescan_ctlr_work,
>> +				h->heartbeat_sample_interval);
>>  	return 0;
>>  
>>  clean4:
>> @@ -6996,6 +7032,8 @@ clean2:
>>  clean1:
>>  	if (h->resubmit_wq)
>>  		destroy_workqueue(h->resubmit_wq);
>> +	if (h->rescan_ctlr_wq)
>> +		destroy_workqueue(h->rescan_ctlr_wq);
>>  	if (h->lockup_detected)
>>  		free_percpu(h->lockup_detected);
>>  	kfree(h);
>> @@ -7069,11 +7107,13 @@ static void hpsa_remove_one(struct pci_dev *pdev)
>>  	/* Get rid of any controller monitoring work items */
>>  	spin_lock_irqsave(&h->lock, flags);
>>  	h->remove_in_progress = 1;
>> -	cancel_delayed_work(&h->monitor_ctlr_work);
>>  	spin_unlock_irqrestore(&h->lock, flags);
>> +	cancel_delayed_work_sync(&h->monitor_ctlr_work);
>> +	cancel_delayed_work_sync(&h->rescan_ctlr_work);
>> +	destroy_workqueue(h->rescan_ctlr_wq);
>> +	destroy_workqueue(h->resubmit_wq);
>>  	hpsa_unregister_scsi(h);	/* unhook from SCSI subsystem */
>>  	hpsa_shutdown(pdev);
>> -	destroy_workqueue(h->resubmit_wq);
>>  	iounmap(h->vaddr);
>>  	iounmap(h->transtable);
>>  	iounmap(h->cfgtable);
>> diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
>> index 62c50c3..6577130 100644
>> --- a/drivers/scsi/hpsa.h
>> +++ b/drivers/scsi/hpsa.h
>> @@ -207,6 +207,7 @@ struct ctlr_info {
>>  	atomic_t firmware_flash_in_progress;
>>  	u32 __percpu *lockup_detected;
>>  	struct delayed_work monitor_ctlr_work;
>> +	struct delayed_work rescan_ctlr_work;
>>  	int remove_in_progress;
>>  	/* Address of h->q[x] is passed to intr handler to know which queue */
>>  	u8 q[MAX_REPLY_QUEUES];
>> @@ -251,6 +252,7 @@ struct ctlr_info {
>>  	int	acciopath_status;
>>  	int	raid_offload_debug;
>>  	struct workqueue_struct *resubmit_wq;
>> +	struct workqueue_struct *rescan_ctlr_wq;
>>  };
>>  
>>  struct offline_device_entry {
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply	[flat|nested] 51+ messages in thread

end of thread, other threads:[~2015-01-27 17:13 UTC | newest]

Thread overview: 51+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-23 22:41 [PATCH v2 00/48] hpsa driver updates Don Brace
2015-01-23 22:41 ` [PATCH v2 01/48] hpsa: correct endian sparse warnings Don Brace
2015-01-23 22:41 ` [PATCH v2 02/48] hpsa: fix memory leak in kdump hard reset Don Brace
2015-01-23 22:41 ` [PATCH v2 03/48] hpsa: turn off interrupts when kdump starts Don Brace
2015-01-23 22:41 ` [PATCH v2 04/48] hpsa: change how SA controllers are reset Don Brace
2015-01-23 22:41 ` [PATCH v2 05/48] hpsa: correct change_queue_depth Don Brace
2015-01-23 22:41 ` [PATCH v2 06/48] hpsa: adjust RAID-1, RAID-1ADM, and RAID-6 names Don Brace
2015-01-23 22:41 ` [PATCH v2 07/48] hpsa: rename free_irqs to hpsa_free_irqs Don Brace
2015-01-23 22:41 ` [PATCH v2 08/48] hpsa: Fix -Wunused-but-set-variable warning Don Brace
2015-01-23 22:41 ` [PATCH v2 09/48] hpsa: notice all request_irq errors Don Brace
2015-01-23 22:41 ` [PATCH v2 10/48] hpsa: remove 0x from queue depth print which is in decimal Don Brace
2015-01-23 22:42 ` [PATCH v2 11/48] hpsa: propagate hard_reset failures in reset_devices mode Don Brace
2015-01-23 22:42 ` [PATCH v2 12/48] hpsa: propagate return value from board ID lookup Don Brace
2015-01-23 22:42 ` [PATCH v2 13/48] hpsa: downgrade the Waiting for no-op print to dev_info Don Brace
2015-01-23 22:42 ` [PATCH v2 14/48] hpsa: refactor hpsa_find_board_params() to encapsulate legacy test Don Brace
2015-01-23 22:42 ` [PATCH v2 15/48] hpsa: trivial message and comment clean ups Don Brace
2015-01-23 22:42 ` [PATCH v2 16/48] hpsa: report failure to ioremap config table Don Brace
2015-01-23 22:42 ` [PATCH v2 17/48] hpsa: rename hpsa_request_irq to hpsa_request_irqs Don Brace
2015-01-23 22:42 ` [PATCH v2 18/48] hpsa: pass error from pci_set_consistent_dma_mask from hpsa_message Don Brace
2015-01-23 22:42 ` [PATCH v2 19/48] hpsa: report allocation failures while allocating SG chain blocks Don Brace
2015-01-23 22:42 ` [PATCH v2 20/48] hpsa: fix memory leak in hpsa_alloc_cmd_pool Don Brace
2015-01-23 22:42 ` [PATCH v2 21/48] hpsa: avoid unneccesary calls to resource freeing functions Don Brace
2015-01-23 22:42 ` [PATCH v2 22/48] hpsa: reserve some commands for use by driver Don Brace
2015-01-23 22:43 ` [PATCH v2 23/48] hpsa: get rid of cmd_special_alloc and cmd_special_free Don Brace
2015-01-23 22:43 ` [PATCH v2 24/48] hpsa: do not queue commands internally in driver Don Brace
2015-01-23 22:43 ` [PATCH v2 25/48] hpsa: do not request device rescan on every ioaccel path error Don Brace
2015-01-23 22:43 ` [PATCH v2 26/48] hpsa: factor out hpsa_ciss_submit function Don Brace
2015-01-23 22:43 ` [PATCH v2 27/48] hpsa: use workqueue to resubmit failed ioaccel commands Don Brace
2015-01-23 22:43 ` [PATCH v2 28/48] hpsa: honor queue depth of physical devices Don Brace
2015-01-23 22:43 ` [PATCH v2 29/48] hpsa: fix race between abort handler and main i/o path Don Brace
2015-01-23 22:43 ` [PATCH v2 30/48] hpsa: optimize cmd_alloc function by remembering last allocation Don Brace
2015-01-23 22:43 ` [PATCH v2 31/48] hpsa: count passthru cmds with atomics, not a spin locked int Don Brace
2015-01-23 22:43 ` [PATCH v2 32/48] hpsa: slightly optimize SA5_performant_completed Don Brace
2015-01-23 22:43 ` [PATCH v2 33/48] hpsa: do not check for msi(x) in interrupt_pending Don Brace
2015-01-23 22:44 ` [PATCH v2 34/48] hpsa: remove incorrect BUG_ONs checking for raid offload enable Don Brace
2015-01-23 22:44 ` [PATCH v2 35/48] hpsa: do not ack controller events on controllers that do not support it Don Brace
2015-01-23 22:44 ` [PATCH v2 36/48] hpsa: guard against overflowing raid map array Don Brace
2015-01-23 22:44 ` [PATCH v2 37/48] hpsa: check for ctlr lockup after command allocation in main io path Don Brace
2015-01-23 22:44 ` [PATCH v2 38/48] hpsa: return failed from device reset/abort handlers Don Brace
2015-01-23 22:44 ` [PATCH v2 39/48] hpsa: do not use a void pointer for scsi_cmd field of struct CommandList Don Brace
2015-01-23 22:44 ` [PATCH v2 40/48] hpsa: print CDBs instead of kernel virtual addresses for uncommon errors Don Brace
2015-01-23 22:44 ` [PATCH v2 41/48] hpsa: do not use function pointers in fast path command submission Don Brace
2015-01-23 22:44 ` [PATCH v2 42/48] hpsa: move SG descriptor set-up out of hpsa_scatter_gather() Don Brace
2015-01-23 22:44 ` [PATCH v2 43/48] hpsa: refactor duplicated scan completion code into a new routine Don Brace
2015-01-23 22:44 ` [PATCH v2 44/48] hpsa: shorten the wait for the CISS doorbell mode change ack Don Brace
2015-01-23 22:45 ` [PATCH v2 45/48] hpsa: detect and report failures changing controller transport modes Don Brace
2015-01-23 22:45 ` [PATCH v2 46/48] hpsa: add in gen9 controller model names Don Brace
2015-01-23 22:45 ` [PATCH v2 47/48] hpsa: add in P840ar controller model name Don Brace
2015-01-23 22:45 ` [PATCH v2 48/48] hpsa: Use local workqueues instead of system workqueues Don Brace
2015-01-27 16:55   ` Tomas Henzl
2015-01-27 17:13     ` Tomas Henzl

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.