diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 11ae5c94608b212a6af423454d7aa9de3deaf976..d8ea04a29199830ed37563f54bbf0f6ed7bf52bc 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -449,7 +449,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); @@ -865,8 +865,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); diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 46897cf23ea6d8b34a4eac378b1680d079dea22e..ccba67ca68a182f770b103f2a5f8b7896ac7d085 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -1449,6 +1449,9 @@ static void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, e_d_tov = ntohl(flp->fl_csp.sp_e_d_tov); if (csp_flags & FC_SP_FT_EDTR) e_d_tov /= 1000000; + + lport->npiv_enabled = !!(csp_flags & FC_SP_FT_NPIV_ACC); + if ((csp_flags & FC_SP_FT_FPORT) == 0) { if (e_d_tov > lport->e_d_tov) lport->e_d_tov = e_d_tov; @@ -1498,7 +1501,8 @@ void fc_lport_enter_flogi(struct fc_lport *lport) if (!fp) return fc_lport_error(lport, fp); - if (!lport->tt.elsct_send(lport, FC_FID_FLOGI, fp, ELS_FLOGI, + if (!lport->tt.elsct_send(lport, FC_FID_FLOGI, fp, + lport->vport ? ELS_FDISC : ELS_FLOGI, fc_lport_flogi_resp, lport, lport->e_d_tov)) fc_lport_error(lport, NULL); } diff --git a/include/scsi/fc/fc_els.h b/include/scsi/fc/fc_els.h index 195ca014d3ce3239063cd171d2aed109b0523cf0..b0872afe2d30849e8dbcf5c013210466e830d782 100644 --- a/include/scsi/fc/fc_els.h +++ b/include/scsi/fc/fc_els.h @@ -248,10 +248,12 @@ 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 */ +#define FC_SP_FT_NPIV_ACC 0x2000 /* NPIV assignment (FLOGI LS_ACC) */ #define FC_SP_FT_FPORT 0x1000 /* F port (1) vs. N port (0) */ #define FC_SP_FT_ABB 0x0800 /* alternate BB_credit management */ #define FC_SP_FT_EDTR 0x0400 /* E_D_TOV Resolution is nanoseconds */ diff --git a/include/scsi/fc_encode.h b/include/scsi/fc_encode.h index 27dad703824f164a442104cc2577ed9dd4cf5a3b..c93ca3ece1a0a795d3ef6e87013a7bfa1d6b319c 100644 --- a/include/scsi/fc_encode.h +++ b/include/scsi/fc_encode.h @@ -198,6 +198,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); } /** @@ -296,6 +321,10 @@ static inline int fc_els_fill(struct fc_lport *lport, fc_flogi_fill(lport, fp); break; + case ELS_FDISC: + fc_fdisc_fill(lport, fp); + break; + case ELS_LOGO: fc_logo_fill(lport, fp); break;