The FIP code in libfcoe needed several changes to support NPIV 1) dst_src_addr needs to be managed per-n_port-ID for FPMA fabrics with NPIV enabled. Managing the MAC address is now handled in fcoe, with some slight changes to update_mac() and a new get_src_addr() function pointer.
2) The FLOGI/FDISC OX_ID also needs to be managed per-n_port. I've added get and set function pointers in the FIP controller structure, but long term I hope to get rid of tracking the OX_ID all together. This patch moves towards using the exchange response handlers instead of manually keeping track of which exchanges are FLOGI/FDISC. There are a few uses that need to be fixed before this can be removed completely, mostly the FIP discovery code needs to manage the virtual FC link state better and stop dropping the first 3 FLOGI attempts to give FIP discovery time to complete. 3) The libfc elsct_send() hook is used to setup FCoE specific response handlers for FIP encapsulated ELS exchanges. This lets the FCoE specific handling know which VN_Port the exchange is for, and doesn't require tracking OX_IDs. It might be possible to roll back to the full FIP frame in these, but for now I've just stashed the contents of the MAC address descriptor in the skb context block for later use. Also, because fcoe_elsct_send() just passes control on to fc_elsct_send(), all transmits still come through the normal frame_send() path. I'd like to be able to bypass that for FIP encapsulated exchanges, and stop scanning for ELSs in fcoe_xmit(). Signed-off-by: Chris Leech <[email protected]> --- drivers/scsi/fcoe/fcoe.c | 157 ++++++++++++++++++++++++++++++++++++----- drivers/scsi/fcoe/fcoe.h | 2 + drivers/scsi/fcoe/libfcoe.c | 71 +++++++++++-------- drivers/scsi/libfc/fc_elsct.c | 3 + drivers/scsi/libfc/fc_lport.c | 6 +- include/scsi/fc_frame.h | 3 + include/scsi/libfc.h | 10 +++ include/scsi/libfcoe.h | 12 ++- 8 files changed, 208 insertions(+), 56 deletions(-) diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 64bdd54..8d0a6c2 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -214,9 +214,22 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe, } static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb); -static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new); +static void fcoe_update_src_mac(struct fc_lport *lport, u8 *addr); +static u8 *fcoe_get_src_mac(struct fc_lport *lport); static void fcoe_destroy_work(struct work_struct *work); +void fcoe_set_flogi_oxid(struct fc_lport *lport, u16 oxid) +{ + struct fcoe_port *port = lport_priv(lport); + port->flogi_oxid = oxid; +} + +u16 fcoe_get_flogi_oxid(struct fc_lport *lport) +{ + struct fcoe_port *port = lport_priv(lport); + return port->flogi_oxid; +} + /** * fcoe_interface_create() * @netdev: network interface @@ -242,6 +255,9 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev) fcoe_ctlr_init(&fcoe->ctlr); fcoe->ctlr.send = fcoe_fip_send; fcoe->ctlr.update_mac = fcoe_update_src_mac; + fcoe->ctlr.get_src_addr = fcoe_get_src_mac; + fcoe->ctlr.set_flogi_oxid = fcoe_set_flogi_oxid; + fcoe->ctlr.get_flogi_oxid = fcoe_get_flogi_oxid; fcoe_interface_setup(fcoe, netdev); @@ -273,8 +289,6 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe) /* Delete secondary MAC addresses */ memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); dev_unicast_delete(netdev, flogi_maddr); - if (!is_zero_ether_addr(fip->data_src_addr)) - dev_unicast_delete(netdev, fip->data_src_addr); if (fip->spma) dev_unicast_delete(netdev, fip->ctl_src_addr); dev_mc_delete(netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); @@ -348,25 +362,33 @@ static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb) /** * fcoe_update_src_mac() - Update Ethernet MAC filters. - * @fip: FCoE controller. - * @old: Unicast MAC address to delete if the MAC is non-zero. - * @new: Unicast MAC address to add. + * @lport: libfc lport + * @addr: Unicast MAC address to add. * * Remove any previously-set unicast MAC filter. * Add secondary FCoE MAC address filter for our OUI. */ -static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new) +static void fcoe_update_src_mac(struct fc_lport *lport, u8 *addr) { - struct fcoe_interface *fcoe; + struct fcoe_port *port = lport_priv(lport); + struct fcoe_interface *fcoe = port->fcoe; - fcoe = fcoe_from_ctlr(fip); rtnl_lock(); - if (!is_zero_ether_addr(old)) - dev_unicast_delete(fcoe->netdev, old); - dev_unicast_add(fcoe->netdev, new); + if (!is_zero_ether_addr(port->data_src_addr)) + dev_unicast_delete(fcoe->netdev, port->data_src_addr); + if (!is_zero_ether_addr(addr)) + dev_unicast_add(fcoe->netdev, addr); + memcpy(port->data_src_addr, addr, ETH_ALEN); rtnl_unlock(); } +static u8 *fcoe_get_src_mac(struct fc_lport *lport) +{ + struct fcoe_port *port = lport_priv(lport); + + return port->data_src_addr; +} + /** * fcoe_lport_config() - sets up the fc_lport * @lp: ptr to the fc_lport @@ -625,6 +647,11 @@ static void fcoe_if_destroy(struct fc_lport *lport) /* Free existing transmit skbs */ fcoe_clean_pending_queue(lport); + rtnl_lock(); + if (!is_zero_ether_addr(port->data_src_addr)) + dev_unicast_delete(netdev, port->data_src_addr); + rtnl_unlock(); + /* receives may not be stopped until after this */ fcoe_interface_put(fcoe); @@ -681,10 +708,16 @@ static int fcoe_ddp_done(struct fc_lport *lp, u16 xid) return 0; } +static struct fc_seq *fcoe_elsct_send(struct fc_lport *lport, + struct fc_rport *rport, struct fc_frame *fp, unsigned int op, + void (*resp)(struct fc_seq *, struct fc_frame *, void *), + void *arg, u32 timeout); + static struct libfc_function_template fcoe_libfc_fcn_templ = { .frame_send = fcoe_xmit, .ddp_setup = fcoe_ddp_setup, .ddp_done = fcoe_ddp_done, + .elsct_send = fcoe_elsct_send, }; /** @@ -769,6 +802,7 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe, goto out_lp_destroy; } + port->flogi_oxid = FC_XID_UNKNOWN; fcoe_interface_get(fcoe); return lport; @@ -1201,7 +1235,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) } if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ) && - fcoe_ctlr_els_send(&fcoe->ctlr, skb)) + fcoe_ctlr_els_send(&fcoe->ctlr, lp, skb)) return 0; sof = fr_sof(fp); @@ -1263,10 +1297,10 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) /* insert GW address */ memcpy(eh->h_dest, fcoe->ctlr.dest_addr, ETH_ALEN); - if (unlikely(fcoe->ctlr.flogi_oxid != FC_XID_UNKNOWN)) + if (unlikely(port->flogi_oxid != FC_XID_UNKNOWN)) memcpy(eh->h_source, fcoe->ctlr.ctl_src_addr, ETH_ALEN); else - memcpy(eh->h_source, fcoe->ctlr.data_src_addr, ETH_ALEN); + memcpy(eh->h_source, port->data_src_addr, ETH_ALEN); hp = (struct fcoe_hdr *)(eh + 1); memset(hp, 0, sizeof(*hp)); @@ -1429,11 +1463,6 @@ int fcoe_percpu_receive_thread(void *arg) } fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED; } - if (unlikely(port->fcoe->ctlr.flogi_oxid != FC_XID_UNKNOWN) && - fcoe_ctlr_recv_flogi(&port->fcoe->ctlr, fp, mac)) { - fc_frame_free(fp); - continue; - } fc_exch_recv(lp, fp); } return 0; @@ -1999,3 +2028,91 @@ static void __exit fcoe_exit(void) fcoe_if_exit(); } module_exit(fcoe_exit); + +/** + * fcoe_flogi_resp() - FCoE specific FLOGI and FDISC response handler + * @seq: active sequence in the FLOGI or FDISC exchange + * @fp: response frame, or error encoded in a pointer (timeout) + * @arg: pointer the the fcoe_ctlr structure + * + * This handles MAC address managment for FCoE, then passes control on to + * the libfc FLOGI response handler. + */ +static void fcoe_flogi_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) +{ + struct fcoe_ctlr *fip = arg; + struct fc_exch *exch = fc_seq_exch(seq); + struct fc_lport *lport = exch->lp; + u8 *mac; + + if (IS_ERR(fp)) + goto done; + + mac = fr_cb(fp)->granted_mac; + if (is_zero_ether_addr(mac)) { + /* pre-FIP */ + mac = eth_hdr(&fp->skb)->h_source; + if (fcoe_ctlr_recv_flogi(fip, lport, fp, mac)) { + fc_frame_free(fp); + return; + } + } else { + /* FIP, libfcoe has already seen it */ + fip->update_mac(lport, fr_cb(fp)->granted_mac); + } +done: + fc_lport_flogi_resp(seq, fp, lport); +} + +/** + * fcoe_flogi_resp() - FCoE specific LOGO response handler + * @seq: active sequence in the LOGO exchange + * @fp: response frame, or error encoded in a pointer (timeout) + * @arg: pointer the the fcoe_ctlr structure + * + * This handles MAC address managment for FCoE, then passes control on to + * the libfc LOGO response handler. + */ +static void fcoe_logo_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) +{ + struct fcoe_ctlr *fip = arg; + struct fc_exch *exch = fc_seq_exch(seq); + struct fc_lport *lport = exch->lp; + static u8 zero_mac[ETH_ALEN] = { 0 }; + + if (!IS_ERR(fp)) + fip->update_mac(lport, zero_mac); + fc_lport_logo_resp(seq, fp, arg); +} + +/** + * fcoe_elsct_send - FCoE specific ELS handler + * + * This does special case handling of FIP encapsualted ELS exchanges for FCoE, + * using FCoE specific response handlers and passing the FIP controller as + * the argument (the lport is still available from the exchange). + * + * Most of the work here is just handed off to the libfc routine. + */ +static struct fc_seq *fcoe_elsct_send(struct fc_lport *lport, + struct fc_rport *rport, struct fc_frame *fp, unsigned int op, + void (*resp)(struct fc_seq *, struct fc_frame *, void *), + void *arg, u32 timeout) +{ + struct fcoe_port *port = lport_priv(lport); + struct fcoe_interface *fcoe = port->fcoe; + struct fcoe_ctlr *fip = &fcoe->ctlr; + + switch (op) { + case ELS_FLOGI: + case ELS_FDISC: + return fc_elsct_send(lport, rport, fp, op, fcoe_flogi_resp, + fip, timeout); + case ELS_LOGO: + return fc_elsct_send(lport, rport, fp, op, fcoe_logo_resp, + fip, timeout); + default: + return fc_elsct_send(lport, rport, fp, op, resp, arg, timeout); + } +} + diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h index ce7f60f..6de64cc 100644 --- a/drivers/scsi/fcoe/fcoe.h +++ b/drivers/scsi/fcoe/fcoe.h @@ -98,6 +98,8 @@ struct fcoe_port { u8 fcoe_pending_queue_active; struct timer_list timer; /* queue timer */ struct work_struct destroy_work; /* to prevent rtnl deadlocks */ + u8 data_src_addr[ETH_ALEN]; + u16 flogi_oxid; }; #define fcoe_from_ctlr(fip) container_of(fip, struct fcoe_interface, ctlr) diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 2bb4193..cd3779a 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -106,7 +106,6 @@ void fcoe_ctlr_init(struct fcoe_ctlr *fip) fip->state = FIP_ST_LINK_WAIT; INIT_LIST_HEAD(&fip->fcfs); spin_lock_init(&fip->lock); - fip->flogi_oxid = FC_XID_UNKNOWN; setup_timer(&fip->timer, fcoe_ctlr_timeout, (unsigned long)fip); INIT_WORK(&fip->link_work, fcoe_ctlr_link_work); INIT_WORK(&fip->recv_work, fcoe_ctlr_recv_work); @@ -287,7 +286,6 @@ static int fcoe_ctlr_reset(struct fcoe_ctlr *fip, enum fip_state new_state) fip->ctlr_ka_time = 0; fip->port_ka_time = 0; fip->sol_time = 0; - fip->flogi_oxid = FC_XID_UNKNOWN; fip->map_dest = 0; fip->last_link = 0; link_dropped = fip->link; @@ -333,7 +331,9 @@ EXPORT_SYMBOL(fcoe_ctlr_link_down); * The source MAC is the assigned mapped source address. * The destination is the FCF's F-port. */ -static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, int ports, u8 *sa) +static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, + struct fc_lport *lport, + int ports, u8 *sa) { struct sk_buff *skb; struct fip_kal { @@ -375,16 +375,14 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, int ports, u8 *sa) kal->mac.fd_desc.fip_dtype = FIP_DT_MAC; kal->mac.fd_desc.fip_dlen = sizeof(kal->mac) / FIP_BPW; memcpy(kal->mac.fd_mac, fip->ctl_src_addr, ETH_ALEN); - if (ports) { vn = (struct fip_vn_desc *)(kal + 1); vn->fd_desc.fip_dtype = FIP_DT_VN_ID; vn->fd_desc.fip_dlen = sizeof(*vn) / FIP_BPW; - memcpy(vn->fd_mac, fip->data_src_addr, ETH_ALEN); + memcpy(vn->fd_mac, fip->get_src_addr(lport), ETH_ALEN); hton24(vn->fd_fc_id, fc_host_port_id(lp->host)); put_unaligned_be64(lp->wwpn, &vn->fd_wwpn); } - skb_put(skb, len); skb->protocol = htons(ETH_P_FIP); skb_reset_mac_header(skb); @@ -406,7 +404,7 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, int ports, u8 *sa) * Headroom includes the FIP encapsulation description, FIP header, and * Ethernet header. The tailroom is for the FIP MAC descriptor. */ -static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, +static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport, u8 dtype, struct sk_buff *skb) { struct fip_encaps_head { @@ -451,7 +449,7 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, mac->fd_desc.fip_dtype = FIP_DT_MAC; mac->fd_desc.fip_dlen = sizeof(*mac) / FIP_BPW; if ((dtype != FIP_DT_FLOGI) && (dtype != FIP_DT_FDISC)) - memcpy(mac->fd_mac, fip->data_src_addr, ETH_ALEN); + memcpy(mac->fd_mac, fip->get_src_addr(lport), ETH_ALEN); else if (fip->spma) memcpy(mac->fd_mac, fip->ctl_src_addr, ETH_ALEN); @@ -472,18 +470,20 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, * The caller must check that the length is a multiple of 4. * The SKB must have enough headroom (28 bytes) and tailroom (8 bytes). */ -int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct sk_buff *skb) +int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport, + struct sk_buff *skb) { struct fc_frame_header *fh; u16 old_xid; u8 op; + u8 mac[ETH_ALEN]; fh = (struct fc_frame_header *)skb->data; op = *(u8 *)(fh + 1); if (op == ELS_FLOGI || op == ELS_FDISC) { - old_xid = fip->flogi_oxid; - fip->flogi_oxid = ntohs(fh->fh_ox_id); + old_xid = fip->get_flogi_oxid(lport); + fip->set_flogi_oxid(lport, ntohs(fh->fh_ox_id)); if (fip->state == FIP_ST_AUTO) { if (old_xid == FC_XID_UNKNOWN) fip->flogi_count = 0; @@ -517,7 +517,7 @@ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct sk_buff *skb) op = FIP_DT_LOGO; break; case ELS_LS_ACC: - if (fip->flogi_oxid == FC_XID_UNKNOWN) + if (fip->get_flogi_oxid(lport) == FC_XID_UNKNOWN) return 0; if (!ntoh24(fh->fh_s_id)) return 0; @@ -530,15 +530,16 @@ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct sk_buff *skb) * MAC in this case would have been set by receving the * FLOGI. */ - fip->flogi_oxid = FC_XID_UNKNOWN; - fc_fcoe_set_mac(fip->data_src_addr, fh->fh_s_id); + fip->set_flogi_oxid(lport, FC_XID_UNKNOWN); + fc_fcoe_set_mac(mac, fh->fh_d_id); + fip->update_mac(lport, mac); return 0; default: if (fip->state != FIP_ST_ENABLED) goto drop; return 0; } - if (fcoe_ctlr_encaps(fip, op, skb)) + if (fcoe_ctlr_encaps(fip, lport, op, skb)) goto drop; fip->send(fip, skb); return -EINPROGRESS; @@ -797,7 +798,7 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) { struct fc_lport *lp = fip->lp; struct fip_header *fiph; - struct fc_frame *fp; + struct fc_frame *fp = (struct fc_frame *)skb; struct fc_frame_header *fh = NULL; struct fip_desc *desc; struct fip_encaps *els; @@ -836,6 +837,7 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) "in FIP ELS\n"); goto drop; } + memcpy(fr_cb(fp)->granted_mac, granted_mac, ETH_ALEN); break; case FIP_DT_FLOGI: case FIP_DT_FDISC: @@ -865,7 +867,7 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) if (!fh) goto drop; els_op = *(u8 *)(fh + 1); - +#if 0 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)) { @@ -873,6 +875,7 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) fip->update_mac(fip, fip->data_src_addr, granted_mac); memcpy(fip->data_src_addr, granted_mac, ETH_ALEN); } +#endif /* * Convert skb into an fc_frame containing only the ELS. @@ -958,11 +961,13 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, vp = (struct fip_vn_desc *)desc; if (dlen < sizeof(*vp)) return; +#if 0 if (compare_ether_addr(vp->fd_mac, fip->data_src_addr) == 0 && get_unaligned_be64(&vp->fd_wwpn) == lp->wwpn && ntoh24(vp->fd_fc_id) == fc_host_port_id(lp->host)) desc_mask &= ~BIT(FIP_DT_VN_ID); +#endif break; default: /* standard says ignore unknown descriptors >= 128 */ @@ -1113,9 +1118,11 @@ static void fcoe_ctlr_timeout(unsigned long arg) struct fcoe_ctlr *fip = (struct fcoe_ctlr *)arg; struct fcoe_fcf *sel; struct fcoe_fcf *fcf; + struct fc_lport *vport; unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD); u8 send_ctlr_ka; u8 send_port_ka; + u8 *mac; spin_lock_bh(&fip->lock); if (fip->state == FIP_ST_DISABLED) { @@ -1180,9 +1187,17 @@ static void fcoe_ctlr_timeout(unsigned long arg) spin_unlock_bh(&fip->lock); if (send_ctlr_ka) - fcoe_ctlr_send_keep_alive(fip, 0, fip->ctl_src_addr); - if (send_port_ka) - fcoe_ctlr_send_keep_alive(fip, 1, fip->data_src_addr); + fcoe_ctlr_send_keep_alive(fip, NULL, 0, fip->ctl_src_addr); + if (send_port_ka) { + mutex_lock(&fip->lp->lp_mutex); + mac = fip->get_src_addr(fip->lp); + fcoe_ctlr_send_keep_alive(fip, fip->lp, 1, mac); + list_for_each_entry(vport, &fip->lp->vports, list) { + mac = fip->get_src_addr(vport); + fcoe_ctlr_send_keep_alive(fip, vport, 1, mac); + } + mutex_unlock(&fip->lp->lp_mutex); + } } /** @@ -1243,13 +1258,14 @@ static void fcoe_ctlr_recv_work(struct work_struct *recv_work) * Snoop potential response to FLOGI or even incoming FLOGI. * * The caller has checked that we are waiting for login as indicated - * by fip->flogi_oxid != FC_XID_UNKNOWN. + * by fip->get_flogi_oxid() != FC_XID_UNKNOWN. * * The caller is responsible for freeing the frame. * * Return non-zero if the frame should not be delivered to libfc. */ -int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_frame *fp, u8 *sa) +int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_lport *lport, + struct fc_frame *fp, u8 *sa) { struct fc_frame_header *fh; u8 op; @@ -1261,7 +1277,7 @@ int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_frame *fp, u8 *sa) op = fc_frame_payload_op(fp); if (op == ELS_LS_ACC && fh->fh_r_ctl == FC_RCTL_ELS_REP && - fip->flogi_oxid == ntohs(fh->fh_ox_id)) { + fip->get_flogi_oxid(lport) == ntohs(fh->fh_ox_id)) { spin_lock_bh(&fip->lock); if (fip->state != FIP_ST_AUTO && fip->state != FIP_ST_NON_FIP) { @@ -1283,12 +1299,10 @@ int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_frame *fp, u8 *sa) memcpy(fip->dest_addr, sa, ETH_ALEN); fip->map_dest = 0; } - fip->flogi_oxid = FC_XID_UNKNOWN; - memcpy(mac, fip->data_src_addr, ETH_ALEN); - fc_fcoe_set_mac(fip->data_src_addr, fh->fh_d_id); + fip->set_flogi_oxid(lport, FC_XID_UNKNOWN); + fc_fcoe_set_mac(mac, fh->fh_d_id); + fip->update_mac(lport, mac); spin_unlock_bh(&fip->lock); - - fip->update_mac(fip, mac, fip->data_src_addr); } else if ((op == ELS_FLOGI || op == ELS_FDISC) && fh->fh_r_ctl == FC_RCTL_ELS_REQ && sa) { /* @@ -1372,3 +1386,4 @@ int fcoe_libfc_config(struct fc_lport *lp, struct libfc_function_template *tt) return 0; } EXPORT_SYMBOL_GPL(fcoe_libfc_config); + diff --git a/drivers/scsi/libfc/fc_elsct.c b/drivers/scsi/libfc/fc_elsct.c index 5878b34..a065910 100644 --- a/drivers/scsi/libfc/fc_elsct.c +++ b/drivers/scsi/libfc/fc_elsct.c @@ -31,7 +31,7 @@ /* * fc_elsct_send - sends ELS/CT frame */ -static struct fc_seq *fc_elsct_send(struct fc_lport *lport, +struct fc_seq *fc_elsct_send(struct fc_lport *lport, struct fc_rport *rport, struct fc_frame *fp, unsigned int op, @@ -60,6 +60,7 @@ static struct fc_seq *fc_elsct_send(struct fc_lport *lport, return lport->tt.exch_seq_send(lport, fp, resp, NULL, arg, timer_msec); } +EXPORT_SYMBOL(fc_elsct_send); int fc_elsct_init(struct fc_lport *lport) { diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index a925211..17a1c15 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -1408,7 +1408,7 @@ static void fc_lport_timeout(struct work_struct *work) * held, but it will lock, call an _enter_* function or fc_lport_error * and then unlock the lport. */ -static void fc_lport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, +void fc_lport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, void *lp_arg) { struct fc_lport *lport = lp_arg; @@ -1445,6 +1445,7 @@ out: err: mutex_unlock(&lport->lp_mutex); } +EXPORT_SYMBOL(fc_lport_logo_resp); /** * fc_rport_enter_logo() - Logout of the fabric @@ -1485,7 +1486,7 @@ static void fc_lport_enter_logo(struct fc_lport *lport) * held, but it will lock, call an _enter_* function or fc_lport_error * and then unlock the lport. */ -static void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, +void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, void *lp_arg) { struct fc_lport *lport = lp_arg; @@ -1573,6 +1574,7 @@ out: err: mutex_unlock(&lport->lp_mutex); } +EXPORT_SYMBOL(fc_lport_flogi_resp); /** * fc_rport_enter_flogi() - Send a FLOGI request to the fabric manager diff --git a/include/scsi/fc_frame.h b/include/scsi/fc_frame.h index c35d238..4d246a9 100644 --- a/include/scsi/fc_frame.h +++ b/include/scsi/fc_frame.h @@ -28,6 +28,8 @@ #include <scsi/fc/fc_fcp.h> #include <scsi/fc/fc_encaps.h> +#include <linux/if_ether.h> + /* * The fc_frame interface is used to pass frame data between functions. * The frame includes the data buffer, length, and SOF / EOF delimiter types. @@ -64,6 +66,7 @@ struct fcoe_rcv_info { enum fc_sof fr_sof; /* start of frame delimiter */ enum fc_eof fr_eof; /* end of frame delimiter */ u8 fr_flags; /* flags - see below */ + u8 granted_mac[ETH_ALEN]; }; diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 1686aba..ce14ca6 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -1108,4 +1108,14 @@ void fc_destroy_exch_mgr(void); int fc_setup_rport(void); void fc_destroy_rport(void); +void fc_lport_flogi_resp(struct fc_seq *, struct fc_frame *, void *); +void fc_lport_logo_resp(struct fc_seq *, struct fc_frame *, void *); +struct fc_seq *fc_elsct_send(struct fc_lport *lport, + struct fc_rport *rport, + struct fc_frame *fp, + unsigned int op, + void (*resp)(struct fc_seq *, + struct fc_frame *fp, + void *arg), + void *arg, u32 timer_msec); #endif /* _LIBFC_H_ */ diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h index b241060..462bfed 100644 --- a/include/scsi/libfcoe.h +++ b/include/scsi/libfcoe.h @@ -100,7 +100,6 @@ struct fcoe_ctlr { struct work_struct recv_work; struct sk_buff_head fip_recv_list; u16 user_mfs; - u16 flogi_oxid; u8 flogi_count; u8 link; u8 last_link; @@ -108,10 +107,12 @@ struct fcoe_ctlr { u8 spma; u8 dest_addr[ETH_ALEN]; u8 ctl_src_addr[ETH_ALEN]; - u8 data_src_addr[ETH_ALEN]; void (*send)(struct fcoe_ctlr *, struct sk_buff *); - void (*update_mac)(struct fcoe_ctlr *, u8 *old, u8 *new); + void (*update_mac)(struct fc_lport *, u8 *addr); + u8 * (*get_src_addr)(struct fc_lport *); + void (*set_flogi_oxid)(struct fc_lport *, u16 oxid); + u16 (*get_flogi_oxid)(struct fc_lport *); spinlock_t lock; }; @@ -155,9 +156,10 @@ void fcoe_ctlr_init(struct fcoe_ctlr *); void fcoe_ctlr_destroy(struct fcoe_ctlr *); void fcoe_ctlr_link_up(struct fcoe_ctlr *); int fcoe_ctlr_link_down(struct fcoe_ctlr *); -int fcoe_ctlr_els_send(struct fcoe_ctlr *, struct sk_buff *); +int fcoe_ctlr_els_send(struct fcoe_ctlr *, struct fc_lport *, struct sk_buff *); void fcoe_ctlr_recv(struct fcoe_ctlr *, struct sk_buff *); -int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *, struct fc_frame *fp, u8 *sa); +int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *, struct fc_lport *lport, + struct fc_frame *fp, u8 *sa); /* libfcoe funcs */ u64 fcoe_wwn_from_mac(unsigned char mac[], unsigned int, unsigned int); _______________________________________________ devel mailing list [email protected] http://www.open-fcoe.org/mailman/listinfo/devel
