diff options
author | Ram Pai <linuxram@us.ibm.com> | 2017-01-26 13:37:01 -0500 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2017-01-31 22:36:53 -0500 |
commit | f2e767bb5d6ee0d988cb7d4e54b0b21175802b6b (patch) | |
tree | 02856806fddc633c2ff9f24703feba2d4e402b56 | |
parent | 2780f3c8f0233de90b6b47a23fc422b7780c5436 (diff) |
scsi: mpt3sas: Force request partial completion alignment
The firmware or device, possibly under a heavy I/O load, can return on a
partial unaligned boundary. Scsi-ml expects these requests to be
completed on an alignment boundary. Scsi-ml blindly requeues the I/O
without checking the alignment boundary of the I/O request for the
remaining bytes. This leads to errors, since devices cannot perform
non-aligned read/write operations.
This patch fixes the issue in the driver. It aligns unaligned
completions of FS requests, by truncating them to the nearest alignment
boundary.
[mkp: simplified if statement]
Reported-by: Mauricio Faria De Oliveira <mauricfo@linux.vnet.ibm.com>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@linux.vnet.ibm.com>
Signed-off-by: Ram Pai <linuxram@us.ibm.com>
Acked-by: Sreekanth Reddy <Sreekanth.Reddy@broadcom.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r-- | drivers/scsi/mpt3sas/mpt3sas_scsih.c | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 75f3fce1c867..268103182d34 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c | |||
@@ -4657,6 +4657,7 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | |||
4657 | struct MPT3SAS_DEVICE *sas_device_priv_data; | 4657 | struct MPT3SAS_DEVICE *sas_device_priv_data; |
4658 | u32 response_code = 0; | 4658 | u32 response_code = 0; |
4659 | unsigned long flags; | 4659 | unsigned long flags; |
4660 | unsigned int sector_sz; | ||
4660 | 4661 | ||
4661 | mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); | 4662 | mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); |
4662 | scmd = _scsih_scsi_lookup_get_clear(ioc, smid); | 4663 | scmd = _scsih_scsi_lookup_get_clear(ioc, smid); |
@@ -4715,6 +4716,20 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | |||
4715 | } | 4716 | } |
4716 | 4717 | ||
4717 | xfer_cnt = le32_to_cpu(mpi_reply->TransferCount); | 4718 | xfer_cnt = le32_to_cpu(mpi_reply->TransferCount); |
4719 | |||
4720 | /* In case of bogus fw or device, we could end up having | ||
4721 | * unaligned partial completion. We can force alignment here, | ||
4722 | * then scsi-ml does not need to handle this misbehavior. | ||
4723 | */ | ||
4724 | sector_sz = scmd->device->sector_size; | ||
4725 | if (unlikely(scmd->request->cmd_type == REQ_TYPE_FS && sector_sz && | ||
4726 | xfer_cnt % sector_sz)) { | ||
4727 | sdev_printk(KERN_INFO, scmd->device, | ||
4728 | "unaligned partial completion avoided (xfer_cnt=%u, sector_sz=%u)\n", | ||
4729 | xfer_cnt, sector_sz); | ||
4730 | xfer_cnt = round_down(xfer_cnt, sector_sz); | ||
4731 | } | ||
4732 | |||
4718 | scsi_set_resid(scmd, scsi_bufflen(scmd) - xfer_cnt); | 4733 | scsi_set_resid(scmd, scsi_bufflen(scmd) - xfer_cnt); |
4719 | if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) | 4734 | if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) |
4720 | log_info = le32_to_cpu(mpi_reply->IOCLogInfo); | 4735 | log_info = le32_to_cpu(mpi_reply->IOCLogInfo); |