diff options
Diffstat (limited to 'drivers/scsi/libfc')
-rw-r--r-- | drivers/scsi/libfc/fc_exch.c | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 3b8a6451ea28..f5a0665b6773 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c | |||
@@ -965,8 +965,30 @@ static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_lport *lport, | |||
965 | sp = &ep->seq; | 965 | sp = &ep->seq; |
966 | if (sp->id != fh->fh_seq_id) { | 966 | if (sp->id != fh->fh_seq_id) { |
967 | atomic_inc(&mp->stats.seq_not_found); | 967 | atomic_inc(&mp->stats.seq_not_found); |
968 | reject = FC_RJT_SEQ_ID; /* sequence/exch should exist */ | 968 | if (f_ctl & FC_FC_END_SEQ) { |
969 | goto rel; | 969 | /* |
970 | * Update sequence_id based on incoming last | ||
971 | * frame of sequence exchange. This is needed | ||
972 | * for FCoE target where DDP has been used | ||
973 | * on target where, stack is indicated only | ||
974 | * about last frame's (payload _header) header. | ||
975 | * Whereas "seq_id" which is part of | ||
976 | * frame_header is allocated by initiator | ||
977 | * which is totally different from "seq_id" | ||
978 | * allocated when XFER_RDY was sent by target. | ||
979 | * To avoid false -ve which results into not | ||
980 | * sending RSP, hence write request on other | ||
981 | * end never finishes. | ||
982 | */ | ||
983 | spin_lock_bh(&ep->ex_lock); | ||
984 | sp->ssb_stat |= SSB_ST_RESP; | ||
985 | sp->id = fh->fh_seq_id; | ||
986 | spin_unlock_bh(&ep->ex_lock); | ||
987 | } else { | ||
988 | /* sequence/exch should exist */ | ||
989 | reject = FC_RJT_SEQ_ID; | ||
990 | goto rel; | ||
991 | } | ||
970 | } | 992 | } |
971 | } | 993 | } |
972 | WARN_ON(ep != fc_seq_exch(sp)); | 994 | WARN_ON(ep != fc_seq_exch(sp)); |