lpfc: Fix external loopback failure.
authorJames Smart <james.smart@avagotech.com>
Wed, 16 Dec 2015 23:12:04 +0000 (18:12 -0500)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 22 Dec 2015 03:05:04 +0000 (22:05 -0500)
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>
drivers/scsi/lpfc/lpfc_sli.c

index 6aae828208e2693a1b044d473b7fd9996dc8e182..92dfd6a5178cef9e6826ad9159261765335c264b 100644 (file)
@@ -14842,10 +14842,12 @@ lpfc_fc_frame_add(struct lpfc_vport *vport, struct hbq_dmabuf *dmabuf)
        struct lpfc_dmabuf *h_buf;
        struct hbq_dmabuf *seq_dmabuf = NULL;
        struct hbq_dmabuf *temp_dmabuf = NULL;
+       uint8_t found = 0;
 
        INIT_LIST_HEAD(&dmabuf->dbuf.list);
        dmabuf->time_stamp = jiffies;
        new_hdr = (struct fc_frame_header *)dmabuf->hbuf.virt;
+
        /* Use the hdr_buf to find the sequence that this frame belongs to */
        list_for_each_entry(h_buf, &vport->rcv_buffer_list, list) {
                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)
                return seq_dmabuf;
        }
        /* find the correct place in the sequence to insert this frame */
-       list_for_each_entry_reverse(d_buf, &seq_dmabuf->dbuf.list, list) {
+       d_buf = list_entry(seq_dmabuf->dbuf.list.prev, typeof(*d_buf), list);
+       while (!found) {
                temp_dmabuf = container_of(d_buf, struct hbq_dmabuf, dbuf);
                temp_hdr = (struct fc_frame_header *)temp_dmabuf->hbuf.virt;
                /*
@@ -14895,9 +14898,17 @@ lpfc_fc_frame_add(struct lpfc_vport *vport, struct hbq_dmabuf *dmabuf)
                if (be16_to_cpu(new_hdr->fh_seq_cnt) >
                        be16_to_cpu(temp_hdr->fh_seq_cnt)) {
                        list_add(&dmabuf->dbuf.list, &temp_dmabuf->dbuf.list);
-                       return seq_dmabuf;
+                       found = 1;
+                       break;
                }
+
+               if (&d_buf->list == &seq_dmabuf->dbuf.list)
+                       break;
+               d_buf = list_entry(d_buf->list.prev, typeof(*d_buf), list);
        }
+
+       if (found)
+               return seq_dmabuf;
        return NULL;
 }