summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/hpsa.c
diff options
context:
space:
mode:
authorWebb Scales <webbnh@hp.com>2015-04-23 09:34:27 -0500
committerJames Bottomley <JBottomley@Odin.com>2015-05-31 11:38:41 -0700
commitb3a7ba7c942ccac8340a93b2bac2254480b1615f (patch)
tree23a581316380d1a7610125a943e1e420f753fad1 /drivers/scsi/hpsa.c
parentb69324ff93127b1a2042612ff2aa95b42af873a0 (diff)
downloadop-kernel-dev-b3a7ba7c942ccac8340a93b2bac2254480b1615f.zip
op-kernel-dev-b3a7ba7c942ccac8340a93b2bac2254480b1615f.tar.gz
hpsa: performance tweak for hpsa_scatter_gather()
Divide the loop in hpsa_scatter_gather() into two, one for the initial SG list and a second one for the chained list, if any. This allows the conditional check which resets the indicies for the chained list to be performed outside the loop instead of being done on every iteration inside the loop. Reviewed-by: Scott Teel <scott.teel@pmcs.com> Reviewed-by: Kevin Barnett <kevin.barnett@pmcs.com> Reviewed-by: Tomas Henzl <thenzl@redhat.com> Reviewed-by: Hannes Reinecke <hare@Suse.de> Signed-off-by: Webb Scales <webbnh@hp.com> Signed-off-by: Don Brace <don.brace@pmcs.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: James Bottomley <JBottomley@Odin.com>
Diffstat (limited to 'drivers/scsi/hpsa.c')
-rw-r--r--drivers/scsi/hpsa.c39
1 files changed, 28 insertions, 11 deletions
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 6e1d5f6..f1ef63b 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -3674,7 +3674,7 @@ static int hpsa_scatter_gather(struct ctlr_info *h,
struct scsi_cmnd *cmd)
{
struct scatterlist *sg;
- int use_sg, i, sg_index, chained;
+ int use_sg, i, sg_limit, chained, last_sg;
struct SGDescriptor *curr_sg;
BUG_ON(scsi_sg_count(cmd) > h->maxsgentries);
@@ -3686,22 +3686,39 @@ static int hpsa_scatter_gather(struct ctlr_info *h,
if (!use_sg)
goto sglist_finished;
+ /*
+ * If the number of entries is greater than the max for a single list,
+ * then we have a chained list; we will set up all but one entry in the
+ * first list (the last entry is saved for link information);
+ * otherwise, we don't have a chained list and we'll set up at each of
+ * the entries in the one list.
+ */
curr_sg = cp->SG;
- chained = 0;
- sg_index = 0;
- scsi_for_each_sg(cmd, sg, use_sg, i) {
- if (i == h->max_cmd_sg_entries - 1 &&
- use_sg > h->max_cmd_sg_entries) {
- chained = 1;
- curr_sg = h->cmd_sg_list[cp->cmdindex];
- sg_index = 0;
- }
+ chained = use_sg > h->max_cmd_sg_entries;
+ sg_limit = chained ? h->max_cmd_sg_entries - 1 : use_sg;
+ last_sg = scsi_sg_count(cmd) - 1;
+ scsi_for_each_sg(cmd, sg, sg_limit, i) {
hpsa_set_sg_descriptor(curr_sg, sg);
curr_sg++;
}
+ if (chained) {
+ /*
+ * Continue with the chained list. Set curr_sg to the chained
+ * list. Modify the limit to the total count less the entries
+ * we've already set up. Resume the scan at the list entry
+ * where the previous loop left off.
+ */
+ curr_sg = h->cmd_sg_list[cp->cmdindex];
+ sg_limit = use_sg - sg_limit;
+ for_each_sg(sg, sg, sg_limit, i) {
+ 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);
+ (curr_sg - 1)->Ext = cpu_to_le32(HPSA_SG_LAST);
if (use_sg + chained > h->maxSG)
h->maxSG = use_sg + chained;
OpenPOWER on IntegriCloud