[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>
This commit is contained in:
parent
91e6ecada7
commit
eeead81152
|
@ -1013,7 +1013,7 @@ struct lpfc_mbx_wq_destroy {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define LPFC_HDR_BUF_SIZE 128
|
#define LPFC_HDR_BUF_SIZE 128
|
||||||
#define LPFC_DATA_BUF_SIZE 4096
|
#define LPFC_DATA_BUF_SIZE 2048
|
||||||
struct rq_context {
|
struct rq_context {
|
||||||
uint32_t word0;
|
uint32_t word0;
|
||||||
#define lpfc_rq_context_rq_size_SHIFT 16
|
#define lpfc_rq_context_rq_size_SHIFT 16
|
||||||
|
|
|
@ -5848,7 +5848,6 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
|
||||||
iocbq->iocb.un.ulpWord[3]);
|
iocbq->iocb.un.ulpWord[3]);
|
||||||
wqe->generic.word3 = 0;
|
wqe->generic.word3 = 0;
|
||||||
bf_set(wqe_rcvoxid, &wqe->generic, iocbq->iocb.ulpContext);
|
bf_set(wqe_rcvoxid, &wqe->generic, iocbq->iocb.ulpContext);
|
||||||
bf_set(wqe_xc, &wqe->generic, 1);
|
|
||||||
/* The entire sequence is transmitted for this IOCB */
|
/* The entire sequence is transmitted for this IOCB */
|
||||||
xmit_len = total_len;
|
xmit_len = total_len;
|
||||||
cmnd = CMD_XMIT_SEQUENCE64_CR;
|
cmnd = CMD_XMIT_SEQUENCE64_CR;
|
||||||
|
@ -10944,7 +10943,8 @@ lpfc_fc_frame_add(struct lpfc_vport *vport, struct hbq_dmabuf *dmabuf)
|
||||||
return dmabuf;
|
return dmabuf;
|
||||||
}
|
}
|
||||||
temp_hdr = seq_dmabuf->hbuf.virt;
|
temp_hdr = seq_dmabuf->hbuf.virt;
|
||||||
if (new_hdr->fh_seq_cnt < temp_hdr->fh_seq_cnt) {
|
if (be16_to_cpu(new_hdr->fh_seq_cnt) <
|
||||||
|
be16_to_cpu(temp_hdr->fh_seq_cnt)) {
|
||||||
list_del_init(&seq_dmabuf->hbuf.list);
|
list_del_init(&seq_dmabuf->hbuf.list);
|
||||||
list_add_tail(&dmabuf->hbuf.list, &vport->rcv_buffer_list);
|
list_add_tail(&dmabuf->hbuf.list, &vport->rcv_buffer_list);
|
||||||
list_add_tail(&dmabuf->dbuf.list, &seq_dmabuf->dbuf.list);
|
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)
|
||||||
list_move_tail(&seq_dmabuf->hbuf.list, &vport->rcv_buffer_list);
|
list_move_tail(&seq_dmabuf->hbuf.list, &vport->rcv_buffer_list);
|
||||||
seq_dmabuf->time_stamp = jiffies;
|
seq_dmabuf->time_stamp = jiffies;
|
||||||
lpfc_update_rcv_time_stamp(vport);
|
lpfc_update_rcv_time_stamp(vport);
|
||||||
|
if (list_empty(&seq_dmabuf->dbuf.list)) {
|
||||||
|
temp_hdr = dmabuf->hbuf.virt;
|
||||||
|
list_add_tail(&dmabuf->dbuf.list, &seq_dmabuf->dbuf.list);
|
||||||
|
return seq_dmabuf;
|
||||||
|
}
|
||||||
/* find the correct place in the sequence to insert this frame */
|
/* find the correct place in the sequence to insert this frame */
|
||||||
list_for_each_entry_reverse(d_buf, &seq_dmabuf->dbuf.list, list) {
|
list_for_each_entry_reverse(d_buf, &seq_dmabuf->dbuf.list, list) {
|
||||||
temp_dmabuf = container_of(d_buf, struct hbq_dmabuf, dbuf);
|
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)
|
||||||
* If the frame's sequence count is greater than the frame on
|
* If the frame's sequence count is greater than the frame on
|
||||||
* the list then insert the frame right after this frame
|
* the list then insert the frame right after this frame
|
||||||
*/
|
*/
|
||||||
if (new_hdr->fh_seq_cnt > temp_hdr->fh_seq_cnt) {
|
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);
|
list_add(&dmabuf->dbuf.list, &temp_dmabuf->dbuf.list);
|
||||||
return seq_dmabuf;
|
return seq_dmabuf;
|
||||||
}
|
}
|
||||||
|
@ -11210,7 +11216,7 @@ lpfc_seq_complete(struct hbq_dmabuf *dmabuf)
|
||||||
seq_dmabuf = container_of(d_buf, struct hbq_dmabuf, dbuf);
|
seq_dmabuf = container_of(d_buf, struct hbq_dmabuf, dbuf);
|
||||||
hdr = (struct fc_frame_header *)seq_dmabuf->hbuf.virt;
|
hdr = (struct fc_frame_header *)seq_dmabuf->hbuf.virt;
|
||||||
/* If there is a hole in the sequence count then fail. */
|
/* If there is a hole in the sequence count then fail. */
|
||||||
if (++seq_count != hdr->fh_seq_cnt)
|
if (++seq_count != be16_to_cpu(hdr->fh_seq_cnt))
|
||||||
return 0;
|
return 0;
|
||||||
fctl = (hdr->fh_f_ctl[0] << 16 |
|
fctl = (hdr->fh_f_ctl[0] << 16 |
|
||||||
hdr->fh_f_ctl[1] << 8 |
|
hdr->fh_f_ctl[1] << 8 |
|
||||||
|
@ -11242,6 +11248,7 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf)
|
||||||
struct lpfc_iocbq *first_iocbq, *iocbq;
|
struct lpfc_iocbq *first_iocbq, *iocbq;
|
||||||
struct fc_frame_header *fc_hdr;
|
struct fc_frame_header *fc_hdr;
|
||||||
uint32_t sid;
|
uint32_t sid;
|
||||||
|
struct ulp_bde64 *pbde;
|
||||||
|
|
||||||
fc_hdr = (struct fc_frame_header *)seq_dmabuf->hbuf.virt;
|
fc_hdr = (struct fc_frame_header *)seq_dmabuf->hbuf.virt;
|
||||||
/* remove from receive buffer list */
|
/* remove from receive buffer list */
|
||||||
|
@ -11283,8 +11290,9 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf)
|
||||||
if (!iocbq->context3) {
|
if (!iocbq->context3) {
|
||||||
iocbq->context3 = d_buf;
|
iocbq->context3 = d_buf;
|
||||||
iocbq->iocb.ulpBdeCount++;
|
iocbq->iocb.ulpBdeCount++;
|
||||||
iocbq->iocb.unsli3.rcvsli3.bde2.tus.f.bdeSize =
|
pbde = (struct ulp_bde64 *)
|
||||||
LPFC_DATA_BUF_SIZE;
|
&iocbq->iocb.unsli3.sli3Words[4];
|
||||||
|
pbde->tus.f.bdeSize = LPFC_DATA_BUF_SIZE;
|
||||||
first_iocbq->iocb.unsli3.rcvsli3.acc_len +=
|
first_iocbq->iocb.unsli3.rcvsli3.acc_len +=
|
||||||
bf_get(lpfc_rcqe_length,
|
bf_get(lpfc_rcqe_length,
|
||||||
&seq_dmabuf->cq_event.cqe.rcqe_cmpl);
|
&seq_dmabuf->cq_event.cqe.rcqe_cmpl);
|
||||||
|
@ -11407,7 +11415,6 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba,
|
||||||
* frame to be freed when it is finished.
|
* frame to be freed when it is finished.
|
||||||
**/
|
**/
|
||||||
lpfc_sli_hbqbuf_fill_hbqs(phba, LPFC_ELS_HBQ, 1);
|
lpfc_sli_hbqbuf_fill_hbqs(phba, LPFC_ELS_HBQ, 1);
|
||||||
dmabuf->tag = -1;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* Send the complete sequence to the upper layer protocol */
|
/* Send the complete sequence to the upper layer protocol */
|
||||||
|
|
Loading…
Reference in New Issue