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 | |
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')
-rw-r--r-- | drivers/scsi/libfc/fc_disc.c | 19 | ||||
-rw-r--r-- | drivers/scsi/libfc/fc_exch.c | 188 | ||||
-rw-r--r-- | drivers/scsi/libfc/fc_lport.c | 58 | ||||
-rw-r--r-- | drivers/scsi/libfc/fc_rport.c | 112 |
4 files changed, 165 insertions, 212 deletions
diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index 04474556f2dc..32f67c4b03fc 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c | |||
@@ -75,15 +75,13 @@ void fc_disc_stop_rports(struct fc_disc *disc) | |||
75 | 75 | ||
76 | /** | 76 | /** |
77 | * fc_disc_recv_rscn_req() - Handle Registered State Change Notification (RSCN) | 77 | * fc_disc_recv_rscn_req() - Handle Registered State Change Notification (RSCN) |
78 | * @sp: The sequence of the RSCN exchange | 78 | * @disc: The discovery object to which the RSCN applies |
79 | * @fp: The RSCN frame | 79 | * @fp: The RSCN frame |
80 | * @lport: The local port that the request will be sent on | ||
81 | * | 80 | * |
82 | * Locking Note: This function expects that the disc_mutex is locked | 81 | * Locking Note: This function expects that the disc_mutex is locked |
83 | * before it is called. | 82 | * before it is called. |
84 | */ | 83 | */ |
85 | static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp, | 84 | static void fc_disc_recv_rscn_req(struct fc_disc *disc, struct fc_frame *fp) |
86 | struct fc_disc *disc) | ||
87 | { | 85 | { |
88 | struct fc_lport *lport; | 86 | struct fc_lport *lport; |
89 | struct fc_els_rscn *rp; | 87 | struct fc_els_rscn *rp; |
@@ -151,7 +149,7 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp, | |||
151 | break; | 149 | break; |
152 | } | 150 | } |
153 | } | 151 | } |
154 | lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL); | 152 | lport->tt.seq_els_rsp_send(fp, ELS_LS_ACC, NULL); |
155 | 153 | ||
156 | /* | 154 | /* |
157 | * If not doing a complete rediscovery, do GPN_ID on | 155 | * If not doing a complete rediscovery, do GPN_ID on |
@@ -177,25 +175,22 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp, | |||
177 | return; | 175 | return; |
178 | reject: | 176 | reject: |
179 | FC_DISC_DBG(disc, "Received a bad RSCN frame\n"); | 177 | FC_DISC_DBG(disc, "Received a bad RSCN frame\n"); |
180 | rjt_data.fp = NULL; | ||
181 | rjt_data.reason = ELS_RJT_LOGIC; | 178 | rjt_data.reason = ELS_RJT_LOGIC; |
182 | rjt_data.explan = ELS_EXPL_NONE; | 179 | rjt_data.explan = ELS_EXPL_NONE; |
183 | lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); | 180 | lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &rjt_data); |
184 | fc_frame_free(fp); | 181 | fc_frame_free(fp); |
185 | } | 182 | } |
186 | 183 | ||
187 | /** | 184 | /** |
188 | * fc_disc_recv_req() - Handle incoming requests | 185 | * fc_disc_recv_req() - Handle incoming requests |
189 | * @sp: The sequence of the request exchange | ||
190 | * @fp: The request frame | ||
191 | * @lport: The local port receiving the request | 186 | * @lport: The local port receiving the request |
187 | * @fp: The request frame | ||
192 | * | 188 | * |
193 | * Locking Note: This function is called from the EM and will lock | 189 | * Locking Note: This function is called from the EM and will lock |
194 | * the disc_mutex before calling the handler for the | 190 | * the disc_mutex before calling the handler for the |
195 | * request. | 191 | * request. |
196 | */ | 192 | */ |
197 | static void fc_disc_recv_req(struct fc_seq *sp, struct fc_frame *fp, | 193 | static void fc_disc_recv_req(struct fc_lport *lport, struct fc_frame *fp) |
198 | struct fc_lport *lport) | ||
199 | { | 194 | { |
200 | u8 op; | 195 | u8 op; |
201 | struct fc_disc *disc = &lport->disc; | 196 | struct fc_disc *disc = &lport->disc; |
@@ -204,7 +199,7 @@ static void fc_disc_recv_req(struct fc_seq *sp, struct fc_frame *fp, | |||
204 | switch (op) { | 199 | switch (op) { |
205 | case ELS_RSCN: | 200 | case ELS_RSCN: |
206 | mutex_lock(&disc->disc_mutex); | 201 | mutex_lock(&disc->disc_mutex); |
207 | fc_disc_recv_rscn_req(sp, fp, disc); | 202 | fc_disc_recv_rscn_req(disc, fp); |
208 | mutex_unlock(&disc->disc_mutex); | 203 | mutex_unlock(&disc->disc_mutex); |
209 | break; | 204 | break; |
210 | default: | 205 | default: |
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: |
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index e50a6606d4bf..1998c03634da 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c | |||
@@ -375,34 +375,31 @@ static void fc_lport_add_fc4_type(struct fc_lport *lport, enum fc_fh_type type) | |||
375 | 375 | ||
376 | /** | 376 | /** |
377 | * fc_lport_recv_rlir_req() - Handle received Registered Link Incident Report. | 377 | * fc_lport_recv_rlir_req() - Handle received Registered Link Incident Report. |
378 | * @sp: The sequence in the RLIR exchange | ||
379 | * @fp: The RLIR request frame | ||
380 | * @lport: Fibre Channel local port recieving the RLIR | 378 | * @lport: Fibre Channel local port recieving the RLIR |
379 | * @fp: The RLIR request frame | ||
381 | * | 380 | * |
382 | * Locking Note: The lport lock is expected to be held before calling | 381 | * Locking Note: The lport lock is expected to be held before calling |
383 | * this function. | 382 | * this function. |
384 | */ | 383 | */ |
385 | static void fc_lport_recv_rlir_req(struct fc_seq *sp, struct fc_frame *fp, | 384 | static void fc_lport_recv_rlir_req(struct fc_lport *lport, struct fc_frame *fp) |
386 | struct fc_lport *lport) | ||
387 | { | 385 | { |
388 | FC_LPORT_DBG(lport, "Received RLIR request while in state %s\n", | 386 | FC_LPORT_DBG(lport, "Received RLIR request while in state %s\n", |
389 | fc_lport_state(lport)); | 387 | fc_lport_state(lport)); |
390 | 388 | ||
391 | lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL); | 389 | lport->tt.seq_els_rsp_send(fp, ELS_LS_ACC, NULL); |
392 | fc_frame_free(fp); | 390 | fc_frame_free(fp); |
393 | } | 391 | } |
394 | 392 | ||
395 | /** | 393 | /** |
396 | * fc_lport_recv_echo_req() - Handle received ECHO request | 394 | * fc_lport_recv_echo_req() - Handle received ECHO request |
397 | * @sp: The sequence in the ECHO exchange | ||
398 | * @fp: ECHO request frame | ||
399 | * @lport: The local port recieving the ECHO | 395 | * @lport: The local port recieving the ECHO |
396 | * @fp: ECHO request frame | ||
400 | * | 397 | * |
401 | * Locking Note: The lport lock is expected to be held before calling | 398 | * Locking Note: The lport lock is expected to be held before calling |
402 | * this function. | 399 | * this function. |
403 | */ | 400 | */ |
404 | static void fc_lport_recv_echo_req(struct fc_seq *sp, struct fc_frame *in_fp, | 401 | static void fc_lport_recv_echo_req(struct fc_lport *lport, |
405 | struct fc_lport *lport) | 402 | struct fc_frame *in_fp) |
406 | { | 403 | { |
407 | struct fc_frame *fp; | 404 | struct fc_frame *fp; |
408 | unsigned int len; | 405 | unsigned int len; |
@@ -431,15 +428,14 @@ static void fc_lport_recv_echo_req(struct fc_seq *sp, struct fc_frame *in_fp, | |||
431 | 428 | ||
432 | /** | 429 | /** |
433 | * fc_lport_recv_rnid_req() - Handle received Request Node ID data request | 430 | * fc_lport_recv_rnid_req() - Handle received Request Node ID data request |
434 | * @sp: The sequence in the RNID exchange | ||
435 | * @fp: The RNID request frame | ||
436 | * @lport: The local port recieving the RNID | 431 | * @lport: The local port recieving the RNID |
432 | * @fp: The RNID request frame | ||
437 | * | 433 | * |
438 | * Locking Note: The lport lock is expected to be held before calling | 434 | * Locking Note: The lport lock is expected to be held before calling |
439 | * this function. | 435 | * this function. |
440 | */ | 436 | */ |
441 | static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp, | 437 | static void fc_lport_recv_rnid_req(struct fc_lport *lport, |
442 | struct fc_lport *lport) | 438 | struct fc_frame *in_fp) |
443 | { | 439 | { |
444 | struct fc_frame *fp; | 440 | struct fc_frame *fp; |
445 | struct fc_els_rnid *req; | 441 | struct fc_els_rnid *req; |
@@ -457,10 +453,9 @@ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp, | |||
457 | 453 | ||
458 | req = fc_frame_payload_get(in_fp, sizeof(*req)); | 454 | req = fc_frame_payload_get(in_fp, sizeof(*req)); |
459 | if (!req) { | 455 | if (!req) { |
460 | rjt_data.fp = NULL; | ||
461 | rjt_data.reason = ELS_RJT_LOGIC; | 456 | rjt_data.reason = ELS_RJT_LOGIC; |
462 | rjt_data.explan = ELS_EXPL_NONE; | 457 | rjt_data.explan = ELS_EXPL_NONE; |
463 | lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); | 458 | lport->tt.seq_els_rsp_send(in_fp, ELS_LS_RJT, &rjt_data); |
464 | } else { | 459 | } else { |
465 | fmt = req->rnid_fmt; | 460 | fmt = req->rnid_fmt; |
466 | len = sizeof(*rp); | 461 | len = sizeof(*rp); |
@@ -492,17 +487,15 @@ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp, | |||
492 | 487 | ||
493 | /** | 488 | /** |
494 | * fc_lport_recv_logo_req() - Handle received fabric LOGO request | 489 | * fc_lport_recv_logo_req() - Handle received fabric LOGO request |
495 | * @sp: The sequence in the LOGO exchange | ||
496 | * @fp: The LOGO request frame | ||
497 | * @lport: The local port recieving the LOGO | 490 | * @lport: The local port recieving the LOGO |
491 | * @fp: The LOGO request frame | ||
498 | * | 492 | * |
499 | * Locking Note: The lport lock is exected to be held before calling | 493 | * Locking Note: The lport lock is exected to be held before calling |
500 | * this function. | 494 | * this function. |
501 | */ | 495 | */ |
502 | static void fc_lport_recv_logo_req(struct fc_seq *sp, struct fc_frame *fp, | 496 | static void fc_lport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp) |
503 | struct fc_lport *lport) | ||
504 | { | 497 | { |
505 | lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL); | 498 | lport->tt.seq_els_rsp_send(fp, ELS_LS_ACC, NULL); |
506 | fc_lport_enter_reset(lport); | 499 | fc_lport_enter_reset(lport); |
507 | fc_frame_free(fp); | 500 | fc_frame_free(fp); |
508 | } | 501 | } |
@@ -773,9 +766,8 @@ EXPORT_SYMBOL(fc_lport_set_local_id); | |||
773 | 766 | ||
774 | /** | 767 | /** |
775 | * fc_lport_recv_flogi_req() - Receive a FLOGI request | 768 | * fc_lport_recv_flogi_req() - Receive a FLOGI request |
776 | * @sp_in: The sequence the FLOGI is on | ||
777 | * @rx_fp: The FLOGI frame | ||
778 | * @lport: The local port that recieved the request | 769 | * @lport: The local port that recieved the request |
770 | * @rx_fp: The FLOGI frame | ||
779 | * | 771 | * |
780 | * A received FLOGI request indicates a point-to-point connection. | 772 | * A received FLOGI request indicates a point-to-point connection. |
781 | * Accept it with the common service parameters indicating our N port. | 773 | * Accept it with the common service parameters indicating our N port. |
@@ -784,13 +776,11 @@ EXPORT_SYMBOL(fc_lport_set_local_id); | |||
784 | * Locking Note: The lport lock is expected to be held before calling | 776 | * Locking Note: The lport lock is expected to be held before calling |
785 | * this function. | 777 | * this function. |
786 | */ | 778 | */ |
787 | static void fc_lport_recv_flogi_req(struct fc_seq *sp_in, | 779 | static void fc_lport_recv_flogi_req(struct fc_lport *lport, |
788 | struct fc_frame *rx_fp, | 780 | struct fc_frame *rx_fp) |
789 | struct fc_lport *lport) | ||
790 | { | 781 | { |
791 | struct fc_frame *fp; | 782 | struct fc_frame *fp; |
792 | struct fc_frame_header *fh; | 783 | struct fc_frame_header *fh; |
793 | struct fc_seq *sp; | ||
794 | struct fc_els_flogi *flp; | 784 | struct fc_els_flogi *flp; |
795 | struct fc_els_flogi *new_flp; | 785 | struct fc_els_flogi *new_flp; |
796 | u64 remote_wwpn; | 786 | u64 remote_wwpn; |
@@ -850,16 +840,13 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in, | |||
850 | } | 840 | } |
851 | fc_lport_ptp_setup(lport, remote_fid, remote_wwpn, | 841 | fc_lport_ptp_setup(lport, remote_fid, remote_wwpn, |
852 | get_unaligned_be64(&flp->fl_wwnn)); | 842 | get_unaligned_be64(&flp->fl_wwnn)); |
853 | |||
854 | out: | 843 | out: |
855 | sp = fr_seq(rx_fp); | ||
856 | fc_frame_free(rx_fp); | 844 | fc_frame_free(rx_fp); |
857 | } | 845 | } |
858 | 846 | ||
859 | /** | 847 | /** |
860 | * fc_lport_recv_req() - The generic lport request handler | 848 | * fc_lport_recv_req() - The generic lport request handler |
861 | * @lport: The local port that received the request | 849 | * @lport: The local port that received the request |
862 | * @sp: The sequence the request is on | ||
863 | * @fp: The request frame | 850 | * @fp: The request frame |
864 | * | 851 | * |
865 | * This function will see if the lport handles the request or | 852 | * This function will see if the lport handles the request or |
@@ -868,11 +855,10 @@ out: | |||
868 | * Locking Note: This function should not be called with the lport | 855 | * Locking Note: This function should not be called with the lport |
869 | * lock held becuase it will grab the lock. | 856 | * lock held becuase it will grab the lock. |
870 | */ | 857 | */ |
871 | static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp, | 858 | static void fc_lport_recv_req(struct fc_lport *lport, struct fc_frame *fp) |
872 | struct fc_frame *fp) | ||
873 | { | 859 | { |
874 | struct fc_frame_header *fh = fc_frame_header_get(fp); | 860 | struct fc_frame_header *fh = fc_frame_header_get(fp); |
875 | void (*recv) (struct fc_seq *, struct fc_frame *, struct fc_lport *); | 861 | void (*recv)(struct fc_lport *, struct fc_frame *); |
876 | 862 | ||
877 | mutex_lock(&lport->lp_mutex); | 863 | mutex_lock(&lport->lp_mutex); |
878 | 864 | ||
@@ -912,19 +898,13 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp, | |||
912 | break; | 898 | break; |
913 | } | 899 | } |
914 | 900 | ||
915 | recv(sp, fp, lport); | 901 | recv(lport, fp); |
916 | } else { | 902 | } else { |
917 | FC_LPORT_DBG(lport, "dropping invalid frame (eof %x)\n", | 903 | FC_LPORT_DBG(lport, "dropping invalid frame (eof %x)\n", |
918 | fr_eof(fp)); | 904 | fr_eof(fp)); |
919 | fc_frame_free(fp); | 905 | fc_frame_free(fp); |
920 | } | 906 | } |
921 | mutex_unlock(&lport->lp_mutex); | 907 | mutex_unlock(&lport->lp_mutex); |
922 | |||
923 | /* | ||
924 | * The common exch_done for all request may not be good | ||
925 | * if any request requires longer hold on exhange. XXX | ||
926 | */ | ||
927 | lport->tt.exch_done(sp); | ||
928 | } | 908 | } |
929 | 909 | ||
930 | /** | 910 | /** |
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 598795123211..25479cc7f170 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c | |||
@@ -68,14 +68,10 @@ static void fc_rport_enter_ready(struct fc_rport_priv *); | |||
68 | static void fc_rport_enter_logo(struct fc_rport_priv *); | 68 | static void fc_rport_enter_logo(struct fc_rport_priv *); |
69 | static void fc_rport_enter_adisc(struct fc_rport_priv *); | 69 | static void fc_rport_enter_adisc(struct fc_rport_priv *); |
70 | 70 | ||
71 | static void fc_rport_recv_plogi_req(struct fc_lport *, | 71 | static void fc_rport_recv_plogi_req(struct fc_lport *, struct fc_frame *); |
72 | struct fc_seq *, struct fc_frame *); | 72 | static void fc_rport_recv_prli_req(struct fc_rport_priv *, struct fc_frame *); |
73 | static void fc_rport_recv_prli_req(struct fc_rport_priv *, | 73 | static void fc_rport_recv_prlo_req(struct fc_rport_priv *, struct fc_frame *); |
74 | struct fc_seq *, struct fc_frame *); | 74 | static void fc_rport_recv_logo_req(struct fc_lport *, struct fc_frame *); |
75 | static void fc_rport_recv_prlo_req(struct fc_rport_priv *, | ||
76 | struct fc_seq *, struct fc_frame *); | ||
77 | static void fc_rport_recv_logo_req(struct fc_lport *, | ||
78 | struct fc_seq *, struct fc_frame *); | ||
79 | static void fc_rport_timeout(struct work_struct *); | 75 | static void fc_rport_timeout(struct work_struct *); |
80 | static void fc_rport_error(struct fc_rport_priv *, struct fc_frame *); | 76 | static void fc_rport_error(struct fc_rport_priv *, struct fc_frame *); |
81 | static void fc_rport_error_retry(struct fc_rport_priv *, struct fc_frame *); | 77 | static void fc_rport_error_retry(struct fc_rport_priv *, struct fc_frame *); |
@@ -736,11 +732,10 @@ static void fc_rport_enter_flogi(struct fc_rport_priv *rdata) | |||
736 | /** | 732 | /** |
737 | * fc_rport_recv_flogi_req() - Handle Fabric Login (FLOGI) request in p-mp mode | 733 | * fc_rport_recv_flogi_req() - Handle Fabric Login (FLOGI) request in p-mp mode |
738 | * @lport: The local port that received the PLOGI request | 734 | * @lport: The local port that received the PLOGI request |
739 | * @sp: The sequence that the PLOGI request was on | ||
740 | * @rx_fp: The PLOGI request frame | 735 | * @rx_fp: The PLOGI request frame |
741 | */ | 736 | */ |
742 | static void fc_rport_recv_flogi_req(struct fc_lport *lport, | 737 | static void fc_rport_recv_flogi_req(struct fc_lport *lport, |
743 | struct fc_seq *sp, struct fc_frame *rx_fp) | 738 | struct fc_frame *rx_fp) |
744 | { | 739 | { |
745 | struct fc_disc *disc; | 740 | struct fc_disc *disc; |
746 | struct fc_els_flogi *flp; | 741 | struct fc_els_flogi *flp; |
@@ -749,7 +744,6 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport, | |||
749 | struct fc_seq_els_data rjt_data; | 744 | struct fc_seq_els_data rjt_data; |
750 | u32 sid; | 745 | u32 sid; |
751 | 746 | ||
752 | rjt_data.fp = NULL; | ||
753 | sid = fc_frame_sid(fp); | 747 | sid = fc_frame_sid(fp); |
754 | 748 | ||
755 | FC_RPORT_ID_DBG(lport, sid, "Received FLOGI request\n"); | 749 | FC_RPORT_ID_DBG(lport, sid, "Received FLOGI request\n"); |
@@ -817,7 +811,6 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport, | |||
817 | if (!fp) | 811 | if (!fp) |
818 | goto out; | 812 | goto out; |
819 | 813 | ||
820 | sp = lport->tt.seq_start_next(sp); | ||
821 | fc_flogi_fill(lport, fp); | 814 | fc_flogi_fill(lport, fp); |
822 | flp = fc_frame_payload_get(fp, sizeof(*flp)); | 815 | flp = fc_frame_payload_get(fp, sizeof(*flp)); |
823 | flp->fl_cmd = ELS_LS_ACC; | 816 | flp->fl_cmd = ELS_LS_ACC; |
@@ -837,7 +830,7 @@ out: | |||
837 | 830 | ||
838 | reject: | 831 | reject: |
839 | mutex_unlock(&disc->disc_mutex); | 832 | mutex_unlock(&disc->disc_mutex); |
840 | lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); | 833 | lport->tt.seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data); |
841 | fc_frame_free(rx_fp); | 834 | fc_frame_free(rx_fp); |
842 | } | 835 | } |
843 | 836 | ||
@@ -1296,13 +1289,12 @@ static void fc_rport_enter_adisc(struct fc_rport_priv *rdata) | |||
1296 | /** | 1289 | /** |
1297 | * fc_rport_recv_adisc_req() - Handler for Address Discovery (ADISC) requests | 1290 | * fc_rport_recv_adisc_req() - Handler for Address Discovery (ADISC) requests |
1298 | * @rdata: The remote port that sent the ADISC request | 1291 | * @rdata: The remote port that sent the ADISC request |
1299 | * @sp: The sequence the ADISC request was on | ||
1300 | * @in_fp: The ADISC request frame | 1292 | * @in_fp: The ADISC request frame |
1301 | * | 1293 | * |
1302 | * Locking Note: Called with the lport and rport locks held. | 1294 | * Locking Note: Called with the lport and rport locks held. |
1303 | */ | 1295 | */ |
1304 | static void fc_rport_recv_adisc_req(struct fc_rport_priv *rdata, | 1296 | static void fc_rport_recv_adisc_req(struct fc_rport_priv *rdata, |
1305 | struct fc_seq *sp, struct fc_frame *in_fp) | 1297 | struct fc_frame *in_fp) |
1306 | { | 1298 | { |
1307 | struct fc_lport *lport = rdata->local_port; | 1299 | struct fc_lport *lport = rdata->local_port; |
1308 | struct fc_frame *fp; | 1300 | struct fc_frame *fp; |
@@ -1313,10 +1305,9 @@ static void fc_rport_recv_adisc_req(struct fc_rport_priv *rdata, | |||
1313 | 1305 | ||
1314 | adisc = fc_frame_payload_get(in_fp, sizeof(*adisc)); | 1306 | adisc = fc_frame_payload_get(in_fp, sizeof(*adisc)); |
1315 | if (!adisc) { | 1307 | if (!adisc) { |
1316 | rjt_data.fp = NULL; | ||
1317 | rjt_data.reason = ELS_RJT_PROT; | 1308 | rjt_data.reason = ELS_RJT_PROT; |
1318 | rjt_data.explan = ELS_EXPL_INV_LEN; | 1309 | rjt_data.explan = ELS_EXPL_INV_LEN; |
1319 | lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); | 1310 | lport->tt.seq_els_rsp_send(in_fp, ELS_LS_RJT, &rjt_data); |
1320 | goto drop; | 1311 | goto drop; |
1321 | } | 1312 | } |
1322 | 1313 | ||
@@ -1335,14 +1326,13 @@ drop: | |||
1335 | /** | 1326 | /** |
1336 | * fc_rport_recv_rls_req() - Handle received Read Link Status request | 1327 | * fc_rport_recv_rls_req() - Handle received Read Link Status request |
1337 | * @rdata: The remote port that sent the RLS request | 1328 | * @rdata: The remote port that sent the RLS request |
1338 | * @sp: The sequence that the RLS was on | ||
1339 | * @rx_fp: The PRLI request frame | 1329 | * @rx_fp: The PRLI request frame |
1340 | * | 1330 | * |
1341 | * Locking Note: The rport lock is expected to be held before calling | 1331 | * Locking Note: The rport lock is expected to be held before calling |
1342 | * this function. | 1332 | * this function. |
1343 | */ | 1333 | */ |
1344 | static void fc_rport_recv_rls_req(struct fc_rport_priv *rdata, | 1334 | static void fc_rport_recv_rls_req(struct fc_rport_priv *rdata, |
1345 | struct fc_seq *sp, struct fc_frame *rx_fp) | 1335 | struct fc_frame *rx_fp) |
1346 | 1336 | ||
1347 | { | 1337 | { |
1348 | struct fc_lport *lport = rdata->local_port; | 1338 | struct fc_lport *lport = rdata->local_port; |
@@ -1393,8 +1383,7 @@ static void fc_rport_recv_rls_req(struct fc_rport_priv *rdata, | |||
1393 | goto out; | 1383 | goto out; |
1394 | 1384 | ||
1395 | out_rjt: | 1385 | out_rjt: |
1396 | rjt_data.fp = NULL; | 1386 | lport->tt.seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data); |
1397 | lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); | ||
1398 | out: | 1387 | out: |
1399 | fc_frame_free(rx_fp); | 1388 | fc_frame_free(rx_fp); |
1400 | } | 1389 | } |
@@ -1402,7 +1391,6 @@ out: | |||
1402 | /** | 1391 | /** |
1403 | * fc_rport_recv_els_req() - Handler for validated ELS requests | 1392 | * fc_rport_recv_els_req() - Handler for validated ELS requests |
1404 | * @lport: The local port that received the ELS request | 1393 | * @lport: The local port that received the ELS request |
1405 | * @sp: The sequence that the ELS request was on | ||
1406 | * @fp: The ELS request frame | 1394 | * @fp: The ELS request frame |
1407 | * | 1395 | * |
1408 | * Handle incoming ELS requests that require port login. | 1396 | * Handle incoming ELS requests that require port login. |
@@ -1410,16 +1398,11 @@ out: | |||
1410 | * | 1398 | * |
1411 | * Locking Note: Called with the lport lock held. | 1399 | * Locking Note: Called with the lport lock held. |
1412 | */ | 1400 | */ |
1413 | static void fc_rport_recv_els_req(struct fc_lport *lport, | 1401 | static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp) |
1414 | struct fc_seq *sp, struct fc_frame *fp) | ||
1415 | { | 1402 | { |
1416 | struct fc_rport_priv *rdata; | 1403 | struct fc_rport_priv *rdata; |
1417 | struct fc_seq_els_data els_data; | 1404 | struct fc_seq_els_data els_data; |
1418 | 1405 | ||
1419 | els_data.fp = NULL; | ||
1420 | els_data.reason = ELS_RJT_UNAB; | ||
1421 | els_data.explan = ELS_EXPL_PLOGI_REQD; | ||
1422 | |||
1423 | mutex_lock(&lport->disc.disc_mutex); | 1406 | mutex_lock(&lport->disc.disc_mutex); |
1424 | rdata = lport->tt.rport_lookup(lport, fc_frame_sid(fp)); | 1407 | rdata = lport->tt.rport_lookup(lport, fc_frame_sid(fp)); |
1425 | if (!rdata) { | 1408 | if (!rdata) { |
@@ -1442,24 +1425,24 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, | |||
1442 | 1425 | ||
1443 | switch (fc_frame_payload_op(fp)) { | 1426 | switch (fc_frame_payload_op(fp)) { |
1444 | case ELS_PRLI: | 1427 | case ELS_PRLI: |
1445 | fc_rport_recv_prli_req(rdata, sp, fp); | 1428 | fc_rport_recv_prli_req(rdata, fp); |
1446 | break; | 1429 | break; |
1447 | case ELS_PRLO: | 1430 | case ELS_PRLO: |
1448 | fc_rport_recv_prlo_req(rdata, sp, fp); | 1431 | fc_rport_recv_prlo_req(rdata, fp); |
1449 | break; | 1432 | break; |
1450 | case ELS_ADISC: | 1433 | case ELS_ADISC: |
1451 | fc_rport_recv_adisc_req(rdata, sp, fp); | 1434 | fc_rport_recv_adisc_req(rdata, fp); |
1452 | break; | 1435 | break; |
1453 | case ELS_RRQ: | 1436 | case ELS_RRQ: |
1454 | els_data.fp = fp; | 1437 | lport->tt.seq_els_rsp_send(fp, ELS_RRQ, NULL); |
1455 | lport->tt.seq_els_rsp_send(sp, ELS_RRQ, &els_data); | 1438 | fc_frame_free(fp); |
1456 | break; | 1439 | break; |
1457 | case ELS_REC: | 1440 | case ELS_REC: |
1458 | els_data.fp = fp; | 1441 | lport->tt.seq_els_rsp_send(fp, ELS_REC, NULL); |
1459 | lport->tt.seq_els_rsp_send(sp, ELS_REC, &els_data); | 1442 | fc_frame_free(fp); |
1460 | break; | 1443 | break; |
1461 | case ELS_RLS: | 1444 | case ELS_RLS: |
1462 | fc_rport_recv_rls_req(rdata, sp, fp); | 1445 | fc_rport_recv_rls_req(rdata, fp); |
1463 | break; | 1446 | break; |
1464 | default: | 1447 | default: |
1465 | fc_frame_free(fp); /* can't happen */ | 1448 | fc_frame_free(fp); /* can't happen */ |
@@ -1470,20 +1453,20 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, | |||
1470 | return; | 1453 | return; |
1471 | 1454 | ||
1472 | reject: | 1455 | reject: |
1473 | lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &els_data); | 1456 | els_data.reason = ELS_RJT_UNAB; |
1457 | els_data.explan = ELS_EXPL_PLOGI_REQD; | ||
1458 | lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &els_data); | ||
1474 | fc_frame_free(fp); | 1459 | fc_frame_free(fp); |
1475 | } | 1460 | } |
1476 | 1461 | ||
1477 | /** | 1462 | /** |
1478 | * fc_rport_recv_req() - Handler for requests | 1463 | * fc_rport_recv_req() - Handler for requests |
1479 | * @sp: The sequence the request was on | ||
1480 | * @fp: The request frame | ||
1481 | * @lport: The local port that received the request | 1464 | * @lport: The local port that received the request |
1465 | * @fp: The request frame | ||
1482 | * | 1466 | * |
1483 | * Locking Note: Called with the lport lock held. | 1467 | * Locking Note: Called with the lport lock held. |
1484 | */ | 1468 | */ |
1485 | void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp, | 1469 | void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp) |
1486 | struct fc_lport *lport) | ||
1487 | { | 1470 | { |
1488 | struct fc_seq_els_data els_data; | 1471 | struct fc_seq_els_data els_data; |
1489 | 1472 | ||
@@ -1495,13 +1478,13 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp, | |||
1495 | */ | 1478 | */ |
1496 | switch (fc_frame_payload_op(fp)) { | 1479 | switch (fc_frame_payload_op(fp)) { |
1497 | case ELS_FLOGI: | 1480 | case ELS_FLOGI: |
1498 | fc_rport_recv_flogi_req(lport, sp, fp); | 1481 | fc_rport_recv_flogi_req(lport, fp); |
1499 | break; | 1482 | break; |
1500 | case ELS_PLOGI: | 1483 | case ELS_PLOGI: |
1501 | fc_rport_recv_plogi_req(lport, sp, fp); | 1484 | fc_rport_recv_plogi_req(lport, fp); |
1502 | break; | 1485 | break; |
1503 | case ELS_LOGO: | 1486 | case ELS_LOGO: |
1504 | fc_rport_recv_logo_req(lport, sp, fp); | 1487 | fc_rport_recv_logo_req(lport, fp); |
1505 | break; | 1488 | break; |
1506 | case ELS_PRLI: | 1489 | case ELS_PRLI: |
1507 | case ELS_PRLO: | 1490 | case ELS_PRLO: |
@@ -1509,14 +1492,13 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp, | |||
1509 | case ELS_RRQ: | 1492 | case ELS_RRQ: |
1510 | case ELS_REC: | 1493 | case ELS_REC: |
1511 | case ELS_RLS: | 1494 | case ELS_RLS: |
1512 | fc_rport_recv_els_req(lport, sp, fp); | 1495 | fc_rport_recv_els_req(lport, fp); |
1513 | break; | 1496 | break; |
1514 | default: | 1497 | default: |
1515 | fc_frame_free(fp); | ||
1516 | els_data.fp = NULL; | ||
1517 | els_data.reason = ELS_RJT_UNSUP; | 1498 | els_data.reason = ELS_RJT_UNSUP; |
1518 | els_data.explan = ELS_EXPL_NONE; | 1499 | els_data.explan = ELS_EXPL_NONE; |
1519 | lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &els_data); | 1500 | lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &els_data); |
1501 | fc_frame_free(fp); | ||
1520 | break; | 1502 | break; |
1521 | } | 1503 | } |
1522 | } | 1504 | } |
@@ -1524,13 +1506,12 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp, | |||
1524 | /** | 1506 | /** |
1525 | * fc_rport_recv_plogi_req() - Handler for Port Login (PLOGI) requests | 1507 | * fc_rport_recv_plogi_req() - Handler for Port Login (PLOGI) requests |
1526 | * @lport: The local port that received the PLOGI request | 1508 | * @lport: The local port that received the PLOGI request |
1527 | * @sp: The sequence that the PLOGI request was on | ||
1528 | * @rx_fp: The PLOGI request frame | 1509 | * @rx_fp: The PLOGI request frame |
1529 | * | 1510 | * |
1530 | * Locking Note: The rport lock is held before calling this function. | 1511 | * Locking Note: The rport lock is held before calling this function. |
1531 | */ | 1512 | */ |
1532 | static void fc_rport_recv_plogi_req(struct fc_lport *lport, | 1513 | static void fc_rport_recv_plogi_req(struct fc_lport *lport, |
1533 | struct fc_seq *sp, struct fc_frame *rx_fp) | 1514 | struct fc_frame *rx_fp) |
1534 | { | 1515 | { |
1535 | struct fc_disc *disc; | 1516 | struct fc_disc *disc; |
1536 | struct fc_rport_priv *rdata; | 1517 | struct fc_rport_priv *rdata; |
@@ -1539,7 +1520,6 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport, | |||
1539 | struct fc_seq_els_data rjt_data; | 1520 | struct fc_seq_els_data rjt_data; |
1540 | u32 sid; | 1521 | u32 sid; |
1541 | 1522 | ||
1542 | rjt_data.fp = NULL; | ||
1543 | sid = fc_frame_sid(fp); | 1523 | sid = fc_frame_sid(fp); |
1544 | 1524 | ||
1545 | FC_RPORT_ID_DBG(lport, sid, "Received PLOGI request\n"); | 1525 | FC_RPORT_ID_DBG(lport, sid, "Received PLOGI request\n"); |
@@ -1635,21 +1615,20 @@ out: | |||
1635 | return; | 1615 | return; |
1636 | 1616 | ||
1637 | reject: | 1617 | reject: |
1638 | lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); | 1618 | lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &rjt_data); |
1639 | fc_frame_free(fp); | 1619 | fc_frame_free(fp); |
1640 | } | 1620 | } |
1641 | 1621 | ||
1642 | /** | 1622 | /** |
1643 | * fc_rport_recv_prli_req() - Handler for process login (PRLI) requests | 1623 | * fc_rport_recv_prli_req() - Handler for process login (PRLI) requests |
1644 | * @rdata: The remote port that sent the PRLI request | 1624 | * @rdata: The remote port that sent the PRLI request |
1645 | * @sp: The sequence that the PRLI was on | ||
1646 | * @rx_fp: The PRLI request frame | 1625 | * @rx_fp: The PRLI request frame |
1647 | * | 1626 | * |
1648 | * Locking Note: The rport lock is exected to be held before calling | 1627 | * Locking Note: The rport lock is exected to be held before calling |
1649 | * this function. | 1628 | * this function. |
1650 | */ | 1629 | */ |
1651 | static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, | 1630 | static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, |
1652 | struct fc_seq *sp, struct fc_frame *rx_fp) | 1631 | struct fc_frame *rx_fp) |
1653 | { | 1632 | { |
1654 | struct fc_lport *lport = rdata->local_port; | 1633 | struct fc_lport *lport = rdata->local_port; |
1655 | struct fc_frame *fp; | 1634 | struct fc_frame *fp; |
@@ -1666,7 +1645,6 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, | |||
1666 | u32 fcp_parm; | 1645 | u32 fcp_parm; |
1667 | u32 roles = FC_RPORT_ROLE_UNKNOWN; | 1646 | u32 roles = FC_RPORT_ROLE_UNKNOWN; |
1668 | 1647 | ||
1669 | rjt_data.fp = NULL; | ||
1670 | FC_RPORT_DBG(rdata, "Received PRLI request while in state %s\n", | 1648 | FC_RPORT_DBG(rdata, "Received PRLI request while in state %s\n", |
1671 | fc_rport_state(rdata)); | 1649 | fc_rport_state(rdata)); |
1672 | 1650 | ||
@@ -1759,7 +1737,7 @@ reject_len: | |||
1759 | rjt_data.reason = ELS_RJT_PROT; | 1737 | rjt_data.reason = ELS_RJT_PROT; |
1760 | rjt_data.explan = ELS_EXPL_INV_LEN; | 1738 | rjt_data.explan = ELS_EXPL_INV_LEN; |
1761 | reject: | 1739 | reject: |
1762 | lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); | 1740 | lport->tt.seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data); |
1763 | drop: | 1741 | drop: |
1764 | fc_frame_free(rx_fp); | 1742 | fc_frame_free(rx_fp); |
1765 | } | 1743 | } |
@@ -1767,18 +1745,15 @@ drop: | |||
1767 | /** | 1745 | /** |
1768 | * fc_rport_recv_prlo_req() - Handler for process logout (PRLO) requests | 1746 | * fc_rport_recv_prlo_req() - Handler for process logout (PRLO) requests |
1769 | * @rdata: The remote port that sent the PRLO request | 1747 | * @rdata: The remote port that sent the PRLO request |
1770 | * @sp: The sequence that the PRLO was on | ||
1771 | * @rx_fp: The PRLO request frame | 1748 | * @rx_fp: The PRLO request frame |
1772 | * | 1749 | * |
1773 | * Locking Note: The rport lock is exected to be held before calling | 1750 | * Locking Note: The rport lock is exected to be held before calling |
1774 | * this function. | 1751 | * this function. |
1775 | */ | 1752 | */ |
1776 | static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata, | 1753 | static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata, |
1777 | struct fc_seq *sp, | ||
1778 | struct fc_frame *rx_fp) | 1754 | struct fc_frame *rx_fp) |
1779 | { | 1755 | { |
1780 | struct fc_lport *lport = rdata->local_port; | 1756 | struct fc_lport *lport = rdata->local_port; |
1781 | struct fc_exch *ep; | ||
1782 | struct fc_frame *fp; | 1757 | struct fc_frame *fp; |
1783 | struct { | 1758 | struct { |
1784 | struct fc_els_prlo prlo; | 1759 | struct fc_els_prlo prlo; |
@@ -1790,8 +1765,6 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata, | |||
1790 | unsigned int plen; | 1765 | unsigned int plen; |
1791 | struct fc_seq_els_data rjt_data; | 1766 | struct fc_seq_els_data rjt_data; |
1792 | 1767 | ||
1793 | rjt_data.fp = NULL; | ||
1794 | |||
1795 | FC_RPORT_DBG(rdata, "Received PRLO request while in state %s\n", | 1768 | FC_RPORT_DBG(rdata, "Received PRLO request while in state %s\n", |
1796 | fc_rport_state(rdata)); | 1769 | fc_rport_state(rdata)); |
1797 | 1770 | ||
@@ -1814,8 +1787,6 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata, | |||
1814 | goto reject; | 1787 | goto reject; |
1815 | } | 1788 | } |
1816 | 1789 | ||
1817 | sp = lport->tt.seq_start_next(sp); | ||
1818 | WARN_ON(!sp); | ||
1819 | pp = fc_frame_payload_get(fp, len); | 1790 | pp = fc_frame_payload_get(fp, len); |
1820 | WARN_ON(!pp); | 1791 | WARN_ON(!pp); |
1821 | memset(pp, 0, len); | 1792 | memset(pp, 0, len); |
@@ -1829,17 +1800,15 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata, | |||
1829 | 1800 | ||
1830 | fc_rport_enter_delete(rdata, RPORT_EV_LOGO); | 1801 | fc_rport_enter_delete(rdata, RPORT_EV_LOGO); |
1831 | 1802 | ||
1832 | ep = fc_seq_exch(sp); | 1803 | fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0); |
1833 | fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, | 1804 | lport->tt.frame_send(lport, fp); |
1834 | FC_TYPE_ELS, FC_FCTL_RESP, 0); | ||
1835 | lport->tt.seq_send(lport, sp, fp); | ||
1836 | goto drop; | 1805 | goto drop; |
1837 | 1806 | ||
1838 | reject_len: | 1807 | reject_len: |
1839 | rjt_data.reason = ELS_RJT_PROT; | 1808 | rjt_data.reason = ELS_RJT_PROT; |
1840 | rjt_data.explan = ELS_EXPL_INV_LEN; | 1809 | rjt_data.explan = ELS_EXPL_INV_LEN; |
1841 | reject: | 1810 | reject: |
1842 | lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); | 1811 | lport->tt.seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data); |
1843 | drop: | 1812 | drop: |
1844 | fc_frame_free(rx_fp); | 1813 | fc_frame_free(rx_fp); |
1845 | } | 1814 | } |
@@ -1847,20 +1816,17 @@ drop: | |||
1847 | /** | 1816 | /** |
1848 | * fc_rport_recv_logo_req() - Handler for logout (LOGO) requests | 1817 | * fc_rport_recv_logo_req() - Handler for logout (LOGO) requests |
1849 | * @lport: The local port that received the LOGO request | 1818 | * @lport: The local port that received the LOGO request |
1850 | * @sp: The sequence that the LOGO request was on | ||
1851 | * @fp: The LOGO request frame | 1819 | * @fp: The LOGO request frame |
1852 | * | 1820 | * |
1853 | * Locking Note: The rport lock is exected to be held before calling | 1821 | * Locking Note: The rport lock is exected to be held before calling |
1854 | * this function. | 1822 | * this function. |
1855 | */ | 1823 | */ |
1856 | static void fc_rport_recv_logo_req(struct fc_lport *lport, | 1824 | static void fc_rport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp) |
1857 | struct fc_seq *sp, | ||
1858 | struct fc_frame *fp) | ||
1859 | { | 1825 | { |
1860 | struct fc_rport_priv *rdata; | 1826 | struct fc_rport_priv *rdata; |
1861 | u32 sid; | 1827 | u32 sid; |
1862 | 1828 | ||
1863 | lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL); | 1829 | lport->tt.seq_els_rsp_send(fp, ELS_LS_ACC, NULL); |
1864 | 1830 | ||
1865 | sid = fc_frame_sid(fp); | 1831 | sid = fc_frame_sid(fp); |
1866 | 1832 | ||