Commit 92261156 authored by Joe Eykholt's avatar Joe Eykholt Committed by James Bottomley

[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: default avatarJoe Eykholt <jeykholt@cisco.com>
Signed-off-by: default avatarRobert Love <robert.w.love@intel.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 239e8104
...@@ -2341,20 +2341,19 @@ static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, struct sk_buff *skb) ...@@ -2341,20 +2341,19 @@ static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, struct sk_buff *skb)
/** /**
* fcoe_ctlr_disc_recv - discovery receive handler for VN2VN mode. * fcoe_ctlr_disc_recv - discovery receive handler for VN2VN mode.
* @fip: The FCoE controller * @lport: The local port
* @fp: The received frame
* *
* This should never be called since we don't see RSCNs or other * This should never be called since we don't see RSCNs or other
* fabric-generated ELSes. * fabric-generated ELSes.
*/ */
static void fcoe_ctlr_disc_recv(struct fc_seq *seq, struct fc_frame *fp, static void fcoe_ctlr_disc_recv(struct fc_lport *lport, struct fc_frame *fp)
struct fc_lport *lport)
{ {
struct fc_seq_els_data rjt_data; struct fc_seq_els_data rjt_data;
rjt_data.fp = NULL;
rjt_data.reason = ELS_RJT_UNSUP; rjt_data.reason = ELS_RJT_UNSUP;
rjt_data.explan = ELS_EXPL_NONE; rjt_data.explan = ELS_EXPL_NONE;
lport->tt.seq_els_rsp_send(seq, ELS_LS_RJT, &rjt_data); lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &rjt_data);
fc_frame_free(fp); fc_frame_free(fp);
} }
......
...@@ -75,15 +75,13 @@ void fc_disc_stop_rports(struct fc_disc *disc) ...@@ -75,15 +75,13 @@ void fc_disc_stop_rports(struct fc_disc *disc)
/** /**
* fc_disc_recv_rscn_req() - Handle Registered State Change Notification (RSCN) * fc_disc_recv_rscn_req() - Handle Registered State Change Notification (RSCN)
* @sp: The sequence of the RSCN exchange * @disc: The discovery object to which the RSCN applies
* @fp: The RSCN frame * @fp: The RSCN frame
* @lport: The local port that the request will be sent on
* *
* Locking Note: This function expects that the disc_mutex is locked * Locking Note: This function expects that the disc_mutex is locked
* before it is called. * before it is called.
*/ */
static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp, static void fc_disc_recv_rscn_req(struct fc_disc *disc, struct fc_frame *fp)
struct fc_disc *disc)
{ {
struct fc_lport *lport; struct fc_lport *lport;
struct fc_els_rscn *rp; 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,7 +149,7 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp,
break; break;
} }
} }
lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL); lport->tt.seq_els_rsp_send(fp, ELS_LS_ACC, NULL);
/* /*
* If not doing a complete rediscovery, do GPN_ID on * 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,25 +175,22 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp,
return; return;
reject: reject:
FC_DISC_DBG(disc, "Received a bad RSCN frame\n"); FC_DISC_DBG(disc, "Received a bad RSCN frame\n");
rjt_data.fp = NULL;
rjt_data.reason = ELS_RJT_LOGIC; rjt_data.reason = ELS_RJT_LOGIC;
rjt_data.explan = ELS_EXPL_NONE; rjt_data.explan = ELS_EXPL_NONE;
lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &rjt_data);
fc_frame_free(fp); fc_frame_free(fp);
} }
/** /**
* fc_disc_recv_req() - Handle incoming requests * fc_disc_recv_req() - Handle incoming requests
* @sp: The sequence of the request exchange
* @fp: The request frame
* @lport: The local port receiving the request * @lport: The local port receiving the request
* @fp: The request frame
* *
* Locking Note: This function is called from the EM and will lock * Locking Note: This function is called from the EM and will lock
* the disc_mutex before calling the handler for the * the disc_mutex before calling the handler for the
* request. * request.
*/ */
static void fc_disc_recv_req(struct fc_seq *sp, struct fc_frame *fp, static void fc_disc_recv_req(struct fc_lport *lport, struct fc_frame *fp)
struct fc_lport *lport)
{ {
u8 op; u8 op;
struct fc_disc *disc = &lport->disc; 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,7 +199,7 @@ static void fc_disc_recv_req(struct fc_seq *sp, struct fc_frame *fp,
switch (op) { switch (op) {
case ELS_RSCN: case ELS_RSCN:
mutex_lock(&disc->disc_mutex); mutex_lock(&disc->disc_mutex);
fc_disc_recv_rscn_req(sp, fp, disc); fc_disc_recv_rscn_req(disc, fp);
mutex_unlock(&disc->disc_mutex); mutex_unlock(&disc->disc_mutex);
break; break;
default: default:
......
...@@ -129,11 +129,11 @@ struct fc_exch_mgr_anchor { ...@@ -129,11 +129,11 @@ struct fc_exch_mgr_anchor {
}; };
static void fc_exch_rrq(struct fc_exch *); static void fc_exch_rrq(struct fc_exch *);
static void fc_seq_ls_acc(struct fc_seq *); static void fc_seq_ls_acc(struct fc_frame *);
static void fc_seq_ls_rjt(struct fc_seq *, enum fc_els_rjt_reason, static void fc_seq_ls_rjt(struct fc_frame *, enum fc_els_rjt_reason,
enum fc_els_rjt_explan); enum fc_els_rjt_explan);
static void fc_exch_els_rec(struct fc_seq *, struct fc_frame *); static void fc_exch_els_rec(struct fc_frame *);
static void fc_exch_els_rrq(struct fc_seq *, struct fc_frame *); static void fc_exch_els_rrq(struct fc_frame *);
/* /*
* Internal implementation notes. * Internal implementation notes.
...@@ -1003,28 +1003,30 @@ static void fc_exch_set_addr(struct fc_exch *ep, ...@@ -1003,28 +1003,30 @@ static void fc_exch_set_addr(struct fc_exch *ep,
/** /**
* fc_seq_els_rsp_send() - Send an ELS response using infomation from * fc_seq_els_rsp_send() - Send an ELS response using infomation from
* the existing sequence/exchange. * the existing sequence/exchange.
* @sp: The sequence/exchange to get information from * @fp: The received frame
* @els_cmd: The ELS command to be sent * @els_cmd: The ELS command to be sent
* @els_data: The ELS data to be sent * @els_data: The ELS data to be sent
*
* The received frame is not freed.
*/ */
static void fc_seq_els_rsp_send(struct fc_seq *sp, enum fc_els_cmd els_cmd, static void fc_seq_els_rsp_send(struct fc_frame *fp, enum fc_els_cmd els_cmd,
struct fc_seq_els_data *els_data) struct fc_seq_els_data *els_data)
{ {
switch (els_cmd) { switch (els_cmd) {
case ELS_LS_RJT: case ELS_LS_RJT:
fc_seq_ls_rjt(sp, els_data->reason, els_data->explan); fc_seq_ls_rjt(fp, els_data->reason, els_data->explan);
break; break;
case ELS_LS_ACC: case ELS_LS_ACC:
fc_seq_ls_acc(sp); fc_seq_ls_acc(fp);
break; break;
case ELS_RRQ: case ELS_RRQ:
fc_exch_els_rrq(sp, els_data->fp); fc_exch_els_rrq(fp);
break; break;
case ELS_REC: case ELS_REC:
fc_exch_els_rec(sp, els_data->fp); fc_exch_els_rec(fp);
break; break;
default: default:
FC_EXCH_DBG(fc_seq_exch(sp), "Invalid ELS CMD:%x\n", els_cmd); FC_LPORT_DBG(fr_dev(fp), "Invalid ELS CMD:%x\n", els_cmd);
} }
} }
...@@ -1253,11 +1255,13 @@ static struct fc_seq *fc_seq_assign(struct fc_lport *lport, struct fc_frame *fp) ...@@ -1253,11 +1255,13 @@ static struct fc_seq *fc_seq_assign(struct fc_lport *lport, struct fc_frame *fp)
} }
/** /**
* fc_exch_recv_req() - Handler for an incoming request where is other * fc_exch_recv_req() - Handler for an incoming request
* end is originating the sequence
* @lport: The local port that received the request * @lport: The local port that received the request
* @mp: The EM that the exchange is on * @mp: The EM that the exchange is on
* @fp: The request frame * @fp: The request frame
*
* This is used when the other end is originating the exchange
* and the sequence.
*/ */
static void fc_exch_recv_req(struct fc_lport *lport, struct fc_exch_mgr *mp, static void fc_exch_recv_req(struct fc_lport *lport, struct fc_exch_mgr *mp,
struct fc_frame *fp) struct fc_frame *fp)
...@@ -1275,8 +1279,17 @@ static void fc_exch_recv_req(struct fc_lport *lport, struct fc_exch_mgr *mp, ...@@ -1275,8 +1279,17 @@ static void fc_exch_recv_req(struct fc_lport *lport, struct fc_exch_mgr *mp,
fc_frame_free(fp); fc_frame_free(fp);
return; return;
} }
fr_dev(fp) = lport;
BUG_ON(fr_seq(fp)); /* XXX remove later */
/*
* If the RX_ID is 0xffff, don't allocate an exchange.
* The upper-level protocol may request one later, if needed.
*/
if (fh->fh_rx_id == htons(FC_XID_UNKNOWN))
return lport->tt.lport_recv(lport, fp);
fr_seq(fp) = NULL;
reject = fc_seq_lookup_recip(lport, mp, fp); reject = fc_seq_lookup_recip(lport, mp, fp);
if (reject == FC_RJT_NONE) { if (reject == FC_RJT_NONE) {
sp = fr_seq(fp); /* sequence will be held */ 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,7 +1311,7 @@ static void fc_exch_recv_req(struct fc_lport *lport, struct fc_exch_mgr *mp,
if (ep->resp) if (ep->resp)
ep->resp(sp, fp, ep->arg); ep->resp(sp, fp, ep->arg);
else else
lport->tt.lport_recv(lport, sp, fp); lport->tt.lport_recv(lport, fp);
fc_exch_release(ep); /* release from lookup */ fc_exch_release(ep); /* release from lookup */
} else { } else {
FC_LPORT_DBG(lport, "exch/seq lookup failed: reject %x\n", 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,53 +1579,55 @@ static void fc_exch_recv_bls(struct fc_exch_mgr *mp, struct fc_frame *fp)
/** /**
* fc_seq_ls_acc() - Accept sequence with LS_ACC * fc_seq_ls_acc() - Accept sequence with LS_ACC
* @req_sp: The request sequence * @rx_fp: The received frame, not freed here.
* *
* If this fails due to allocation or transmit congestion, assume the * If this fails due to allocation or transmit congestion, assume the
* originator will repeat the sequence. * originator will repeat the sequence.
*/ */
static void fc_seq_ls_acc(struct fc_seq *req_sp) static void fc_seq_ls_acc(struct fc_frame *rx_fp)
{ {
struct fc_seq *sp; struct fc_lport *lport;
struct fc_els_ls_acc *acc; struct fc_els_ls_acc *acc;
struct fc_frame *fp; struct fc_frame *fp;
sp = fc_seq_start_next(req_sp); lport = fr_dev(rx_fp);
fp = fc_frame_alloc(fc_seq_exch(sp)->lp, sizeof(*acc)); fp = fc_frame_alloc(lport, sizeof(*acc));
if (fp) { if (!fp)
acc = fc_frame_payload_get(fp, sizeof(*acc)); return;
memset(acc, 0, sizeof(*acc)); acc = fc_frame_payload_get(fp, sizeof(*acc));
acc->la_cmd = ELS_LS_ACC; memset(acc, 0, sizeof(*acc));
fc_seq_send_last(sp, fp, FC_RCTL_ELS_REP, FC_TYPE_ELS); acc->la_cmd = ELS_LS_ACC;
} fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0);
lport->tt.frame_send(lport, fp);
} }
/** /**
* fc_seq_ls_rjt() - Reject a sequence with ELS LS_RJT * fc_seq_ls_rjt() - Reject a sequence with ELS LS_RJT
* @req_sp: The request sequence * @rx_fp: The received frame, not freed here.
* @reason: The reason the sequence is being rejected * @reason: The reason the sequence is being rejected
* @explan: The explaination for the rejection * @explan: The explanation for the rejection
* *
* If this fails due to allocation or transmit congestion, assume the * If this fails due to allocation or transmit congestion, assume the
* originator will repeat the sequence. * originator will repeat the sequence.
*/ */
static void fc_seq_ls_rjt(struct fc_seq *req_sp, enum fc_els_rjt_reason reason, static void fc_seq_ls_rjt(struct fc_frame *rx_fp, enum fc_els_rjt_reason reason,
enum fc_els_rjt_explan explan) enum fc_els_rjt_explan explan)
{ {
struct fc_seq *sp; struct fc_lport *lport;
struct fc_els_ls_rjt *rjt; struct fc_els_ls_rjt *rjt;
struct fc_frame *fp; struct fc_frame *fp;
sp = fc_seq_start_next(req_sp); lport = fr_dev(rx_fp);
fp = fc_frame_alloc(fc_seq_exch(sp)->lp, sizeof(*rjt)); fp = fc_frame_alloc(lport, sizeof(*rjt));
if (fp) { if (!fp)
rjt = fc_frame_payload_get(fp, sizeof(*rjt)); return;
memset(rjt, 0, sizeof(*rjt)); rjt = fc_frame_payload_get(fp, sizeof(*rjt));
rjt->er_cmd = ELS_LS_RJT; memset(rjt, 0, sizeof(*rjt));
rjt->er_reason = reason; rjt->er_cmd = ELS_LS_RJT;
rjt->er_explan = explan; rjt->er_reason = reason;
fc_seq_send_last(sp, fp, FC_RCTL_ELS_REP, FC_TYPE_ELS); rjt->er_explan = explan;
} fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0);
lport->tt.frame_send(lport, fp);
} }
/** /**
...@@ -1714,18 +1729,34 @@ void fc_exch_mgr_reset(struct fc_lport *lport, u32 sid, u32 did) ...@@ -1714,18 +1729,34 @@ void fc_exch_mgr_reset(struct fc_lport *lport, u32 sid, u32 did)
} }
EXPORT_SYMBOL(fc_exch_mgr_reset); EXPORT_SYMBOL(fc_exch_mgr_reset);
/**
* fc_exch_lookup() - find an exchange
* @lport: The local port
* @xid: The exchange ID
*
* Returns exchange pointer with hold for caller, or NULL if not found.
*/
static struct fc_exch *fc_exch_lookup(struct fc_lport *lport, u32 xid)
{
struct fc_exch_mgr_anchor *ema;
list_for_each_entry(ema, &lport->ema_list, ema_list)
if (ema->mp->min_xid <= xid && xid <= ema->mp->max_xid)
return fc_exch_find(ema->mp, xid);
return NULL;
}
/** /**
* fc_exch_els_rec() - Handler for ELS REC (Read Exchange Concise) requests * fc_exch_els_rec() - Handler for ELS REC (Read Exchange Concise) requests
* @sp: The sequence the REC is on * @rfp: The REC frame, not freed here.
* @rfp: The REC frame
* *
* Note that the requesting port may be different than the S_ID in the request. * Note that the requesting port may be different than the S_ID in the request.
*/ */
static void fc_exch_els_rec(struct fc_seq *sp, struct fc_frame *rfp) static void fc_exch_els_rec(struct fc_frame *rfp)
{ {
struct fc_lport *lport;
struct fc_frame *fp; struct fc_frame *fp;
struct fc_exch *ep; struct fc_exch *ep;
struct fc_exch_mgr *em;
struct fc_els_rec *rp; struct fc_els_rec *rp;
struct fc_els_rec_acc *acc; struct fc_els_rec_acc *acc;
enum fc_els_rjt_reason reason = ELS_RJT_LOGIC; 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,6 +1765,7 @@ static void fc_exch_els_rec(struct fc_seq *sp, struct fc_frame *rfp)
u16 rxid; u16 rxid;
u16 oxid; u16 oxid;
lport = fr_dev(rfp);
rp = fc_frame_payload_get(rfp, sizeof(*rp)); rp = fc_frame_payload_get(rfp, sizeof(*rp));
explan = ELS_EXPL_INV_LEN; explan = ELS_EXPL_INV_LEN;
if (!rp) if (!rp)
...@@ -1742,35 +1774,19 @@ static void fc_exch_els_rec(struct fc_seq *sp, struct fc_frame *rfp) ...@@ -1742,35 +1774,19 @@ static void fc_exch_els_rec(struct fc_seq *sp, struct fc_frame *rfp)
rxid = ntohs(rp->rec_rx_id); rxid = ntohs(rp->rec_rx_id);
oxid = ntohs(rp->rec_ox_id); oxid = ntohs(rp->rec_ox_id);
/* ep = fc_exch_lookup(lport,
* Currently it's hard to find the local S_ID from the exchange sid == fc_host_port_id(lport->host) ? oxid : rxid);
* manager. This will eventually be fixed, but for now it's easier
* to lookup the subject exchange twice, once as if we were
* the initiator, and then again if we weren't.
*/
em = fc_seq_exch(sp)->em;
ep = fc_exch_find(em, oxid);
explan = ELS_EXPL_OXID_RXID; explan = ELS_EXPL_OXID_RXID;
if (ep && ep->oid == sid) { if (!ep)
if (ep->rxid != FC_XID_UNKNOWN && goto reject;
rxid != FC_XID_UNKNOWN && if (ep->oid != sid || oxid != ep->oxid)
ep->rxid != rxid) goto rel;
goto rel; if (rxid != FC_XID_UNKNOWN && rxid != ep->rxid)
} else { goto rel;
if (ep) fp = fc_frame_alloc(lport, sizeof(*acc));
fc_exch_release(ep); if (!fp)
ep = NULL;
if (rxid != FC_XID_UNKNOWN)
ep = fc_exch_find(em, rxid);
if (!ep)
goto reject;
}
fp = fc_frame_alloc(fc_seq_exch(sp)->lp, sizeof(*acc));
if (!fp) {
fc_exch_done(sp);
goto out; goto out;
}
acc = fc_frame_payload_get(fp, sizeof(*acc)); acc = fc_frame_payload_get(fp, sizeof(*acc));
memset(acc, 0, sizeof(*acc)); memset(acc, 0, sizeof(*acc));
acc->reca_cmd = ELS_LS_ACC; 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,18 +1801,16 @@ static void fc_exch_els_rec(struct fc_seq *sp, struct fc_frame *rfp)
acc->reca_e_stat = htonl(ep->esb_stat & (ESB_ST_RESP | acc->reca_e_stat = htonl(ep->esb_stat & (ESB_ST_RESP |
ESB_ST_SEQ_INIT | ESB_ST_SEQ_INIT |
ESB_ST_COMPLETE)); ESB_ST_COMPLETE));
sp = fc_seq_start_next(sp); fc_fill_reply_hdr(fp, rfp, FC_RCTL_ELS_REP, 0);
fc_seq_send_last(sp, fp, FC_RCTL_ELS_REP, FC_TYPE_ELS); lport->tt.frame_send(lport, fp);
out: out:
fc_exch_release(ep); fc_exch_release(ep);
fc_frame_free(rfp);
return; return;
rel: rel:
fc_exch_release(ep); fc_exch_release(ep);
reject: reject:
fc_seq_ls_rjt(sp, reason, explan); fc_seq_ls_rjt(rfp, reason, explan);
fc_frame_free(rfp);
} }
/** /**
...@@ -1971,20 +1985,20 @@ static void fc_exch_rrq(struct fc_exch *ep) ...@@ -1971,20 +1985,20 @@ static void fc_exch_rrq(struct fc_exch *ep)
spin_unlock_bh(&ep->ex_lock); spin_unlock_bh(&ep->ex_lock);
} }
/** /**
* fc_exch_els_rrq() - Handler for ELS RRQ (Reset Recovery Qualifier) requests * fc_exch_els_rrq() - Handler for ELS RRQ (Reset Recovery Qualifier) requests
* @sp: The sequence that the RRQ is on * @fp: The RRQ frame, not freed here.
* @fp: The RRQ frame
*/ */
static void fc_exch_els_rrq(struct fc_seq *sp, struct fc_frame *fp) static void fc_exch_els_rrq(struct fc_frame *fp)
{ {
struct fc_lport *lport;
struct fc_exch *ep = NULL; /* request or subject exchange */ struct fc_exch *ep = NULL; /* request or subject exchange */
struct fc_els_rrq *rp; struct fc_els_rrq *rp;
u32 sid; u32 sid;
u16 xid; u16 xid;
enum fc_els_rjt_explan explan; enum fc_els_rjt_explan explan;
lport = fr_dev(fp);
rp = fc_frame_payload_get(fp, sizeof(*rp)); rp = fc_frame_payload_get(fp, sizeof(*rp));
explan = ELS_EXPL_INV_LEN; explan = ELS_EXPL_INV_LEN;
if (!rp) if (!rp)
...@@ -1993,11 +2007,10 @@ static void fc_exch_els_rrq(struct fc_seq *sp, struct fc_frame *fp) ...@@ -1993,11 +2007,10 @@ static void fc_exch_els_rrq(struct fc_seq *sp, struct fc_frame *fp)
/* /*
* lookup subject exchange. * lookup subject exchange.
*/ */
ep = fc_seq_exch(sp);
sid = ntoh24(rp->rrq_s_id); /* subject source */ sid = ntoh24(rp->rrq_s_id); /* subject source */
xid = ep->did == sid ? ntohs(rp->rrq_ox_id) : ntohs(rp->rrq_rx_id); xid = fc_host_port_id(lport->host) == sid ?
ep = fc_exch_find(ep->em, xid); ntohs(rp->rrq_ox_id) : ntohs(rp->rrq_rx_id);
ep = fc_exch_lookup(lport, xid);
explan = ELS_EXPL_OXID_RXID; explan = ELS_EXPL_OXID_RXID;
if (!ep) if (!ep)
goto reject; goto reject;
...@@ -2028,15 +2041,14 @@ static void fc_exch_els_rrq(struct fc_seq *sp, struct fc_frame *fp) ...@@ -2028,15 +2041,14 @@ static void fc_exch_els_rrq(struct fc_seq *sp, struct fc_frame *fp)
/* /*
* Send LS_ACC. * Send LS_ACC.
*/ */
fc_seq_ls_acc(sp); fc_seq_ls_acc(fp);
goto out; goto out;
unlock_reject: unlock_reject:
spin_unlock_bh(&ep->ex_lock); spin_unlock_bh(&ep->ex_lock);
reject: reject:
fc_seq_ls_rjt(sp, ELS_RJT_LOGIC, explan); fc_seq_ls_rjt(fp, ELS_RJT_LOGIC, explan);
out: out:
fc_frame_free(fp);
if (ep) if (ep)
fc_exch_release(ep); /* drop hold from fc_exch_find */ fc_exch_release(ep); /* drop hold from fc_exch_find */
} }
...@@ -2267,7 +2279,7 @@ void fc_exch_recv(struct fc_lport *lport, struct fc_frame *fp) ...@@ -2267,7 +2279,7 @@ void fc_exch_recv(struct fc_lport *lport, struct fc_frame *fp)
fc_exch_recv_seq_resp(ema->mp, fp); fc_exch_recv_seq_resp(ema->mp, fp);
else if (f_ctl & FC_FC_SEQ_CTX) else if (f_ctl & FC_FC_SEQ_CTX)
fc_exch_recv_resp(ema->mp, fp); fc_exch_recv_resp(ema->mp, fp);
else else /* no EX_CTX and no SEQ_CTX */
fc_exch_recv_req(lport, ema->mp, fp); fc_exch_recv_req(lport, ema->mp, fp);
break; break;
default: default:
......
...@@ -375,34 +375,31 @@ static void fc_lport_add_fc4_type(struct fc_lport *lport, enum fc_fh_type type) ...@@ -375,34 +375,31 @@ static void fc_lport_add_fc4_type(struct fc_lport *lport, enum fc_fh_type type)
/** /**
* fc_lport_recv_rlir_req() - Handle received Registered Link Incident Report. * fc_lport_recv_rlir_req() - Handle received Registered Link Incident Report.
* @sp: The sequence in the RLIR exchange
* @fp: The RLIR request frame
* @lport: Fibre Channel local port recieving the RLIR * @lport: Fibre Channel local port recieving the RLIR
* @fp: The RLIR request frame
* *
* Locking Note: The lport lock is expected to be held before calling * Locking Note: The lport lock is expected to be held before calling
* this function. * this function.
*/ */
static void fc_lport_recv_rlir_req(struct fc_seq *sp, struct fc_frame *fp, static void fc_lport_recv_rlir_req(struct fc_lport *lport, struct fc_frame *fp)
struct fc_lport *lport)
{ {
FC_LPORT_DBG(lport, "Received RLIR request while in state %s\n", FC_LPORT_DBG(lport, "Received RLIR request while in state %s\n",
fc_lport_state(lport)); fc_lport_state(lport));
lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL); lport->tt.seq_els_rsp_send(fp, ELS_LS_ACC, NULL);
fc_frame_free(fp); fc_frame_free(fp);
} }
/** /**
* fc_lport_recv_echo_req() - Handle received ECHO request * fc_lport_recv_echo_req() - Handle received ECHO request
* @sp: The sequence in the ECHO exchange
* @fp: ECHO request frame
* @lport: The local port recieving the ECHO * @lport: The local port recieving the ECHO
* @fp: ECHO request frame
* *
* Locking Note: The lport lock is expected to be held before calling * Locking Note: The lport lock is expected to be held before calling
* this function. * this function.
*/ */
static void fc_lport_recv_echo_req(struct fc_seq *sp, struct fc_frame *in_fp, static void fc_lport_recv_echo_req(struct fc_lport *lport,
struct fc_lport *lport) struct fc_frame *in_fp)
{ {
struct fc_frame *fp; struct fc_frame *fp;
unsigned int len; unsigned int len;
...@@ -431,15 +428,14 @@ static void fc_lport_recv_echo_req(struct fc_seq *sp, struct fc_frame *in_fp, ...@@ -431,15 +428,14 @@ static void fc_lport_recv_echo_req(struct fc_seq *sp, struct fc_frame *in_fp,
/** /**
* fc_lport_recv_rnid_req() - Handle received Request Node ID data request * fc_lport_recv_rnid_req() - Handle received Request Node ID data request
* @sp: The sequence in the RNID exchange
* @fp: The RNID request frame
* @lport: The local port recieving the RNID * @lport: The local port recieving the RNID
* @fp: The RNID request frame
* *
* Locking Note: The lport lock is expected to be held before calling * Locking Note: The lport lock is expected to be held before calling
* this function. * this function.
*/ */
static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp, static void fc_lport_recv_rnid_req(struct fc_lport *lport,
struct fc_lport *lport) struct fc_frame *in_fp)
{ {
struct fc_frame *fp; struct fc_frame *fp;
struct fc_els_rnid *req; 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,10 +453,9 @@ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp,
req = fc_frame_payload_get(in_fp, sizeof(*req)); req = fc_frame_payload_get(in_fp, sizeof(*req));
if (!req) { if (!req) {
rjt_data.fp = NULL;
rjt_data.reason = ELS_RJT_LOGIC; rjt_data.reason = ELS_RJT_LOGIC;
rjt_data.explan = ELS_EXPL_NONE; rjt_data.explan = ELS_EXPL_NONE;
lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); lport->tt.seq_els_rsp_send(in_fp, ELS_LS_RJT, &rjt_data);
} else { } else {
fmt = req->rnid_fmt; fmt = req->rnid_fmt;
len = sizeof(*rp); len = sizeof(*rp);
...@@ -492,17 +487,15 @@ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp, ...@@ -492,17 +487,15 @@ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp,
/** /**
* fc_lport_recv_logo_req() - Handle received fabric LOGO request * fc_lport_recv_logo_req() - Handle received fabric LOGO request
* @sp: The sequence in the LOGO exchange
* @fp: The LOGO request frame
* @lport: The local port recieving the LOGO * @lport: The local port recieving the LOGO
* @fp: The LOGO request frame
* *
* Locking Note: The lport lock is exected to be held before calling * Locking Note: The lport lock is exected to be held before calling
* this function. * this function.
*/ */
static void fc_lport_recv_logo_req(struct fc_seq *sp, struct fc_frame *fp, static void fc_lport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp)
struct fc_lport *lport)
{ {
lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL); lport->tt.seq_els_rsp_send(fp, ELS_LS_ACC, NULL);
fc_lport_enter_reset(lport); fc_lport_enter_reset(lport);
fc_frame_free(fp); fc_frame_free(fp);
} }
...@@ -773,9 +766,8 @@ EXPORT_SYMBOL(fc_lport_set_local_id); ...@@ -773,9 +766,8 @@ EXPORT_SYMBOL(fc_lport_set_local_id);
/** /**
* fc_lport_recv_flogi_req() - Receive a FLOGI request * fc_lport_recv_flogi_req() - Receive a FLOGI request
* @sp_in: The sequence the FLOGI is on
* @rx_fp: The FLOGI frame
* @lport: The local port that recieved the request * @lport: The local port that recieved the request
* @rx_fp: The FLOGI frame
* *
* A received FLOGI request indicates a point-to-point connection. * A received FLOGI request indicates a point-to-point connection.
* Accept it with the common service parameters indicating our N port. * Accept it with the common service parameters indicating our N port.
...@@ -784,13 +776,11 @@ EXPORT_SYMBOL(fc_lport_set_local_id); ...@@ -784,13 +776,11 @@ EXPORT_SYMBOL(fc_lport_set_local_id);
* Locking Note: The lport lock is expected to be held before calling * Locking Note: The lport lock is expected to be held before calling
* this function. * this function.
*/ */
static void fc_lport_recv_flogi_req(struct fc_seq *sp_in, static void fc_lport_recv_flogi_req(struct fc_lport *lport,
struct fc_frame *rx_fp, struct fc_frame *rx_fp)
struct fc_lport *lport)
{ {
struct fc_frame *fp; struct fc_frame *fp;
struct fc_frame_header *fh; struct fc_frame_header *fh;
struct fc_seq *sp;
struct fc_els_flogi *flp; struct fc_els_flogi *flp;
struct fc_els_flogi *new_flp; struct fc_els_flogi *new_flp;
u64 remote_wwpn; u64 remote_wwpn;
...@@ -850,16 +840,13 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in, ...@@ -850,16 +840,13 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in,
} }
fc_lport_ptp_setup(lport, remote_fid, remote_wwpn, fc_lport_ptp_setup(lport, remote_fid, remote_wwpn,
get_unaligned_be64(&flp->fl_wwnn)); get_unaligned_be64(&flp->fl_wwnn));
out: out:
sp = fr_seq(rx_fp);
fc_frame_free(rx_fp); fc_frame_free(rx_fp);
} }
/** /**
* fc_lport_recv_req() - The generic lport request handler * fc_lport_recv_req() - The generic lport request handler
* @lport: The local port that received the request * @lport: The local port that received the request
* @sp: The sequence the request is on
* @fp: The request frame * @fp: The request frame
* *
* This function will see if the lport handles the request or * This function will see if the lport handles the request or
...@@ -868,11 +855,10 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in, ...@@ -868,11 +855,10 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in,
* Locking Note: This function should not be called with the lport * Locking Note: This function should not be called with the lport
* lock held becuase it will grab the lock. * lock held becuase it will grab the lock.
*/ */
static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp, static void fc_lport_recv_req(struct fc_lport *lport, struct fc_frame *fp)
struct fc_frame *fp)
{ {
struct fc_frame_header *fh = fc_frame_header_get(fp); struct fc_frame_header *fh = fc_frame_header_get(fp);
void (*recv) (struct fc_seq *, struct fc_frame *, struct fc_lport *); void (*recv)(struct fc_lport *, struct fc_frame *);
mutex_lock(&lport->lp_mutex); mutex_lock(&lport->lp_mutex);
...@@ -912,19 +898,13 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp, ...@@ -912,19 +898,13 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp,
break; break;
} }
recv(sp, fp, lport); recv(lport, fp);
} else { } else {
FC_LPORT_DBG(lport, "dropping invalid frame (eof %x)\n", FC_LPORT_DBG(lport, "dropping invalid frame (eof %x)\n",
fr_eof(fp)); fr_eof(fp));
fc_frame_free(fp); fc_frame_free(fp);
} }
mutex_unlock(&lport->lp_mutex); mutex_unlock(&lport->lp_mutex);
/*
* The common exch_done for all request may not be good
* if any request requires longer hold on exhange. XXX
*/
lport->tt.exch_done(sp);
} }
/** /**
......
...@@ -68,14 +68,10 @@ static void fc_rport_enter_ready(struct fc_rport_priv *); ...@@ -68,14 +68,10 @@ static void fc_rport_enter_ready(struct fc_rport_priv *);
static void fc_rport_enter_logo(struct fc_rport_priv *); static void fc_rport_enter_logo(struct fc_rport_priv *);
static void fc_rport_enter_adisc(struct fc_rport_priv *); static void fc_rport_enter_adisc(struct fc_rport_priv *);
static void fc_rport_recv_plogi_req(struct fc_lport *, static void fc_rport_recv_plogi_req(struct fc_lport *, struct fc_frame *);
struct fc_seq *, struct fc_frame *); static void fc_rport_recv_prli_req(struct fc_rport_priv *, struct fc_frame *);
static void fc_rport_recv_prli_req(struct fc_rport_priv *, static void fc_rport_recv_prlo_req(struct fc_rport_priv *, struct fc_frame *);
struct fc_seq *, struct fc_frame *); static void fc_rport_recv_logo_req(struct fc_lport *, struct fc_frame *);
static void fc_rport_recv_prlo_req(struct fc_rport_priv *,
struct fc_seq *, struct fc_frame *);
static void fc_rport_recv_logo_req(struct fc_lport *,
struct fc_seq *, struct fc_frame *);
static void fc_rport_timeout(struct work_struct *); static void fc_rport_timeout(struct work_struct *);
static void fc_rport_error(struct fc_rport_priv *, struct fc_frame *); static void fc_rport_error(struct fc_rport_priv *, struct fc_frame *);
static void fc_rport_error_retry(struct fc_rport_priv *, struct fc_frame *); 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,11 +732,10 @@ static void fc_rport_enter_flogi(struct fc_rport_priv *rdata)
/** /**
* fc_rport_recv_flogi_req() - Handle Fabric Login (FLOGI) request in p-mp mode * fc_rport_recv_flogi_req() - Handle Fabric Login (FLOGI) request in p-mp mode
* @lport: The local port that received the PLOGI request * @lport: The local port that received the PLOGI request
* @sp: The sequence that the PLOGI request was on
* @rx_fp: The PLOGI request frame * @rx_fp: The PLOGI request frame
*/ */
static void fc_rport_recv_flogi_req(struct fc_lport *lport, static void fc_rport_recv_flogi_req(struct fc_lport *lport,
struct fc_seq *sp, struct fc_frame *rx_fp) struct fc_frame *rx_fp)
{ {
struct fc_disc *disc; struct fc_disc *disc;
struct fc_els_flogi *flp; struct fc_els_flogi *flp;
...@@ -749,7 +744,6 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport, ...@@ -749,7 +744,6 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport,
struct fc_seq_els_data rjt_data; struct fc_seq_els_data rjt_data;
u32 sid; u32 sid;
rjt_data.fp = NULL;
sid = fc_frame_sid(fp); sid = fc_frame_sid(fp);
FC_RPORT_ID_DBG(lport, sid, "Received FLOGI request\n"); 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,7 +811,6 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport,
if (!fp) if (!fp)
goto out; goto out;
sp = lport->tt.seq_start_next(sp);
fc_flogi_fill(lport, fp); fc_flogi_fill(lport, fp);
flp = fc_frame_payload_get(fp, sizeof(*flp)); flp = fc_frame_payload_get(fp, sizeof(*flp));
flp->fl_cmd = ELS_LS_ACC; flp->fl_cmd = ELS_LS_ACC;
...@@ -837,7 +830,7 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport, ...@@ -837,7 +830,7 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport,
reject: reject:
mutex_unlock(&disc->disc_mutex); mutex_unlock(&disc->disc_mutex);
lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); lport->tt.seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data);
fc_frame_free(rx_fp); fc_frame_free(rx_fp);
} }
...@@ -1296,13 +1289,12 @@ static void fc_rport_enter_adisc(struct fc_rport_priv *rdata) ...@@ -1296,13 +1289,12 @@ static void fc_rport_enter_adisc(struct fc_rport_priv *rdata)
/** /**
* fc_rport_recv_adisc_req() - Handler for Address Discovery (ADISC) requests * fc_rport_recv_adisc_req() - Handler for Address Discovery (ADISC) requests
* @rdata: The remote port that sent the ADISC request * @rdata: The remote port that sent the ADISC request
* @sp: The sequence the ADISC request was on
* @in_fp: The ADISC request frame * @in_fp: The ADISC request frame
* *
* Locking Note: Called with the lport and rport locks held. * Locking Note: Called with the lport and rport locks held.
*/ */
static void fc_rport_recv_adisc_req(struct fc_rport_priv *rdata, static void fc_rport_recv_adisc_req(struct fc_rport_priv *rdata,
struct fc_seq *sp, struct fc_frame *in_fp) struct fc_frame *in_fp)
{ {
struct fc_lport *lport = rdata->local_port; struct fc_lport *lport = rdata->local_port;
struct fc_frame *fp; struct fc_frame *fp;
...@@ -1313,10 +1305,9 @@ static void fc_rport_recv_adisc_req(struct fc_rport_priv *rdata, ...@@ -1313,10 +1305,9 @@ static void fc_rport_recv_adisc_req(struct fc_rport_priv *rdata,
adisc = fc_frame_payload_get(in_fp, sizeof(*adisc)); adisc = fc_frame_payload_get(in_fp, sizeof(*adisc));
if (!adisc) { if (!adisc) {
rjt_data.fp = NULL;
rjt_data.reason = ELS_RJT_PROT; rjt_data.reason = ELS_RJT_PROT;
rjt_data.explan = ELS_EXPL_INV_LEN; rjt_data.explan = ELS_EXPL_INV_LEN;
lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); lport->tt.seq_els_rsp_send(in_fp, ELS_LS_RJT, &rjt_data);
goto drop; goto drop;
} }
...@@ -1335,14 +1326,13 @@ static void fc_rport_recv_adisc_req(struct fc_rport_priv *rdata, ...@@ -1335,14 +1326,13 @@ static void fc_rport_recv_adisc_req(struct fc_rport_priv *rdata,
/** /**
* fc_rport_recv_rls_req() - Handle received Read Link Status request * fc_rport_recv_rls_req() - Handle received Read Link Status request
* @rdata: The remote port that sent the RLS request * @rdata: The remote port that sent the RLS request
* @sp: The sequence that the RLS was on
* @rx_fp: The PRLI request frame * @rx_fp: The PRLI request frame
* *
* Locking Note: The rport lock is expected to be held before calling * Locking Note: The rport lock is expected to be held before calling
* this function. * this function.
*/ */
static void fc_rport_recv_rls_req(struct fc_rport_priv *rdata, static void fc_rport_recv_rls_req(struct fc_rport_priv *rdata,
struct fc_seq *sp, struct fc_frame *rx_fp) struct fc_frame *rx_fp)
{ {
struct fc_lport *lport = rdata->local_port; struct fc_lport *lport = rdata->local_port;
...@@ -1393,8 +1383,7 @@ static void fc_rport_recv_rls_req(struct fc_rport_priv *rdata, ...@@ -1393,8 +1383,7 @@ static void fc_rport_recv_rls_req(struct fc_rport_priv *rdata,
goto out; goto out;
out_rjt: out_rjt:
rjt_data.fp = NULL; lport->tt.seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data);
lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data);
out: out:
fc_frame_free(rx_fp); fc_frame_free(rx_fp);
} }
...@@ -1402,7 +1391,6 @@ static void fc_rport_recv_rls_req(struct fc_rport_priv *rdata, ...@@ -1402,7 +1391,6 @@ static void fc_rport_recv_rls_req(struct fc_rport_priv *rdata,
/** /**
* fc_rport_recv_els_req() - Handler for validated ELS requests * fc_rport_recv_els_req() - Handler for validated ELS requests
* @lport: The local port that received the ELS request * @lport: The local port that received the ELS request
* @sp: The sequence that the ELS request was on
* @fp: The ELS request frame * @fp: The ELS request frame
* *
* Handle incoming ELS requests that require port login. * Handle incoming ELS requests that require port login.
...@@ -1410,16 +1398,11 @@ static void fc_rport_recv_rls_req(struct fc_rport_priv *rdata, ...@@ -1410,16 +1398,11 @@ static void fc_rport_recv_rls_req(struct fc_rport_priv *rdata,
* *
* Locking Note: Called with the lport lock held. * Locking Note: Called with the lport lock held.
*/ */
static void fc_rport_recv_els_req(struct fc_lport *lport, static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp)
struct fc_seq *sp, struct fc_frame *fp)
{ {
struct fc_rport_priv *rdata; struct fc_rport_priv *rdata;
struct fc_seq_els_data els_data; struct fc_seq_els_data els_data;
els_data.fp = NULL;
els_data.reason = ELS_RJT_UNAB;
els_data.explan = ELS_EXPL_PLOGI_REQD;
mutex_lock(&lport->disc.disc_mutex); mutex_lock(&lport->disc.disc_mutex);
rdata = lport->tt.rport_lookup(lport, fc_frame_sid(fp)); rdata = lport->tt.rport_lookup(lport, fc_frame_sid(fp));
if (!rdata) { if (!rdata) {
...@@ -1442,24 +1425,24 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, ...@@ -1442,24 +1425,24 @@ static void fc_rport_recv_els_req(struct fc_lport *lport,
switch (fc_frame_payload_op(fp)) { switch (fc_frame_payload_op(fp)) {
case ELS_PRLI: case ELS_PRLI:
fc_rport_recv_prli_req(rdata, sp, fp); fc_rport_recv_prli_req(rdata, fp);
break; break;
case ELS_PRLO: case ELS_PRLO:
fc_rport_recv_prlo_req(rdata, sp, fp); fc_rport_recv_prlo_req(rdata, fp);
break; break;
case ELS_ADISC: case ELS_ADISC:
fc_rport_recv_adisc_req(rdata, sp, fp); fc_rport_recv_adisc_req(rdata, fp);
break; break;
case ELS_RRQ: case ELS_RRQ:
els_data.fp = fp; lport->tt.seq_els_rsp_send(fp, ELS_RRQ, NULL);
lport->tt.seq_els_rsp_send(sp, ELS_RRQ, &els_data); fc_frame_free(fp);
break; break;
case ELS_REC: case ELS_REC:
els_data.fp = fp; lport->tt.seq_els_rsp_send(fp, ELS_REC, NULL);
lport->tt.seq_els_rsp_send(sp, ELS_REC, &els_data); fc_frame_free(fp);
break; break;
case ELS_RLS: case ELS_RLS:
fc_rport_recv_rls_req(rdata, sp, fp); fc_rport_recv_rls_req(rdata, fp);
break; break;
default: default:
fc_frame_free(fp); /* can't happen */ fc_frame_free(fp); /* can't happen */
...@@ -1470,20 +1453,20 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, ...@@ -1470,20 +1453,20 @@ static void fc_rport_recv_els_req(struct fc_lport *lport,
return; return;
reject: reject:
lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &els_data); els_data.reason = ELS_RJT_UNAB;
els_data.explan = ELS_EXPL_PLOGI_REQD;
lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &els_data);
fc_frame_free(fp); fc_frame_free(fp);
} }
/** /**
* fc_rport_recv_req() - Handler for requests * fc_rport_recv_req() - Handler for requests
* @sp: The sequence the request was on
* @fp: The request frame
* @lport: The local port that received the request * @lport: The local port that received the request
* @fp: The request frame
* *
* Locking Note: Called with the lport lock held. * Locking Note: Called with the lport lock held.
*/ */
void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp, void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp)
struct fc_lport *lport)
{ {
struct fc_seq_els_data els_data; struct fc_seq_els_data els_data;
...@@ -1495,13 +1478,13 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp, ...@@ -1495,13 +1478,13 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp,
*/ */
switch (fc_frame_payload_op(fp)) { switch (fc_frame_payload_op(fp)) {
case ELS_FLOGI: case ELS_FLOGI:
fc_rport_recv_flogi_req(lport, sp, fp); fc_rport_recv_flogi_req(lport, fp);
break; break;
case ELS_PLOGI: case ELS_PLOGI:
fc_rport_recv_plogi_req(lport, sp, fp); fc_rport_recv_plogi_req(lport, fp);
break; break;
case ELS_LOGO: case ELS_LOGO:
fc_rport_recv_logo_req(lport, sp, fp); fc_rport_recv_logo_req(lport, fp);
break; break;
case ELS_PRLI: case ELS_PRLI:
case ELS_PRLO: case ELS_PRLO:
...@@ -1509,14 +1492,13 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp, ...@@ -1509,14 +1492,13 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp,
case ELS_RRQ: case ELS_RRQ:
case ELS_REC: case ELS_REC:
case ELS_RLS: case ELS_RLS:
fc_rport_recv_els_req(lport, sp, fp); fc_rport_recv_els_req(lport, fp);
break; break;
default: default:
fc_frame_free(fp);
els_data.fp = NULL;
els_data.reason = ELS_RJT_UNSUP; els_data.reason = ELS_RJT_UNSUP;
els_data.explan = ELS_EXPL_NONE; els_data.explan = ELS_EXPL_NONE;
lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &els_data); lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &els_data);
fc_frame_free(fp);
break; break;
} }
} }
...@@ -1524,13 +1506,12 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp, ...@@ -1524,13 +1506,12 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp,
/** /**
* fc_rport_recv_plogi_req() - Handler for Port Login (PLOGI) requests * fc_rport_recv_plogi_req() - Handler for Port Login (PLOGI) requests
* @lport: The local port that received the PLOGI request * @lport: The local port that received the PLOGI request
* @sp: The sequence that the PLOGI request was on
* @rx_fp: The PLOGI request frame * @rx_fp: The PLOGI request frame
* *
* Locking Note: The rport lock is held before calling this function. * Locking Note: The rport lock is held before calling this function.
*/ */
static void fc_rport_recv_plogi_req(struct fc_lport *lport, static void fc_rport_recv_plogi_req(struct fc_lport *lport,
struct fc_seq *sp, struct fc_frame *rx_fp) struct fc_frame *rx_fp)
{ {
struct fc_disc *disc; struct fc_disc *disc;
struct fc_rport_priv *rdata; struct fc_rport_priv *rdata;
...@@ -1539,7 +1520,6 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport, ...@@ -1539,7 +1520,6 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport,
struct fc_seq_els_data rjt_data; struct fc_seq_els_data rjt_data;
u32 sid; u32 sid;
rjt_data.fp = NULL;
sid = fc_frame_sid(fp); sid = fc_frame_sid(fp);
FC_RPORT_ID_DBG(lport, sid, "Received PLOGI request\n"); FC_RPORT_ID_DBG(lport, sid, "Received PLOGI request\n");
...@@ -1635,21 +1615,20 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport, ...@@ -1635,21 +1615,20 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport,
return; return;
reject: reject:
lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &rjt_data);
fc_frame_free(fp); fc_frame_free(fp);
} }
/** /**
* fc_rport_recv_prli_req() - Handler for process login (PRLI) requests * fc_rport_recv_prli_req() - Handler for process login (PRLI) requests
* @rdata: The remote port that sent the PRLI request * @rdata: The remote port that sent the PRLI request
* @sp: The sequence that the PRLI was on
* @rx_fp: The PRLI request frame * @rx_fp: The PRLI request frame
* *
* Locking Note: The rport lock is exected to be held before calling * Locking Note: The rport lock is exected to be held before calling
* this function. * this function.
*/ */
static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
struct fc_seq *sp, struct fc_frame *rx_fp) struct fc_frame *rx_fp)
{ {
struct fc_lport *lport = rdata->local_port; struct fc_lport *lport = rdata->local_port;
struct fc_frame *fp; struct fc_frame *fp;
...@@ -1666,7 +1645,6 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, ...@@ -1666,7 +1645,6 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
u32 fcp_parm; u32 fcp_parm;
u32 roles = FC_RPORT_ROLE_UNKNOWN; u32 roles = FC_RPORT_ROLE_UNKNOWN;
rjt_data.fp = NULL;
FC_RPORT_DBG(rdata, "Received PRLI request while in state %s\n", FC_RPORT_DBG(rdata, "Received PRLI request while in state %s\n",
fc_rport_state(rdata)); fc_rport_state(rdata));
...@@ -1759,7 +1737,7 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, ...@@ -1759,7 +1737,7 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
rjt_data.reason = ELS_RJT_PROT; rjt_data.reason = ELS_RJT_PROT;
rjt_data.explan = ELS_EXPL_INV_LEN; rjt_data.explan = ELS_EXPL_INV_LEN;
reject: reject:
lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); lport->tt.seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data);
drop: drop:
fc_frame_free(rx_fp); fc_frame_free(rx_fp);
} }
...@@ -1767,18 +1745,15 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, ...@@ -1767,18 +1745,15 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
/** /**
* fc_rport_recv_prlo_req() - Handler for process logout (PRLO) requests * fc_rport_recv_prlo_req() - Handler for process logout (PRLO) requests
* @rdata: The remote port that sent the PRLO request * @rdata: The remote port that sent the PRLO request
* @sp: The sequence that the PRLO was on
* @rx_fp: The PRLO request frame * @rx_fp: The PRLO request frame
* *
* Locking Note: The rport lock is exected to be held before calling * Locking Note: The rport lock is exected to be held before calling
* this function. * this function.
*/ */
static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata, static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata,
struct fc_seq *sp,
struct fc_frame *rx_fp) struct fc_frame *rx_fp)
{ {
struct fc_lport *lport = rdata->local_port; struct fc_lport *lport = rdata->local_port;
struct fc_exch *ep;
struct fc_frame *fp; struct fc_frame *fp;
struct { struct {
struct fc_els_prlo prlo; struct fc_els_prlo prlo;
...@@ -1790,8 +1765,6 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata, ...@@ -1790,8 +1765,6 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata,
unsigned int plen; unsigned int plen;
struct fc_seq_els_data rjt_data; struct fc_seq_els_data rjt_data;
rjt_data.fp = NULL;
FC_RPORT_DBG(rdata, "Received PRLO request while in state %s\n", FC_RPORT_DBG(rdata, "Received PRLO request while in state %s\n",
fc_rport_state(rdata)); fc_rport_state(rdata));
...@@ -1814,8 +1787,6 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata, ...@@ -1814,8 +1787,6 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata,
goto reject; goto reject;
} }
sp = lport->tt.seq_start_next(sp);
WARN_ON(!sp);
pp = fc_frame_payload_get(fp, len); pp = fc_frame_payload_get(fp, len);
WARN_ON(!pp); WARN_ON(!pp);
memset(pp, 0, len); memset(pp, 0, len);
...@@ -1829,17 +1800,15 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata, ...@@ -1829,17 +1800,15 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata,
fc_rport_enter_delete(rdata, RPORT_EV_LOGO); fc_rport_enter_delete(rdata, RPORT_EV_LOGO);
ep = fc_seq_exch(sp); fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0);
fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, lport->tt.frame_send(lport, fp);
FC_TYPE_ELS, FC_FCTL_RESP, 0);
lport->tt.seq_send(lport, sp, fp);
goto drop; goto drop;
reject_len: reject_len:
rjt_data.reason = ELS_RJT_PROT; rjt_data.reason = ELS_RJT_PROT;
rjt_data.explan = ELS_EXPL_INV_LEN; rjt_data.explan = ELS_EXPL_INV_LEN;
reject: reject:
lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); lport->tt.seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data);
drop: drop:
fc_frame_free(rx_fp); fc_frame_free(rx_fp);
} }
...@@ -1847,20 +1816,17 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata, ...@@ -1847,20 +1816,17 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata,
/** /**
* fc_rport_recv_logo_req() - Handler for logout (LOGO) requests * fc_rport_recv_logo_req() - Handler for logout (LOGO) requests
* @lport: The local port that received the LOGO request * @lport: The local port that received the LOGO request
* @sp: The sequence that the LOGO request was on
* @fp: The LOGO request frame * @fp: The LOGO request frame
* *
* Locking Note: The rport lock is exected to be held before calling * Locking Note: The rport lock is exected to be held before calling
* this function. * this function.
*/ */
static void fc_rport_recv_logo_req(struct fc_lport *lport, static void fc_rport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp)
struct fc_seq *sp,
struct fc_frame *fp)
{ {
struct fc_rport_priv *rdata; struct fc_rport_priv *rdata;
u32 sid; u32 sid;
lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL); lport->tt.seq_els_rsp_send(fp, ELS_LS_ACC, NULL);
sid = fc_frame_sid(fp); sid = fc_frame_sid(fp);
......
...@@ -249,14 +249,12 @@ struct fcoe_dev_stats { ...@@ -249,14 +249,12 @@ struct fcoe_dev_stats {
/** /**
* struct fc_seq_els_data - ELS data used for passing ELS specific responses * struct fc_seq_els_data - ELS data used for passing ELS specific responses
* @fp: The ELS frame
* @reason: The reason for rejection * @reason: The reason for rejection
* @explan: The explaination of the rejection * @explan: The explaination of the rejection
* *
* Mainly used by the exchange manager layer. * Mainly used by the exchange manager layer.
*/ */
struct fc_seq_els_data { struct fc_seq_els_data {
struct fc_frame *fp;
enum fc_els_rjt_reason reason; enum fc_els_rjt_reason reason;
enum fc_els_rjt_explan explan; enum fc_els_rjt_explan explan;
}; };
...@@ -519,12 +517,11 @@ struct libfc_function_template { ...@@ -519,12 +517,11 @@ struct libfc_function_template {
struct fc_frame *); struct fc_frame *);
/* /*
* Send an ELS response using infomation from a previous * Send an ELS response using infomation from the received frame.
* exchange and sequence.
* *
* STATUS: OPTIONAL * STATUS: OPTIONAL
*/ */
void (*seq_els_rsp_send)(struct fc_seq *, enum fc_els_cmd, void (*seq_els_rsp_send)(struct fc_frame *, enum fc_els_cmd,
struct fc_seq_els_data *); struct fc_seq_els_data *);
/* /*
...@@ -583,8 +580,7 @@ struct libfc_function_template { ...@@ -583,8 +580,7 @@ struct libfc_function_template {
* *
* STATUS: OPTIONAL * STATUS: OPTIONAL
*/ */
void (*lport_recv)(struct fc_lport *, struct fc_seq *, void (*lport_recv)(struct fc_lport *, struct fc_frame *);
struct fc_frame *);
/* /*
* Reset the local port. * Reset the local port.
...@@ -646,8 +642,7 @@ struct libfc_function_template { ...@@ -646,8 +642,7 @@ struct libfc_function_template {
* *
* STATUS: OPTIONAL * STATUS: OPTIONAL
*/ */
void (*rport_recv_req)(struct fc_seq *, struct fc_frame *, void (*rport_recv_req)(struct fc_lport *, struct fc_frame *);
struct fc_lport *);
/* /*
* lookup an rport by it's port ID. * lookup an rport by it's port ID.
...@@ -693,8 +688,7 @@ struct libfc_function_template { ...@@ -693,8 +688,7 @@ struct libfc_function_template {
* *
* STATUS: OPTIONAL * STATUS: OPTIONAL
*/ */
void (*disc_recv_req)(struct fc_seq *, struct fc_frame *, void (*disc_recv_req)(struct fc_lport *, struct fc_frame *);
struct fc_lport *);
/* /*
* Start discovery for a local port. * Start discovery for a local port.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment