[PATCH] hpsa: scsi-mq support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch enables full scsi-mq support for the hpsa driver.
Due to some reports of performance regressions this patch
also adds a parameter 'use_blk_mq' which can be used to
disable multiqueue support if required.

Signed-off-by: Hannes Reinecke <hare@xxxxxxxx>
---
 drivers/scsi/hpsa.c | 64 +++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 52 insertions(+), 12 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 0df0e04..ef4e81a 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -91,6 +91,9 @@
 MODULE_PARM_DESC(hpsa_simple_mode,
 	"Use 'simple mode' rather than 'performant mode'");
 
+bool use_blk_mq = true;
+module_param(use_blk_mq, bool, 0);
+
 /* define the PCI info for the cards we can control */
 static const struct pci_device_id hpsa_pci_device_id[] = {
 	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3241},
@@ -1137,12 +1140,13 @@ static void __enqueue_cmd_and_start_io(struct ctlr_info *h,
 	}
 }
 
-static void enqueue_cmd_and_start_io(struct ctlr_info *h, struct CommandList *c)
+static void enqueue_cmd_and_start_io(struct ctlr_info *h,
+				     struct CommandList *c, int reply_queue)
 {
 	if (unlikely(hpsa_is_pending_event(c)))
 		return finish_cmd(c);
 
-	__enqueue_cmd_and_start_io(h, c, DEFAULT_REPLY_QUEUE);
+	__enqueue_cmd_and_start_io(h, c, reply_queue);
 }
 
 static inline int is_hba_lunid(unsigned char scsi3addr[])
@@ -4614,6 +4618,7 @@ static int hpsa_scsi_ioaccel1_queue_command(struct ctlr_info *h,
 	int use_sg, i;
 	struct SGDescriptor *curr_sg;
 	u32 control = IOACCEL1_CONTROL_SIMPLEQUEUE;
+	int reply_queue = DEFAULT_REPLY_QUEUE;
 
 	/* TODO: implement chaining support */
 	if (scsi_sg_count(cmd) > h->ioaccel_maxsg) {
@@ -4683,8 +4688,12 @@ static int hpsa_scsi_ioaccel1_queue_command(struct ctlr_info *h,
 	cp->control = cpu_to_le32(control);
 	memcpy(cp->CDB, cdb, cdb_len);
 	memcpy(cp->CISS_LUN, scsi3addr, 8);
+	if (shost_use_blk_mq(cmd->device->host)) {
+		u32 blk_tag = blk_mq_unique_tag(cmd->request);
+		reply_queue = blk_mq_unique_tag_to_hwq(blk_tag);
+	}
 	/* Tag was already set at init time. */
-	enqueue_cmd_and_start_io(h, c);
+	enqueue_cmd_and_start_io(h, c, reply_queue);
 	return 0;
 }
 
@@ -4778,6 +4787,7 @@ static int hpsa_scsi_ioaccel2_queue_command(struct ctlr_info *h,
 	u64 addr64;
 	u32 len;
 	u32 total_len = 0;
+	int reply_queue = DEFAULT_REPLY_QUEUE;
 
 	if (!cmd->device)
 		return -1;
@@ -4882,7 +4892,11 @@ static int hpsa_scsi_ioaccel2_queue_command(struct ctlr_info *h,
 	} else
 		cp->sg_count = (u8) use_sg;
 
-	enqueue_cmd_and_start_io(h, c);
+	if (shost_use_blk_mq(cmd->device->host)) {
+		u32 blk_tag = blk_mq_unique_tag(cmd->request);
+		reply_queue = blk_mq_unique_tag_to_hwq(blk_tag);
+	}
+	enqueue_cmd_and_start_io(h, c, reply_queue);
 	return 0;
 }
 
@@ -5284,6 +5298,8 @@ static int hpsa_ciss_submit(struct ctlr_info *h,
 	struct CommandList *c, struct scsi_cmnd *cmd,
 	unsigned char scsi3addr[])
 {
+	int reply_queue = DEFAULT_REPLY_QUEUE;
+
 	cmd->host_scribble = (unsigned char *) c;
 	c->cmd_type = CMD_SCSI;
 	c->scsi_cmd = cmd;
@@ -5339,7 +5355,11 @@ static int hpsa_ciss_submit(struct ctlr_info *h,
 		hpsa_cmd_resolve_and_free(h, c);
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
-	enqueue_cmd_and_start_io(h, c);
+	if (shost_use_blk_mq(cmd->device->host)) {
+		u32 blk_tag = blk_mq_unique_tag(cmd->request);
+		reply_queue = blk_mq_unique_tag_to_hwq(blk_tag);
+	}
+	enqueue_cmd_and_start_io(h, c, reply_queue);
 	/* the cmd'll come back via intr handler in complete_scsi_command()  */
 	return 0;
 }
@@ -5642,13 +5662,23 @@ static int hpsa_scsi_host_alloc(struct ctlr_info *h)
 static int hpsa_scsi_add_host(struct ctlr_info *h)
 {
 	int rv;
+	struct Scsi_Host *sh = h->scsi_host;
 
-	rv = scsi_add_host(h->scsi_host, &h->pdev->dev);
+	if (h->intr_mode == PERF_MODE_INT && h->msix_vectors > 0)
+		sh->nr_hw_queues = h->msix_vectors;
+	else
+		sh->nr_hw_queues = 1;
+
+	if (use_blk_mq) {
+		sh->can_queue = sh->can_queue / sh->nr_hw_queues;
+		sh->use_blk_mq = 1;
+	}
+	rv = scsi_add_host(sh, &h->pdev->dev);
 	if (rv) {
 		dev_err(&h->pdev->dev, "scsi_add_host failed\n");
 		return rv;
 	}
-	scsi_scan_host(h->scsi_host);
+	scsi_scan_host(sh);
 	return 0;
 }
 
@@ -5658,10 +5688,20 @@ static int hpsa_scsi_add_host(struct ctlr_info *h)
  * an index to select our command block.  (The offset allows us to reserve the
  * low-numbered entries for our own uses.)
  */
-static int hpsa_get_cmd_index(struct scsi_cmnd *scmd)
+static int hpsa_get_cmd_index(struct ctlr_info *h, struct scsi_cmnd *scmd)
 {
 	int idx = scmd->request->tag;
 
+	if (shost_use_blk_mq(scmd->device->host)) {
+		u32 blk_tag = blk_mq_unique_tag(scmd->request);
+		u16 hwq = blk_mq_unique_tag_to_hwq(blk_tag);
+		u16 tag = blk_mq_unique_tag_to_tag(blk_tag);
+		int msix_vectors, hwq_size;
+
+		msix_vectors = h->msix_vectors > 0 ? h->msix_vectors : 1;
+		hwq_size = (h->nr_cmds - HPSA_NRESERVED_CMDS) / msix_vectors;
+		idx = (hwq * hwq_size) + tag;
+	}
 	if (idx < 0)
 		return idx;
 
@@ -5811,7 +5851,7 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd)
 	if (lockup_detected(h)) {
 		snprintf(msg, sizeof(msg),
 			 "cmd %d RESET FAILED, lockup detected",
-			 hpsa_get_cmd_index(scsicmd));
+			 hpsa_get_cmd_index(h, scsicmd));
 		hpsa_show_dev_msg(KERN_WARNING, h, dev, msg);
 		return FAILED;
 	}
@@ -5820,7 +5860,7 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd)
 	if (detect_controller_lockup(h)) {
 		snprintf(msg, sizeof(msg),
 			 "cmd %d RESET FAILED, new lockup detected",
-			 hpsa_get_cmd_index(scsicmd));
+			 hpsa_get_cmd_index(h, scsicmd));
 		hpsa_show_dev_msg(KERN_WARNING, h, dev, msg);
 		return FAILED;
 	}
@@ -6293,7 +6333,7 @@ static int hpsa_eh_abort_handler(struct scsi_cmnd *sc)
 static struct CommandList *cmd_tagged_alloc(struct ctlr_info *h,
 					    struct scsi_cmnd *scmd)
 {
-	int idx = hpsa_get_cmd_index(scmd);
+	int idx = hpsa_get_cmd_index(h, scmd);
 	struct CommandList *c = h->cmd_pool + idx;
 
 	if (idx < HPSA_NRESERVED_CMDS || idx >= h->nr_cmds) {
@@ -6857,7 +6897,7 @@ static void hpsa_send_host_reset(struct ctlr_info *h, unsigned char *scsi3addr,
 		RAID_CTLR_LUNID, TYPE_MSG);
 	c->Request.CDB[1] = reset_type; /* fill_cmd defaults to target reset */
 	c->waiting = NULL;
-	enqueue_cmd_and_start_io(h, c);
+	enqueue_cmd_and_start_io(h, c, DEFAULT_REPLY_QUEUE);
 	/* Don't wait for completion, the reset won't complete.  Don't free
 	 * the command either.  This is the last command we will send before
 	 * re-initializing everything, so it doesn't matter and won't leak.
-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]

  Powered by Linux