aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2009-12-21 17:01:23 -0500
committerJames Bottomley <James.Bottomley@suse.de>2010-01-04 12:39:42 -0500
commiteeead8115276a76675dc7cfc823a2461745edd27 (patch)
tree3a07e0195d5c8a3ee4c91552dc03d0cf50566a0e /drivers/scsi
parent91e6ecada757a6e2ef7b937634af8a04376772a1 (diff)
[SCSI] lpfc 8.3.7: Fix FC protocol errors
Fix FC protocol errors: - Fix multi-frame unsolicited sequences not queued properly - Fix frames for unsolicited sequences not being associated with sequence. - Fix unsolicited frame buffer sizes are not set properly - Fix Sequence count for unsolicited frame headers not byte swapped. - Fix Multi-frame sequence response frames go to wrong DID. Signed-off-by: James Smart <james.smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/lpfc/lpfc_hw4.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c21
2 files changed, 15 insertions, 8 deletions
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index 1585148a17e5..09c8e362aee3 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -1013,7 +1013,7 @@ struct lpfc_mbx_wq_destroy {
1013}; 1013};
1014 1014
1015#define LPFC_HDR_BUF_SIZE 128 1015#define LPFC_HDR_BUF_SIZE 128
1016#define LPFC_DATA_BUF_SIZE 4096 1016#define LPFC_DATA_BUF_SIZE 2048
1017struct rq_context { 1017struct rq_context {
1018 uint32_t word0; 1018 uint32_t word0;
1019#define lpfc_rq_context_rq_size_SHIFT 16 1019#define lpfc_rq_context_rq_size_SHIFT 16
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 7935667b81a5..50f72bf18256 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -5848,7 +5848,6 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
5848 iocbq->iocb.un.ulpWord[3]); 5848 iocbq->iocb.un.ulpWord[3]);
5849 wqe->generic.word3 = 0; 5849 wqe->generic.word3 = 0;
5850 bf_set(wqe_rcvoxid, &wqe->generic, iocbq->iocb.ulpContext); 5850 bf_set(wqe_rcvoxid, &wqe->generic, iocbq->iocb.ulpContext);
5851 bf_set(wqe_xc, &wqe->generic, 1);
5852 /* The entire sequence is transmitted for this IOCB */ 5851 /* The entire sequence is transmitted for this IOCB */
5853 xmit_len = total_len; 5852 xmit_len = total_len;
5854 cmnd = CMD_XMIT_SEQUENCE64_CR; 5853 cmnd = CMD_XMIT_SEQUENCE64_CR;
@@ -10944,7 +10943,8 @@ lpfc_fc_frame_add(struct lpfc_vport *vport, struct hbq_dmabuf *dmabuf)
10944 return dmabuf; 10943 return dmabuf;
10945 } 10944 }
10946 temp_hdr = seq_dmabuf->hbuf.virt; 10945 temp_hdr = seq_dmabuf->hbuf.virt;
10947 if (new_hdr->fh_seq_cnt < temp_hdr->fh_seq_cnt) { 10946 if (be16_to_cpu(new_hdr->fh_seq_cnt) <
10947 be16_to_cpu(temp_hdr->fh_seq_cnt)) {
10948 list_del_init(&seq_dmabuf->hbuf.list); 10948 list_del_init(&seq_dmabuf->hbuf.list);
10949 list_add_tail(&dmabuf->hbuf.list, &vport->rcv_buffer_list); 10949 list_add_tail(&dmabuf->hbuf.list, &vport->rcv_buffer_list);
10950 list_add_tail(&dmabuf->dbuf.list, &seq_dmabuf->dbuf.list); 10950 list_add_tail(&dmabuf->dbuf.list, &seq_dmabuf->dbuf.list);
@@ -10955,6 +10955,11 @@ lpfc_fc_frame_add(struct lpfc_vport *vport, struct hbq_dmabuf *dmabuf)
10955 list_move_tail(&seq_dmabuf->hbuf.list, &vport->rcv_buffer_list); 10955 list_move_tail(&seq_dmabuf->hbuf.list, &vport->rcv_buffer_list);
10956 seq_dmabuf->time_stamp = jiffies; 10956 seq_dmabuf->time_stamp = jiffies;
10957 lpfc_update_rcv_time_stamp(vport); 10957 lpfc_update_rcv_time_stamp(vport);
10958 if (list_empty(&seq_dmabuf->dbuf.list)) {
10959 temp_hdr = dmabuf->hbuf.virt;
10960 list_add_tail(&dmabuf->dbuf.list, &seq_dmabuf->dbuf.list);
10961 return seq_dmabuf;
10962 }
10958 /* find the correct place in the sequence to insert this frame */ 10963 /* find the correct place in the sequence to insert this frame */
10959 list_for_each_entry_reverse(d_buf, &seq_dmabuf->dbuf.list, list) { 10964 list_for_each_entry_reverse(d_buf, &seq_dmabuf->dbuf.list, list) {
10960 temp_dmabuf = container_of(d_buf, struct hbq_dmabuf, dbuf); 10965 temp_dmabuf = container_of(d_buf, struct hbq_dmabuf, dbuf);
@@ -10963,7 +10968,8 @@ lpfc_fc_frame_add(struct lpfc_vport *vport, struct hbq_dmabuf *dmabuf)
10963 * If the frame's sequence count is greater than the frame on 10968 * If the frame's sequence count is greater than the frame on
10964 * the list then insert the frame right after this frame 10969 * the list then insert the frame right after this frame
10965 */ 10970 */
10966 if (new_hdr->fh_seq_cnt > temp_hdr->fh_seq_cnt) { 10971 if (be16_to_cpu(new_hdr->fh_seq_cnt) >
10972 be16_to_cpu(temp_hdr->fh_seq_cnt)) {
10967 list_add(&dmabuf->dbuf.list, &temp_dmabuf->dbuf.list); 10973 list_add(&dmabuf->dbuf.list, &temp_dmabuf->dbuf.list);
10968 return seq_dmabuf; 10974 return seq_dmabuf;
10969 } 10975 }
@@ -11210,7 +11216,7 @@ lpfc_seq_complete(struct hbq_dmabuf *dmabuf)
11210 seq_dmabuf = container_of(d_buf, struct hbq_dmabuf, dbuf); 11216 seq_dmabuf = container_of(d_buf, struct hbq_dmabuf, dbuf);
11211 hdr = (struct fc_frame_header *)seq_dmabuf->hbuf.virt; 11217 hdr = (struct fc_frame_header *)seq_dmabuf->hbuf.virt;
11212 /* If there is a hole in the sequence count then fail. */ 11218 /* If there is a hole in the sequence count then fail. */
11213 if (++seq_count != hdr->fh_seq_cnt) 11219 if (++seq_count != be16_to_cpu(hdr->fh_seq_cnt))
11214 return 0; 11220 return 0;
11215 fctl = (hdr->fh_f_ctl[0] << 16 | 11221 fctl = (hdr->fh_f_ctl[0] << 16 |
11216 hdr->fh_f_ctl[1] << 8 | 11222 hdr->fh_f_ctl[1] << 8 |
@@ -11242,6 +11248,7 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf)
11242 struct lpfc_iocbq *first_iocbq, *iocbq; 11248 struct lpfc_iocbq *first_iocbq, *iocbq;
11243 struct fc_frame_header *fc_hdr; 11249 struct fc_frame_header *fc_hdr;
11244 uint32_t sid; 11250 uint32_t sid;
11251 struct ulp_bde64 *pbde;
11245 11252
11246 fc_hdr = (struct fc_frame_header *)seq_dmabuf->hbuf.virt; 11253 fc_hdr = (struct fc_frame_header *)seq_dmabuf->hbuf.virt;
11247 /* remove from receive buffer list */ 11254 /* remove from receive buffer list */
@@ -11283,8 +11290,9 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf)
11283 if (!iocbq->context3) { 11290 if (!iocbq->context3) {
11284 iocbq->context3 = d_buf; 11291 iocbq->context3 = d_buf;
11285 iocbq->iocb.ulpBdeCount++; 11292 iocbq->iocb.ulpBdeCount++;
11286 iocbq->iocb.unsli3.rcvsli3.bde2.tus.f.bdeSize = 11293 pbde = (struct ulp_bde64 *)
11287 LPFC_DATA_BUF_SIZE; 11294 &iocbq->iocb.unsli3.sli3Words[4];
11295 pbde->tus.f.bdeSize = LPFC_DATA_BUF_SIZE;
11288 first_iocbq->iocb.unsli3.rcvsli3.acc_len += 11296 first_iocbq->iocb.unsli3.rcvsli3.acc_len +=
11289 bf_get(lpfc_rcqe_length, 11297 bf_get(lpfc_rcqe_length,
11290 &seq_dmabuf->cq_event.cqe.rcqe_cmpl); 11298 &seq_dmabuf->cq_event.cqe.rcqe_cmpl);
@@ -11407,7 +11415,6 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba,
11407 * frame to be freed when it is finished. 11415 * frame to be freed when it is finished.
11408 **/ 11416 **/
11409 lpfc_sli_hbqbuf_fill_hbqs(phba, LPFC_ELS_HBQ, 1); 11417 lpfc_sli_hbqbuf_fill_hbqs(phba, LPFC_ELS_HBQ, 1);
11410 dmabuf->tag = -1;
11411 return; 11418 return;
11412 } 11419 }
11413 /* Send the complete sequence to the upper layer protocol */ 11420 /* Send the complete sequence to the upper layer protocol */