diff options
author | Joe Eykholt <jeykholt@cisco.com> | 2010-07-20 18:21:12 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-07-28 10:06:02 -0400 |
commit | 922611569572d3c1aa0ed6491d21583fb3fcca22 (patch) | |
tree | f7cb42bf5519d1c42853808f2f784188afe1bc2e /drivers/scsi/libfc/fc_exch.c | |
parent | 239e81048b7dcd27448db40c845f88ac7c68424e (diff) |
[SCSI] libfc: don't require a local exchange for incoming requests
Incoming requests shouldn't require a local exchange if we're
just going to reply with one or two frames and don't expect
anything further. Don't allocate exchanges for such requests
until requested by the upper-layer protocol.
The sequence is always NULL for new requests, so remove
that as an argument to request handlers.
Also change the first argument to lport->tt.seq_els_rsp_send
from the sequence pointer to the received frame pointer, to
supply the exchange IDs and destination ID info.
Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/libfc/fc_exch.c')
-rw-r--r-- | drivers/scsi/libfc/fc_exch.c | 188 |
1 files changed, 100 insertions, 88 deletions
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 027042a6de3b..b8560ad8cf66 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c | |||
@@ -129,11 +129,11 @@ struct fc_exch_mgr_anchor { | |||
129 | }; | 129 | }; |
130 | 130 | ||
131 | static void fc_exch_rrq(struct fc_exch *); | 131 | static void fc_exch_rrq(struct fc_exch *); |
132 | static void fc_seq_ls_acc(struct fc_seq *); | 132 | static void fc_seq_ls_acc(struct fc_frame *); |
133 | static void fc_seq_ls_rjt(struct fc_seq *, enum fc_els_rjt_reason, | 133 | static void fc_seq_ls_rjt(struct fc_frame *, enum fc_els_rjt_reason, |
134 | enum fc_els_rjt_explan); | 134 | enum fc_els_rjt_explan); |
135 | static void fc_exch_els_rec(struct fc_seq *, struct fc_frame *); | 135 | static void fc_exch_els_rec(struct fc_frame *); |
136 | static void fc_exch_els_rrq(struct fc_seq *, struct fc_frame *); | 136 | static void fc_exch_els_rrq(struct fc_frame *); |
137 | 137 | ||
138 | /* | 138 | /* |
139 | * Internal implementation notes. | 139 | * Internal implementation notes. |
@@ -1003,28 +1003,30 @@ static void fc_exch_set_addr(struct fc_exch *ep, | |||
1003 | /** | 1003 | /** |
1004 | * fc_seq_els_rsp_send() - Send an ELS response using infomation from | 1004 | * fc_seq_els_rsp_send() - Send an ELS response using infomation from |
1005 | * the existing sequence/exchange. | 1005 | * the existing sequence/exchange. |
1006 | * @sp: The sequence/exchange to get information from | 1006 | * @fp: The received frame |
1007 | * @els_cmd: The ELS command to be sent | 1007 | * @els_cmd: The ELS command to be sent |
1008 | * @els_data: The ELS data to be sent | 1008 | * @els_data: The ELS data to be sent |
1009 | * | ||
1010 | * The received frame is not freed. | ||
1009 | */ | 1011 | */ |
1010 | static void fc_seq_els_rsp_send(struct fc_seq *sp, enum fc_els_cmd els_cmd, | 1012 | static void fc_seq_els_rsp_send(struct fc_frame *fp, enum fc_els_cmd els_cmd, |
1011 | struct fc_seq_els_data *els_data) | 1013 | struct fc_seq_els_data *els_data) |
1012 | { | 1014 | { |
1013 | switch (els_cmd) { | 1015 | switch (els_cmd) { |
1014 | case ELS_LS_RJT: | 1016 | case ELS_LS_RJT: |
1015 | fc_seq_ls_rjt(sp, els_data->reason, els_data->explan); | 1017 | fc_seq_ls_rjt(fp, els_data->reason, els_data->explan); |
1016 | break; | 1018 | break; |
1017 | case ELS_LS_ACC: | 1019 | case ELS_LS_ACC: |
1018 | fc_seq_ls_acc(sp); | 1020 | fc_seq_ls_acc(fp); |
1019 | break; | 1021 | break; |
1020 | case ELS_RRQ: | 1022 | case ELS_RRQ: |
1021 | fc_exch_els_rrq(sp, els_data->fp); | 1023 | fc_exch_els_rrq(fp); |
1022 | break; | 1024 | break; |
1023 | case ELS_REC: | 1025 | case ELS_REC: |
1024 | fc_exch_els_rec(sp, els_data->fp); | 1026 | fc_exch_els_rec(fp); |
1025 | break; | 1027 | break; |
1026 | default: | 1028 | default: |
1027 | FC_EXCH_DBG(fc_seq_exch(sp), "Invalid ELS CMD:%x\n", els_cmd); | 1029 | FC_LPORT_DBG(fr_dev(fp), "Invalid ELS CMD:%x\n", els_cmd); |
1028 | } | 1030 | } |
1029 | } | 1031 | } |
1030 | 1032 | ||
@@ -1253,11 +1255,13 @@ static struct fc_seq *fc_seq_assign(struct fc_lport *lport, struct fc_frame *fp) | |||
1253 | } | 1255 | } |
1254 | 1256 | ||
1255 | /** | 1257 | /** |
1256 | * fc_exch_recv_req() - Handler for an incoming request where is other | 1258 | * fc_exch_recv_req() - Handler for an incoming request |
1257 | * end is originating the sequence | ||
1258 | * @lport: The local port that received the request | 1259 | * @lport: The local port that received the request |
1259 | * @mp: The EM that the exchange is on | 1260 | * @mp: The EM that the exchange is on |
1260 | * @fp: The request frame | 1261 | * @fp: The request frame |
1262 | * | ||
1263 | * This is used when the other end is originating the exchange | ||
1264 | * and the sequence. | ||
1261 | */ | 1265 | */ |
1262 | static void fc_exch_recv_req(struct fc_lport *lport, struct fc_exch_mgr *mp, | 1266 | static void fc_exch_recv_req(struct fc_lport *lport, struct fc_exch_mgr *mp, |
1263 | struct fc_frame *fp) | 1267 | struct fc_frame *fp) |
@@ -1275,8 +1279,17 @@ static void fc_exch_recv_req(struct fc_lport *lport, struct fc_exch_mgr *mp, | |||
1275 | fc_frame_free(fp); | 1279 | fc_frame_free(fp); |
1276 | return; | 1280 | return; |
1277 | } | 1281 | } |
1282 | fr_dev(fp) = lport; | ||
1283 | |||
1284 | BUG_ON(fr_seq(fp)); /* XXX remove later */ | ||
1285 | |||
1286 | /* | ||
1287 | * If the RX_ID is 0xffff, don't allocate an exchange. | ||
1288 | * The upper-level protocol may request one later, if needed. | ||
1289 | */ | ||
1290 | if (fh->fh_rx_id == htons(FC_XID_UNKNOWN)) | ||
1291 | return lport->tt.lport_recv(lport, fp); | ||
1278 | 1292 | ||
1279 | fr_seq(fp) = NULL; | ||
1280 | reject = fc_seq_lookup_recip(lport, mp, fp); | 1293 | reject = fc_seq_lookup_recip(lport, mp, fp); |
1281 | if (reject == FC_RJT_NONE) { | 1294 | if (reject == FC_RJT_NONE) { |
1282 | sp = fr_seq(fp); /* sequence will be held */ | 1295 | sp = fr_seq(fp); /* sequence will be held */ |
@@ -1298,7 +1311,7 @@ static void fc_exch_recv_req(struct fc_lport *lport, struct fc_exch_mgr *mp, | |||
1298 | if (ep->resp) | 1311 | if (ep->resp) |
1299 | ep->resp(sp, fp, ep->arg); | 1312 | ep->resp(sp, fp, ep->arg); |
1300 | else | 1313 | else |
1301 | lport->tt.lport_recv(lport, sp, fp); | 1314 | lport->tt.lport_recv(lport, fp); |
1302 | fc_exch_release(ep); /* release from lookup */ | 1315 | fc_exch_release(ep); /* release from lookup */ |
1303 | } else { | 1316 | } else { |
1304 | FC_LPORT_DBG(lport, "exch/seq lookup failed: reject %x\n", | 1317 | FC_LPORT_DBG(lport, "exch/seq lookup failed: reject %x\n", |
@@ -1566,53 +1579,55 @@ static void fc_exch_recv_bls(struct fc_exch_mgr *mp, struct fc_frame *fp) | |||
1566 | 1579 | ||
1567 | /** | 1580 | /** |
1568 | * fc_seq_ls_acc() - Accept sequence with LS_ACC | 1581 | * fc_seq_ls_acc() - Accept sequence with LS_ACC |
1569 | * @req_sp: The request sequence | 1582 | * @rx_fp: The received frame, not freed here. |
1570 | * | 1583 | * |
1571 | * If this fails due to allocation or transmit congestion, assume the | 1584 | * If this fails due to allocation or transmit congestion, assume the |
1572 | * originator will repeat the sequence. | 1585 | * originator will repeat the sequence. |
1573 | */ | 1586 | */ |
1574 | static void fc_seq_ls_acc(struct fc_seq *req_sp) | 1587 | static void fc_seq_ls_acc(struct fc_frame *rx_fp) |
1575 | { | 1588 | { |
1576 | struct fc_seq *sp; | 1589 | struct fc_lport *lport; |
1577 | struct fc_els_ls_acc *acc; | 1590 | struct fc_els_ls_acc *acc; |
1578 | struct fc_frame *fp; | 1591 | struct fc_frame *fp; |
1579 | 1592 | ||
1580 | sp = fc_seq_start_next(req_sp); | 1593 | lport = fr_dev(rx_fp); |
1581 | fp = fc_frame_alloc(fc_seq_exch(sp)->lp, sizeof(*acc)); | 1594 | fp = fc_frame_alloc(lport, sizeof(*acc)); |
1582 | if (fp) { | 1595 | if (!fp) |
1583 | acc = fc_frame_payload_get(fp, sizeof(*acc)); | 1596 | return; |
1584 | memset(acc, 0, sizeof(*acc)); | 1597 | acc = fc_frame_payload_get(fp, sizeof(*acc)); |
1585 | acc->la_cmd = ELS_LS_ACC; | 1598 | memset(acc, 0, sizeof(*acc)); |
1586 | fc_seq_send_last(sp, fp, FC_RCTL_ELS_REP, FC_TYPE_ELS); | 1599 | acc->la_cmd = ELS_LS_ACC; |
1587 | } | 1600 | fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0); |
1601 | lport->tt.frame_send(lport, fp); | ||
1588 | } | 1602 | } |
1589 | 1603 | ||
1590 | /** | 1604 | /** |
1591 | * fc_seq_ls_rjt() - Reject a sequence with ELS LS_RJT | 1605 | * fc_seq_ls_rjt() - Reject a sequence with ELS LS_RJT |
1592 | * @req_sp: The request sequence | 1606 | * @rx_fp: The received frame, not freed here. |
1593 | * @reason: The reason the sequence is being rejected | 1607 | * @reason: The reason the sequence is being rejected |
1594 | * @explan: The explaination for the rejection | 1608 | * @explan: The explanation for the rejection |
1595 | * | 1609 | * |
1596 | * If this fails due to allocation or transmit congestion, assume the | 1610 | * If this fails due to allocation or transmit congestion, assume the |
1597 | * originator will repeat the sequence. | 1611 | * originator will repeat the sequence. |
1598 | */ | 1612 | */ |
1599 | static void fc_seq_ls_rjt(struct fc_seq *req_sp, enum fc_els_rjt_reason reason, | 1613 | static void fc_seq_ls_rjt(struct fc_frame *rx_fp, enum fc_els_rjt_reason reason, |
1600 | enum fc_els_rjt_explan explan) | 1614 | enum fc_els_rjt_explan explan) |
1601 | { | 1615 | { |
1602 | struct fc_seq *sp; | 1616 | struct fc_lport *lport; |
1603 | struct fc_els_ls_rjt *rjt; | 1617 | struct fc_els_ls_rjt *rjt; |
1604 | struct fc_frame *fp; | 1618 | struct fc_frame *fp; |
1605 | 1619 | ||
1606 | sp = fc_seq_start_next(req_sp); | 1620 | lport = fr_dev(rx_fp); |
1607 | fp = fc_frame_alloc(fc_seq_exch(sp)->lp, sizeof(*rjt)); | 1621 | fp = fc_frame_alloc(lport, sizeof(*rjt)); |
1608 | if (fp) { | 1622 | if (!fp) |
1609 | rjt = fc_frame_payload_get(fp, sizeof(*rjt)); | 1623 | return; |
1610 | memset(rjt, 0, sizeof(*rjt)); | 1624 | rjt = fc_frame_payload_get(fp, sizeof(*rjt)); |
1611 | rjt->er_cmd = ELS_LS_RJT; | 1625 | memset(rjt, 0, sizeof(*rjt)); |
1612 | rjt->er_reason = reason; | 1626 | rjt->er_cmd = ELS_LS_RJT; |
1613 | rjt->er_explan = explan; | 1627 | rjt->er_reason = reason; |
1614 | fc_seq_send_last(sp, fp, FC_RCTL_ELS_REP, FC_TYPE_ELS); | 1628 | rjt->er_explan = explan; |
1615 | } | 1629 | fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0); |
1630 | lport->tt.frame_send(lport, fp); | ||
1616 | } | 1631 | } |
1617 | 1632 | ||
1618 | /** | 1633 | /** |
@@ -1715,17 +1730,33 @@ void fc_exch_mgr_reset(struct fc_lport *lport, u32 sid, u32 did) | |||
1715 | EXPORT_SYMBOL(fc_exch_mgr_reset); | 1730 | EXPORT_SYMBOL(fc_exch_mgr_reset); |
1716 | 1731 | ||
1717 | /** | 1732 | /** |
1733 | * fc_exch_lookup() - find an exchange | ||
1734 | * @lport: The local port | ||
1735 | * @xid: The exchange ID | ||
1736 | * | ||
1737 | * Returns exchange pointer with hold for caller, or NULL if not found. | ||
1738 | */ | ||
1739 | static struct fc_exch *fc_exch_lookup(struct fc_lport *lport, u32 xid) | ||
1740 | { | ||
1741 | struct fc_exch_mgr_anchor *ema; | ||
1742 | |||
1743 | list_for_each_entry(ema, &lport->ema_list, ema_list) | ||
1744 | if (ema->mp->min_xid <= xid && xid <= ema->mp->max_xid) | ||
1745 | return fc_exch_find(ema->mp, xid); | ||
1746 | return NULL; | ||
1747 | } | ||
1748 | |||
1749 | /** | ||
1718 | * fc_exch_els_rec() - Handler for ELS REC (Read Exchange Concise) requests | 1750 | * fc_exch_els_rec() - Handler for ELS REC (Read Exchange Concise) requests |
1719 | * @sp: The sequence the REC is on | 1751 | * @rfp: The REC frame, not freed here. |
1720 | * @rfp: The REC frame | ||
1721 | * | 1752 | * |
1722 | * Note that the requesting port may be different than the S_ID in the request. | 1753 | * Note that the requesting port may be different than the S_ID in the request. |
1723 | */ | 1754 | */ |
1724 | static void fc_exch_els_rec(struct fc_seq *sp, struct fc_frame *rfp) | 1755 | static void fc_exch_els_rec(struct fc_frame *rfp) |
1725 | { | 1756 | { |
1757 | struct fc_lport *lport; | ||
1726 | struct fc_frame *fp; | 1758 | struct fc_frame *fp; |
1727 | struct fc_exch *ep; | 1759 | struct fc_exch *ep; |
1728 | struct fc_exch_mgr *em; | ||
1729 | struct fc_els_rec *rp; | 1760 | struct fc_els_rec *rp; |
1730 | struct fc_els_rec_acc *acc; | 1761 | struct fc_els_rec_acc *acc; |
1731 | enum fc_els_rjt_reason reason = ELS_RJT_LOGIC; | 1762 | enum fc_els_rjt_reason reason = ELS_RJT_LOGIC; |
@@ -1734,6 +1765,7 @@ static void fc_exch_els_rec(struct fc_seq *sp, struct fc_frame *rfp) | |||
1734 | u16 rxid; | 1765 | u16 rxid; |
1735 | u16 oxid; | 1766 | u16 oxid; |
1736 | 1767 | ||
1768 | lport = fr_dev(rfp); | ||
1737 | rp = fc_frame_payload_get(rfp, sizeof(*rp)); | 1769 | rp = fc_frame_payload_get(rfp, sizeof(*rp)); |
1738 | explan = ELS_EXPL_INV_LEN; | 1770 | explan = ELS_EXPL_INV_LEN; |
1739 | if (!rp) | 1771 | if (!rp) |
@@ -1742,35 +1774,19 @@ static void fc_exch_els_rec(struct fc_seq *sp, struct fc_frame *rfp) | |||
1742 | rxid = ntohs(rp->rec_rx_id); | 1774 | rxid = ntohs(rp->rec_rx_id); |
1743 | oxid = ntohs(rp->rec_ox_id); | 1775 | oxid = ntohs(rp->rec_ox_id); |
1744 | 1776 | ||
1745 | /* | 1777 | ep = fc_exch_lookup(lport, |
1746 | * Currently it's hard to find the local S_ID from the exchange | 1778 | sid == fc_host_port_id(lport->host) ? oxid : rxid); |
1747 | * manager. This will eventually be fixed, but for now it's easier | ||
1748 | * to lookup the subject exchange twice, once as if we were | ||
1749 | * the initiator, and then again if we weren't. | ||
1750 | */ | ||
1751 | em = fc_seq_exch(sp)->em; | ||
1752 | ep = fc_exch_find(em, oxid); | ||
1753 | explan = ELS_EXPL_OXID_RXID; | 1779 | explan = ELS_EXPL_OXID_RXID; |
1754 | if (ep && ep->oid == sid) { | 1780 | if (!ep) |
1755 | if (ep->rxid != FC_XID_UNKNOWN && | 1781 | goto reject; |
1756 | rxid != FC_XID_UNKNOWN && | 1782 | if (ep->oid != sid || oxid != ep->oxid) |
1757 | ep->rxid != rxid) | 1783 | goto rel; |
1758 | goto rel; | 1784 | if (rxid != FC_XID_UNKNOWN && rxid != ep->rxid) |
1759 | } else { | 1785 | goto rel; |
1760 | if (ep) | 1786 | fp = fc_frame_alloc(lport, sizeof(*acc)); |
1761 | fc_exch_release(ep); | 1787 | if (!fp) |
1762 | ep = NULL; | ||
1763 | if (rxid != FC_XID_UNKNOWN) | ||
1764 | ep = fc_exch_find(em, rxid); | ||
1765 | if (!ep) | ||
1766 | goto reject; | ||
1767 | } | ||
1768 | |||
1769 | fp = fc_frame_alloc(fc_seq_exch(sp)->lp, sizeof(*acc)); | ||
1770 | if (!fp) { | ||
1771 | fc_exch_done(sp); | ||
1772 | goto out; | 1788 | goto out; |
1773 | } | 1789 | |
1774 | acc = fc_frame_payload_get(fp, sizeof(*acc)); | 1790 | acc = fc_frame_payload_get(fp, sizeof(*acc)); |
1775 | memset(acc, 0, sizeof(*acc)); | 1791 | memset(acc, 0, sizeof(*acc)); |
1776 | acc->reca_cmd = ELS_LS_ACC; | 1792 | acc->reca_cmd = ELS_LS_ACC; |
@@ -1785,18 +1801,16 @@ static void fc_exch_els_rec(struct fc_seq *sp, struct fc_frame *rfp) | |||
1785 | acc->reca_e_stat = htonl(ep->esb_stat & (ESB_ST_RESP | | 1801 | acc->reca_e_stat = htonl(ep->esb_stat & (ESB_ST_RESP | |
1786 | ESB_ST_SEQ_INIT | | 1802 | ESB_ST_SEQ_INIT | |
1787 | ESB_ST_COMPLETE)); | 1803 | ESB_ST_COMPLETE)); |
1788 | sp = fc_seq_start_next(sp); | 1804 | fc_fill_reply_hdr(fp, rfp, FC_RCTL_ELS_REP, 0); |
1789 | fc_seq_send_last(sp, fp, FC_RCTL_ELS_REP, FC_TYPE_ELS); | 1805 | lport->tt.frame_send(lport, fp); |
1790 | out: | 1806 | out: |
1791 | fc_exch_release(ep); | 1807 | fc_exch_release(ep); |
1792 | fc_frame_free(rfp); | ||
1793 | return; | 1808 | return; |
1794 | 1809 | ||
1795 | rel: | 1810 | rel: |
1796 | fc_exch_release(ep); | 1811 | fc_exch_release(ep); |
1797 | reject: | 1812 | reject: |
1798 | fc_seq_ls_rjt(sp, reason, explan); | 1813 | fc_seq_ls_rjt(rfp, reason, explan); |
1799 | fc_frame_free(rfp); | ||
1800 | } | 1814 | } |
1801 | 1815 | ||
1802 | /** | 1816 | /** |
@@ -1971,20 +1985,20 @@ retry: | |||
1971 | spin_unlock_bh(&ep->ex_lock); | 1985 | spin_unlock_bh(&ep->ex_lock); |
1972 | } | 1986 | } |
1973 | 1987 | ||
1974 | |||
1975 | /** | 1988 | /** |
1976 | * fc_exch_els_rrq() - Handler for ELS RRQ (Reset Recovery Qualifier) requests | 1989 | * fc_exch_els_rrq() - Handler for ELS RRQ (Reset Recovery Qualifier) requests |
1977 | * @sp: The sequence that the RRQ is on | 1990 | * @fp: The RRQ frame, not freed here. |
1978 | * @fp: The RRQ frame | ||
1979 | */ | 1991 | */ |
1980 | static void fc_exch_els_rrq(struct fc_seq *sp, struct fc_frame *fp) | 1992 | static void fc_exch_els_rrq(struct fc_frame *fp) |
1981 | { | 1993 | { |
1994 | struct fc_lport *lport; | ||
1982 | struct fc_exch *ep = NULL; /* request or subject exchange */ | 1995 | struct fc_exch *ep = NULL; /* request or subject exchange */ |
1983 | struct fc_els_rrq *rp; | 1996 | struct fc_els_rrq *rp; |
1984 | u32 sid; | 1997 | u32 sid; |
1985 | u16 xid; | 1998 | u16 xid; |
1986 | enum fc_els_rjt_explan explan; | 1999 | enum fc_els_rjt_explan explan; |
1987 | 2000 | ||
2001 | lport = fr_dev(fp); | ||
1988 | rp = fc_frame_payload_get(fp, sizeof(*rp)); | 2002 | rp = fc_frame_payload_get(fp, sizeof(*rp)); |
1989 | explan = ELS_EXPL_INV_LEN; | 2003 | explan = ELS_EXPL_INV_LEN; |
1990 | if (!rp) | 2004 | if (!rp) |
@@ -1993,11 +2007,10 @@ static void fc_exch_els_rrq(struct fc_seq *sp, struct fc_frame *fp) | |||
1993 | /* | 2007 | /* |
1994 | * lookup subject exchange. | 2008 | * lookup subject exchange. |
1995 | */ | 2009 | */ |
1996 | ep = fc_seq_exch(sp); | ||
1997 | sid = ntoh24(rp->rrq_s_id); /* subject source */ | 2010 | sid = ntoh24(rp->rrq_s_id); /* subject source */ |
1998 | xid = ep->did == sid ? ntohs(rp->rrq_ox_id) : ntohs(rp->rrq_rx_id); | 2011 | xid = fc_host_port_id(lport->host) == sid ? |
1999 | ep = fc_exch_find(ep->em, xid); | 2012 | ntohs(rp->rrq_ox_id) : ntohs(rp->rrq_rx_id); |
2000 | 2013 | ep = fc_exch_lookup(lport, xid); | |
2001 | explan = ELS_EXPL_OXID_RXID; | 2014 | explan = ELS_EXPL_OXID_RXID; |
2002 | if (!ep) | 2015 | if (!ep) |
2003 | goto reject; | 2016 | goto reject; |
@@ -2028,15 +2041,14 @@ static void fc_exch_els_rrq(struct fc_seq *sp, struct fc_frame *fp) | |||
2028 | /* | 2041 | /* |
2029 | * Send LS_ACC. | 2042 | * Send LS_ACC. |
2030 | */ | 2043 | */ |
2031 | fc_seq_ls_acc(sp); | 2044 | fc_seq_ls_acc(fp); |
2032 | goto out; | 2045 | goto out; |
2033 | 2046 | ||
2034 | unlock_reject: | 2047 | unlock_reject: |
2035 | spin_unlock_bh(&ep->ex_lock); | 2048 | spin_unlock_bh(&ep->ex_lock); |
2036 | reject: | 2049 | reject: |
2037 | fc_seq_ls_rjt(sp, ELS_RJT_LOGIC, explan); | 2050 | fc_seq_ls_rjt(fp, ELS_RJT_LOGIC, explan); |
2038 | out: | 2051 | out: |
2039 | fc_frame_free(fp); | ||
2040 | if (ep) | 2052 | if (ep) |
2041 | fc_exch_release(ep); /* drop hold from fc_exch_find */ | 2053 | fc_exch_release(ep); /* drop hold from fc_exch_find */ |
2042 | } | 2054 | } |
@@ -2267,7 +2279,7 @@ void fc_exch_recv(struct fc_lport *lport, struct fc_frame *fp) | |||
2267 | fc_exch_recv_seq_resp(ema->mp, fp); | 2279 | fc_exch_recv_seq_resp(ema->mp, fp); |
2268 | else if (f_ctl & FC_FC_SEQ_CTX) | 2280 | else if (f_ctl & FC_FC_SEQ_CTX) |
2269 | fc_exch_recv_resp(ema->mp, fp); | 2281 | fc_exch_recv_resp(ema->mp, fp); |
2270 | else | 2282 | else /* no EX_CTX and no SEQ_CTX */ |
2271 | fc_exch_recv_req(lport, ema->mp, fp); | 2283 | fc_exch_recv_req(lport, ema->mp, fp); |
2272 | break; | 2284 | break; |
2273 | default: | 2285 | default: |