summaryrefslogtreecommitdiff
path: root/drivers/scsi/smartpqi
diff options
context:
space:
mode:
authorKevin Barnett <kevin.barnett@microsemi.com>2016-08-31 22:54:11 +0300
committerMartin K. Petersen <martin.petersen@oracle.com>2016-09-02 13:21:37 +0300
commita60eec0251fe1bfc0cd549c073591e6657761158 (patch)
tree77ee5da669f12556439fda67e80d9fc8e7e9ac37 /drivers/scsi/smartpqi
parentb2990536f44752e54dc300a2f98253519adfe649 (diff)
downloadlinux-a60eec0251fe1bfc0cd549c073591e6657761158.tar.xz
scsi: smartpqi: change aio sg processing
Take advantage of controller improvements. Reviewed-by: Scott Teel <scott.teel@microsemi.com> Reviewed-by: Scott Benesh <scott.benesh@microsemi.com> Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de> Reviewed-by: Tomas Henzl <thenzl@redhat.com> Signed-off-by: Kevin Barnett <kevin.barnett@microsemi.com> Signed-off-by: Don Brace <don.brace@microsemi.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/smartpqi')
-rw-r--r--drivers/scsi/smartpqi/smartpqi_init.c68
1 files changed, 39 insertions, 29 deletions
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c
index 906f1aaf7cd2..418f63670d71 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -4263,48 +4263,58 @@ static int pqi_build_aio_sg_list(struct pqi_ctrl_info *ctrl_info,
int i;
u16 iu_length;
int sg_count;
- unsigned int num_sg_in_iu = 0;
+ bool chained;
+ unsigned int num_sg_in_iu;
+ unsigned int max_sg_per_iu;
struct scatterlist *sg;
struct pqi_sg_descriptor *sg_descriptor;
sg_count = scsi_dma_map(scmd);
if (sg_count < 0)
return sg_count;
+
+ iu_length = offsetof(struct pqi_aio_path_request, sg_descriptors) -
+ PQI_REQUEST_HEADER_LENGTH;
+ num_sg_in_iu = 0;
+
if (sg_count == 0)
goto out;
- if (sg_count <= ctrl_info->max_sg_per_iu) {
- sg_descriptor = &request->sg_descriptors[0];
- scsi_for_each_sg(scmd, sg, sg_count, i) {
- pqi_set_sg_descriptor(sg_descriptor, sg);
- sg_descriptor++;
- }
- put_unaligned_le32(CISS_SG_LAST,
- &request->sg_descriptors[sg_count - 1].flags);
- num_sg_in_iu = sg_count;
- } else {
- sg_descriptor = &request->sg_descriptors[0];
- put_unaligned_le64((u64)io_request->sg_chain_buffer_dma_handle,
- &sg_descriptor->address);
- put_unaligned_le32(sg_count * sizeof(*sg_descriptor),
- &sg_descriptor->length);
- put_unaligned_le32(CISS_SG_CHAIN, &sg_descriptor->flags);
-
- sg_descriptor = io_request->sg_chain_buffer;
- scsi_for_each_sg(scmd, sg, sg_count, i) {
- pqi_set_sg_descriptor(sg_descriptor, sg);
- sg_descriptor++;
+ sg = scsi_sglist(scmd);
+ sg_descriptor = request->sg_descriptors;
+ max_sg_per_iu = ctrl_info->max_sg_per_iu - 1;
+ chained = false;
+ i = 0;
+
+ while (1) {
+ pqi_set_sg_descriptor(sg_descriptor, sg);
+ if (!chained)
+ num_sg_in_iu++;
+ i++;
+ if (i == sg_count)
+ break;
+ sg_descriptor++;
+ if (i == max_sg_per_iu) {
+ put_unaligned_le64(
+ (u64)io_request->sg_chain_buffer_dma_handle,
+ &sg_descriptor->address);
+ put_unaligned_le32((sg_count - num_sg_in_iu)
+ * sizeof(*sg_descriptor),
+ &sg_descriptor->length);
+ put_unaligned_le32(CISS_SG_CHAIN,
+ &sg_descriptor->flags);
+ chained = true;
+ num_sg_in_iu++;
+ sg_descriptor = io_request->sg_chain_buffer;
}
- put_unaligned_le32(CISS_SG_LAST,
- &io_request->sg_chain_buffer[sg_count - 1].flags);
- num_sg_in_iu = 1;
- request->partial = 1;
+ sg = sg_next(sg);
}
-out:
- iu_length = offsetof(struct pqi_aio_path_request, sg_descriptors) -
- PQI_REQUEST_HEADER_LENGTH;
+ put_unaligned_le32(CISS_SG_LAST, &sg_descriptor->flags);
+ request->partial = chained;
iu_length += num_sg_in_iu * sizeof(*sg_descriptor);
+
+out:
put_unaligned_le16(iu_length, &request->header.iu_length);
request->num_sg_descriptors = num_sg_in_iu;