aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc
diff options
context:
space:
mode:
authorJames Smart <james.smart@avagotech.com>2015-12-16 18:12:04 -0500
committerMartin K. Petersen <martin.petersen@oracle.com>2015-12-21 22:05:04 -0500
commit4360ca9c24388e44cb0e14861a62fff43cf225c0 (patch)
treeaede500b275f6050b87be985315d57e560d930ea /drivers/scsi/lpfc
parent01c73bbcd7cc4f31f45a1b0caeacdba46acd9c9c (diff)
lpfc: Fix external loopback failure.
Fix external loopback failure. Rx sequence reassembly was incorrect. Signed-off-by: Dick Kennedy <dick.kennedy@avagotech.com> Signed-off-by: James Smart <james.smart@avagotech.com> Reviewed-by: Hannes Reinicke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 6aae828208e2..92dfd6a5178c 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -14842,10 +14842,12 @@ lpfc_fc_frame_add(struct lpfc_vport *vport, struct hbq_dmabuf *dmabuf)
14842 struct lpfc_dmabuf *h_buf; 14842 struct lpfc_dmabuf *h_buf;
14843 struct hbq_dmabuf *seq_dmabuf = NULL; 14843 struct hbq_dmabuf *seq_dmabuf = NULL;
14844 struct hbq_dmabuf *temp_dmabuf = NULL; 14844 struct hbq_dmabuf *temp_dmabuf = NULL;
14845 uint8_t found = 0;
14845 14846
14846 INIT_LIST_HEAD(&dmabuf->dbuf.list); 14847 INIT_LIST_HEAD(&dmabuf->dbuf.list);
14847 dmabuf->time_stamp = jiffies; 14848 dmabuf->time_stamp = jiffies;
14848 new_hdr = (struct fc_frame_header *)dmabuf->hbuf.virt; 14849 new_hdr = (struct fc_frame_header *)dmabuf->hbuf.virt;
14850
14849 /* Use the hdr_buf to find the sequence that this frame belongs to */ 14851 /* Use the hdr_buf to find the sequence that this frame belongs to */
14850 list_for_each_entry(h_buf, &vport->rcv_buffer_list, list) { 14852 list_for_each_entry(h_buf, &vport->rcv_buffer_list, list) {
14851 temp_hdr = (struct fc_frame_header *)h_buf->virt; 14853 temp_hdr = (struct fc_frame_header *)h_buf->virt;
@@ -14885,7 +14887,8 @@ lpfc_fc_frame_add(struct lpfc_vport *vport, struct hbq_dmabuf *dmabuf)
14885 return seq_dmabuf; 14887 return seq_dmabuf;
14886 } 14888 }
14887 /* find the correct place in the sequence to insert this frame */ 14889 /* find the correct place in the sequence to insert this frame */
14888 list_for_each_entry_reverse(d_buf, &seq_dmabuf->dbuf.list, list) { 14890 d_buf = list_entry(seq_dmabuf->dbuf.list.prev, typeof(*d_buf), list);
14891 while (!found) {
14889 temp_dmabuf = container_of(d_buf, struct hbq_dmabuf, dbuf); 14892 temp_dmabuf = container_of(d_buf, struct hbq_dmabuf, dbuf);
14890 temp_hdr = (struct fc_frame_header *)temp_dmabuf->hbuf.virt; 14893 temp_hdr = (struct fc_frame_header *)temp_dmabuf->hbuf.virt;
14891 /* 14894 /*
@@ -14895,9 +14898,17 @@ lpfc_fc_frame_add(struct lpfc_vport *vport, struct hbq_dmabuf *dmabuf)
14895 if (be16_to_cpu(new_hdr->fh_seq_cnt) > 14898 if (be16_to_cpu(new_hdr->fh_seq_cnt) >
14896 be16_to_cpu(temp_hdr->fh_seq_cnt)) { 14899 be16_to_cpu(temp_hdr->fh_seq_cnt)) {
14897 list_add(&dmabuf->dbuf.list, &temp_dmabuf->dbuf.list); 14900 list_add(&dmabuf->dbuf.list, &temp_dmabuf->dbuf.list);
14898 return seq_dmabuf; 14901 found = 1;
14902 break;
14899 } 14903 }
14904
14905 if (&d_buf->list == &seq_dmabuf->dbuf.list)
14906 break;
14907 d_buf = list_entry(d_buf->list.prev, typeof(*d_buf), list);
14900 } 14908 }
14909
14910 if (found)
14911 return seq_dmabuf;
14901 return NULL; 14912 return NULL;
14902} 14913}
14903 14914