diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 8ca488de492d..a64c398c981e 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -226,7 +226,8 @@ 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); /** @@ -254,6 +255,7 @@ 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_interface_setup(fcoe, netdev); @@ -286,8 +288,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); @@ -369,25 +369,37 @@ 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(); } +/** + * fcoe_get_src_mac() - return the Ethernet source address for an lport + * @lport: libfc lport + */ +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 @@ -650,6 +662,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); @@ -706,10 +723,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, + u32 did, 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, }; /** @@ -1226,7 +1249,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); @@ -1291,7 +1314,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) if (unlikely(fcoe->ctlr.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)); @@ -1464,11 +1487,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; @@ -2061,3 +2079,94 @@ 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_logo_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, lport); +} + +/** + * 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, + u32 did, 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; + struct fc_frame_header *fh = fc_frame_header_get(fp); + + switch (op) { + case ELS_FLOGI: + case ELS_FDISC: + return fc_elsct_send(lport, did, fp, op, fcoe_flogi_resp, + fip, timeout); + case ELS_LOGO: + /* only hook onto fabric logouts, not port logouts */ + if (ntoh24(fh->fh_d_id) != FC_FID_FLOGI) + break; + return fc_elsct_send(lport, did, fp, op, fcoe_logo_resp, + fip, timeout); + } + return fc_elsct_send(lport, did, fp, op, resp, arg, timeout); +} + diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h index a123552847e5..99dfa7c2aeaa 100644 --- a/drivers/scsi/fcoe/fcoe.h +++ b/drivers/scsi/fcoe/fcoe.h @@ -104,6 +104,7 @@ 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]; }; #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 d8ea04a29199..6a93ba96569f 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -322,6 +322,7 @@ EXPORT_SYMBOL(fcoe_ctlr_link_down); /** * fcoe_ctlr_send_keep_alive() - Send a keep-alive to the selected FCF. * @fip: FCoE controller. + * @lport: libfc fc_lport to send from * @ports: 0 for controller keep-alive, 1 for port keep-alive. * @sa: source MAC address. * @@ -332,7 +333,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 { @@ -374,16 +377,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); @@ -394,6 +395,7 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, int ports, u8 *sa) /** * fcoe_ctlr_encaps() - Encapsulate an ELS frame for FIP, without sending it. * @fip: FCoE controller. + * @lport: libfc fc_lport to use for the source address * @dtype: FIP descriptor type for the frame. * @skb: FCoE ELS frame including FC header but no FCoE headers. * @@ -405,7 +407,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 { @@ -450,7 +452,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); @@ -463,6 +465,7 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, /** * fcoe_ctlr_els_send() - Send an ELS frame encapsulated by FIP if appropriate. * @fip: FCoE controller. + * @lport: libfc fc_lport to send from * @skb: FCoE ELS frame including FC header but no FCoE headers. * * Returns a non-zero error code if the frame should not be sent. @@ -471,11 +474,13 @@ 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); @@ -530,14 +535,15 @@ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct sk_buff *skb) * FLOGI. */ fip->flogi_oxid = FC_XID_UNKNOWN; - fc_fcoe_set_mac(fip->data_src_addr, fh->fh_s_id); + 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; @@ -796,7 +802,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; @@ -835,6 +841,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,13 +872,10 @@ 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 || 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)) { + if (els_dtype == FIP_DT_FLOGI && 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); - memcpy(fip->data_src_addr, granted_mac, ETH_ALEN); - } /* * Convert skb into an fc_frame containing only the ELS. @@ -958,7 +962,7 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, if (dlen < sizeof(*vp)) return; if (compare_ether_addr(vp->fd_mac, - fip->data_src_addr) == 0 && + fip->get_src_addr(lp)) == 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); @@ -1113,8 +1117,6 @@ static void fcoe_ctlr_timeout(unsigned long arg) struct fcoe_fcf *sel; struct fcoe_fcf *fcf; unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD); - u8 send_ctlr_ka; - u8 send_port_ka; spin_lock_bh(&fip->lock); if (fip->state == FIP_ST_DISABLED) { @@ -1153,12 +1155,10 @@ static void fcoe_ctlr_timeout(unsigned long arg) schedule_work(&fip->link_work); } - send_ctlr_ka = 0; - send_port_ka = 0; if (sel) { if (time_after_eq(jiffies, fip->ctlr_ka_time)) { fip->ctlr_ka_time = jiffies + sel->fka_period; - send_ctlr_ka = 1; + fip->send_ctlr_ka = 1; } if (time_after(next_timer, fip->ctlr_ka_time)) next_timer = fip->ctlr_ka_time; @@ -1166,7 +1166,7 @@ static void fcoe_ctlr_timeout(unsigned long arg) if (time_after_eq(jiffies, fip->port_ka_time)) { fip->port_ka_time += jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD); - send_port_ka = 1; + fip->send_port_ka = 1; } if (time_after(next_timer, fip->port_ka_time)) next_timer = fip->port_ka_time; @@ -1176,12 +1176,9 @@ static void fcoe_ctlr_timeout(unsigned long arg) msecs_to_jiffies(FCOE_CTLR_START_DELAY); mod_timer(&fip->timer, next_timer); } + if (fip->send_ctlr_ka || fip->send_port_ka) + schedule_work(&fip->link_work); 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); } /** @@ -1196,6 +1193,8 @@ static void fcoe_ctlr_timeout(unsigned long arg) static void fcoe_ctlr_link_work(struct work_struct *work) { struct fcoe_ctlr *fip; + struct fc_lport *vport; + u8 *mac; int link; int last_link; @@ -1212,6 +1211,22 @@ static void fcoe_ctlr_link_work(struct work_struct *work) else fcoe_ctlr_reset(fip, FIP_ST_LINK_WAIT); } + + if (fip->send_ctlr_ka) { + fip->send_ctlr_ka = 0; + fcoe_ctlr_send_keep_alive(fip, NULL, 0, fip->ctl_src_addr); + } + if (fip->send_port_ka) { + fip->send_port_ka = 0; + 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); + } } /** @@ -1236,6 +1251,7 @@ static void fcoe_ctlr_recv_work(struct work_struct *recv_work) /** * fcoe_ctlr_recv_flogi() - snoop Pre-FIP receipt of FLOGI response or request. * @fip: FCoE controller. + * @lport: libfc fc_lport instance received on * @fp: FC frame. * @sa: Ethernet source MAC address from received FCoE frame. * @@ -1248,7 +1264,8 @@ static void fcoe_ctlr_recv_work(struct work_struct *recv_work) * * 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; @@ -1283,11 +1300,9 @@ int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_frame *fp, u8 *sa) 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); + 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 && fh->fh_r_ctl == FC_RCTL_ELS_REQ && sa) { /* * Save source MAC for point-to-point responses. @@ -1370,3 +1385,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 92984587ff4d..aae54fe3b299 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, u32 did, struct fc_frame *fp, unsigned int op, @@ -63,6 +63,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 ccba67ca68a1..807f5b3e4efe 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -1320,7 +1320,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; @@ -1357,6 +1357,7 @@ out: err: mutex_unlock(&lport->lp_mutex); } +EXPORT_SYMBOL(fc_lport_logo_resp); /** * fc_rport_enter_logo() - Logout of the fabric @@ -1397,7 +1398,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; @@ -1480,6 +1481,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 148126dcf9e9..ab2f8d41761b 100644 --- a/include/scsi/fc_frame.h +++ b/include/scsi/fc_frame.h @@ -28,6 +28,8 @@ #include #include +#include + /* * The fc_frame interface is used to pass frame data between functions. * The frame includes the data buffer, length, and SOF / EOF delimiter types. @@ -67,6 +69,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]; /* FCoE MAC address */ }; diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index dfeb1ee4f03f..dad66ce8673d 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -900,6 +900,16 @@ void fc_fcp_destroy(struct fc_lport *); * Initializes ELS/CT interface */ int fc_elsct_init(struct fc_lport *lp); +struct fc_seq *fc_elsct_send(struct fc_lport *lport, + u32 did, + struct fc_frame *fp, + unsigned int op, + void (*resp)(struct fc_seq *, + struct fc_frame *fp, + void *arg), + void *arg, u32 timer_msec); +void fc_lport_flogi_resp(struct fc_seq *, struct fc_frame *, void *); +void fc_lport_logo_resp(struct fc_seq *, struct fc_frame *, void *); /* diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h index b2410605b740..8ef5e209c216 100644 --- a/include/scsi/libfcoe.h +++ b/include/scsi/libfcoe.h @@ -74,11 +74,13 @@ enum fip_state { * @last_link: last link state reported to libfc. * @map_dest: use the FC_MAP mode for destination MAC addresses. * @spma: supports SPMA server-provided MACs mode + * @send_ctlr_ka: need to send controller keep alive + * @send_port_ka: need to send port keep alives * @dest_addr: MAC address of the selected FC forwarder. * @ctl_src_addr: the native MAC address of our local port. - * @data_src_addr: the assigned MAC address for the local port after FLOGI. * @send: LLD-supplied function to handle sending of FIP Ethernet frames. * @update_mac: LLD-supplied function to handle changes to MAC addresses. + * @get_src_addr: LLD-supplied function to supply a source MAC address. * @lock: lock protecting this structure. * * This structure is used by all FCoE drivers. It contains information @@ -106,12 +108,14 @@ struct fcoe_ctlr { u8 last_link; u8 map_dest; u8 spma; + u8 send_ctlr_ka; + u8 send_port_ka; 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 *); spinlock_t lock; }; @@ -155,9 +159,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);