Add FDISC ELS handling to libfc and libfcoe, treat it the same as FLOGI
Signed-off-by: Chris Leech <[email protected]>
---
drivers/scsi/fcoe/libfcoe.c | 11 ++++++-----
drivers/scsi/libfc/fc_lport.c | 8 ++++++--
include/scsi/fc/fc_els.h | 3 ++-
include/scsi/fc_encode.h | 30 ++++++++++++++++++++++++++++++
4 files changed, 44 insertions(+), 8 deletions(-)
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c
index 62a4c20..2bb4193 100644
--- a/drivers/scsi/fcoe/libfcoe.c
+++ b/drivers/scsi/fcoe/libfcoe.c
@@ -450,7 +450,7 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip,
memset(mac, 0, sizeof(mac));
mac->fd_desc.fip_dtype = FIP_DT_MAC;
mac->fd_desc.fip_dlen = sizeof(*mac) / FIP_BPW;
- if (dtype != FIP_DT_FLOGI)
+ if ((dtype != FIP_DT_FLOGI) && (dtype != FIP_DT_FDISC))
memcpy(mac->fd_mac, fip->data_src_addr, ETH_ALEN);
else if (fip->spma)
memcpy(mac->fd_mac, fip->ctl_src_addr, ETH_ALEN);
@@ -481,7 +481,7 @@ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct
sk_buff *skb)
fh = (struct fc_frame_header *)skb->data;
op = *(u8 *)(fh + 1);
- if (op == ELS_FLOGI) {
+ if (op == ELS_FLOGI || op == ELS_FDISC) {
old_xid = fip->flogi_oxid;
fip->flogi_oxid = ntohs(fh->fh_ox_id);
if (fip->state == FIP_ST_AUTO) {
@@ -866,8 +866,8 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip,
struct sk_buff *skb)
goto drop;
els_op = *(u8 *)(fh + 1);
- if (els_dtype == FIP_DT_FLOGI && sub == FIP_SC_REP &&
- fip->flogi_oxid == ntohs(fh->fh_ox_id) &&
+ if ((els_dtype == FIP_DT_FLOGI || els_dtype == FIP_DT_FDISC) &&
+ sub == FIP_SC_REP && fip->flogi_oxid == ntohs(fh->fh_ox_id) &&
els_op == ELS_LS_ACC && is_valid_ether_addr(granted_mac)) {
fip->flogi_oxid = FC_XID_UNKNOWN;
fip->update_mac(fip, fip->data_src_addr, granted_mac);
@@ -1289,7 +1289,8 @@ int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct
fc_frame *fp, u8 *sa)
spin_unlock_bh(&fip->lock);
fip->update_mac(fip, mac, fip->data_src_addr);
- } else if (op == ELS_FLOGI && fh->fh_r_ctl == FC_RCTL_ELS_REQ && sa) {
+ } else if ((op == ELS_FLOGI || op == ELS_FDISC) &&
+ fh->fh_r_ctl == FC_RCTL_ELS_REQ && sa) {
/*
* Save source MAC for point-to-point responses.
*/
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index df555a3..a925211 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -1584,6 +1584,7 @@ err:
void fc_lport_enter_flogi(struct fc_lport *lport)
{
struct fc_frame *fp;
+ enum fc_els_cmd cmd;
FC_LPORT_DBG(lport, "Entered FLOGI state from %s state\n",
fc_lport_state(lport));
@@ -1594,9 +1595,12 @@ void fc_lport_enter_flogi(struct fc_lport *lport)
if (!fp)
return fc_lport_error(lport, fp);
- if (!lport->tt.elsct_send(lport, NULL, fp, ELS_FLOGI,
- fc_lport_flogi_resp, lport, lport->e_d_tov))
+ cmd = lport->vn_port ? ELS_FDISC : ELS_FLOGI;
+ if (!lport->tt.elsct_send(lport, NULL, fp, cmd,
+ fc_lport_flogi_resp, lport, lport->e_d_tov)) {
fc_lport_error(lport, fp);
+ }
+
}
/* Configure a fc_lport */
diff --git a/include/scsi/fc/fc_els.h b/include/scsi/fc/fc_els.h
index 195ca01..b5b5ac2 100644
--- a/include/scsi/fc/fc_els.h
+++ b/include/scsi/fc/fc_els.h
@@ -248,7 +248,8 @@ struct fc_els_csp {
/*
* sp_features
*/
-#define FC_SP_FT_CIRO 0x8000 /* continuously increasing rel. off. */
+#define FC_SP_FT_NPIV 0x8000 /* multiple n_port id support (FLOGI) */
+#define FC_SP_FT_CIRO 0x8000 /* continuously increasing rel off
(PLOGI) */
#define FC_SP_FT_CLAD 0x8000 /* clean address (in FLOGI LS_ACC) */
#define FC_SP_FT_RAND 0x4000 /* random relative offset */
#define FC_SP_FT_VAL 0x2000 /* valid vendor version level */
diff --git a/include/scsi/fc_encode.h b/include/scsi/fc_encode.h
index a0ff61c..ac39447 100644
--- a/include/scsi/fc_encode.h
+++ b/include/scsi/fc_encode.h
@@ -169,6 +169,31 @@ static inline void fc_flogi_fill(struct fc_lport *lport,
struct fc_frame *fp)
sp->sp_bb_data = htons((u16) lport->mfs);
cp = &flogi->fl_cssp[3 - 1]; /* class 3 parameters */
cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ);
+ if (lport->does_npiv)
+ sp->sp_features = htons(FC_SP_FT_NPIV);
+}
+
+/**
+ * fc_fdisc_fill - Fill in a fdisc request frame.
+ */
+static inline void fc_fdisc_fill(struct fc_lport *lport, struct fc_frame *fp)
+{
+ struct fc_els_csp *sp;
+ struct fc_els_cssp *cp;
+ struct fc_els_flogi *fdisc;
+
+ fdisc = fc_frame_payload_get(fp, sizeof(*fdisc));
+ memset(fdisc, 0, sizeof(*fdisc));
+ fdisc->fl_cmd = (u8) ELS_FDISC;
+ put_unaligned_be64(lport->wwpn, &fdisc->fl_wwpn);
+ put_unaligned_be64(lport->wwnn, &fdisc->fl_wwnn);
+ sp = &fdisc->fl_csp;
+ sp->sp_hi_ver = 0x20;
+ sp->sp_lo_ver = 0x20;
+ sp->sp_bb_cred = htons(10); /* this gets set by gateway */
+ sp->sp_bb_data = htons((u16) lport->mfs);
+ cp = &fdisc->fl_cssp[3 - 1]; /* class 3 parameters */
+ cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ);
}
/**
@@ -264,6 +289,11 @@ static inline int fc_els_fill(struct fc_lport *lport,
struct fc_rport *rport,
*did = FC_FID_FLOGI;
break;
+ case ELS_FDISC:
+ fc_fdisc_fill(lport, fp);
+ *did = FC_FID_FLOGI;
+ break;
+
case ELS_LOGO:
fc_logo_fill(lport, fp);
*did = FC_FID_FLOGI;
_______________________________________________
devel mailing list
[email protected]
http://www.open-fcoe.org/mailman/listinfo/devel